Google Cloud Spanner C++ Client
A C++ Client Library for Google Cloud Spanner
row.h
Go to the documentation of this file.
1 // Copyright 2019 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H
17 
18 #include "google/cloud/spanner/internal/tuple_utils.h"
21 #include "google/cloud/status.h"
22 #include "google/cloud/status_or.h"
23 #include <functional>
24 #include <iterator>
25 #include <memory>
26 #include <string>
27 #include <tuple>
28 #include <type_traits>
29 #include <utility>
30 #include <vector>
31 
32 namespace google {
33 namespace cloud {
34 namespace spanner {
35 inline namespace SPANNER_CLIENT_NS {
36 
37 class Row;
38 namespace internal {
39 Row MakeRow(std::vector<Value>,
40  std::shared_ptr<const std::vector<std::string>>);
41 } // namespace internal
42 
78 class Row {
79  public:
81  Row();
82 
85  Row(Row const&) = default;
86  Row& operator=(Row const&) = default;
87  Row(Row&&) = default;
88  Row& operator=(Row&&) = default;
90 
92  std::size_t size() const { return columns_->size(); }
93 
95  std::vector<std::string> const& columns() const { return *columns_; }
96 
98  std::vector<Value> const& values() const& { return values_; }
99 
101  std::vector<Value>&& values() && { return std::move(values_); }
102 
104  StatusOr<Value> get(std::size_t pos) const;
105 
107  StatusOr<Value> get(std::string const& name) const;
108 
115  template <typename T, typename Arg>
116  StatusOr<T> get(Arg&& arg) const {
117  auto v = get(std::forward<Arg>(arg));
118  if (v) return v->template get<T>();
119  return v.status();
120  }
121 
128  template <typename Tuple>
129  StatusOr<Tuple> get() const& {
130  if (size() != std::tuple_size<Tuple>::value) {
131  auto const msg = "Tuple has the wrong number of elements";
132  return Status(StatusCode::kInvalidArgument, msg);
133  }
134  Tuple tup;
135  auto it = values_.begin();
136  Status status;
137  internal::ForEach(tup, ExtractValue{status}, it);
138  if (!status.ok()) return status;
139  return tup;
140  }
141 
148  template <typename Tuple>
149  StatusOr<Tuple> get() && {
150  if (size() != std::tuple_size<Tuple>::value) {
151  auto const msg = "Tuple has the wrong number of elements";
152  return Status(StatusCode::kInvalidArgument, msg);
153  }
154  Tuple tup;
155  auto it = std::make_move_iterator(values_.begin());
156  Status status;
157  internal::ForEach(tup, ExtractValue{status}, it);
158  if (!status.ok()) return status;
159  return tup;
160  }
161 
164  friend bool operator==(Row const& a, Row const& b);
165  friend bool operator!=(Row const& a, Row const& b) { return !(a == b); }
167 
168  private:
169  friend Row internal::MakeRow(std::vector<Value>,
170  std::shared_ptr<const std::vector<std::string>>);
171  struct ExtractValue {
172  Status& status;
173  template <typename T, typename It>
174  void operator()(T& t, It& it) const {
175  auto x = it++->template get<T>();
176  if (!x) {
177  status = std::move(x).status();
178  } else {
179  t = *std::move(x);
180  }
181  }
182  };
183 
190  Row(std::vector<Value> values,
191  std::shared_ptr<const std::vector<std::string>> columns);
192 
193  std::vector<Value> values_;
194  std::shared_ptr<const std::vector<std::string>> columns_;
195 };
196 
206 Row MakeTestRow(std::vector<std::pair<std::string, Value>> pairs);
207 
220 template <typename... Ts>
221 Row MakeTestRow(Ts&&... ts) {
222  auto columns = std::make_shared<std::vector<std::string>>();
223  for (std::size_t i = 0; i < sizeof...(ts); ++i) {
224  columns->emplace_back(std::to_string(i));
225  }
226  std::vector<Value> v{Value(std::forward<Ts>(ts))...};
227  return internal::MakeRow(std::move(v), std::move(columns));
228 }
229 
245  public:
250  using Source = std::function<StatusOr<Row>()>;
251 
254  using iterator_category = std::input_iterator_tag;
255  using value_type = StatusOr<Row>;
256  using difference_type = std::ptrdiff_t;
257  using pointer = value_type*;
259  using const_pointer = value_type const*;
260  using const_reference = value_type const&;
262 
265 
270  explicit RowStreamIterator(Source source);
271 
272  reference operator*() { return row_; }
273  pointer operator->() { return &row_; }
274 
275  const_reference operator*() const { return row_; }
276  const_pointer operator->() const { return &row_; }
277 
278  RowStreamIterator& operator++();
279  RowStreamIterator operator++(int);
280 
281  friend bool operator==(RowStreamIterator const&, RowStreamIterator const&);
282  friend bool operator!=(RowStreamIterator const&, RowStreamIterator const&);
283 
284  private:
285  value_type row_;
286  Source source_; // nullptr means "end"
287 };
288 
308 template <typename Tuple>
310  public:
313  using iterator_category = std::input_iterator_tag;
314  using value_type = StatusOr<Tuple>;
315  using difference_type = std::ptrdiff_t;
316  using pointer = value_type*;
318  using const_pointer = value_type const*;
319  using const_reference = value_type const&;
321 
323  TupleStreamIterator() = default;
324 
327  : it_(std::move(begin)), end_(std::move(end)) {
328  ParseTuple();
329  }
330 
331  reference operator*() { return tup_; }
332  pointer operator->() { return &tup_; }
333 
334  const_reference operator*() const { return tup_; }
335  const_pointer operator->() const { return &tup_; }
336 
338  if (!tup_) {
339  it_ = end_;
340  return *this;
341  }
342  ++it_;
343  ParseTuple();
344  return *this;
345  }
346 
348  auto const old = *this;
349  ++*this;
350  return old;
351  }
352 
353  friend bool operator==(TupleStreamIterator const& a,
354  TupleStreamIterator const& b) {
355  return a.it_ == b.it_;
356  }
357 
358  friend bool operator!=(TupleStreamIterator const& a,
359  TupleStreamIterator const& b) {
360  return !(a == b);
361  }
362 
363  private:
364  void ParseTuple() {
365  if (it_ == end_) return;
366  tup_ = *it_ ? std::move(*it_)->template get<Tuple>() : it_->status();
367  }
368 
369  value_type tup_;
370  RowStreamIterator it_;
371  RowStreamIterator end_;
372 };
373 
401 template <typename Tuple>
402 class TupleStream {
403  public:
405  static_assert(internal::IsTuple<Tuple>::value,
406  "TupleStream<T> requires a std::tuple parameter");
407 
408  iterator begin() const { return begin_; }
409  iterator end() const { return end_; }
410 
411  private:
412  template <typename T, typename RowRange>
413  friend TupleStream<T> StreamOf(RowRange&& range);
414 
415  template <typename It>
416  explicit TupleStream(It&& start, It&& end)
417  : begin_(std::forward<It>(start), std::forward<It>(end)) {}
418 
419  iterator begin_;
420  iterator end_;
421 };
422 
435 template <typename Tuple, typename RowRange>
436 TupleStream<Tuple> StreamOf(RowRange&& range) {
437  static_assert(std::is_lvalue_reference<decltype(range)>::value,
438  "range must be an lvalue since it must outlive StreamOf");
439  return TupleStream<Tuple>(std::begin(std::forward<RowRange>(range)),
440  std::end(std::forward<RowRange>(range)));
441 }
442 
461 template <typename RowRange>
462 auto GetSingularRow(RowRange&& range) -> typename std::decay<
463  decltype(*std::forward<RowRange>(range).begin())>::type {
464  auto const e = std::forward<RowRange>(range).end();
465  auto it = std::forward<RowRange>(range).begin();
466  if (it == e) return Status(StatusCode::kInvalidArgument, "no rows");
467  auto row = std::move(*it);
468  if (++it != e) return Status(StatusCode::kInvalidArgument, "too many rows");
469  return row;
470 }
471 
472 } // namespace SPANNER_CLIENT_NS
473 } // namespace spanner
474 } // namespace cloud
475 } // namespace google
476 
477 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H
TupleStreamIterator operator++(int)
Definition: row.h:347
The Value class represents a type-safe, nullable Spanner value.
Definition: value.h:162
bool operator!=(Backup const &a, Backup const &b)
Definition: backup.cc:33
std::function< StatusOr< Row >()> Source
A function that returns a sequence of StatusOr<Row> objects.
Definition: row.h:250
StatusOr< Tuple > get() &&
Returns all the native C++ values for the whole row in a std::tuple with the specified type.
Definition: row.h:149
std::input_iterator_tag iterator_category
Definition: row.h:254
TupleStreamIterator(RowStreamIterator begin, RowStreamIterator end)
Creates an iterator that wraps the given RowStreamIterator range.
Definition: row.h:326
const_reference operator*() const
Definition: row.h:334
const_pointer operator->() const
Definition: row.h:276
std::size_t size() const
Returns the number of columns in the row.
Definition: row.h:92
A TupleStream<Tuple> defines a range that parses Tuple objects from the given range of RowStreamItera...
Definition: row.h:402
bool operator==(Backup const &a, Backup const &b)
Definition: backup.cc:29
TupleStream< Tuple > StreamOf(RowRange &&range)
A factory that creates a TupleStream<Tuple> by wrapping the given range.
Definition: row.h:436
A RowStreamIterator is an Input Iterator (see below) that returns a sequence of StatusOr<Row> objects...
Definition: row.h:244
std::vector< Value > && values() &&
Returns the Value objects in the given row.
Definition: row.h:101
const_reference operator*() const
Definition: row.h:275
Contains all the Cloud Spanner C++ client types and functions.
std::vector< std::string > const & columns() const
Returns the column names for the row.
Definition: row.h:95
friend bool operator!=(Row const &a, Row const &b)
Definition: row.h:165
StatusOr< Tuple > get() const &
Returns all the native C++ values for the whole row in a std::tuple with the specified type.
Definition: row.h:129
auto GetSingularRow(RowRange &&range) -> typename std::decay< decltype(*std::forward< RowRange >(range).begin())>::type
Returns the only row from a range that contains exactly one row.
Definition: row.h:462
std::input_iterator_tag iterator_category
Definition: row.h:313
A Row is a sequence of columns each with a name and an associated Value.
Definition: row.h:78
#define SPANNER_CLIENT_NS
Definition: version.h:22
friend bool operator==(TupleStreamIterator const &a, TupleStreamIterator const &b)
Definition: row.h:353
friend bool operator!=(TupleStreamIterator const &a, TupleStreamIterator const &b)
Definition: row.h:358
std::vector< Value > const & values() const &
Returns the Value objects in the given row.
Definition: row.h:98
A TupleStreamIterator<Tuple> is an "Input Iterator" that wraps a RowStreamIterator,...
Definition: row.h:309
Row MakeTestRow(Ts &&... ts)
Creates a Row with Values created from the given arguments and with auto-generated column names.
Definition: row.h:221
StatusOr< T > get(Arg &&arg) const
Returns the native C++ value at the given position or column name.
Definition: row.h:116
TupleStreamIterator & operator++()
Definition: row.h:337