3 #include <ozo/ext/std.h>
4 #include <ozo/ext/boost.h>
5 #include <ozo/io/send.h>
6 #include <ozo/io/array.h>
7 #include <ozo/io/composite.h>
8 #include <ozo/core/concept.h>
10 #include <ozo/type_traits.h>
11 #include <ozo/optional.h>
12 #include <ozo/pg/types.h>
14 #include <boost/hana/for_each.hpp>
15 #include <boost/hana/tuple.hpp>
16 #include <boost/hana/ext/std/array.hpp>
23 #include <string_view>
48 template <
class Text,
class Params,
class O
idMap,
class Allocator = std::allocator<
char>>
50 : impl{std::allocate_shared<impl_type<Text, Params, OidMap, Allocator>>(
51 allocator, std::move(
text), params, oid_map, allocator
59 const char*
text() const noexcept {
78 return impl->formats();
88 return impl->lengths();
96 const char*
const*
values() const noexcept {
97 return impl->values();
106 return impl->params_count();
110 static constexpr
auto binary_format = 1;
113 virtual const char*
text() const noexcept = 0;
114 virtual const
oid_t*
types() const noexcept = 0;
115 virtual const
int*
formats() const noexcept = 0;
116 virtual const
int*
lengths() const noexcept = 0;
117 virtual const
char* const*
values() const noexcept = 0;
118 virtual std::ptrdiff_t
params_count() const noexcept = 0;
119 virtual ~interface() = default;
122 template <class Text, class Params, class
OidMap, class Allocator = std::allocator<
char>>
123 struct impl_type final : interface {
124 static_assert(ozo::HanaSequence<Params>,
"Params should be Hana.Sequence");
125 static_assert(ozo::OidMap<OidMap>,
"OidMap should model ozo::OidMap");
126 static_assert(ozo::QueryText<Text>,
"Text should model ozo::QueryText concept");
128 using allocator_type = std::conditional_t<
129 std::is_same_v<typename Allocator::value_type, char>,
131 typename Allocator::template rebind<char>::other>;
132 using buffer_type = std::vector<char, allocator_type>;
133 using oid_map_type =
OidMap;
134 using text_type = std::decay_t<Text>;
135 using params_type = Params;
137 static constexpr
auto params_count_ = decltype(hana::length(std::declval<params_type>()))::
value;
141 std::array<oid_t, params_count_> types_;
142 std::array<int, params_count_> formats_;
143 std::array<int, params_count_> lengths_;
144 std::array<const char*, params_count_> values_;
146 impl_type(Text
text,
const Params& params,
147 const OidMap& oid_map,
const Allocator& allocator)
148 : text_(std::move(
text)), buffer_(allocator) {
149 formats_.fill(binary_format);
151 const auto range = hana::to_tuple(hana::make_range(hana::size_c<0>, hana::size_c<params_count_>));
153 hana::for_each(range, [&] (
auto i) {
154 lengths_[i] = std::max(0,
size_of(params[i]));
155 types_[i] =
type_oid(oid_map, params[i]);
158 buffer_.reserve(hana::unpack(lengths_, [](
auto ...x) {
return (x + ... + 0);}));
160 ozo::ostream os(buffer_);
162 hana::for_each(params, [&] (
auto& param) {
send(os, oid_map, param);});
164 std::size_t offset = 0;
165 hana::for_each(range, [&] (
auto i) {
166 values_[i] = lengths_[i] ? std::data(buffer_) + offset :
nullptr;
167 offset += lengths_[i];
171 impl_type(
const impl_type&) =
delete;
172 impl_type(impl_type&&) =
delete;
174 const char*
text() const noexcept
override {
178 const oid_t*
types() const noexcept
override {
179 return std::data(types_);
182 const int*
formats() const noexcept
override {
183 return std::data(formats_);
186 const int*
lengths() const noexcept
override {
187 return std::data(lengths_);
190 const char*
const*
values() const noexcept
override {
191 return std::data(values_);
195 return params_count_;
199 std::shared_ptr<const interface> impl;
203 struct no_binary_query_conversion {};
206 template <
typename T,
typename = hana::when<true>>
207 struct to_binary_query_impl : detail::no_binary_query_conversion {
208 template <
typename O
idMap,
typename Alloc>
209 static auto apply(
const T&,
const OidMap&,
const Alloc&) {
210 static_assert(std::is_void_v<to_binary_query_impl>,
"no conversion to the binary_query is defined");
214 template <
typename T>
215 using is_binary_query_convertible =
typename std::negation<typename std::is_base_of<detail::no_binary_query_conversion, T>::type>::type;
217 template <
typename T>
218 inline constexpr
auto is_binary_query_convertible_v = is_binary_query_convertible<T>::value;
275 template <
typename T>
280 template <
typename T>
281 struct to_binary_query_impl<T, hana::when<Query<T>>> {
282 template <
typename O
idMap,
typename Alloc>
283 static binary_query apply(
const T& query,
const OidMap& oid_map,
const Alloc& allocator) {
290 template <
typename O
idMap,
typename Alloc>
313 template <
typename BinaryQueryConvertible,
typename O
idMap,
typename Allocator = std::allocator<
char>>
315 const OidMap& oid_map,
const Allocator& allocator = Allocator{}) {
316 return to_binary_query_impl<BinaryQueryConvertible>::apply(query, oid_map, allocator);