0
0
mirror of https://github.com/rbock/sqlpp11.git synced 2024-11-16 04:47:18 +08:00

Replaced implicit trivial_value_is_null tag for columns with explicit tvin method

This isn't database vendor specific, but library vendor specific, as I
used this implicit behaviour quite a lot, but it is utterly confusing
when mixed with prepared statements. Explicit is better here.
This commit is contained in:
rbock 2014-01-14 22:54:07 +01:00
parent fa18ce5476
commit 9335a62087
16 changed files with 196 additions and 105 deletions

View File

@ -63,26 +63,24 @@ namespace sqlpp
using _value_type = boolean; using _value_type = boolean;
_parameter_t(const std::true_type&): _parameter_t(const std::true_type&):
_trivial_value_is_null(true),
_value(false), _value(false),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t(const std::false_type&): _parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(false), _value(false),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = (false);
return *this; return *this;
} }
@ -99,8 +97,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == false; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -120,7 +116,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
signed char _value; signed char _value;
bool _is_null; bool _is_null;
}; };
@ -164,8 +159,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == false; }
bool is_null() const bool is_null() const
{ {
if (not _is_valid) if (not _is_valid)

View File

@ -75,7 +75,7 @@ namespace sqlpp
-> typename std::enable_if<not std::is_same<column_t, typename std::decay<T>::type>::value, -> typename std::enable_if<not std::is_same<column_t, typename std::decay<T>::type>::value,
assignment_t<column_t, typename _value_type::template _constraint<T>::type>>::type assignment_t<column_t, typename _value_type::template _constraint<T>::type>>::type
{ {
return { *this, std::forward<T>(t) }; return { *this, {std::forward<T>(t)} };
} }
}; };

View File

@ -155,8 +155,6 @@ namespace sqlpp
static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot have a name"); static_assert(not is_multi_expression_t<Base>::value, "multi-expression cannot have a name");
return { *static_cast<const Base*>(this) }; return { *static_cast<const Base*>(this) };
} }
constexpr bool _is_trivial() const { return false; }
}; };
} }

View File

