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

Merge branch 'release/0.16'

This commit is contained in:
rbock 2014-06-30 05:38:15 +02:00
commit f2c4e9c160
128 changed files with 7505 additions and 6690 deletions

View File

@ -28,9 +28,9 @@ enable_testing()
message(STATUS "Using ${CMAKE_CXX_COMPILER} (compiler id: ${CMAKE_CXX_COMPILER_ID})") message(STATUS "Using ${CMAKE_CXX_COMPILER} (compiler id: ${CMAKE_CXX_COMPILER_ID})")
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-std=c++11 -stdlib=libc++ -Wall ${CMAKE_CXX_FLAGS}")
elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
set(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}") set(CMAKE_CXX_FLAGS "-std=c++11 -Wall ${CMAKE_CXX_FLAGS}")
endif () endif ()
set(include_dir "${PROJECT_SOURCE_DIR}/include") set(include_dir "${PROJECT_SOURCE_DIR}/include")

View File

@ -28,45 +28,39 @@
#define SQLPP_ALIAS_H #define SQLPP_ALIAS_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/serializer.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Expression, typename AliasProvider> template<typename Expression, typename AliasProvider>
struct expression_alias_t struct expression_alias_t
{ {
using _traits = make_traits<value_type_of<Expression>, tag::named_expression, tag::alias>;
using _recursive_traits = make_recursive_traits<Expression>;
static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias"); static_assert(is_expression_t<Expression>::value, "invalid argument for an expression alias");
static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias"); static_assert(not is_alias_t<Expression>::value, "cannot create an alias of an alias");
struct _value_type: Expression::_value_type
{
using _is_expression = std::false_type;
using _is_named_expression = std::true_type;
using _is_alias = std::true_type;
};
using _name_t = typename AliasProvider::_name_t; using _name_t = typename AliasProvider::_name_t;
using _table_set = typename Expression::_table_set;
Expression _expression; Expression _expression;
}; };
namespace vendor template<typename Context, typename Expression, typename AliasProvider>
{ struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>>
template<typename Context, typename Expression, typename AliasProvider> {
struct serializer_t<Context, expression_alias_t<Expression, AliasProvider>> using T = expression_alias_t<Expression, AliasProvider>;
static Context& _(const T& t, Context& context)
{ {
using T = expression_alias_t<Expression, AliasProvider>; context << '(';
serialize(t._expression, context);
context << ") AS ";
context << T::_name_t::_get_name();
return context;
}
};
static Context& _(const T& t, Context& context)
{
context << '(';
serialize(t._expression, context);
context << ") AS ";
context << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -31,20 +31,20 @@
#define SQLPP_ALIAS_PROVIDER(name) \ #define SQLPP_ALIAS_PROVIDER(name) \
struct name##_t\ struct name##_t\
{\
struct _name_t\
{\ {\
struct _name_t\ static constexpr const char* _get_name() { return #name; }\
template<typename T>\
struct _member_t\
{\ {\
static constexpr const char* _get_name() { return #name; }\ T name;\
template<typename T>\ T& operator()() { return name; }\
struct _member_t\ const T& operator()() const { return name; }\
{\
T name;\
T& operator()() { return name; }\
const T& operator()() const { return name; }\
};\
};\ };\
};\ };\
constexpr name##_t name = {}; };\
constexpr name##_t name = {};
namespace sqlpp namespace sqlpp
{ {

View File

@ -34,36 +34,33 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Table> template<typename Table>
struct all_of_t struct all_of_t
{ {
using _column_tuple_t = typename Table::_column_tuple_t; using _column_tuple_t = typename Table::_column_tuple_t;
template<typename AliasProvider> template<typename AliasProvider>
detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias) detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias)
{ {
return ::sqlpp::multi_column(_column_tuple_t{}).as(alias); return ::sqlpp::multi_column(_column_tuple_t{}).as(alias);
} }
}; };
template<typename Table> template<typename Table>
auto all_of(Table t) -> all_of_t<Table> auto all_of(Table t) -> all_of_t<Table>
{ {
return {}; return {};
} }
namespace vendor template<typename Context, typename Table>
{ struct serializer_t<Context, all_of_t<Table>>
template<typename Context, typename Table> {
struct serializer_t<Context, all_of_t<Table>> using T = all_of_t<Table>;
static Context& _(const T& t, const Context&)
{ {
using T = all_of_t<Table>; static_assert(wrong_t<T>::value, "all_of(table) does not seem to be used in select");
}
static Context& _(const T& t, const Context&) };
{
static_assert(wrong_t<T>::value, "all_of(table) does not seem to be used in select");
}
};
}
} }

View File

@ -32,16 +32,11 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Select>
{
template<typename Select>
struct any_t struct any_t
{ {
struct _value_type: public Select::_value_type::_base_value_type using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::multi_expression>;
{ using _recursive_traits = make_recursive_traits<Select>;
using _is_expression = std::false_type;
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
};
struct _name_t struct _name_t
{ {
@ -55,8 +50,6 @@ namespace sqlpp
}; };
}; };
using _table_set = typename Select::_table_set;
any_t(Select select): any_t(Select select):
_select(select) _select(select)
{} {}
@ -69,33 +62,30 @@ namespace sqlpp
Select _select; Select _select;
}; };
}
namespace vendor template<typename Context, typename Select>
{ struct serializer_t<Context, any_t<Select>>
template<typename Context, typename Select> {
struct serializer_t<Context, vendor::any_t<Select>> using T = any_t<Select>;
static Context& _(const T& t, Context& context)
{ {
using T = vendor::any_t<Select>; context << "ANY(";
serialize(t._select, context);
static Context& _(const T& t, Context& context) context << ")";
{ return context;
context << "ANY(";
serialize(t._select, context);
context << ")";
return context;
}
};
template<typename T>
auto any(T t) -> typename vendor::any_t<vendor::wrap_operand_t<T>>
{
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "any() requires a select expression as argument");
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
return { t };
} }
};
template<typename T>
auto any(T t) -> any_t<wrap_operand_t<T>>
{
static_assert(is_select_t<wrap_operand_t<T>>::value, "any() requires a select expression as argument");
static_assert(is_expression_t<wrap_operand_t<T>>::value, "any() requires a single column select expression as argument");
// FIXME: can we accept non-values like NULL here?
return { t };
}
}
} }
#endif #endif

View File

