15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H
18 #include "google/cloud/spanner/internal/tuple_utils.h"
19 #include "google/cloud/spanner/value.h"
20 #include "google/cloud/spanner/version.h"
21 #include "google/cloud/status.h"
22 #include "google/cloud/status_or.h"
28 #include <type_traits>
40 namespace spanner_internal {
43 std::shared_ptr<std::vector<std::string>
const>);
99 std::size_t
size()
const {
return columns_->size(); }
102 std::vector<std::string>
const&
columns()
const {
return *columns_; }
111 StatusOr<
Value>
get(std::size_t pos)
const;
114 StatusOr<
Value>
get(std::string
const& name)
const;
122 template <
typename T,
typename Arg>
123 StatusOr<T>
get(Arg&& arg)
const {
124 auto v = get(std::forward<Arg>(arg));
125 if (v)
return v->
template get<T>();
135 template <
typename Tuple>
136 StatusOr<Tuple>
get()
const& {
137 if (
size() != std::tuple_size<Tuple>::value) {
138 auto constexpr kMsg =
"Tuple has the wrong number of elements";
142 auto it = values_.begin();
144 spanner_internal::ForEach(tup, ExtractValue{status}, it);
145 if (!status
.ok())
return status;
155 template <
typename Tuple>
156 StatusOr<Tuple>
get() && {
157 if (
size() != std::tuple_size<Tuple>::value) {
158 auto constexpr kMsg =
"Tuple has the wrong number of elements";
162 auto it = std::make_move_iterator(values_.begin());
164 spanner_internal::ForEach(tup, ExtractValue{status}, it);
165 if (!status
.ok())
return status;
178 std::shared_ptr<std::vector<std::string>
const>);
179 struct ExtractValue {
181 template <
typename T,
typename It>
182 void operator()(T& t, It& it)
const {
183 auto x = it++->
template get<T>();
185 status = std::move(x).status();
198 Row(std::vector<
Value> values,
199 std::shared_ptr<
const std::vector<std::string>> columns);
201 std::vector<
Value> values_;
202 std::shared_ptr<
const std::vector<std::string>> columns_;
228 template <
typename... Ts>
230 auto columns = std::make_shared<std::vector<std::string>>();
231 for (std::size_t i = 0; i <
sizeof...(ts); ++i) {
232 columns->emplace_back(std::to_string(i));
234 std::vector<
Value> v{
Value(std::forward<Ts>(ts))...};
235 return spanner_internal::MakeRow(std::move(v), std::move(columns));
258 using Source = std::function<StatusOr<
Row>()>;
262 using iterator_category = std::input_iterator_tag;
263 using value_type = StatusOr<
Row>;
264 using difference_type = std::ptrdiff_t;
265 using pointer = value_type*;
266 using reference = value_type&;
267 using const_pointer = value_type
const*;
268 using const_reference = value_type
const&;
316 template <
typename Tuple>
321 using iterator_category = std::input_iterator_tag;
322 using value_type = StatusOr<Tuple>;
323 using difference_type = std::ptrdiff_t;
324 using pointer = value_type*;
325 using reference = value_type&;
326 using const_pointer = value_type
const*;
327 using const_reference = value_type
const&;
335 : it_(std::move(begin)), end_(std::move(end)) {
356 auto const old = *
this;
363 return a.it_ == b.it_;
373 if (it_
== end_)
return;
374 tup_ =
*it_ ? std::move(
*it_)
->template get<Tuple>() : it_
->status();
409 template <
typename Tuple>
413 static_assert(spanner_internal::IsTuple<Tuple>::value,
414 "TupleStream<T> requires a std::tuple parameter");
416 iterator
begin()
const {
return begin_; }
417 iterator
end()
const {
return end_; }
420 template <
typename T,
typename RowRange>
423 template <
typename It>
424 explicit TupleStream(It&& start, It&& end)
425 : begin_(std::forward<It>(start), std::forward<It>(end)) {}
443 template <
typename Tuple,
typename RowRange>
445 static_assert(std::is_lvalue_reference<
decltype(range)>::value,
446 "range must be an lvalue since it must outlive StreamOf");
447 return TupleStream<Tuple>(std::begin(std::forward<RowRange>(range)),
448 std::end(std::forward<RowRange>(range)));
469 template <
typename RowRange>
471 decltype(*std::forward<RowRange>(range).begin())>::
type {
472 auto const e = std::forward<RowRange>(range).end();
473 auto it = std::forward<RowRange>(range).begin();
475 auto row = std::move(*it);