Skip to content

Commit 9ea1ae9

Browse files
committed
feat(spanner): add spanner::Value support for TypeCode::UUID
1 parent 6e34f52 commit 9ea1ae9

File tree

3 files changed

+85
-0
lines changed

3 files changed

+85
-0
lines changed

google/cloud/spanner/value.cc

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,7 @@ std::ostream& StreamHelper(std::ostream& os, // NOLINT(misc-no-recursion)
158158
case google::spanner::v1::TypeCode::JSON:
159159
case google::spanner::v1::TypeCode::TIMESTAMP:
160160
case google::spanner::v1::TypeCode::NUMERIC:
161+
case google::spanner::v1::TypeCode::UUID:
161162
return os << v.string_value();
162163

163164
case google::spanner::v1::TypeCode::DATE:
@@ -269,6 +270,10 @@ bool Value::TypeProtoIs(absl::CivilDay, google::spanner::v1::Type const& type) {
269270
return type.code() == google::spanner::v1::TypeCode::DATE;
270271
}
271272

273+
bool Value::TypeProtoIs(Uuid, google::spanner::v1::Type const& type) {
274+
return type.code() == google::spanner::v1::TypeCode::UUID;
275+
}
276+
272277
bool Value::TypeProtoIs(std::string const&,
273278
google::spanner::v1::Type const& type) {
274279
return type.code() == google::spanner::v1::TypeCode::STRING;
@@ -404,6 +409,12 @@ google::spanner::v1::Type Value::MakeTypeProto(absl::CivilDay) {
404409
return t;
405410
}
406411

412+
google::spanner::v1::Type Value::MakeTypeProto(Uuid) {
413+
google::spanner::v1::Type t;
414+
t.set_code(google::spanner::v1::TypeCode::UUID);
415+
return t;
416+
}
417+
407418
google::spanner::v1::Type Value::MakeTypeProto(int) {
408419
return MakeTypeProto(std::int64_t{});
409420
}
@@ -520,6 +531,12 @@ google::protobuf::Value Value::MakeValueProto(absl::CivilDay d) {
520531
return v;
521532
}
522533

534+
google::protobuf::Value Value::MakeValueProto(Uuid u) {
535+
google::protobuf::Value v;
536+
v.set_string_value(std::string(u));
537+
return v;
538+
}
539+
523540
google::protobuf::Value Value::MakeValueProto(int i) {
524541
return MakeValueProto(std::int64_t{i});
525542
}
@@ -711,6 +728,14 @@ StatusOr<absl::CivilDay> Value::GetValue(absl::CivilDay,
711728
s + ": Failed to match RFC3339 full-date", GCP_ERROR_INFO());
712729
}
713730

731+
StatusOr<Uuid> Value::GetValue(Uuid, google::protobuf::Value const& pv,
732+
google::spanner::v1::Type const&) {
733+
if (pv.kind_case() != google::protobuf::Value::kStringValue) {
734+
return Status(StatusCode::kUnknown, "missing UUID");
735+
}
736+
return MakeUuid(pv.string_value());
737+
}
738+
714739
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
715740
} // namespace spanner
716741
} // namespace cloud