@ -0,0 +1,161 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ASSIGNMENT_H
#define SQLPP_ASSIGNMENT_H
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/simple_column.h>
namespace sqlpp
{
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<T>::_(t);
}
template<typename Lhs, typename Rhs>
struct assignment_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _column_t = Lhs;
using _value_t = Rhs;
static_assert(can_be_null_t<_column_t>::value ? true : not std::is_same<_value_t, null_t>::value, "column must not be null");
assignment_t(_column_t lhs, _value_t rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
_value_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, assignment_t<Lhs, Rhs>>
{
using T = assignment_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
if ((trivial_value_is_null_t<typename T::_column_t>::value
and is_trivial(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;
}
};
template<typename Lhs, typename Rhs>
struct assignment_t<Lhs, tvin_t<Rhs>>
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::assignment>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
using _column_t = Lhs;
using _value_t = tvin_t<Rhs>;
static_assert(can_be_null_t<_column_t>::value, "column cannot be null");
assignment_t(_column_t lhs, _value_t rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
_value_t _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, assignment_t<Lhs, tvin_t<Rhs>>>
{
using T = assignment_t<Lhs, tvin_t<Rhs>>;
static Context& _(const T& t, Context& context)
{
serialize(simple_column(t._lhs), context);
if (t._rhs._value._is_trivial())
{
context << "=NULL";
}
else
{
context << "=";
serialize(t._rhs._value, context);
}
return context;
}
};
}
#endif

View File

@ -31,80 +31,71 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Flag, typename Expr>
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>>,
public alias_operators<avg_t<Flag, Expr>>
{ {
template<typename Flag, typename Expr> using _traits = make_traits<floating_point, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct avg_t: public floating_point::template expression_operators<avg_t<Flag, Expr>> using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument");
struct _name_t
{ {
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "avg() used with flag other than 'distinct'"); static constexpr const char* _get_name() { return "AVG"; }
static_assert(is_numeric_t<Expr>::value, "avg() requires a value expression as argument"); template<typename T>
struct _member_t
struct _value_type: public floating_point
{
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "AVG"; }
template<typename T>
struct _member_t
{
T avg;
T& operator()() { return avg; }
const T& operator()() const { return avg; }
};
};
avg_t(Expr expr):
_expr(expr)
{}
avg_t(const avg_t&) = default;
avg_t(avg_t&&) = default;
avg_t& operator=(const avg_t&) = default;
avg_t& operator=(avg_t&&) = default;
~avg_t() = default;
Expr _expr;
};
}
namespace vendor
{
template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, vendor::avg_t<Flag, Expr>>
{
using T = vendor::avg_t<Flag, Expr>;
static Context& _(const T& t, Context& context)
{ {
context << "AVG("; T avg;
if (std::is_same<sqlpp::distinct_t, Flag>::value) T& operator()() { return avg; }
{ const T& operator()() const { return avg; }
serialize(Flag(), context); };
context << ' '; };
}
serialize(t._expr, context); avg_t(Expr expr):
context << ")"; _expr(expr)
return context; {}
avg_t(const avg_t&) = default;
avg_t(avg_t&&) = default;
avg_t& operator=(const avg_t&) = default;
avg_t& operator=(avg_t&&) = default;
~avg_t() = default;
Expr _expr;
};
template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, avg_t<Flag, Expr>>
{
using T = avg_t<Flag, Expr>;
static Context& _(const T& t, Context& context)
{
context << "AVG(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
{
serialize(Flag(), context);
context << ' ';
} }
}; serialize(t._expr, context);
} context << ")";
return context;
}
};
template<typename T> template<typename T>
auto avg(T t) -> typename vendor::avg_t<vendor::noop, vendor::wrap_operand_t<T>> auto avg(T t) -> avg_t<noop, wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto avg(const sqlpp::distinct_t&, T t) -> typename vendor::avg_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>> auto avg(const sqlpp::distinct_t&, T t) -> avg_t<sqlpp::distinct_t, wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "avg() requires a value expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "avg() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -29,93 +29,88 @@
#include <sqlpp11/alias.h> #include <sqlpp11/alias.h>
#include <sqlpp11/sort_order.h> #include <sqlpp11/sort_order.h>
#include <sqlpp11/vendor/expression_fwd.h> #include <sqlpp11/expression_fwd.h>
#include <sqlpp11/vendor/in_fwd.h> #include <sqlpp11/in_fwd.h>
#include <sqlpp11/vendor/is_null_fwd.h> #include <sqlpp11/is_null_fwd.h>
#include <sqlpp11/wrap_operand.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
{ {
namespace detail
{
struct boolean;
}
// basic operators // basic operators
template<typename Base, template<typename> class IsCorrectValueType> template<typename Base, template<typename> class IsCorrectValueType>
struct basic_expression_operators struct basic_expression_operators
{ {
template<typename T> template<typename T>
struct _is_valid_comparison_operand struct _is_valid_comparison_operand
{ {
static constexpr bool value = static constexpr bool value =
(is_expression_t<T>::value // expressions are OK (is_expression_t<T>::value // expressions are OK
or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too or is_multi_expression_t<T>::value) // multi-expressions like ANY are OK for comparisons, too
and IsCorrectValueType<T>::value // the correct value type is required, of course and IsCorrectValueType<T>::value // the correct value type is required, of course
; ;
}; };
template<typename T> template<typename T>
vendor::equal_to_t<Base, vendor::wrap_operand_t<T>> operator==(T t) const equal_to_t<Base, wrap_operand_t<T>> operator==(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::not_equal_to_t<Base, vendor::wrap_operand_t<T>> operator!=(T t) const not_equal_to_t<Base, wrap_operand_t<T>> operator!=(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::less_than_t<Base, vendor::wrap_operand_t<T>> operator<(T t) const less_than_t<Base, wrap_operand_t<T>> operator<(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::less_equal_t<Base, vendor::wrap_operand_t<T>> operator<=(T t) const less_equal_t<Base, wrap_operand_t<T>> operator<=(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::greater_than_t<Base, vendor::wrap_operand_t<T>> operator>(T t) const greater_than_t<Base, wrap_operand_t<T>> operator>(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::greater_equal_t<Base, vendor::wrap_operand_t<T>> operator>=(T t) const greater_equal_t<Base, wrap_operand_t<T>> operator>=(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison"); static_assert(_is_valid_comparison_operand<rhs>::value, "invalid rhs operand in comparison");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
vendor::is_null_t<true, Base> is_null() const is_null_t<true, Base> is_null() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
vendor::is_null_t<false, Base> is_not_null() const is_null_t<false, Base> is_not_null() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
@ -132,19 +127,23 @@ namespace sqlpp
// Hint: use value_list wrapper for containers... // Hint: use value_list wrapper for containers...
template<typename... T> template<typename... T>
vendor::in_t<true, Base, vendor::wrap_operand_t<T>...> in(T... t) const in_t<true, Base, wrap_operand_t<T>...> in(T... t) const
{ {
static_assert(detail::all_t<_is_valid_comparison_operand<vendor::wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... }; return { *static_cast<const Base*>(this), wrap_operand_t<T>{t}... };
} }
template<typename... T> template<typename... T>
vendor::in_t<false, Base, vendor::wrap_operand_t<T>...> not_in(T... t) const in_t<false, Base, wrap_operand_t<T>...> not_in(T... t) const
{ {
static_assert(detail::all_t<_is_valid_comparison_operand<vendor::wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid"); static_assert(detail::all_t<_is_valid_comparison_operand<wrap_operand_t<T>>::value...>::value, "at least one operand of in() is not valid");
return { *static_cast<const Base*>(this), vendor::wrap_operand_t<T>{t}... }; return { *static_cast<const Base*>(this), wrap_operand_t<T>{t}... };
} }
};
template<typename Base>
struct alias_operators
{
template<typename alias_provider> template<typename alias_provider>
expression_alias_t<Base, alias_provider> as(const alias_provider&) expression_alias_t<Base, alias_provider> as(const alias_provider&)
{ {

View File

@ -42,26 +42,22 @@ namespace sqlpp
// boolean value type // boolean value type
struct boolean struct boolean
{ {
using _value_type = boolean; using _tag = ::sqlpp::tag::boolean;
using _base_value_type = boolean;
using _is_boolean = std::true_type;
using _is_value = std::true_type;
using _is_expression = std::true_type;
using _cpp_value_type = bool; using _cpp_value_type = bool;
struct _parameter_t struct _parameter_t
{ {
using _value_type = boolean; using _value_type = boolean; // FIXME
_parameter_t(): _parameter_t():
_value(false), _value(false),
_is_null(true) _is_null(true)
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
@ -78,7 +74,7 @@ namespace sqlpp
} }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
} }
@ -101,111 +97,98 @@ namespace sqlpp
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t struct _result_entry_t
{ {
_result_entry_t(): _result_entry_t():
_is_valid(false), _is_valid(false),
_is_null(true), _is_null(true),
_value(false) _value(false)
{} {}
_result_entry_t(const char* data, size_t): void _validate()
_is_valid(true),
_is_null(data == nullptr),
_value(_is_null ? false : (data[0] == 't' or data[0] == '1'))
{}
void assign(const char* data, size_t)
{
_is_valid = true;
_is_null = data == nullptr;
_value = _is_null ? false : (data[0] == 't' or data[0] == '1');
}
void validate()
{
_is_valid = true;
}
void invalidate()
{
_is_valid = false;
_is_null = true;
_value = 0;
}
bool is_null() const
{
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
{
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); _is_valid = true;
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;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_boolean_result(i, &_value, &_is_null);
} }
private: void _invalidate()
bool _is_valid; {
bool _is_null; _is_valid = false;
signed char _value; _is_null = true;
}; _value = 0;
}
bool is_null() const
{
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
{
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;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_boolean_result(i, &_value, &_is_null);
}
private:
bool _is_valid;
bool _is_null;
signed char _value;
};
template<typename T> template<typename T>
struct _is_valid_operand struct _is_valid_operand
{ {
static constexpr bool value = static constexpr bool value =
is_expression_t<T>::value // expressions are OK is_expression_t<T>::value // expressions are OK
and is_boolean_t<T>::value // the correct value type is required, of course and is_boolean_t<T>::value // the correct value type is required, of course
; ;
}; };
template<typename Base> template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_boolean_t> struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
{ {
template<typename T> template<typename T>
vendor::logical_and_t<Base, vendor::wrap_operand_t<T>> operator and(T t) const logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::logical_or_t<Base, vendor::wrap_operand_t<T>> operator or(T t) const logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
vendor::logical_not_t<Base> operator not() const logical_not_t<Base> operator not() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
@ -213,15 +196,15 @@ namespace sqlpp
template<typename Base> template<typename Base>
struct column_operators struct column_operators
{ {
}; };
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t<Db, TrivialIsNull>& e) inline std::ostream& operator<<(std::ostream& os, const boolean::_result_entry_t<Db, TrivialIsNull>& e)
{ {
return os << e.value(); return os << e.value();
} }
} }
using boolean = detail::boolean; using boolean = detail::boolean;

View File

@ -33,33 +33,34 @@
#include <sqlpp11/null.h> #include <sqlpp11/null.h>
#include <sqlpp11/sort_order.h> #include <sqlpp11/sort_order.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/assignment.h> #include <sqlpp11/assignment.h>
#include <sqlpp11/vendor/expression.h> #include <sqlpp11/expression.h>
#include <sqlpp11/vendor/serializer.h> #include <sqlpp11/serializer.h>
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/wrong.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Table, typename ColumnSpec> template<typename Table, typename ColumnSpec>
struct column_t: public ColumnSpec::_value_type::template expression_operators<column_t<Table, ColumnSpec>>, struct column_t: public ColumnSpec::_value_type::template expression_operators<column_t<Table, ColumnSpec>>,
public ColumnSpec::_value_type::template column_operators<column_t<Table, ColumnSpec>> public ColumnSpec::_value_type::template column_operators<column_t<Table, ColumnSpec>>
{ {
using _is_column = std::true_type; using _traits = make_traits<typename ColumnSpec::_value_type, tag::column, tag::expression, tag::named_expression>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _provided_tables = detail::type_set<>;
using _required_tables = detail::type_set<Table>;
using _extra_tables = detail::type_set<>;
};
using _spec_t = ColumnSpec; using _spec_t = ColumnSpec;
using _table = Table; using _table = Table;
using _table_set = detail::type_set<_table>; using _column_type = typename _spec_t::_column_type;
using _column_type = typename ColumnSpec::_column_type; using _name_t = typename _spec_t::_name_t;
struct _value_type: ColumnSpec::_value_type
{
using _is_expression = std::true_type;
using _is_named_expression = std::true_type;
using _is_alias = std::false_type;
};
template<typename T>
using _is_valid_operand = typename _value_type::template _is_valid_operand<T>;
using _name_t = typename ColumnSpec::_name_t; template<typename T>
using _is_valid_operand = typename ColumnSpec::_value_type::template _is_valid_operand<T>;
column_t() = default; column_t() = default;
column_t(const column_t&) = default; column_t(const column_t&) = default;
@ -80,43 +81,40 @@ namespace sqlpp
} }
template<typename T> template<typename T>
auto operator =(T t) const -> vendor::assignment_t<column_t, typename vendor::wrap_operand<T>::type> auto operator =(T t) const -> assignment_t<column_t, wrap_operand_t<T>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand assignment operand");
return { *this, {t} }; return { *this, rhs{t} };
} }
auto operator =(sqlpp::null_t) const auto operator =(sqlpp::null_t) const
->vendor::assignment_t<column_t, sqlpp::null_t> ->assignment_t<column_t, sqlpp::null_t>
{ {
static_assert(can_be_null_t<column_t>::value, "column cannot be null"); static_assert(can_be_null_t<column_t>::value, "column cannot be null");
return { *this, {} }; return { *this, {} };
} }
auto operator =(sqlpp::default_value_t) const auto operator =(sqlpp::default_value_t) const
->vendor::assignment_t<column_t, sqlpp::default_value_t> ->assignment_t<column_t, sqlpp::default_value_t>
{ {
return { *this, {} }; return { *this, {} };
} }
}; };
namespace vendor template<typename Context, typename... Args>
{ struct serializer_t<Context, column_t<Args...>>
template<typename Context, typename... Args> {
struct serializer_t<Context, column_t<Args...>> using T = column_t<Args...>;
static Context& _(const T& t, Context& context)
{ {
using T = column_t<Args...>; context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name();
return context;
}
};
static Context& _(const T& t, Context& context)
{
context << T::_table::_name_t::_get_name() << '.' << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -31,7 +31,7 @@
namespace sqlpp namespace sqlpp
{ {
template<typename Table, typename ColumnSpec> template<typename Table, typename ColumnSpec>
class column_t; struct column_t;
} }
#endif #endif

View File

@ -28,62 +28,58 @@
#define SQLPP_CONCAT_H #define SQLPP_CONCAT_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor // FIXME: Remove First, inherit from text_t
template<typename First, typename... Args>
struct concat_t: public value_type_of<First>::template expression_operators<concat_t<First, Args...>>,
public alias_operators<concat_t<First, Args...>>
{ {
template<typename First, typename... Args> using _traits = make_traits<value_type_of<First>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct concat_t: public First::_value_type::template expression_operators<concat_t<First, Args...>> using _recursive_traits = make_recursive_traits<First, Args...>;
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least");
static_assert(sqlpp::detail::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()");
struct _name_t
{ {
static_assert(sizeof...(Args) > 0, "concat requires two arguments at least"); static constexpr const char* _get_name() { return "CONCAT"; }
static_assert(sqlpp::detail::all_t<is_text_t<First>::value, is_text_t<Args>::value...>::value, "at least one non-text argument detected in concat()"); template<typename T>
using _table_set = typename ::sqlpp::detail::make_joined_set<typename First::_table_set, typename Args::_table_set...>::type; struct _member_t
{
struct _value_type: public First::_value_type::_base_value_type T concat;
{ };
using _is_named_expression = std::true_type;
};
struct _name_t
{
static constexpr const char* _get_name() { return "CONCAT"; }
template<typename T>
struct _member_t
{
T concat;
};
};
concat_t(First first, Args... args):
_args(first, args...)
{}
concat_t(const concat_t&) = default;
concat_t(concat_t&&) = default;
concat_t& operator=(const concat_t&) = default;
concat_t& operator=(concat_t&&) = default;
~concat_t() = default;
std::tuple<First, Args...> _args;
}; };
template<typename Context, typename First, typename... Args> concat_t(First first, Args... args):
struct serializer_t<Context, concat_t<First, Args...>> _args(first, args...)
{ {}
using T = concat_t<First, Args...>;
static Context& _(const T& t, Context& context) concat_t(const concat_t&) = default;
{ concat_t(concat_t&&) = default;
context << "("; concat_t& operator=(const concat_t&) = default;
interpret_tuple(t._args, "||", context); concat_t& operator=(concat_t&&) = default;
context << ")"; ~concat_t() = default;
return context;
} std::tuple<First, Args...> _args;
}; };
}
template<typename Context, typename First, typename... Args>
struct serializer_t<Context, concat_t<First, Args...>>
{
using T = concat_t<First, Args...>;
static Context& _(const T& t, Context& context)
{
context << "(";
interpret_tuple(t._args, "||", context);
context << ")";
return context;
}
};
} }
#endif #endif

View File

@ -32,80 +32,71 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Flag, typename Expr>
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>,
public alias_operators<count_t<Flag, Expr>>
{ {
template<typename Flag, typename Expr> using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>> using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'");
static_assert(is_expression_t<Expr>::value, "count() requires a sql expression as argument");
struct _name_t
{ {
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "count() used with flag other than 'distinct'"); static constexpr const char* _get_name() { return "COUNT"; }
static_assert(is_expression_t<Expr>::value, "count() requires a sql expression as argument"); template<typename T>
struct _member_t
struct _value_type: public sqlpp::detail::integral
{
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "COUNT"; }
template<typename T>
struct _member_t
{
T count;
T& operator()() { return count; }
const T& operator()() const { return count; }
};
};
count_t(const Expr expr):
_expr(expr)
{}
count_t(const count_t&) = default;
count_t(count_t&&) = default;
count_t& operator=(const count_t&) = default;
count_t& operator=(count_t&&) = default;
~count_t() = default;
Expr _expr;
};
}
namespace vendor
{
template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, vendor::count_t<Flag, Expr>>
{
using T = vendor::count_t<Flag, Expr>;
static Context& _(const T& t, Context& context)
{ {
context << "COUNT("; T count;
if (std::is_same<sqlpp::distinct_t, Flag>::value) T& operator()() { return count; }
{ const T& operator()() const { return count; }
serialize(Flag(), context); };
context << ' '; };
}
serialize(t._expr, context); count_t(const Expr expr):
context << ")"; _expr(expr)
return context; {}
count_t(const count_t&) = default;
count_t(count_t&&) = default;
count_t& operator=(const count_t&) = default;
count_t& operator=(count_t&&) = default;
~count_t() = default;
Expr _expr;
};
template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, count_t<Flag, Expr>>
{
using T = count_t<Flag, Expr>;
static Context& _(const T& t, Context& context)
{
context << "COUNT(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
{
serialize(Flag(), context);
context << ' ';
} }
}; serialize(t._expr, context);
} context << ")";
return context;
}
};
template<typename T> template<typename T>
auto count(T t) -> typename vendor::count_t<vendor::noop, vendor::wrap_operand_t<T>> auto count(T t) -> count_t<noop, wrap_operand_t<T>>
{ {
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "count() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto count(const sqlpp::distinct_t&, T t) -> typename vendor::count_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>> auto count(const sqlpp::distinct_t&, T t) -> count_t<sqlpp::distinct_t, wrap_operand_t<T>>
{ {
static_assert(is_expression_t<vendor::wrap_operand_t<T>>::value, "count() requires an expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "count() requires an expression as argument");
return { t }; return { t };
} }

View File

@ -33,27 +33,23 @@ namespace sqlpp
{ {
struct default_value_t struct default_value_t
{ {
static constexpr bool _is_expression = true; using _traits = make_traits<no_value_t, tag::expression>;
using _value_type = no_value_t; using _recursive_traits = make_recursive_traits<>;
using _table_set = ::sqlpp::detail::type_set<>;
static constexpr bool _is_trivial() { return false; } static constexpr bool _is_trivial() { return false; }
}; };
namespace vendor template<typename Context>
{ struct serializer_t<Context, default_value_t>
template<typename Context> {
struct serializer_t<Context, default_value_t> using Operand = default_value_t;
{
using Operand = default_value_t;
static Context& _(const Operand& t, Context& context) static Context& _(const Operand& t, Context& context)
{ {
context << "DEFAULT"; context << "DEFAULT";
return context; return context;
} }
}; };
}
constexpr default_value_t default_value = {}; constexpr default_value_t default_value = {};

View File

@ -49,7 +49,7 @@ namespace sqlpp
}; };
template<std::size_t LastIndex, std::size_t... Ints, typename AliasProvider, typename... Fields, typename... Rest> template<std::size_t LastIndex, std::size_t... Ints, typename AliasProvider, typename... Fields, typename... Rest>
struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>, vendor::multi_field_t<AliasProvider, Fields...>, Rest...> struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>, multi_field_t<AliasProvider, Fields...>, Rest...>
{ {
using type = typename make_column_index_sequence_impl<column_index_sequence<LastIndex + sizeof...(Fields), Ints..., LastIndex + sizeof...(Fields)>, Rest...>::type; using type = typename make_column_index_sequence_impl<column_index_sequence<LastIndex + sizeof...(Fields), Ints..., LastIndex + sizeof...(Fields)>, Rest...>::type;
}; };

View File

@ -57,7 +57,7 @@ namespace sqlpp
template<template<typename, typename...> class Target, typename First, typename T> template<template<typename, typename...> class Target, typename First, typename T>
struct copy_tuple_args_impl struct copy_tuple_args_impl
{ {
static_assert(vendor::wrong_t<T>::value, "copy_tuple_args must be called with a tuple"); static_assert(wrong_t<T>::value, "copy_tuple_args must be called with a tuple");
}; };
template<template<typename First, typename...> class Target, typename First, typename... Args> template<template<typename First, typename...> class Target, typename First, typename... Args>

View File

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

View File

@ -24,36 +24,35 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_VENDOR_POLICY_UPDATE_H #ifndef SQLPP_DETAIL_PICK_ARG_H
#define SQLPP_VENDOR_POLICY_UPDATE_H #define SQLPP_DETAIL_PICK_ARG_H
#include <sqlpp11/vendor/wrong.h> #include <type_traits>
namespace sqlpp namespace sqlpp
{ {
namespace vendor namespace detail
{ {
template<typename Needle, typename Replacement> template<typename Target, typename Statement, typename Term>
struct policy_update_impl typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::true_type&)
{ {
template<typename T> return term;
using _policy_t = typename std::conditional<std::is_same<Needle, T>::value, Replacement, T>::type;
}; };
template<typename T, typename Needle, typename Replacement> template<typename Target, typename Statement, typename Term>
using policy_update_t = typename policy_update_impl<Needle, Replacement>::template _policy_t<T>; typename Target::_data_t pick_arg_impl(Statement statement, Term term, const std::false_type&)
template<typename Original, typename Needle, typename Replacement>
struct update_policies_impl
{ {
using type = typename Original::template _policy_update_t<Needle, Replacement>; return Target::_get_member(statement)._data;
}; };
template<typename Original, typename Needle, typename Replacement> // Returns a statement's term either by picking the term from the statement or using the new term
using update_policies_t = typename update_policies_impl<Original, Needle, Replacement>::type; template<typename Target, typename Statement, typename Term>
typename Target::_data_t pick_arg(Statement statement, Term term)
{
return pick_arg_impl<Target>(statement, term, std::is_same<typename Target::_data_t, Term>());
};
} }
} }
#endif #endif

View File

@ -24,26 +24,39 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_DETAIL_ARG_SELECTOR_H #ifndef SQLPP_DETAIL_SUM_H
#define SQLPP_DETAIL_ARG_SELECTOR_H #define SQLPP_DETAIL_SUM_H
namespace sqlpp namespace sqlpp
{ {
namespace detail namespace detail
{ {
template<typename Target>
struct arg_selector /** a non-recursive C++14 version
template<typename... Args>
constexpr std::size_t sum(Args... args)
{ {
static Target _(Target, Target t) { return t; } std::size_t result = 0;
template<typename X> using swallow = int[];
static Target _(X, Target t) { return t; } (void) swallow{(result += args, 0)...};
template<typename X> return result;
static Target _(Target t, X) { return t; } }
}; */
constexpr std::size_t sum()
{
return 0;
}
template<typename Arg, typename... Rest>
constexpr std::size_t sum(Arg arg, Rest... rest)
{
return arg + sum(rest...);
}
} }
} }
#endif #endif

View File

@ -29,7 +29,7 @@
#include <tuple> #include <tuple>
#include <type_traits> #include <type_traits>
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/wrong.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
@ -73,7 +73,7 @@ namespace sqlpp
template<typename E, typename SET> template<typename E, typename SET>
struct is_element_of struct is_element_of
{ {
static_assert(::sqlpp::vendor::wrong_t<E, SET>::value, "SET has to be a type set"); static_assert(::sqlpp::wrong_t<E, SET>::value, "SET has to be a type set");
}; };
template<typename E, typename... Elements> template<typename E, typename... Elements>
@ -85,7 +85,7 @@ namespace sqlpp
template<typename L, typename R> template<typename L, typename R>
struct joined_set struct joined_set
{ {
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "L and R have to be type sets"); static_assert(::sqlpp::wrong_t<L, R>::value, "L and R have to be type sets");
}; };
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
@ -100,7 +100,7 @@ namespace sqlpp
template<typename L, typename R> template<typename L, typename R>
struct is_superset_of struct is_superset_of
{ {
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "L and R have to be type sets"); static_assert(::sqlpp::wrong_t<L, R>::value, "L and R have to be type sets");
}; };
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
@ -118,7 +118,7 @@ namespace sqlpp
template<typename L, typename R> template<typename L, typename R>
struct is_disjunct_from struct is_disjunct_from
{ {
static_assert(::sqlpp::vendor::wrong_t<L, R>::value, "invalid argument for is_disjunct_from"); static_assert(::sqlpp::wrong_t<L, R>::value, "invalid argument for is_disjunct_from");
}; };
template<typename... LElements, typename... RElements> template<typename... LElements, typename... RElements>
@ -157,6 +157,9 @@ namespace sqlpp
using type = typename make_type_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>
using make_type_set_if_t = typename make_type_set_if<Predicate, T...>::type;
template<template<typename> class Predicate, typename... T> template<template<typename> class Predicate, typename... T>
struct make_type_set_if_not struct make_type_set_if_not
{ {
@ -171,7 +174,7 @@ namespace sqlpp
template<typename... T> template<typename... T>
struct make_joined_set struct make_joined_set
{ {
static_assert(::sqlpp::vendor::wrong_t<T...>::value, "invalid argument for joined set"); static_assert(::sqlpp::wrong_t<T...>::value, "invalid argument for joined set");
}; };
template<> template<>
@ -194,7 +197,7 @@ namespace sqlpp
template<typename Minuend, typename Subtrahend> template<typename Minuend, typename Subtrahend>
struct make_difference_set struct make_difference_set
{ {
static_assert(::sqlpp::vendor::wrong_t<Minuend, Subtrahend>::value, "invalid argument for difference set"); static_assert(::sqlpp::wrong_t<Minuend, Subtrahend>::value, "invalid argument for difference set");
}; };
template<typename... Minuends, typename... Subtrahends> template<typename... Minuends, typename... Subtrahends>
@ -208,6 +211,24 @@ namespace sqlpp
template<typename Minuend, typename Subtrahend> template<typename Minuend, typename Subtrahend>
using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type; using make_difference_set_t = typename make_difference_set<Minuend, Subtrahend>::type;
template<template<typename> class Transformation, typename T>
struct transform_set
{
static_assert(::sqlpp::wrong_t<T>::value, "invalid argument for transform_set");
};
template<template<typename> class Transformation, typename... E>
struct transform_set<Transformation, type_set<E...>>
{
using type = typename make_type_set<Transformation<E>...>::type;
};
template<template<typename> class Transformation, typename T>
using transform_set_t = typename transform_set<Transformation, T>::type;
} }
} }

View File

@ -31,68 +31,59 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Select>
struct exists_t: public boolean::template expression_operators<exists_t<Select>>,
public alias_operators<exists_t<Select>>
{ {
template<typename Select> using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct exists_t: public boolean::template expression_operators<exists_t<Select>> using _recursive_traits = make_recursive_traits<Select>;
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument");
struct _name_t
{ {
static_assert(is_select_t<Select>::value, "exists() requires a select expression as argument"); static constexpr const char* _get_name() { return "EXISTS"; }
template<typename T>
struct _value_type: public boolean struct _member_t
{
using _is_named_expression = std::true_type;
};
using _table_set = typename Select::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "EXISTS"; }
template<typename T>
struct _member_t
{
T exists;
T& operator()() { return exists; }
const T& operator()() const { return exists; }
};
};
exists_t(Select select):
_select(select)
{}
exists_t(const exists_t&) = default;
exists_t(exists_t&&) = default;
exists_t& operator=(const exists_t&) = default;
exists_t& operator=(exists_t&&) = default;
~exists_t() = default;
Select _select;
};
}
namespace vendor
{
template<typename Context, typename Select>
struct serializer_t<Context, vendor::exists_t<Select>>
{
using T = vendor::exists_t<Select>;
static Context& _(const T& t, Context& context)
{ {
context << "EXISTS("; T exists;
serialize(t._select, context); T& operator()() { return exists; }
context << ")"; const T& operator()() const { return exists; }
return context; };
} };
};
} exists_t(Select select):
_select(select)
{}
exists_t(const exists_t&) = default;
exists_t(exists_t&&) = default;
exists_t& operator=(const exists_t&) = default;
exists_t& operator=(exists_t&&) = default;
~exists_t() = default;
Select _select;
};
template<typename Context, typename Select>
struct serializer_t<Context, exists_t<Select>>
{
using T = exists_t<Select>;
static Context& _(const T& t, Context& context)
{
context << "EXISTS(";
serialize(t._select, context);
context << ")";
return context;
}
};
template<typename T> template<typename T>
auto exists(T t) -> typename vendor::exists_t<vendor::wrap_operand_t<T>> auto exists(T t) -> exists_t<wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "exists() requires a select expression as argument"); static_assert(is_select_t<wrap_operand_t<T>>::value, "exists() requires a select expression as argument");
return { t }; return { t };
} }

View File

@ -0,0 +1,239 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_H
#define SQLPP_EXPRESSION_H
#include <sqlpp11/alias.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/noop.h>
#include <sqlpp11/expression_fwd.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/wrap_operand.h>
namespace sqlpp
{
template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>,
public alias_operators<binary_expression_t<Lhs, op::equal_to, Rhs>>
{
using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, equal_to_t<Lhs, Rhs>>
{
using T = equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NULL";
}
else
{
context << "=";
serialize(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>,
public alias_operators<binary_expression_t<Lhs, op::not_equal_to, Rhs>>
{
using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, not_equal_to_t<Lhs, Rhs>>
{
using T = not_equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NOT NULL";
}
else
{
context << "!=";
serialize(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Rhs>
struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<unary_expression_t<op::logical_not, Rhs>>,
public alias_operators<unary_expression_t<op::logical_not, Rhs>>
{
using _traits = make_traits<boolean, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Rhs>;
unary_expression_t(Rhs rhs):
_rhs(rhs)
{}
unary_expression_t(const unary_expression_t&) = default;
unary_expression_t(unary_expression_t&&) = default;
unary_expression_t& operator=(const unary_expression_t&) = default;
unary_expression_t& operator=(unary_expression_t&&) = default;
~unary_expression_t() = default;
Rhs _rhs;
};
template<typename Context, typename Rhs>
struct serializer_t<Context, logical_not_t<Rhs>>
{
using T = logical_not_t<Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << "NOT ";
serialize(t._lhs, context);
context << ")";
return context;
}
};
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public value_type_of<O>::template expression_operators<binary_expression_t<Lhs, O, Rhs>>,
public alias_operators<binary_expression_t<Lhs, O, Rhs>>
{
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
Rhs _rhs;
};
template<typename Context, typename Lhs, typename O, typename Rhs>
struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>>
{
using T = binary_expression_t<Lhs, O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._lhs, context);
context << O::_name;
serialize(t._rhs, context);
context << ")";
return context;
}
};
template<typename O, typename Rhs>
struct unary_expression_t: public value_type_of<O>::template expression_operators<unary_expression_t<O, Rhs>>,
public alias_operators<unary_expression_t<O, Rhs>>
{
using _traits = make_traits<value_type_of<O>, sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<Rhs>;
unary_expression_t(Rhs rhs):
_rhs(rhs)
{}
unary_expression_t(const unary_expression_t&) = default;
unary_expression_t(unary_expression_t&&) = default;
unary_expression_t& operator=(const unary_expression_t&) = default;
unary_expression_t& operator=(unary_expression_t&&) = default;
~unary_expression_t() = default;
Rhs _rhs;
};
template<typename Context, typename O, typename Rhs>
struct serializer_t<Context, unary_expression_t<O, Rhs>>
{
using T = unary_expression_t<O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << O::_name;
serialize(t._rhs, context);
context << ")";
return context;
}
};
}
#endif

View File

@ -0,0 +1,196 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_FWD_H
#define SQLPP_EXPRESSION_FWD_H
namespace sqlpp
{
namespace detail
{
struct boolean;
struct integral;
struct floating_point;
}
namespace op
{
struct less
{
using _traits = make_traits<::sqlpp::detail::boolean>;
static constexpr const char* _name = "<";
};
struct less_equal
{
using _traits = make_traits<::sqlpp::detail::boolean>;
static constexpr const char* _name = "<=";
};
struct equal_to
{
using _traits = make_traits<::sqlpp::detail::boolean>;
};
struct not_equal_to
{
using _traits = make_traits<::sqlpp::detail::boolean>;
};
struct greater_equal
{
using _traits = make_traits<::sqlpp::detail::boolean>;
static constexpr const char* _name = ">=";
};
struct greater
{
using _traits = make_traits<::sqlpp::detail::boolean>;
static constexpr const char* _name = ">";
};
struct logical_or
{
using _traits = make_traits<::sqlpp::detail::boolean>;
static constexpr const char* _name = " OR ";
};
struct logical_and
{
using _traits = make_traits<::sqlpp::detail::boolean>;
static constexpr const char* _name = " AND ";
};
struct logical_not
{
using _traits = make_traits<::sqlpp::detail::boolean>;
};
template<typename ValueType>
struct plus
{
using _traits = make_traits<ValueType>;
static constexpr const char* _name = "+";
};
template<typename ValueType>
struct minus
{
using _traits = make_traits<ValueType>;
static constexpr const char* _name = "-";
};
template<typename ValueType>
struct multiplies
{
using _traits = make_traits<ValueType>;
static constexpr const char* _name = "*";
};
struct divides
{
using _traits = make_traits<::sqlpp::detail::floating_point>;
static constexpr const char* _name = "/";
};
struct modulus
{
using _traits = make_traits<::sqlpp::detail::integral>;
static constexpr const char* _name = "%";
};
template<typename ValueType>
struct unary_minus
{
using _traits = make_traits<ValueType>;
static constexpr const char* _name = "-";
};
template<typename ValueType>
struct unary_plus
{
using _traits = make_traits<ValueType>;
static constexpr const char* _name = "+";
};
}
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t;
template<typename O, typename Rhs>
struct unary_expression_t;
template<typename Lhs, typename Rhs>
using less_than_t = binary_expression_t<Lhs, op::less, Rhs>;
template<typename Lhs, typename Rhs>
using less_equal_t = binary_expression_t<Lhs, op::less_equal, Rhs>;
template<typename Lhs, typename Rhs>
using equal_to_t = binary_expression_t<Lhs, op::equal_to, Rhs>;
template<typename Lhs, typename Rhs>
using not_equal_to_t = binary_expression_t<Lhs, op::not_equal_to, Rhs>;
template<typename Lhs, typename Rhs>
using greater_than_t = binary_expression_t<Lhs, op::greater, Rhs>;
template<typename Lhs, typename Rhs>
using greater_equal_t = binary_expression_t<Lhs, op::greater_equal, Rhs>;
template<typename Lhs, typename Rhs>
using logical_and_t = binary_expression_t<Lhs, op::logical_and, Rhs>;
template<typename Lhs, typename Rhs>
using logical_or_t = binary_expression_t<Lhs, op::logical_or, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using plus_t = binary_expression_t<Lhs, op::plus<ValueType>, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using minus_t = binary_expression_t<Lhs, op::minus<ValueType>, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using multiplies_t = binary_expression_t<Lhs, op::multiplies<ValueType>, Rhs>;
template<typename Lhs, typename Rhs>
using divides_t = binary_expression_t<Lhs, op::divides, Rhs>;
template<typename Lhs, typename Rhs>
using modulus_t = binary_expression_t<Lhs, op::modulus, Rhs>;
template<typename Rhs>
using logical_not_t = unary_expression_t<op::logical_not, Rhs>;
template<typename ValueType, typename Rhs>
using unary_plus_t = unary_expression_t<op::unary_plus<ValueType>, Rhs>;
template<typename ValueType, typename Rhs>
using unary_minus_t = unary_expression_t<op::unary_minus<ValueType>, Rhs>;
}
#endif

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXTRA_TABLES_H
#define SQLPP_EXTRA_TABLES_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
{
template<typename... Tables>
struct extra_tables_data_t
{
extra_tables_data_t()
{}
extra_tables_data_t(const extra_tables_data_t&) = default;
extra_tables_data_t(extra_tables_data_t&&) = default;
extra_tables_data_t& operator=(const extra_tables_data_t&) = default;
extra_tables_data_t& operator=(extra_tables_data_t&&) = default;
~extra_tables_data_t() = default;
};
// EXTRA_TABLES
template<typename... Tables>
struct extra_tables_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::extra_tables>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _required_tables = ::sqlpp::detail::type_set<>;
using _provided_tables = ::sqlpp::detail::type_set<>;
using _extra_tables = ::sqlpp::detail::type_set<Tables...>;
};
// FIXME: extra_tables must not require tables!
static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()");
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()");
// Data
using _data_t = extra_tables_data_t<Tables...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = extra_tables_data_t<Tables...>;
_impl_t<Policies> extra_tables;
_impl_t<Policies>& operator()() { return extra_tables; }
const _impl_t<Policies>& operator()() const { return extra_tables; }
template<typename T>
static auto _get_member(T t) -> decltype(t.extra_tables)
{
return t.extra_tables;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO EXTRA TABLES YET
struct no_extra_tables_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_extra_tables;
_impl_t<Policies>& operator()() { return no_extra_tables; }
const _impl_t<Policies>& operator()() const { return no_extra_tables; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_extra_tables)
{
return t.no_extra_tables;
}
};
template<typename Policies>
struct _methods_t
{
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_extra_tables_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto extra_tables(Args...)
-> _new_statement_t<extra_tables_t<Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), extra_tables_data_t<Args...>{} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, extra_tables_data_t<Database, Tables...>>
{
using T = extra_tables_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
#endif

View File

@ -31,42 +31,41 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename NameType, typename ValueType, bool TrivialValueIsNull>
{ struct field_t
template<typename NameType, typename ValueType, bool TrivialValueIsNull> {
struct field_t using _traits = make_traits<ValueType, tag::noop>;
{ using _recursive_traits = make_recursive_traits<>;
using _name_t = NameType;
using _value_type = ValueType;
static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
};
template<typename AliasProvider, typename FieldTuple> using _name_t = NameType;
struct multi_field_t static constexpr bool _trivial_value_is_null = TrivialValueIsNull;
{ };
};
namespace detail template<typename AliasProvider, typename FieldTuple>
struct multi_field_t
{ {
template<typename NamedExpr> };
struct make_field_t_impl
{
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>
struct make_field_t_impl<multi_column_alias_t<AliasProvider, NamedExpr...>>
{
using type = multi_field_t<AliasProvider, std::tuple<typename make_field_t_impl<NamedExpr>::type...>>;
};
}
namespace detail
{
template<typename NamedExpr> template<typename NamedExpr>
using make_field_t = typename detail::make_field_t_impl<NamedExpr>::type; struct make_field_t_impl
{
using type = field_t<typename NamedExpr::_name_t,
value_type_of<NamedExpr>,
trivial_value_is_null_t<NamedExpr>::value>;
};
template<typename AliasProvider, typename... NamedExpr>
struct make_field_t_impl<multi_column_alias_t<AliasProvider, NamedExpr...>>
{
using type = multi_field_t<AliasProvider, std::tuple<typename make_field_t_impl<NamedExpr>::type...>>;
};
} }
template<typename NamedExpr>
using make_field_t = typename detail::make_field_t_impl<NamedExpr>::type;
} }
#endif #endif

View File

@ -41,27 +41,22 @@ namespace sqlpp
// floating_point value type // floating_point value type
struct floating_point struct floating_point
{ {
using _value_type = floating_point; using _tag = ::sqlpp::tag::floating_point;
using _base_value_type = floating_point;
using _is_numeric = std::true_type;
using _is_floating_point = std::true_type;
using _is_value = std::true_type;
using _is_expression = std::true_type;
using _cpp_value_type = double; using _cpp_value_type = double;
struct _parameter_t struct _parameter_t
{ {
using _value_type = integral; using _value_type = floating_point;
_parameter_t(): _parameter_t():
_value(0), _value(0),
_is_null(true) _is_null(true)
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
@ -78,7 +73,7 @@ namespace sqlpp
} }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
} }
@ -101,134 +96,121 @@ namespace sqlpp
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t struct _result_entry_t
{ {
using _value_type = integral; using _value_type = integral;
_result_entry_t(): _result_entry_t():
_is_valid(false), _is_valid(false),
_is_null(true), _is_null(true),
_value(0) _value(0)
{} {}
_result_entry_t(const char* data, size_t): void _validate()
_is_valid(true),
_is_null(data == nullptr),
_value(_is_null ? 0 : std::strtoll(data, nullptr, 10))
{}
void assign(const char* data, size_t)
{
_is_valid = true;
_is_null = data == nullptr;
_value = _is_null ? 0 : std::strtoll(data, nullptr, 10);
}
void validate()
{
_is_valid = true;
}
void invalidate()
{
_is_valid = false;
_is_null = true;
_value = 0;
}
bool is_null() const
{
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
{
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); _is_valid = true;
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;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_floating_point_result(i, &_value, &_is_null);
} }
private: void _invalidate()
bool _is_valid; {
bool _is_null; _is_valid = false;
_cpp_value_type _value; _is_null = true;
}; _value = 0;
}
bool is_null() const
{
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
{
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;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_floating_point_result(i, &_value, &_is_null);
}
private:
bool _is_valid;
bool _is_null;
_cpp_value_type _value;
};
template<typename T> template<typename T>
struct _is_valid_operand struct _is_valid_operand
{ {
static constexpr bool value = static constexpr bool value =
is_expression_t<T>::value // expressions are OK is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course and is_numeric_t<T>::value // the correct value type is required, of course
; ;
}; };
template<typename Base> template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t> struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{ {
template<typename T> template<typename T>
vendor::plus_t<Base, floating_point, vendor::wrap_operand_t<T>> operator +(T t) const plus_t<Base, floating_point, wrap_operand_t<T>> operator +(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::minus_t<Base, floating_point, vendor::wrap_operand_t<T>> operator -(T t) const minus_t<Base, floating_point, wrap_operand_t<T>> operator -(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::multiplies_t<Base, floating_point, vendor::wrap_operand_t<T>> operator *(T t) const multiplies_t<Base, floating_point, wrap_operand_t<T>> operator *(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
template<typename T> template<typename T>
vendor::divides_t<Base, vendor::wrap_operand_t<T>> operator /(T t) const divides_t<Base, wrap_operand_t<T>> operator /(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
return { *static_cast<const Base*>(this), rhs{t} }; return { *static_cast<const Base*>(this), rhs{t} };
} }
vendor::unary_plus_t<floating_point, Base> operator +() const unary_plus_t<floating_point, Base> operator +() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
vendor::unary_minus_t<floating_point, Base> operator -() const unary_minus_t<floating_point, Base> operator -() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
@ -236,50 +218,50 @@ namespace sqlpp
template<typename Base> template<typename Base>
struct column_operators struct column_operators
{ {
template<typename T> template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::plus_t<Base, floating_point, vendor::wrap_operand_t<T>>> auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, floating_point, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator -=(T t) const -> vendor::assignment_t<Base, vendor::minus_t<Base, floating_point, vendor::wrap_operand_t<T>>> auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, floating_point, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator /=(T t) const -> vendor::assignment_t<Base, vendor::divides_t<Base, vendor::wrap_operand_t<T>>> auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator *=(T t) const -> vendor::assignment_t<Base, vendor::multiplies_t<Base, floating_point, vendor::wrap_operand_t<T>>> auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, floating_point, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
}; };
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t<Db, TrivialIsNull>& e) inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_entry_t<Db, TrivialIsNull>& e)
{ {
return os << e.value(); return os << e.value();
} }
} }
using floating_point = detail::floating_point; using floating_point = detail::floating_point;

225
include/sqlpp11/from.h Normal file
View File

@ -0,0 +1,225 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_FROM_H
#define SQLPP_FROM_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/no_data.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/detail/sum.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
{
// FROM DATA
template<typename Database, typename... Tables>
struct from_data_t
{
from_data_t(Tables... tables):
_tables(tables...)
{}
from_data_t(const from_data_t&) = default;
from_data_t(from_data_t&&) = default;
from_data_t& operator=(const from_data_t&) = default;
from_data_t& operator=(from_data_t&&) = default;
~from_data_t() = default;
std::tuple<Tables...> _tables;
interpretable_list_t<Database> _dynamic_tables;
};
// FROM
template<typename Database, typename... Tables>
struct from_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::from>;
using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>;
// Data
using _data_t = from_data_t<Database, Tables...>;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
template<typename Table>
void add(Table table)
{
static_assert(_is_dynamic::value, "from::add() must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in from::add()");
using _known_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>; // Hint: Joins contain more than one table
using _known_table_names = detail::transform_set_t<name_of, _known_tables>;
static_assert(not detail::is_element_of<typename Table::_name_t, _known_table_names>::value, "Must not use the same table name twice in from()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Table>
void _add_impl(Table table, const std::true_type&)
{
return _data._dynamic_tables.emplace_back(table);
}
template<typename Table>
void _add_impl(Table table, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = from_data_t<Database, Tables...>;
_impl_t<Policies> from;
_impl_t<Policies>& operator()() { return from; }
const _impl_t<Policies>& operator()() const { return from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.from)
{
return t.from;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
struct no_from_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_from;
_impl_t<Policies>& operator()() { return no_from; }
const _impl_t<Policies>& operator()() const { return no_from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_from)
{
return t.no_from;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_from_t, T>;
static void _check_consistency() {}
template<typename... Tables>
auto from(Tables... tables)
-> _new_statement_t<from_t<void, Tables...>>
{
static_assert(sizeof...(Tables), "at least one table or join argument required in from()");
return _from_impl<void>(tables...);
}
template<typename... Tables>
auto dynamic_from(Tables... tables)
-> _new_statement_t<from_t<_database_t, Tables...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return _from_impl<_database_t>(tables...);
}
private:
template<typename Database, typename... Tables>
auto _from_impl(Tables... tables)
-> _new_statement_t<from_t<Database, Tables...>>
{
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()");
static_assert(required_tables_of<from_t<Database, Tables...>>::size::value == 0, "at least one table depends on another table");
static constexpr std::size_t _number_of_tables = detail::sum(provided_tables_of<Tables>::size::value...);
using _unique_tables = detail::make_joined_set_t<provided_tables_of<Tables>...>;
using _unique_table_names = detail::transform_set_t<name_of, _unique_tables>;
static_assert(_number_of_tables == _unique_tables::size::value, "at least one duplicate table detected in from()");
static_assert(_number_of_tables == _unique_table_names::size::value, "at least one duplicate table name detected in from()");
return { *static_cast<typename Policies::_statement_t*>(this), from_data_t<Database, Tables...>{tables...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_data_t<Database, Tables...>>
{
using T = from_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
return context;
context << " FROM ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(Tables) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
}
#endif

View File

@ -30,9 +30,9 @@
#include <sqlpp11/parameter.h> #include <sqlpp11/parameter.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/column_types.h> #include <sqlpp11/column_types.h>
#include <sqlpp11/vendor/in.h> #include <sqlpp11/in.h>
#include <sqlpp11/vendor/is_null.h> #include <sqlpp11/is_null.h>
#include <sqlpp11/vendor/value_type.h> #include <sqlpp11/value_type.h>
#include <sqlpp11/exists.h> #include <sqlpp11/exists.h>
#include <sqlpp11/any.h> #include <sqlpp11/any.h>
#include <sqlpp11/some.h> #include <sqlpp11/some.h>
@ -46,18 +46,18 @@
namespace sqlpp namespace sqlpp
{ {
template<typename T> template<typename T>
auto value(T t) -> vendor::wrap_operand_t<T> auto value(T t) -> wrap_operand_t<T>
{ {
using _table_set = ::sqlpp::detail::type_set<>; static_assert(is_wrapped_value_t<wrap_operand_t<T>>::value, "value() is to be called with non-sql-type like int, or string");
static_assert(not is_value_t<T>::value, "value() is to be called with non-sql-type like int, or string");
return { t }; return { t };
} }
template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim template<typename ValueType> // Csaba Csoma suggests: unsafe_sql instead of verbatim
struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>> struct verbatim_t: public ValueType::template expression_operators<verbatim_t<ValueType>>,
public alias_operators<verbatim_t<ValueType>>
{ {
using _value_type = ValueType; using _traits = make_traits<ValueType, ::sqlpp::tag::expression>;
using _table_set = ::sqlpp::detail::type_set<>; using _recursive_traits = make_recursive_traits<>;
verbatim_t(std::string verbatim): _verbatim(verbatim) {} verbatim_t(std::string verbatim): _verbatim(verbatim) {}
verbatim_t(const verbatim_t&) = default; verbatim_t(const verbatim_t&) = default;
@ -69,20 +69,17 @@ namespace sqlpp
std::string _verbatim; std::string _verbatim;
}; };
namespace vendor template<typename Context, typename ValueType>
{ struct serializer_t<Context, verbatim_t<ValueType>>
template<typename Context, typename ValueType> {
struct serializer_t<Context, verbatim_t<ValueType>> using T = verbatim_t<ValueType>;
{
using T = verbatim_t<ValueType>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << t._verbatim; context << t._verbatim;
return context; return context;
} }
}; };
}
template<typename ValueType, typename StringType> template<typename ValueType, typename StringType>
auto verbatim(StringType s) -> verbatim_t<ValueType> auto verbatim(StringType s) -> verbatim_t<ValueType>
@ -91,7 +88,7 @@ namespace sqlpp
} }
template<typename Expression, typename Context> template<typename Expression, typename Context>
auto flatten(const Expression& exp, const Context& context) -> verbatim_t<typename Expression::_value_type::_base_value_type> auto flatten(const Expression& exp, const Context& context) -> verbatim_t<value_type_of<Expression>>
{ {
static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions"); static_assert(not make_parameter_list_t<Expression>::type::size::value, "parameters not supported in flattened expressions");
context.clear(); context.clear();
@ -102,9 +99,10 @@ namespace sqlpp
template<typename Container> template<typename Container>
struct value_list_t // to be used in .in() method struct value_list_t // to be used in .in() method
{ {
using _traits = make_traits<value_type_t<typename Container::value_type>, ::sqlpp::tag::expression>;
using _recursive_traits = make_recursive_traits<>;
using _container_t = Container; using _container_t = Container;
using _table_set = ::sqlpp::detail::type_set<>;// FIXME: Could it be something else?
using _value_type = vendor::value_type_t<typename _container_t::value_type>;
value_list_t(_container_t container): value_list_t(_container_t container):
_container(container) _container(container)
@ -119,34 +117,31 @@ namespace sqlpp
_container_t _container; _container_t _container;
}; };
namespace vendor template<typename Context, typename Container>
{ struct serializer_t<Context, value_list_t<Container>>
template<typename Context, typename Container> {
struct serializer_t<Context, value_list_t<Container>> using T = value_list_t<Container>;
static Context& _(const T& t, Context& context)
{ {
using T = value_list_t<Container>; bool first = true;
for (const auto& entry: t._container)
static Context& _(const T& t, Context& context)
{ {
bool first = true; if (first)
for (const auto& entry: t._container) first = false;
{ else
if (first) context << ',';
first = false;
else
context << ',';
serialize(value(entry), context); serialize(value(entry), context);
}
return context;
} }
}; return context;
} }
};
template<typename Container> template<typename Container>
auto value_list(Container c) -> value_list_t<Container> auto value_list(Container c) -> value_list_t<Container>
{ {
static_assert(not is_value_t<typename Container::value_type>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)"); static_assert(is_wrapped_value_t<wrap_operand_t<typename Container::value_type>>::value, "value_list() is to be called with a container of non-sql-type like std::vector<int>, or std::list(string)");
return { c }; return { c };
} }

214
include/sqlpp11/group_by.h Normal file
View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_GROUP_BY_H
#define SQLPP_GROUP_BY_H
#include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
// GROUP BY DATA
template<typename Database, typename... Expressions>
struct group_by_data_t
{
group_by_data_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_data_t(const group_by_data_t&) = default;
group_by_data_t(group_by_data_t&&) = default;
group_by_data_t& operator=(const group_by_data_t&) = default;
group_by_data_t& operator=(group_by_data_t&&) = default;
~group_by_data_t() = default;
std::tuple<Expressions...> _expressions;
interpretable_list_t<Database> _dynamic_expressions;
};
// GROUP BY
template<typename Database, typename... Expressions>
struct group_by_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::group_by>;
using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
// Data
using _data_t = group_by_data_t<Database, Expressions...>;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
template<typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "add() must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in group_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in group_by::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_impl(Expression expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = group_by_data_t<Database, Expressions...>;
_impl_t<Policies> group_by;
_impl_t<Policies>& operator()() { return group_by; }
const _impl_t<Policies>& operator()() const { return group_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.group_by)
{
return t.group_by;
}
};
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO GROUP BY YET
struct no_group_by_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_group_by;
_impl_t<Policies>& operator()() { return no_group_by; }
const _impl_t<Policies>& operator()() const { return no_group_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_group_by)
{
return t.no_group_by;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_group_by_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto group_by(Args... args)
-> _new_statement_t<group_by_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> _new_statement_t<group_by_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), group_by_data_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, group_by_data_t<Database, Expressions...>>
{
using T = group_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " GROUP BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
}
#endif

212
include/sqlpp11/having.h Normal file
View File

@ -0,0 +1,212 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_HAVING_H
#define SQLPP_HAVING_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/expression.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
// HAVING DATA
template<typename Database, typename... Expressions>
struct having_data_t
{
having_data_t(Expressions... expressions):
_expressions(expressions...)
{}
having_data_t(const having_data_t&) = default;
having_data_t(having_data_t&&) = default;
having_data_t& operator=(const having_data_t&) = default;
having_data_t& operator=(having_data_t&&) = default;
~having_data_t() = default;
std::tuple<Expressions...> _expressions;
interpretable_list_t<Database> _dynamic_expressions;
};
// HAVING
template<typename Database, typename... Expressions>
struct having_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::having>;
using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression argument required in having()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
// Data
using _data_t = having_data_t<Database, Expressions...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "having::add() can only be called for dynamic_having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in having::add()");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in having::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_impl(Expression expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = having_data_t<Database, Expressions...>;
_impl_t<Policies> having;
_impl_t<Policies>& operator()() { return having; }
const _impl_t<Policies>& operator()() const { return having; }
template<typename T>
static auto _get_member(T t) -> decltype(t.having)
{
return t.having;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO HAVING YET
struct no_having_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_having;
_impl_t<Policies>& operator()() { return no_having; }
const _impl_t<Policies>& operator()() const { return no_having; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_having)
{
return t.no_having;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_having_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto having(Args... args)
-> _new_statement_t<having_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> _new_statement_t<having_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), having_data_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, having_data_t<Database, Expressions...>>
{
using T = having_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " HAVING ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
}
#endif

View File

@ -29,65 +29,60 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/vendor/in_fwd.h> #include <sqlpp11/in_fwd.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<bool NotInverted, typename Operand, typename... Args>
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>>,
public alias_operators<in_t<NotInverted, Operand, Args...>>
{ {
template<bool NotInverted, typename Operand, typename... Args> using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct in_t: public boolean::template expression_operators<in_t<NotInverted, Operand, Args...>> using _recursive_traits = make_recursive_traits<Operand, Args...>;
static constexpr bool _inverted = not NotInverted;
static_assert(sizeof...(Args) > 0, "in() requires at least one argument");
struct _name_t
{ {
static constexpr bool _inverted = not NotInverted; static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; }
static_assert(sizeof...(Args) > 0, "in() requires at least one argument"); template<typename T>
struct _member_t
struct _value_type: public boolean {
{ T in;
using _is_named_expression = std::true_type; };
};
struct _name_t
{
static constexpr const char* _get_name() { return _inverted ? "NOT IN" : "IN"; }
template<typename T>
struct _member_t
{
T in;
};
};
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Operand::_table_set, typename Args::_table_set...>::type;
in_t(Operand operand, Args... args):
_operand(operand),
_args(args...)
{}
in_t(const in_t&) = default;
in_t(in_t&&) = default;
in_t& operator=(const in_t&) = default;
in_t& operator=(in_t&&) = default;
~in_t() = default;
Operand _operand;
std::tuple<Args...> _args;
}; };
template<typename Context, bool NotInverted, typename Operand, typename... Args> in_t(Operand operand, Args... args):
struct serializer_t<Context, vendor::in_t<NotInverted, Operand, Args...>> _operand(operand),
{ _args(args...)
using T = vendor::in_t<NotInverted, Operand, Args...>; {}
static Context& _(const T& t, Context& context) in_t(const in_t&) = default;
{ in_t(in_t&&) = default;
serialize(t._operand, context); in_t& operator=(const in_t&) = default;
context << (t._inverted ? " NOT IN(" : " IN("); in_t& operator=(in_t&&) = default;
interpret_tuple(t._args, ',', context); ~in_t() = default;
context << ')';
return context; Operand _operand;
} std::tuple<Args...> _args;
}; };
}
template<typename Context, bool NotInverted, typename Operand, typename... Args>
struct serializer_t<Context, in_t<NotInverted, Operand, Args...>>
{
using T = in_t<NotInverted, Operand, Args...>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << (t._inverted ? " NOT IN(" : " IN(");
interpret_tuple(t._args, ',', context);
context << ')';
return context;
}
};
} }

View File

@ -29,11 +29,8 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<bool NotInverted, typename Operand, typename... Args>
{
template<bool NotInverted, typename Operand, typename... Args>
struct in_t; struct in_t;
}
} }

View File

@ -27,172 +27,99 @@
#ifndef SQLPP_INSERT_H #ifndef SQLPP_INSERT_H
#define SQLPP_INSERT_H #define SQLPP_INSERT_H
#include <sqlpp11/statement.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_insert.h> #include <sqlpp11/prepared_insert.h>
#include <sqlpp11/default_value.h> #include <sqlpp11/default_value.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/into.h>
#include <sqlpp11/vendor/insert_value_list.h> #include <sqlpp11/insert_value_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, struct insert_name_t {};
typename... Policies
>
struct insert_t;
namespace detail struct insert_t: public statement_name_t<insert_name_t>
{ {
template<typename Db, using _traits = make_traits<no_value_t, tag::return_value>;
typename Table = vendor::no_single_table_t, struct _name_t {};
typename InsertValueList = vendor::no_insert_value_list_t
> template<typename Policies>
struct insert_policies_t struct _result_methods_t
{ {
using _database_t = Db; using _statement_t = typename Policies::_statement_t;
using _table_t = Table;
using _insert_value_list_t = InsertValueList;
using _statement_t = insert_t<Db, Table, InsertValueList>; const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
struct _methods_t: template<typename Db>
public _insert_value_list_t::template _methods_t<insert_policies_t> auto _run(Db& db) const -> decltype(db.insert(this->_get_statement()))
{};
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_insert_t
{ {
using type = insert_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>; _statement_t::_check_consistency();
};
template<typename Needle, typename Replacement> static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
using _new_statement_t = typename _policies_insert_t<Needle, Replacement, Table, InsertValueList>::type; return db.insert(_get_statement());
}
using _table_set = typename _table_t::_table_set; template<typename Db>
auto _prepare(Db& db) const
-> prepared_insert_t<Db, _statement_t>
{
_statement_t::_check_consistency();
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>; return {{}, db.prepare_insert(_get_statement())};
}
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
}; };
} };
// INSERT template<typename Context>
template<typename Db, struct serializer_t<Context, insert_name_t>
typename... Policies
>
struct insert_t:
public detail::insert_policies_t<Db, Policies...>::_methods_t
{ {
using _policies_t = typename detail::insert_policies_t<Db, Policies...>; using T = insert_name_t;
using _database_t = typename _policies_t::_database_t;
using _table_t = typename _policies_t::_table_t;
using _insert_value_list_t = typename _policies_t::_insert_value_list_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; static Context& _(const T& t, Context& context)
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<insert_t>::type;
static_assert(::sqlpp::detail::is_superset_of<typename _table_t::_table_set, typename _insert_value_list_t::_table_set>::value, "columns do not match the table they are to be inserted into");
// Constructors
insert_t()
{}
template<typename Statement, typename T>
insert_t(Statement s, T t):
_table(detail::arg_selector<_table_t>::_(s._table, t)),
_insert_value_list(detail::arg_selector<_insert_value_list_t>::_(s._insert_value_list, t))
{}
insert_t(const insert_t&) = default;
insert_t(insert_t&&) = default;
insert_t& operator=(const insert_t&) = default;
insert_t& operator=(insert_t&&) = default;
~insert_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; context << "INSERT ";
return context;
} }
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
template<typename A>
struct is_table_subset_of_table
{
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
};
void _check_consistency() const
{
// FIXME: Read up on what is allowed/prohibited in INSERT
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run insert directly with parameters, use prepare instead");
return db.insert(*this);
}
template<typename Database>
auto _prepare(Database& db) const
-> prepared_insert_t<Database, insert_t>
{
_check_consistency();
return {{}, db.prepare_insert(*this)};
}
_insert_value_list_t _insert_value_list;
_table_t _table;
}; };
namespace vendor template<typename Database>
{ using blank_insert_t = statement_t<Database,
template<typename Context, typename Database, typename... Policies> insert_t,
struct serializer_t<Context, insert_t<Database, Policies...>> no_into_t,
{ no_insert_value_list_t>;
using T = insert_t<Database, Policies...>;
static Context& _(const T& t, Context& context) auto insert()
{ -> blank_insert_t<void>
context << "INSERT INTO "; {
serialize(t._table, context); return { blank_insert_t<void>() };
serialize(t._insert_value_list, context); }
return context;
}
};
}
template<typename Database, typename... Policies>
using make_insert_t = typename detail::insert_policies_t<Database, Policies...>::_statement_t;
template<typename Table> template<typename Table>
constexpr auto insert_into(Table table) constexpr auto insert_into(Table table)
-> make_insert_t<void, vendor::single_table_t<void, Table>> -> decltype(blank_insert_t<void>().into(table))
{ {
return { make_insert_t<void>(), vendor::single_table_t<void, Table>{table} }; return { blank_insert_t<void>().into(table) };
}
template<typename Database>
constexpr auto dynamic_insert(const Database&)
-> decltype(blank_insert_t<Database>())
{
return { blank_insert_t<Database>() };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_insert_into(const Database&, Table table) constexpr auto dynamic_insert_into(const Database&, Table table)
-> make_insert_t<Database, vendor::single_table_t<void, Table>> -> decltype(blank_insert_t<Database>().into(table))
{ {
return { make_insert_t<Database>(), vendor::single_table_t<void, Table>{table} }; return { blank_insert_t<Database>().into(table) };
} }
} }
#endif #endif

View File

@ -0,0 +1,121 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INSERT_VALUE_H
#define SQLPP_INSERT_VALUE_H
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace detail
{
template<typename Type, bool>
struct type_if
{
using type = Type;
};
template<typename Type>
struct type_if<Type, false>
{
struct type
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
};
};
}
template<typename Column>
struct insert_value_t
{
using _is_insert_value = std::true_type;
using _pure_value_t = typename value_type_of<Column>::_cpp_value_type;
using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type;
using _tvin_t = typename detail::type_if<tvin_t<_wrapped_value_t>, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
using _null_t = typename detail::type_if<null_t, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
insert_value_t(assignment_t<Column, _wrapped_value_t> assignment):
_is_null(false),
_is_default(false),
_value(assignment._rhs)
{}
insert_value_t(assignment_t<Column, _tvin_t> assignment):
_is_null(assignment._rhs._is_trivial()),
_is_default(false),
_value(assignment._rhs._value)
{}
insert_value_t(const assignment_t<Column, _null_t>&):
_is_null(true),
_is_default(false),
_value()
{}
insert_value_t(const assignment_t<Column, ::sqlpp::default_value_t>&):
_is_null(false),
_is_default(true),
_value()
{}
insert_value_t(const insert_value_t&) = default;
insert_value_t(insert_value_t&&) = default;
insert_value_t& operator=(const insert_value_t&) = default;
insert_value_t& operator=(insert_value_t&&) = default;
~insert_value_t() = default;
bool _is_null;
bool _is_default;
_wrapped_value_t _value;
};
template<typename Context, typename ValueType>
struct serializer_t<Context, insert_value_t<ValueType>>
{
using T = insert_value_t<ValueType>;
static Context& _(const T& t, Context& context)
{
if (t._is_null)
context << "NULL";
else if (t._is_default)
context << "DEFAULT";
else
serialize(t._value, context);
return context;
}
};
}
#endif

View File

@ -0,0 +1,443 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INSERT_VALUE_LIST_H
#define SQLPP_INSERT_VALUE_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/assignment.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/insert_value.h>
#include <sqlpp11/simple_column.h>
#include <sqlpp11/no_data.h>
namespace sqlpp
{
struct insert_default_values_data_t
{};
// COLUMN AND VALUE LIST
struct insert_default_values_t
{
using _traits = make_traits<no_value_t>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = insert_default_values_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = insert_default_values_data_t;
_impl_t<Policies> default_values;
_impl_t<Policies>& operator()() { return default_values; }
const _impl_t<Policies>& operator()() const { return default_values; }
template<typename T>
static auto _get_member(T t) -> decltype(t.default_values)
{
return t.default_values;
}
};
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
template<typename Database, typename... Assignments>
struct insert_list_data_t
{
insert_list_data_t(Assignments... assignments):
_assignments(assignments...),
_columns({assignments._lhs}...),
_values(assignments._rhs...)
{}
insert_list_data_t(const insert_list_data_t&) = default;
insert_list_data_t(insert_list_data_t&&) = default;
insert_list_data_t& operator=(const insert_list_data_t&) = default;
insert_list_data_t& operator=(insert_list_data_t&&) = default;
~insert_list_data_t() = default;
std::tuple<Assignments...> _assignments; // FIXME: Need to replace _columns and _values by _assignments (connector-container requires assignments)
std::tuple<simple_column_t<typename Assignments::_column_t>...> _columns;
std::tuple<typename Assignments::_value_t...> _values;
interpretable_list_t<Database> _dynamic_columns;
interpretable_list_t<Database> _dynamic_values;
};
template<typename Database, typename... Assignments>
struct insert_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::insert_list>;
using _recursive_traits = make_recursive_traits<typename Assignments::_column_t..., typename Assignments::_value_t...>;
using _is_dynamic = is_database<Database>;
template<template<typename...> class Target>
using copy_assignments_t = Target<Assignments...>; // FIXME: Nice idea to copy variadic template arguments?
template<template<typename...> class Target, template<typename> class Wrap>
using copy_wrapped_assignments_t = Target<Wrap<Assignments>...>;
// Data
using _data_t = insert_list_data_t<Database, Assignments...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Assignment>
void add_ntc(Assignment assignment)
{
add<Assignment, std::false_type>(assignment);
}
template<typename Assignment, typename TableCheckRequired = std::true_type>
void add(Assignment assignment)
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "add() arguments require to be assigments");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>;
static_assert(not detail::is_element_of<typename Assignment::_column_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(not must_not_insert_t<typename Assignment::_column_t>::value, "add() argument must not be used in insert");
static_assert(not TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "add() contains a column from a foreign table");
using ok = ::sqlpp::detail::all_t<
_is_dynamic::value,
is_assignment_t<Assignment>::value>;
_add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Assignment>
void _add_impl(Assignment assignment, const std::true_type&)
{
_data._dynamic_columns.emplace_back(simple_column_t<typename Assignment::_column_t>{assignment._lhs});
_data._dynamic_values.emplace_back(assignment._rhs);
}
template<typename Assignment>
void _add_impl(Assignment assignment, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = insert_list_data_t<Database, Assignments...>;
_impl_t<Policies> insert_list;
_impl_t<Policies>& operator()() { return insert_list; }
const _impl_t<Policies>& operator()() const { return insert_list; }
template<typename T>
static auto _get_member(T t) -> decltype(t.insert_list)
{
return t.insert_list;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
template<typename... Columns>
struct column_list_data_t
{
column_list_data_t(Columns... columns):
_columns(simple_column_t<Columns>{columns}...)
{}
column_list_data_t(const column_list_data_t&) = default;
column_list_data_t(column_list_data_t&&) = default;
column_list_data_t& operator=(const column_list_data_t&) = default;
column_list_data_t& operator=(column_list_data_t&&) = default;
~column_list_data_t() = default;
using _value_tuple_t = std::tuple<insert_value_t<Columns>...>;
std::tuple<simple_column_t<Columns>...> _columns;
std::vector<_value_tuple_t> _insert_values;
};
template<typename... Columns>
struct column_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::column_list>;
using _recursive_traits = make_recursive_traits<Columns...>;
static_assert(sizeof...(Columns), "at least one column required in columns()");
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected in columns()");
static_assert(::sqlpp::detail::all_t<is_column_t<Columns>::value...>::value, "at least one argument is not a column in columns()");
static_assert(::sqlpp::detail::none_t<must_not_insert_t<Columns>::value...>::value, "at least one column argument has a must_not_insert flag in its definition");
using _value_tuple_t = typename column_list_data_t<Columns...>::_value_tuple_t;
static_assert(required_tables_of<column_list_t>::size::value == 1, "columns from multiple tables in columns()");
// Data
using _data_t = column_list_data_t<Columns...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename... Assignments>
void add(Assignments... assignments)
{
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "add_values() arguments have to be assignments");
using _arg_value_tuple = std::tuple<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");
using ok = ::sqlpp::detail::all_t<
::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value,
_args_correct::value>;
_add_impl(ok(), assignments...); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename... Assignments>
void _add_impl(const std::true_type&, Assignments... assignments)
{
return _data._insert_values.emplace_back(insert_value_t<typename Assignments::_column_t>{assignments}...);
}
template<typename... Assignments>
void _add_impl(const std::false_type&, Assignments... assignments);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = column_list_data_t<Columns...>;
_impl_t<Policies> values;
_impl_t<Policies>& operator()() { return values; }
const _impl_t<Policies>& operator()() const { return values; }
template<typename T>
static auto _get_member(T t) -> decltype(t.values)
{
return t.values;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO INSERT COLUMNS/VALUES YET
struct no_insert_value_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_insert_values;
_impl_t<Policies>& operator()() { return no_insert_values; }
const _impl_t<Policies>& operator()() const { return no_insert_values; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_insert_values)
{
return t.no_insert_values;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_insert_value_list_t, T>;
static void _check_consistency() {}
auto default_values()
-> _new_statement_t<insert_default_values_t>
{
return { *static_cast<typename Policies::_statement_t*>(this), insert_default_values_data_t{} };
}
template<typename... Args>
auto columns(Args... args)
-> _new_statement_t<column_list_t<Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), column_list_data_t<Args...>{args...} };
}
template<typename... Assignments>
auto set(Assignments... assignments)
-> _new_statement_t<insert_list_t<void, Assignments...>>
{
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
return _set_impl<void>(assignments...);
}
template<typename... Assignments>
auto dynamic_set(Assignments... assignments)
-> _new_statement_t<insert_list_t<_database_t, Assignments...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set must not be called in a static statement");
return _set_impl<_database_t>(assignments...);
}
private:
template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments)
-> _new_statement_t<insert_list_t<Database, Assignments...>>
{
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
static_assert(sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
static_assert(sqlpp::detail::none_t<must_not_insert_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<required_tables_of<typename Assignments::_column_t>...>::type;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from several tables");
return { *static_cast<typename Policies::_statement_t*>(this), insert_list_data_t<Database, Assignments...>{assignments...} };
}
};
};
// Interpreters
template<typename Context>
struct serializer_t<Context, insert_default_values_data_t>
{
using T = insert_default_values_data_t;
static Context& _(const T& t, Context& context)
{
context << " DEFAULT VALUES";
return context;
}
};
template<typename Context, typename... Columns>
struct serializer_t<Context, column_list_data_t<Columns...>>
{
using T = column_list_data_t<Columns...>;
static Context& _(const T& t, Context& context)
{
context << " (";
interpret_tuple(t._columns, ",", context);
context << ")";
context << " VALUES ";
bool first = true;
for (const auto& row : t._insert_values)
{
if (not first)
context << ',';
else
first = false;
context << '(';
interpret_tuple(row, ",", context);
context << ')';
}
return context;
}
};
template<typename Context, typename Database, typename... Assignments>
struct serializer_t<Context, insert_list_data_t<Database, Assignments...>>
{
using T = insert_list_data_t<Database, Assignments...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Assignments) + t._dynamic_columns.size() == 0)
{
serialize(insert_default_values_data_t(), context);
}
else
{
context << " (";
interpret_tuple(t._columns, ",", context);
if (sizeof...(Assignments) and not t._dynamic_columns.empty())
context << ',';
interpret_list(t._dynamic_columns, ',', context);
context << ") VALUES(";
interpret_tuple(t._values, ",", context);
if (sizeof...(Assignments) and not t._dynamic_values.empty())
context << ',';
interpret_list(t._dynamic_values, ',', context);
context << ")";
}
return context;
}
};
}
#endif

