mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Merge branch 'release/0.20'
This commit is contained in:
commit
b48014d1dc
@ -37,6 +37,7 @@ set(include_dir "${PROJECT_SOURCE_DIR}/include")
|
||||
file(GLOB_RECURSE sqlpp_headers ${include_dir}/*.h)
|
||||
include_directories(${include_dir})
|
||||
add_subdirectory(tests)
|
||||
add_subdirectory(test_constraints)
|
||||
|
||||
install(DIRECTORY "${PROJECT_SOURCE_DIR}/include/sqlpp11" DESTINATION include)
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace sqlpp
|
||||
|
||||
static Context& _(const T& t, const Context&)
|
||||
{
|
||||
static_assert(wrong_t<T>::value, "all_of(table) does not seem to be used in select");
|
||||
static_assert(wrong_t<serializer_t>::value, "all_of(table) does not seem to be used in select");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include <sqlpp11/null.h>
|
||||
#include <sqlpp11/tvin.h>
|
||||
#include <sqlpp11/rhs_is_null.h>
|
||||
#include <sqlpp11/rhs_is_trivial.h>
|
||||
#include <sqlpp11/serialize.h>
|
||||
#include <sqlpp11/serializer.h>
|
||||
#include <sqlpp11/simple_column.h>
|
||||
@ -70,9 +71,8 @@ namespace sqlpp
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
if (((trivial_value_is_null_t<typename T::_lhs_t>::value or is_tvin_t<typename T::_rhs_t>::value)
|
||||
and is_trivial(t._rhs))
|
||||
or (std::is_same<Rhs, null_t>::value))
|
||||
if ((trivial_value_is_null_t<typename T::_lhs_t>::value and rhs_is_trivial(t))
|
||||
or rhs_is_null(t))
|
||||
{
|
||||
serialize(simple_column(t._lhs), context);
|
||||
context << "=NULL";
|
||||
|
@ -32,215 +32,185 @@
|
||||
#include <sqlpp11/basic_expression_operators.h>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/result_field.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
// boolean operators
|
||||
namespace detail
|
||||
// boolean value type
|
||||
struct boolean
|
||||
{
|
||||
// boolean value type
|
||||
struct boolean
|
||||
using _traits = make_traits<boolean, ::sqlpp::tag::is_boolean, ::sqlpp::tag::is_value_type>;
|
||||
using _tag = ::sqlpp::tag::is_boolean;
|
||||
using _cpp_value_type = bool;
|
||||
|
||||
struct _parameter_t
|
||||
{
|
||||
using _traits = make_traits<boolean, ::sqlpp::tag::is_boolean, ::sqlpp::tag::is_expression>;
|
||||
using _tag = ::sqlpp::tag::is_boolean;
|
||||
using _cpp_value_type = bool;
|
||||
using _value_type = boolean; // FIXME
|
||||
|
||||
struct _parameter_t
|
||||
_parameter_t():
|
||||
_value(false),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
_parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
using _value_type = boolean; // FIXME
|
||||
_value = value;
|
||||
_is_null = (false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t():
|
||||
_value(false),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
_parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
_value = value;
|
||||
_is_null = (false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t& operator=(const std::nullptr_t&)
|
||||
{
|
||||
_value = false;
|
||||
_is_null = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
operator _cpp_value_type() const { return value(); }
|
||||
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
target._bind_boolean_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
private:
|
||||
signed char _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t;
|
||||
|
||||
// I am SO waiting for concepts lite!
|
||||
template<typename Field, typename Enable = void>
|
||||
struct field_methods_t
|
||||
{
|
||||
static constexpr bool _null_is_trivial = true;
|
||||
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct field_methods_t<
|
||||
_result_field_t<Db, FieldSpec>,
|
||||
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
|
||||
and column_spec_can_be_null_t<FieldSpec>::value
|
||||
and not null_is_trivial_value_t<FieldSpec>::value>::type>
|
||||
{
|
||||
static constexpr bool _null_is_trivial = false;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
|
||||
{
|
||||
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
|
||||
|
||||
using _traits = make_traits<integral,
|
||||
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _provided_outer_tables = detail::type_set<>;
|
||||
using _required_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
|
||||
};
|
||||
|
||||
_result_field_t():
|
||||
_is_valid(false),
|
||||
_is_null(true),
|
||||
_value(false)
|
||||
{}
|
||||
|
||||
void _validate()
|
||||
{
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
void _invalidate()
|
||||
{
|
||||
_is_valid = false;
|
||||
_is_null = true;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (_is_null)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_boolean_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
|
||||
_parameter_t& operator=(const std::nullptr_t&)
|
||||
{
|
||||
template<typename T>
|
||||
logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
_value = false;
|
||||
_is_null = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
operator _cpp_value_type() const { return value(); }
|
||||
|
||||
logical_not_t<Base> operator not() const
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
target._bind_boolean_parameter(index, &_value, _is_null);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
};
|
||||
private:
|
||||
signed char _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const boolean::_result_field_t<Db, FieldSpec>& e)
|
||||
template<typename T>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
return os << e.value();
|
||||
}
|
||||
}
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_boolean_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
using boolean = detail::boolean;
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_boolean_t>
|
||||
{
|
||||
template<typename T>
|
||||
logical_and_t<Base, wrap_operand_t<T>> operator and(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
logical_or_t<Base, wrap_operand_t<T>> operator or(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
logical_not_t<Base> operator not() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct result_field_t<boolean, Db, FieldSpec>: public result_field_methods_t<result_field_t<boolean, Db, FieldSpec>>
|
||||
{
|
||||
static_assert(std::is_same<value_type_of<FieldSpec>, boolean>::value, "field type mismatch");
|
||||
using _cpp_value_type = typename boolean::_cpp_value_type;
|
||||
|
||||
result_field_t():
|
||||
_is_valid(false),
|
||||
_is_null(true),
|
||||
_value(false)
|
||||
{}
|
||||
|
||||
void _validate()
|
||||
{
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
void _invalidate()
|
||||
{
|
||||
_is_valid = false;
|
||||
_is_null = true;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
bool _is_trivial() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
|
||||
return value() == false;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (_is_null)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
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 Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<boolean, Db, FieldSpec>& e)
|
||||
{
|
||||
return serialize(e, os);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
83
include/sqlpp11/boolean_expression.h
Normal file
83
include/sqlpp11/boolean_expression.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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_BOOLEAN_EXPRESSION_H
|
||||
#define SQLPP_BOOLEAN_EXPRESSION_H
|
||||
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/interpretable.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename Database>
|
||||
struct boolean_expression_t
|
||||
{
|
||||
using _traits = make_traits<boolean, tag::is_expression>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
template<typename Expression>
|
||||
boolean_expression_t(Expression expression):
|
||||
_expression(expression)
|
||||
{
|
||||
static_assert(is_expression_t<Expression>::value, "boolean_expression requires a boolean expression argument");
|
||||
static_assert(is_boolean_t<Expression>::value, "boolean_expression requires a boolean expression argument");
|
||||
}
|
||||
|
||||
boolean_expression_t(const boolean_expression_t&) = default;
|
||||
boolean_expression_t(boolean_expression_t&&) = default;
|
||||
boolean_expression_t& operator=(const boolean_expression_t&) = default;
|
||||
boolean_expression_t& operator=(boolean_expression_t&&) = default;
|
||||
~boolean_expression_t() = default;
|
||||
|
||||
interpretable_t<Database> _expression;
|
||||
};
|
||||
|
||||
template<typename Database, typename T>
|
||||
boolean_expression_t<Database> boolean_expression(const Database&, T t)
|
||||
{
|
||||
return {t};
|
||||
}
|
||||
|
||||
template<typename Database, typename T>
|
||||
boolean_expression_t<Database> boolean_expression(T t)
|
||||
{
|
||||
return {t};
|
||||
}
|
||||
|
||||
template<typename Context, typename Database>
|
||||
struct serializer_t<Context, boolean_expression_t<Database>>
|
||||
{
|
||||
using T = boolean_expression_t<Database>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
return serialize(t._expression);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -33,10 +33,10 @@
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename Flag, typename Expr>
|
||||
struct count_t: public sqlpp::detail::integral::template expression_operators<count_t<Flag, Expr>>,
|
||||
struct count_t: public sqlpp::integral::template expression_operators<count_t<Flag, Expr>>,
|
||||
public alias_operators<count_t<Flag, Expr>>
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
|
||||
using _traits = make_traits<::sqlpp::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_named_expression>;
|
||||
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'");
|
||||
|
@ -57,7 +57,7 @@ namespace sqlpp
|
||||
template<template<typename, typename...> class Target, typename First, typename T>
|
||||
struct copy_tuple_args_impl
|
||||
{
|
||||
static_assert(wrong_t<T>::value, "copy_tuple_args must be called with a tuple");
|
||||
static_assert(wrong_t<copy_tuple_args_impl>::value, "copy_tuple_args must be called with a tuple");
|
||||
};
|
||||
|
||||
template<template<typename First, typename...> class Target, typename First, typename... Args>
|
||||
|
@ -73,7 +73,7 @@ namespace sqlpp
|
||||
template<typename E, typename SET>
|
||||
struct is_element_of
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<E, SET>::value, "SET has to be a type set");
|
||||
static_assert(::sqlpp::wrong_t<is_element_of>::value, "SET has to be a type set");
|
||||
};
|
||||
|
||||
template<typename E, typename... Elements>
|
||||
@ -85,7 +85,7 @@ namespace sqlpp
|
||||
template<typename L, typename R>
|
||||
struct joined_set
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<L, R>::value, "L and R have to be type sets");
|
||||
static_assert(::sqlpp::wrong_t<joined_set>::value, "L and R have to be type sets");
|
||||
};
|
||||
|
||||
template<typename... LElements, typename... RElements>
|
||||
@ -100,7 +100,7 @@ namespace sqlpp
|
||||
template<typename L, typename R>
|
||||
struct is_superset_of
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<L, R>::value, "L and R have to be type sets");
|
||||
static_assert(::sqlpp::wrong_t<is_superset_of>::value, "L and R have to be type sets");
|
||||
};
|
||||
|
||||
template<typename... LElements, typename... RElements>
|
||||
@ -118,7 +118,7 @@ namespace sqlpp
|
||||
template<typename L, typename R>
|
||||
struct is_disjunct_from
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<L, R>::value, "invalid argument for is_disjunct_from");
|
||||
static_assert(::sqlpp::wrong_t<is_disjunct_from>::value, "invalid argument for is_disjunct_from");
|
||||
};
|
||||
|
||||
template<typename... LElements, typename... RElements>
|
||||
@ -174,7 +174,7 @@ namespace sqlpp
|
||||
template<typename... T>
|
||||
struct make_joined_set
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<T...>::value, "invalid argument for joined set");
|
||||
static_assert(::sqlpp::wrong_t<make_joined_set>::value, "invalid argument for joined set");
|
||||
};
|
||||
|
||||
template<>
|
||||
@ -197,7 +197,7 @@ namespace sqlpp
|
||||
template<typename Minuend, typename Subtrahend>
|
||||
struct make_difference_set
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<Minuend, Subtrahend>::value, "invalid argument for difference set");
|
||||
static_assert(::sqlpp::wrong_t<make_difference_set>::value, "invalid argument for difference set");
|
||||
};
|
||||
|
||||
template<typename... Minuends, typename... Subtrahends>
|
||||
@ -214,14 +214,14 @@ namespace sqlpp
|
||||
template<typename Lhs, typename Rhs>
|
||||
struct make_intersect_set
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<Lhs, Rhs>::value, "invalid argument for intersect set");
|
||||
static_assert(::sqlpp::wrong_t<make_intersect_set>::value, "invalid argument for intersect set");
|
||||
};
|
||||
|
||||
template<typename... LhsElements, typename... RhsElements>
|
||||
struct make_intersect_set<type_set<LhsElements...>, type_set<RhsElements...>>
|
||||
{
|
||||
template<typename E>
|
||||
using is_in_both = is_element_of<E, make_type_set_t<LhsElements..., RhsElements...>>;
|
||||
using is_in_both = all_t<is_element_of<E, type_set<LhsElements...>>::value, is_element_of<E, type_set<RhsElements...>>::value>;
|
||||
using type = typename make_type_set_if<is_in_both, LhsElements...>::type;
|
||||
};
|
||||
|
||||
@ -232,7 +232,7 @@ namespace sqlpp
|
||||
template<template<typename> class Transformation, typename T>
|
||||
struct transform_set
|
||||
{
|
||||
static_assert(::sqlpp::wrong_t<T>::value, "invalid argument for transform_set");
|
||||
static_assert(::sqlpp::wrong_t<transform_set>::value, "invalid argument for transform_set");
|
||||
};
|
||||
|
||||
template<template<typename> class Transformation, typename... E>
|
||||
|
@ -30,6 +30,8 @@
|
||||
#include <sqlpp11/alias.h>
|
||||
#include <sqlpp11/boolean.h>
|
||||
#include <sqlpp11/tvin.h>
|
||||
#include <sqlpp11/rhs_is_null.h>
|
||||
#include <sqlpp11/rhs_is_trivial.h>
|
||||
#include <sqlpp11/noop.h>
|
||||
#include <sqlpp11/expression_fwd.h>
|
||||
#include <sqlpp11/serializer.h>
|
||||
@ -38,7 +40,7 @@
|
||||
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>>,
|
||||
struct binary_expression_t<Lhs, op::equal_to, Rhs>: public ::sqlpp::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::is_expression>;
|
||||
@ -70,7 +72,8 @@ namespace sqlpp
|
||||
{
|
||||
context << "(";
|
||||
serialize(t._lhs, context);
|
||||
if (rhs_is_null(t))
|
||||
if ((trivial_value_is_null_t<typename T::_lhs_t>::value and rhs_is_trivial(t))
|
||||
or rhs_is_null(t))
|
||||
{
|
||||
context << " IS NULL";
|
||||
}
|
||||
@ -85,7 +88,7 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
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>>,
|
||||
struct binary_expression_t<Lhs, op::not_equal_to, Rhs>: public ::sqlpp::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::is_expression>;
|
||||
@ -117,7 +120,8 @@ namespace sqlpp
|
||||
{
|
||||
context << "(";
|
||||
serialize(t._lhs, context);
|
||||
if (rhs_is_null(t))
|
||||
if ((trivial_value_is_null_t<typename T::_lhs_t>::value and rhs_is_trivial(t))
|
||||
or rhs_is_null(t))
|
||||
{
|
||||
context << " IS NOT NULL";
|
||||
}
|
||||
@ -132,7 +136,7 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
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>>,
|
||||
struct unary_expression_t<op::logical_not, Rhs>: public ::sqlpp::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::is_expression>;
|
||||
@ -161,7 +165,7 @@ namespace sqlpp
|
||||
context << "(";
|
||||
if (trivial_value_is_null_t<Rhs>::value)
|
||||
{
|
||||
serialize(t._lhs, context);
|
||||
serialize(t._rhs, context);
|
||||
context << " IS NULL ";
|
||||
}
|
||||
else
|
||||
@ -170,6 +174,8 @@ namespace sqlpp
|
||||
serialize(t._rhs, context);
|
||||
}
|
||||
context << ")";
|
||||
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -29,64 +29,61 @@
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct boolean;
|
||||
struct integral;
|
||||
struct floating_point;
|
||||
}
|
||||
struct boolean;
|
||||
struct integral;
|
||||
struct floating_point;
|
||||
|
||||
namespace op
|
||||
{
|
||||
struct less
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
static constexpr const char* _name = "<";
|
||||
};
|
||||
|
||||
struct less_equal
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
static constexpr const char* _name = "<=";
|
||||
};
|
||||
|
||||
struct equal_to
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
};
|
||||
|
||||
struct not_equal_to
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
};
|
||||
|
||||
struct greater_equal
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
static constexpr const char* _name = ">=";
|
||||
};
|
||||
|
||||
struct greater
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
static constexpr const char* _name = ">";
|
||||
};
|
||||
|
||||
struct logical_or
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
static constexpr const char* _name = " OR ";
|
||||
};
|
||||
|
||||
struct logical_and
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
static constexpr const char* _name = " AND ";
|
||||
};
|
||||
|
||||
struct logical_not
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean>;
|
||||
using _traits = make_traits<::sqlpp::boolean>;
|
||||
};
|
||||
|
||||
template<typename ValueType>
|
||||
@ -112,13 +109,13 @@ namespace sqlpp
|
||||
|
||||
struct divides
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::floating_point>;
|
||||
using _traits = make_traits<::sqlpp::floating_point>;
|
||||
static constexpr const char* _name = "/";
|
||||
};
|
||||
|
||||
struct modulus
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::integral>;
|
||||
using _traits = make_traits<::sqlpp::integral>;
|
||||
static constexpr const char* _name = "%";
|
||||
};
|
||||
|
||||
|
@ -31,271 +31,241 @@
|
||||
#include <sqlpp11/basic_expression_operators.h>
|
||||
#include <sqlpp11/type_traits.h>
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/result_field.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace detail
|
||||
// floating_point value type
|
||||
struct floating_point
|
||||
{
|
||||
using _traits = make_traits<floating_point, ::sqlpp::tag::is_floating_point, ::sqlpp::tag::is_value_type>;
|
||||
using _tag = ::sqlpp::tag::is_floating_point;
|
||||
using _cpp_value_type = double;
|
||||
|
||||
// floating_point value type
|
||||
struct floating_point
|
||||
struct _parameter_t
|
||||
{
|
||||
using _traits = make_traits<floating_point, ::sqlpp::tag::is_floating_point, ::sqlpp::tag::is_expression>;
|
||||
using _tag = ::sqlpp::tag::is_floating_point;
|
||||
using _cpp_value_type = double;
|
||||
using _value_type = floating_point;
|
||||
|
||||
struct _parameter_t
|
||||
_parameter_t():
|
||||
_value(0),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
_parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
using _value_type = floating_point;
|
||||
_value = value;
|
||||
_is_null = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t():
|
||||
_value(0),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
_parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
_value = value;
|
||||
_is_null = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t& operator=(const std::nullptr_t&)
|
||||
{
|
||||
_value = 0;
|
||||
_is_null = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
const _cpp_value_type& value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
operator _cpp_value_type() const { return _value; }
|
||||
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
target._bind_floating_point_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
private:
|
||||
_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t;
|
||||
|
||||
// I am SO waiting for concepts lite!
|
||||
template<typename Field, typename Enable = void>
|
||||
struct field_methods_t
|
||||
{
|
||||
static constexpr bool _null_is_trivial = true;
|
||||
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct field_methods_t<
|
||||
_result_field_t<Db, FieldSpec>,
|
||||
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
|
||||
and column_spec_can_be_null_t<FieldSpec>::value
|
||||
and not null_is_trivial_value_t<FieldSpec>::value>::type>
|
||||
{
|
||||
static constexpr bool _null_is_trivial = false;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
|
||||
{
|
||||
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
|
||||
|
||||
using _traits = make_traits<integral,
|
||||
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _provided_outer_tables = detail::type_set<>;
|
||||
using _required_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
|
||||
};
|
||||
|
||||
_result_field_t():
|
||||
_is_valid(false),
|
||||
_is_null(true),
|
||||
_value(0)
|
||||
{}
|
||||
|
||||
void _validate()
|
||||
{
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
void _invalidate()
|
||||
{
|
||||
_is_valid = false;
|
||||
_is_null = true;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (_is_null)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_numeric_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
|
||||
_parameter_t& operator=(const std::nullptr_t&)
|
||||
{
|
||||
template<typename T>
|
||||
plus_t<Base, floating_point, wrap_operand_t<T>> operator +(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
_value = 0;
|
||||
_is_null = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
minus_t<Base, floating_point, wrap_operand_t<T>> operator -(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
const _cpp_value_type& value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
operator _cpp_value_type() const { return _value; }
|
||||
|
||||
template<typename T>
|
||||
multiplies_t<Base, floating_point, wrap_operand_t<T>> operator *(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
unary_plus_t<floating_point, Base> operator +() const
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
target._bind_floating_point_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
unary_minus_t<floating_point, Base> operator -() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
template<typename T>
|
||||
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, floating_point, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, floating_point, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, floating_point, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
};
|
||||
private:
|
||||
_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const floating_point::_result_field_t<Db, FieldSpec>& e)
|
||||
template<typename T>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
return os << e.value();
|
||||
}
|
||||
}
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_numeric_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
using floating_point = detail::floating_point;
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
|
||||
{
|
||||
template<typename T>
|
||||
plus_t<Base, floating_point, wrap_operand_t<T>> operator +(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
minus_t<Base, floating_point, wrap_operand_t<T>> operator -(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
multiplies_t<Base, floating_point, wrap_operand_t<T>> operator *(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
|
||||
return { *static_cast<const Base*>(this), rhs{t} };
|
||||
}
|
||||
|
||||
unary_plus_t<floating_point, Base> operator +() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
|
||||
unary_minus_t<floating_point, Base> operator -() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
template<typename T>
|
||||
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, floating_point, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, floating_point, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, floating_point, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct result_field_t<floating_point, Db, FieldSpec>: public result_field_methods_t<result_field_t<floating_point, Db, FieldSpec>>
|
||||
{
|
||||
static_assert(std::is_same<value_type_of<FieldSpec>, floating_point>::value, "field type mismatch");
|
||||
using _cpp_value_type = typename floating_point::_cpp_value_type;
|
||||
|
||||
result_field_t():
|
||||
_is_valid(false),
|
||||
_is_null(true),
|
||||
_value(0)
|
||||
{}
|
||||
|
||||
void _validate()
|
||||
{
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
void _invalidate()
|
||||
{
|
||||
_is_valid = false;
|
||||
_is_null = true;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
bool _is_trivial() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
|
||||
return value() == 0;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (_is_null)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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 Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<floating_point, Db, FieldSpec>& e)
|
||||
{
|
||||
return serialize(e, os);
|
||||
}
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include <sqlpp11/avg.h>
|
||||
#include <sqlpp11/sum.h>
|
||||
#include <sqlpp11/verbatim_table.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
||||
#include <sqlpp11/value_or_null.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@ -99,6 +100,18 @@ namespace sqlpp
|
||||
return { context.str() };
|
||||
}
|
||||
|
||||
template<typename Expression>
|
||||
auto is_null(Expression e) -> decltype(e.is_null())
|
||||
{
|
||||
return e.is_null();
|
||||
}
|
||||
|
||||
template<typename Expression>
|
||||
auto is_not_null(Expression e) -> decltype(e.is_not_null())
|
||||
{
|
||||
return e.is_not_null();
|
||||
}
|
||||
|
||||
template<typename Container>
|
||||
struct value_list_t // to be used in .in() method
|
||||
{
|
||||
|
@ -33,284 +33,257 @@
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/value_type.h>
|
||||
#include <sqlpp11/assignment.h>
|
||||
#include <sqlpp11/result_field.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace detail
|
||||
// integral value type
|
||||
struct integral
|
||||
{
|
||||
using _traits = make_traits<integral, ::sqlpp::tag::is_integral, ::sqlpp::tag::is_value_type>;
|
||||
using _tag = ::sqlpp::tag::is_integral;
|
||||
using _cpp_value_type = int64_t;
|
||||
|
||||
// integral value type
|
||||
struct integral
|
||||
struct _parameter_t
|
||||
{
|
||||
using _traits = make_traits<integral, ::sqlpp::tag::is_integral, ::sqlpp::tag::is_expression>;
|
||||
using _tag = ::sqlpp::tag::is_integral;
|
||||
using _cpp_value_type = int64_t;
|
||||
using _value_type = integral;
|
||||
|
||||
struct _parameter_t
|
||||
_parameter_t():
|
||||
_value(0),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
explicit _parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
using _value_type = integral;
|
||||
_value = value;
|
||||
_is_null = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t():
|
||||
_value(0),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
explicit _parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
_value = value;
|
||||
_is_null = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set_null()
|
||||
{
|
||||
_value = 0;
|
||||
_is_null = true;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
const _cpp_value_type& value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
operator _cpp_value_type() const { return _value; }
|
||||
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
target._bind_integral_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
private:
|
||||
_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t;
|
||||
|
||||
// I am SO waiting for concepts lite!
|
||||
template<typename Field, typename Enable = void>
|
||||
struct field_methods_t
|
||||
{
|
||||
static constexpr bool _null_is_trivial = true;
|
||||
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct field_methods_t<
|
||||
_result_field_t<Db, FieldSpec>,
|
||||
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
|
||||
and column_spec_can_be_null_t<FieldSpec>::value
|
||||
and not null_is_trivial_value_t<FieldSpec>::value>::type>
|
||||
{
|
||||
static constexpr bool _null_is_trivial = false;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
|
||||
{
|
||||
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
|
||||
|
||||
using _traits = make_traits<integral,
|
||||
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _provided_outer_tables = detail::type_set<>;
|
||||
using _required_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
|
||||
};
|
||||
|
||||
_result_field_t():
|
||||
_is_valid(false),
|
||||
_is_null(true),
|
||||
_value(0)
|
||||
{}
|
||||
|
||||
void _invalidate()
|
||||
{
|
||||
_is_valid = false;
|
||||
_is_null = true;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
void _validate()
|
||||
{
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (_is_null)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_numeric_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
|
||||
void set_null()
|
||||
{
|
||||
template<typename T>
|
||||
plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator +(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
_value = 0;
|
||||
_is_null = true;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator -(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
const _cpp_value_type& value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
operator _cpp_value_type() const { return _value; }
|
||||
|
||||
template<typename T>
|
||||
multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator *(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
modulus_t<Base, wrap_operand_t<T>> operator %(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
unary_plus_t<integral, Base> operator +() const
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
target._bind_integral_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
unary_minus_t<integral, Base> operator -() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
template<typename T>
|
||||
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
};
|
||||
private:
|
||||
_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const integral::_result_field_t<Db, FieldSpec>& e)
|
||||
template<typename T>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
return os << e.value();
|
||||
}
|
||||
}
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_numeric_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
using tinyint = detail::integral;
|
||||
using smallint = detail::integral;
|
||||
using integer = detail::integral;
|
||||
using bigint = detail::integral;
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_numeric_t>
|
||||
{
|
||||
template<typename T>
|
||||
plus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator +(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
minus_t<Base, value_type_t<T>, wrap_operand_t<T>> operator -(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>> operator *(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
divides_t<Base, wrap_operand_t<T>> operator /(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
modulus_t<Base, wrap_operand_t<T>> operator %(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
unary_plus_t<integral, Base> operator +() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
|
||||
unary_minus_t<integral, Base> operator -() const
|
||||
{
|
||||
return { *static_cast<const Base*>(this) };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
template<typename T>
|
||||
auto operator +=(T t) const -> assignment_t<Base, plus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator -=(T t) const -> assignment_t<Base, minus_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator /=(T t) const -> assignment_t<Base, divides_t<Base, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto operator *=(T t) const -> assignment_t<Base, multiplies_t<Base, value_type_t<T>, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct result_field_t<integral, Db, FieldSpec>: public result_field_methods_t<result_field_t<integral, Db, FieldSpec>>
|
||||
{
|
||||
static_assert(std::is_same<value_type_of<FieldSpec>, integral>::value, "field type mismatch");
|
||||
using _cpp_value_type = typename integral::_cpp_value_type;
|
||||
|
||||
result_field_t():
|
||||
_is_valid(false),
|
||||
_is_null(true),
|
||||
_value(0)
|
||||
{}
|
||||
|
||||
void _invalidate()
|
||||
{
|
||||
_is_valid = false;
|
||||
_is_null = true;
|
||||
_value = 0;
|
||||
}
|
||||
|
||||
void _validate()
|
||||
{
|
||||
_is_valid = true;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
bool _is_trivial() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
|
||||
return value() == 0;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (_is_null)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
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 Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<integral, Db, FieldSpec>& e)
|
||||
{
|
||||
return serialize(e, os);
|
||||
}
|
||||
|
||||
using tinyint = integral;
|
||||
using smallint = integral;
|
||||
using integer = integral;
|
||||
using bigint = integral;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -36,7 +36,7 @@ namespace sqlpp
|
||||
{
|
||||
static void _(const T& t, Context& context)
|
||||
{
|
||||
static_assert(wrong_t<Context, T>::value, "missing interpreter specialization");
|
||||
static_assert(wrong_t<interpreter_t>::value, "missing interpreter specialization");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -140,10 +140,10 @@ namespace sqlpp
|
||||
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");
|
||||
}
|
||||
static void _check_consistency()
|
||||
{
|
||||
static_assert(wrong_t<_methods_t>::value, "into() required");
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
auto into(Args... args)
|
||||
|
@ -50,14 +50,14 @@ namespace sqlpp
|
||||
struct left_outer_join_t
|
||||
{
|
||||
template<typename Lhs, typename Rhs>
|
||||
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
||||
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
||||
|
||||
static constexpr const char* _name = " LEFT OUTER ";
|
||||
};
|
||||
struct right_outer_join_t
|
||||
{
|
||||
template<typename Lhs, typename Rhs>
|
||||
using _provided_outer_tables = detail::make_joined_set_t<provided_tables_of<Lhs>, provided_outer_tables_of<Rhs>>;
|
||||
using _provided_outer_tables = detail::make_joined_set_t<provided_outer_tables_of<Lhs>, provided_tables_of<Rhs>>;
|
||||
|
||||
static constexpr const char* _name = " RIGHT OUTER ";
|
||||
};
|
||||
|
@ -117,7 +117,7 @@ namespace sqlpp
|
||||
|
||||
static void _(const T& t, Context& context)
|
||||
{
|
||||
static_assert(wrong_t<Columns...>::value, "multi_column must be used with an alias");
|
||||
static_assert(wrong_t<serializer_t>::value, "multi_column must be used with an alias");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace sqlpp
|
||||
{
|
||||
struct null_t
|
||||
{
|
||||
using _traits = make_traits<no_value_t, tag::is_expression>;
|
||||
using _traits = make_traits<no_value_t, tag::is_expression, tag::is_sql_null>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
};
|
||||
|
||||
|
@ -83,7 +83,7 @@ namespace sqlpp
|
||||
auto parameter(const ValueType&, const AliasProvider&)
|
||||
-> parameter_t<wrap_operand_t<ValueType>, AliasProvider>
|
||||
{
|
||||
static_assert(is_expression_t<ValueType>::value, "first argument is not a value type");
|
||||
static_assert(is_value_type_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");
|
||||
return {};
|
||||
}
|
||||
|
@ -37,7 +37,7 @@ namespace sqlpp
|
||||
template<typename T>
|
||||
struct parameter_list_t
|
||||
{
|
||||
static_assert(wrong_t<T>::value, "Template parameter for parameter_list_t has to be a tuple");
|
||||
static_assert(wrong_t<parameter_list_t>::value, "Template parameter for parameter_list_t has to be a tuple");
|
||||
};
|
||||
|
||||
template<typename... Parameter>
|
||||
|
62
include/sqlpp11/result_field.h
Normal file
62
include/sqlpp11/result_field.h
Normal file
@ -0,0 +1,62 @@
|
||||
/*
|
||||
* 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_RESULT_FIELD_H
|
||||
#define SQLPP_RESULT_FIELD_H
|
||||
|
||||
#include <sqlpp11/wrong.h>
|
||||
#include <sqlpp11/result_field_methods.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename ValueType, typename Db, typename Field>
|
||||
struct result_field_t
|
||||
{
|
||||
static_assert(wrong_t<result_field_t>::value, "Missing specialization for result_field_t");
|
||||
};
|
||||
|
||||
template<typename Context, typename ValueType, typename Db, typename FieldSpec>
|
||||
struct serializer_t<Context, result_field_t<ValueType, Db, FieldSpec>>
|
||||
{
|
||||
using T = result_field_t<ValueType, Db, FieldSpec>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
if (t.is_null() and not null_is_trivial_value_t<T>::value)
|
||||
{
|
||||
context << "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
context << t.value();
|
||||
}
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
#endif
|
97
include/sqlpp11/result_field_methods.h
Normal file
97
include/sqlpp11/result_field_methods.h
Normal file
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* 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_RESULT_FIELD_METHODS_H
|
||||
#define SQLPP_RESULT_FIELD_METHODS_H
|
||||
|
||||
#include <utility>
|
||||
#include <sqlpp11/basic_expression_operators.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Field>
|
||||
struct get_field_spec_impl
|
||||
{
|
||||
static_assert(wrong_t<get_field_spec_impl>::value, "Invalid argument for get_field_spec");
|
||||
};
|
||||
|
||||
template<template<typename, typename, typename> class Field, typename ValueType, typename Db, typename FieldSpec>
|
||||
struct get_field_spec_impl<Field<ValueType, Db, FieldSpec>>
|
||||
{
|
||||
using type = FieldSpec;
|
||||
};
|
||||
|
||||
template<typename Field>
|
||||
using get_field_spec_t = typename get_field_spec_impl<Field>::type;
|
||||
}
|
||||
|
||||
template<typename Field, typename Enable = void>
|
||||
struct result_field_methods_base_t
|
||||
{
|
||||
using _field_spec_t = detail::get_field_spec_t<Field>;
|
||||
static constexpr bool _null_is_trivial = true;
|
||||
operator cpp_value_type_of<_field_spec_t>() const { return static_cast<const Field&>(*this).value(); }
|
||||
};
|
||||
|
||||
template<template<typename, typename, typename> class Field, typename ValueType, typename Db, typename FieldSpec>
|
||||
struct result_field_methods_base_t<
|
||||
Field<ValueType, Db, FieldSpec>,
|
||||
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
|
||||
and column_spec_can_be_null_t<FieldSpec>::value
|
||||
and not null_is_trivial_value_t<FieldSpec>::value>::type>
|
||||
{
|
||||
using _field_spec_t = FieldSpec;
|
||||
static constexpr bool _null_is_trivial = false;
|
||||
};
|
||||
|
||||
template<typename Field>
|
||||
struct result_field_methods_t: public result_field_methods_base_t<Field>,
|
||||
public alias_operators<Field>
|
||||
{
|
||||
using _base_t = result_field_methods_base_t<Field>;
|
||||
using _field_spec_t = typename _base_t::_field_spec_t;
|
||||
|
||||
using _traits = make_traits<value_type_of<_field_spec_t>,
|
||||
tag::is_result_field,
|
||||
tag::is_expression,
|
||||
tag_if<tag::null_is_trivial_value, _base_t::_null_is_trivial>>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _provided_outer_tables = detail::type_set<>;
|
||||
using _required_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
using _can_be_null = column_spec_can_be_null_t<_field_spec_t>;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
@ -41,9 +41,9 @@ namespace sqlpp
|
||||
|
||||
template<typename Db, std::size_t index, typename FieldSpec>
|
||||
struct result_field:
|
||||
public FieldSpec::_name_t::template _member_t<typename value_type_of<FieldSpec>::template _result_field_t<Db, FieldSpec>>
|
||||
public FieldSpec::_name_t::template _member_t<result_field_t<value_type_of<FieldSpec>, Db, FieldSpec>>
|
||||
{
|
||||
using _field = typename FieldSpec::_name_t::template _member_t<typename value_type_of<FieldSpec>::template _result_field_t<Db, FieldSpec>>;
|
||||
using _field = typename FieldSpec::_name_t::template _member_t<result_field_t<value_type_of<FieldSpec>, Db, FieldSpec>>;
|
||||
|
||||
result_field() = default;
|
||||
|
||||
@ -184,12 +184,12 @@ namespace sqlpp
|
||||
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>;
|
||||
struct _field_spec_t
|
||||
{
|
||||
using _traits = make_traits<detail::text, tag::is_noop, tag::can_be_null, tag::null_is_trivial_value>;
|
||||
using _traits = make_traits<text, tag::is_noop, tag::can_be_null, tag::null_is_trivial_value>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
struct _name_t {};
|
||||
};
|
||||
using _field_type = detail::text::_result_field_t<Db, _field_spec_t>;
|
||||
using _field_type = result_field_t<text, Db, _field_spec_t>;
|
||||
static constexpr size_t _last_static_index = _impl::_last_index;
|
||||
|
||||
bool _is_valid;
|
||||
|
@ -32,7 +32,7 @@
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename T, typename Enable = void>
|
||||
struct is_trivial_t
|
||||
struct rhs_is_null_t
|
||||
{
|
||||
static constexpr bool _(const T&)
|
||||
{
|
||||
@ -41,27 +41,29 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_trivial_t<T, typename std::enable_if<std::is_member_function_pointer<decltype(&T::_is_trivial)>::value, void>::type>
|
||||
struct rhs_is_null_t<T, typename std::enable_if<is_tvin_t<T>::value, void>::type>
|
||||
{
|
||||
static bool _(const T& t)
|
||||
{
|
||||
return t._is_trivial();
|
||||
return t._is_null();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool is_trivial(const T& t)
|
||||
struct rhs_is_null_t<T, typename std::enable_if<is_result_field_t<T>::value, void>::type>
|
||||
{
|
||||
return is_trivial_t<T>::_(t);
|
||||
}
|
||||
static bool _(const T& t)
|
||||
{
|
||||
return t.is_null();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Expression>
|
||||
constexpr bool rhs_is_null(const Expression& e)
|
||||
{
|
||||
return (((trivial_value_is_null_t<typename Expression::_lhs_t>::value or is_tvin_t<typename Expression::_rhs_t>::value)
|
||||
and is_trivial(e._rhs))
|
||||
or (std::is_same<typename Expression::_rhs_t, null_t>::value));
|
||||
return rhs_is_null_t<typename std::decay<Expression>::type::_rhs_t>::_(e._rhs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
91
include/sqlpp11/rhs_is_trivial.h
Normal file
91
include/sqlpp11/rhs_is_trivial.h
Normal file
@ -0,0 +1,91 @@
|
||||
/*
|
||||
* 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_RHS_IS_TRIVIAL_H
|
||||
#define SQLPP_RHS_IS_TRIVIAL_H
|
||||
|
||||
#include <sqlpp11/tvin.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename T, typename Enable = void>
|
||||
struct rhs_is_trivial_t
|
||||
{
|
||||
static constexpr bool _(const T&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct rhs_is_trivial_t<T, typename std::enable_if<is_wrapped_value_t<T>::value, void>::type>
|
||||
{
|
||||
static bool _(const T& t)
|
||||
{
|
||||
return t._is_trivial();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct rhs_is_trivial_t<T, typename std::enable_if<is_tvin_t<T>::value, void>::type>
|
||||
{
|
||||
static bool _(const T& t)
|
||||
{
|
||||
return t._is_trivial();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct rhs_is_trivial_t<T, typename std::enable_if<is_result_field_t<T>::value, void>::type>
|
||||
{
|
||||
static bool _(const T& t)
|
||||
{
|
||||
if (null_is_trivial_value_t<T>::value)
|
||||
{
|
||||
return t._is_trivial();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (t.is_null())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return t._is_trivial();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Expression>
|
||||
constexpr bool rhs_is_trivial(const Expression& e)
|
||||
{
|
||||
return rhs_is_trivial_t<typename std::decay<Expression>::type::_rhs_t>::_(e._rhs);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@ -36,7 +36,7 @@ namespace sqlpp
|
||||
{
|
||||
static void _(const T& t, Context& context)
|
||||
{
|
||||
static_assert(wrong_t<Context, T>::value, "missing serializer specialization");
|
||||
static_assert(wrong_t<serializer_t>::value, "missing serializer specialization");
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -35,6 +35,7 @@
|
||||
#include <sqlpp11/select.h>
|
||||
#include <sqlpp11/functions.h>
|
||||
#include <sqlpp11/transaction.h>
|
||||
#include <sqlpp11/boolean_expression.h>
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -112,7 +112,7 @@ namespace sqlpp
|
||||
::sqlpp::detail::make_intersect_set_t<
|
||||
required_tables_of<_result_type_provider>,
|
||||
provided_outer_tables_of<statement_policies_t>
|
||||
>::size::value>;
|
||||
>::size::value != 0>;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -32,223 +32,222 @@
|
||||
#include <sqlpp11/exception.h>
|
||||
#include <sqlpp11/concat.h>
|
||||
#include <sqlpp11/like.h>
|
||||
#include <sqlpp11/result_field.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace detail
|
||||
// text value type
|
||||
struct text
|
||||
{
|
||||
// text value type
|
||||
struct text
|
||||
using _traits = make_traits<text, ::sqlpp::tag::is_text, ::sqlpp::tag::is_value_type>;
|
||||
using _tag = ::sqlpp::tag::is_text;
|
||||
using _cpp_value_type = std::string;
|
||||
|
||||
struct _parameter_t
|
||||
{
|
||||
using _traits = make_traits<text, ::sqlpp::tag::is_text, ::sqlpp::tag::is_expression>;
|
||||
using _tag = ::sqlpp::tag::is_text;
|
||||
using _cpp_value_type = std::string;
|
||||
using _value_type = text;
|
||||
|
||||
struct _parameter_t
|
||||
_parameter_t():
|
||||
_value(""),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
_parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
using _value_type = integral;
|
||||
_value = value;
|
||||
_is_null = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t():
|
||||
_value(""),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
_parameter_t(const _cpp_value_type& value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
_parameter_t& operator=(const _cpp_value_type& value)
|
||||
{
|
||||
_value = value;
|
||||
_is_null = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
_parameter_t& operator=(const std::nullptr_t&)
|
||||
{
|
||||
_value = "";
|
||||
_is_null = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
operator _cpp_value_type() const { return value(); }
|
||||
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
target._bind_text_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
private:
|
||||
_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t;
|
||||
|
||||
// I am SO waiting for concepts lite!
|
||||
template<typename Field, typename Enable = void>
|
||||
struct field_methods_t
|
||||
{
|
||||
static constexpr bool _null_is_trivial = true;
|
||||
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct field_methods_t<
|
||||
_result_field_t<Db, FieldSpec>,
|
||||
typename std::enable_if<enforce_null_result_treatment_t<Db>::value
|
||||
and column_spec_can_be_null_t<FieldSpec>::value
|
||||
and not null_is_trivial_value_t<FieldSpec>::value>::type>
|
||||
{
|
||||
static constexpr bool _null_is_trivial = false;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct _result_field_t: public field_methods_t<_result_field_t<Db, FieldSpec>>
|
||||
{
|
||||
using _field_methods_t = field_methods_t<_result_field_t<Db, FieldSpec>>;
|
||||
|
||||
using _traits = make_traits<integral,
|
||||
tag_if<tag::null_is_trivial_value, _field_methods_t::_null_is_trivial>>;
|
||||
|
||||
struct _recursive_traits
|
||||
{
|
||||
using _parameters = std::tuple<>;
|
||||
using _provided_tables = detail::type_set<>;
|
||||
using _provided_outer_tables = detail::type_set<>;
|
||||
using _required_tables = detail::type_set<>;
|
||||
using _extra_tables = detail::type_set<>;
|
||||
using _can_be_null = column_spec_can_be_null_t<FieldSpec>;
|
||||
};
|
||||
|
||||
_result_field_t():
|
||||
_is_valid(false),
|
||||
_value_ptr(nullptr),
|
||||
_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 (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _value_ptr == nullptr;
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (not _value_ptr)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return std::string(_value_ptr, _value_ptr + _len);
|
||||
}
|
||||
|
||||
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>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_text_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_text_t>
|
||||
_parameter_t& operator=(const std::nullptr_t&)
|
||||
{
|
||||
template<typename T>
|
||||
concat_t<Base, wrap_operand_t<T>> operator+(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
_value = "";
|
||||
_is_null = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
bool is_null() const
|
||||
{
|
||||
return _is_null;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
like_t<Base, wrap_operand_t<T>> like(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()");
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
};
|
||||
operator _cpp_value_type() const { return value(); }
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
template<typename Target>
|
||||
void _bind(Target& target, size_t index) const
|
||||
{
|
||||
template<typename T>
|
||||
auto operator +=(T t) const -> assignment_t<Base, concat_t<Base, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
target._bind_text_parameter(index, &_value, _is_null);
|
||||
}
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
};
|
||||
private:
|
||||
_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const text::_result_field_t<Db, FieldSpec>& e)
|
||||
|
||||
template<typename T>
|
||||
struct _is_valid_operand
|
||||
{
|
||||
static constexpr bool value =
|
||||
is_expression_t<T>::value // expressions are OK
|
||||
and is_text_t<T>::value // the correct value type is required, of course
|
||||
;
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct expression_operators: public basic_expression_operators<Base, is_text_t>
|
||||
{
|
||||
template<typename T>
|
||||
concat_t<Base, wrap_operand_t<T>> operator+(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
like_t<Base, wrap_operand_t<T>> like(T t) const
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid argument for like()");
|
||||
|
||||
return { *static_cast<const Base*>(this), {t} };
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base>
|
||||
struct column_operators
|
||||
{
|
||||
template<typename T>
|
||||
auto operator +=(T t) const -> assignment_t<Base, concat_t<Base, wrap_operand_t<T>>>
|
||||
{
|
||||
using rhs = wrap_operand_t<T>;
|
||||
static_assert(_is_valid_operand<rhs>::value, "invalid rhs assignment operand");
|
||||
|
||||
return { *static_cast<const Base*>(this), { *static_cast<const Base*>(this), rhs{t} } };
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
struct result_field_t<text, Db, FieldSpec>: public result_field_methods_t<result_field_t<text, Db, FieldSpec>>
|
||||
{
|
||||
static_assert(std::is_same<value_type_of<FieldSpec>, text>::value, "field type mismatch");
|
||||
using _cpp_value_type = typename text::_cpp_value_type;
|
||||
|
||||
result_field_t():
|
||||
_is_valid(false),
|
||||
_value_ptr(nullptr),
|
||||
_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 (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
return _value_ptr == nullptr;
|
||||
}
|
||||
|
||||
bool _is_trivial() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing is_null in non-existing row");
|
||||
|
||||
return value() == "";
|
||||
}
|
||||
|
||||
_cpp_value_type value() const
|
||||
{
|
||||
if (not _is_valid)
|
||||
throw exception("accessing value in non-existing row");
|
||||
|
||||
if (not _value_ptr)
|
||||
{
|
||||
if (enforce_null_result_treatment_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
throw exception("accessing value of NULL field");
|
||||
}
|
||||
else
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
return std::string(_value_ptr, _value_ptr + _len);
|
||||
}
|
||||
|
||||
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 Context, typename Db, typename FieldSpec>
|
||||
struct serializer_t<Context, result_field_t<text, Db, FieldSpec>>
|
||||
{
|
||||
using T = result_field_t<text, Db, FieldSpec>;
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
if (t.is_null() and not null_is_trivial_value_t<T>::value)
|
||||
{
|
||||
context << "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
context << '\'' << context.escape(t.value()) << '\'';
|
||||
}
|
||||
return context;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Db, typename FieldSpec>
|
||||
inline std::ostream& operator<<(std::ostream& os, const result_field_t<text, Db, FieldSpec>& e)
|
||||
{
|
||||
if (e.is_null() and not null_is_trivial_value_t<FieldSpec>::value)
|
||||
{
|
||||
return os << "NULL";
|
||||
}
|
||||
else
|
||||
{
|
||||
return os << e.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using text = detail::text;
|
||||
using blob = detail::text;
|
||||
using varchar = detail::text;
|
||||
using char_ = detail::text;
|
||||
using blob = text;
|
||||
using varchar = text;
|
||||
using char_ = text;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
@ -63,7 +63,7 @@ namespace sqlpp
|
||||
|
||||
static Context& _(const T& t, Context& context)
|
||||
{
|
||||
static_assert(wrong_t<Context, Operand>::value, "tvin may only be used with operators =, == and !=");
|
||||
static_assert(wrong_t<serializer_t>::value, "tvin may only be used with operators =, == and !=");
|
||||
}
|
||||
};
|
||||
|
||||
@ -108,6 +108,11 @@ namespace sqlpp
|
||||
return _value._is_trivial();
|
||||
}
|
||||
|
||||
bool _is_null() const
|
||||
{
|
||||
return _value._is_trivial();
|
||||
}
|
||||
|
||||
_operand_t _value;
|
||||
};
|
||||
|
||||
@ -150,8 +155,7 @@ namespace sqlpp
|
||||
auto tvin(Operand operand) -> tvin_arg_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)");
|
||||
static_assert(not std::is_same<_operand_t, Operand>::value or is_result_field_t<Operand>::value, "tvin() used with invalid type (only string and primitive types allowed)");
|
||||
return {{operand}};
|
||||
}
|
||||
|
||||
|
@ -71,6 +71,8 @@ namespace sqlpp
|
||||
template<typename T>\
|
||||
using name##_t = typename detail::name##_impl<T>::type;
|
||||
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_value_type);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_sql_null);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_boolean);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_integral);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_floating_point);
|
||||
@ -85,6 +87,7 @@ namespace sqlpp
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_expression);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_alias);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_select_flag);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(is_result_field);
|
||||
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(must_not_insert);
|
||||
SQLPP_VALUE_TRAIT_GENERATOR(must_not_update);
|
||||
@ -191,6 +194,9 @@ namespace sqlpp
|
||||
template<typename T>
|
||||
using value_type_of = typename detail::value_type_of_impl<T>::type;
|
||||
|
||||
template<typename T>
|
||||
using cpp_value_type_of = typename value_type_of<T>::_cpp_value_type;
|
||||
|
||||
template<typename T>
|
||||
using required_tables_of = typename detail::required_table_of_impl<T>::type;
|
||||
|
||||
|
86
include/sqlpp11/value_or_null.h
Normal file
86
include/sqlpp11/value_or_null.h
Normal file
@ -0,0 +1,86 @@
|
||||
/*
|
||||
* 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_VALUE_OR_NULL_H
|
||||
#define SQLPP_VALUE_OR_NULL_H
|
||||
|
||||
#include <sqlpp11/parameter.h>
|
||||
#include <sqlpp11/parameter_list.h>
|
||||
#include <sqlpp11/column_types.h>
|
||||
#include <sqlpp11/in.h>
|
||||
#include <sqlpp11/value_type.h>
|
||||
#include <sqlpp11/exists.h>
|
||||
#include <sqlpp11/any.h>
|
||||
#include <sqlpp11/some.h>
|
||||
#include <sqlpp11/count.h>
|
||||
#include <sqlpp11/min.h>
|
||||
#include <sqlpp11/max.h>
|
||||
#include <sqlpp11/avg.h>
|
||||
#include <sqlpp11/sum.h>
|
||||
#include <sqlpp11/verbatim_table.h> // Csaba Csoma suggests: unsafe_sql instead of verbatim
|
||||
#include <sqlpp11/value_or_null.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
template<typename ValueType>
|
||||
struct value_or_null_t
|
||||
{
|
||||
using _cpp_value_type = typename ValueType::_cpp_value_type;
|
||||
|
||||
using _traits = make_traits<ValueType, tag::is_expression>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
value_or_null_t(_cpp_value_type value):
|
||||
_value(value),
|
||||
_is_null(false)
|
||||
{}
|
||||
|
||||
value_or_null_t(const null_t&):
|
||||
_value(),
|
||||
_is_null(true)
|
||||
{}
|
||||
|
||||
typename ValueType::_cpp_value_type _value;
|
||||
bool _is_null;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
auto value_or_null(T t) -> value_or_null_t<value_type_of<wrap_operand_t<T>>>
|
||||
{
|
||||
static_assert(is_wrapped_value_t<wrap_operand_t<T>>::value, "value_or_null() is to be called with non-sql-type like int, or string or null");
|
||||
return { t };
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
auto value_or_null(null_t t) -> value_or_null_t<ValueType>
|
||||
{
|
||||
static_assert(is_value_type_t<ValueType>::value, "value_or_null() is to be called with non-sql-type like int, or string");
|
||||
return { t };
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -224,7 +224,7 @@ namespace sqlpp
|
||||
|
||||
static void _check_consistency()
|
||||
{
|
||||
static_assert(Required ? wrong_t<Policies>::value : true, "where expression required, e.g. where(true)");
|
||||
static_assert(Required ? wrong_t<_methods_t>::value : true, "where expression required, e.g. where(true)");
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
|
@ -33,17 +33,14 @@
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
struct boolean;
|
||||
struct integral;
|
||||
struct floating_point;
|
||||
struct text;
|
||||
}
|
||||
struct boolean;
|
||||
struct integral;
|
||||
struct floating_point;
|
||||
struct text;
|
||||
|
||||
struct boolean_operand
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _traits = make_traits<::sqlpp::boolean, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
using _value_t = bool;
|
||||
@ -81,7 +78,7 @@ namespace sqlpp
|
||||
|
||||
struct integral_operand
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _traits = make_traits<::sqlpp::integral, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
using _value_t = int64_t;
|
||||
@ -120,7 +117,7 @@ namespace sqlpp
|
||||
|
||||
struct floating_point_operand
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::floating_point, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _traits = make_traits<::sqlpp::floating_point, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
using _value_t = double;
|
||||
@ -158,7 +155,7 @@ namespace sqlpp
|
||||
|
||||
struct text_operand
|
||||
{
|
||||
using _traits = make_traits<::sqlpp::detail::text, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _traits = make_traits<::sqlpp::text, ::sqlpp::tag::is_expression, ::sqlpp::tag::is_wrapped_value>;
|
||||
using _recursive_traits = make_recursive_traits<>;
|
||||
|
||||
using _value_t = std::string;
|
||||
@ -219,7 +216,7 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct wrap_operand<T, typename std::enable_if<std::is_convertible<T, std::string>::value>::type>
|
||||
struct wrap_operand<T, typename std::enable_if<std::is_convertible<T, std::string>::value and not is_result_field_t<T>::value>::type>
|
||||
{
|
||||
using type = text_operand;
|
||||
};
|
||||
|
17
test_constraints/CMakeLists.txt
Normal file
17
test_constraints/CMakeLists.txt
Normal file
@ -0,0 +1,17 @@
|
||||
include_directories(${CMAKE_BINARY_DIR}/tests)
|
||||
|
||||
add_executable(
|
||||
no_conversion_operator_if_null_not_trivial
|
||||
EXCLUDE_FROM_ALL
|
||||
no_conversion_operator_if_null_not_trivial.cpp
|
||||
)
|
||||
|
||||
add_custom_command(OUTPUT no_conversion_operator_if_null_not_trivial.out
|
||||
COMMAND ${CMAKE_MAKE_PROGRAM} no_conversion_operator_if_null_not_trivial > ${CMAKE_CURRENT_BINARY_DIR}/no_conversion_operator_if_null_not_trivial.out 2>&1 || true
|
||||
COMMAND grep "int i = row.alpha" ${CMAKE_CURRENT_BINARY_DIR}/no_conversion_operator_if_null_not_trivial.out > /dev/null
|
||||
DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/no_conversion_operator_if_null_not_trivial.cpp
|
||||
COMMENT "no_conversion_operator_if_null_not_trivial"
|
||||
)
|
||||
|
||||
add_custom_target(test_constraints DEPENDS no_conversion_operator_if_null_not_trivial.out COMMAND true)
|
||||
|
@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "Sample.h"
|
||||
#include "MockDb.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
EnforceDb edb {};
|
||||
|
||||
int main()
|
||||
{
|
||||
test::TabBar t;
|
||||
|
||||
static_assert(sqlpp::can_be_null_t<decltype(t.alpha)>::value, "t.alpha can be null");
|
||||
static_assert(not sqlpp::null_is_trivial_value_t<decltype(t.alpha)>::value, "t.alpha does not say null_is_trivial");
|
||||
|
||||
for (const auto& row : edb(select(all_of(t)).from(t).where(true)))
|
||||
{
|
||||
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
|
||||
static_assert(not sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha does not interpret null_is_trivial");
|
||||
|
||||
int i = row.alpha;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
42
tests/BooleanExpressionTest.cpp
Normal file
42
tests/BooleanExpressionTest.cpp
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include "Sample.h"
|
||||
#include "MockDb.h"
|
||||
#include <sqlpp11/sqlpp11.h>
|
||||
|
||||
MockDb db = {};
|
||||
|
||||
int main()
|
||||
{
|
||||
test::TabBar t;
|
||||
|
||||
auto x = boolean_expression(db, t.alpha == 7);
|
||||
x = boolean_expression(db, t.gamma);
|
||||
x = sqlpp::boolean_expression<MockDb>(t.beta.like("%cheesecake"));
|
||||
|
||||
return 0;
|
||||
}
|
@ -6,6 +6,7 @@ macro (build_and_run arg)
|
||||
add_test(${arg} ${arg})
|
||||
endmacro ()
|
||||
|
||||
build_and_run(BooleanExpressionTest)
|
||||
build_and_run(InterpretTest)
|
||||
build_and_run(InsertTest)
|
||||
build_and_run(RemoveTest)
|
||||
|
@ -135,6 +135,12 @@ int main()
|
||||
using TI = decltype(t.alpha.is_null());
|
||||
using TF = decltype(f.omega.is_null());
|
||||
using TT = decltype(t.beta.is_null());
|
||||
using TTI = decltype(is_null(t.alpha));
|
||||
using TTF = decltype(is_null(f.omega));
|
||||
using TTT = decltype(is_null(t.beta));
|
||||
static_assert(std::is_same<TI, TTI>::value, "type requirement");
|
||||
static_assert(std::is_same<TF, TTF>::value, "type requirement");
|
||||
static_assert(std::is_same<TT, TTT>::value, "type requirement");
|
||||
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement");
|
||||
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
|
||||
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
|
||||
@ -154,6 +160,12 @@ int main()
|
||||
using TI = decltype(t.alpha.is_not_null());
|
||||
using TF = decltype(f.omega.is_not_null());
|
||||
using TT = decltype(t.beta.is_not_null());
|
||||
using TTI = decltype(is_not_null(t.alpha));
|
||||
using TTF = decltype(is_not_null(f.omega));
|
||||
using TTT = decltype(is_not_null(t.beta));
|
||||
static_assert(std::is_same<TI, TTI>::value, "type requirement");
|
||||
static_assert(std::is_same<TF, TTF>::value, "type requirement");
|
||||
static_assert(std::is_same<TT, TTT>::value, "type requirement");
|
||||
static_assert(sqlpp::is_named_expression_t<TI>::value, "type requirement");
|
||||
static_assert(sqlpp::is_boolean_t<TI>::value, "type requirement");
|
||||
static_assert(not sqlpp::is_numeric_t<TI>::value, "type requirement");
|
||||
@ -356,6 +368,30 @@ int main()
|
||||
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
||||
}
|
||||
|
||||
// test value_or_null
|
||||
{
|
||||
using TB = decltype(sqlpp::value_or_null(true));
|
||||
using TI = decltype(sqlpp::value_or_null(7));
|
||||
using TF = decltype(sqlpp::value_or_null(5.6));
|
||||
using TT = decltype(sqlpp::value_or_null("hallo"));
|
||||
using TBN = decltype(sqlpp::value_or_null<sqlpp::boolean>(sqlpp::null));
|
||||
using TIN = decltype(sqlpp::value_or_null<sqlpp::integral>(sqlpp::null));
|
||||
using TFN = decltype(sqlpp::value_or_null<sqlpp::floating_point>(sqlpp::null));
|
||||
using TTN = decltype(sqlpp::value_or_null<sqlpp::text>(sqlpp::null));
|
||||
static_assert(std::is_same<TB, TBN>::value, "type_requirement");
|
||||
static_assert(std::is_same<TI, TIN>::value, "type_requirement");
|
||||
static_assert(std::is_same<TF, TFN>::value, "type_requirement");
|
||||
static_assert(std::is_same<TT, TTN>::value, "type_requirement");
|
||||
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement");
|
||||
static_assert(sqlpp::is_boolean_t<TB>::value, "type requirement");
|
||||
static_assert(not sqlpp::is_named_expression_t<TB>::value, "type requirement");
|
||||
static_assert(sqlpp::is_integral_t<TI>::value, "type requirement");
|
||||
static_assert(not sqlpp::is_named_expression_t<TI>::value, "type requirement");
|
||||
static_assert(sqlpp::is_floating_point_t<TF>::value, "type requirement");
|
||||
static_assert(not sqlpp::is_named_expression_t<TT>::value, "type requirement");
|
||||
static_assert(sqlpp::is_text_t<TT>::value, "type requirement");
|
||||
}
|
||||
|
||||
// test verbatim
|
||||
{
|
||||
using TB = decltype(sqlpp::verbatim<sqlpp::boolean>("1"));
|
||||
@ -389,5 +425,20 @@ int main()
|
||||
static_assert(sqlpp::is_alias_t<T>::value, "type requirement");
|
||||
}
|
||||
|
||||
// test tvin
|
||||
{
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin(1)), sqlpp::tvin_arg_t<sqlpp::integral_operand>>::value, "integral values are accepted and wrapped") ;
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin(false)), sqlpp::tvin_arg_t<sqlpp::boolean_operand>>::value, "bool values are accepted and wrapped") ;
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin(0.17)), sqlpp::tvin_arg_t<sqlpp::floating_point_operand>>::value, "float values are accepted and wrapped") ;
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin("test")), sqlpp::tvin_arg_t<sqlpp::text_operand>>::value, "text values are accepted and wrapped") ;
|
||||
|
||||
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
|
||||
{
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin(row.alpha)), sqlpp::tvin_arg_t<decltype(row.alpha)>>::value, "result fields are accepted and not wrapped") ;
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin(row.beta)), sqlpp::tvin_arg_t<decltype(row.beta)>>::value, "result fields are accepted and not wrapped") ;
|
||||
static_assert(std::is_same<decltype(sqlpp::tvin(row.gamma)), sqlpp::tvin_arg_t<decltype(row.gamma)>>::value, "result fields are accepted and not wrapped") ;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ int main()
|
||||
|
||||
// functions
|
||||
serialize(sqlpp::value(7), printer).str();
|
||||
serialize(sqlpp::verbatim<sqlpp::detail::integral>("irgendwas integrales"), printer).str();
|
||||
serialize(sqlpp::verbatim<sqlpp::integral>("irgendwas integrales"), printer).str();
|
||||
serialize(sqlpp::value_list(std::vector<int>({1,2,3,4,5,6,8})), printer).str();
|
||||
serialize(exists(select(t.alpha).from(t)), printer).str();
|
||||
serialize(any(select(t.alpha).from(t)), printer).str();
|
||||
@ -156,6 +156,7 @@ int main()
|
||||
serialize(s, printer).str();
|
||||
}
|
||||
|
||||
|
||||
// distinct aggregate
|
||||
serialize(count(sqlpp::distinct, t.alpha % 7), printer).str();
|
||||
serialize(avg(sqlpp::distinct, t.alpha - 7), printer).str();
|
||||
@ -164,5 +165,12 @@ int main()
|
||||
serialize(select(all_of(t)).from(t).where(true), printer).str();
|
||||
serialize(select(all_of(t)).from(t).where(false), printer).str();
|
||||
|
||||
for (const auto& row : db(select(all_of(t)).from(t).where(true)))
|
||||
{
|
||||
serialize(row.alpha, printer);
|
||||
serialize(row.beta, printer);
|
||||
serialize(row.gamma, printer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -104,24 +104,32 @@ struct MockDbT: public sqlpp::connection
|
||||
template<typename Insert>
|
||||
size_t insert(const Insert& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Update>
|
||||
size_t update(const Update& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Remove>
|
||||
size_t remove(const Remove& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Select>
|
||||
result_t select(const Select& s)
|
||||
result_t select(const Select& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return {};
|
||||
}
|
||||
|
||||
@ -138,24 +146,32 @@ struct MockDbT: public sqlpp::connection
|
||||
template<typename Insert>
|
||||
_prepared_statement_t prepare_insert(Insert& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename PreparedInsert>
|
||||
size_t run_prepared_insert(const PreparedInsert& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
template<typename Select>
|
||||
_prepared_statement_t prepare_select(Select& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
template<typename PreparedSelect>
|
||||
result_t run_prepared_select(PreparedSelect& x)
|
||||
{
|
||||
_serializer_context_t context;
|
||||
::sqlpp::serialize(x, context);
|
||||
return {};
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,20 @@ int main()
|
||||
{
|
||||
static_assert(sqlpp::can_be_null_t<decltype(row.alpha)>::value, "row.alpha can be null");
|
||||
static_assert(sqlpp::null_is_trivial_value_t<decltype(row.alpha)>::value, "row.alpha interprets null_is_trivial");
|
||||
static_assert(std::is_member_function_pointer<decltype(&decltype(row.alpha)::is_null)>::value, "Yikes");
|
||||
using T = sqlpp::wrap_operand_t<decltype(row.alpha)>;
|
||||
static_assert(sqlpp::can_be_null_t<T>::value, "row.alpha can be null");
|
||||
static_assert(sqlpp::is_result_field_t<T>::value, "result_fields are not wrapped");
|
||||
|
||||
bool x = sqlpp::rhs_is_null(t.alpha == row.alpha);
|
||||
bool y = sqlpp::rhs_is_trivial(t.alpha == row.alpha);
|
||||
std::cerr << x << std::endl;
|
||||
std::cerr << y << std::endl;
|
||||
|
||||
for (const auto& sub : db(select(all_of(t)).from(t).where(t.alpha == row.alpha)))
|
||||
{
|
||||
std::cerr << sub.alpha << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
sqlpp::select((t.alpha + 1).as(t.alpha)).flags(sqlpp::all).from(t);
|
||||
|
@ -64,6 +64,11 @@ int main()
|
||||
std::cout << a << ", " << b << ", " << g << std::endl;
|
||||
}
|
||||
|
||||
for (const auto& row : db(select(all_of(t), all_of(f)).from(t.join(f).on(t.alpha > f.omega and not t.gamma)).where(true)))
|
||||
{
|
||||
std::cout << row.alpha << std::endl;
|
||||
}
|
||||
|
||||
auto stat = sqlpp::select().columns(all_of(t)).flags(sqlpp::all).from(t).extra_tables(f,t).where(t.alpha > 0).group_by(t.alpha).order_by(t.gamma.asc()).having(t.gamma).limit(7).offset(19);
|
||||
|
||||
auto s = dynamic_select(db).dynamic_columns(all_of(t)).dynamic_flags().dynamic_from(t).extra_tables(f,t).dynamic_where().dynamic_group_by(t.alpha).dynamic_order_by().dynamic_having(t.gamma).dynamic_limit().dynamic_offset();
|
||||
|
Loading…
Reference in New Issue
Block a user