mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +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 <sqlpp11/field_spec.h>
|
||||
#include <sqlpp11/text.h>
|
||||
#include <sqlpp11/detail/column_index_sequence.h>
|
||||
#include <sqlpp11/detail/field_index_sequence.h>
|
||||
|
||||
namespace sqlpp
|
||||
{
|
||||
@ -66,9 +66,9 @@ namespace sqlpp
|
||||
|
||||
template<std::size_t index, typename AliasProvider, typename Db, typename... 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;
|
||||
|
||||
@ -89,12 +89,10 @@ namespace sqlpp
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Db, std::size_t LastIndex, std::size_t... Is, typename... FieldSpecs>
|
||||
struct result_row_impl<Db, detail::column_index_sequence<LastIndex, Is...>, FieldSpecs...>:
|
||||
template<typename Db, std::size_t NextIndex, std::size_t... Is, typename... FieldSpecs>
|
||||
struct result_row_impl<Db, detail::field_index_sequence<NextIndex, Is...>, FieldSpecs...>:
|
||||
public result_field<Db, Is, FieldSpecs>...
|
||||
{
|
||||
static constexpr std::size_t _last_index = LastIndex;
|
||||
|
||||
result_row_impl() = default;
|
||||
|
||||
void _validate()
|
||||
@ -120,11 +118,11 @@ namespace sqlpp
|
||||
}
|
||||
|
||||
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;
|
||||
static constexpr size_t _last_static_index = _impl::_last_index;
|
||||
|
||||
result_row_t():
|
||||
_impl(),
|
||||
@ -168,7 +166,7 @@ namespace sqlpp
|
||||
|
||||
static constexpr size_t static_size()
|
||||
{
|
||||
return _last_static_index;
|
||||
return _field_index_sequence::_next_index;
|
||||
}
|
||||
|
||||
template<typename Target>
|
||||
@ -179,9 +177,10 @@ namespace sqlpp
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
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 {};
|
||||
};
|
||||
using _field_type = result_field_t<text, Db, _field_spec_t>;
|
||||
static constexpr size_t _last_static_index = _impl::_last_index;
|
||||
|
||||
bool _is_valid;
|
||||
std::vector<std::string> _dynamic_columns;
|
||||
std::vector<std::string> _dynamic_field_names;
|
||||
std::map<std::string, _field_type> _dynamic_fields;
|
||||
|
||||
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(),
|
||||
_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{}});
|
||||
}
|
||||
@ -259,10 +257,11 @@ namespace sqlpp
|
||||
{
|
||||
_impl::_bind(target);
|
||||
|
||||
std::size_t index = _last_static_index;
|
||||
for (const auto& name : _dynamic_columns)
|
||||
std::size_t index = _field_index_sequence::_next_index;
|
||||
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");
|
||||
}
|
||||
|
||||
// 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 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()");
|
||||
}
|
||||
|
||||
// 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 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");
|
||||
}
|
||||
|
||||
// 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
|
||||
{
|
||||
auto a = select(t.alpha);
|
||||
|
Loading…
Reference in New Issue
Block a user