View File

@ -32,7 +32,8 @@
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/vendor/value_type.h> #include <sqlpp11/value_type.h>
#include <sqlpp11/assignment.h>
namespace sqlpp namespace sqlpp
{ {
@ -42,15 +43,10 @@ namespace sqlpp
// integral value type // integral value type
struct integral struct integral
{ {
using _value_type = integral; using _traits = make_traits<integral, ::sqlpp::tag::expression>;
using _base_value_type = integral; using _tag = ::sqlpp::tag::integral;
using _is_numeric = std::true_type;
using _is_integral = std::true_type;
using _is_value = std::true_type;
using _is_expression = std::true_type;
using _cpp_value_type = int64_t; using _cpp_value_type = int64_t;
struct _parameter_t struct _parameter_t
{ {
using _value_type = integral; using _value_type = integral;
@ -58,12 +54,12 @@ namespace sqlpp
_parameter_t(): _parameter_t():
_value(0), _value(0),
_is_null(true) _is_null(true)
{} {}
explicit _parameter_t(const _cpp_value_type& value): explicit _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
@ -79,7 +75,7 @@ namespace sqlpp
} }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
} }
@ -102,145 +98,132 @@ namespace sqlpp
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t struct _result_entry_t
{ {
using _value_type = integral; using _value_type = integral;
_result_entry_t(): _result_entry_t():
_is_valid(false), _is_valid(false),
_is_null(true), _is_null(true),
_value(0) _value(0)
{} {}
_result_entry_t(const char* data, size_t): void _invalidate()
_is_valid(true),
_is_null(data == nullptr),
_value(_is_null ? 0 : std::strtoll(data, nullptr, 10))
{}
void assign(const char* data, size_t)
{
_is_valid = true;
_is_null = data == nullptr;
_value = _is_null ? 0 : std::strtoll(data, nullptr, 10);
}
void invalidate()
{
_is_valid = false;
_is_null = true;
_value = 0;
}
void validate()
{
_is_valid = true;
}
bool is_null() const
{
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
{
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); _is_valid = false;
assert(not null_value); _is_null = true;
} _value = 0;
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;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_integral_result(i, &_value, &_is_null);
} }
private: void _validate()
bool _is_valid; {
bool _is_null; _is_valid = true;
_cpp_value_type _value; }
};
bool is_null() const
{
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
{
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;
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_integral_result(i, &_value, &_is_null);
}
private:
bool _is_valid;
bool _is_null;
_cpp_value_type _value;
};
template<typename T> template<typename T>
struct _is_valid_operand struct _is_valid_operand
{ {
static constexpr bool value = static constexpr bool value =
is_expression_t<T>::value // expressions are OK is_expression_t<T>::value // expressions are OK
and is_numeric_t<T>::value // the correct value type is required, of course and is_numeric_t<T>::value // the correct value type is required, of course
; ;
}; };
template<typename Base> template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_numeric_t> struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
{ {
template<typename T> template<typename T>
vendor::plus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator +(T t) const plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator +(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::minus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator -(T t) const minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator -(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::multiplies_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>> operator *(T t) const multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator *(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::divides_t<Base, vendor::wrap_operand_t<T>> operator /(T t) const divides_t<Base, wrap_operand_t<T>> operator /(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::modulus_t<Base, vendor::wrap_operand_t<T>> operator %(T t) const modulus_t<Base, wrap_operand_t<T>> operator %(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
vendor::unary_plus_t<integral, Base> operator +() const unary_plus_t<integral, Base> operator +() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
vendor::unary_minus_t<integral, Base> operator -() const unary_minus_t<integral, Base> operator -() const
{ {
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
@ -248,50 +231,50 @@ namespace sqlpp
template<typename Base> template<typename Base>
struct column_operators struct column_operators
{ {
template<typename T> template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::plus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>> auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator -=(T t) const -> vendor::assignment_t<Base, vendor::minus_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>> auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator /=(T t) const -> vendor::assignment_t<Base, vendor::divides_t<Base, vendor::wrap_operand_t<T>>> auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
template<typename T> template<typename T>
auto operator *=(T t) const -> vendor::assignment_t<Base, vendor::multiplies_t<Base, vendor::value_type_t<T>, vendor::wrap_operand_t<T>>> auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
}; };
}; };
template<typename Db, bool NullIsTrivial> template<typename Db, bool NullIsTrivial>
inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t<Db, NullIsTrivial>& e) inline std::ostream& operator<<(std::ostream& os, const integral::_result_entry_t<Db, NullIsTrivial>& e)
{ {
return os << e.value(); return os << e.value();
} }
} }
using tinyint = detail::integral; using tinyint = detail::integral;

View File

@ -27,15 +27,15 @@
#ifndef SQLPP_INTERPRET_H #ifndef SQLPP_INTERPRET_H
#define SQLPP_INTERPRET_H #define SQLPP_INTERPRET_H
#include <sqlpp11/vendor/interpreter.h> #include <sqlpp11/interpreter.h>
namespace sqlpp namespace sqlpp
{ {
template<typename T, typename Context> template<typename T, typename Context>
auto interpret(const T& t, Context& context) auto interpret(const T& t, Context& context)
-> decltype(vendor::interpreter_t<Context, T>::_(t, context)) -> decltype(interpreter_t<Context, T>::_(t, context))
{ {
return vendor::interpreter_t<Context, T>::_(t, context); return interpreter_t<Context, T>::_(t, context);
} }
} }

View File

@ -50,7 +50,7 @@ namespace sqlpp
auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const ::sqlpp::detail::index_sequence<Is...>&) auto interpret_tuple_impl(const Tuple& t, const Separator& separator, Context& context, const ::sqlpp::detail::index_sequence<Is...>&)
-> Context& -> Context&
{ {
// Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4. // Note: A braced-init-list does guarantee the order of evaluation according to 12.6.1 [class.explicit.init] paragraph 2 and 8.5.4 [dcl.init.list] paragraph 4.
// See for example: "http://en.cppreference.com/w/cpp/utility/integer_sequence" // See for example: "http://en.cppreference.com/w/cpp/utility/integer_sequence"
// See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777" // See also: "http://stackoverflow.com/questions/6245735/pretty-print-stdtuple/6245777#6245777"
// Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used // Beware of gcc-bug: "http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51253", otherwise an empty swallow struct could be used

View File

@ -0,0 +1,128 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INTERPRETABLE_H
#define SQLPP_INTERPRETABLE_H
#include <memory>
#include <sqlpp11/serializer_context.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/interpret.h>
namespace sqlpp
{
template<typename Db>
struct interpretable_t
{
using _serializer_context_t = typename Db::_serializer_context_t;
using _interpreter_context_t = typename Db::_interpreter_context_t;
template<typename T>
interpretable_t(T t):
_impl(std::make_shared<_impl_t<T>>(t))
{}
interpretable_t(const interpretable_t&) = default;
interpretable_t(interpretable_t&&) = default;
interpretable_t& operator=(const interpretable_t&) = default;
interpretable_t& operator=(interpretable_t&&) = default;
~interpretable_t() = default;
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
return _impl->serialize(context);
}
// 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->db_serialize(context);
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
return _impl->interpret(context);
}
private:
struct _impl_base
{
virtual sqlpp::serializer_context_t& serialize(sqlpp::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;
};
template<typename T>
struct _impl_t: public _impl_base
{
static_assert(not make_parameter_list_t<T>::size::value, "parameters not supported in dynamic statement parts");
_impl_t(T t):
_t(t)
{}
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
sqlpp::serialize(_t, context);
return context;
}
_serializer_context_t& db_serialize(_serializer_context_t& context) const
{
Db::_serialize_interpretable(_t, context);
return context;
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
Db::_interpret_interpretable(_t, context);
return context;
}
T _t;
};
std::shared_ptr<const _impl_base> _impl;
};
template<typename Context, typename Database>
struct serializer_t<Context, interpretable_t<Database>>
{
using T = interpretable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.serialize(context);
return context;
}
};
}
#endif

View File

@ -28,92 +28,89 @@
#define SQLPP_INTERPRETABLE_LIST_H #define SQLPP_INTERPRETABLE_LIST_H
#include <vector> #include <vector>
#include <sqlpp11/vendor/interpretable.h> #include <sqlpp11/interpretable.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Db>
{ struct interpretable_list_t
template<typename Db> {
struct interpretable_list_t std::vector<interpretable_t<Db>> _serializables;
std::size_t size() const
{ {
std::vector<interpretable_t<Db>> _serializables; return _serializables.size();
}
std::size_t size() const bool empty() const
{ {
return _serializables.size(); return _serializables.empty();
} }
bool empty() const template<typename Expr>
{
return _serializables.empty();
}
template<typename Expr>
void emplace_back(Expr expr) void emplace_back(Expr expr)
{ {
_serializables.emplace_back(expr); _serializables.emplace_back(expr);
} }
}; };
template<> template<>
struct interpretable_list_t<void> struct interpretable_list_t<void>
{
static constexpr std::size_t size()
{ {
static constexpr std::size_t size() return 0;
{
return 0;
}
static constexpr bool empty()
{
return true;
}
};
template<typename Context, typename List>
struct serializable_list_interpreter_t
{
using T = List;
template<typename Separator>
static Context& _(const T& t, const Separator& separator, Context& context)
{
bool first = true;
for (const auto entry : t._serializables)
{
if (not first)
{
context << separator;
first = false;
}
serialize(entry, context);
}
return context;
}
};
template<typename Context>
struct serializable_list_interpreter_t<Context, interpretable_list_t<void>>
{
using T = interpretable_list_t<void>;
template<typename Separator>
static Context& _(const T& t, const Separator& separator, Context& context)
{
return context;
}
};
template<typename T, typename Separator, typename Context>
auto interpret_list(const T& t, const Separator& separator, Context& context)
-> decltype(serializable_list_interpreter_t<Context, T>::_(t, separator, context))
{
return serializable_list_interpreter_t<Context, T>::_(t, separator, context);
} }
} static constexpr bool empty()
{
return true;
}
};
template<typename Context, typename List>
struct serializable_list_interpreter_t
{
using T = List;
template<typename Separator>
static Context& _(const T& t, const Separator& separator, Context& context)
{
bool first = true;
for (const auto entry : t._serializables)
{
if (not first)
{
context << separator;
first = false;
}
serialize(entry, context);
}
return context;
}
};
template<typename Context>
struct serializable_list_interpreter_t<Context, interpretable_list_t<void>>
{
using T = interpretable_list_t<void>;
template<typename Separator>
static Context& _(const T& t, const Separator& separator, Context& context)
{
return context;
}
};
template<typename T, typename Separator, typename Context>
auto interpret_list(const T& t, const Separator& separator, Context& context)
-> decltype(serializable_list_interpreter_t<Context, T>::_(t, separator, context))
{
return serializable_list_interpreter_t<Context, T>::_(t, separator, context);
}
} }
#endif #endif

View File

@ -24,24 +24,21 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_VENDOR_INTERPRETER_H #ifndef SQLPP_INTERPRETER_H
#define SQLPP_VENDOR_INTERPRETER_H #define SQLPP_INTERPRETER_H
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/wrong.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Context, typename T, typename Enable = void>
{ struct interpreter_t
template<typename Context, typename T, typename Enable = void> {
struct interpreter_t static void _(const T& t, Context& context)
{ {
static void _(const T& t, Context& context) static_assert(wrong_t<Context, T>::value, "missing interpreter specialization");
{ }
static_assert(wrong_t<Context, T>::value, "missing interpreter specialization"); };
}
};
}
} }

173
include/sqlpp11/into.h Normal file
View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INTO_H
#define SQLPP_INTO_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/no_data.h>
#include <sqlpp11/prepared_insert.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
// A SINGLE TABLE DATA
template<typename Database, typename Table>
struct into_data_t
{
into_data_t(Table table):
_table(table)
{}
into_data_t(const into_data_t&) = default;
into_data_t(into_data_t&&) = default;
into_data_t& operator=(const into_data_t&) = default;
into_data_t& operator=(into_data_t&&) = default;
~into_data_t() = default;
Table _table;
};
// A SINGLE TABLE
template<typename Database, typename Table>
struct into_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::into>;
using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
using _data_t = into_data_t<Database, Table>;
struct _name_t {};
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = into_data_t<Database, Table>;
_impl_t<Policies> into;
_impl_t<Policies>& operator()() { return into; }
const _impl_t<Policies>& operator()() const { return into; }
template<typename T>
static auto _get_member(T t) -> decltype(t.into)
{
return t.into;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO INTO YET
struct no_into_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_into;
_impl_t<Policies>& operator()() { return no_into; }
const _impl_t<Policies>& operator()() const { return no_into; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_into)
{
return t.no_into;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_into_t, T>;
static void _check_consistency()
{
static_assert(wrong_t<Policies>::value, "into() required");
}
template<typename... Args>
auto into(Args... args)
-> _new_statement_t<into_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), into_data_t<void, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename Table>
struct serializer_t<Context, into_data_t<Database, Table>>
{
using T = into_data_t<Database, Table>;
static Context& _(const T& t, Context& context)
{
context << " INTO ";
serialize(t._table, context);
return context;
}
};
}
#endif

View File