@ -31,6 +31,7 @@
#include <sqlpp11/boolean.h> #include <sqlpp11/boolean.h>
#include <sqlpp11/noop.h> #include <sqlpp11/noop.h>
#include <sqlpp11/expression_fwd.h> #include <sqlpp11/expression_fwd.h>
#include <sqlpp11/tvin.h>
#include <sqlpp11/interpreter.h> #include <sqlpp11/interpreter.h>
#include <sqlpp11/detail/wrap_operand.h> #include <sqlpp11/detail/wrap_operand.h>
#include <sqlpp11/detail/serialize_tuple.h> #include <sqlpp11/detail/serialize_tuple.h>
@ -42,10 +43,22 @@ namespace sqlpp
{ {
using _is_assignment = std::true_type; using _is_assignment = std::true_type;
using column_type = Lhs; using column_type = Lhs;
using value_type = Rhs; using value_type = tvin_wrap_t<Rhs>;
// FIXME: Need parameter_tuple back
assignment_t(Lhs lhs, Rhs rhs):
_lhs(lhs),
_rhs(rhs)
{}
assignment_t(const assignment_t&) = default;
assignment_t(assignment_t&&) = default;
assignment_t& operator=(const assignment_t&) = default;
assignment_t& operator=(assignment_t&&) = default;
~assignment_t() = default;
Lhs _lhs; Lhs _lhs;
Rhs _rhs; tvin_wrap_t<Rhs> _rhs;
}; };
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
@ -56,7 +69,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
interpret(t._lhs, context); interpret(t._lhs, context);
if (trivial_value_is_null_t<Lhs>::value and t._rhs._is_trivial()) if (t._rhs._is_trivial())
{ {
context << "=NULL"; context << "=NULL";
} }
@ -75,9 +88,9 @@ namespace sqlpp
{ {
using _value_type = detail::boolean; using _value_type = detail::boolean;
equal_t(Lhs lhs, Rhs rhs): equal_t(Lhs lhs, Rhs rhs):
_lhs(lhs), _lhs(lhs),
_rhs(rhs) _rhs(rhs)
{} {}
equal_t(const equal_t&) = default; equal_t(const equal_t&) = default;
@ -87,7 +100,7 @@ namespace sqlpp
~equal_t() = default; ~equal_t() = default;
Lhs _lhs; Lhs _lhs;
Rhs _rhs; tvin_wrap_t<Rhs> _rhs;
}; };
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
@ -99,9 +112,9 @@ namespace sqlpp
{ {
context << "("; context << "(";
interpret(t._lhs, context); interpret(t._lhs, context);
if (trivial_value_is_null_t<Lhs>::value and t._rhs._is_trivial()) if (t._rhs._is_trivial())
{ {
context << "IS NULL"; context << " IS NULL";
} }
else else
{ {
@ -130,7 +143,7 @@ namespace sqlpp
~not_equal_t() = default; ~not_equal_t() = default;
Lhs _lhs; Lhs _lhs;
Rhs _rhs; tvin_wrap_t<Rhs> _rhs;
}; };
template<typename Context, typename Lhs, typename Rhs> template<typename Context, typename Lhs, typename Rhs>
@ -142,9 +155,9 @@ namespace sqlpp
{ {
context << "("; context << "(";
interpret(t._lhs, context); interpret(t._lhs, context);
if (trivial_value_is_null_t<Lhs>::value and t._rhs._is_trivial()) if (t._rhs._is_trivial())
{ {
context << "IS NOT NULL"; context << " IS NOT NULL";
} }
else else
{ {
@ -182,16 +195,8 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "("; context << "(";
if (trivial_value_is_null_t<Lhs>::value and t._lhs._is_trivial()) context << "NOT ";
{ interpret(t._lhs, context);
interpret(t._lhs, context);
context << "IS NULL";
}
else
{
context << "NOT ";
interpret(t._lhs, context);
}
context << ")"; context << ")";
return context; return context;
} }

View File

@ -52,27 +52,20 @@ namespace sqlpp
{ {
using _value_type = integral; using _value_type = integral;
_parameter_t(const std::true_type&): _parameter_t():
_trivial_value_is_null(true),
_value(0), _value(0),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{}
_parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(0),
_is_null(_trivial_value_is_null and _is_trivial())
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = false;
return *this; return *this;
} }
@ -89,8 +82,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -110,7 +101,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
_cpp_value_type _value; _cpp_value_type _value;
bool _is_null; bool _is_null;
}; };
@ -156,8 +146,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
if (not _is_valid) if (not _is_valid)

View File

@ -48,7 +48,6 @@ namespace sqlpp
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()"); static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in having()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
static_assert(not _parameter_list_t::_contains_trivial_value_is_null_t::value, "must not use trivial_value_is_null in parameters of having expression, use where_parameter() instead of parameter() to turn off automatic conversion");
template<typename E> template<typename E>
void add(E&& expr) void add(E&& expr)

View File

@ -52,26 +52,24 @@ namespace sqlpp
using _value_type = integral; using _value_type = integral;
_parameter_t(const std::true_type&): _parameter_t(const std::true_type&):
_trivial_value_is_null(true),
_value(0), _value(0),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t(const std::false_type&): _parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(0), _value(0),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
explicit _parameter_t(const _cpp_value_type& value): explicit _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = false;
return *this; return *this;
} }
@ -87,8 +85,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -108,7 +104,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
_cpp_value_type _value; _cpp_value_type _value;
bool _is_null; bool _is_null;
}; };
@ -154,8 +149,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == 0; }
bool is_null() const bool is_null() const
{ {
if (not _is_valid) if (not _is_valid)

View File

@ -50,7 +50,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "LIMIT " << t._limit; context << " LIMIT " << t._limit;
return context; return context;
} }
}; };

View File

@ -50,7 +50,7 @@ namespace sqlpp
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
context << "OFFSET " << t._offset; context << " OFFSET " << t._offset;
return context; return context;
} }
}; };

View File

