Google Cloud Spanner C++ Client 2.13.0
A C++ Client Library for Google Cloud Spanner
Loading...
Searching...
No Matches
row.h
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
32namespace google {
33namespace cloud {
34namespace spanner {
35GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
36class Row;
37GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
38} // namespace spanner
39
40namespace spanner_internal {
41GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
42struct RowFriend {
43 static spanner::Row MakeRow(std::vector<spanner::Value>,
44 std::shared_ptr<std::vector<std::string> const>);
45};
46GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
47} // namespace spanner_internal
48
49namespace spanner {
50GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
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 */
84class 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";
138 return Status(StatusCode::kInvalidArgument, kMsg);
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";
158 return Status(StatusCode::kInvalidArgument, kMsg);
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 */
212Row 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 */
226template <typename... Ts>
228Row 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 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 */
251class RowStreamIterator {
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 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 */
316template <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_;
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 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 */
411template <typename Tuple>
412class 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 */
445template <typename Tuple, typename RowRange>
446TupleStream<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 */
466template <typename RowRange>
467auto 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
477GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
478} // namespace spanner
479} // namespace cloud
480} // namespace google
481
482#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_ROW_H
T const * operator->() const &
Status const & status() const &
Status(StatusCode code, std::string message, ErrorInfo info={})
A RowStreamIterator is an Input Iterator (see below) that returns a sequence of StatusOr<Row> objects...
Definition: row.h:251
friend bool operator==(RowStreamIterator const &, RowStreamIterator const &)
reference operator*()
Definition: row.h:279
const_reference operator*() const
Definition: row.h:282
friend bool operator!=(RowStreamIterator const &, RowStreamIterator const &)
pointer operator->()
Definition: row.h:280
RowStreamIterator()
Default constructs an "end" iterator.
RowStreamIterator(Source source)
Constructs a RowStreamIterator that will consume rows from the given source, which must not be nullpt...
const_pointer operator->() const
Definition: row.h:283
A Row is a sequence of columns each with a name and an associated Value.
Definition: row.h:84
Row & operator=(Row const &)=default
friend bool operator==(Row const &a, Row const &b)
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:135
Row(Row const &)=default
std::size_t size() const
Returns the number of columns in the row.
Definition: row.h:98
StatusOr< Tuple > get() &&
Returns all the native C++ values for the whole row in a std::tuple with the specified type.
Definition: row.h:155
Row & operator=(Row &&)=default
std::vector< Value > const & values() const &
Returns the Value objects in the given row.
Definition: row.h:104
StatusOr< Value > get(std::string const &name) const
Returns the Value in the column with name.
StatusOr< T > get(Arg &&arg) const
Returns the native C++ value at the given position or column name.
Definition: row.h:122
friend bool operator!=(Row const &a, Row const &b)
Definition: row.h:171
Row()
Default constructs an empty row with no columns nor values.
std::vector< Value > && values() &&
Returns the Value objects in the given row.
Definition: row.h:107
std::vector< std::string > const & columns() const
Returns the column names for the row.
Definition: row.h:101
StatusOr< Value > get(std::size_t pos) const
Returns the Value at the given pos.
A TupleStreamIterator<Tuple> is an "Input Iterator" that wraps a RowStreamIterator,...
Definition: row.h:317
TupleStreamIterator(RowStreamIterator begin, RowStreamIterator end)
Creates an iterator that wraps the given RowStreamIterator range.
Definition: row.h:334
TupleStreamIterator operator++(int)
Definition: row.h:355
reference operator*()
Definition: row.h:339
friend bool operator==(TupleStreamIterator const &a, TupleStreamIterator const &b)
Definition: row.h:361
pointer operator->()
Definition: row.h:340
TupleStreamIterator & operator++()
Definition: row.h:345
const_pointer operator->() const
Definition: row.h:343
const_reference operator*() const
Definition: row.h:342
friend bool operator!=(TupleStreamIterator const &a, TupleStreamIterator const &b)
Definition: row.h:366
TupleStreamIterator()=default
Default constructs an "end" iterator.
A TupleStream<Tuple> defines a range that parses Tuple objects from the given range of RowStreamItera...
Definition: row.h:412
iterator end() const
Definition: row.h:419
iterator begin() const
Definition: row.h:418
friend TupleStream< T > StreamOf(RowRange &&range)
A factory that creates a TupleStream<Tuple> by wrapping the given range.
Definition: row.h:446
The Value class represents a type-safe, nullable Spanner value.
Definition: value.h:170
Contains all the Cloud Spanner C++ client types and functions.
Definition: backoff_policy.h:23
TupleStream< Tuple > StreamOf(RowRange &&range)
A factory that creates a TupleStream<Tuple> by wrapping the given range.
Definition: row.h:446
Row MakeTestRow(Ts &&... ts)
Creates a Row with Values created from the given arguments and with auto-generated column names.
Definition: row.h:228
auto GetSingularRow(RowRange range) -> typename std::decay< decltype(*range.begin())>::type
Returns the only row from a range that contains exactly one row.
Definition: row.h:467
Row MakeTestRow(std::vector< std::pair< std::string, Value > > pairs)
Creates a Row with the specified column names and values.
#define GOOGLE_CLOUD_CPP_SPANNER_MAKE_TEST_ROW_DEPRECATED()
Definition: version.h:30