google/cloud/spanner/value.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "google/cloud/spanner/proto_enum.h"
2525
#include "google/cloud/spanner/proto_message.h"
2626
#include "google/cloud/spanner/timestamp.h"
27+
#include "google/cloud/spanner/uuid.h"
2728
#include "google/cloud/spanner/version.h"
2829
#include "google/cloud/internal/base64_transforms.h"
2930
#include "google/cloud/internal/make_status.h"
@@ -77,6 +78,7 @@ GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
7778
* OID(PG) | `google::cloud::spanner::PgOid`
7879
* TIMESTAMP | `google::cloud::spanner::Timestamp`
7980
* DATE | `absl::CivilDay`
81+
* UUID | `google::cloud::spanner::Uuid`
8082
* ENUM | `google::cloud::spanner::ProtoEnum<E>`
8183
* PROTO | `google::cloud::spanner::ProtoMessage<M>`
8284
* ARRAY | `std::vector<T>` // [1]
@@ -222,6 +224,8 @@ class Value {
222224
explicit Value(absl::CivilDay v)
223225
: Value(PrivateConstructor{}, std::move(v)) {}
224226
/// @copydoc Value(bool)
227+
explicit Value(Uuid v) : Value(PrivateConstructor{}, std::move(v)) {}
228+
/// @copydoc Value(bool)
225229
template <typename E>
226230
explicit Value(ProtoEnum<E> v) : Value(PrivateConstructor{}, std::move(v)) {}
227231
/// @copydoc Value(bool)
@@ -387,6 +391,7 @@ class Value {
387391
static bool TypeProtoIs(Timestamp, google::spanner::v1::Type const&);
388392
static bool TypeProtoIs(CommitTimestamp, google::spanner::v1::Type const&);
389393
static bool TypeProtoIs(absl::CivilDay, google::spanner::v1::Type const&);
394+
static bool TypeProtoIs(Uuid, google::spanner::v1::Type const&);
390395
static bool TypeProtoIs(std::string const&, google::spanner::v1::Type const&);
391396
static bool TypeProtoIs(Bytes const&, google::spanner::v1::Type const&);
392397
static bool TypeProtoIs(Json const&, google::spanner::v1::Type const&);
@@ -460,6 +465,7 @@ class Value {
460465
static google::spanner::v1::Type MakeTypeProto(Timestamp);
461466
static google::spanner::v1::Type MakeTypeProto(CommitTimestamp);
462467
static google::spanner::v1::Type MakeTypeProto(absl::CivilDay);
468+
static google::spanner::v1::Type MakeTypeProto(Uuid);
463469
template <typename E>
464470
static google::spanner::v1::Type MakeTypeProto(ProtoEnum<E>) {
465471
google::spanner::v1::Type t;
@@ -539,6 +545,7 @@ class Value {
539545
static google::protobuf::Value MakeValueProto(Timestamp ts);
540546
static google::protobuf::Value MakeValueProto(CommitTimestamp ts);
541547
static google::protobuf::Value MakeValueProto(absl::CivilDay d);
548+
static google::protobuf::Value MakeValueProto(Uuid u);
542549
template <typename E>
543550
static google::protobuf::Value MakeValueProto(ProtoEnum<E> e) {
544551
return MakeValueProto(std::int64_t{E{e}});
@@ -629,6 +636,8 @@ class Value {
629636
static StatusOr<absl::CivilDay> GetValue(absl::CivilDay,
630637
google::protobuf::Value const&,
631638
google::spanner::v1::Type const&);
639+
static StatusOr<Uuid> GetValue(Uuid, google::protobuf::Value const&,
640+
google::spanner::v1::Type const&);
632641
template <typename E>
633642
static StatusOr<ProtoEnum<E>> GetValue(ProtoEnum<E>,
634643
google::protobuf::Value const& pv,

google/cloud/spanner/value_test.cc

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,15 @@ TEST(Value, BasicSemantics) {
264264
v.resize(10);
265265
TestBasicSemantics(v);
266266

267+
for (auto x : {Uuid()}) {
268+
SCOPED_TRACE("Testing: google::cloud::spanner::Uuid " + std::string{x});
269+
TestBasicSemantics(x);
270+
TestBasicSemantics(std::vector<Uuid>(5, x));
271+
std::vector<absl::optional<Uuid>> v(5, x);
272+
v.resize(10);
273+
TestBasicSemantics(v);
274+
}
275+
267276
for (auto x : {testing::Genre::POP, testing::Genre::JAZZ,
268277
testing::Genre::FOLK, testing::Genre::ROCK}) {
269278
SCOPED_TRACE("Testing: ProtoEnum<testing::Genre> " +
@@ -922,6 +931,20 @@ TEST(Value, ProtoConversionDate) {
922931
}
923932
}
924933

934+
TEST(Value, ProtoConversionUuid) {
935+
for (auto const& x : std::vector<Uuid>{
936+
Uuid(),
937+
Uuid(0x7bf8a7b819171919, 0x2625f208c5824254),
938+
MakeUuid("{0b6ed04ca16dfc4652817f9978c13738}").value(),
939+
}) {
940+
Value const v(x);
941+
auto const p = spanner_internal::ToProto(v);
942+
EXPECT_EQ(v, spanner_internal::FromProto(p.first, p.second));
943+
EXPECT_EQ(google::spanner::v1::TypeCode::UUID, p.first.code());
944+
EXPECT_EQ(std::string{x}, p.second.string_value());
945+
}
946+
}
947+
925948
TEST(Value, ProtoConversionProtoEnum) {
926949
for (auto e : {testing::Genre::POP, testing::Genre::JAZZ,
927950
testing::Genre::FOLK, testing::Genre::ROCK}) {
@@ -1251,6 +1274,24 @@ TEST(Value, GetBadDate) {
12511274
EXPECT_THAT(v.get<absl::CivilDay>(), Not(IsOk()));
12521275
}
12531276

1277+
TEST(Value, GetBadUuid) {
1278+
Value v(Uuid{});
1279+
ClearProtoKind(v);
1280+
EXPECT_THAT(v.get<Uuid>(), Not(IsOk()));
1281+
1282+
SetProtoKind(v, google::protobuf::NULL_VALUE);
1283+
EXPECT_THAT(v.get<Uuid>(), Not(IsOk()));
1284+
1285+
SetProtoKind(v, true);
1286+
EXPECT_THAT(v.get<Uuid>(), Not(IsOk()));
1287+
1288+
SetProtoKind(v, 0.0);
1289+
EXPECT_THAT(v.get<Uuid>(), Not(IsOk()));
1290+
1291+
SetProtoKind(v, "blah");
1292+
EXPECT_THAT(v.get<Uuid>(), Not(IsOk()));
1293+
}
1294+
12541295
TEST(Value, GetBadProtoEnum) {
12551296
Value v(ProtoEnum<testing::Genre>{});
12561297
ClearProtoKind(v);
@@ -1429,6 +1470,7 @@ TEST(Value, OutputStream) {
14291470
{Value(PgOid(1234567890)), "1234567890", normal},
14301471
{Value(absl::CivilDay()), "1970-01-01", normal},
14311472
{Value(Timestamp()), "1970-01-01T00:00:00Z", normal},
1473+
{Value(Uuid()), "00000000-0000-0000-0000-000000000000", normal},
14321474
{Value(ProtoEnum<testing::Genre>(testing::Genre::POP)),
14331475
"google.cloud.spanner.testing.POP", normal},
14341476
{Value(ProtoMessage<testing::SingerInfo>(singer)),
@@ -1462,6 +1504,7 @@ TEST(Value, OutputStream) {
14621504
{MakeNullValue<PgOid>(), "NULL", normal},
14631505
{MakeNullValue<absl::CivilDay>(), "NULL", normal},
14641506
{MakeNullValue<Timestamp>(), "NULL", normal},
1507+
{MakeNullValue<Uuid>(), "NULL", normal},
14651508
{MakeNullValue<ProtoEnum<testing::Genre>>(), "NULL", normal},
14661509
{MakeNullValue<ProtoMessage<testing::SingerInfo>>(), "NULL", normal},
14671510

@@ -1482,6 +1525,8 @@ TEST(Value, OutputStream) {
14821525
{Value(std::vector<absl::CivilDay>{2}), "[1970-01-01, 1970-01-01]",
14831526
normal},
14841527
{Value(std::vector<Timestamp>{1}), "[1970-01-01T00:00:00Z]", normal},
1528+
{Value(std::vector<Uuid>{1}), "[00000000-0000-0000-0000-000000000000]",
1529+
normal},
14851530
{Value(std::vector<ProtoEnum<testing::Genre>>{testing::JAZZ,
14861531
testing::FOLK}),
14871532
"[google.cloud.spanner.testing.JAZZ, google.cloud.spanner.testing.FOLK]",
@@ -1507,6 +1552,7 @@ TEST(Value, OutputStream) {
15071552
{MakeNullValue<std::vector<Numeric>>(), "NULL", normal},
15081553
{MakeNullValue<std::vector<absl::CivilDay>>(), "NULL", normal},
15091554
{MakeNullValue<std::vector<Timestamp>>(), "NULL", normal},
1555+
{MakeNullValue<std::vector<Uuid>>(), "NULL", normal},
15101556
{MakeNullValue<std::vector<ProtoEnum<testing::Genre>>>(), "NULL", normal},
15111557
{MakeNullValue<std::vector<ProtoMessage<testing::SingerInfo>>>(), "NULL",
15121558
normal},
@@ -1657,6 +1703,11 @@ TEST(Value, OutputStreamMatchesT) {
16571703
StreamMatchesValueStream(Timestamp());
16581704
StreamMatchesValueStream(MakeTimestamp(MakeTime(1, 1)).value());
16591705

1706+
// Uuid
1707+
StreamMatchesValueStream(Uuid());
1708+
StreamMatchesValueStream(
1709+
MakeUuid("{0b6ed04ca16dfc4652817f9978c13738}").value());
1710+
16601711
// ProtoEnum
16611712
StreamMatchesValueStream(ProtoEnum<testing::Genre>());
16621713
StreamMatchesValueStream(ProtoEnum<testing::Genre>(testing::ROCK));

0 commit comments

Comments
 (0)