Google Cloud Spanner C++ Client  2.5.0
A C++ Client Library for Google Cloud Spanner
value.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_VALUE_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H
17 
18 #include "google/cloud/spanner/bytes.h"
19 #include "google/cloud/spanner/date.h"
20 #include "google/cloud/spanner/internal/tuple_utils.h"
21 #include "google/cloud/spanner/json.h"
22 #include "google/cloud/spanner/numeric.h"
23 #include "google/cloud/spanner/timestamp.h"
24 #include "google/cloud/spanner/version.h"
25 #include "google/cloud/internal/throw_delegate.h"
26 #include "google/cloud/optional.h"
27 #include "google/cloud/status_or.h"
28 #include "absl/time/civil_time.h"
29 #include "absl/types/optional.h"
30 #include <google/protobuf/struct.pb.h>
31 #include <google/protobuf/util/message_differencer.h>
32 #include <google/spanner/v1/type.pb.h>
33 #include <ostream>
34 #include <string>
35 #include <tuple>
36 #include <type_traits>
37 #include <utility>
38 #include <vector>
39 
40 namespace google {
41 namespace cloud {
42 namespace spanner_internal {
44 struct ValueInternals;
46 } // namespace spanner_internal
47 
48 namespace spanner {
50 
51 /**
52  * The Value class represents a type-safe, nullable Spanner value.
53  *
54  * It is conceptually similar to a `std::any` except the only allowed types are
55  * those supported by Spanner, and a "null" value (similar to a `std::any`
56  * without a value) still has an associated type. The supported types are shown
57  * in the following table along with how they map to the Spanner types
58  * (https://cloud.google.com/spanner/docs/data-types):
59  *
60  * Spanner Type | C++ Type `T`
61  * ------------ | ------------
62  * BOOL | `bool`
63  * INT64 | `std::int64_t`
64  * FLOAT64 | `double`
65  * STRING | `std::string`
66  * BYTES | `google::cloud::spanner::Bytes`
67  * JSON | `google::cloud::spanner::Json`
68  * JSONB | `google::cloud::spanner::JsonB`
69  * NUMERIC | `google::cloud::spanner::Numeric`
70  * NUMERIC(PG) | `google::cloud::spanner::PgNumeric`
71  * TIMESTAMP | `google::cloud::spanner::Timestamp`
72  * DATE | `absl::CivilDay`
73  * ARRAY | `std::vector<T>` // [1]
74  * STRUCT | `std::tuple<Ts...>`
75  *
76  * [1] The type `T` may be any of the other supported types, except for
77  * ARRAY/`std::vector`.
78  *
79  * Value is a regular C++ value type with support for copy, move, equality,
80  * etc. A default-constructed Value represents an empty value with no type.
81  *
82  * @note There is also a C++ type of `CommitTimestamp` that corresponds to a
83  * Cloud Spanner TIMESTAMP object for setting the commit timestamp on a
84  * column with the `allow_commit_timestamp` set to `true` in the schema.
85  *
86  * @see https://cloud.google.com/spanner/docs/commit-timestamp
87  *
88  * Callers may create instances by passing any of the supported values
89  * (shown in the table above) to the constructor. "Null" values are created
90  * using the `MakeNullValue<T>()` factory function or by passing an empty
91  * `absl::optional<T>` to the Value constructor..
92  *
93  * @par Example with a non-null value
94  *
95  * @code
96  * std::string msg = "hello";
97  * spanner::Value v(msg);
98  * StatusOr<std::string> copy = v.get<std::string>();
99  * if (copy) {
100  * std::cout << *copy; // prints "hello"
101  * }
102  * @endcode
103  *
104  * @par Example with a null
105  *
106  * @code
107  * spanner::Value v = spanner::MakeNullValue<std::int64_t>();
108  * StatusOr<std::int64_t> i = v.get<std::int64_t>();
109  * assert(!i.ok()); // Can't get the value because v is null
110  * StatusOr < absl::optional<std::int64_t> j =
111  * v.get<absl::optional<std::int64_t>>();
112  * assert(j.ok()); // OK because an empty option can represent the null
113  * assert(!j->has_value()); // v held no value.
114  * @endcode
115  *
116  * @par Nullness
117  *
118  * All of the supported types (above) are "nullable". A null is created in one
119  * of two ways:
120  *
121  * 1. Passing an `absl::optional<T>()` with no value to `Value`'s constructor.
122  * 2. Using the `MakeNullValue<T>()` helper function (defined below).
123  *
124  * Nulls can be retrieved from a `Value::get<T>` by specifying the type `T`
125  * as an `absl::optional<U>`. The returned optional will either be empty
126  * (indicating null) or it will contain the actual value. See the documentation
127  * for `Value::get<T>` below for more details.
128  *
129  * @par Spanner Arrays (i.e., `std::vector<T>`)
130  *
131  * Spanner arrays are represented in C++ as a `std::vector<T>`, where the type
132  * `T` may be any of the other allowed Spanner types, such as `bool`,
133  * `std::int64_t`, etc. The only exception is that arrays may not directly
134  * contain another array; to achieve a similar result you could create an array
135  * of a 1-element struct holding an array. The following examples show usage of
136  * arrays.
137  *
138  * @code
139  * std::vector<std::int64_t> vec = {1, 2, 3, 4, 5};
140  * spanner::Value v(vec);
141  * auto copy = *v.get<std::vector<std::int64_t>>();
142  * assert(vec == copy);
143  * @endcode
144  *
145  * @par Spanner Structs (i.e., `std::tuple<Ts...>`)
146  *
147  * Spanner structs are represented in C++ as instances of `std::tuple` holding
148  * zero or more of the allowed Spanner types, such as `bool`, `std::int64_t`,
149  * `std::vector`, and even other `std::tuple` objects. Each tuple element
150  * corresponds to a single field in a Spanner STRUCT.
151  *
152  * Spanner STRUCT fields may optionally contain a string indicating the field's
153  * name. Fields names may be empty, unique, or repeated. A named field may be
154  * specified as a tuple element of type `std::pair<std::string, T>`, where the
155  * pair's `.first` member indicates the field's name, and the `.second` member
156  * is any valid Spanner type `T`.
157  *
158  * @code
159  * using Struct = std::tuple<bool, std::pair<std::string, std::int64_t>>;
160  * Struct s = {true, {"Foo", 42}};
161  * spanner::Value v(s);
162  * assert(s == *v.get<Struct>());
163  * @endcode
164  *
165  * @note While a STRUCT's (optional) field names are not part of its C++ type,
166  * they are part of its Spanner STRUCT type. Array's (i.e., `std::vector`)
167  * must contain a single element type, therefore it is an error to construct
168  * a `std::vector` of `std::tuple` objects with differently named fields.
169  */
170 class Value {
171  public:
172  /**
173  * Constructs a `Value` that holds nothing.
174  *
175  * All calls to `get<T>()` will return an error.
176  */
177  Value() = default;
178 
179  // Copy and move.
180  Value(Value const&) = default;
181  Value(Value&&) = default;
182  Value& operator=(Value const&) = default;
183  Value& operator=(Value&&) = default;
184 
185  /// Constructs an instance with the specified type and value.
186  explicit Value(bool v) : Value(PrivateConstructor{}, v) {}
187  /// @copydoc Value(bool)
188  explicit Value(std::int64_t v) : Value(PrivateConstructor{}, v) {}
189  /// @copydoc Value(bool)
190  explicit Value(double v) : Value(PrivateConstructor{}, v) {}
191  /// @copydoc Value(bool)
192  explicit Value(std::string v) : Value(PrivateConstructor{}, std::move(v)) {}
193  /// @copydoc Value(bool)
194  explicit Value(Bytes v) : Value(PrivateConstructor{}, std::move(v)) {}
195  /// @copydoc Value(bool)
196  explicit Value(Json v) : Value(PrivateConstructor{}, std::move(v)) {}
197  /// @copydoc Value(bool)
198  explicit Value(JsonB v) : Value(PrivateConstructor{}, std::move(v)) {}
199  /// @copydoc Value(bool)
200  explicit Value(Numeric v) : Value(PrivateConstructor{}, std::move(v)) {}
201  /// @copydoc Value(bool)
202  explicit Value(PgNumeric v) : Value(PrivateConstructor{}, std::move(v)) {}
203  /// @copydoc Value(bool)
204  explicit Value(Timestamp v) : Value(PrivateConstructor{}, std::move(v)) {}
205  /// @copydoc Value(bool)
206  explicit Value(CommitTimestamp v)
207  : Value(PrivateConstructor{}, std::move(v)) {}
208  /// @copydoc Value(bool)
209  explicit Value(absl::CivilDay v)
210  : Value(PrivateConstructor{}, std::move(v)) {}
211 
212  /**
213  * Constructs an instance from common C++ literal types that closely, though
214  * not exactly, match supported Spanner types.
215  *
216  * An integer literal in C++ is of type `int`, which is not exactly an
217  * allowed Spanner type. This will be allowed but it will be implicitly up
218  * converted to a `std::int64_t`. Similarly, a C++ string literal will be
219  * implicitly converted to a `std::string`. For example:
220  *
221  * @code
222  * spanner::Value v1(42);
223  * assert(42 == *v1.get<std::int64_t>());
224  *
225  * spanner::Value v2("hello");
226  * assert("hello" == *v2.get<std::string>());
227  * @endcode
228  */
229  explicit Value(int v) : Value(PrivateConstructor{}, v) {}
230  /// @copydoc Value(int)
231  explicit Value(char const* v) : Value(PrivateConstructor{}, v) {}
232 
233  /**
234  * Constructs a non-null instance if `opt` has a value, otherwise constructs
235  * a null instance with the specified type `T`.
236  */
237  template <typename T>
238  explicit Value(absl::optional<T> opt)
239  : Value(PrivateConstructor{}, std::move(opt)) {}
240 
241  /**
242  * Constructs an instance from a Spanner ARRAY of the specified type and
243  * values.
244  *
245  * The type `T` may be any valid type shown above, except vectors of vectors
246  * are not allowed.
247  *
248  * @warning If `T` is a `std::tuple` with field names (i.e., at least one of
249  * its element types is a `std::pair<std::string, T>`) then, all of the
250  * vector's elements must have exactly the same field names. Any mismatch
251  * in in field names results in undefined behavior.
252  */
253  template <typename T>
254  explicit Value(std::vector<T> v) : Value(PrivateConstructor{}, std::move(v)) {
255  static_assert(!IsVector<typename std::decay<T>::type>::value,
256  "vector of vector not allowed. See value.h documentation.");
257  }
258 
259  /**
260  * Constructs an instance from a Spanner STRUCT with a type and values
261  * matching the given `std::tuple`.
262  *
263  * Any STRUCT field may optionally have a name, which is specified as
264  * `std::pair<std::string, T>`.
265  */
266  template <typename... Ts>
267  explicit Value(std::tuple<Ts...> tup)
268  : Value(PrivateConstructor{}, std::move(tup)) {}
269 
270  friend bool operator==(Value const& a, Value const& b);
271  friend bool operator!=(Value const& a, Value const& b) { return !(a == b); }
272 
273  /**
274  * Returns the contained value wrapped in a `google::cloud::StatusOr<T>`.
275  *
276  * Returns a non-OK status IFF:
277  *
278  * * The contained value is "null", and `T` is not an `absl::optional`.
279  * * There is an error converting the contained value to `T`.
280  *
281  * @par Example
282  *
283  * @code
284  * spanner::Value v{3.14};
285  * StatusOr<double> d = v.get<double>();
286  * if (d) {
287  * std::cout << "d=" << *d;
288  * }
289  *
290  * // Now using a "null" std::int64_t
291  * v = spanner::MakeNullValue<std::int64_t>();
292  * StatusOr<std::int64_t> i = v.get<std::int64_t>();
293  * if (!i) {
294  * std::cerr << "Could not get integer: " << i.status();
295  * }
296  * StatusOr<absl::optional<std::int64_t>> j =
297  * v.get<absl::optional<std::int64_t>>();
298  * assert(j.ok()); // Since we know the types match in this example
299  * assert(!v->has_value()); // Since we know v was null in this example
300  * @endcode
301  */
302  template <typename T>
303  StatusOr<T> get() const& {
304  if (!TypeProtoIs(T{}, type_))
305  return Status(StatusCode::kUnknown, "wrong type");
306  if (value_.kind_case() == google::protobuf::Value::kNullValue) {
307  if (IsOptional<T>::value) return T{};
308  return Status(StatusCode::kUnknown, "null value");
309  }
310  return GetValue(T{}, value_, type_);
311  }
312 
313  /// @copydoc get()
314  template <typename T>
315  StatusOr<T> get() && {
316  if (!TypeProtoIs(T{}, type_))
317  return Status(StatusCode::kUnknown, "wrong type");
318  if (value_.kind_case() == google::protobuf::Value::kNullValue) {
319  if (IsOptional<T>::value) return T{};
320  return Status(StatusCode::kUnknown, "null value");
321  }
322  auto tag = T{}; // Works around an odd msvc issue
323  return GetValue(std::move(tag), std::move(value_), type_);
324  }
325 
326  /**
327  * Outputs string representation of a given Value to the provided stream.
328  *
329  * @warning This is intended for debugging and human consumption only, not
330  * machine consumption, as the output format may change without notice.
331  *
332  * @par Example:
333  * @code
334  * spanner::Value v{42};
335  * std::cout << v << "\n";
336  * @endcode
337  */
338  friend std::ostream& operator<<(std::ostream& os, Value const& v);
339 
340  /**
341  * Prints the same output as `operator<<`.
342  *
343  * @warning DO NOT CALL. This function will be removed in a future release.
344  * Use `operator<<` instead.
345  */
346  friend void PrintTo(Value const& v, std::ostream* os) { *os << v; }
347 
348  private:
349  // Metafunction that returns true if `T` is an `absl::optional<U>`
350  template <typename T>
351  struct IsOptional : std::false_type {};
352  template <typename T>
353  struct IsOptional<absl::optional<T>> : std::true_type {};
354 
355  // Metafunction that returns true if `T` is a std::vector<U>
356  template <typename T>
357  struct IsVector : std::false_type {};
358  template <typename... Ts>
359  struct IsVector<std::vector<Ts...>> : std::true_type {};
360 
361  // Tag-dispatch overloads to check if a C++ type matches the type specified
362  // by the given `Type` proto.
363  static bool TypeProtoIs(bool, google::spanner::v1::Type const&);
364  static bool TypeProtoIs(std::int64_t, google::spanner::v1::Type const&);
365  static bool TypeProtoIs(double, google::spanner::v1::Type const&);
366  static bool TypeProtoIs(Timestamp, google::spanner::v1::Type const&);
367  static bool TypeProtoIs(CommitTimestamp, google::spanner::v1::Type const&);
368  static bool TypeProtoIs(absl::CivilDay, google::spanner::v1::Type const&);
369  static bool TypeProtoIs(std::string const&, google::spanner::v1::Type const&);
370  static bool TypeProtoIs(Bytes const&, google::spanner::v1::Type const&);
371  static bool TypeProtoIs(Json const&, google::spanner::v1::Type const&);
372  static bool TypeProtoIs(JsonB const&, google::spanner::v1::Type const&);
373  static bool TypeProtoIs(Numeric const&, google::spanner::v1::Type const&);
374  static bool TypeProtoIs(PgNumeric const&, google::spanner::v1::Type const&);
375  template <typename T>
376  static bool TypeProtoIs(absl::optional<T>,
377  google::spanner::v1::Type const& type) {
378  return TypeProtoIs(T{}, type);
379  }
380  template <typename T>
381  static bool TypeProtoIs(std::vector<T> const&,
382  google::spanner::v1::Type const& type) {
383  return type.code() == google::spanner::v1::TypeCode::ARRAY &&
384  TypeProtoIs(T{}, type.array_element_type());
385  }
386  template <typename... Ts>
387  static bool TypeProtoIs(std::tuple<Ts...> const& tup,
388  google::spanner::v1::Type const& type) {
389  bool ok = type.code() == google::spanner::v1::TypeCode::STRUCT;
390  ok = ok && type.struct_type().fields().size() == sizeof...(Ts);
391  spanner_internal::ForEach(tup, IsStructTypeProto{ok, 0},
392  type.struct_type());
393  return ok;
394  }
395 
396  // A functor to be used with internal::ForEach to check if a StructType proto
397  // matches the types in a std::tuple.
398  struct IsStructTypeProto {
399  bool& ok;
400  int field;
401  template <typename T>
402  void operator()(T const&, google::spanner::v1::StructType const& type) {
403  ok = ok && TypeProtoIs(T{}, type.fields(field).type());
404  ++field;
405  }
406  template <typename T>
407  void operator()(std::pair<std::string, T> const&,
408  google::spanner::v1::StructType const& type) {
409  operator()(T{}, type);
410  }
411  };
412 
413  // Tag-dispatch overloads to convert a C++ type to a `Type` protobuf. The
414  // argument type is the tag, the argument value is ignored.
415  static google::spanner::v1::Type MakeTypeProto(bool);
416  static google::spanner::v1::Type MakeTypeProto(std::int64_t);
417  static google::spanner::v1::Type MakeTypeProto(double);
418  static google::spanner::v1::Type MakeTypeProto(std::string const&);
419  static google::spanner::v1::Type MakeTypeProto(Bytes const&);
420  static google::spanner::v1::Type MakeTypeProto(Json const&);
421  static google::spanner::v1::Type MakeTypeProto(JsonB const&);
422  static google::spanner::v1::Type MakeTypeProto(Numeric const&);
423  static google::spanner::v1::Type MakeTypeProto(PgNumeric const&);
424  static google::spanner::v1::Type MakeTypeProto(Timestamp);
425  static google::spanner::v1::Type MakeTypeProto(CommitTimestamp);
426  static google::spanner::v1::Type MakeTypeProto(absl::CivilDay);
427  static google::spanner::v1::Type MakeTypeProto(int);
428  static google::spanner::v1::Type MakeTypeProto(char const*);
429  template <typename T>
430  static google::spanner::v1::Type MakeTypeProto(absl::optional<T> const&) {
431  return MakeTypeProto(T{});
432  }
433  template <typename T>
434  static google::spanner::v1::Type MakeTypeProto(std::vector<T> const& v) {
435  google::spanner::v1::Type t;
436  t.set_code(google::spanner::v1::TypeCode::ARRAY);
437  *t.mutable_array_element_type() = MakeTypeProto(v.empty() ? T{} : v[0]);
438  // Checks that vector elements have exactly the same proto Type, which
439  // includes field names. This is documented UB.
440  for (auto&& e : v) {
441  if (!google::protobuf::util::MessageDifferencer::Equals(
442  MakeTypeProto(e), t.array_element_type())) {
443  google::cloud::internal::ThrowInvalidArgument("Mismatched types");
444  }
445  }
446  return t;
447  }
448  template <typename... Ts>
449  static google::spanner::v1::Type MakeTypeProto(std::tuple<Ts...> const& tup) {
450  google::spanner::v1::Type t;
451  t.set_code(google::spanner::v1::TypeCode::STRUCT);
452  spanner_internal::ForEach(tup, AddStructTypes{}, *t.mutable_struct_type());
453  return t;
454  }
455 
456  // A functor to be used with internal::ForEach to add type protos for all the
457  // elements of a tuple.
458  struct AddStructTypes {
459  template <typename T>
460  void operator()(T const& t,
461  google::spanner::v1::StructType& struct_type) const {
462  auto* field = struct_type.add_fields();
463  *field->mutable_type() = MakeTypeProto(t);
464  }
465  template <typename S, typename T,
466  typename std::enable_if<
467  std::is_convertible<S, std::string>::value, int>::type = 0>
468  void operator()(std::pair<S, T> const& p,
469  google::spanner::v1::StructType& struct_type) const {
470  auto* field = struct_type.add_fields();
471  field->set_name(p.first);
472  *field->mutable_type() = MakeTypeProto(p.second);
473  }
474  };
475 
476  // Encodes the argument as a protobuf according to the rules described in
477  // https://github.com/googleapis/googleapis/blob/master/google/spanner/v1/type.proto
478  static google::protobuf::Value MakeValueProto(bool b);
479  static google::protobuf::Value MakeValueProto(std::int64_t i);
480  static google::protobuf::Value MakeValueProto(double d);
481  static google::protobuf::Value MakeValueProto(std::string s);
482  static google::protobuf::Value MakeValueProto(Bytes b);
483  static google::protobuf::Value MakeValueProto(Json j);
484  static google::protobuf::Value MakeValueProto(JsonB j);
485  static google::protobuf::Value MakeValueProto(Numeric n);
486  static google::protobuf::Value MakeValueProto(PgNumeric n);
487  static google::protobuf::Value MakeValueProto(Timestamp ts);
488  static google::protobuf::Value MakeValueProto(CommitTimestamp ts);
489  static google::protobuf::Value MakeValueProto(absl::CivilDay d);
490  static google::protobuf::Value MakeValueProto(int i);
491  static google::protobuf::Value MakeValueProto(char const* s);
492  template <typename T>
493  static google::protobuf::Value MakeValueProto(absl::optional<T> opt) {
494  if (opt.has_value()) return MakeValueProto(*std::move(opt));
495  google::protobuf::Value v;
496  v.set_null_value(google::protobuf::NullValue::NULL_VALUE);
497  return v;
498  }
499  template <typename T>
500  static google::protobuf::Value MakeValueProto(std::vector<T> vec) {
501  google::protobuf::Value v;
502  auto& list = *v.mutable_list_value();
503  for (auto&& e : vec) {
504  *list.add_values() = MakeValueProto(std::move(e));
505  }
506  return v;
507  }
508  template <typename... Ts>
509  static google::protobuf::Value MakeValueProto(std::tuple<Ts...> tup) {
510  google::protobuf::Value v;
511  spanner_internal::ForEach(tup, AddStructValues{}, *v.mutable_list_value());
512  return v;
513  }
514 
515  // A functor to be used with internal::ForEach to add Value protos for all
516  // the elements of a tuple.
517  struct AddStructValues {
518  template <typename T>
519  void operator()(T& t, google::protobuf::ListValue& list_value) const {
520  *list_value.add_values() = MakeValueProto(std::move(t));
521  }
522  template <typename S, typename T,
523  typename std::enable_if<
524  std::is_convertible<S, std::string>::value, int>::type = 0>
525  void operator()(std::pair<S, T> p,
526  google::protobuf::ListValue& list_value) const {
527  *list_value.add_values() = MakeValueProto(std::move(p.second));
528  }
529  };
530 
531  // Tag-dispatch overloads to extract a C++ value from a `Value` protobuf. The
532  // first argument type is the tag, its value is ignored.
533  static StatusOr<bool> GetValue(bool, google::protobuf::Value const&,
534  google::spanner::v1::Type const&);
535  static StatusOr<std::int64_t> GetValue(std::int64_t,
536  google::protobuf::Value const&,
537  google::spanner::v1::Type const&);
538  static StatusOr<double> GetValue(double, google::protobuf::Value const&,
539  google::spanner::v1::Type const&);
540  static StatusOr<std::string> GetValue(std::string const&,
541  google::protobuf::Value const&,
542  google::spanner::v1::Type const&);
543  static StatusOr<std::string> GetValue(std::string const&,
544  google::protobuf::Value&&,
545  google::spanner::v1::Type const&);
546  static StatusOr<Bytes> GetValue(Bytes const&, google::protobuf::Value const&,
547  google::spanner::v1::Type const&);
548  static StatusOr<Json> GetValue(Json const&, google::protobuf::Value const&,
549  google::spanner::v1::Type const&);
550  static StatusOr<JsonB> GetValue(JsonB const&, google::protobuf::Value const&,
551  google::spanner::v1::Type const&);
552  static StatusOr<Numeric> GetValue(Numeric const&,
553  google::protobuf::Value const&,
554  google::spanner::v1::Type const&);
555  static StatusOr<PgNumeric> GetValue(PgNumeric const&,
556  google::protobuf::Value const&,
557  google::spanner::v1::Type const&);
558  static StatusOr<Timestamp> GetValue(Timestamp, google::protobuf::Value const&,
559  google::spanner::v1::Type const&);
560  static StatusOr<CommitTimestamp> GetValue(CommitTimestamp,
561  google::protobuf::Value const&,
562  google::spanner::v1::Type const&);
563  static StatusOr<absl::CivilDay> GetValue(absl::CivilDay,
564  google::protobuf::Value const&,
565  google::spanner::v1::Type const&);
566  template <typename T, typename V>
567  static StatusOr<absl::optional<T>> GetValue(
568  absl::optional<T> const&, V&& pv, google::spanner::v1::Type const& pt) {
569  if (pv.kind_case() == google::protobuf::Value::kNullValue) {
570  return absl::optional<T>{};
571  }
572  auto value = GetValue(T{}, std::forward<V>(pv), pt);
573  if (!value) return std::move(value).status();
574  return absl::optional<T>{*std::move(value)};
575  }
576  template <typename T, typename V>
577  static StatusOr<std::vector<T>> GetValue(
578  std::vector<T> const&, V&& pv, google::spanner::v1::Type const& pt) {
579  if (pv.kind_case() != google::protobuf::Value::kListValue) {
580  return Status(StatusCode::kUnknown, "missing ARRAY");
581  }
582  std::vector<T> v;
583  for (int i = 0; i < pv.list_value().values().size(); ++i) {
584  auto&& e = GetProtoListValueElement(std::forward<V>(pv), i);
585  using ET = decltype(e);
586  auto value = GetValue(T{}, std::forward<ET>(e), pt.array_element_type());
587  if (!value) return std::move(value).status();
588  v.push_back(*std::move(value));
589  }
590  return v;
591  }
592  template <typename V, typename... Ts>
593  static StatusOr<std::tuple<Ts...>> GetValue(
594  std::tuple<Ts...> const&, V&& pv, google::spanner::v1::Type const& pt) {
595  if (pv.kind_case() != google::protobuf::Value::kListValue) {
596  return Status(StatusCode::kUnknown, "missing STRUCT");
597  }
598  std::tuple<Ts...> tup;
599  Status status; // OK
600  ExtractTupleValues<V> f{status, 0, std::forward<V>(pv), pt};
601  spanner_internal::ForEach(tup, f);
602  if (!status.ok()) return status;
603  return tup;
604  }
605 
606  // A functor to be used with internal::ForEach to extract C++ types from a
607  // ListValue proto and store then in a tuple.
608  template <typename V>
609  struct ExtractTupleValues {
610  Status& status;
611  int i;
612  V&& pv;
613  google::spanner::v1::Type const& type;
614  template <typename T>
615  void operator()(T& t) {
616  auto&& e = GetProtoListValueElement(std::forward<V>(pv), i);
617  using ET = decltype(e);
618  auto value = GetValue(T{}, std::forward<ET>(e), type);
619  ++i;
620  if (!value) {
621  status = std::move(value).status();
622  } else {
623  t = *std::move(value);
624  }
625  }
626  template <typename T>
627  void operator()(std::pair<std::string, T>& p) {
628  p.first = type.struct_type().fields(i).name();
629  auto&& e = GetProtoListValueElement(std::forward<V>(pv), i);
630  using ET = decltype(e);
631  auto value = GetValue(T{}, std::forward<ET>(e), type);
632  ++i;
633  if (!value) {
634  status = std::move(value).status();
635  } else {
636  p.second = *std::move(value);
637  }
638  }
639  };
640 
641  // Protocol buffers are not friendly to generic programming, because they use
642  // different syntax and different names for mutable and non-mutable
643  // functions. To make GetValue(vector<T>, ...) (above) work, we need split
644  // the different protobuf syntaxes into overloaded functions.
645  static google::protobuf::Value const& GetProtoListValueElement(
646  google::protobuf::Value const& pv, int pos) {
647  return pv.list_value().values(pos);
648  }
649  static google::protobuf::Value&& GetProtoListValueElement(
650  google::protobuf::Value&& pv, int pos) {
651  return std::move(*pv.mutable_list_value()->mutable_values(pos));
652  }
653 
654  // A private templated constructor that is called by all the public
655  // constructors to set the type_ and value_ members. The `PrivateConstructor`
656  // type is used so that this overload is never chosen for
657  // non-member/non-friend callers. Otherwise, since visibility restrictions
658  // apply after overload resolution, users could get weird error messages if
659  // this constructor matched their arguments best.
660  struct PrivateConstructor {};
661  template <typename T>
662  Value(PrivateConstructor, T&& t)
663  : type_(MakeTypeProto(t)), value_(MakeValueProto(std::forward<T>(t))) {}
664 
665  Value(google::spanner::v1::Type t, google::protobuf::Value v)
666  : type_(std::move(t)), value_(std::move(v)) {}
667 
668  friend struct spanner_internal::ValueInternals;
669 
670  google::spanner::v1::Type type_;
671  google::protobuf::Value value_;
672 };
673 
674 /**
675  * Factory to construct a "null" Value of the specified type `T`.
676  *
677  * This is equivalent to passing an `absl::optional<T>` without a value to
678  * the constructor, though this factory may be easier to invoke and result
679  * in clearer code at the call site.
680  */
681 template <typename T>
683  return Value(absl::optional<T>{});
684 }
685 
687 } // namespace spanner
688 
689 namespace spanner_internal {
691 
692 struct ValueInternals {
693  static spanner::Value FromProto(google::spanner::v1::Type t,
694  google::protobuf::Value v) {
695  return spanner::Value(std::move(t), std::move(v));
696  }
697 
698  static std::pair<google::spanner::v1::Type, google::protobuf::Value> ToProto(
699  spanner::Value v) {
700  return std::make_pair(std::move(v.type_), std::move(v.value_));
701  }
702 };
703 
704 inline spanner::Value FromProto(google::spanner::v1::Type t,
705  google::protobuf::Value v) {
706  return ValueInternals::FromProto(std::move(t), std::move(v));
707 }
708 
709 inline std::pair<google::spanner::v1::Type, google::protobuf::Value> ToProto(
710  spanner::Value v) {
711  return ValueInternals::ToProto(std::move(v));
712 }
713 
715 } // namespace spanner_internal
716 } // namespace cloud
717 } // namespace google
718 
719 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H