Google Cloud Spanner C++ Client  2.1.0
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 // https://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"
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"
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 {
36 class Row;
38 } // namespace spanner
39 
40 namespace spanner_internal {
42 struct RowFriend {
43  static spanner::Row MakeRow(std::vector<spanner::Value>,
44  std::shared_ptr<std::vector<std::string> const>);
45 };
47 } // namespace spanner_internal
48 
49 namespace spanner {
51 
52 /**
53  * A `Row` is a sequence of columns each with a name and an associated `Value`.
54  *
55  * The `Row` class is a regular value type that may be copied, moved, assigned,
56  * compared for equality, etc. Instances may be large if they hold lots of
57  * `Value` data, so copy only when necessary.
58  *
59  * `Row` instances are typically returned as the result of queries or reads of
60  * a Cloud Spanner table (see `Client::Read` and `Client::ExecuteQuery`). Users
61  * will mostly just use the accessor methods on `Row, and will rarely (if ever)
62  * need to construct a `Row` of their own.
63  *
64  * The number of columns in a `Row` can be obtained from the `size()` member
65  * function. The `Value`s can be obtained using the `values()` accessor. The
66  * names of each column in the row can be obtained using the `columns()`
67  * accessor.
68  *
69  * Perhaps the most convenient way to access the `Values` in a row is through
70  * the variety of "get" accessors. A user may access a column's `Value' by
71  * calling `get` with a `std::size_t` 0-indexed position, or a `std::string`
72  * column name. Furthermore, callers may directly extract the native C++ type
73  * by specifying the C++ type along with the column's position or name.
74  *
75  * @par Example
76  *
77  * @code
78  * Row row = ...;
79  * if (StatusOr<std::string> x = row.get<std::string>("LastName")) {
80  * std::cout << "LastName=" << *x << "\n";
81  * }
82  * @endcode
83  */
84 class Row {
85  public:
86  /// Default constructs an empty row with no columns nor values.
87  Row();
88 
89  /// @name Copy and move.
90  ///@{
91  Row(Row const&) = default;
92  Row& operator=(Row const&) = default;
93  Row(Row&&) = default;
94  Row& operator=(Row&&) = default;
95  ///@}
96 
97  /// Returns the number of columns in the row.
98  std::size_t size() const { return columns_->size(); }
99 
100  /// Returns the column names for the row.
101  std::vector<std::string> const& columns() const { return *columns_; }
102 
103  /// Returns the `Value` objects in the given row.
104  std::vector<Value> const& values() const& { return values_; }
105 
106  /// Returns the `Value` objects in the given row.
107  std::vector<Value>&& values() && { return std::move(values_); }
108 
109  /// Returns the `Value` at the given @p pos.
110  StatusOr<Value> get(std::size_t pos) const;
111 
112  /// Returns the `Value` in the column with @p name
113  StatusOr<Value> get(std::string const& name) const;
114 
115  /**
116  * Returns the native C++ value at the given position or column name.
117  *
118  * @tparam T the native C++ type, e.g., std::int64_t or std::string
119  * @tparam Arg a deduced parameter convertible to a std::size_t or std::string
120  */
121  template <typename T, typename Arg>
122  StatusOr<T> get(Arg&& arg) const {
123  auto v = get(std::forward<Arg>(arg));
124  if (v) return v->template get<T>();
125  return v.status();
126  }
127 
128  /**
129  * Returns all the native C++ values for the whole row in a `std::tuple` with
130  * the specified type.
131  *
132  * @tparam Tuple the `std::tuple` type that the whole row must unpack into.
133  */
134  template <typename Tuple>
135  StatusOr<Tuple> get() const& {
136  if (size() != std::tuple_size<Tuple>::value) {
137  auto constexpr kMsg = "Tuple has the wrong number of elements";
139  }
140  Tuple tup;
141  auto it = values_.begin();
142  Status status;
143  spanner_internal::ForEach(tup, ExtractValue{status}, it);
144  if (!status.ok()) return status;
145  return tup;
146  }
147 
148  /**
149  * Returns all the native C++ values for the whole row in a `std::tuple` with
150  * the specified type.
151  *
152  * @tparam Tuple the `std::tuple` type that the whole row must unpack into.
153  */
154  template <typename Tuple>
155  StatusOr<Tuple> get() && {
156  if (size() != std::tuple_size<Tuple>::value) {
157  auto constexpr kMsg = "Tuple has the wrong number of elements";
159  }
160  Tuple tup;
161  auto it = std::make_move_iterator(values_.begin());
162  Status status;
163  spanner_internal::ForEach(tup, ExtractValue{status}, it);
164  if (!status.ok()) return status;
165  return tup;
166  }
167 
168  /// @name Equality
169  ///@{
170  friend bool operator==(Row const& a, Row const& b);
171  friend bool operator!=(Row const& a, Row const& b) { return !(a == b); }
172  ///@}
173 
174  private:
175  friend struct spanner_internal::RowFriend;
176  struct ExtractValue {
177  Status& status;
178  template <typename T, typename It>
179  void operator()(T& t, It& it) const {
180  auto x = it++->template get<T>();
181  if (!x) {
182  status = std::move(x).status();
183  } else {
184  t = *std::move(x);
185  }
186  }
187  };
188 
189  /**
190  * Constructs a `Row` with the given @p values and @p columns.
191  *
192  * @note columns must not be nullptr
193  * @note columns.size() must equal values.size()
194  */
195  Row(std::vector<Value> values,
196  std::shared_ptr<const std::vector<std::string>> columns);
197 
198  std::vector<Value> values_;
199  std::shared_ptr<const std::vector<std::string>> columns_;
200 };
201 
202 /**
203  * Creates a `Row` with the specified column names and values.
204  *
205  * This overload accepts a vector of pairs, allowing the caller to specify both
206  * the column names and the `Value` that goes in each column.
207  *
208  * This function is intended for application developers who are mocking the
209  * results of a `Client::ExecuteQuery` call.
210  */
212 Row MakeTestRow(std::vector<std::pair<std::string, Value>> pairs);
213 
214 /**
215  * Creates a `Row` with `Value`s created from the given arguments and with
216  * auto-generated column names.
217  *
218  * This overload accepts a variadic list of arguments that will be used to
219  * create the `Value`s in the row. The column names will be implicitly
220  * generated, the first column being "0", the second "1", and so on,
221  * corresponding to the argument's position.
222  *
223  * This function is intended for application developers who are mocking the
224  * results of a `Client::ExecuteQuery` call.
225  */
226 template <typename... Ts>
228 Row MakeTestRow(Ts&&... ts) {
229  auto columns = std::make_shared<std::vector<std::string>>();
230  for (std::size_t i = 0; i < sizeof...(ts); ++i) {
231  columns->emplace_back(std::to_string(i));
232  }
233  std::vector<Value> v{Value(std::forward<Ts>(ts))...};
234  return spanner_internal::RowFriend::MakeRow(std::move(v), std::move(columns));
235 }
236 
237 /**
238  * A `RowStreamIterator` is an _Input Iterator_ (see below) that returns a
239  * sequence of `StatusOr<Row>` objects.
240  *
241  * As an [Input Iterator][input-iterator], the sequence may only be consumed
242  * once. Default constructing a `RowStreamIterator` creates an instance that
243  * represents "end".
244  *
245  * @note The term "stream" in this name refers to the general nature
246  * of the the data source, and is not intended to suggest any similarity to
247  * C++'s I/O streams library. Syntactically, this class is an "iterator".
248  *
249  * [input-iterator]: https://en.cppreference.com/w/cpp/named_req/InputIterator
250  */
252  public:
253  /**
254  * A function that returns a sequence of `StatusOr<Row>` objects. Returning
255  * an empty `Row` indicates that there are no more rows to be returned.
256  */
257  using Source = std::function<StatusOr<Row>()>;
258 
259  /// @name Iterator type aliases
260  ///@{
261  using iterator_category = std::input_iterator_tag;
262  using value_type = StatusOr<Row>;
263  using difference_type = std::ptrdiff_t;
264  using pointer = value_type*;
265  using reference = value_type&;
266  using const_pointer = value_type const*;
267  using const_reference = value_type const&;
268  ///@}
269 
270  /// Default constructs an "end" iterator.
272 
273  /**
274  * Constructs a `RowStreamIterator` that will consume rows from the given
275  * @p source, which must not be `nullptr`.
276  */
277  explicit RowStreamIterator(Source source);
278 
279  reference operator*() { return row_; }
280  pointer operator->() { return &row_; }
281 
282  const_reference operator*() const { return row_; }
283  const_pointer operator->() const { return &row_; }
284 
287 
288  friend bool operator==(RowStreamIterator const&, RowStreamIterator const&);
289  friend bool operator!=(RowStreamIterator const&, RowStreamIterator const&);
290 
291  private:
292  bool row_ok_{true};
293  value_type row_{Row{}};
294  Source source_; // nullptr means "end"
295 };
296 
297 /**
298  * A `TupleStreamIterator<Tuple>` is an "Input Iterator" that wraps a
299  * `RowStreamIterator`, parsing its elements into a sequence of
300  * `StatusOr<Tuple>` objects.
301  *
302  * As an Input Iterator, the sequence may only be consumed once. See
303  * https://en.cppreference.com/w/cpp/named_req/InputIterator for more details.
304  *
305  * Default constructing this object creates an instance that represents "end".
306  *
307  * Each `Row` returned by the wrapped `RowStreamIterator` must be convertible
308  * to the specified `Tuple` template parameter.
309  *
310  * @note The term "stream" in this name refers to the general nature
311  * of the the data source, and is not intended to suggest any similarity to
312  * C++'s I/O streams library. Syntactically, this class is an "iterator".
313  *
314  * @tparam Tuple the std::tuple<...> to parse each `Row` into.
315  */
316 template <typename Tuple>
318  public:
319  /// @name Iterator type aliases
320  ///@{
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&;
328  ///@}
329 
330  /// Default constructs an "end" iterator.
331  TupleStreamIterator() = default;
332 
333  /// Creates an iterator that wraps the given `RowStreamIterator` range.
335  : it_(std::move(begin)), end_(std::move(end)) {
336  ParseTuple();
337  }
338 
339  reference operator*() { return tup_; }
340  pointer operator->() { return &tup_; }
341 
342  const_reference operator*() const { return tup_; }
343  const_pointer operator->() const { return &tup_; }
344 
346  if (!tup_ok_) {
347  it_ = end_;
348  return *this;
349  }
350  ++it_;
351  ParseTuple();
352  return *this;
353  }
354 
356  auto const old = *this;
357  ++*this;
358  return old;
359  }
360 
361  friend bool operator==(TupleStreamIterator const& a,
362  TupleStreamIterator const& b) {
363  return a.it_ == b.it_;
364  }
365 
366  friend bool operator!=(TupleStreamIterator const& a,
367  TupleStreamIterator const& b) {
368  return !(a == b);
369  }
370 
371  private:
372  void ParseTuple() {
373  if (it_ == end_) return;
374  tup_ = *it_ ? std::move(*it_)->template get<Tuple>() : it_->status();
375  tup_ok_ = tup_.ok();
376  }
377 
378  bool tup_ok_{false};
379  value_type tup_;
380  RowStreamIterator it_;
381  RowStreamIterator end_;
382 };
383 
384 /**
385  * A `TupleStream<Tuple>` defines a range that parses `Tuple` objects from the
386  * given range of `RowStreamIterator`s.
387  *
388  * Users create instances using the `StreamOf<T>(range)` non-member factory
389  * function (defined below). The following is a typical usage of this class in
390  * a range-for loop.
391  *
392  * @code
393  * auto row_range = ...
394  * using RowType = std::tuple<std::int64_t, std::string, bool>;
395  * for (auto const& row : StreamOf<RowType>(row_range)) {
396  * if (!row) {
397  * // Handle error;
398  * }
399  * std::int64_t x = std::get<0>(*row);
400  * ...
401  * }
402  * @endcode
403  *
404  * @note The term "stream" in this name refers to the general nature
405  * of the the data source, and is not intended to suggest any similarity to
406  * C++'s I/O streams library. Syntactically, this class is a "range"
407  * defined by two "iterator" objects of type `TupleStreamIterator<Tuple>`.
408  *
409  * @tparam Tuple the std::tuple<...> to parse each `Row` into.
410  */
411 template <typename Tuple>
412 class TupleStream {
413  public:
414  using iterator = TupleStreamIterator<Tuple>;
415  static_assert(spanner_internal::IsTuple<Tuple>::value,
416  "TupleStream<T> requires a std::tuple parameter");
417 
418  iterator begin() const { return begin_; }
419  iterator end() const { return end_; }
420 
421  private:
422  template <typename T, typename RowRange>
423  friend TupleStream<T> StreamOf(RowRange&& range);
424 
425  template <typename It>
426  explicit TupleStream(It&& start, It&& end)
427  : begin_(std::forward<It>(start), std::forward<It>(end)) {}
428 
429  iterator begin_;
430  iterator end_;
431 };
432 
433 /**
434  * A factory that creates a `TupleStream<Tuple>` by wrapping the given @p
435  * range. The `RowRange` must be a range defined by `RowStreamIterator`
436  * objects.
437  *
438  * @snippet samples.cc stream-of
439  *
440  * @note Ownership of the @p range is not transferred, so it must outlive the
441  * returned `TupleStream`.
442  *
443  * @tparam RowRange must be a range defined by `RowStreamIterator`s.
444  */
445 template <typename Tuple, typename RowRange>
446 TupleStream<Tuple> StreamOf(RowRange&& range) {
447  static_assert(std::is_lvalue_reference<decltype(range)>::value,
448  "range must be an lvalue since it must outlive StreamOf");
449  return TupleStream<Tuple>(std::begin(std::forward<RowRange>(range)),
450  std::end(std::forward<RowRange>(range)));
451 }
452 
453 /**
454  * Returns the only row from a range that contains exactly one row.
455  *
456  * An error is returned if the given range does not contain exactly one row.
457  * This is a convenience function that may be useful when the caller knows that
458  * a range should contain exactly one row, such as when `LIMIT 1` is used in an
459  * SQL query, or when a read is performed on a guaranteed unique key such that
460  * only a single row could possibly match. In cases where the caller does not
461  * know how many rows may be returned, they should instead consume the range in
462  * a loop.
463  *
464  * @snippet samples.cc get-singular-row
465  */
466 template <typename RowRange>
467 auto GetSingularRow(RowRange range) ->
468  typename std::decay<decltype(*range.begin())>::type {
469  auto const e = range.end();
470  auto it = range.begin();
471  if (it == e) return Status(StatusCode::kInvalidArgument, "no rows");
472  auto row = std::move(*it);
473  if (++it != e) return Status(StatusCode::kInvalidArgument, "too many rows");
474  return row;
475 }
476 
478 } // namespace spanner
479 } // namespace cloud
480 } // namespace google
481 
482 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H