@ -33,16 +33,13 @@
namespace sqlpp namespace sqlpp
{ {
template<typename ValueType, typename NameType, typename TrivialValueIsNull> template<typename ValueType, typename NameType>
struct parameter_t: public ValueType::template operators<parameter_t<ValueType, NameType, TrivialValueIsNull>> struct parameter_t: public ValueType::template operators<parameter_t<ValueType, NameType>>
{ {
using _value_type = ValueType; using _value_type = ValueType;
using _is_parameter = std::true_type; using _is_parameter = std::true_type;
using _is_expression_t = std::true_type; using _is_expression_t = std::true_type;
using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>; using _instance_t = typename NameType::_name_t::template _member_t<typename ValueType::_parameter_t>;
using _trivial_value_is_null_t = TrivialValueIsNull;
static_assert(std::is_same<_trivial_value_is_null_t, std::true_type>::value or std::is_same<_trivial_value_is_null_t, std::false_type>::value, "Invalid template parameter TrivialValueIsNull");
parameter_t() parameter_t()
{} {}
@ -52,17 +49,12 @@ namespace sqlpp
parameter_t& operator=(const parameter_t&) = default; parameter_t& operator=(const parameter_t&) = default;
parameter_t& operator=(parameter_t&&) = default; parameter_t& operator=(parameter_t&&) = default;
~parameter_t() = default; ~parameter_t() = default;
constexpr bool _is_trivial() const
{
return false;
}
}; };
template<typename Context, typename ValueType, typename NameType, typename TrivialValueIsNull> template<typename Context, typename ValueType, typename NameType>
struct interpreter_t<Context, parameter_t<ValueType, NameType, TrivialValueIsNull>> struct interpreter_t<Context, parameter_t<ValueType, NameType>>
{ {
using T = parameter_t<ValueType, NameType, TrivialValueIsNull>; using T = parameter_t<ValueType, NameType>;
static Context& _(const T& t, Context& context) static Context& _(const T& t, Context& context)
{ {
@ -71,16 +63,9 @@ namespace sqlpp
} }
}; };
template<typename NamedExpr, typename TrivialValueIsNull = trivial_value_is_null_t<typename std::decay<NamedExpr>::type>>
auto parameter(NamedExpr&& namedExpr)
-> parameter_t<typename std::decay<NamedExpr>::type::_value_type, typename std::decay<NamedExpr>::type, TrivialValueIsNull>
{
return {};
}
template<typename NamedExpr> template<typename NamedExpr>
auto where_parameter(NamedExpr&& namedExpr) auto parameter(NamedExpr&& namedExpr)
-> parameter_t<typename std::decay<NamedExpr>::type::_value_type, typename std::decay<NamedExpr>::type, std::false_type> -> parameter_t<typename std::decay<NamedExpr>::type::_value_type, typename std::decay<NamedExpr>::type>
{ {
return {}; return {};
} }

View File

@ -62,10 +62,8 @@ namespace sqlpp
{ {
using _member_tuple_t = std::tuple<typename Parameter::_instance_t...>; using _member_tuple_t = std::tuple<typename Parameter::_instance_t...>;
using size = std::integral_constant<std::size_t, sizeof...(Parameter)>; using size = std::integral_constant<std::size_t, sizeof...(Parameter)>;
using _contains_trivial_value_is_null_t = detail::or_t<typename Parameter::_trivial_value_is_null_t...>;
parameter_list_t(): parameter_list_t()
Parameter::_instance_t({typename Parameter::_trivial_value_is_null_t()})...
{} {}
template<typename Target> template<typename Target>

View File

@ -52,26 +52,24 @@ namespace sqlpp
using _value_type = integral; using _value_type = integral;
_parameter_t(const std::true_type&): _parameter_t(const std::true_type&):
_trivial_value_is_null(true),
_value(""), _value(""),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t(const std::false_type&): _parameter_t(const std::false_type&):
_trivial_value_is_null(false),
_value(""), _value(""),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t(const _cpp_value_type& value): _parameter_t(const _cpp_value_type& value):
_value(value), _value(value),
_is_null(_trivial_value_is_null and _is_trivial()) _is_null(false)
{} {}
_parameter_t& operator=(const _cpp_value_type& value) _parameter_t& operator=(const _cpp_value_type& value)
{ {
_value = value; _value = value;
_is_null = (_trivial_value_is_null and _is_trivial()); _is_null = false;
return *this; return *this;
} }
@ -88,8 +86,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return value() == ""; }
bool is_null() const bool is_null() const
{ {
return _is_null; return _is_null;
@ -109,7 +105,6 @@ namespace sqlpp
} }
private: private:
bool _trivial_value_is_null;
_cpp_value_type _value; _cpp_value_type _value;
bool _is_null; bool _is_null;
}; };
@ -153,8 +148,6 @@ namespace sqlpp
os << value(); os << value();
} }
bool _is_trivial() const { return _len == 0; }
bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; } bool operator==(const _cpp_value_type& rhs) const { return value() == rhs; }
bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); } bool operator!=(const _cpp_value_type& rhs) const { return not operator==(rhs); }

135
include/sqlpp11/tvin.h Normal file
View File

