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

Using column's can_be_null and connector's enforce_validity

This commit is contained in:
rbock 2014-07-25 01:01:42 +02:00
parent e21fdb4829
commit e5f055ac19
6 changed files with 134 additions and 79 deletions

View File

@ -28,7 +28,6 @@
#define SQLPP_BOOLEAN_H #define SQLPP_BOOLEAN_H
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <ostream> #include <ostream>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
@ -97,7 +96,26 @@ namespace sqlpp
}; };
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_entry_t;
// I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_entry_t<Db, FieldSpec>,
typename std::enable_if<connector_enforce_result_validity_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
};
template<typename Db, typename FieldSpec>
struct _result_entry_t: public field_methods_t<_result_entry_t<Db, FieldSpec>>
{ {
_result_entry_t(): _result_entry_t():
_is_valid(false), _is_valid(false),
@ -119,33 +137,30 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _is_null; return _is_null;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _is_null and not null_is_trivial_value_t<FieldSpec>::value and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
if (_is_null)
{ {
assert(_is_valid); if (connector_enforce_result_validity_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
assert(not null_value); {
throw exception("accessing value of NULL field");
} }
else else
{ {
if (not _is_valid) return false;
throw exception("accessing value in non-existing row"); }
if (null_value)
throw exception("accessing value of NULL field");
} }
return _value; return _value;
} }
operator _cpp_value_type() const { return value(); }
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
{ {

View File

@ -50,7 +50,6 @@ namespace sqlpp
namespace detail namespace detail
{ {
#warning: Need to transport the "can be null" information via field_t to result_entry structs
template<typename Select, typename NamedExpr> template<typename Select, typename NamedExpr>
struct make_field_t_impl struct make_field_t_impl
{ {
@ -60,7 +59,7 @@ namespace sqlpp
using type = field_t<typename NamedExpr::_name_t, using type = field_t<typename NamedExpr::_name_t,
value_type_of<NamedExpr>, value_type_of<NamedExpr>,
detail::any_t<_can_be_null, _depends_on_outer_table>::value, detail::any_t<_can_be_null, _depends_on_outer_table>::value,
null_is_trivial_value<NamedExpr>::value>; null_is_trivial_value_t<NamedExpr>::value>;
}; };
template<typename Select, typename AliasProvider, typename... NamedExprs> template<typename Select, typename AliasProvider, typename... NamedExprs>

View File

@ -28,7 +28,6 @@
#define SQLPP_FLOATING_POINT_H #define SQLPP_FLOATING_POINT_H
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -96,7 +95,26 @@ namespace sqlpp
}; };
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_entry_t;
// I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_entry_t<Db, FieldSpec>,
typename std::enable_if<connector_enforce_result_validity_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
};
template<typename Db, typename FieldSpec>
struct _result_entry_t: public field_methods_t<_result_entry_t<Db, FieldSpec>>
{ {
using _value_type = integral; using _value_type = integral;
@ -120,33 +138,30 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _is_null; return _is_null;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _is_null and not null_is_trivial_value_t<FieldSpec>::value and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
if (_is_null)
{ {
assert(_is_valid); if (connector_enforce_result_validity_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
assert(not null_value); {
throw exception("accessing value of NULL field");
} }
else else
{ {
if (not _is_valid) return 0;
throw exception("accessing value in non-existing row"); }
if (null_value)
throw exception("accessing value of NULL field");
} }
return _value; return _value;
} }
operator _cpp_value_type() const { return value(); }
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
{ {

View File

@ -28,7 +28,6 @@
#define SQLPP_INTEGRAL_H #define SQLPP_INTEGRAL_H
#include <cstdlib> #include <cstdlib>
#include <cassert>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -98,7 +97,26 @@ namespace sqlpp
}; };
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_entry_t;
// I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_entry_t<Db, FieldSpec>,
typename std::enable_if<connector_enforce_result_validity_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
};
template<typename Db, typename FieldSpec>
struct _result_entry_t: public field_methods_t<_result_entry_t<Db, FieldSpec>>
{ {
using _value_type = integral; using _value_type = integral;
@ -122,33 +140,30 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _is_null; return _is_null;
} }
_cpp_value_type value() const _cpp_value_type value() const
{ {
const bool null_value = _is_null and not null_is_trivial_value_t<FieldSpec>::value and not connector_null_result_is_trivial_value_t<Db>::value; if (not _is_valid)
if (connector_assert_result_validity_t<Db>::value) throw exception("accessing value in non-existing row");
if (_is_null)
{ {
assert(_is_valid); if (connector_enforce_result_validity_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
assert(not null_value); {
throw exception("accessing value of NULL field");
} }
else else
{ {
if (not _is_valid) return 0;
throw exception("accessing value in non-existing row"); }
if (null_value)
throw exception("accessing value of NULL field");
} }
return _value; return _value;
} }
operator _cpp_value_type() const { return value(); }
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)
{ {

View File

@ -27,7 +27,6 @@
#ifndef SQLPP_TEXT_H #ifndef SQLPP_TEXT_H
#define SQLPP_TEXT_H #define SQLPP_TEXT_H
#include <cassert>
#include <sqlpp11/basic_expression_operators.h> #include <sqlpp11/basic_expression_operators.h>
#include <sqlpp11/type_traits.h> #include <sqlpp11/type_traits.h>
#include <sqlpp11/exception.h> #include <sqlpp11/exception.h>
@ -96,7 +95,26 @@ namespace sqlpp
}; };
template<typename Db, typename FieldSpec> template<typename Db, typename FieldSpec>
struct _result_entry_t struct _result_entry_t;
// I am SO waiting for concepts lite!
template<typename Field, typename Enable = void>
struct field_methods_t
{
operator _cpp_value_type() const { return static_cast<const Field&>(*this).value(); }
};
template<typename Db, typename FieldSpec>
struct field_methods_t<
_result_entry_t<Db, FieldSpec>,
typename std::enable_if<connector_enforce_result_validity_t<Db>::value
and column_spec_can_be_null_t<FieldSpec>::value
and not null_is_trivial_value_t<FieldSpec>::value>::type>
{
};
template<typename Db, typename FieldSpec>
struct _result_entry_t: public field_methods_t<_result_entry_t<Db, FieldSpec>>
{ {
_result_entry_t(): _result_entry_t():
_is_valid(false), _is_valid(false),
@ -121,35 +139,29 @@ namespace sqlpp
bool is_null() const bool is_null() const
{ {
if (connector_assert_result_validity_t<Db>::value) if (not _is_valid)
assert(_is_valid);
else if (not _is_valid)
throw exception("accessing is_null in non-existing row"); throw exception("accessing is_null in non-existing row");
return _value_ptr == nullptr; return _value_ptr == nullptr;
} }
_cpp_value_type value() const _cpp_value_type value() const
{
const bool null_value = _value_ptr == nullptr and not null_is_trivial_value_t<FieldSpec>::value and not connector_null_result_is_trivial_value_t<Db>::value;
if (connector_assert_result_validity_t<Db>::value)
{
assert(_is_valid);
assert(not null_value);
}
else
{ {
if (not _is_valid) if (not _is_valid)
throw exception("accessing value in non-existing row"); throw exception("accessing value in non-existing row");
if (null_value)
if (not _value_ptr)
{
if (connector_enforce_result_validity_t<Db>::value and not null_is_trivial_value_t<FieldSpec>::value)
{
throw exception("accessing value of NULL field"); throw exception("accessing value of NULL field");
} }
if (_value_ptr)
return std::string(_value_ptr, _value_ptr + _len);
else else
{
return ""; return "";
} }
}
operator _cpp_value_type() const { return value(); } return std::string(_value_ptr, _value_ptr + _len);
}
template<typename Target> template<typename Target>
void _bind(Target& target, size_t i) void _bind(Target& target, size_t i)

View File

@ -174,8 +174,7 @@ namespace sqlpp
SQLPP_TYPE_TRAIT_GENERATOR(requires_braces); SQLPP_TYPE_TRAIT_GENERATOR(requires_braces);
SQLPP_CONNECTOR_TRAIT_GENERATOR(null_result_is_trivial_value); SQLPP_CONNECTOR_TRAIT_GENERATOR(enforce_result_validity);
SQLPP_CONNECTOR_TRAIT_GENERATOR(assert_result_validity);
template<typename Database> template<typename Database>
using is_database = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type; using is_database = typename std::conditional<std::is_same<Database, void>::value, std::false_type, std::true_type>::type;