@ -33,55 +33,55 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<bool NotInverted, typename Operand>
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>>,
public alias_operators<is_null_t<NotInverted, Operand>>
{ {
template<bool NotInverted, typename Operand> using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct is_null_t: public boolean::template expression_operators<is_null_t<NotInverted, Operand>> using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _inverted = not NotInverted;
struct _value_type: public boolean
{ {
static constexpr bool _inverted = not NotInverted; using _is_named_expression = std::true_type;
using _table_set = typename Operand::_table_set;
struct _value_type: public boolean
{
using _is_named_expression = std::true_type;
};
struct _name_t
{
static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; }
template<typename T>
struct _member_t
{
T in;
};
};
is_null_t(Operand operand):
_operand(operand)
{}
is_null_t(const is_null_t&) = default;
is_null_t(is_null_t&&) = default;
is_null_t& operator=(const is_null_t&) = default;
is_null_t& operator=(is_null_t&&) = default;
~is_null_t() = default;
Operand _operand;
}; };
template<typename Context, bool NotInverted, typename Operand> struct _name_t
struct serializer_t<Context, ::sqlpp::vendor::is_null_t<NotInverted, Operand>> {
{ static constexpr const char* _get_name() { return _inverted ? "IS NOT NULL" : "IS NULL"; }
using T = ::sqlpp::vendor::is_null_t<NotInverted, Operand>; template<typename T>
struct _member_t
static Context& _(const T& t, Context& context)
{ {
serialize(t._operand, context); T in;
context << (t._inverted ? " IS NOT NULL" : " IS NULL"); };
return context; };
}
}; is_null_t(Operand operand):
} _operand(operand)
{}
is_null_t(const is_null_t&) = default;
is_null_t(is_null_t&&) = default;
is_null_t& operator=(const is_null_t&) = default;
is_null_t& operator=(is_null_t&&) = default;
~is_null_t() = default;
Operand _operand;
};
template<typename Context, bool NotInverted, typename Operand>
struct serializer_t<Context, ::sqlpp::is_null_t<NotInverted, Operand>>
{
using T = ::sqlpp::is_null_t<NotInverted, Operand>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << (t._inverted ? " IS NOT NULL" : " IS NULL");
return context;
}
};
} }

View File

@ -29,11 +29,8 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<bool NotInverted, typename Operand>
{
template<bool NotInverted, typename Operand>
struct is_null_t; struct is_null_t;
}
} }
#endif #endif

View File

@ -29,7 +29,7 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/on.h> #include <sqlpp11/on.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/noop.h>
namespace sqlpp namespace sqlpp
{ {
@ -74,19 +74,20 @@ namespace sqlpp
static constexpr const char* _name = " RIGHT OUTER "; static constexpr const char* _name = " RIGHT OUTER ";
}; };
template<typename JoinType, typename Lhs, typename Rhs, typename On = vendor::noop> template<typename JoinType, typename Lhs, typename Rhs, typename On = noop>
struct join_t struct join_t
{ {
using _traits = make_traits<no_value_t, tag::table, tag::join>;
using _recursive_traits = make_recursive_traits<Lhs, Rhs>;
static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join"); static_assert(is_table_t<Lhs>::value, "lhs argument for join() has to be a table or join");
static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table"); static_assert(is_table_t<Rhs>::value, "rhs argument for join() has to be a table");
static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join"); static_assert(not is_join_t<Rhs>::value, "rhs argument for join must not be a join");
static_assert(vendor::is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()"); static_assert(is_noop<On>::value or is_on_t<On>::value, "invalid on expression in join().on()");
static_assert(::sqlpp::detail::is_disjunct_from<typename Lhs::_table_set, typename Rhs::_table_set>::value, "joined tables must not be identical"); static_assert(::sqlpp::detail::is_disjunct_from<provided_tables_of<Lhs>, provided_tables_of<Rhs>>::value, "joined tables must not be identical");
using _is_table = std::true_type; static_assert(_recursive_traits::_required_tables::size::value == 0, "joined tables must not depend on other tables");
using _is_join = std::true_type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
template<typename OnT> template<typename OnT>
using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>; using set_on_t = join_t<JoinType, Lhs, Rhs, OnT>;
@ -95,7 +96,7 @@ namespace sqlpp
auto on(Expr... expr) auto on(Expr... expr)
-> set_on_t<on_t<void, Expr...>> -> set_on_t<on_t<void, Expr...>>
{ {
static_assert(vendor::is_noop<On>::value, "cannot call on() twice for a single join()"); static_assert(is_noop<On>::value, "cannot call on() twice for a single join()");
return { _lhs, return { _lhs,
_rhs, _rhs,
{std::tuple<Expr...>{expr...}} {std::tuple<Expr...>{expr...}}
@ -105,35 +106,35 @@ namespace sqlpp
template<typename T> template<typename T>
join_t<inner_join_t, join_t, T> join(T t) join_t<inner_join_t, join_t, T> join(T t)
{ {
static_assert(not vendor::is_noop<On>::value, "join type requires on()"); static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, t }; return { *this, t };
} }
template<typename T> template<typename T>
join_t<inner_join_t, join_t, T> inner_join(T t) join_t<inner_join_t, join_t, T> inner_join(T t)
{ {
static_assert(not vendor::is_noop<On>::value, "join type requires on()"); static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, t }; return { *this, t };
} }
template<typename T> template<typename T>
join_t<outer_join_t, join_t, T> outer_join(T t) join_t<outer_join_t, join_t, T> outer_join(T t)
{ {
static_assert(not vendor::is_noop<On>::value, "join type requires on()"); static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, t }; return { *this, t };
} }
template<typename T> template<typename T>
join_t<left_outer_join_t, join_t, T> left_outer_join(T t) join_t<left_outer_join_t, join_t, T> left_outer_join(T t)
{ {
static_assert(not vendor::is_noop<On>::value, "join type requires on()"); static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, t }; return { *this, t };
} }
template<typename T> template<typename T>
join_t<right_outer_join_t, join_t, T> right_outer_join(T t) join_t<right_outer_join_t, join_t, T> right_outer_join(T t)
{ {
static_assert(not vendor::is_noop<On>::value, "join type requires on()"); static_assert(not is_noop<On>::value, "join type requires on()");
return { *this, t }; return { *this, t };
} }
@ -142,26 +143,23 @@ namespace sqlpp
On _on; On _on;
}; };
namespace vendor template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On>
{ struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>>
template<typename Context, typename JoinType, typename Lhs, typename Rhs, typename On> {
struct serializer_t<Context, join_t<JoinType, Lhs, Rhs, On>> using T = join_t<JoinType, Lhs, Rhs, On>;
static Context& _(const T& t, Context& context)
{ {
using T = join_t<JoinType, Lhs, Rhs, On>; static_assert(not is_noop<On>::value, "joined tables require on()");
serialize(t._lhs, context);
context << JoinType::_name;
context << " JOIN ";
serialize(t._rhs, context);
serialize(t._on, context);
return context;
}
};
static Context& _(const T& t, Context& context)
{
static_assert(not vendor::is_noop<On>::value, "joined tables require on()");
serialize(t._lhs, context);
context << JoinType::_name;
context << " JOIN ";
serialize(t._rhs, context);
serialize(t._on, context);
return context;
}
};
}
} }
#endif #endif

View File

@ -33,61 +33,55 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Operand, typename Pattern>
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>>,
public alias_operators<like_t<Operand, Pattern>>
{ {
template<typename Operand, typename Pattern> using _traits = make_traits<boolean, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct like_t: public boolean::template expression_operators<like_t<Operand, Pattern>> using _recursive_traits = make_recursive_traits<Operand, Pattern>;
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text");
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text");
struct _name_t
{ {
static_assert(is_text_t<Operand>::value, "Operand for like() has to be a text"); static constexpr const char* _get_name() { return "LIKE"; }
static_assert(is_text_t<Pattern>::value, "Pattern for like() has to be a text"); template<typename T>
using _parameter_tuple_t = std::tuple<Operand, Pattern>; struct _member_t
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Operand::_table_set, typename Pattern::_table_set>::type; {
T like;
struct _value_type: public boolean };
{
using _is_named_expression = std::true_type;
};
struct _name_t
{
static constexpr const char* _get_name() { return "LIKE"; }
template<typename T>
struct _member_t
{
T like;
};
};
like_t(Operand operand, Pattern pattern):
_operand(operand),
_pattern(pattern)
{}
like_t(const like_t&) = default;
like_t(like_t&&) = default;
like_t& operator=(const like_t&) = default;
like_t& operator=(like_t&&) = default;
~like_t() = default;
Operand _operand;
Pattern _pattern;
}; };
template<typename Context, typename Operand, typename Pattern> like_t(Operand operand, Pattern pattern):
struct serializer_t<Context, like_t<Operand, Pattern>> _operand(operand),
{ _pattern(pattern)
using T = like_t<Operand, Pattern>; {}
static Context& _(const T& t, Context& context) like_t(const like_t&) = default;
{ like_t(like_t&&) = default;
serialize(t._operand, context); like_t& operator=(const like_t&) = default;
context << " LIKE("; like_t& operator=(like_t&&) = default;
serialize(t._pattern, context); ~like_t() = default;
context << ")";
return context; Operand _operand;
} Pattern _pattern;
}; };
}
template<typename Context, typename Operand, typename Pattern>
struct serializer_t<Context, like_t<Operand, Pattern>>
{
using T = like_t<Operand, Pattern>;
static Context& _(const T& t, Context& context)
{
serialize(t._operand, context);
context << " LIKE(";
serialize(t._pattern, context);
context << ")";
return context;
}
};
} }
#endif #endif

261
include/sqlpp11/limit.h Normal file
View File

@ -0,0 +1,261 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_LIMIT_H
#define SQLPP_LIMIT_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
// LIMIT DATA
template<typename Limit>
struct limit_data_t
{
limit_data_t(Limit value):
_value(value)
{}
limit_data_t(const limit_data_t&) = default;
limit_data_t(limit_data_t&&) = default;
limit_data_t& operator=(const limit_data_t&) = default;
limit_data_t& operator=(limit_data_t&&) = default;
~limit_data_t() = default;
Limit _value;
};
// LIMIT
template<typename Limit>
struct limit_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>;
using _recursive_traits = make_recursive_traits<Limit>;
static_assert(is_integral_t<Limit>::value, "limit requires an integral value or integral parameter");
// Data
using _data_t = limit_data_t<Limit>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = limit_data_t<Limit>;
_impl_t<Policies> limit;
_impl_t<Policies>& operator()() { return limit; }
const _impl_t<Policies>& operator()() const { return limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.limit)
{
return t.limit;
}
};
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// DYNAMIC LIMIT DATA
template<typename Database>
struct dynamic_limit_data_t
{
dynamic_limit_data_t():
_value(noop())
{
}
template<typename Limit>
dynamic_limit_data_t(Limit value):
_initialized(true),
_value(typename wrap_operand<Limit>::type(value))
{
}
dynamic_limit_data_t(const dynamic_limit_data_t&) = default;
dynamic_limit_data_t(dynamic_limit_data_t&&) = default;
dynamic_limit_data_t& operator=(const dynamic_limit_data_t&) = default;
dynamic_limit_data_t& operator=(dynamic_limit_data_t&&) = default;
~dynamic_limit_data_t() = default;
bool _initialized = false;
interpretable_t<Database> _value;
};
// DYNAMIC LIMIT
template<typename Database>
struct dynamic_limit_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::limit>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = dynamic_limit_data_t<Database>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Limit>
void set(Limit value)
{
// FIXME: Make sure that Limit does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Limit>::type;
_data._value = arg_t{value};
_data._initialized = true;
}
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = dynamic_limit_data_t<Database>;
_impl_t<Policies> limit;
_impl_t<Policies>& operator()() { return limit; }
const _impl_t<Policies>& operator()() const { return limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.limit)
{
return t.limit;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
struct no_limit_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_limit;
_impl_t<Policies>& operator()() { return no_limit; }
const _impl_t<Policies>& operator()() const { return no_limit; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_limit)
{
return t.no_limit;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_limit_t, T>;
static void _check_consistency() {}
template<typename Arg>
auto limit(Arg arg)
-> _new_statement_t<limit_t<typename wrap_operand<Arg>::type>>
{
return { *static_cast<typename Policies::_statement_t*>(this), limit_data_t<typename wrap_operand<Arg>::type>{{arg}} };
}
auto dynamic_limit()
-> _new_statement_t<dynamic_limit_t<_database_t>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_limit must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_limit_data_t<_database_t>{} };
}
};
};
// Interpreters
template<typename Context, typename Database>
struct serializer_t<Context, dynamic_limit_data_t<Database>>
{
using T = dynamic_limit_data_t<Database>;
static Context& _(const T& t, Context& context)
{
if (t._initialized)
{
context << " LIMIT ";
serialize(t._value, context);
}
return context;
}
};
template<typename Context, typename Limit>
struct serializer_t<Context, limit_data_t<Limit>>
{
using T = limit_data_t<Limit>;
static Context& _(const T& t, Context& context)
{
context << " LIMIT ";
serialize(t._value, context);
return context;
}
};
}
#endif

View File

@ -31,67 +31,58 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Expr>
struct max_t: public value_type_of<Expr>::template expression_operators<max_t<Expr>>,
public alias_operators<max_t<Expr>>
{ {
template<typename Expr> using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct max_t: public Expr::_value_type::template expression_operators<max_t<Expr>> using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_expression_t<Expr>::value, "max() requires a value expression as argument");
struct _name_t
{ {
static_assert(is_value_t<Expr>::value, "max() requires a value expression as argument"); static constexpr const char* _get_name() { return "MAX"; }
template<typename T>
struct _value_type: public Expr::_value_type::_base_value_type struct _member_t
{
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "MAX"; }
template<typename T>
struct _member_t
{
T max;
T& operator()() { return max; }
const T& operator()() const { return max; }
};
};
max_t(Expr expr):
_expr(expr)
{}
max_t(const max_t&) = default;
max_t(max_t&&) = default;
max_t& operator=(const max_t&) = default;
max_t& operator=(max_t&&) = default;
~max_t() = default;
Expr _expr;
};
}
namespace vendor
{
template<typename Context, typename Expr>
struct serializer_t<Context, vendor::max_t<Expr>>
{
using T = vendor::max_t<Expr>;
static Context& _(const T& t, Context& context)
{ {
context << "MAX("; T max;
serialize(t._expr, context); T& operator()() { return max; }
context << ")"; const T& operator()() const { return max; }
return context; };
} };
};
} max_t(Expr expr):
_expr(expr)
{}
max_t(const max_t&) = default;
max_t(max_t&&) = default;
max_t& operator=(const max_t&) = default;
max_t& operator=(max_t&&) = default;
~max_t() = default;
Expr _expr;
};
template<typename Context, typename Expr>
struct serializer_t<Context, max_t<Expr>>
{
using T = max_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "MAX(";
serialize(t._expr, context);
context << ")";
return context;
}
};
template<typename T> template<typename T>
auto max(T t) -> typename vendor::max_t<vendor::wrap_operand_t<T>> auto max(T t) -> max_t<wrap_operand_t<T>>
{ {
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "max() requires a value expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "max() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -31,67 +31,58 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Expr>
struct min_t: public value_type_of<Expr>::template expression_operators<min_t<Expr>>,
public alias_operators<min_t<Expr>>
{ {
template<typename Expr> using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct min_t: public Expr::_value_type::template expression_operators<min_t<Expr>> using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_expression_t<Expr>::value, "min() requires a value expression as argument");
struct _name_t
{ {
static_assert(is_value_t<Expr>::value, "min() requires a value expression as argument"); static constexpr const char* _get_name() { return "MIN"; }
template<typename T>
struct _value_type: public Expr::_value_type::_base_value_type struct _member_t
{
using _is_named_expression = std::true_type;
};
using _table_set = typename Expr::_table_set;
struct _name_t
{
static constexpr const char* _get_name() { return "MIN"; }
template<typename T>
struct _member_t
{
T min;
T& operator()() { return min; }
const T& operator()() const { return min; }
};
};
min_t(Expr expr):
_expr(expr)
{}
min_t(const min_t&) = default;
min_t(min_t&&) = default;
min_t& operator=(const min_t&) = default;
min_t& operator=(min_t&&) = default;
~min_t() = default;
Expr _expr;
};
}
namespace vendor
{
template<typename Context, typename Expr>
struct serializer_t<Context, vendor::min_t<Expr>>
{
using T = vendor::min_t<Expr>;
static Context& _(const T& t, Context& context)
{ {
context << "MIN("; T min;
serialize(t._expr, context); T& operator()() { return min; }
context << ")"; const T& operator()() const { return min; }
return context; };
} };
};
} min_t(Expr expr):
_expr(expr)
{}
min_t(const min_t&) = default;
min_t(min_t&&) = default;
min_t& operator=(const min_t&) = default;
min_t& operator=(min_t&&) = default;
~min_t() = default;
Expr _expr;
};
template<typename Context, typename Expr>
struct serializer_t<Context, min_t<Expr>>
{
using T = min_t<Expr>;
static Context& _(const T& t, Context& context)
{
context << "MIN(";
serialize(t._expr, context);
context << ")";
return context;
}
};
template<typename T> template<typename T>
auto min(T t) -> typename vendor::min_t<vendor::wrap_operand_t<T>> auto min(T t) -> min_t<wrap_operand_t<T>>
{ {
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "min() requires a value expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "min() requires a value expression as argument");
return { t }; return { t };
} }

View File

@ -41,9 +41,10 @@ namespace sqlpp
template<typename Unused, typename... Columns> template<typename Unused, typename... Columns>
struct multi_column_t struct multi_column_t
{ {
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); using _traits = make_traits<no_value_t>;
using _recursive_traits = make_recursive_traits<Columns...>;
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>; static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
multi_column_t(std::tuple<Columns...> columns): multi_column_t(std::tuple<Columns...> columns):
_columns(columns) _columns(columns)
@ -75,10 +76,12 @@ namespace sqlpp
template<typename AliasProvider, typename... Columns> template<typename AliasProvider, typename... Columns>
struct multi_column_alias_t struct multi_column_alias_t
{ {
using _traits = make_traits<no_value_t, tag::alias, tag::multi_column, tag::named_expression>;
using _recursive_traits = make_recursive_traits<Columns...>;
static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions"); static_assert(detail::all_t<is_named_expression_t<Columns>::value...>::value, "multi_column parameters need to be named expressions");
using _name_t = typename AliasProvider::_name_t; using _name_t = typename AliasProvider::_name_t;
using _table_set = sqlpp::detail::make_joined_set_t<typename Columns::_table_set...>;
multi_column_alias_t(multi_column_t<void, Columns...> multi_column): multi_column_alias_t(multi_column_t<void, Columns...> multi_column):
_columns(multi_column._columns) _columns(multi_column._columns)
@ -107,31 +110,28 @@ namespace sqlpp
std::tuple<Columns...> _columns; std::tuple<Columns...> _columns;
}; };
namespace vendor template<typename Context, typename... Columns>
{ struct serializer_t<Context, multi_column_t<void, Columns...>>
template<typename Context, typename... Columns> {
struct serializer_t<Context, multi_column_t<void, Columns...>> using T = multi_column_t<void, Columns...>;
static void _(const T& t, Context& context)
{ {
using T = multi_column_t<void, Columns...>; static_assert(wrong_t<Columns...>::value, "multi_column must be used with an alias");
}
};
static void _(const T& t, Context& context) template<typename Context, typename AliasProvider, typename... Columns>
{ struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
static_assert(wrong_t<Columns...>::value, "multi_column must be used with an alias"); {
} using T = multi_column_alias_t<AliasProvider, Columns...>;
};
template<typename Context, typename AliasProvider, typename... Columns> static Context& _(const T& t, Context& context)
struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
{ {
using T = multi_column_alias_t<AliasProvider, Columns...>; interpret_tuple(t._columns, ',', context);
return context;
static Context& _(const T& t, Context& context) }
{ };
interpret_tuple(t._columns, ',', context);
return context;
}
};
}
namespace detail namespace detail
{ {

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_NAMED_SERIALIZABLE_H
#define SQLPP_NAMED_SERIALIZABLE_H
#include <memory>
#include <sqlpp11/serializer_context.h>
#include <sqlpp11/parameter_list.h>
namespace sqlpp
{
template<typename Db>
struct named_interpretable_t
{
using _serializer_context_t = typename Db::_serializer_context_t;
using _interpreter_context_t = typename Db::_interpreter_context_t;
template<typename T>
named_interpretable_t(T t):
_impl(std::make_shared<_impl_t<T>>(t))
{}
named_interpretable_t(const named_interpretable_t&) = default;
named_interpretable_t(named_interpretable_t&&) = default;
named_interpretable_t& operator=(const named_interpretable_t&) = default;
named_interpretable_t& operator=(named_interpretable_t&&) = default;
~named_interpretable_t() = default;
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
return _impl->serialize(context);
}
// 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->db_serialize(context);
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
return _impl->interpret(context);
}
std::string _get_name() const
{
return _impl->_get_name();
}
private:
struct _impl_base
{
virtual sqlpp::serializer_context_t& serialize(sqlpp::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;
};
template<typename T>
struct _impl_t: public _impl_base
{
static_assert(not make_parameter_list_t<T>::size::value, "parameters not supported in dynamic statement parts");
_impl_t(T t):
_t(t)
{}
sqlpp::serializer_context_t& serialize(sqlpp::serializer_context_t& context) const
{
sqlpp::serialize(_t, context);
return context;
}
_serializer_context_t& db_serialize(_serializer_context_t& context) const
{
Db::_serialize_interpretable(_t, context);
return context;
}
_interpreter_context_t& interpret(_interpreter_context_t& context) const
{
Db::_interpret_interpretable(_t, context);
return context;
}
std::string _get_name() const
{
return T::_name_t::_get_name();
}
T _t;
};
std::shared_ptr<const _impl_base> _impl;
};
template<typename Context, typename Database>
struct serializer_t<Context, named_interpretable_t<Database>>
{
using T = named_interpretable_t<Database>;
static Context& _(const T& t, Context& context)
{
t.serialize(context);
return context;
}
};
}
#endif

View File

@ -24,21 +24,25 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_CHAR_RESULT_ROW_H #ifndef SQLPP_NO_DATA_H
#define SQLPP_CHAR_RESULT_ROW_H #define SQLPP_NO_DATA_H
#include <type_traits>
#include <sqlpp11/serializer.h>
namespace sqlpp namespace sqlpp
{ {
struct char_result_row_t struct no_data_t {};
{
const char** data;
size_t* len;
bool operator==(const char_result_row_t& rhs) const template<typename Context>
struct serializer_t<Context, no_data_t>
{ {
return data == rhs.data and len == rhs.len; using T = no_data_t;
}
};
}
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
#endif #endif

View File

@ -33,11 +33,7 @@ namespace sqlpp
{ {
struct no_value_t struct no_value_t
{ {
template<typename T> using _tag = void;
using _constraint = std::false_type;
using _base_value_type = no_value_t;
template<typename T> template<typename T>
struct _is_valid_operand struct _is_valid_operand
{ {

View File

@ -28,30 +28,36 @@
#define SQLPP_NOOP_H #define SQLPP_NOOP_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/no_value.h>
#include <sqlpp11/serializer.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor struct noop
{ {
struct noop using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
template<typename Policies>
struct _result_methods_t
{};
};
template<typename Context>
struct serializer_t<Context, noop>
{ {
using is_noop = std::true_type; using T = noop;
static Context& _(const T& t, Context& context)
{
return context;
}
}; };
template<typename Context> template<typename T>
struct serializer_t<Context, noop> struct is_noop: std::is_same<T, noop> {};
{
using T = noop;
static Context& _(const T& t, Context& context)
{
return context;
}
};
template<typename T>
struct is_noop: std::is_same<T, noop> {};
}
} }
#endif #endif

View File

@ -29,12 +29,9 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor struct noop;
{
struct noop;
template<typename T> template<typename T>
struct is_noop; struct is_noop;
}
} }
#endif #endif

View File

@ -33,25 +33,21 @@ namespace sqlpp
{ {
struct null_t struct null_t
{ {
static constexpr bool _is_expression = true; using _traits = make_traits<no_value_t, tag::expression>;
using _value_type = no_value_t; using _recursive_traits = make_recursive_traits<>;
using _table_set = ::sqlpp::detail::type_set<>;
}; };
namespace vendor template<typename Context>
{ struct serializer_t<Context, null_t>
template<typename Context> {
struct serializer_t<Context, null_t> using Operand = null_t;
{
using Operand = null_t;
static Context& _(const Operand& t, Context& context) static Context& _(const Operand& t, Context& context)
{ {
context << "NULL"; context << "NULL";
return context; return context;
} }
}; };
}
constexpr null_t null = {}; constexpr null_t null = {};

272
include/sqlpp11/offset.h Normal file
View File

@ -0,0 +1,272 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_OFFSET_H
#define SQLPP_OFFSET_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
// OFFSET DATA
template<typename Offset>
struct offset_data_t
{
offset_data_t(Offset value):
_value(value)
{}
offset_data_t(const offset_data_t&) = default;
offset_data_t(offset_data_t&&) = default;
offset_data_t& operator=(const offset_data_t&) = default;
offset_data_t& operator=(offset_data_t&&) = default;
~offset_data_t() = default;
Offset _value;
};
// OFFSET
template<typename Offset>
struct offset_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>;
using _recursive_traits = make_recursive_traits<Offset>;
static_assert(is_integral_t<Offset>::value, "offset requires an integral value or integral parameter");
// Data
using _data_t = offset_data_t<Offset>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = offset_data_t<Offset>;
_impl_t<Policies> offset;
_impl_t<Policies>& operator()() { return offset; }
const _impl_t<Policies>& operator()() const { return offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.offset)
{
return t.offset;
}
};
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// DYNAMIC OFFSET DATA
template<typename Database>
struct dynamic_offset_data_t
{
dynamic_offset_data_t():
_value(noop())
{
}
template<typename Offset>
dynamic_offset_data_t(Offset value):
_initialized(true),
_value(typename wrap_operand<Offset>::type(value))
{
}
dynamic_offset_data_t(const dynamic_offset_data_t&) = default;
dynamic_offset_data_t(dynamic_offset_data_t&&) = default;
dynamic_offset_data_t& operator=(const dynamic_offset_data_t&) = default;
dynamic_offset_data_t& operator=(dynamic_offset_data_t&&) = default;
~dynamic_offset_data_t() = default;
bool _initialized = false;
interpretable_t<Database> _value;
};
// DYNAMIC OFFSET
template<typename Database>
struct dynamic_offset_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::offset>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = dynamic_offset_data_t<Database>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Offset>
void set(Offset value)
{
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type;
_data._value = arg_t{value};
_data._initialized = true;
}
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = dynamic_offset_data_t<Database>;
_impl_t<Policies> offset;
_impl_t<Policies>& operator()() { return offset; }
const _impl_t<Policies>& operator()() const { return offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.offset)
{
return t.offset;
}
};
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
template<typename Offset>
void set_offset(Offset value)
{
// FIXME: Make sure that Offset does not require external tables? Need to read up on SQL
using arg_t = typename wrap_operand<Offset>::type;
static_cast<typename Policies::_statement_t*>(this)->_offset()._value = arg_t{value};
static_cast<typename Policies::_statement_t*>(this)->_offset()._initialized = true;
}
};
bool _initialized = false;
interpretable_t<Database> _value;
};
struct no_offset_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_offset;
_impl_t<Policies>& operator()() { return no_offset; }
const _impl_t<Policies>& operator()() const { return no_offset; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_offset)
{
return t.no_offset;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_offset_t, T>;
static void _check_consistency() {}
template<typename Arg>
auto offset(Arg arg)
-> _new_statement_t<offset_t<typename wrap_operand<Arg>::type>>
{
return { *static_cast<typename Policies::_statement_t*>(this), offset_data_t<typename wrap_operand<Arg>::type>{{arg}} };
}
auto dynamic_offset()
-> _new_statement_t<dynamic_offset_t<_database_t>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_offset must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), dynamic_offset_data_t<_database_t>{} };
}
};
};
// Interpreters
template<typename Context, typename Offset>
struct serializer_t<Context, offset_data_t<Offset>>
{
using T = offset_data_t<Offset>;
static Context& _(const T& t, Context& context)
{
context << " OFFSET ";
serialize(t._value, context);
return context;
}
};
template<typename Context, typename Database>
struct serializer_t<Context, dynamic_offset_data_t<Database>>
{
using T = dynamic_offset_data_t<Database>;
static Context& _(const T& t, Context& context)
{
if (t._initialized)
{
context << " OFFSET ";
serialize(t._value, context);
}
return context;
}
};
}
#endif

View File

@ -28,8 +28,8 @@
#define SQLPP_ON_H #define SQLPP_ON_H
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h> #include <sqlpp11/interpretable_list.h>
#include <sqlpp11/detail/logic.h> #include <sqlpp11/detail/logic.h>
namespace sqlpp namespace sqlpp
@ -37,8 +37,10 @@ namespace sqlpp
template<typename Database, typename... Expr> template<typename Database, typename... Expr>
struct on_t struct on_t
{ {
using _is_on = std::true_type; using _traits = make_traits<no_value_t, tag::on>;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using _recursive_traits = make_recursive_traits<Expr...>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()"); static_assert(_is_dynamic::value or sizeof...(Expr), "at least one expression argument required in on()");
static_assert(detail::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()"); static_assert(detail::all_t<is_expression_t<Expr>::value...>::value, "at least one argument is not an expression in on()");
@ -51,30 +53,27 @@ namespace sqlpp
} }
std::tuple<Expr...> _expressions; std::tuple<Expr...> _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions; interpretable_list_t<Database> _dynamic_expressions;
}; };
namespace vendor template<typename Context, typename Database, typename... Expr>
{ struct serializer_t<Context, on_t<Database, Expr...>>
template<typename Context, typename Database, typename... Expr> {
struct serializer_t<Context, on_t<Database, Expr...>> using T = on_t<Database, Expr...>;
static Context& _(const T& t, Context& context)
{ {
using T = on_t<Database, Expr...>; if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expr) == 0 and t._dynamic_expressions.empty())
return context;
context << " ON ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context; return context;
} context << " ON ";
}; interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expr) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
}
} }
#endif #endif

214
include/sqlpp11/order_by.h Normal file
View File