@ -0,0 +1,135 @@
/*
* Copyright (c) 2013, Roland Bock
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice, this
* list of conditions and the following disclaimer in the documentation and/or
* other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef SQLPP_TVIN_H
#define SQLPP_TVIN_H
// TVIN: Trivial value is NULL
#include <sqlpp11/type_traits.h>
#include <sqlpp11/interpreter.h>
namespace sqlpp
{
template<typename T>
struct tvin_t
{
using _wrapped_t = typename wrap_operand<T>::type;
static_assert(not std::is_same<_wrapped_t, T>::value, "tvin() used with invalid type (only string and primitive types allowed)");
using _value_type = typename _wrapped_t::_value_type;
tvin_t(T t):
_value({t})
{}
tvin_t(const tvin_t&) = default;
tvin_t(tvin_t&&) = default;
tvin_t& operator=(const tvin_t&) = default;
tvin_t& operator=(tvin_t&&) = default;
~tvin_t() = default;
_wrapped_t _value;
};
template<typename Context, typename Type>
struct interpreter_t<Context, tvin_t<Type>>
{
using T = tvin_t<Type>;
static void _(const T& t, Context& context)
{
static_assert(detail::wrong<T>::value, "tvin() must not be used with anything but =, ==, != and !");
}
};
template<typename T>
struct tvin_wrap_t
{
static constexpr bool _is_trivial()
{
return false;
}
tvin_wrap_t(T t):
_value(t)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
T _value;
};
template<typename T>
struct tvin_wrap_t<tvin_t<T>>
{
bool _is_trivial() const
{
return _value._is_trivial();
};
tvin_wrap_t(tvin_t<T> t):
_value(t._value)
{}
tvin_wrap_t(const tvin_wrap_t&) = default;
tvin_wrap_t(tvin_wrap_t&&) = default;
tvin_wrap_t& operator=(const tvin_wrap_t&) = default;
tvin_wrap_t& operator=(tvin_wrap_t&&) = default;
~tvin_wrap_t() = default;
typename tvin_t<T>::_wrapped_t _value;
};
template<typename Context, typename Type>
struct interpreter_t<Context, tvin_wrap_t<Type>>
{
using T = tvin_wrap_t<Type>;
static Context& _(const T& t, Context& context)
{
if (t._is_trivial())
{
context << "NULL";
}
else
{
interpret(t._value, context);
}
return context;
}
};
template<typename T>
auto tvin(T t) -> tvin_t<typename std::decay<T>::type>
{
return {t};
}
}
#endif

View File

@ -92,7 +92,6 @@ namespace sqlpp
SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update); SQLPP_IS_COLUMN_TRAIT_GENERATOR(must_not_update);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert); SQLPP_IS_COLUMN_TRAIT_GENERATOR(require_insert);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null); SQLPP_IS_COLUMN_TRAIT_GENERATOR(can_be_null);
SQLPP_IS_COLUMN_TRAIT_GENERATOR(trivial_value_is_null);
SQLPP_TYPE_TRAIT_GENERATOR(is_table); SQLPP_TYPE_TRAIT_GENERATOR(is_table);
SQLPP_TYPE_TRAIT_GENERATOR(is_select); SQLPP_TYPE_TRAIT_GENERATOR(is_select);

View File

@ -50,7 +50,6 @@ namespace sqlpp
static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in where()"); static_assert(_valid_expressions::size::value == sizeof...(Expr), "at least one argument is not an expression in where()");
using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type; using _parameter_list_t = typename make_parameter_list_t<_parameter_tuple_t>::type;
static_assert(not _parameter_list_t::_contains_trivial_value_is_null_t::value, "must not use trivial_value_is_null in parameters of where expression, use where_parameter() instead of parameter() to turn off automatic conversion");
template<typename E> template<typename E>
void add(E&& expr) void add(E&& expr)

View File

@ -40,7 +40,12 @@ int main()
TabSample t; TabSample t;
interpret(t.alpha, printer).flush(); interpret(t.alpha, printer).flush();
interpret(t.alpha = 7, printer).flush(); interpret(t.alpha = 0, printer).flush();
interpret(t.alpha = sqlpp::tvin(0), printer).flush();
interpret(t.alpha == 0, printer).flush();
interpret(t.alpha == sqlpp::tvin(0), printer).flush();
interpret(t.alpha != 0, printer).flush();
interpret(t.gamma != sqlpp::tvin(false), printer).flush();
interpret(t.alpha == 7, printer).flush(); interpret(t.alpha == 7, printer).flush();
interpret(t.beta + "kaesekuchen", printer).flush(); interpret(t.beta + "kaesekuchen", printer).flush();
@ -58,6 +63,7 @@ int main()
interpret(insert_into(t), printer).flush(); interpret(insert_into(t), printer).flush();
interpret(insert_into(t).default_values(), printer).flush(); interpret(insert_into(t).default_values(), printer).flush();
interpret(insert_into(t).set(t.gamma = true), printer).flush(); interpret(insert_into(t).set(t.gamma = true), printer).flush();
interpret(insert_into(t).set(t.gamma = sqlpp::tvin(false)), printer).flush();
return 0; return 0;
} }