15 #ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_VALUE_H
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>
36 #include <type_traits>
42 namespace spanner_internal {
44 struct ValueInternals;
186 explicit Value(std::int64_t v) :
Value(PrivateConstructor{}, v) {}
190 explicit Value(std::string v) :
Value(PrivateConstructor{}, std::move(v)) {}
201 :
Value(PrivateConstructor{}, std::move(v)) {}
204 :
Value(PrivateConstructor{}, std::move(v)) {}
225 explicit Value(
char const* v) :
Value(PrivateConstructor{}, v) {}
231 template <
typename T>
232 explicit Value(absl::optional<T> opt)
233 :
Value(PrivateConstructor{}, std::move(opt)) {}
247 template <
typename T>
248 explicit Value(std::vector<T> v) :
Value(PrivateConstructor{}, std::move(v)) {
249 static_assert(!IsVector<
typename std::decay<T>::type>::value,
250 "vector of vector not allowed. See value.h documentation.");
260 template <
typename... Ts>
261 explicit Value(std::tuple<Ts...> tup)
262 :
Value(PrivateConstructor{}, std::move(tup)) {}
296 template <
typename T>
297 StatusOr<T>
get()
const& {
298 if (!TypeProtoIs(T{}, type_))
300 if (value_.kind_case() ==
google::protobuf::Value::kNullValue) {
301 if (IsOptional<T>::value)
return T{};
304 return GetValue(T{}, value_, type_);
308 template <
typename T>
310 if (!TypeProtoIs(T{}, type_))
312 if (value_.kind_case() ==
google::protobuf::Value::kNullValue) {
313 if (IsOptional<T>::value)
return T{};
317 return GetValue(std::move(tag), std::move(value_), type_);
332 friend std::ostream& operator<<(std::ostream& os,
Value const& v);
344 template <
typename T>
345 struct IsOptional : std::false_type {};
346 template <
typename T>
347 struct IsOptional<absl::optional<T>> : std::true_type {};
350 template <
typename T>
351 struct IsVector : std::false_type {};
352 template <
typename... Ts>
353 struct IsVector<std::vector<Ts...>> : std::true_type {};
357 static bool TypeProtoIs(
bool,
google::spanner::v1::Type
const&);
358 static bool TypeProtoIs(std::int64_t,
google::spanner::v1::Type
const&);
359 static bool TypeProtoIs(
double,
google::spanner::v1::Type
const&);
362 static bool TypeProtoIs(absl::CivilDay,
google::spanner::v1::Type
const&);
363 static bool TypeProtoIs(std::string
const&,
google::spanner::v1::Type
const&);
364 static bool TypeProtoIs(
Bytes const&,
google::spanner::v1::Type
const&);
365 static bool TypeProtoIs(
Json const&,
google::spanner::v1::Type
const&);
366 static bool TypeProtoIs(
Numeric const&,
google::spanner::v1::Type
const&);
367 template <
typename T>
368 static bool TypeProtoIs(absl::optional<T>,
369 google::spanner::v1::Type
const& type) {
370 return TypeProtoIs(T{}, type);
372 template <
typename T>
373 static bool TypeProtoIs(std::vector<T>
const&,
374 google::spanner::v1::Type
const& type) {
375 return type.code() ==
google::spanner::v1::TypeCode::ARRAY &&
376 TypeProtoIs(T{}, type.array_element_type());
378 template <
typename... Ts>
379 static bool TypeProtoIs(std::tuple<Ts...>
const& tup,
380 google::spanner::v1::Type
const& type) {
381 bool ok = type.code() ==
google::spanner::v1::TypeCode::STRUCT;
382 ok = ok && type.struct_type().fields().size() ==
sizeof...(Ts);
383 spanner_internal::ForEach(tup, IsStructTypeProto{ok, 0},
390 struct IsStructTypeProto {
393 template <
typename T>
394 void operator()(T
const&,
google::spanner::v1::StructType
const& type) {
395 ok = ok && TypeProtoIs(T{}, type.fields(field).type());
398 template <
typename T>
399 void operator()(std::pair<std::string, T>
const&,
400 google::spanner::v1::StructType
const& type) {
401 operator()(T{}, type);
407 static google::spanner::v1::Type MakeTypeProto(
bool);
408 static google::spanner::v1::Type MakeTypeProto(std::int64_t);
409 static google::spanner::v1::Type MakeTypeProto(
double);
410 static google::spanner::v1::Type MakeTypeProto(std::string
const&);
411 static google::spanner::v1::Type MakeTypeProto(
Bytes const&);
412 static google::spanner::v1::Type MakeTypeProto(
Json const&);
413 static google::spanner::v1::Type MakeTypeProto(
Numeric const&);
416 static google::spanner::v1::Type MakeTypeProto(absl::CivilDay);
417 static google::spanner::v1::Type MakeTypeProto(
int);
418 static google::spanner::v1::Type MakeTypeProto(
char const*);
419 template <
typename T>
420 static google::spanner::v1::Type MakeTypeProto(absl::optional<T>
const&) {
421 return MakeTypeProto(T{});
423 template <
typename T>
424 static google::spanner::v1::Type MakeTypeProto(std::vector<T>
const& v) {
425 google::spanner::v1::Type t;
426 t.set_code(
google::spanner::v1::TypeCode::ARRAY);
427 *t.mutable_array_element_type() = MakeTypeProto(v.empty() ? T{} : v[0]);
431 if (!
google::protobuf::util::MessageDifferencer::Equals(
432 MakeTypeProto(e), t.array_element_type())) {
433 google::
cloud::internal::ThrowInvalidArgument(
"Mismatched types");
438 template <
typename... Ts>
439 static google::spanner::v1::Type MakeTypeProto(std::tuple<Ts...>
const& tup) {
440 google::spanner::v1::Type t;
441 t.set_code(
google::spanner::v1::TypeCode::STRUCT);
442 spanner_internal::ForEach(tup, AddStructTypes{}, *t.mutable_struct_type());
448 struct AddStructTypes {
449 template <
typename T>
450 void operator()(T
const& t,
451 google::spanner::v1::StructType& struct_type)
const {
452 auto* field = struct_type.add_fields();
453 *field->mutable_type() = MakeTypeProto(t);
455 template <
typename S,
typename T,
456 typename std::enable_if<
457 std::is_convertible<S, std::string>::value,
int>::type = 0>
458 void operator()(std::pair<S, T>
const& p,
459 google::spanner::v1::StructType& struct_type)
const {
460 auto* field = struct_type.add_fields();
461 field->set_name(p.first);
462 *field->mutable_type() = MakeTypeProto(p.second);
468 static google::protobuf::Value MakeValueProto(
bool b);
469 static google::protobuf::Value MakeValueProto(std::int64_t i);
470 static google::protobuf::Value MakeValueProto(
double d);
471 static google::protobuf::Value MakeValueProto(std::string s);
472 static google::protobuf::Value MakeValueProto(
Bytes b);
473 static google::protobuf::Value MakeValueProto(
Json j);
477 static google::protobuf::Value MakeValueProto(absl::CivilDay d);
478 static google::protobuf::Value MakeValueProto(
int i);
479 static google::protobuf::Value MakeValueProto(
char const* s);
480 template <
typename T>
481 static google::protobuf::Value MakeValueProto(absl::optional<T> opt) {
482 if (opt.has_value())
return MakeValueProto(*std::move(opt));
483 google::protobuf::Value v;
484 v.set_null_value(
google::protobuf::NullValue::NULL_VALUE);
487 template <
typename T>
488 static google::protobuf::Value MakeValueProto(std::vector<T> vec) {
489 google::protobuf::Value v;
490 auto& list = *v.mutable_list_value();
491 for (
auto&& e : vec) {
492 *list.add_values() = MakeValueProto(std::move(e));
496 template <
typename... Ts>
497 static google::protobuf::Value MakeValueProto(std::tuple<Ts...> tup) {
498 google::protobuf::Value v;
499 spanner_internal::ForEach(tup, AddStructValues{}, *v.mutable_list_value());
505 struct AddStructValues {
506 template <
typename T>
507 void operator()(T& t,
google::protobuf::ListValue& list_value)
const {
508 *list_value.add_values() = MakeValueProto(std::move(t));
510 template <
typename S,
typename T,
511 typename std::enable_if<
512 std::is_convertible<S, std::string>::value,
int>::type = 0>
513 void operator()(std::pair<S, T> p,
514 google::protobuf::ListValue& list_value)
const {
515 *list_value.add_values() = MakeValueProto(std::move(p.second));
521 static StatusOr<
bool> GetValue(
bool,
google::protobuf::Value
const&,
522 google::spanner::v1::Type
const&);
523 static StatusOr<std::int64_t> GetValue(std::int64_t,
524 google::protobuf::Value
const&,
525 google::spanner::v1::Type
const&);
526 static StatusOr<
double> GetValue(
double,
google::protobuf::Value
const&,
527 google::spanner::v1::Type
const&);
528 static StatusOr<std::string> GetValue(std::string
const&,
529 google::protobuf::Value
const&,
530 google::spanner::v1::Type
const&);
531 static StatusOr<std::string> GetValue(std::string
const&,
532 google::protobuf::Value&&,
533 google::spanner::v1::Type
const&);
534 static StatusOr<
Bytes> GetValue(
Bytes const&,
google::protobuf::Value
const&,
535 google::spanner::v1::Type
const&);
536 static StatusOr<
Json> GetValue(
Json const&,
google::protobuf::Value
const&,
537 google::spanner::v1::Type
const&);
539 google::protobuf::Value
const&,
540 google::spanner::v1::Type
const&);
542 google::spanner::v1::Type
const&);
544 google::protobuf::Value
const&,
545 google::spanner::v1::Type
const&);
546 static StatusOr<absl::CivilDay> GetValue(absl::CivilDay,
547 google::protobuf::Value
const&,
548 google::spanner::v1::Type
const&);
549 template <
typename T,
typename V>
550 static StatusOr<absl::optional<T>> GetValue(
551 absl::optional<T>
const&, V&& pv,
google::spanner::v1::Type
const& pt) {
552 if (pv.kind_case() ==
google::protobuf::Value::kNullValue) {
553 return absl::optional<T>{};
555 auto value = GetValue(T{}, std::forward<V>(pv), pt);
556 if (!value)
return std::move(value).status();
557 return absl::optional<T>{*std::move(value)};
559 template <
typename T,
typename V>
560 static StatusOr<std::vector<T>> GetValue(
561 std::vector<T>
const&, V&& pv,
google::spanner::v1::Type
const& pt) {
562 if (pv.kind_case() !=
google::protobuf::Value::kListValue) {
566 for (
int i = 0; i < pv.list_value().values().size(); ++i) {
567 auto&& e = GetProtoListValueElement(std::forward<V>(pv), i);
568 using ET =
decltype(e);
569 auto value = GetValue(T{}, std::forward<ET>(e), pt.array_element_type());
570 if (!value)
return std::move(value).status();
571 v.push_back(*std::move(value));
575 template <
typename V,
typename... Ts>
576 static StatusOr<std::tuple<Ts...>> GetValue(
577 std::tuple<Ts...>
const&, V&& pv,
google::spanner::v1::Type
const& pt) {
578 if (pv.kind_case() !=
google::protobuf::Value::kListValue) {
581 std::tuple<Ts...> tup;
583 ExtractTupleValues<V> f{status, 0, std::forward<V>(pv), pt};
584 spanner_internal::ForEach(tup, f);
585 if (!status
.ok())
return status;
591 template <
typename V>
592 struct ExtractTupleValues {
596 google::spanner::v1::Type
const& type;
597 template <
typename T>
598 void operator()(T& t) {
599 auto&& e = GetProtoListValueElement(std::forward<V>(pv), i);
600 using ET =
decltype(e);
601 auto value = GetValue(T{}, std::forward<ET>(e), type);
604 status = std::move(value).status();
606 t = *std::move(value);
609 template <
typename T>
610 void operator()(std::pair<std::string, T>& p) {
611 p.first = type.struct_type().fields(i).name();
612 auto&& e = GetProtoListValueElement(std::forward<V>(pv), i);
613 using ET =
decltype(e);
614 auto value = GetValue(T{}, std::forward<ET>(e), type);
617 status = std::move(value).status();
619 p.second = *std::move(value);
628 static google::protobuf::Value
const& GetProtoListValueElement(
629 google::protobuf::Value
const& pv,
int pos) {
630 return pv.list_value().values(pos);
632 static google::protobuf::Value&& GetProtoListValueElement(
633 google::protobuf::Value&& pv,
int pos) {
634 return std::move(*pv.mutable_list_value()->mutable_values(pos));
643 struct PrivateConstructor {};
644 template <
typename T>
645 Value(PrivateConstructor, T&& t)
646 : type_(MakeTypeProto(t)), value_(MakeValueProto(std::forward<T>(t))) {}
648 Value(
google::spanner::v1::Type t,
google::protobuf::Value v)
649 : type_(std::move(t)), value_(std::move(v)) {}
653 google::spanner::v1::Type type_;
654 google::protobuf::Value value_;
664 template <
typename T>
666 return Value(absl::optional<T>{});
672 namespace spanner_internal {
675 struct ValueInternals {
677 google::protobuf::Value v) {
681 static std::pair<
google::spanner::v1::Type,
google::protobuf::Value> ToProto(
683 return std::make_pair(std::move(v.type_), std::move(v.value_));
688 google::protobuf::Value v) {
689 return ValueInternals::FromProto(std::move(t), std::move(v));
692 inline std::pair<
google::spanner::v1::Type,
google::protobuf::Value> ToProto(
694 return ValueInternals::ToProto(std::move(v));