@ -0,0 +1,214 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ORDER_BY_H
#define SQLPP_ORDER_BY_H
#include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
// ORDER BY DATA
template<typename Database, typename... Expressions>
struct order_by_data_t
{
order_by_data_t(Expressions... expressions):
_expressions(expressions...)
{}
order_by_data_t(const order_by_data_t&) = default;
order_by_data_t(order_by_data_t&&) = default;
order_by_data_t& operator=(const order_by_data_t&) = default;
order_by_data_t& operator=(order_by_data_t&&) = default;
~order_by_data_t() = default;
std::tuple<Expressions...> _expressions;
interpretable_list_t<Database> _dynamic_expressions;
};
// ORDER BY
template<typename Database, typename... Expressions>
struct order_by_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::order_by>;
using _recursive_traits = make_recursive_traits<Expressions...>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in order_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in order_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in order_by()");
// Data
using _data_t = order_by_data_t<Database, Expressions...>;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
template<typename Expression>
void add_ntc(Expression expression)
{
add<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add(Expression expression)
{
static_assert(_is_dynamic::value, "add() must not be called for static order_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in order_by::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in order_by::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_impl(Expression expression, const std::true_type&)
{
return _data._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_impl(Expression expression, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = order_by_data_t<Database, Expressions...>;
_impl_t<Policies> order_by;
_impl_t<Policies>& operator()() { return order_by; }
const _impl_t<Policies>& operator()() const { return order_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.order_by)
{
return t.order_by;
}
};
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO ORDER BY YET
struct no_order_by_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_order_by;
_impl_t<Policies>& operator()() { return no_order_by; }
const _impl_t<Policies>& operator()() const { return no_order_by; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_order_by)
{
return t.no_order_by;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_order_by_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto order_by(Args... args)
-> _new_statement_t<order_by_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_order_by(Args... args)
-> _new_statement_t<order_by_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_order_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), order_by_data_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, order_by_data_t<Database, Expressions...>>
{
using T = order_by_data_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " ORDER BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
}
#endif

View File

@ -34,16 +34,18 @@
namespace sqlpp namespace sqlpp
{ {
template<typename ValueType, typename NameType> template<typename ValueType, typename NameType>
struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>> struct parameter_t: public ValueType::template expression_operators<parameter_t<ValueType, NameType>>
{ {
struct _value_type: public ValueType using _traits = make_traits<ValueType, tag::parameter, tag::expression>;
struct _recursive_traits
{ {
using _is_expression = std::true_type; using _parameters = std::tuple<parameter_t>;
using _is_alias = std::false_type; using _provided_tables = detail::type_set<>;
using _required_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
}; };
using _is_parameter = std::true_type;
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
using _table_set = sqlpp::detail::type_set<>;
parameter_t() parameter_t()
{} {}
@ -55,24 +57,21 @@ namespace sqlpp
~parameter_t() = default; ~parameter_t() = default;
}; };
namespace vendor template<typename Context, typename ValueType, typename NameType>
{ struct serializer_t<Context, parameter_t<ValueType, NameType>>
template<typename Context, typename ValueType, typename NameType> {
struct serializer_t<Context, parameter_t<ValueType, NameType>> using T = parameter_t<ValueType, NameType>;
{
using T = parameter_t<ValueType, NameType>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "?"; context << "?";
return context; return context;
} }
}; };
}
template<typename NamedExpr> template<typename NamedExpr>
auto parameter(const NamedExpr&) auto parameter(const NamedExpr&)
-> parameter_t<typename NamedExpr::_value_type, NamedExpr> -> parameter_t<value_type_of<NamedExpr>, NamedExpr>
{ {
static_assert(is_named_expression_t<NamedExpr>::value, "not a named expression"); static_assert(is_named_expression_t<NamedExpr>::value, "not a named expression");
return {}; return {};
@ -80,9 +79,9 @@ namespace sqlpp
template<typename ValueType, typename AliasProvider> template<typename ValueType, typename AliasProvider>
auto parameter(const ValueType&, const AliasProvider&) auto parameter(const ValueType&, const AliasProvider&)
-> parameter_t<ValueType, AliasProvider> -> parameter_t<wrap_operand_t<ValueType>, AliasProvider>
{ {
static_assert(is_value_t<ValueType>::value, "first argument is not a value type"); static_assert(is_expression_t<ValueType>::value, "first argument is not a value type");
static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider"); static_assert(is_alias_provider_t<AliasProvider>::value, "second argument is not an alias provider");
return {}; return {};
} }

View File

@ -28,7 +28,8 @@
#define SQLPP_PARAMETER_LIST_H #define SQLPP_PARAMETER_LIST_H
#include <tuple> #include <tuple>
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/wrong.h>
#include <sqlpp11/detail/index_sequence.h> #include <sqlpp11/detail/index_sequence.h>
namespace sqlpp namespace sqlpp
@ -36,7 +37,7 @@ namespace sqlpp
template<typename T> template<typename T>
struct parameter_list_t struct parameter_list_t
{ {
static_assert(vendor::wrong_t<T>::value, "Template parameter for parameter_list_t has to be a tuple"); static_assert(wrong_t<T>::value, "Template parameter for parameter_list_t has to be a tuple");
}; };
template<typename... Parameter> template<typename... Parameter>
@ -63,40 +64,8 @@ namespace sqlpp
} }
}; };
namespace detail
{
template<typename Exp, typename Enable = void>
struct get_parameter_tuple
{
using type = std::tuple<>;
};
template<typename Exp>
struct get_parameter_tuple<Exp, typename std::enable_if<is_parameter_t<Exp>::value, void>::type>
{
using type = std::tuple<Exp>;
};
template<typename... Param>
struct get_parameter_tuple<std::tuple<Param...>, void>
{
// cat together parameter tuples
using type = decltype(std::tuple_cat(std::declval<typename get_parameter_tuple<Param>::type>()...));
};
template<typename Exp>
struct get_parameter_tuple<Exp, typename std::enable_if<not std::is_same<typename Exp::_parameter_tuple_t, void>::value, void>::type>
{
using type = typename get_parameter_tuple<typename Exp::_parameter_tuple_t>::type;
};
}
template<typename Exp> template<typename Exp>
struct make_parameter_list_t using make_parameter_list_t = parameter_list_t<parameters_of<Exp>>;
{
using type = parameter_list_t<typename detail::get_parameter_tuple<Exp>::type>;
};
} }

View File

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

View File

@ -35,14 +35,14 @@ namespace sqlpp
template<typename Db, typename Insert> template<typename Db, typename Insert>
struct prepared_insert_t struct prepared_insert_t
{ {
using _parameter_list_t = typename Insert::_parameter_list_t; using _parameter_list_t = make_parameter_list_t<Insert>;
using _prepared_statement_t = typename Db::_prepared_statement_t; using _prepared_statement_t = typename Db::_prepared_statement_t;
auto _run(Db& db) const auto _run(Db& db) const
-> size_t -> size_t
{ {
return db.run_prepared_insert(*this); return db.run_prepared_insert(*this);
} }
void _bind_params() const void _bind_params() const
{ {

View File

@ -35,14 +35,14 @@ namespace sqlpp
template<typename Db, typename Remove> template<typename Db, typename Remove>
struct prepared_remove_t struct prepared_remove_t
{ {
using _parameter_list_t = typename Remove::_parameter_list_t; using _parameter_list_t = make_parameter_list_t<Remove>;
using _prepared_statement_t = typename Db::_prepared_statement_t; using _prepared_statement_t = typename Db::_prepared_statement_t;
auto _run(Db& db) const auto _run(Db& db) const
-> size_t -> size_t
{ {
return db.run_prepared_insert(*this); return db.run_prepared_insert(*this);
} }
void _bind_params() const void _bind_params() const
{ {

View File

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

View File

@ -35,14 +35,14 @@ namespace sqlpp
template<typename Db, typename Update> template<typename Db, typename Update>
struct prepared_update_t struct prepared_update_t
{ {
using _parameter_list_t = typename Update::_parameter_list_t; using _parameter_list_t = make_parameter_list_t<Update>;
using _prepared_statement_t = typename Db::_prepared_statement_t; using _prepared_statement_t = typename Db::_prepared_statement_t;
auto _run(Db& db) const auto _run(Db& db) const
-> size_t -> size_t
{ {
return db.run_prepared_insert(*this); return db.run_prepared_insert(*this);
} }
void _bind_params() const void _bind_params() const
{ {

View File

@ -27,183 +27,103 @@
#ifndef SQLPP_REMOVE_H #ifndef SQLPP_REMOVE_H
#define SQLPP_REMOVE_H #define SQLPP_REMOVE_H
#include <sqlpp11/statement.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_remove.h> #include <sqlpp11/prepared_remove.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/from.h>
#include <sqlpp11/vendor/extra_tables.h> #include <sqlpp11/extra_tables.h>
#include <sqlpp11/vendor/using.h> #include <sqlpp11/using.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/where.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, struct remove_name_t {};
typename... Policies struct remove_t: public statement_name_t<remove_name_t>
>
struct remove_t;
namespace detail
{ {
template<typename Db = void, using _traits = make_traits<no_value_t, tag::return_value>;
typename Table = vendor::no_single_table_t, struct _name_t {};
typename Using = vendor::no_using_t,
typename ExtraTables = vendor::no_extra_tables_t, template<typename Policies>
typename Where = vendor::no_where_t struct _result_methods_t
>
struct remove_policies_t
{ {
using _database_t = Db; using _statement_t = typename Policies::_statement_t;
using _table_t = Table;
using _using_t = Using;
using _extra_tables_t = ExtraTables;
using _where_t = Where;
using _statement_t = remove_t<Db, Table, Using, ExtraTables, Where>; const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
struct _methods_t: template<typename Db>
public _using_t::template _methods_t<remove_policies_t>, auto _run(Db& db) const -> decltype(db.remove(this->_get_statement()))
public _extra_tables_t::template _methods_t<remove_policies_t>,
public _where_t::template _methods_t<remove_policies_t>
{};
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_t
{ {
using type = remove_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>; _statement_t::_check_consistency();
};
template<typename Needle, typename Replacement> static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, Using, ExtraTables, Where>::type; return db.remove(_get_statement());
}
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set, typename _using_t::_table_set, typename _extra_tables_t::_table_set>; template<typename Db>
auto _prepare(Db& db) const
-> prepared_remove_t<Db, _statement_t>
{
_statement_t::_check_consistency();
template<typename Expression> return {{}, db.prepare_remove(_get_statement())};
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>; }
}; };
} };
// REMOVE
template<typename Db, template<typename Context>
typename... Policies struct serializer_t<Context, remove_name_t>
>
struct remove_t:
public detail::remove_policies_t<Db, Policies...>::_methods_t
{ {
using _policies_t = typename detail::remove_policies_t<Db, Policies...>; using T = remove_name_t;
using _database_t = typename _policies_t::_database_t;
using _table_t = typename _policies_t::_table_t;
using _using_t = typename _policies_t::_using_t;
using _extra_tables_t = typename _policies_t::_extra_tables_t;
using _where_t = typename _policies_t::_where_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; static Context& _(const T& t, Context& context)
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<remove_t>::type;
// Constructors
remove_t()
{}
template<typename Statement, typename T>
remove_t(Statement s, T t):
_table(detail::arg_selector<_table_t>::_(s._table, t)),
_using(detail::arg_selector<_using_t>::_(s._using, t)),
_where(detail::arg_selector<_where_t>::_(s._where, t))
{}
remove_t(const remove_t&) = default;
remove_t(remove_t&&) = default;
remove_t& operator=(const remove_t&) = default;
remove_t& operator=(remove_t&&) = default;
~remove_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; context << "DELETE";
return context;
} }
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
template<typename A>
struct is_table_subset_of_table
{
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
};
void _check_consistency() const
{
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
// FIXME: Read more details about what is allowed and what not in SQL DELETE
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run remove directly with parameters, use prepare instead");
return db.remove(*this);
}
template<typename Database>
auto _prepare(Database& db) const
-> prepared_remove_t<Database, remove_t>
{
_check_consistency();
return {{}, db.prepare_remove(*this)};
}
_table_t _table;
_using_t _using;
_where_t _where;
}; };
namespace vendor template<typename Database>
{ using blank_remove_t = statement_t<Database,
template<typename Context, typename Database, typename... Policies> remove_t,
struct serializer_t<Context, remove_t<Database, Policies...>> no_from_t,
{ no_using_t,
using T = remove_t<Database, Policies...>; no_extra_tables_t,
no_where_t<true>
>;
static Context& _(const T& t, Context& context) auto remove()
{ -> blank_remove_t<void>
context << "DELETE FROM "; {
serialize(t._table, context); return { blank_remove_t<void>() };
serialize(t._using, context); }
serialize(t._where, context);
return context;
}
};
}
template<typename Database, typename... Policies>
using make_remove_t = typename detail::remove_policies_t<Database, Policies...>::_statement_t;
template<typename Table> template<typename Table>
constexpr auto remove_from(Table table) auto remove_from(Table table)
-> make_remove_t<void, vendor::single_table_t<void, Table>> -> decltype(blank_remove_t<void>().from(table))
{ {
return { make_remove_t<void>(), vendor::single_table_t<void, Table>{table} }; return { blank_remove_t<void>().from(table) };
}
template<typename Database>
auto dynamic_remove(const Database&)
-> decltype(blank_remove_t<Database>())
{
return { blank_remove_t<Database>() };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_remove_from(const Database&, Table table) auto dynamic_remove_from(const Database&, Table table)
-> make_remove_t<Database, vendor::single_table_t<void, Table>> -> decltype(blank_remove_t<Database>().from(table))
{ {
return { make_remove_t<Database>(), vendor::single_table_t<void, Table>{table} }; return { blank_remove_t<Database>().from(table) };
} }
} }
#endif #endif

View File

@ -45,12 +45,12 @@ namespace sqlpp
result_t() = default; result_t() = default;
template<typename DynamicNames> template<typename DynamicNames>
result_t(db_result_t&& result, const DynamicNames& dynamic_names): result_t(db_result_t&& result, const DynamicNames& dynamic_names):
_result(std::move(result)), _result(std::move(result)),
_result_row(dynamic_names) _result_row(dynamic_names)
{ {
_result.next(_result_row); _result.next(_result_row);
} }
result_t(const result_t&) = delete; result_t(const result_t&) = delete;
result_t(result_t&&) = default; result_t(result_t&&) = default;

View File

@ -28,8 +28,7 @@
#define SQLPP_RESULT_ROW_H #define SQLPP_RESULT_ROW_H
#include <map> #include <map>
#include <sqlpp11/vendor/char_result_row.h> #include <sqlpp11/field.h>
#include <sqlpp11/vendor/field.h>
#include <sqlpp11/text.h> #include <sqlpp11/text.h>
#include <sqlpp11/detail/column_index_sequence.h> #include <sqlpp11/detail/column_index_sequence.h>
@ -42,115 +41,86 @@ namespace sqlpp
template<typename Db, std::size_t index, typename NamedExpr> template<typename Db, std::size_t index, typename NamedExpr>
struct result_field: struct result_field:
public NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>> public NamedExpr::_name_t::template _member_t<typename value_type_of<NamedExpr>::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>
{
using _field = typename NamedExpr::_name_t::template _member_t<typename value_type_of<NamedExpr>::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>;
result_field() = default;
void _validate()
{ {
using _field = typename NamedExpr::_name_t::template _member_t<typename NamedExpr::_value_type::template _result_entry_t<Db, NamedExpr::_trivial_value_is_null>>; _field::operator()()._validate();
}
result_field() = default; void _invalidate()
result_field(const char_result_row_t& char_result_row_t): {
_field({{char_result_row_t.data[index], char_result_row_t.len[index]}}) _field::operator()()._invalidate();
{ }
}
result_field& operator=(const char_result_row_t& char_result_row_t) template<typename Target>
{
_field::operator()().assign(char_result_row_t.data[index], char_result_row_t.len[index]);
return *this;
}
void validate()
{
_field::operator()().validate();
}
void invalidate()
{
_field::operator()().invalidate();
}
template<typename Target>
void _bind(Target& target) void _bind(Target& target)
{ {
_field::operator()()._bind(target, index); _field::operator()()._bind(target, index);
} }
}; };
template<std::size_t index, typename AliasProvider, typename Db, typename... NamedExprs> template<std::size_t index, typename AliasProvider, typename Db, typename... NamedExprs>
struct result_field<Db, index, vendor::multi_field_t<AliasProvider, std::tuple<NamedExprs...>>>: struct result_field<Db, index, multi_field_t<AliasProvider, std::tuple<NamedExprs...>>>:
public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>> public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>>
{ {
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>>; using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, NamedExprs...>, NamedExprs...>>;
result_field() = default; result_field() = default;
result_field(const char_result_row_t& char_result_row_t):
_multi_field({char_result_row_t})
{}
result_field& operator=(const char_result_row_t& char_result_row_t) void _validate()
{ {
_multi_field::operator()() = char_result_row_t; _multi_field::operator()()._validate();
return *this;
} }
void validate() void _invalidate()
{ {
_multi_field::operator()().validate(); _multi_field::operator()()._invalidate();
}
void invalidate()
{
_multi_field::operator()().invalidate();
} }
template<typename Target> template<typename Target>
void _bind(Target& target) void _bind(Target& target)
{ {
_multi_field::operator()()._bind(target); _multi_field::operator()()._bind(target);
} }
}; };
template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... NamedExprs> template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... NamedExprs>
struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, NamedExprs...>: struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, NamedExprs...>:
public result_field<Db, Is, NamedExprs>... public result_field<Db, Is, NamedExprs>...
{ {
static constexpr std::size_t _last_index = LastIndex; static constexpr std::size_t _last_index = LastIndex;
result_row_impl() = default; result_row_impl() = default;
result_row_impl(const char_result_row_t& char_result_row):
result_field<Db, Is, NamedExprs>(char_result_row)...
{
}
result_row_impl& operator=(const char_result_row_t& char_result_row) void _validate()
{ {
using swallow = int[]; using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::operator=(char_result_row), 0)...}; (void) swallow{(result_field<Db, Is, NamedExprs>::_validate(), 0)...};
return *this;
} }
void validate() void _invalidate()
{ {
using swallow = int[]; using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::validate(), 0)...}; (void) swallow{(result_field<Db, Is, NamedExprs>::_invalidate(), 0)...};
}
void invalidate()
{
using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::invalidate(), 0)...};
} }
template<typename Target> template<typename Target>
void _bind(Target& target) void _bind(Target& target)
{ {
using swallow = int[]; using swallow = int[];
(void) swallow{(result_field<Db, Is, NamedExprs>::_bind(target), 0)...}; (void) swallow{(result_field<Db, Is, NamedExprs>::_bind(target), 0)...};
} }
}; };
} }
template<typename Db, typename... NamedExprs> template<typename Db, typename... NamedExprs>
struct result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...> struct result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>
{ {
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>; using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>;
bool _is_valid; bool _is_valid;
@ -163,9 +133,9 @@ namespace sqlpp
} }
template<typename DynamicNames> template<typename DynamicNames>
result_row_t(const DynamicNames&): result_row_t(const DynamicNames&):
_impl(), _impl(),
_is_valid(false) _is_valid(false)
{ {
} }
@ -174,22 +144,15 @@ namespace sqlpp
result_row_t& operator=(const result_row_t&) = delete; result_row_t& operator=(const result_row_t&) = delete;
result_row_t& operator=(result_row_t&&) = default; result_row_t& operator=(result_row_t&&) = default;
result_row_t& operator=(const char_result_row_t& char_result_row_t) void _validate()
{ {
_impl::operator=(char_result_row_t); _impl::_validate();
_is_valid = true;
return *this;
}
void validate()
{
_impl::validate();
_is_valid = true; _is_valid = true;
} }
void invalidate() void _invalidate()
{ {
_impl::invalidate(); _impl::_invalidate();
_is_valid = false; _is_valid = false;
} }
@ -209,14 +172,14 @@ namespace sqlpp
} }
template<typename Target> template<typename Target>
void bind_result(Target& target) void _bind(Target& target)
{ {
_impl::_bind(target); _impl::_bind(target);
} }
}; };
template<typename Db, typename... NamedExprs> template<typename Db, typename... NamedExprs>
struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...> struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>
{ {
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>; using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, NamedExprs...>, NamedExprs...>;
using _field_type = detail::text::_result_entry_t<Db, false>; using _field_type = detail::text::_result_entry_t<Db, false>;
@ -237,6 +200,10 @@ namespace sqlpp
_is_valid(false), _is_valid(false),
_dynamic_columns(dynamic_columns) _dynamic_columns(dynamic_columns)
{ {
for (auto name : _dynamic_columns)
{
_dynamic_fields.insert({name, _field_type{}});
}
} }
dynamic_result_row_t(const dynamic_result_row_t&) = delete; dynamic_result_row_t(const dynamic_result_row_t&) = delete;
@ -244,31 +211,24 @@ namespace sqlpp
dynamic_result_row_t& operator=(const dynamic_result_row_t&) = delete; dynamic_result_row_t& operator=(const dynamic_result_row_t&) = delete;
dynamic_result_row_t& operator=(dynamic_result_row_t&&) = default; dynamic_result_row_t& operator=(dynamic_result_row_t&&) = default;
dynamic_result_row_t& operator=(const char_result_row_t& char_result_row) void _validate()
{ {
_impl::operator=(char_result_row);
_impl::_validate();
_is_valid = true; _is_valid = true;
for (auto& field : _dynamic_fields)
char_result_row_t dynamic_row = char_result_row;
dynamic_row.data += _last_static_index;
dynamic_row.len += _last_static_index;
for (const auto& column : _dynamic_columns)
{ {
_dynamic_fields[column].assign(dynamic_row.data[0], dynamic_row.len[0]); field.second._validate();
++dynamic_row.data;
++dynamic_row.len;
} }
return *this;
} }
void invalidate() void _invalidate()
{ {
_impl::invalidate(); _impl::_invalidate();
_is_valid = false; _is_valid = false;
for (auto& field : _dynamic_fields) for (auto& field : _dynamic_fields)
{ {
field.second.invalidate(); field.second._invalidate();
} }
} }
@ -287,6 +247,17 @@ namespace sqlpp
return _is_valid; return _is_valid;
} }
template<typename Target>
void _bind(Target& target)
{
_impl::_bind(target);
std::size_t index = _last_static_index;
for (const auto& name : _dynamic_columns)
{
_dynamic_fields.at(name)._bind(target, ++index);
}
}
}; };
} }

View File

@ -27,332 +27,81 @@
#ifndef SQLPP_SELECT_H #ifndef SQLPP_SELECT_H
#define SQLPP_SELECT_H #define SQLPP_SELECT_H
#include <sqlpp11/result.h> #include <sqlpp11/statement.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_select.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/vendor/select_flag_list.h> #include <sqlpp11/select_flag_list.h>
#include <sqlpp11/vendor/select_column_list.h> #include <sqlpp11/select_column_list.h>
#include <sqlpp11/vendor/from.h> #include <sqlpp11/from.h>
#include <sqlpp11/vendor/extra_tables.h> #include <sqlpp11/extra_tables.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/where.h>
#include <sqlpp11/vendor/group_by.h> #include <sqlpp11/group_by.h>
#include <sqlpp11/vendor/having.h> #include <sqlpp11/having.h>
#include <sqlpp11/vendor/order_by.h> #include <sqlpp11/order_by.h>
#include <sqlpp11/vendor/limit.h> #include <sqlpp11/limit.h>
#include <sqlpp11/vendor/offset.h> #include <sqlpp11/offset.h>
#include <sqlpp11/vendor/expression.h> #include <sqlpp11/expression.h>
#include <sqlpp11/vendor/serializer.h> #include <sqlpp11/wrong.h>
#include <sqlpp11/vendor/wrong.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, struct select_name_t {};
typename... Policies
>
struct select_t;
namespace detail struct select_t: public statement_name_t<select_name_t>
{ {};
template<typename Db = void,
typename FlagList = vendor::no_select_flag_list_t,
typename ColumnList = vendor::no_select_column_list_t,
typename From = vendor::no_from_t,
typename ExtraTables = vendor::no_extra_tables_t,
typename Where = vendor::no_where_t,
typename GroupBy = vendor::no_group_by_t,
typename Having = vendor::no_having_t,
typename OrderBy = vendor::no_order_by_t,
typename Limit = vendor::no_limit_t,
typename Offset = vendor::no_offset_t
>
struct select_policies_t
{
using _database_t = Db;
using _flag_list_t = FlagList;
using _column_list_t = ColumnList;
using _from_t = From;
using _extra_tables_t = ExtraTables;
using _where_t = Where;
using _group_by_t = GroupBy;
using _having_t = Having;
using _order_by_t = OrderBy;
using _limit_t = Limit;
using _offset_t = Offset;
using _statement_t = select_t<Db, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>; template<typename Context>
struct serializer_t<Context, select_name_t>
struct _methods_t:
public _flag_list_t::template _methods_t<select_policies_t>,
public _column_list_t::template _methods_t<select_policies_t>,
public _from_t::template _methods_t<select_policies_t>,
public _extra_tables_t::template _methods_t<select_policies_t>,
public _where_t::template _methods_t<select_policies_t>,
public _group_by_t::template _methods_t<select_policies_t>,
public _having_t::template _methods_t<select_policies_t>,
public _order_by_t::template _methods_t<select_policies_t>,
public _limit_t::template _methods_t<select_policies_t>,
public _offset_t::template _methods_t<select_policies_t>
{};
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_t
{
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
using type = select_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement, FlagList, ColumnList, From, ExtraTables, Where, GroupBy, Having, OrderBy, Limit, Offset>::type;
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 _known_tables = detail::make_joined_set_t<typename _from_t::_table_set, typename _extra_tables_t::_table_set>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>;
using _required_tables =
detail::make_joined_set_t<
typename _flag_list_t::_table_set,
typename _column_list_t::_table_set,
typename _where_t::_table_set,
typename _group_by_t::_table_set,
typename _having_t::_table_set,
typename _order_by_t::_table_set,
typename _limit_t::_table_set,
typename _offset_t::_table_set
>;
// The tables not covered by the from.
using _table_set = detail::make_difference_set_t<
_required_tables,
typename _from_t::_table_set // Hint: extra_tables_t is not used here because it is just a helper for dynamic .add_*() methods and should not change the structural integrity
>;
// A select can be used as a pseudo table if
// - at least one column is selected
// - the select is complete (leaks no tables)
using _can_be_used_as_table = typename std::conditional<
is_select_column_list_t<_column_list_t>::value and _table_set::size::value == 0,
std::true_type,
std::false_type
>::type;
using _value_type = typename std::conditional<
is_select_column_list_t<_column_list_t>::value and is_subset_of<typename _column_list_t::_table_set, typename _from_t::_table_set>::value,
typename ColumnList::_value_type,
no_value_t // If something is selected that requires a table, then we require a from for this to be a value
>::type;
};
}
// SELECT
template<typename Db,
typename... Policies
>
struct select_t:
public detail::select_policies_t<Db, Policies...>::_value_type::template expression_operators<select_t<Db, Policies...>>,
public detail::select_policies_t<Db, Policies...>::_methods_t
{ {
using _policies_t = typename detail::select_policies_t<Db, Policies...>; using T = select_name_t;
using _database_t = typename _policies_t::_database_t;
using _flag_list_t = typename _policies_t::_flag_list_t;
using _column_list_t = typename _policies_t::_column_list_t;
using _from_t = typename _policies_t::_from_t;
using _extra_tables_t = typename _policies_t::_extra_tables_t;
using _where_t = typename _policies_t::_where_t;
using _group_by_t = typename _policies_t::_group_by_t;
using _having_t = typename _policies_t::_having_t;
using _order_by_t = typename _policies_t::_order_by_t;
using _limit_t = typename _policies_t::_limit_t;
using _offset_t = typename _policies_t::_offset_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; static Context& _(const T& t, Context& context)
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<select_t>::type;
using _table_set = typename _policies_t::_table_set;
template<typename Database>
using _result_row_t = typename _column_list_t::template _result_row_t<Database>;
using _dynamic_names_t = typename _column_list_t::_dynamic_names_t;
using _is_select = std::true_type;
using _requires_braces = std::true_type;
using _value_type = typename detail::select_policies_t<Db, Policies...>::_value_type;
using _name_t = typename _column_list_t::_name_t;
// Constructors
select_t()
{}
template<typename Statement, typename T>
select_t(Statement s, T t):
_flag_list(detail::arg_selector<_flag_list_t>::_(s._flag_list, t)),
_column_list(detail::arg_selector<_column_list_t>::_(s._column_list, t)),
_from(detail::arg_selector<_from_t>::_(s._from, t)),
_where(detail::arg_selector<_where_t>::_(s._where, t)),
_group_by(detail::arg_selector<_group_by_t>::_(s._group_by, t)),
_having(detail::arg_selector<_having_t>::_(s._having, t)),
_order_by(detail::arg_selector<_order_by_t>::_(s._order_by, t)),
_limit(detail::arg_selector<_limit_t>::_(s._limit, t)),
_offset(detail::arg_selector<_offset_t>::_(s._offset, t))
{}
select_t(const select_t& r) = default;
select_t(select_t&& r) = default;
select_t& operator=(const select_t& r) = default;
select_t& operator=(select_t&& r) = default;
~select_t() = default;
// PseudoTable
template<typename AliasProvider>
struct _pseudo_table_t
{
using table = typename _column_list_t::template _pseudo_table_t<select_t>;
using alias = typename table::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
typename _pseudo_table_t<AliasProvider>::alias as(const AliasProvider& aliasProvider) const
{
static_assert(_policies_t::_can_be_used_as_table::value, "select cannot be used as table, incomplete from()");
return typename _pseudo_table_t<AliasProvider>::table(
*this).as(aliasProvider);
}
const _dynamic_names_t& get_dynamic_names() const
{ {
return _column_list._dynamic_columns._dynamic_expression_names; context << "SELECT ";
return context;
} }
static constexpr size_t _get_static_no_of_parameters()
{
return _parameter_list_t::size::value;
}
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
size_t get_no_of_result_columns() const
{
return _column_list_t::static_size() + get_dynamic_names().size();
}
template<typename A>
struct is_table_subset_of_from
{
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _from_t::_table_set>::value;
};
void _check_consistency() const
{
static_assert(is_select_column_list_t<_column_list_t>::value, "no columns selected");
static_assert(is_table_subset_of_from<_flag_list_t>::value, "flags require additional tables in from()");
static_assert(is_table_subset_of_from<_column_list_t>::value, "selected columns require additional tables in from()");
static_assert(is_table_subset_of_from<_where_t>::value, "where() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_group_by_t>::value, "group_by() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_having_t>::value, "having() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_order_by_t>::value, "order_by() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_limit_t>::value, "limit() expression requires additional tables in from()");
static_assert(is_table_subset_of_from<_offset_t>::value, "offset() expression requires additional tables in from()");
static_assert(not _table_set::size::value, "one sub expression contains tables which are not in the from()");
}
// Execute
template<typename Database>
auto _run(Database& db) const
-> result_t<decltype(db.select(*this)), _result_row_t<Database>>
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(*this), get_dynamic_names()};
}
// Prepare
template<typename Database>
auto _prepare(Database& db) const
-> prepared_select_t<Database, select_t>
{
_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(*this)};
}
_flag_list_t _flag_list;
_column_list_t _column_list;
_from_t _from;
_where_t _where;
_group_by_t _group_by;
_having_t _having;
_order_by_t _order_by;
_limit_t _limit;
_offset_t _offset;
}; };
namespace vendor template<typename Database>
{ using blank_select_t = statement_t<Database,
template<typename Context, typename Database, typename... Policies> select_t,
struct serializer_t<Context, select_t<Database, Policies...>> no_select_flag_list_t,
{ no_select_column_list_t,
using T = select_t<Database, Policies...>; no_from_t,
no_extra_tables_t,
no_where_t<true>,
no_group_by_t,
no_having_t,
no_order_by_t,
no_limit_t,
no_offset_t>;
static Context& _(const T& t, Context& context)
{
context << "SELECT ";
serialize(t._flag_list, context); blank_select_t<void> select() // FIXME: These should be constexpr
serialize(t._column_list, context);
serialize(t._from, context);
serialize(t._where, context);
serialize(t._group_by, context);
serialize(t._having, context);
serialize(t._order_by, context);
serialize(t._limit, context);
serialize(t._offset, context);
return context;
}
};
}
template<typename Database, typename... Policies>
using make_select_t = typename detail::select_policies_t<Database, Policies...>::_statement_t;
make_select_t<void> select() // FIXME: These should be constexpr
{ {
return { }; return { };
} }
template<typename... Columns> template<typename... Columns>
auto select(Columns... columns) auto select(Columns... columns)
-> make_select_t<void, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>> -> decltype(blank_select_t<void>().columns(columns...))
{ {
return { make_select_t<void>(), detail::make_select_column_list_t<void, Columns...>{std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)} }; return blank_select_t<void>().columns(columns...);
} }
template<typename Database> template<typename Database>
make_select_t<Database> dynamic_select(const Database&) blank_select_t<Database> dynamic_select(const Database&)
{ {
return { make_select_t<Database>() }; return { };
} }
template<typename Database, typename... Columns> template<typename Database, typename... Columns>
auto dynamic_select(const Database&, Columns... columns) auto dynamic_select(const Database&, Columns... columns)
-> make_select_t<Database, vendor::no_select_flag_list_t, detail::make_select_column_list_t<void, Columns...>> -> decltype(blank_select_t<Database>().columns(columns...))
{ {
return { make_select_t<Database>(), detail::make_select_column_list_t<void, Columns...>(std::tuple_cat(detail::as_tuple<Columns>::_(columns)...)) }; return blank_select_t<Database>().columns(columns...);
} }
} }

