mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-16 04:47:18 +08:00
Fixed bug in field index calculation for multi_fields
This commit is contained in:
parent
ce0c344d0a
commit
a59d7ed381
@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2014, Roland Bock
|
|
||||||
* All rights reserved.
|
|
||||||
*
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer.
|
|
||||||
*
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
|
||||||
* list of conditions and the following disclaimer in the documentation and/or
|
|
||||||
* other materials provided with the distribution.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
|
||||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
|
||||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SQLPP_DETAIL_COLUMN_INDEX_SEQUENCE_H
|
|
||||||
#define SQLPP_DETAIL_COLUMN_INDEX_SEQUENCE_H
|
|
||||||
|
|
||||||
#include <type_traits>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template<std::size_t LastIndex, std::size_t... Ints>
|
|
||||||
struct column_index_sequence
|
|
||||||
{
|
|
||||||
static constexpr std::size_t last_index = LastIndex;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T, typename... Fields>
|
|
||||||
struct make_column_index_sequence_impl;
|
|
||||||
|
|
||||||
template<std::size_t LastIndex, std::size_t... Ints, typename Column, typename... Rest>
|
|
||||||
struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>, Column, Rest...>
|
|
||||||
{
|
|
||||||
using type = typename make_column_index_sequence_impl<column_index_sequence<LastIndex + 1, Ints..., LastIndex + 1>, Rest...>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t LastIndex, std::size_t... Ints, typename AliasProvider, typename... Fields, typename... Rest>
|
|
||||||
struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>, multi_field_spec_t<AliasProvider, Fields...>, Rest...>
|
|
||||||
{
|
|
||||||
using type = typename make_column_index_sequence_impl<column_index_sequence<LastIndex + sizeof...(Fields), Ints..., LastIndex + sizeof...(Fields)>, Rest...>::type;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t LastIndex, std::size_t... Ints>
|
|
||||||
struct make_column_index_sequence_impl<column_index_sequence<LastIndex, Ints...>>
|
|
||||||
{
|
|
||||||
using type = column_index_sequence<LastIndex, Ints...>;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<std::size_t StartIndex, typename... Fields>
|
|
||||||
using make_column_index_sequence = typename make_column_index_sequence_impl<column_index_sequence<StartIndex - 1>, Fields...>::type;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif
|
|
74
include/sqlpp11/detail/field_index_sequence.h
Normal file
74
include/sqlpp11/detail/field_index_sequence.h
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013-2014, Roland Bock
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without modification,
|
||||||
|
* are permitted provided that the following conditions are met:
|
||||||
|
*
|
||||||
|
* Redistributions of source code must retain the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer.
|
||||||
|
*
|
||||||
|
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||||
|
* list of conditions and the following disclaimer in the documentation and/or
|
||||||
|
* other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||||
|
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SQLPP_DETAIL_FIELD_INDEX_SEQUENCE_H
|
||||||
|
#define SQLPP_DETAIL_FIELD_INDEX_SEQUENCE_H
|
||||||
|
|
||||||
|
#include <type_traits>
|
||||||
|
#include <sqlpp11/field_spec.h>
|
||||||
|
|
||||||
|
namespace sqlpp
|
||||||
|
{
|
||||||
|
namespace detail
|
||||||
|
{
|
||||||
|
template<std::size_t NextIndex, std::size_t... Ints>
|
||||||
|
struct field_index_sequence
|
||||||
|
{
|
||||||
|
static constexpr std::size_t _next_index = NextIndex;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename... Fields>
|
||||||
|
struct make_field_index_sequence_impl
|
||||||
|
{
|
||||||
|
static_assert(wrong_t<make_field_index_sequence_impl>::value, "invalid field index sequence arguments");
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t NextIndex, std::size_t... Ints, typename NameType, typename ValueType, bool CanBeNull, bool NullIsTrivialValue, typename... Rest>
|
||||||
|
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>, field_spec_t<NameType, ValueType, CanBeNull, NullIsTrivialValue>, Rest...>
|
||||||
|
{
|
||||||
|
using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + 1, Ints..., NextIndex>, Rest...>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t NextIndex, std::size_t... Ints, typename AliasProvider, typename FieldTuple, typename... Rest>
|
||||||
|
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>, multi_field_spec_t<AliasProvider, FieldTuple>, Rest...>
|
||||||
|
{
|
||||||
|
using type = typename make_field_index_sequence_impl<field_index_sequence<NextIndex + std::tuple_size<FieldTuple>::value, Ints..., NextIndex>, Rest...>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t NextIndex, std::size_t... Ints>
|
||||||
|
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>>
|
||||||
|
{
|
||||||
|
using type = field_index_sequence<NextIndex, Ints...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::size_t StartIndex, typename... Fields>
|
||||||
|
using make_field_index_sequence = typename make_field_index_sequence_impl<field_index_sequence<StartIndex>, Fields...>::type;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
@ -30,7 +30,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <sqlpp11/field_spec.h>
|
#include <sqlpp11/field_spec.h>
|
||||||
#include <sqlpp11/text.h>
|
#include <sqlpp11/text.h>
|
||||||
#include <sqlpp11/detail/column_index_sequence.h>
|
#include <sqlpp11/detail/field_index_sequence.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -66,9 +66,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
template<std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs>
|
template<std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs>
|
||||||
struct result_field<Db, index, multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>>:
|
struct result_field<Db, index, multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>>:
|
||||||
public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, FieldSpecs...>, FieldSpecs...>>
|
public AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>
|
||||||
{
|
{
|
||||||
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_column_index_sequence<index, FieldSpecs...>, FieldSpecs...>>;
|
using _multi_field = typename AliasProvider::_name_t::template _member_t<result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>;
|
||||||
|
|
||||||
result_field() = default;
|
result_field() = default;
|
||||||
|
|
||||||
@ -89,12 +89,10 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... FieldSpecs>
|
template<typename Db, std::size_t NextIndex, std::size_t... Is, typename... FieldSpecs>
|
||||||
struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, FieldSpecs...>:
|
struct result_row_impl<Db, detail::field_index_sequence<NextIndex, Is...>, FieldSpecs...>:
|
||||||
public result_field<Db, Is, FieldSpecs>...
|
public result_field<Db, Is, FieldSpecs>...
|
||||||
{
|
{
|
||||||
static constexpr std::size_t _last_index = LastIndex;
|
|
||||||
|
|
||||||
result_row_impl() = default;
|
result_row_impl() = default;
|
||||||
|
|
||||||
void _validate()
|
void _validate()
|
||||||
@ -120,11 +118,11 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Db, typename... FieldSpecs>
|
template<typename Db, typename... FieldSpecs>
|
||||||
struct result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>
|
struct result_row_t: public detail::result_row_impl<Db, detail::make_field_index_sequence<0, FieldSpecs...>, FieldSpecs...>
|
||||||
{
|
{
|
||||||
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>;
|
using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>;
|
||||||
|
using _impl = detail::result_row_impl<Db, _field_index_sequence, FieldSpecs...>;
|
||||||
bool _is_valid;
|
bool _is_valid;
|
||||||
static constexpr size_t _last_static_index = _impl::_last_index;
|
|
||||||
|
|
||||||
result_row_t():
|
result_row_t():
|
||||||
_impl(),
|
_impl(),
|
||||||
@ -168,7 +166,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
static constexpr size_t static_size()
|
static constexpr size_t static_size()
|
||||||
{
|
{
|
||||||
return _last_static_index;
|
return _field_index_sequence::_next_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Target>
|
template<typename Target>
|
||||||
@ -179,9 +177,10 @@ namespace sqlpp
|
|||||||
};
|
};
|
||||||
|
|
||||||
template<typename Db, typename... FieldSpecs>
|
template<typename Db, typename... FieldSpecs>
|
||||||
struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>
|
struct dynamic_result_row_t: public detail::result_row_impl<Db, detail::make_field_index_sequence<0, FieldSpecs...>, FieldSpecs...>
|
||||||
{
|
{
|
||||||
using _impl = detail::result_row_impl<Db, detail::make_column_index_sequence<0, FieldSpecs...>, FieldSpecs...>;
|
using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>;
|
||||||
|
using _impl = detail::result_row_impl<Db, _field_index_sequence, FieldSpecs...>;
|
||||||
struct _field_spec_t
|
struct _field_spec_t
|
||||||
{
|
{
|
||||||
using _traits = make_traits<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>;
|
||||||
@ -190,10 +189,9 @@ namespace sqlpp
|
|||||||
struct _name_t {};
|
struct _name_t {};
|
||||||
};
|
};
|
||||||
using _field_type = result_field_t<text, 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;
|
bool _is_valid;
|
||||||
std::vector<std::string> _dynamic_columns;
|
std::vector<std::string> _dynamic_field_names;
|
||||||
std::map<std::string, _field_type> _dynamic_fields;
|
std::map<std::string, _field_type> _dynamic_fields;
|
||||||
|
|
||||||
dynamic_result_row_t():
|
dynamic_result_row_t():
|
||||||
@ -202,12 +200,12 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic_result_row_t(const std::vector<std::string>& dynamic_columns):
|
dynamic_result_row_t(const std::vector<std::string>& dynamic_field_names):
|
||||||
_impl(),
|
_impl(),
|
||||||
_is_valid(false),
|
_is_valid(false),
|
||||||
_dynamic_columns(dynamic_columns)
|
_dynamic_field_names(dynamic_field_names)
|
||||||
{
|
{
|
||||||
for (auto name : _dynamic_columns)
|
for (auto name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.insert({name, _field_type{}});
|
_dynamic_fields.insert({name, _field_type{}});
|
||||||
}
|
}
|
||||||
@ -259,10 +257,11 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_bind(target);
|
_impl::_bind(target);
|
||||||
|
|
||||||
std::size_t index = _last_static_index;
|
std::size_t index = _field_index_sequence::_next_index;
|
||||||
for (const auto& name : _dynamic_columns)
|
for (const auto& name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(name)._bind(target, ++index);
|
_dynamic_fields.at(name)._bind(target, index);
|
||||||
|
++index;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -270,7 +270,7 @@ int main()
|
|||||||
static_assert(sqlpp::is_regular<T>::value, "type requirement");
|
static_assert(sqlpp::is_regular<T>::value, "type requirement");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that select(all_of(tab)) is expanded in select
|
// Test that all_of(tab) is expanded in select
|
||||||
{
|
{
|
||||||
auto a = select(all_of(t));
|
auto a = select(all_of(t));
|
||||||
auto b = select(t.alpha, t.beta, t.gamma, t.delta);
|
auto b = select(t.alpha, t.beta, t.gamma, t.delta);
|
||||||
@ -279,7 +279,7 @@ int main()
|
|||||||
//static_assert(std::is_same<decltype(b), decltype(c)>::value, "t has to be expanded by select()");
|
//static_assert(std::is_same<decltype(b), decltype(c)>::value, "t has to be expanded by select()");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test that select(all_of(tab)) is expanded in multi_column
|
// Test that all_of(tab) is expanded in multi_column
|
||||||
{
|
{
|
||||||
auto a = multi_column(all_of(t)).as(alias::a);
|
auto a = multi_column(all_of(t)).as(alias::a);
|
||||||
auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a);
|
auto b = multi_column(t.alpha, t.beta, t.gamma, t.delta).as(alias::a);
|
||||||
@ -292,6 +292,19 @@ int main()
|
|||||||
static_assert(not sqlpp::is_expression_t<decltype(m)>::value, "a multi_column is not a value");
|
static_assert(not sqlpp::is_expression_t<decltype(m)>::value, "a multi_column is not a value");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test result field indices
|
||||||
|
{
|
||||||
|
using Select = decltype(select(
|
||||||
|
all_of(t), // index 0, 1, 2, 3 (alpha, beta, gamma, delta)
|
||||||
|
multi_column(all_of(t)).as(alias::left), // index 4 (including 4, 5, 6, 7)
|
||||||
|
multi_column(all_of(t)).as(alias::right), // index 8 (including 8, 9, 10, 11)
|
||||||
|
t.alpha.as(alias::a) // index 12
|
||||||
|
).from(t).where(true)); // next index is 13
|
||||||
|
using ResultRow = typename Select::_result_methods_t::template _result_row_t<MockDb>;
|
||||||
|
using IndexSequence = ResultRow::_field_index_sequence;
|
||||||
|
static_assert(std::is_same<IndexSequence, sqlpp::detail::field_index_sequence<13, 0, 1, 2, 3, 4, 8, 12>>::value, "invalid field sequence");
|
||||||
|
}
|
||||||
|
|
||||||
// Test that result sets with identical name/value combinations have identical types
|
// Test that result sets with identical name/value combinations have identical types
|
||||||
{
|
{
|
||||||
auto a = select(t.alpha);
|
auto a = select(t.alpha);
|
||||||
|
Loading…
Reference in New Issue
Block a user