mirror of
https://github.com/rbock/sqlpp11.git
synced 2024-11-15 20:31:16 +08:00
Remove multi_column.
While a nice feature in theory, this was extremely rarely used and added quite a bit of complexity to the code.
This commit is contained in:
parent
77db53436d
commit
34a8f34821
@ -75,7 +75,7 @@ Using aliases also comes in handy when you join tables and have several columns
|
|||||||
select(foo.id, bar.id); // compile error
|
select(foo.id, bar.id); // compile error
|
||||||
```
|
```
|
||||||
|
|
||||||
One of the columns needs an alias (or you use multi-columns as shown below).
|
One of the columns needs an alias.
|
||||||
```C++
|
```C++
|
||||||
SQLPP_ALIAS_PROVIDER(barId);
|
SQLPP_ALIAS_PROVIDER(barId);
|
||||||
select(foo.id, bar.id.as(barId));
|
select(foo.id, bar.id.as(barId));
|
||||||
@ -129,28 +129,6 @@ Statements like `SELECT * from foo` is used pretty often in SQL. sqlpp11 offers
|
|||||||
```C++
|
```C++
|
||||||
select(all_of(foo));
|
select(all_of(foo));
|
||||||
```
|
```
|
||||||
### Multi-Columns
|
|
||||||
Sometimes, when you join tables `foo`, `bar` and `baz`, you might want to select several columns of the same name. As shown above, you could use aliases to resolve name clashes. Another option is to group columns together in multi-columns. Here is an example:
|
|
||||||
|
|
||||||
```
|
|
||||||
SQLPP_ALIAS_PROVIDER_GENERATOR(left);
|
|
||||||
for(const auto& row : db(
|
|
||||||
select(foo.id,
|
|
||||||
multi_column(left, foo.id, foo.name, foo.hasFun),
|
|
||||||
multi_column(foo, all_of(foo)))
|
|
||||||
.from(foo)))
|
|
||||||
{
|
|
||||||
std::cerr << "row.left.id: " << row.left.id
|
|
||||||
<< ", row.left.name: " << row.left.name
|
|
||||||
<< ", row.left.hasFun: " << row.left.hasFun << std::endl;
|
|
||||||
std::cerr << "row.foo.id: " << row.foo.id
|
|
||||||
<< ", row.foo.name: " << row.foo.name
|
|
||||||
<< ", row.foo.hasFun: " << row.foo.hasFun << std::endl;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
That might not be the most creative example in the world, but it shows how to use multi-columns. The first argument is an alias provider. In the cases shown above, the alias provider `left` is created using the `SQLPP_ALIAS_PROVIDER` macro. Tables also have a name and can provide an alias.
|
|
||||||
|
|
||||||
In the result rows, the multi-columns are accessed by their name. Their members in turn are accessed by their names.
|
|
||||||
|
|
||||||
## From
|
## From
|
||||||
The `from` method expects one argument. The following subsections expand on the types of valid arguments:
|
The `from` method expects one argument. The following subsections expand on the types of valid arguments:
|
||||||
|
@ -29,7 +29,6 @@
|
|||||||
|
|
||||||
#include <sqlpp11/alias.h>
|
#include <sqlpp11/alias.h>
|
||||||
#include <sqlpp11/interpret.h>
|
#include <sqlpp11/interpret.h>
|
||||||
#include <sqlpp11/multi_column.h>
|
|
||||||
#include <sqlpp11/portable_static_assert.h>
|
#include <sqlpp11/portable_static_assert.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
@ -38,12 +37,6 @@ namespace sqlpp
|
|||||||
struct all_of_t
|
struct all_of_t
|
||||||
{
|
{
|
||||||
using _column_tuple_t = typename Table::_column_tuple_t;
|
using _column_tuple_t = typename Table::_column_tuple_t;
|
||||||
|
|
||||||
template <typename AliasProvider>
|
|
||||||
detail::copy_tuple_args_t<multi_column_alias_t, AliasProvider, _column_tuple_t> as(const AliasProvider& alias)
|
|
||||||
{
|
|
||||||
return multi_column(_column_tuple_t{}).as(alias);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Table>
|
template <typename Table>
|
||||||
|
@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, 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 SQLPP11_DETAIL_FIELD_INDEX_SEQUENCE_H
|
|
||||||
#define SQLPP11_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,
|
|
||||||
typename... Rest>
|
|
||||||
struct make_field_index_sequence_impl<field_index_sequence<NextIndex, Ints...>,
|
|
||||||
field_spec_t<NameType, ValueType, CanBeNull>,
|
|
||||||
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;
|
|
||||||
} // namespace detail
|
|
||||||
} // namespace sqlpp
|
|
||||||
|
|
||||||
#endif
|
|
@ -27,7 +27,7 @@
|
|||||||
#ifndef SQLPP11_FIELD_SPEC_H
|
#ifndef SQLPP11_FIELD_SPEC_H
|
||||||
#define SQLPP11_FIELD_SPEC_H
|
#define SQLPP11_FIELD_SPEC_H
|
||||||
|
|
||||||
#include <sqlpp11/multi_column.h>
|
#include <sqlpp11/type_traits.h>
|
||||||
|
|
||||||
namespace sqlpp
|
namespace sqlpp
|
||||||
{
|
{
|
||||||
@ -42,18 +42,6 @@ namespace sqlpp
|
|||||||
using _alias_t = NameType;
|
using _alias_t = NameType;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename AliasProvider, typename FieldSpecTuple>
|
|
||||||
struct multi_field_spec_t
|
|
||||||
{
|
|
||||||
static_assert(wrong_t<AliasProvider, FieldSpecTuple>::value,
|
|
||||||
"multi_field_spec_t needs to be specialized with a tuple");
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename AliasProvider, typename... FieldSpecs>
|
|
||||||
struct multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Left, typename Right, typename Enable = void>
|
template <typename Left, typename Right, typename Enable = void>
|
||||||
struct is_field_compatible
|
struct is_field_compatible
|
||||||
{
|
{
|
||||||
@ -76,14 +64,6 @@ namespace sqlpp
|
|||||||
// NULL if the right hand side allows it
|
// NULL if the right hand side allows it
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename LeftAlias, typename... LeftFields, typename RightAlias, typename... RightFields>
|
|
||||||
struct is_field_compatible<multi_field_spec_t<LeftAlias, std::tuple<LeftFields...>>,
|
|
||||||
multi_field_spec_t<RightAlias, std::tuple<RightFields...>>,
|
|
||||||
typename std::enable_if<sizeof...(LeftFields) == sizeof...(RightFields)>::type>
|
|
||||||
{
|
|
||||||
static constexpr auto value = logic::all_t<is_field_compatible<LeftFields, RightFields>::value...>::value;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template <typename Select, typename NamedExpr>
|
template <typename Select, typename NamedExpr>
|
||||||
@ -98,13 +78,6 @@ namespace sqlpp
|
|||||||
value_type_of<NamedExpr>,
|
value_type_of<NamedExpr>,
|
||||||
logic::any_t<_can_be_null, _depends_on_outer_table>::value>;
|
logic::any_t<_can_be_null, _depends_on_outer_table>::value>;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename Select, typename AliasProvider, typename... NamedExprs>
|
|
||||||
struct make_field_spec_impl<Select, multi_column_alias_t<AliasProvider, NamedExprs...>>
|
|
||||||
{
|
|
||||||
using type =
|
|
||||||
multi_field_spec_t<AliasProvider, std::tuple<typename make_field_spec_impl<Select, NamedExprs>::type...>>;
|
|
||||||
};
|
|
||||||
} // namespace detail
|
} // namespace detail
|
||||||
|
|
||||||
template <typename Select, typename NamedExpr>
|
template <typename Select, typename NamedExpr>
|
||||||
|
@ -1,145 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (c) 2013-2015, 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 SQLPP11_MULTI_COLUMN_H
|
|
||||||
#define SQLPP11_MULTI_COLUMN_H
|
|
||||||
|
|
||||||
#include <sqlpp11/logic.h>
|
|
||||||
#include <sqlpp11/detail/type_set.h>
|
|
||||||
|
|
||||||
#include <sqlpp11/detail/copy_tuple_args.h>
|
|
||||||
|
|
||||||
namespace sqlpp
|
|
||||||
{
|
|
||||||
struct no_value_t;
|
|
||||||
|
|
||||||
template <typename AliasProvider, typename... Columns>
|
|
||||||
struct multi_column_alias_t;
|
|
||||||
|
|
||||||
template <typename Unused, typename... Columns>
|
|
||||||
struct multi_column_t
|
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t>;
|
|
||||||
using _nodes = detail::type_vector<Columns...>;
|
|
||||||
|
|
||||||
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value,
|
|
||||||
"multi_column parameters need to be named expressions");
|
|
||||||
|
|
||||||
multi_column_t(std::tuple<Columns...> columns) : _columns(columns)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
multi_column_t(Columns... columns) : _columns(columns...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
multi_column_t(const multi_column_t&) = default;
|
|
||||||
multi_column_t(multi_column_t&&) = default;
|
|
||||||
multi_column_t& operator=(const multi_column_t&) = default;
|
|
||||||
multi_column_t& operator=(multi_column_t&&) = default;
|
|
||||||
~multi_column_t() = default;
|
|
||||||
|
|
||||||
template <typename AliasProvider>
|
|
||||||
multi_column_alias_t<AliasProvider, Columns...> as(const AliasProvider& /*unused*/)
|
|
||||||
{
|
|
||||||
return {*this};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::tuple<Columns...> _columns;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename AliasProvider, typename... Columns>
|
|
||||||
struct multi_column_alias_t
|
|
||||||
{
|
|
||||||
using _traits = make_traits<no_value_t, tag::is_alias, tag::is_multi_column, tag::is_selectable>;
|
|
||||||
using _nodes = detail::type_vector<Columns...>;
|
|
||||||
|
|
||||||
static_assert(logic::all_t<is_selectable_t<Columns>::value...>::value,
|
|
||||||
"multi_column parameters need to be named expressions");
|
|
||||||
|
|
||||||
using _alias_t = typename AliasProvider::_alias_t;
|
|
||||||
|
|
||||||
multi_column_alias_t(multi_column_t<void, Columns...> multi_column) : _columns(multi_column._columns)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
multi_column_alias_t(std::tuple<Columns...> columns) : _columns(columns)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
multi_column_alias_t(Columns... columns) : _columns(columns...)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
multi_column_alias_t(const multi_column_alias_t&) = default;
|
|
||||||
multi_column_alias_t(multi_column_alias_t&&) = default;
|
|
||||||
multi_column_alias_t& operator=(const multi_column_alias_t&) = default;
|
|
||||||
multi_column_alias_t& operator=(multi_column_alias_t&&) = default;
|
|
||||||
~multi_column_alias_t() = default;
|
|
||||||
|
|
||||||
std::tuple<Columns...> _columns;
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Context, typename... Columns>
|
|
||||||
struct serializer_t<Context, multi_column_t<void, Columns...>>
|
|
||||||
{
|
|
||||||
using _serialize_check = serialize_check_of<Context, Columns...>;
|
|
||||||
using T = multi_column_t<void, Columns...>;
|
|
||||||
|
|
||||||
static void _(const T& /*unused*/, Context& /*unused*/)
|
|
||||||
{
|
|
||||||
static_assert(wrong_t<serializer_t>::value, "multi_column must be used with an alias");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename Context, typename AliasProvider, typename... Columns>
|
|
||||||
struct serializer_t<Context, multi_column_alias_t<AliasProvider, Columns...>>
|
|
||||||
{
|
|
||||||
using _serialize_check = serialize_check_of<Context, Columns...>;
|
|
||||||
using T = multi_column_alias_t<AliasProvider, Columns...>;
|
|
||||||
|
|
||||||
static Context& _(const T& t, Context& context)
|
|
||||||
{
|
|
||||||
interpret_tuple(t._columns, ',', context);
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace detail
|
|
||||||
{
|
|
||||||
template <typename... Columns>
|
|
||||||
using make_multi_column_t =
|
|
||||||
copy_tuple_args_t<multi_column_t, void, decltype(column_tuple_merge(std::declval<Columns>()...))>;
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
template <typename... Columns>
|
|
||||||
auto multi_column(Columns... columns) -> detail::make_multi_column_t<Columns...>
|
|
||||||
{
|
|
||||||
return detail::make_multi_column_t<Columns...>(std::tuple_cat(detail::as_column_tuple<Columns>::_(columns)...));
|
|
||||||
}
|
|
||||||
} // namespace sqlpp
|
|
||||||
|
|
||||||
#endif
|
|
@ -30,7 +30,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <sqlpp11/data_types/text.h>
|
#include <sqlpp11/data_types/text.h>
|
||||||
#include <sqlpp11/detail/field_index_sequence.h>
|
#include <sqlpp11/detail/index_sequence.h>
|
||||||
#include <sqlpp11/dynamic_select_column_list.h>
|
#include <sqlpp11/dynamic_select_column_list.h>
|
||||||
#include <sqlpp11/field_spec.h>
|
#include <sqlpp11/field_spec.h>
|
||||||
#include <sqlpp11/no_name.h>
|
#include <sqlpp11/no_name.h>
|
||||||
@ -85,54 +85,8 @@ namespace sqlpp
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <std::size_t index, typename AliasProvider, typename Db, typename... FieldSpecs>
|
template <typename Db, std::size_t... Is, typename... FieldSpecs>
|
||||||
struct result_field<Db, index, multi_field_spec_t<AliasProvider, std::tuple<FieldSpecs...>>>
|
struct result_row_impl<Db, detail::index_sequence<Is...>, FieldSpecs...>
|
||||||
: public member_t<AliasProvider,
|
|
||||||
result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>
|
|
||||||
{
|
|
||||||
using _multi_field =
|
|
||||||
member_t<AliasProvider,
|
|
||||||
result_row_impl<Db, detail::make_field_index_sequence<index, FieldSpecs...>, FieldSpecs...>>;
|
|
||||||
|
|
||||||
result_field() = default;
|
|
||||||
|
|
||||||
void _validate()
|
|
||||||
{
|
|
||||||
_multi_field::operator()()._validate();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _invalidate()
|
|
||||||
{
|
|
||||||
_multi_field::operator()()._invalidate();
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _bind(Target& target)
|
|
||||||
{
|
|
||||||
_multi_field::operator()()._bind(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Target>
|
|
||||||
void _post_bind(Target& target)
|
|
||||||
{
|
|
||||||
_multi_field::operator()()._post_bind(target);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callable>
|
|
||||||
void _apply(Callable& callable) const
|
|
||||||
{
|
|
||||||
_multi_field::operator()()._apply(callable);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename Callable>
|
|
||||||
void _apply(const Callable& callable) const
|
|
||||||
{
|
|
||||||
_multi_field::operator()()._apply(callable);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
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>...
|
: public result_field<Db, Is, FieldSpecs>...
|
||||||
{
|
{
|
||||||
result_row_impl() = default;
|
result_row_impl() = default;
|
||||||
@ -181,10 +135,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
template <typename Db, typename... FieldSpecs>
|
template <typename Db, typename... FieldSpecs>
|
||||||
struct result_row_t
|
struct result_row_t
|
||||||
: public detail::result_row_impl<Db, detail::make_field_index_sequence<0, FieldSpecs...>, FieldSpecs...>
|
: public detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>
|
||||||
{
|
{
|
||||||
using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>;
|
using _impl = detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>;
|
||||||
using _impl = detail::result_row_impl<Db, _field_index_sequence, FieldSpecs...>;
|
|
||||||
bool _is_valid{false};
|
bool _is_valid{false};
|
||||||
|
|
||||||
result_row_t() : _impl()
|
result_row_t() : _impl()
|
||||||
@ -224,7 +177,7 @@ namespace sqlpp
|
|||||||
|
|
||||||
static constexpr size_t static_size()
|
static constexpr size_t static_size()
|
||||||
{
|
{
|
||||||
return _field_index_sequence::_next_index;
|
return sizeof...(FieldSpecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Target>
|
template <typename Target>
|
||||||
@ -268,10 +221,9 @@ namespace sqlpp
|
|||||||
|
|
||||||
template <typename Db, typename... FieldSpecs>
|
template <typename Db, typename... FieldSpecs>
|
||||||
struct dynamic_result_row_t
|
struct dynamic_result_row_t
|
||||||
: public detail::result_row_impl<Db, detail::make_field_index_sequence<0, FieldSpecs...>, FieldSpecs...>
|
: public detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>
|
||||||
{
|
{
|
||||||
using _field_index_sequence = detail::make_field_index_sequence<0, FieldSpecs...>;
|
using _impl = detail::result_row_impl<Db, detail::make_index_sequence<sizeof...(FieldSpecs)>, FieldSpecs...>;
|
||||||
using _impl = detail::result_row_impl<Db, _field_index_sequence, FieldSpecs...>;
|
|
||||||
using _field_type = result_field_t<Db, field_spec_t<no_name_t, text, true>>;
|
using _field_type = result_field_t<Db, field_spec_t<no_name_t, text, true>>;
|
||||||
|
|
||||||
bool _is_valid{false};
|
bool _is_valid{false};
|
||||||
@ -336,7 +288,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_bind(target);
|
_impl::_bind(target);
|
||||||
|
|
||||||
std::size_t index = _field_index_sequence::_next_index;
|
std::size_t index = sizeof...(FieldSpecs);
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._bind(target, index);
|
_dynamic_fields.at(field_name)._bind(target, index);
|
||||||
@ -349,7 +301,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_post_bind(target);
|
_impl::_post_bind(target);
|
||||||
|
|
||||||
std::size_t index = _field_index_sequence::_next_index;
|
std::size_t index = sizeof...(FieldSpecs);
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._post_bind(target, index);
|
_dynamic_fields.at(field_name)._post_bind(target, index);
|
||||||
@ -362,7 +314,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_apply(callable);
|
_impl::_apply(callable);
|
||||||
|
|
||||||
std::size_t index = _field_index_sequence::_next_index;
|
std::size_t index = sizeof...(FieldSpecs);
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._apply(callable);
|
_dynamic_fields.at(field_name)._apply(callable);
|
||||||
@ -375,7 +327,7 @@ namespace sqlpp
|
|||||||
{
|
{
|
||||||
_impl::_apply(callable);
|
_impl::_apply(callable);
|
||||||
|
|
||||||
std::size_t index = _field_index_sequence::_next_index;
|
std::size_t index = sizeof...(FieldSpecs);
|
||||||
for (const auto& field_name : _dynamic_field_names)
|
for (const auto& field_name : _dynamic_field_names)
|
||||||
{
|
{
|
||||||
_dynamic_fields.at(field_name)._apply(callable);
|
_dynamic_fields.at(field_name)._apply(callable);
|
||||||
|
@ -251,8 +251,6 @@ namespace sqlpp
|
|||||||
consistency_check_t<_statement_t>{};
|
consistency_check_t<_statement_t>{};
|
||||||
static_assert(_statement_t::_can_be_used_as_table(),
|
static_assert(_statement_t::_can_be_used_as_table(),
|
||||||
"statement cannot be used as table, e.g. due to missing tables");
|
"statement cannot be used as table, e.g. due to missing tables");
|
||||||
static_assert(logic::none_t<is_multi_column_t<Columns>::value...>::value,
|
|
||||||
"cannot use multi-columns in sub selects");
|
|
||||||
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
return _table_t<AliasProvider>(_get_statement()).as(aliasProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -306,8 +304,7 @@ namespace sqlpp
|
|||||||
struct check_selected_columns
|
struct check_selected_columns
|
||||||
{
|
{
|
||||||
using type = static_combined_check_t<
|
using type = static_combined_check_t<
|
||||||
static_check_t<logic::all_t<(is_selectable_t<T>::value or is_multi_column_t<T>::value)...>::value,
|
static_check_t<logic::all_t<is_selectable_t<T>::value...>::value, assert_selected_colums_are_selectable_t>>;
|
||||||
assert_selected_colums_are_selectable_t>>;
|
|
||||||
};
|
};
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
using check_selected_columns_t = typename check_selected_columns<T...>::type;
|
using check_selected_columns_t = typename check_selected_columns<T...>::type;
|
||||||
|
@ -206,7 +206,6 @@ namespace sqlpp
|
|||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_offset)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_offset)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_using_)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_using_)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_column_list)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_column_list)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_multi_column)
|
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_value_list)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_value_list)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_assignment)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_assignment)
|
||||||
SQLPP_VALUE_TRAIT_GENERATOR(is_update_list)
|
SQLPP_VALUE_TRAIT_GENERATOR(is_update_list)
|
||||||
|
@ -135,11 +135,6 @@ int Interpret(int, char* [])
|
|||||||
serialize(select(t.alpha).from(inner), printer).str();
|
serialize(select(t.alpha).from(inner), printer).str();
|
||||||
}
|
}
|
||||||
|
|
||||||
// multi_column
|
|
||||||
serialize(multi_column(t.alpha, (t.beta + "cake").as(t.gamma)).as(t.alpha), printer).str();
|
|
||||||
serialize(multi_column(all_of(t)).as(t), printer).str();
|
|
||||||
serialize(all_of(t).as(t), printer).str();
|
|
||||||
|
|
||||||
// dynamic select
|
// dynamic select
|
||||||
{
|
{
|
||||||
auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t);
|
auto s = dynamic_select(db).dynamic_flags().dynamic_columns().from(t);
|
||||||
|
@ -92,21 +92,6 @@ int Select(int, char*[])
|
|||||||
std::cout << a << ", " << b << std::endl;
|
std::cout << a << ", " << b << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(t).as(t)).from(t).unconditionally()))
|
|
||||||
{
|
|
||||||
int64_t a = row.tabBar.alpha;
|
|
||||||
const std::string b = row.tabBar.beta;
|
|
||||||
std::cout << a << ", " << b << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& row : db(select(all_of(t).as(t), t.gamma).from(t).where(t.alpha > 7)))
|
|
||||||
{
|
|
||||||
int64_t a = row.tabBar.alpha;
|
|
||||||
const std::string b = row.tabBar.beta;
|
|
||||||
const bool g = row.gamma;
|
|
||||||
std::cout << a << ", " << b << ", " << g << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& row :
|
for (const auto& row :
|
||||||
db(select(all_of(t), t.gamma.as(t)).from(t).where(t.alpha > 7 and trim(t.beta) == "test").for_update()))
|
db(select(all_of(t), t.gamma.as(t)).from(t).where(t.alpha > 7 and trim(t.beta) == "test").for_update()))
|
||||||
{
|
{
|
||||||
|
@ -330,34 +330,6 @@ int SelectType(int, char*[])
|
|||||||
// 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 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);
|
|
||||||
static_assert(std::is_same<decltype(a), decltype(b)>::value, "all_of(t) has to be expanded by multi_column");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Test that a multicolumn is not a value
|
|
||||||
{
|
|
||||||
auto m = multi_column(t.alpha, t.beta).as(alias::a);
|
|
||||||
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)
|
|
||||||
.unconditionally()); // next index is 13
|
|
||||||
using ResultRow = typename Select::_result_methods_t<Select>::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