View File

@ -0,0 +1,397 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SELECT_COLUMN_LIST_H
#define SQLPP_SELECT_COLUMN_LIST_H
#include <tuple>
#include <sqlpp11/result_row.h>
#include <sqlpp11/table.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/field.h>
#include <sqlpp11/expression_fwd.h>
#include <sqlpp11/select_pseudo_table.h>
#include <sqlpp11/named_interpretable.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/detail/copy_tuple_args.h>
namespace sqlpp
{
namespace detail
{
template<typename... Columns>
struct select_traits
{
using _traits = make_traits<no_value_t, tag::select_column_list, tag::return_value>;
struct _name_t {};
};
template<typename Column>
struct select_traits<Column>
{
using _traits = make_traits<value_type_of<Column>, tag::select_column_list, tag::return_value, tag::expression, tag::named_expression>;
using _name_t = typename Column::_name_t;
};
}
template<typename Db>
struct dynamic_select_column_list
{
using _names_t = std::vector<std::string>;
std::vector<named_interpretable_t<Db>> _dynamic_columns;
_names_t _dynamic_expression_names;
template<typename Expr>
void emplace_back(Expr expr)
{
_dynamic_expression_names.push_back(Expr::_name_t::_get_name());
_dynamic_columns.emplace_back(expr);
}
bool empty() const
{
return _dynamic_columns.empty();
}
};
template<>
struct dynamic_select_column_list<void>
{
struct _names_t
{
static constexpr size_t size() { return 0; }
};
_names_t _dynamic_expression_names;
static constexpr bool empty()
{
return true;
}
};
template<typename Context, typename Db>
struct serializer_t<Context, dynamic_select_column_list<Db>>
{
using T = dynamic_select_column_list<Db>;
static Context& _(const T& t, Context& context)
{
bool first = true;
for (const auto column : t._dynamic_columns)
{
if (first)
first = false;
else
context << ',';
serialize(column, context);
}
return context;
}
};
template<typename Context>
struct serializer_t<Context, dynamic_select_column_list<void>>
{
using T = dynamic_select_column_list<void>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
// SELECTED COLUMNS DATA
template<typename Database, typename... Columns>
struct select_column_list_data_t
{
select_column_list_data_t(Columns... columns):
_columns(columns...)
{}
select_column_list_data_t(std::tuple<Columns...> columns):
_columns(columns)
{}
select_column_list_data_t(const select_column_list_data_t&) = default;
select_column_list_data_t(select_column_list_data_t&&) = default;
select_column_list_data_t& operator=(const select_column_list_data_t&) = default;
select_column_list_data_t& operator=(select_column_list_data_t&&) = default;
~select_column_list_data_t() = default;
std::tuple<Columns...> _columns;
dynamic_select_column_list<Database> _dynamic_columns;
};
// SELECTED COLUMNS
template<typename Database, typename... Columns>
struct select_column_list_t
{
using _traits = typename ::sqlpp::detail::select_traits<Columns...>::_traits;
using _recursive_traits = make_recursive_traits<Columns...>;
using _name_t = typename ::sqlpp::detail::select_traits<Columns...>::_name_t;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Columns), "at least one select expression required");
static_assert(not ::sqlpp::detail::has_duplicates<Columns...>::value, "at least one duplicate argument detected");
static_assert(::sqlpp::detail::all_t<(is_named_expression_t<Columns>::value or is_multi_column_t<Columns>::value)...>::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");
struct _column_type {};
// Data
using _data_t = select_column_list_data_t<Database, Columns...>;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
template<typename NamedExpression>
void add_ntc(NamedExpression namedExpression)
{
add<NamedExpression, std::false_type>(namedExpression);
}
template<typename NamedExpression, typename TableCheckRequired = std::true_type>
void add(NamedExpression namedExpression)
{
static_assert(_is_dynamic::value, "selected_columns::add() can only be called for dynamic_column");
static_assert(is_named_expression_t<NamedExpression>::value, "invalid named expression argument in selected_columns::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<NamedExpression>::value, "named expression uses tables unknown to this statement in selected_columns::add()");
using column_names = ::sqlpp::detail::make_type_set_t<typename Columns::_name_t...>;
static_assert(not ::sqlpp::detail::is_element_of<typename NamedExpression::_name_t, column_names>::value, "a column of this name is present in the select already");
using ok = ::sqlpp::detail::all_t<
_is_dynamic::value,
is_named_expression_t<NamedExpression>::value
>;
_add_impl(namedExpression, ok()); // dispatch to prevent compile messages after the static_assert
}
//private:
template<typename NamedExpression>
void _add_impl(NamedExpression namedExpression, const std::true_type&)
{
return _data._dynamic_columns.emplace_back(namedExpression);
}
template<typename NamedExpression>
void _add_column_impl(NamedExpression namedExpression, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = select_column_list_data_t<Database, Columns...>;
_impl_t<Policies> selected_columns;
_impl_t<Policies>& operator()() { return selected_columns; }
const _impl_t<Policies>& operator()() const { return selected_columns; }
template<typename T>
static auto _get_member(T t) -> decltype(t.selected_columns)
{
return t.selected_columns;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
// Result methods
template<typename Policies>
struct _result_methods_t
{
using _statement_t = typename Policies::_statement_t;
const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
template<typename Db>
using _result_row_t = typename std::conditional<_is_dynamic::value,
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;
template<typename AliasProvider>
struct _deferred_table_t
{
using table = select_pseudo_table_t<_statement_t, Columns...>;
using alias = typename table::template _alias_t<AliasProvider>;
};
template<typename AliasProvider>
using _table_t = typename _deferred_table_t<AliasProvider>::table;
template<typename AliasProvider>
using _alias_t = typename _deferred_table_t<AliasProvider>::alias;
template<typename AliasProvider>
_alias_t<AliasProvider> as(const AliasProvider& aliasProvider) const
{
static_assert(Policies::_can_be_used_as_table::value, "statement cannot be used as table, e.g. due to missing tables");
static_assert(::sqlpp::detail::none_t<is_multi_column_t<Columns>::value...>::value, "cannot use multi-columns in sub selects");
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
}
const _dynamic_names_t& get_dynamic_names() const
{
return _get_statement().selected_columns._data._dynamic_columns._dynamic_expression_names;
}
size_t get_no_of_result_columns() const
{
return sizeof...(Columns) + get_dynamic_names().size();
}
// Execute
template<typename Db>
auto _run(Db& db) const
-> result_t<decltype(db.select(this->_get_statement())), _result_row_t<Db>>
{
_statement_t::_check_consistency();
static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run select directly with parameters, use prepare instead");
return {db.select(_get_statement()), get_dynamic_names()};
}
// Prepare
template<typename Db>
auto _prepare(Db& db) const
-> prepared_select_t<Db, _statement_t>
{
_statement_t::_check_consistency();
return {{}, get_dynamic_names(), db.prepare_select(_get_statement())};
}
};
};
namespace detail
{
template<typename Database, typename... Columns>
using make_select_column_list_t =
copy_tuple_args_t<select_column_list_t, Database,
decltype(std::tuple_cat(as_tuple<Columns>::_(std::declval<Columns>())...))>;
}
struct no_select_column_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop, ::sqlpp::tag::missing>;
using _recursive_traits = make_recursive_traits<>;
struct _name_t {};
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_selected_columns;
_impl_t<Policies>& operator()() { return no_selected_columns; }
const _impl_t<Policies>& operator()() const { return no_selected_columns; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_selected_columns)
{
return t.no_selected_columns;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_select_column_list_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<void, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
}
template<typename... Args>
auto dynamic_columns(Args... args)
-> _new_statement_t<::sqlpp::detail::make_select_column_list_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_columns must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), typename ::sqlpp::detail::make_select_column_list_t<_database_t, Args...>::_data_t{std::tuple_cat(::sqlpp::detail::as_tuple<Args>::_(args)...)} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Columns>
struct serializer_t<Context, select_column_list_data_t<Database, Columns...>>
{
using T = select_column_list_data_t<Database, Columns...>;
static Context& _(const T& t, Context& context)
{
interpret_tuple(t._columns, ',', context);
if (sizeof...(Columns) and not t._dynamic_columns.empty())
context << ',';
serialize(t._dynamic_columns, context);
return context;
}
};
}
#endif

View File

@ -0,0 +1,215 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SELECT_FLAG_LIST_H
#define SQLPP_SELECT_FLAG_LIST_H
#include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/no_data.h>
#include <sqlpp11/select_flags.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
{
// SELECTED FLAGS DATA
template<typename Database, typename... Flags>
struct select_flag_list_data_t
{
select_flag_list_data_t(Flags... flags):
_flags(flags...)
{}
select_flag_list_data_t(const select_flag_list_data_t&) = default;
select_flag_list_data_t(select_flag_list_data_t&&) = default;
select_flag_list_data_t& operator=(const select_flag_list_data_t&) = default;
select_flag_list_data_t& operator=(select_flag_list_data_t&&) = default;
~select_flag_list_data_t() = default;
std::tuple<Flags...> _flags;
interpretable_list_t<Database> _dynamic_flags;
};
// SELECT FLAGS
template<typename Database, typename... Flags>
struct select_flag_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::select_flag_list>;
using _recursive_traits = make_recursive_traits<Flags...>;
using _is_dynamic = is_database<Database>;
static_assert(not ::sqlpp::detail::has_duplicates<Flags...>::value, "at least one duplicate argument detected in select flag list");
static_assert(::sqlpp::detail::all_t<is_select_flag_t<Flags>::value...>::value, "at least one argument is not a select flag in select flag list");
// Data
using _data_t = select_flag_list_data_t<Database, Flags...>;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
template<typename Flag>
void add_ntc(Flag flag)
{
add<Flag, std::false_type>(flag);
}
template<typename Flag, typename TableCheckRequired = std::true_type>
void add(Flag flag)
{
static_assert(_is_dynamic::value, "select_flags::add() must not be called for static select flags");
static_assert(is_select_flag_t<Flag>::value, "invalid select flag argument in select_flags::add()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Flag>::value, "flag uses tables unknown to this statement in select_flags::add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_select_flag_t<Flag>::value>;
_add_impl(flag, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Flag>
void _add_impl(Flag flag, const std::true_type&)
{
return _data._dynamic_flags.emplace_back(flag);
}
template<typename Flag>
void _add_impl(Flag flag, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = select_flag_list_data_t<Database, Flags...>;
_impl_t<Policies> select_flags;
_impl_t<Policies>& operator()() { return select_flags; }
const _impl_t<Policies>& operator()() const { return select_flags; }
template<typename T>
static auto _get_member(T t) -> decltype(t.select_flags)
{
return t.select_flags;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
struct no_select_flag_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_select_flags;
_impl_t<Policies>& operator()() { return no_select_flags; }
const _impl_t<Policies>& operator()() const { return no_select_flags; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_select_flags)
{
return t.no_select_flags;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_select_flag_list_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto flags(Args... args)
-> _new_statement_t<select_flag_list_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_data_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_flags(Args... args)
-> _new_statement_t<select_flag_list_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_flags must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), select_flag_list_data_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Flags>
struct serializer_t<Context, select_flag_list_data_t<Database, Flags...>>
{
using T = select_flag_list_data_t<Database, Flags...>;
static Context& _(const T& t, Context& context)
{
interpret_tuple(t._flags, ' ', context);
if (sizeof...(Flags))
context << ' ';
interpret_list(t._dynamic_flags, ',', context);
if (not t._dynamic_flags.empty())
context << ' ';
return context;
}
};
}
#endif

View File

@ -29,7 +29,7 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
#include <sqlpp11/vendor/interpret_tuple.h> #include <sqlpp11/interpret_tuple.h>
#include <tuple> #include <tuple>
namespace sqlpp namespace sqlpp
@ -37,72 +37,54 @@ namespace sqlpp
// standard select flags // standard select flags
struct all_t struct all_t
{ {
struct _value_type using _traits = make_traits<no_value_t, tag::select_flag>;
{ using _recursive_traits = make_recursive_traits<>;
using _is_select_flag = std::true_type;
};
using _table_set = detail::type_set<>;
}; };
static constexpr all_t all = {}; static constexpr all_t all = {};
namespace vendor template<typename Context>
{ struct serializer_t<Context, all_t>
template<typename Context> {
struct serializer_t<Context, all_t> static Context& _(const all_t&, Context& context)
{ {
static Context& _(const all_t&, Context& context) context << "ALL";
{ return context;
context << "ALL"; }
return context; };
}
};
}
struct distinct_t struct distinct_t
{ {
struct _value_type using _traits = make_traits<no_value_t, tag::select_flag>;
{ using _recursive_traits = make_recursive_traits<>;
using _is_select_flag = std::true_type;
};
using _table_set = detail::type_set<>;
}; };
static constexpr distinct_t distinct = {}; static constexpr distinct_t distinct = {};
namespace vendor template<typename Context>
{ struct serializer_t<Context, distinct_t>
template<typename Context> {
struct serializer_t<Context, distinct_t> static Context& _(const distinct_t&, Context& context)
{ {
static Context& _(const distinct_t&, Context& context) context << "DISTINCT";
{ return context;
context << "DISTINCT"; }
return context; };
}
};
}
struct straight_join_t struct straight_join_t
{ {
struct _value_type using _traits = make_traits<no_value_t, tag::select_flag>;
{ using _recursive_traits = make_recursive_traits<>;
using _is_select_flag = std::true_type;
};
using _table_set = detail::type_set<>;
}; };
static constexpr straight_join_t straight_join = {}; static constexpr straight_join_t straight_join = {};
namespace vendor template<typename Context>
{ struct serializer_t<Context, straight_join_t>
template<typename Context> {
struct serializer_t<Context, straight_join_t> static Context& _(const straight_join_t&, Context& context)
{ {
static Context& _(const straight_join_t&, Context& context) context << "STRAIGHT_JOIN";
{ return context;
context << "STRAIGHT_JOIN"; }
return context; };
}
};
}
} }

View File

@ -32,28 +32,31 @@
namespace sqlpp namespace sqlpp
{ {
// provide type information for sub-selects that are used as named expressions or tables // provide type information for sub-selects that are used as named expressions or tables
template<typename Expr> template<typename ValueType, typename NameType>
struct select_column_spec_t struct select_column_spec_t
{ {
using _name_t = typename Expr::_name_t; using _traits = make_traits<ValueType>;
using _value_type = typename Expr::_value_type; using _recursive_traits = make_recursive_traits<>;
using _value_type = ValueType; // FIXME: column specs probably should use _traits, too
using _name_t = NameType;
struct _column_type struct _column_type
{ {
using _must_not_insert = std::true_type; using _must_not_insert = std::true_type;
using _must_not_update = std::true_type; using _must_not_update = std::true_type;
}; };
}; };
template< template<
typename Select, typename Select,
typename... NamedExpr typename... NamedExpr
> >
struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t< struct select_pseudo_table_t: public sqlpp::table_t<select_pseudo_table_t<
Select, Select,
NamedExpr...>, select_column_spec_t<NamedExpr>...> NamedExpr...>, select_column_spec_t<value_type_of<NamedExpr>, typename NamedExpr::_name_t>...>
{ {
using _value_type = no_value_t; using _traits = make_traits<no_value_t, tag::table, tag::pseudo_table>;
using _is_pseudo_table = std::true_type; using _recursive_traits = make_recursive_traits<>;
select_pseudo_table_t(Select select): select_pseudo_table_t(Select select):
_select(select) _select(select)
@ -69,21 +72,18 @@ namespace sqlpp
Select _select; Select _select;
}; };
namespace vendor template<typename Context, typename Select, typename... NamedExpr>
{ struct serializer_t<Context, select_pseudo_table_t<Select, NamedExpr...>>
template<typename Context, typename Select, typename... NamedExpr> {
struct serializer_t<Context, select_pseudo_table_t<Select, NamedExpr...>> using T = select_pseudo_table_t<Select, NamedExpr...>;
static Context& _(const T& t, Context& context)
{ {
using T = select_pseudo_table_t<Select, NamedExpr...>; serialize(t._select, context);
return context;
}
};
static Context& _(const T& t, Context& context)
{
serialize(t._select, context);
return context;
}
};
}
} }
#endif #endif

View File

@ -27,28 +27,25 @@
#ifndef SQLPP_SERIALIZE_H #ifndef SQLPP_SERIALIZE_H
#define SQLPP_SERIALIZE_H #define SQLPP_SERIALIZE_H
#include <sqlpp11/vendor/serializer.h> #include <sqlpp11/serializer.h>
namespace sqlpp namespace sqlpp
{ {
template<typename T, typename Context> template<typename T, typename Context>
auto serialize(const T& t, Context& context) auto serialize(const T& t, Context& context)
-> decltype(vendor::serializer_t<Context, T>::_(t, context)) -> decltype(serializer_t<Context, T>::_(t, context))
{ {
return vendor::serializer_t<Context, T>::_(t, context); return 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)
template<typename T, typename Context> -> decltype(serializer_t<Context, T>::_(t, context))
auto serialize(const T& t, Context& context) {
-> decltype(vendor::serializer_t<Context, T>::_(t, context)) return serializer_t<Context, T>::_(t, context);
{ }
return vendor::serializer_t<Context, T>::_(t, context); */
}
}
*/
} }

View File

@ -24,24 +24,21 @@
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#ifndef SQLPP_VENDOR_SERIALIZER_H #ifndef SQLPP_SERIALIZER_H
#define SQLPP_VENDOR_SERIALIZER_H #define SQLPP_SERIALIZER_H
#include <sqlpp11/vendor/wrong.h> #include <sqlpp11/wrong.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Context, typename T, typename Enable = void>
{ struct serializer_t
template<typename Context, typename T, typename Enable = void> {
struct serializer_t static void _(const T& t, Context& context)
{ {
static void _(const T& t, Context& context) static_assert(wrong_t<Context, T>::value, "missing serializer specialization");
{ }
static_assert(wrong_t<Context, T>::value, "missing serializer specialization"); };
}
};
}
} }

View File

@ -27,36 +27,37 @@
#ifndef SQLPP_SIMPLE_COLUMN_H #ifndef SQLPP_SIMPLE_COLUMN_H
#define SQLPP_SIMPLE_COLUMN_H #define SQLPP_SIMPLE_COLUMN_H
#include <sqlpp11/vendor/serializer.h> #include <sqlpp11/serializer.h>
#include <sqlpp11/type_traits.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Column>
{ struct simple_column_t
template<typename Column> {
struct simple_column_t Column _column;
{
Column _column;
};
template<typename Context, typename Column> using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
struct serializer_t<Context, simple_column_t<Column>> using _recursive_traits = make_recursive_traits<>;
{ };
using T = simple_column_t<Column>;
static Context& _(const T& t, Context& context) template<typename Context, typename Column>
{ struct serializer_t<Context, simple_column_t<Column>>
context << t._column._get_name(); {
return context; using T = simple_column_t<Column>;
}
};
template<typename Column> static Context& _(const T& t, Context& context)
simple_column_t<Column> simple_column(Column c)
{ {
return {c}; context << t._column._get_name();
return context;
} }
} };
template<typename Column>
simple_column_t<Column> simple_column(Column c)
{
return {c};
}
} }
#endif #endif

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_SINGLE_TABLE_H
#define SQLPP_SINGLE_TABLE_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/no_value.h>
#include <sqlpp11/no_data.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/prepared_insert.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
// A SINGLE TABLE DATA
template<typename Database, typename Table>
struct single_table_data_t
{
single_table_data_t(Table table):
_table(table)
{}
single_table_data_t(const single_table_data_t&) = default;
single_table_data_t(single_table_data_t&&) = default;
single_table_data_t& operator=(const single_table_data_t&) = default;
single_table_data_t& operator=(single_table_data_t&&) = default;
~single_table_data_t() = default;
Table _table;
};
// A SINGLE TABLE
template<typename Database, typename Table>
struct single_table_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::single_table>;
using _recursive_traits = make_recursive_traits<Table>;
static_assert(is_table_t<Table>::value, "argument has to be a table");
static_assert(required_tables_of<Table>::size::value == 0, "table depends on another table");
using _data_t = single_table_data_t<Database, Table>;
struct _name_t {};
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = single_table_data_t<Database, Table>;
_impl_t<Policies> from;
_impl_t<Policies>& operator()() { return from; }
const _impl_t<Policies>& operator()() const { return from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.from)
{
return t.from;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO INTO YET
struct no_single_table_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_from;
_impl_t<Policies>& operator()() { return no_from; }
const _impl_t<Policies>& operator()() const { return no_from; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_from)
{
return t.no_from;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_single_table_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto from(Args... args)
-> _new_statement_t<single_table_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), single_table_data_t<void, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename Table>
struct serializer_t<Context, single_table_data_t<Database, Table>>
{
using T = single_table_data_t<Database, Table>;
static Context& _(const T& t, Context& context)
{
serialize(t._table, context);
return context;
}
};
}
#endif

View File

@ -32,16 +32,11 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Select>
{
template<typename Select>
struct some_t struct some_t
{ {
struct _value_type: public Select::_value_type::_base_value_type using _traits = make_traits<value_type_of<Select>, ::sqlpp::tag::multi_expression>;
{ using _recursive_traits = make_recursive_traits<Select>;
using _is_expression = std::false_type;
using _is_multi_expression = std::true_type; // must not be named or used with +,-,*,/, etc
};
struct _name_t struct _name_t
{ {
@ -54,7 +49,6 @@ namespace sqlpp
const T& operator()() const { return some; } const T& operator()() const { return some; }
}; };
}; };
using _table_set = typename Select::_table_set;
some_t(Select select): some_t(Select select):
_select(select) _select(select)
@ -68,30 +62,26 @@ namespace sqlpp
Select _select; Select _select;
}; };
}
namespace vendor template<typename Context, typename Select>
{ struct serializer_t<Context, some_t<Select>>
template<typename Context, typename Select> {
struct serializer_t<Context, vendor::some_t<Select>> using T = some_t<Select>;
static Context& _(const T& t, Context& context)
{ {
using T = vendor::some_t<Select>; context << "SOME(";
serialize(t._select, context);
static Context& _(const T& t, Context& context) context << ")";
{ return context;
context << "SOME("; }
serialize(t._select, context); };
context << ")";
return context;
}
};
}
template<typename T> template<typename T>
auto some(T t) -> typename vendor::some_t<vendor::wrap_operand_t<T>> auto some(T t) -> some_t<wrap_operand_t<T>>
{ {
static_assert(is_select_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument"); static_assert(is_select_t<wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
static_assert(is_value_t<vendor::wrap_operand_t<T>>::value, "some() requires a single column select expression as argument"); static_assert(is_expression_t<wrap_operand_t<T>>::value, "some() requires a single column select expression as argument");
return { t }; return { t };
} }

View File

@ -28,6 +28,7 @@
#define SQLPP_SORT_ORDER_H #define SQLPP_SORT_ORDER_H
#include <sqlpp11/detail/type_set.h> #include <sqlpp11/detail/type_set.h>
#include <sqlpp11/no_value.h>
namespace sqlpp namespace sqlpp
{ {
@ -40,36 +41,33 @@ namespace sqlpp
template<typename Expression, sort_type SortType> template<typename Expression, sort_type SortType>
struct sort_order_t struct sort_order_t
{ {
using _is_sort_order = std::true_type; using _traits = make_traits<no_value_t, tag::sort_order, sqlpp::tag::expression>;
using _table_set = typename Expression::_table_set; using _recursive_traits = make_recursive_traits<Expression>;
Expression _expression; Expression _expression;
}; };
namespace vendor template<typename Context, typename Expression, sort_type SortType>
{ struct serializer_t<Context, sort_order_t<Expression, SortType>>
template<typename Context, typename Expression, sort_type SortType> {
struct serializer_t<Context, sort_order_t<Expression, SortType>> using T = sort_order_t<Expression, SortType>;
static Context& _(const T& t, Context& context)
{ {
using T = sort_order_t<Expression, SortType>; serialize(t._expression, context);
switch(SortType)
static Context& _(const T& t, Context& context)
{ {
serialize(t._expression, context); case sort_type::asc:
switch(SortType) context << " ASC";
{ break;
case sort_type::asc: default:
context << " ASC"; context << " DESC";
break; break;
default:
context << " DESC";
break;
}
return context;
} }
}; return context;
}
};
}
} }
#endif #endif

237
include/sqlpp11/statement.h Normal file
View File

@ -0,0 +1,237 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_STATEMENT_H
#define SQLPP_STATEMENT_H
#include <sqlpp11/result.h>
#include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_select.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/noop.h>
#include <sqlpp11/policy_update.h>
#include <sqlpp11/serializer.h>
#include <sqlpp11/detail/get_last.h>
#include <sqlpp11/detail/pick_arg.h>
namespace sqlpp
{
template<typename Db, typename... Policies>
struct statement_t;
namespace detail
{
template<typename Db = void, typename... Policies>
struct statement_policies_t
{
using _database_t = Db;
using _statement_t = statement_t<Db, Policies...>;
template<typename Needle, typename Replacement>
struct _policies_update_t
{
static_assert(detail::is_element_of<Needle, make_type_set_t<Policies...>>::value, "policies update for non-policy class detected");
using type = statement_t<Db, policy_update_t<Policies, Needle, Replacement>...>;
};
template<typename Needle, typename Replacement>
using _new_statement_t = typename _policies_update_t<Needle, Replacement>::type;
using _all_required_tables = detail::make_joined_set_t<required_tables_of<Policies>...>;
using _all_provided_tables = detail::make_joined_set_t<provided_tables_of<Policies>...>;
using _all_extra_tables = detail::make_joined_set_t<extra_tables_of<Policies>...>;
using _known_tables = detail::make_joined_set_t<_all_provided_tables, _all_extra_tables>;
template<typename Expression>
using _no_unknown_tables = detail::is_subset_of<required_tables_of<Expression>, _known_tables>;
// The tables not covered by the from.
using _required_tables = detail::make_difference_set_t<
_all_required_tables,
_all_provided_tables // Hint: extra_tables are not used here because they are just a helper for dynamic .add_*()
>;
using _result_type_provider = detail::get_last_if<is_return_value_t, noop, Policies...>;
struct _result_methods_t: public _result_type_provider::template _result_methods_t<statement_policies_t>
{};
// A select can be used as a pseudo table if
// - at least one column is selected
// - the select is complete (leaks no tables)
using _can_be_used_as_table = typename std::conditional<
is_select_column_list_t<_result_type_provider>::value and _required_tables::size::value == 0,
std::true_type,
std::false_type
>::type;
using _value_type = typename std::conditional<
detail::none_t<is_missing_t<Policies>::value...>::value,
value_type_of<_result_type_provider>,
no_value_t // if a required statement part is missing (e.g. columns in a select), then the statement cannot be used as a value
>::type;
using _is_expression = typename std::conditional<
std::is_same<_value_type, no_value_t>::value,
std::false_type,
std::true_type>::type;
using _traits = make_traits<_value_type>;
struct _recursive_traits
{
using _required_tables = statement_policies_t::_required_tables;
using _provided_tables = detail::type_set<>;
using _extra_tables = detail::type_set<>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Policies>...>;
};
};
}
template<typename Db,
typename... Policies
>
struct statement_t:
public Policies::template _member_t<detail::statement_policies_t<Db, Policies...>>...,
public detail::statement_policies_t<Db, Policies...>::_value_type::template expression_operators<statement_t<Db, Policies...>>,
public detail::statement_policies_t<Db, Policies...>::_result_methods_t,
public Policies::template _methods_t<detail::statement_policies_t<Db, Policies...>>...
{
using _policies_t = typename detail::statement_policies_t<Db, Policies...>;
using _traits = make_traits<value_type_of<_policies_t>, ::sqlpp::tag::select, tag::expression_if<typename _policies_t::_is_expression>, tag::named_expression_if<typename _policies_t::_is_expression>>;
using _recursive_traits = typename _policies_t::_recursive_traits;
using _result_type_provider = typename _policies_t::_result_type_provider;
using _requires_braces = std::true_type;
using _name_t = typename _result_type_provider::_name_t;
// Constructors
statement_t()
{}
template<typename Statement, typename Term>
statement_t(Statement statement, Term term):
Policies::template _member_t<_policies_t>{
typename Policies::template _impl_t<_policies_t>{
detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)
}}...
//Policies::template _member_t<_policies_t>{{detail::pick_arg<typename Policies::template _member_t<_policies_t>>(statement, term)}}...
{}
statement_t(const statement_t& r) = default;
statement_t(statement_t&& r) = default;
statement_t& operator=(const statement_t& r) = default;
statement_t& operator=(statement_t&& r) = default;
~statement_t() = default;
static constexpr size_t _get_static_no_of_parameters()
{
return std::tuple_size<parameters_of<statement_t>>::value;
}
size_t _get_no_of_parameters() const
{
return _get_static_no_of_parameters();
}
static void _check_consistency()
{
static_assert(not required_tables_of<_policies_t>::size::value, "one sub expression requires tables which are otherwise not known in the statement");
using swallow = int[];
(void) swallow{(Policies::template _methods_t<detail::statement_policies_t<Db, Policies...>>::_check_consistency(), 0)...};
}
};
template<typename Context, typename Database, typename... Policies>
struct serializer_t<Context, statement_t<Database, Policies...>>
{
using T = statement_t<Database, Policies...>;
using P = ::sqlpp::detail::statement_policies_t<Database, Policies...>;
static Context& _(const T& t, Context& context)
{
using swallow = int[];
(void) swallow{(serialize(static_cast<const typename Policies::template _member_t<P>&>(t)()._data, context), 0)...};
return context;
}
};
template<typename NameData>
struct statement_name_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::noop>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = NameData;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = NameData;
_impl_t<Policies> statement_name;
_impl_t<Policies>& operator()() { return statement_name; }
const _impl_t<Policies>& operator()() const { return statement_name; }
template<typename T>
static auto _get_member(T t) -> decltype(t.statement_name)
{
return t.statement_name;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
}
#endif

View File

@ -31,78 +31,71 @@
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename Flag, typename Expr>
struct sum_t: public value_type_of<Expr>::template expression_operators<sum_t<Flag, Expr>>,
public alias_operators<sum_t<Flag, Expr>>
{ {
template<typename Flag, typename Expr> using _traits = make_traits<value_type_of<Expr>, ::sqlpp::tag::expression, ::sqlpp::tag::named_expression>;
struct sum_t: public Expr::_value_type::template expression_operators<sum_t<Flag, Expr>> using _recursive_traits = make_recursive_traits<Expr>;
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'");
static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument");
struct _name_t
{ {
static_assert(is_noop<Flag>::value or std::is_same<sqlpp::distinct_t, Flag>::value, "sum() used with flag other than 'distinct'"); static constexpr const char* _get_name() { return "SUM"; }
static_assert(is_numeric_t<Expr>::value, "sum() requires a numeric expression as argument"); template<typename T>
struct _member_t
struct _value_type: public Expr::_value_type::_base_value_type
{
using _is_named_expression = std::true_type;
};
struct _name_t
{
static constexpr const char* _get_name() { return "SUM"; }
template<typename T>
struct _member_t
{
T sum;
T& operator()() { return sum; }
const T& operator()() const { return sum; }
};
};
sum_t(Expr expr):
_expr(expr)
{}
sum_t(const sum_t&) = default;
sum_t(sum_t&&) = default;
sum_t& operator=(const sum_t&) = default;
sum_t& operator=(sum_t&&) = default;
~sum_t() = default;
Expr _expr;
};
}
namespace vendor
{
template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, vendor::sum_t<Flag, Expr>>
{
using T = vendor::sum_t<Flag, Expr>;
static Context& _(const T& t, Context& context)
{ {
context << "SUM("; T sum;
if (std::is_same<sqlpp::distinct_t, Flag>::value) T& operator()() { return sum; }
{ const T& operator()() const { return sum; }
serialize(Flag(), context); };
context << ' '; };
}
serialize(t._expr, context); sum_t(Expr expr):
context << ")"; _expr(expr)
return context; {}
sum_t(const sum_t&) = default;
sum_t(sum_t&&) = default;
sum_t& operator=(const sum_t&) = default;
sum_t& operator=(sum_t&&) = default;
~sum_t() = default;
Expr _expr;
};
template<typename Context, typename Flag, typename Expr>
struct serializer_t<Context, sum_t<Flag, Expr>>
{
using T = sum_t<Flag, Expr>;
static Context& _(const T& t, Context& context)
{
context << "SUM(";
if (std::is_same<sqlpp::distinct_t, Flag>::value)
{
serialize(Flag(), context);
context << ' ';
} }
}; serialize(t._expr, context);
} context << ")";
return context;
}
};
template<typename T> template<typename T>
auto sum(T t) -> typename vendor::sum_t<vendor::noop, vendor::wrap_operand_t<T>> auto sum(T t) -> sum_t<noop, wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t }; return { t };
} }
template<typename T> template<typename T>
auto sum(const sqlpp::distinct_t&, T t) -> typename vendor::sum_t<sqlpp::distinct_t, vendor::wrap_operand_t<T>> auto sum(const sqlpp::distinct_t&, T t) -> sum_t<sqlpp::distinct_t, wrap_operand_t<T>>
{ {
static_assert(is_numeric_t<vendor::wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument"); static_assert(is_numeric_t<wrap_operand_t<T>>::value, "sum() requires a numeric expression as argument");
return { t }; return { t };
} }

View File

@ -40,16 +40,24 @@ namespace sqlpp
struct table_base_t {}; struct table_base_t {};
template<typename Table, typename... ColumnSpec> template<typename Table, typename... ColumnSpec>
struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>... struct table_t: public table_base_t, public ColumnSpec::_name_t::template _member_t<column_t<Table, ColumnSpec>>...
{ {
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) using _traits = make_traits<no_value_t, tag::table>;
struct _recursive_traits
{
using _parameters = std::tuple<>;
using _required_tables = detail::type_set<>;
using _provided_tables = detail::type_set<Table>;
using _extra_tables = detail::type_set<>;
};
static_assert(sizeof...(ColumnSpec), "at least one column required per table"); static_assert(sizeof...(ColumnSpec), "at least one column required per table");
using _required_insert_columns = typename detail::make_type_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>...>; using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
template<typename AliasProvider> template<typename AliasProvider>
using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>; using _alias_t = table_alias_t<AliasProvider, Table, ColumnSpec...>;
using _is_table = std::true_type;
template<typename T> template<typename T>
join_t<inner_join_t, Table, T> join(T t) join_t<inner_join_t, Table, T> join(T t)
@ -93,22 +101,19 @@ namespace sqlpp
} }
}; };
namespace vendor template<typename Context, typename X>
{ struct serializer_t<Context, X, typename std::enable_if<std::is_base_of<table_base_t, X>::value and not is_pseudo_table_t<X>::value, void>::type>
template<typename Context, typename X> {
struct serializer_t<Context, X, typename std::enable_if<std::is_base_of<table_base_t, X>::value and not is_pseudo_table_t<X>::value, void>::type> using T = X;
static Context& _(const T& t, Context& context)
{ {
using T = X; context << T::_name_t::_get_name();
return context;
static Context& _(const T& t, Context& context) }
{ };
context << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -35,22 +35,22 @@
namespace sqlpp namespace sqlpp
{ {
struct table_alias_base_t {};
template<typename AliasProvider, typename Table, typename... ColumnSpec> template<typename AliasProvider, typename Table, typename... ColumnSpec>
struct table_alias_t: public table_alias_base_t, public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>... struct table_alias_t: public ColumnSpec::_name_t::template _member_t<column_t<AliasProvider, ColumnSpec>>...
{ {
//FIXME: Need to add join functionality //FIXME: Need to add join functionality
using _is_table = std::true_type; using _traits = make_traits<value_type_of<Table>, tag::table, tag::alias, tag::named_expression_if<is_expression_t<Table>>>;
using _table_set = detail::type_set<AliasProvider>;
struct _value_type: Table::_value_type struct _recursive_traits
{ {
using _is_expression = std::false_type; using _parameters = std::tuple<>;
using _is_named_expression = copy_type_trait<Table, is_value_t>; using _required_tables = detail::type_set<>;
using _is_alias = std::true_type; using _provided_tables = detail::type_set<AliasProvider>;
using _extra_tables = detail::type_set<>;
}; };
static_assert(required_tables_of<Table>::size::value == 0, "table aliases must not depend on external tables");
using _name_t = typename AliasProvider::_name_t; using _name_t = typename AliasProvider::_name_t;
using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>; using _column_tuple_t = std::tuple<column_t<Table, ColumnSpec>...>;
@ -61,23 +61,20 @@ namespace sqlpp
Table _table; Table _table;
}; };
namespace vendor template<typename Context, typename AliasProvider, typename Table, typename... ColumnSpec>
{ struct serializer_t<Context, table_alias_t<AliasProvider, Table, ColumnSpec...>>
template<typename Context, typename X> {
struct serializer_t<Context, X, typename std::enable_if<std::is_base_of<table_alias_base_t, X>::value, void>::type> using T = table_alias_t<AliasProvider, Table, ColumnSpec...>;
static Context& _(const T& t, Context& context)
{ {
using T = X; context << "(";
serialize(t._table, context);
context << ") AS " << T::_name_t::_get_name();
return context;
}
};
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._table, context);
context << ") AS " << T::_name_t::_get_name();
return context;
}
};
}
} }
#endif #endif

View File

@ -31,8 +31,8 @@
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
#include <sqlpp11/vendor/concat.h> #include <sqlpp11/concat.h>
#include <sqlpp11/vendor/like.h> #include <sqlpp11/like.h>
namespace sqlpp namespace sqlpp
{ {
@ -41,11 +41,7 @@ namespace sqlpp
// text value type // text value type
struct text struct text
{ {
using _value_type = text; using _tag = ::sqlpp::tag::text;
using _base_value_type = text;
using _is_text = std::true_type;
using _is_value = std::true_type;
using _is_expression = std::true_type;
using _cpp_value_type = std::string; using _cpp_value_type = std::string;
struct _parameter_t struct _parameter_t
@ -55,12 +51,12 @@ namespace sqlpp
_parameter_t(): _parameter_t():
_value(""), _value(""),
_is_null(true) _is_null(true)
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(false) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
@ -77,7 +73,7 @@ namespace sqlpp
} }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
} }
@ -100,111 +96,98 @@ namespace sqlpp
}; };
template<typename Db, bool NullIsTrivial = false> template<typename Db, bool NullIsTrivial = false>
struct _result_entry_t struct _result_entry_t
{ {
_result_entry_t(): _result_entry_t():
_is_valid(false), _is_valid(false),
_value_ptr(nullptr), _value_ptr(nullptr),
_len(0) _len(0)
{} {}
_result_entry_t(char* data, size_t len): void _validate()
_is_valid(true),
_value_ptr(data),
_len(_value_ptr ? 0 : len)
{}
void assign(const char* data, size_t len)
{
_is_valid = true;
_value_ptr = data;
_len = _value_ptr ? len: 0;
}
void validate()
{
_is_valid = true;
}
void invalidate()
{
_is_valid = false;
_value_ptr = nullptr;
_len = 0;
}
bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; }
bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); }
bool is_null() const
{
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
{
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); _is_valid = true;
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 "";
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_text_result(i, &_value_ptr, &_len);
} }
private: void _invalidate()
bool _is_valid; {
const char* _value_ptr; _is_valid = false;
size_t _len; _value_ptr = nullptr;
}; _len = 0;
}
bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; }
bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); }
bool is_null() const
{
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
{
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 "";
}
operator _cpp_value_type() const { return value(); }
template<typename Target>
void _bind(Target& target, size_t i)
{
target._bind_text_result(i, &_value_ptr, &_len);
}
private:
bool _is_valid;
const char* _value_ptr;
size_t _len;
};
template<typename T> template<typename T>
struct _is_valid_operand struct _is_valid_operand
{ {
static constexpr bool value = static constexpr bool value =
is_expression_t<T>::value // expressions are OK is_expression_t<T>::value // expressions are OK
and is_text_t<T>::value // the correct value type is required, of course and is_text_t<T>::value // the correct value type is required, of course
; ;
}; };
template<typename Base> template<typename Base>
struct expression_operators: public basic_expression_operators<Base, is_text_t> struct expression_operators: public basic_expression_operators<Base, is_text_t>
{ {
template<typename T> template<typename T>
vendor::concat_t<Base, vendor::wrap_operand_t<T>> operator+(T t) const concat_t<Base, wrap_operand_t<T>> operator+(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
} }
template<typename T> template<typename T>
vendor::like_t<Base, vendor::wrap_operand_t<T>> like(T t) const like_t<Base, wrap_operand_t<T>> like(T t) const
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()"); static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()");
return { *static_cast<const Base*>(this), {t} }; return { *static_cast<const Base*>(this), {t} };
@ -213,23 +196,23 @@ namespace sqlpp
template<typename Base> template<typename Base>
struct column_operators struct column_operators
{ {
template<typename T> template<typename T>
auto operator +=(T t) const -> vendor::assignment_t<Base, vendor::concat_t<Base, vendor::wrap_operand_t<T>>> auto operator +=(T t) const -> assignment_t<Base, concat_t<Base, wrap_operand_t<T>>>
{ {
using rhs = vendor::wrap_operand_t<T>; using rhs = wrap_operand_t<T>;
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand"); static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } }; return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
} }
}; };
}; };
template<typename Db, bool TrivialIsNull> template<typename Db, bool TrivialIsNull>
inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t<Db, TrivialIsNull>& e) inline std::ostream& operator<<(std::ostream& os, const text::_result_entry_t<Db, TrivialIsNull>& e)
{ {
return os << e.value(); return os << e.value();
} }
} }
using text = detail::text; using text = detail::text;

View File

@ -35,56 +35,56 @@ namespace sqlpp
static constexpr bool report_auto_rollback = true; static constexpr bool report_auto_rollback = true;
template<typename Db> template<typename Db>
class transaction_t class transaction_t
{
Db& _db;
const bool _report_unfinished_transaction;
bool _finished = false;
public:
transaction_t(Db& db, bool report_unfinished_transaction):
_db(db),
_report_unfinished_transaction(report_unfinished_transaction)
{ {
_db.start_transaction(); Db& _db;
} const bool _report_unfinished_transaction;
bool _finished = false;
transaction_t(const transaction_t&) = delete; public:
transaction_t(transaction_t&&) = default; transaction_t(Db& db, bool report_unfinished_transaction):
transaction_t& operator=(const transaction_t&) = delete; _db(db),
transaction_t& operator=(transaction_t&&) = delete; _report_unfinished_transaction(report_unfinished_transaction)
~transaction_t()
{
if (not _finished)
{ {
try _db.start_transaction();
}
transaction_t(const transaction_t&) = delete;
transaction_t(transaction_t&&) = default;
transaction_t& operator=(const transaction_t&) = delete;
transaction_t& operator=(transaction_t&&) = delete;
~transaction_t()
{
if (not _finished)
{ {
_db.rollback_transaction(_report_unfinished_transaction); try
} {
catch(const std::exception& e) _db.rollback_transaction(_report_unfinished_transaction);
{ }
_db.report_rollback_failure(std::string("auto rollback failed: ") + e.what()); catch(const std::exception& e)
} {
catch(...) _db.report_rollback_failure(std::string("auto rollback failed: ") + e.what());
{ }
_db.report_rollback_failure("auto rollback failed with unknown exception"); catch(...)
{
_db.report_rollback_failure("auto rollback failed with unknown exception");
}
} }
} }
}
void commit() void commit()
{ {
_finished = true; _finished = true;
_db.commit_transaction(); _db.commit_transaction();
} }
void rollback() void rollback()
{ {
_finished = true; _finished = true;
_db.rollback_transaction(false); _db.rollback_transaction(false);
} }
}; };
template<typename Db> template<typename Db>
transaction_t<Db> start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback) transaction_t<Db> start_transaction(Db& db, bool report_unfinished_transaction = report_auto_rollback)

View File

@ -31,16 +31,18 @@
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/serialize.h> #include <sqlpp11/serialize.h>
#include <sqlpp11/vendor/serializer.h> #include <sqlpp11/serializer.h>
#include <sqlpp11/wrap_operand.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Operand> template<typename Operand>
struct tvin_t struct tvin_t
{ {
using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
using _operand_t = Operand; using _operand_t = Operand;
using _value_type = typename _operand_t::_value_type;
using _table_set = typename _operand_t::_table_set;
tvin_t(Operand operand): tvin_t(Operand operand):
_value(operand) _value(operand)
@ -56,34 +58,33 @@ namespace sqlpp
return _value._is_trivial(); return _value._is_trivial();
} }
_operand_t _value; Operand _value;
}; };
namespace vendor template<typename Context, typename Operand>
{ struct serializer_t<Context, tvin_t<Operand>>
template<typename Context, typename Operand> {
struct serializer_t<Context, tvin_t<Operand>> using T = tvin_t<Operand>;
static void _(const T& t, Context& context)
{ {
using T = tvin_t<Operand>; static_assert(wrong_t<T>::value, "tvin() must not be used with anything but =, ==, != and !");
}
};
static void _(const T& t, Context& context) template<typename Operand>
{
static_assert(vendor::wrong_t<T>::value, "tvin() must not be used with anything but =, ==, != and !");
}
};
}
template<typename T>
struct maybe_tvin_t struct maybe_tvin_t
{ {
using _table_set = typename T::_table_set; using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
static constexpr bool _is_trivial() static constexpr bool _is_trivial()
{ {
return false; return false;
} }
maybe_tvin_t(T t): maybe_tvin_t(Operand operand):
_value(t) _value(operand)
{} {}
maybe_tvin_t(const maybe_tvin_t&) = default; maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default; maybe_tvin_t(maybe_tvin_t&&) = default;
@ -91,20 +92,22 @@ namespace sqlpp
maybe_tvin_t& operator=(maybe_tvin_t&&) = default; maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default; ~maybe_tvin_t() = default;
T _value; Operand _value;
}; };
template<typename T> template<typename Operand>
struct maybe_tvin_t<tvin_t<T>> struct maybe_tvin_t<tvin_t<Operand>>
{ {
using _table_set = typename T::_table_set; using _traits = make_traits<value_type_of<Operand>, tag::expression>;
using _recursive_traits = make_recursive_traits<Operand>;
bool _is_trivial() const bool _is_trivial() const
{ {
return _value._is_trivial(); return _value._is_trivial();
}; };
maybe_tvin_t(tvin_t<T> t): maybe_tvin_t(tvin_t<Operand> operand):
_value(t._value) _value(operand._value)
{} {}
maybe_tvin_t(const maybe_tvin_t&) = default; maybe_tvin_t(const maybe_tvin_t&) = default;
maybe_tvin_t(maybe_tvin_t&&) = default; maybe_tvin_t(maybe_tvin_t&&) = default;
@ -112,38 +115,35 @@ namespace sqlpp
maybe_tvin_t& operator=(maybe_tvin_t&&) = default; maybe_tvin_t& operator=(maybe_tvin_t&&) = default;
~maybe_tvin_t() = default; ~maybe_tvin_t() = default;
typename tvin_t<T>::_operand_t _value; typename tvin_t<Operand>::_operand_t _value;
}; };
namespace vendor template<typename Context, typename Operand>
{ struct serializer_t<Context, maybe_tvin_t<Operand>>
template<typename Context, typename Operand>
struct serializer_t<Context, maybe_tvin_t<Operand>>
{
using T = maybe_tvin_t<Operand>;
static Context& _(const T& t, Context& context)
{
if (t._is_trivial())
{
context << "NULL";
}
else
{
serialize(t._value, context);
}
return context;
}
};
}
template<typename T>
auto tvin(T t) -> tvin_t<typename vendor::wrap_operand<T>::type>
{ {
using _operand_t = typename vendor::wrap_operand<T>::type; using T = maybe_tvin_t<Operand>;
static_assert(std::is_same<_operand_t, vendor::text_operand>::value
or not std::is_same<_operand_t, T>::value, "tvin() used with invalid type (only string and primitive types allowed)"); static Context& _(const T& t, Context& context)
return {{t}}; {
if (t._is_trivial())
{
context << "NULL";
}
else
{
serialize(t._value, context);
}
return context;
}
};
template<typename Operand>
auto tvin(Operand operand) -> tvin_t<typename wrap_operand<Operand>::type>
{
using _operand_t = typename wrap_operand<Operand>::type;
static_assert(std::is_same<_operand_t, text_operand>::value
or not std::is_same<_operand_t, Operand>::value, "tvin() used with invalid type (only string and primitive types allowed)");
return {{operand}};
} }
} }

View File

@ -28,7 +28,7 @@
#define SQLPP_TYPE_TRAITS_H #define SQLPP_TYPE_TRAITS_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/vendor/wrap_operand.h> #include <sqlpp11/detail/type_set.h>
namespace sqlpp namespace sqlpp
{ {
@ -36,54 +36,71 @@ namespace sqlpp
namespace detail\ namespace detail\
{\ {\
template<typename T, typename Enable = void>\ template<typename T, typename Enable = void>\
struct is_##name##_impl: std::false_type {};\ struct is_##name##_impl: std::false_type {};\
template<typename T>\ template<typename T>\
struct is_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_value_type::_is_##name, std::true_type>::value>::type>: std::true_type {};\ struct is_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_value_type::_is_##name, std::true_type>::value>::type>: std::true_type {};\
}\ }\
namespace tag\
{\
struct name{};\
};\
template<typename T>\ template<typename T>\
struct is_##name##_t: detail::is_##name##_impl<T> {}; using is_##name##_t = detail::is_element_of<tag::name, typename T::_traits::_tags>;
#define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \ #define SQLPP_IS_COLUMN_TRAIT_GENERATOR(name) \
namespace detail\ namespace detail\
{\ {\
template<typename T, typename Enable = void>\ template<typename T, typename Enable = void>\
struct name##_impl { using type = std::false_type; };\ struct name##_impl { using type = std::false_type; };\
template<typename T>\ template<typename T>\
struct name##_impl<T, typename std::enable_if<std::is_same<typename T::_column_type::_##name, std::true_type>::value>::type> { using type = std::true_type; };\ struct name##_impl<T, typename std::enable_if<std::is_same<typename T::_column_type::_##name, std::true_type>::value>::type> { using type = std::true_type; };\
}\ }\
template<typename T>\ template<typename T>\
using name##_t = typename detail::name##_impl<T>::type; using name##_t = typename detail::name##_impl<T>::type;
#define SQLPP_TYPE_TRAIT_GENERATOR(name) \ #define SQLPP_TYPE_TRAIT_GENERATOR(name) \
namespace detail\ namespace detail\
{\ {\
template<typename T, typename Enable = void>\ template<typename T, typename Enable = void>\
struct name##_impl: std::false_type {};\ struct name##_impl: std::false_type {};\
template<typename T>\ template<typename T>\
struct name##_impl<T, typename std::enable_if<std::is_same<typename T::_##name, std::true_type>::value>::type>: std::true_type {};\ struct name##_impl<T, typename std::enable_if<std::is_same<typename T::_##name, std::true_type>::value>::type>: std::true_type {};\
}\ }\
template<typename T>\ template<typename T>\
struct name##_t: detail::name##_impl<T> {}; struct name##_t: detail::name##_impl<T> {};
#define SQLPP_CONNECTOR_TRAIT_GENERATOR(name) \ #define SQLPP_CONNECTOR_TRAIT_GENERATOR(name) \
namespace detail\ namespace detail\
{\ {\
template<typename T, typename Enable = void>\ template<typename T, typename Enable = void>\
struct connector_##name##_impl: std::false_type {};\ struct connector_##name##_impl: std::false_type {};\
template<typename T>\ template<typename T>\
struct connector_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_tags::_##name, std::true_type>::value>::type>: std::true_type {};\ struct connector_##name##_impl<T, typename std::enable_if<std::is_same<typename T::_tags::_##name, std::true_type>::value>::type>: std::true_type {};\
}\ }\
template<typename T>\ template<typename T>\
struct connector_##name##_t: detail::connector_##name##_impl<T> {}; struct connector_##name##_t: detail::connector_##name##_impl<T> {};
SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean); SQLPP_IS_VALUE_TRAIT_GENERATOR(boolean);
SQLPP_IS_VALUE_TRAIT_GENERATOR(numeric);
SQLPP_IS_VALUE_TRAIT_GENERATOR(integral); SQLPP_IS_VALUE_TRAIT_GENERATOR(integral);
SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point); SQLPP_IS_VALUE_TRAIT_GENERATOR(floating_point);
template<typename T>
using is_numeric_t = detail::any_t<
detail::is_element_of<tag::integral, typename T::_traits::_tags>::value,
detail::is_element_of<tag::floating_point, typename T::_traits::_tags>::value>;
SQLPP_IS_VALUE_TRAIT_GENERATOR(text); SQLPP_IS_VALUE_TRAIT_GENERATOR(text);
SQLPP_IS_VALUE_TRAIT_GENERATOR(value); SQLPP_IS_VALUE_TRAIT_GENERATOR(wrapped_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(expression);
SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(named_expression);
namespace tag
{
template<typename C>
using named_expression_if = typename std::conditional<C::value, tag::named_expression, void>::type;
}
namespace tag
{
template<typename C>
using expression_if = typename std::conditional<C::value, tag::expression, void>::type;
}
SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression); SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_expression);
SQLPP_IS_VALUE_TRAIT_GENERATOR(alias); SQLPP_IS_VALUE_TRAIT_GENERATOR(alias);
SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag);
@ -94,41 +111,130 @@ namespace sqlpp
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null); SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_TYPE_TRAIT_GENERATOR(is_noop); SQLPP_IS_VALUE_TRAIT_GENERATOR(noop);
SQLPP_TYPE_TRAIT_GENERATOR(is_table); SQLPP_IS_VALUE_TRAIT_GENERATOR(missing);
SQLPP_TYPE_TRAIT_GENERATOR(is_join); SQLPP_IS_VALUE_TRAIT_GENERATOR(return_value);
SQLPP_TYPE_TRAIT_GENERATOR(is_pseudo_table); SQLPP_IS_VALUE_TRAIT_GENERATOR(table);
SQLPP_TYPE_TRAIT_GENERATOR(is_column); SQLPP_IS_VALUE_TRAIT_GENERATOR(join);
SQLPP_TYPE_TRAIT_GENERATOR(is_select); SQLPP_IS_VALUE_TRAIT_GENERATOR(pseudo_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_select_flag_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(column);
SQLPP_TYPE_TRAIT_GENERATOR(is_select_column_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(select);
SQLPP_TYPE_TRAIT_GENERATOR(is_from); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_flag_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_on); SQLPP_IS_VALUE_TRAIT_GENERATOR(select_column_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_dynamic); SQLPP_IS_VALUE_TRAIT_GENERATOR(from);
SQLPP_TYPE_TRAIT_GENERATOR(is_where); SQLPP_IS_VALUE_TRAIT_GENERATOR(single_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_group_by); SQLPP_IS_VALUE_TRAIT_GENERATOR(into);
SQLPP_TYPE_TRAIT_GENERATOR(is_having); SQLPP_IS_VALUE_TRAIT_GENERATOR(extra_tables);
SQLPP_TYPE_TRAIT_GENERATOR(is_order_by); SQLPP_IS_VALUE_TRAIT_GENERATOR(on);
SQLPP_TYPE_TRAIT_GENERATOR(is_limit); SQLPP_IS_VALUE_TRAIT_GENERATOR(where);
SQLPP_TYPE_TRAIT_GENERATOR(is_offset); SQLPP_IS_VALUE_TRAIT_GENERATOR(group_by);
SQLPP_TYPE_TRAIT_GENERATOR(is_using); SQLPP_IS_VALUE_TRAIT_GENERATOR(having);
SQLPP_TYPE_TRAIT_GENERATOR(is_column_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(order_by);
SQLPP_TYPE_TRAIT_GENERATOR(is_multi_column); SQLPP_IS_VALUE_TRAIT_GENERATOR(limit);
SQLPP_TYPE_TRAIT_GENERATOR(is_value_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(offset);
SQLPP_TYPE_TRAIT_GENERATOR(is_assignment); SQLPP_IS_VALUE_TRAIT_GENERATOR(using_);
SQLPP_TYPE_TRAIT_GENERATOR(is_update_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(column_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(multi_column);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value); SQLPP_IS_VALUE_TRAIT_GENERATOR(value_list);
SQLPP_TYPE_TRAIT_GENERATOR(is_insert_value_list); SQLPP_IS_VALUE_TRAIT_GENERATOR(assignment);
SQLPP_TYPE_TRAIT_GENERATOR(is_sort_order); SQLPP_IS_VALUE_TRAIT_GENERATOR(update_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value);
SQLPP_IS_VALUE_TRAIT_GENERATOR(insert_value_list);
SQLPP_IS_VALUE_TRAIT_GENERATOR(sort_order);
SQLPP_IS_VALUE_TRAIT_GENERATOR(parameter);
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
SQLPP_TYPE_TRAIT_GENERATOR(is_parameter);
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value); SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value);
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity); SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
template<typename Database>
using is_database = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
template<typename T, template<typename> class IsTag> template<typename T, template<typename> class IsTag>
using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type; using copy_type_trait = typename std::conditional<IsTag<T>::value, std::true_type, std::false_type>::type;
namespace detail
{
template<typename T>
struct value_type_of_impl
{
using type = typename T::_traits::_value_type;
};
template<typename T>
struct required_table_of_impl
{
using type = typename T::_recursive_traits::_required_tables;
};
template<typename T>
struct provided_table_of_impl
{
using type = typename T::_recursive_traits::_provided_tables;
};
template<typename T>
struct extra_table_of_impl
{
using type = typename T::_recursive_traits::_extra_tables;
};
template<typename T>
struct parameters_of_impl
{
using type = typename T::_recursive_traits::_parameters;
};
template<typename T>
struct name_of_impl
{
using type = typename T::_name_t;
};
template<typename... T>
struct make_parameter_tuple_impl
{
using type = decltype(std::tuple_cat(std::declval<T>()...));
};
template<typename... T>
using make_parameter_tuple_t = typename make_parameter_tuple_impl<T...>::type;
}
template<typename T>
using value_type_of = typename detail::value_type_of_impl<T>::type;
template<typename T>
using required_tables_of = typename detail::required_table_of_impl<T>::type;
template<typename T>
using provided_tables_of = typename detail::provided_table_of_impl<T>::type;
template<typename T>
using extra_tables_of = typename detail::extra_table_of_impl<T>::type;
template<typename T>
using parameters_of = typename detail::parameters_of_impl<T>::type;
template<typename T>
using name_of = typename detail::name_of_impl<T>::type;
template<typename ValueType, typename... Tags>
struct make_traits
{
using _value_type = ValueType;
using _tags = detail::make_type_set_t<typename ValueType::_tag, Tags...>;
};
template<typename... Arguments>
struct make_recursive_traits
{
using _required_tables = detail::make_joined_set_t<required_tables_of<Arguments>...>;
using _provided_tables = detail::make_joined_set_t<provided_tables_of<Arguments>...>;
using _extra_tables = detail::make_joined_set_t<extra_tables_of<Arguments>...>;
using _parameters = detail::make_parameter_tuple_t<parameters_of<Arguments>...>;
};
} }
#endif #endif

View File

@ -27,181 +27,90 @@
#ifndef SQLPP_UPDATE_H #ifndef SQLPP_UPDATE_H
#define SQLPP_UPDATE_H #define SQLPP_UPDATE_H
#include <sqlpp11/statement.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/parameter_list.h> #include <sqlpp11/parameter_list.h>
#include <sqlpp11/prepared_update.h> #include <sqlpp11/prepared_update.h>
#include <sqlpp11/vendor/single_table.h> #include <sqlpp11/single_table.h>
#include <sqlpp11/vendor/update_list.h> #include <sqlpp11/update_list.h>
#include <sqlpp11/vendor/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/vendor/where.h> #include <sqlpp11/where.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/arg_selector.h>
namespace sqlpp namespace sqlpp
{ {
template<typename Db, struct update_name_t {};
typename... Policies
>
struct update_t;
namespace detail struct update_t: public statement_name_t<update_name_t>
{ {
template<typename Db = void, using _traits = make_traits<no_value_t, tag::return_value>;
typename Table = vendor::no_single_table_t, struct _name_t {};
typename UpdateList = vendor::no_update_list_t,
typename Where = vendor::no_where_t template<typename Policies>
> struct _result_methods_t
struct update_policies_t
{ {
using _database_t = Db; using _statement_t = typename Policies::_statement_t;
using _table_t = Table;
using _update_list_t = UpdateList;
using _where_t = Where;
using _statement_t = update_t<Db, Table, UpdateList, Where>; const _statement_t& _get_statement() const
{
return static_cast<const _statement_t&>(*this);
}
struct _methods_t: template<typename Db>
public _update_list_t::template _methods_t<update_policies_t>, auto _run(Db& db) const -> decltype(db.update(this->_get_statement()))
public _where_t::template _methods_t<update_policies_t>
{};
template<typename Needle, typename Replacement, typename... Policies>
struct _policies_update_t
{ {
using type = update_t<Db, vendor::policy_update_t<Policies, Needle, Replacement>...>; _statement_t::_check_consistency();
};
template<typename Needle, typename Replacement> static_assert(_statement_t::_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
using _new_statement_t = typename _policies_update_t<Needle, Replacement, Table, UpdateList, Where>::type; return db.update(_get_statement());
}
using _known_tables = detail::make_joined_set_t<typename _table_t::_table_set>; template<typename Db>
auto _prepare(Db& db) const
template<typename Expression> -> prepared_update_t<Db, _statement_t>
using _no_unknown_tables = detail::is_subset_of<typename Expression::_table_set, _known_tables>; {
_statement_t::_check_consistency();
return {{}, db.prepare_update(_get_statement())};
}
}; };
} };
template<typename Db,
typename... Policies template<typename Context>
> struct serializer_t<Context, update_name_t>
struct update_t:
public detail::update_policies_t<Db, Policies...>::_methods_t
{ {
using _policies_t = typename detail::update_policies_t<Db, Policies...>; using T = update_name_t;
using _database_t = typename _policies_t::_database_t;
using _table_t = typename _policies_t::_table_t;
using _update_list_t = typename _policies_t::_update_list_t;
using _where_t = typename _policies_t::_where_t;
using _is_dynamic = typename std::conditional<std::is_same<_database_t, void>::value, std::false_type, std::true_type>::type; static Context& _(const T& t, Context& context)
using _parameter_tuple_t = std::tuple<Policies...>;
using _parameter_list_t = typename make_parameter_list_t<update_t>::type;
static_assert(::sqlpp::detail::is_superset_of<typename _table_t::_table_set, typename _update_list_t::_table_set>::value, "updated columns do not match the table");
static_assert(::sqlpp::detail::is_superset_of<typename _table_t::_table_set, typename _where_t::_table_set>::value, "where condition does not match updated table");
// Constructors
update_t()
{}
template<typename Statement, typename T>
update_t(Statement s, T t):
_table(detail::arg_selector<_table_t>::_(s._table, t)),
_update_list(detail::arg_selector<_update_list_t>::_(s._update_list, t)),
_where(detail::arg_selector<_where_t>::_(s._where, t))
{}
update_t(const update_t&) = default;
update_t(update_t&&) = default;
update_t& operator=(const update_t&) = default;
update_t& operator=(update_t&&) = default;
~update_t() = default;
// run and prepare
static constexpr size_t _get_static_no_of_parameters()
{ {
return _parameter_list_t::size::value; context << "UPDATE ";
return context;
} }
size_t _get_no_of_parameters() const
{
return _parameter_list_t::size::value;
}
template<typename A>
struct is_table_subset_of_table
{
static constexpr bool value = ::sqlpp::detail::is_subset_of<typename A::_table_set, typename _table_t::_table_set>::value;
};
void _check_consistency() const
{
static_assert(is_where_t<_where_t>::value, "cannot run update without having a where condition, use .where(true) to update all rows");
static_assert(is_table_subset_of_table<_update_list_t>::value, "updates require additional tables");
static_assert(is_table_subset_of_table<_where_t>::value, "where requires additional tables");
}
template<typename Database>
std::size_t _run(Database& db) const
{
_check_consistency();
static_assert(_get_static_no_of_parameters() == 0, "cannot run update directly with parameters, use prepare instead");
return db.update(*this);
}
template<typename Database>
auto _prepare(Database& db) const
-> prepared_update_t<Database, update_t>
{
_check_consistency();
return {{}, db.prepare_update(*this)};
}
_table_t _table;
_update_list_t _update_list;
_where_t _where;
}; };
namespace vendor template<typename Database>
{ using blank_update_t = statement_t<Database,
template<typename Context, typename Database, typename... Policies> update_t,
struct serializer_t<Context, update_t<Database, Policies...>> no_single_table_t,
{ no_update_list_t,
using T = update_t<Database, Policies...>; no_where_t<true>
>;
static Context& _(const T& t, Context& context)
{
context << "UPDATE ";
serialize(t._table, context);
serialize(t._update_list, context);
serialize(t._where, context);
return context;
}
};
}
template<typename Database, typename... Policies>
using make_update_t = typename detail::update_policies_t<Database, Policies...>::_statement_t;
template<typename Table> template<typename Table>
constexpr auto update(Table table) constexpr auto update(Table table)
-> make_update_t<void, vendor::single_table_t<void, Table>> -> decltype(blank_update_t<void>().from(table))
{ {
return { update_t<void>(), vendor::single_table_t<void, Table>{table} }; return { blank_update_t<void>().from(table) };
} }
template<typename Database, typename Table> template<typename Database, typename Table>
constexpr auto dynamic_update(const Database&, Table table) constexpr auto dynamic_update(const Database&, Table table)
-> make_update_t<Database, vendor::single_table_t<void, Table>> -> decltype(blank_update_t<Database>().from(table))
{ {
return { update_t<Database>(), vendor::single_table_t<void, Table>{table} }; return { blank_update_t<Database>().from(table) };
} }
} }
#endif #endif

View File

@ -0,0 +1,223 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_UPDATE_LIST_H
#define SQLPP_UPDATE_LIST_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/interpretable_list.h>
namespace sqlpp
{
// UPDATE ASSIGNMENTS DATA
template<typename Database, typename... Assignments>
struct update_list_data_t
{
update_list_data_t(Assignments... assignments):
_assignments(assignments...)
{}
update_list_data_t(const update_list_data_t&) = default;
update_list_data_t(update_list_data_t&&) = default;
update_list_data_t& operator=(const update_list_data_t&) = default;
update_list_data_t& operator=(update_list_data_t&&) = default;
~update_list_data_t() = default;
std::tuple<Assignments...> _assignments;
interpretable_list_t<Database> _dynamic_assignments;
};
// UPDATE ASSIGNMENTS
template<typename Database, typename... Assignments>
struct update_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::update_list>;
using _recursive_traits = make_recursive_traits<Assignments...>;
using _is_dynamic = is_database<Database>;
// Data
using _data_t = update_list_data_t<Database, Assignments...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Assignment>
void add_ntc(Assignment assignment)
{
add<Assignment, std::false_type>(assignment);
}
template<typename Assignment, typename TableCheckRequired = std::true_type>
void add(Assignment assignment)
{
static_assert(_is_dynamic::value, "add must not be called for static from()");
static_assert(is_assignment_t<Assignment>::value, "invalid assignment argument in add()");
using _assigned_columns = detail::make_type_set_t<typename Assignments::_column_t...>;
static_assert(not detail::is_element_of<typename Assignment::_column_t, _assigned_columns>::value, "Must not assign value to column twice");
static_assert(sqlpp::detail::not_t<must_not_update_t, typename Assignment::_column_t>::value, "add() argument must not be updated");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Assignment>::value, "assignment uses tables unknown to this statement in add()");
using ok = ::sqlpp::detail::all_t<
_is_dynamic::value,
is_assignment_t<Assignment>::value>;
_add_impl(assignment, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Assignment>
void _add_impl(Assignment assignment, const std::true_type&)
{
return _data._dynamic_assignments.emplace_back(assignment);
}
template<typename Assignment>
void _add_impl(Assignment assignment, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = update_list_data_t<Database, Assignments...>;
_impl_t<Policies> assignments;
_impl_t<Policies>& operator()() { return assignments; }
const _impl_t<Policies>& operator()() const { return assignments; }
template<typename T>
static auto _get_member(T t) -> decltype(t.assignments)
{
return t.assignments;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
struct no_update_list_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_assignments;
_impl_t<Policies>& operator()() { return no_assignments; }
const _impl_t<Policies>& operator()() const { return no_assignments; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_assignments)
{
return t.no_assignments;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_update_list_t, T>;
static void _check_consistency() {}
template<typename... Assignments>
auto set(Assignments... assignments)
-> _new_statement_t<update_list_t<void, Assignments...>>
{
static_assert(sizeof...(Assignments), "at least one assignment expression required in set()");
return _set_impl<void>(assignments...);
}
template<typename... Assignments>
auto dynamic_set(Assignments... assignments)
-> _new_statement_t<update_list_t<_database_t, Assignments...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_set() must not be called in a static statement");
return _set_impl<_database_t>(assignments...);
}
private:
template<typename Database, typename... Assignments>
auto _set_impl(Assignments... assignments)
-> _new_statement_t<update_list_t<Database, Assignments...>>
{
static_assert(not ::sqlpp::detail::has_duplicates<Assignments...>::value, "at least one duplicate argument detected in set()");
static_assert(::sqlpp::detail::all_t<is_assignment_t<Assignments>::value...>::value, "at least one argument is not an assignment in set()");
static_assert(::sqlpp::detail::none_t<must_not_update_t<typename Assignments::_column_t>::value...>::value, "at least one assignment is prohibited by its column definition in set()");
using _column_required_tables = typename ::sqlpp::detail::make_joined_set<required_tables_of<typename Assignments::_column_t>...>::type;
static_assert(sizeof...(Assignments) ? (_column_required_tables::size::value == 1) : true, "set() contains assignments for columns from more than one table");
return { *static_cast<typename Policies::_statement_t*>(this), update_list_data_t<Database, Assignments...>{assignments...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Assignments>
struct serializer_t<Context, update_list_data_t<Database, Assignments...>>
{
using T = update_list_data_t<Database, Assignments...>;
static Context& _(const T& t, Context& context)
{
context << " SET ";
interpret_tuple(t._assignments, ",", context);
if (sizeof...(Assignments) and not t._dynamic_assignments.empty())
context << ',';
interpret_list(t._dynamic_assignments, ',', context);
return context;
}
};
}
#endif

207
include/sqlpp11/using.h Normal file
View File

@ -0,0 +1,207 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_USING_H
#define SQLPP_USING_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/interpretable_list.h>
#include <sqlpp11/interpret_tuple.h>
#include <sqlpp11/detail/type_set.h>
#include <sqlpp11/policy_update.h>
namespace sqlpp
{
// USING DATA
template<typename Database, typename... Tables>
struct using_data_t
{
using_data_t(Tables... tables):
_tables(tables...)
{}
using_data_t(const using_data_t&) = default;
using_data_t(using_data_t&&) = default;
using_data_t& operator=(const using_data_t&) = default;
using_data_t& operator=(using_data_t&&) = default;
~using_data_t() = default;
std::tuple<Tables...> _tables;
interpretable_list_t<Database> _dynamic_tables;
};
// USING
template<typename Database, typename... Tables>
struct using_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::using_>;
using _recursive_traits = make_recursive_traits<Tables...>;
using _is_dynamic = is_database<Database>;
static_assert(_is_dynamic::value or sizeof...(Tables), "at least one table argument required in using()");
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in using()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not an table in using()");
// Data
using _data_t = using_data_t<Database, Tables...>;
// Member implementation with data and methods
template <typename Policies>
struct _impl_t
{
template<typename Table>
void add(Table table)
{
static_assert(_is_dynamic::value, "add must not be called for static using()");
static_assert(is_table_t<Table>::value, "invalid table argument in add()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Table>
void _add_impl(Table table, const std::true_type&)
{
return _data._dynamic_tables.emplace_back(table);
}
template<typename Table>
void _add_impl(Table table, const std::false_type&);
public:
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = using_data_t<Database, Tables...>;
_impl_t<Policies> using_;
_impl_t<Policies>& operator()() { return using_; }
const _impl_t<Policies>& operator()() const { return using_; }
template<typename T>
static auto _get_member(T t) -> decltype(t.using_)
{
return t.using_;
}
};
// Additional methods for the statement
template<typename Policies>
struct _methods_t
{
static void _check_consistency() {}
};
};
// NO USING YET
struct no_using_t
{
using _traits = make_traits<no_value_t, ::sqlpp::tag::where>;
using _recursive_traits = make_recursive_traits<>;
// Data
using _data_t = no_data_t;
// Member implementation with data and methods
template<typename Policies>
struct _impl_t
{
_data_t _data;
};
// Member template for adding the named member to a statement
template<typename Policies>
struct _member_t
{
using _data_t = no_data_t;
_impl_t<Policies> no_using;
_impl_t<Policies>& operator()() { return no_using; }
const _impl_t<Policies>& operator()() const { return no_using; }
template<typename T>
static auto _get_member(T t) -> decltype(t.no_using)
{
return t.no_using;
}
};
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_using_t, T>;
static void _check_consistency() {}
template<typename... Args>
auto using_(Args... args)
-> _new_statement_t<using_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), using_data_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_using(Args... args)
-> _new_statement_t<using_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_using must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), using_data_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, using_data_t<Database, Tables...>>
{
using T = using_data_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
return context;
context << " USING ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(Tables) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
}
#endif

View File

@ -28,14 +28,11 @@
#define SQLPP_VALUE_TYPE_H #define SQLPP_VALUE_TYPE_H
#include <type_traits> #include <type_traits>
#include <sqlpp11/vendor/wrap_operand.h> #include <sqlpp11/wrap_operand.h>
namespace sqlpp namespace sqlpp
{ {
namespace vendor template<typename T>
{ using value_type_t = value_type_of<wrap_operand_t<T>>;
template<typename T>
using value_type_t = typename wrap_operand<T>::type::_value_type;
}
} }
#endif #endif

View File

@ -1,164 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_ASSIGNMENT_H
#define SQLPP_ASSIGNMENT_H
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/serialize.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/simple_column.h>
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
{
using _is_assignment = std::true_type;
using _column_t = Lhs;
using value_type = 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 ? true : not std::is_same<Rhs, null_t>::value, "column must not be null");
assignment_t(_column_t lhs, value_type rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
value_type _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, assignment_t<Lhs, Rhs>>
{
using T = assignment_t<Lhs, Rhs>;
static Context& _(const T& t, Context& 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;
}
};
template<typename Lhs, typename Rhs>
struct assignment_t<Lhs, tvin_t<Rhs>>
{
using _is_assignment = std::true_type;
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");
assignment_t(_column_t lhs, value_type rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
_column_t _lhs;
value_type _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, assignment_t<Lhs, tvin_t<Rhs>>>
{
using T = assignment_t<Lhs, tvin_t<Rhs>>;
static Context& _(const T& t, Context& context)
{
serialize(simple_column(t._lhs), context);
if (t._rhs._value._is_trivial())
{
context << "=NULL";
}
else
{
context << "=";
serialize(t._rhs._value, context);
}
return context;
}
};
}
}
#endif

View File

@ -1,244 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_H
#define SQLPP_EXPRESSION_H
#include <sqlpp11/alias.h>
#include <sqlpp11/boolean.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/vendor/noop.h>
#include <sqlpp11/vendor/expression_fwd.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/vendor/wrap_operand.h>
namespace sqlpp
{
namespace vendor
{
template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, tag::equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<equal_to_t<Lhs, Rhs>>
{
using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, equal_to_t<Lhs, Rhs>>
{
using T = equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NULL";
}
else
{
context << "=";
serialize(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Lhs, typename Rhs>
struct binary_expression_t<Lhs, tag::not_equal_to, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<not_equal_to_t<Lhs, Rhs>>
{
using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Lhs, Rhs>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
binary_expression_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
Lhs _lhs;
maybe_tvin_t<Rhs> _rhs;
};
template<typename Context, typename Lhs, typename Rhs>
struct serializer_t<Context, not_equal_to_t<Lhs, Rhs>>
{
using T = not_equal_to_t<Lhs, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._lhs, context);
if (t._rhs._is_trivial())
{
context << " IS NOT NULL";
}
else
{
context << "!=";
serialize(t._rhs, context);
}
context << ")";
return context;
}
};
template<typename Rhs>
struct unary_expression_t<tag::logical_not, Rhs>: public ::sqlpp::detail::boolean::template expression_operators<logical_not_t<Rhs>>
{
using _value_type = ::sqlpp::detail::boolean;
using _parameter_tuple_t = std::tuple<Rhs>;
using _table_set = typename Rhs::_table_set;
unary_expression_t(Rhs rhs):
_rhs(rhs)
{}
unary_expression_t(const unary_expression_t&) = default;
unary_expression_t(unary_expression_t&&) = default;
unary_expression_t& operator=(const unary_expression_t&) = default;
unary_expression_t& operator=(unary_expression_t&&) = default;
~unary_expression_t() = default;
Rhs _rhs;
};
template<typename Context, typename Rhs>
struct serializer_t<Context, logical_not_t<Rhs>>
{
using T = logical_not_t<Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << "NOT ";
serialize(t._lhs, context);
context << ")";
return context;
}
};
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t: public O::_value_type::template expression_operators<binary_expression_t<Lhs, O, Rhs>>
{
using _lhs_t = Lhs;
using _rhs_t = Rhs;
using _value_type = typename O::_value_type;
using _parameter_tuple_t = std::tuple<_lhs_t, _rhs_t>;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Lhs::_table_set, typename Rhs::_table_set>::type;
binary_expression_t(_lhs_t lhs, _rhs_t rhs):
_lhs(lhs),
_rhs(rhs)
{}
binary_expression_t(const binary_expression_t&) = default;
binary_expression_t(binary_expression_t&&) = default;
binary_expression_t& operator=(const binary_expression_t&) = default;
binary_expression_t& operator=(binary_expression_t&&) = default;
~binary_expression_t() = default;
_lhs_t _lhs;
_rhs_t _rhs;
};
template<typename Context, typename Lhs, typename O, typename Rhs>
struct serializer_t<Context, binary_expression_t<Lhs, O, Rhs>>
{
using T = binary_expression_t<Lhs, O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
serialize(t._lhs, context);
context << O::_name;
serialize(t._rhs, context);
context << ")";
return context;
}
};
template<typename O, typename Rhs>
struct unary_expression_t: public O::_value_type::template expression_operators<unary_expression_t<O, Rhs>>
{
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)
{}
unary_expression_t(const unary_expression_t&) = default;
unary_expression_t(unary_expression_t&&) = default;
unary_expression_t& operator=(const unary_expression_t&) = default;
unary_expression_t& operator=(unary_expression_t&&) = default;
~unary_expression_t() = default;
Rhs _rhs;
};
template<typename Context, typename O, typename Rhs>
struct serializer_t<Context, unary_expression_t<O, Rhs>>
{
using T = unary_expression_t<O, Rhs>;
static Context& _(const T& t, Context& context)
{
context << "(";
context << O::_name;
serialize(t._rhs, context);
context << ")";
return context;
}
};
}
}
#endif

View File

@ -1,192 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXPRESSION_FWD_H
#define SQLPP_EXPRESSION_FWD_H
namespace sqlpp
{
namespace vendor
{
namespace tag
{
struct less
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = "<";
};
struct less_equal
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = "<=";
};
struct equal_to
{
using _value_type = ::sqlpp::detail::boolean;
};
struct not_equal_to
{
using _value_type = ::sqlpp::detail::boolean;
};
struct greater_equal
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = ">=";
};
struct greater
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = ">";
};
struct logical_or
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = " OR ";
};
struct logical_and
{
using _value_type = ::sqlpp::detail::boolean;
static constexpr const char* _name = " AND ";
};
struct logical_not
{
using _value_type = ::sqlpp::detail::boolean;
};
template<typename ValueType>
struct plus
{
using _value_type = ValueType;
static constexpr const char* _name = "+";
};
template<typename ValueType>
struct minus
{
using _value_type = ValueType;
static constexpr const char* _name = "-";
};
template<typename ValueType>
struct multiplies
{
using _value_type = ValueType;
static constexpr const char* _name = "*";
};
struct divides
{
using _value_type = ::sqlpp::detail::floating_point;
static constexpr const char* _name = "/";
};
struct modulus
{
using _value_type = ::sqlpp::detail::integral;
static constexpr const char* _name = "%";
};
template<typename ValueType>
struct unary_minus
{
using _value_type = ValueType;
static constexpr const char* _name = "-";
};
template<typename ValueType>
struct unary_plus
{
using _value_type = ValueType;
static constexpr const char* _name = "+";
};
}
template<typename Lhs, typename O, typename Rhs>
struct binary_expression_t;
template<typename O, typename Rhs>
struct unary_expression_t;
template<typename Lhs, typename Rhs>
using less_than_t = binary_expression_t<Lhs, tag::less, Rhs>;
template<typename Lhs, typename Rhs>
using less_equal_t = binary_expression_t<Lhs, tag::less_equal, Rhs>;
template<typename Lhs, typename Rhs>
using equal_to_t = binary_expression_t<Lhs, tag::equal_to, Rhs>;
template<typename Lhs, typename Rhs>
using not_equal_to_t = binary_expression_t<Lhs, tag::not_equal_to, Rhs>;
template<typename Lhs, typename Rhs>
using greater_than_t = binary_expression_t<Lhs, tag::greater, Rhs>;
template<typename Lhs, typename Rhs>
using greater_equal_t = binary_expression_t<Lhs, tag::greater_equal, Rhs>;
template<typename Lhs, typename Rhs>
using logical_and_t = binary_expression_t<Lhs, tag::logical_and, Rhs>;
template<typename Lhs, typename Rhs>
using logical_or_t = binary_expression_t<Lhs, tag::logical_or, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using plus_t = binary_expression_t<Lhs, tag::plus<ValueType>, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using minus_t = binary_expression_t<Lhs, tag::minus<ValueType>, Rhs>;
template<typename Lhs, typename ValueType, typename Rhs>
using multiplies_t = binary_expression_t<Lhs, tag::multiplies<ValueType>, Rhs>;
template<typename Lhs, typename Rhs>
using divides_t = binary_expression_t<Lhs, tag::divides, Rhs>;
template<typename Lhs, typename Rhs>
using modulus_t = binary_expression_t<Lhs, tag::modulus, Rhs>;
template<typename Rhs>
using logical_not_t = unary_expression_t<tag::logical_not, Rhs>;
template<typename ValueType, typename Rhs>
using unary_plus_t = unary_expression_t<tag::unary_plus<ValueType>, Rhs>;
template<typename ValueType, typename Rhs>
using unary_minus_t = unary_expression_t<tag::unary_minus<ValueType>, Rhs>;
}
}
#endif

View File

@ -1,114 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_EXTRA_TABLES_H
#define SQLPP_EXTRA_TABLES_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/policy_update.h>
namespace sqlpp
{
namespace vendor
{
// EXTRA_TABLES
template<typename... Tables>
struct extra_tables_t
{
using _is_extra_tables = std::true_type;
static_assert(sizeof...(Tables), "at least one table or join argument required in extra_tables()");
static_assert(not ::sqlpp::detail::has_duplicates<Tables...>::value, "at least one duplicate argument detected in extra_tables()");
static_assert(::sqlpp::detail::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in extra_tables()");
using _table_set = ::sqlpp::detail::make_joined_set_t<typename Tables::_table_set...>;
extra_tables_t()
{}
extra_tables_t(const extra_tables_t&) = default;
extra_tables_t(extra_tables_t&&) = default;
extra_tables_t& operator=(const extra_tables_t&) = default;
extra_tables_t& operator=(extra_tables_t&&) = default;
~extra_tables_t() = default;
template<typename Policies>
struct _methods_t
{
};
};
struct no_extra_tables_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
template<typename Policies>
struct _methods_t
{
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_extra_tables_t, T>;
template<typename... Args>
auto extra_tables(Args...)
-> _new_statement_t<extra_tables_t<Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), extra_tables_t<Args...>{} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, extra_tables_t<Database, Tables...>>
{
using T = extra_tables_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_extra_tables_t>
{
using T = no_extra_tables_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -1,158 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_FROM_H
#define SQLPP_FROM_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/detail/logic.h>
#include <sqlpp11/vendor/policy_update.h>
namespace sqlpp
{
namespace vendor
{
// FROM
template<typename Database, typename... Tables>
struct from_t
{
using _is_from = std::true_type;
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...(Tables), "at least one table or join argument required in from()");
// 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::all_t<is_table_t<Tables>::value...>::value, "at least one argument is not a table or join in from()");
using _table_set = ::sqlpp::detail::make_joined_set_t<typename Tables::_table_set...>;
from_t(Tables... tables):
_tables(tables...)
{}
from_t(const from_t&) = default;
from_t(from_t&&) = default;
from_t& operator=(const from_t&) = default;
from_t& operator=(from_t&&) = default;
~from_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Table>
void add_from(Table table)
{
static_assert(_is_dynamic::value, "add_from must not be called for static from()");
static_assert(is_table_t<Table>::value, "invalid table argument in add_from()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_table_t<Table>::value>;
_add_from_impl(table, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Table>
void _add_from_impl(Table table, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_from._dynamic_tables.emplace_back(table);
}
template<typename Table>
void _add_from_impl(Table table, const std::false_type&);
};
std::tuple<Tables...> _tables;
vendor::interpretable_list_t<Database> _dynamic_tables;
};
struct no_from_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_from_t, T>;
template<typename... Args>
auto from(Args... args)
-> _new_statement_t<from_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), from_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_from(Args... args)
-> _new_statement_t<from_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_from must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::from_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Tables>
struct serializer_t<Context, from_t<Database, Tables...>>
{
using T = from_t<Database, Tables...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Tables) == 0 and t._dynamic_tables.empty())
return context;
context << " FROM ";
interpret_tuple(t._tables, ',', context);
if (sizeof...(Tables) and not t._dynamic_tables.empty())
context << ',';
interpret_list(t._dynamic_tables, ',', context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_from_t>
{
using T = no_from_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -1,168 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_GROUP_BY_H
#define SQLPP_GROUP_BY_H
#include <tuple>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace vendor
{
// GROUP BY
template<typename Database, typename... Expressions>
struct group_by_t
{
using _is_group_by = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
using _parameter_tuple_t = std::tuple<Expressions...>;
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
static_assert(_is_dynamic::value or sizeof...(Expressions), "at least one expression (e.g. a column) required in group_by()");
static_assert(not ::sqlpp::detail::has_duplicates<Expressions...>::value, "at least one duplicate argument detected in group_by()");
static_assert(::sqlpp::detail::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in group_by()");
group_by_t(Expressions... expressions):
_expressions(expressions...)
{}
group_by_t(const group_by_t&) = default;
group_by_t(group_by_t&&) = default;
group_by_t& operator=(const group_by_t&) = default;
group_by_t& operator=(group_by_t&&) = default;
~group_by_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Expression>
void add_group_by_ntc(Expression expression)
{
add_group_by<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_group_by(Expression expression)
{
static_assert(_is_dynamic::value, "add_group_by must not be called for static group_by");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_group_by()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_group_by()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_group_by_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_group_by_impl(Expression expression, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_group_by._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_group_by_impl(Expression expression, const std::false_type&);
};
const group_by_t& _group_by() const { return *this; }
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
struct no_group_by_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_group_by_t, T>;
template<typename... Args>
auto group_by(Args... args)
-> _new_statement_t<group_by_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), group_by_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_group_by(Args... args)
-> _new_statement_t<group_by_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_group_by must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::group_by_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, group_by_t<Database, Expressions...>>
{
using T = group_by_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " GROUP BY ";
interpret_tuple(t._expressions, ',', context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << ',';
interpret_list(t._dynamic_expressions, ',', context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_group_by_t>
{
using T = no_group_by_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -1,164 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_HAVING_H
#define SQLPP_HAVING_H
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/expression.h>
#include <sqlpp11/vendor/interpret_tuple.h>
#include <sqlpp11/vendor/interpretable_list.h>
#include <sqlpp11/vendor/policy_update.h>
#include <sqlpp11/detail/logic.h>
namespace sqlpp
{
namespace vendor
{
// HAVING
template<typename Database, typename... Expressions>
struct having_t
{
using _is_having = std::true_type;
using _is_dynamic = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;
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::all_t<is_expression_t<Expressions>::value...>::value, "at least one argument is not an expression in having()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
using _table_set = typename ::sqlpp::detail::make_joined_set<typename Expressions::_table_set...>::type;
having_t(Expressions... expressions):
_expressions(expressions...)
{}
having_t(const having_t&) = default;
having_t(having_t&&) = default;
having_t& operator=(const having_t&) = default;
having_t& operator=(having_t&&) = default;
~having_t() = default;
template<typename Policies>
struct _methods_t
{
template<typename Expression>
void add_having_ntc(Expression expression)
{
add_having<Expression, std::false_type>(expression);
}
template<typename Expression, typename TableCheckRequired = std::true_type>
void add_having(Expression expression)
{
static_assert(_is_dynamic::value, "add_having must not be called for static having");
static_assert(is_expression_t<Expression>::value, "invalid expression argument in add_having()");
static_assert(TableCheckRequired::value or Policies::template _no_unknown_tables<Expression>::value, "expression uses tables unknown to this statement in add_having()");
using ok = ::sqlpp::detail::all_t<_is_dynamic::value, is_expression_t<Expression>::value>;
_add_having_impl(expression, ok()); // dispatch to prevent compile messages after the static_assert
}
private:
template<typename Expression>
void _add_having_impl(Expression expression, const std::true_type&)
{
return static_cast<typename Policies::_statement_t*>(this)->_having._dynamic_expressions.emplace_back(expression);
}
template<typename Expression>
void _add_having_impl(Expression expression, const std::false_type&);
};
_parameter_tuple_t _expressions;
vendor::interpretable_list_t<Database> _dynamic_expressions;
};
struct no_having_t
{
using _is_noop = std::true_type;
using _table_set = ::sqlpp::detail::type_set<>;
template<typename Policies>
struct _methods_t
{
using _database_t = typename Policies::_database_t;
template<typename T>
using _new_statement_t = typename Policies::template _new_statement_t<no_having_t, T>;
template<typename... Args>
auto having(Args... args)
-> _new_statement_t<having_t<void, Args...>>
{
return { *static_cast<typename Policies::_statement_t*>(this), having_t<void, Args...>{args...} };
}
template<typename... Args>
auto dynamic_having(Args... args)
-> _new_statement_t<having_t<_database_t, Args...>>
{
static_assert(not std::is_same<_database_t, void>::value, "dynamic_having must not be called in a static statement");
return { *static_cast<typename Policies::_statement_t*>(this), vendor::having_t<_database_t, Args...>{args...} };
}
};
};
// Interpreters
template<typename Context, typename Database, typename... Expressions>
struct serializer_t<Context, having_t<Database, Expressions...>>
{
using T = having_t<Database, Expressions...>;
static Context& _(const T& t, Context& context)
{
if (sizeof...(Expressions) == 0 and t._dynamic_expressions.empty())
return context;
context << " HAVING ";
interpret_tuple(t._expressions, " AND ", context);
if (sizeof...(Expressions) and not t._dynamic_expressions.empty())
context << " AND ";
interpret_list(t._dynamic_expressions, " AND ", context);
return context;
}
};
template<typename Context>
struct serializer_t<Context, no_having_t>
{
using T = no_having_t;
static Context& _(const T& t, Context& context)
{
return context;
}
};
}
}
#endif

View File

@ -1,124 +0,0 @@
/*
* Copyright (c) 2013-2014, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_INSERT_VALUE_H
#define SQLPP_INSERT_VALUE_H
#include <sqlpp11/default_value.h>
#include <sqlpp11/null.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/type_traits.h>
#include <sqlpp11/vendor/serializer.h>
#include <sqlpp11/detail/type_set.h>
namespace sqlpp
{
namespace vendor
{
namespace detail
{
template<typename Type, bool>
struct type_if
{
using type = Type;
using _table_set = typename Type::_table_set;
};
template<typename Type>
struct type_if<Type, false>
{
struct type
{
using _table_set = sqlpp::detail::type_set<>;
};
};
}
template<typename Column>
struct insert_value_t
{
using _is_insert_value = std::true_type;
using _pure_value_t = typename Column::_value_type::_cpp_value_type;
using _wrapped_value_t = typename wrap_operand<_pure_value_t>::type;
using _tvin_t = typename detail::type_if<tvin_t<_wrapped_value_t>, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
using _null_t = typename detail::type_if<null_t, can_be_null_t<Column>::value>::type; // static asserts and SFINAE do not work together
insert_value_t(assignment_t<Column, _wrapped_value_t> assignment):
_is_null(false),
_is_default(false),
_value(assignment._rhs)
{}
insert_value_t(assignment_t<Column, _tvin_t> assignment):
_is_null(assignment._rhs._is_trivial()),
_is_default(false),
_value(assignment._rhs._value)
{}
insert_value_t(const assignment_t<Column, _null_t>&):
_is_null(true),
_is_default(false),
_value()
{}
insert_value_t(const assignment_t<Column, ::sqlpp::default_value_t>&):
_is_null(false),
_is_default(true),
_value()
{}
insert_value_t(const insert_value_t&) = default;
insert_value_t(insert_value_t&&) = default;
insert_value_t& operator=(const insert_value_t&) = default;
insert_value_t& operator=(insert_value_t&&) = default;
~insert_value_t() = default;
bool _is_null;
bool _is_default;
_wrapped_value_t _value;
};
template<typename Context, typename ValueType>
struct serializer_t<Context, insert_value_t<ValueType>>
{
using T = insert_value_t<ValueType>;
static Context& _(const T& t, Context& context)
{
if (t._is_null)
context << "NULL";
else if (t._is_default)
context << "DEFAULT";
else
serialize(t._value, context);
return context;
}
};
}
}
#endif

Some files were not shown because too many files have changed in this diff Show More