Skip to content
This repository was archived by the owner on Dec 8, 2021. It is now read-only.

Commit 6c7fcd1

Browse files
authored
fix!: support full TIMESTAMP range in g::c::spanner::Timestamp (#1166)
Move `google::cloud::spanner::Timestamp` from an alias for ``` std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds> ``` to a custom class that supports the full range of Spanner TIMESTAMP values: 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. User conversions are provided from/to standard `std::chrono::time_point` types. Fixes #1098.
1 parent e33b4f8 commit 6c7fcd1

24 files changed

+1096
-763
lines changed
1.1 KB
Binary file not shown.

google/cloud/spanner/CMakeLists.txt

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,8 +173,6 @@ add_library(
173173
internal/spanner_stub.h
174174
internal/status_utils.cc
175175
internal/status_utils.h
176-
internal/time.cc
177-
internal/time.h
178176
internal/time_format.cc
179177
internal/time_format.h
180178
internal/transaction_impl.cc
@@ -202,6 +200,7 @@ add_library(
202200
sql_statement.cc
203201
sql_statement.h
204202
timestamp.h
203+
timestamp.cc
205204
transaction.cc
206205
transaction.h
207206
update_instance_request_builder.h
@@ -333,7 +332,6 @@ function (spanner_client_define_tests)
333332
internal/spanner_stub_test.cc
334333
internal/status_utils_test.cc
335334
internal/time_format_test.cc
336-
internal/time_test.cc
337335
internal/transaction_impl_test.cc
338336
internal/tuple_utils_test.cc
339337
bytes_test.cc
@@ -349,6 +347,7 @@ function (spanner_client_define_tests)
349347
session_pool_options_test.cc
350348
spanner_version_test.cc
351349
sql_statement_test.cc
350+
timestamp_test.cc
352351
transaction_test.cc
353352
create_instance_request_builder_test.cc
354353
update_instance_request_builder_test.cc

google/cloud/spanner/benchmarks/multiple_rows_cpu_benchmark.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,10 +293,9 @@ struct TimestampTraits {
293293
static std::string TableSuffix() { return "timestamp"; }
294294
static native_type MakeRandomValue(
295295
google::cloud::internal::DefaultPRNG& generator) {
296-
using rep = cs::Timestamp::duration::rep;
297-
return cs::Timestamp(
298-
cs::Timestamp::duration(std::uniform_int_distribution<rep>(
299-
0, std::numeric_limits<rep>::max())(generator)));
296+
auto const nanos = std::uniform_int_distribution<std::int64_t>(
297+
0, std::numeric_limits<std::int64_t>::max())(generator);
298+
return cs::internal::TimestampFromCounts(0, nanos).value();
300299
}
301300
};
302301

google/cloud/spanner/client_test.cc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#include "google/cloud/spanner/client.h"
1616
#include "google/cloud/spanner/connection.h"
17-
#include "google/cloud/spanner/internal/time.h"
1817
#include "google/cloud/spanner/mocks/mock_spanner_connection.h"
1918
#include "google/cloud/spanner/mutations.h"
2019
#include "google/cloud/spanner/results.h"
@@ -334,7 +333,7 @@ TEST(ClientTest, ExecutePartitionedDmlSuccess) {
334333
TEST(ClientTest, CommitSuccess) {
335334
auto conn = std::make_shared<MockConnection>();
336335

337-
auto ts = Timestamp(std::chrono::seconds(123));
336+
auto ts = internal::TimestampFromCounts(123, 0).value();
338337
CommitResult result;
339338
result.commit_timestamp = ts;
340339

@@ -397,7 +396,7 @@ TEST(ClientTest, MakeConnectionOptionalArguments) {
397396
}
398397

399398
TEST(ClientTest, CommitMutatorSuccess) {
400-
auto timestamp = internal::TimestampFromString("2019-08-14T21:16:21.123Z");
399+
auto timestamp = internal::TimestampFromRFC3339("2019-08-14T21:16:21.123Z");
401400
ASSERT_STATUS_OK(timestamp);
402401

403402
auto conn = std::make_shared<MockConnection>();
@@ -588,7 +587,7 @@ TEST(ClientTest, CommitMutatorException) {
588587
#endif
589588

590589
TEST(ClientTest, CommitMutatorRerunTransientFailures) {
591-
auto timestamp = internal::TimestampFromString("2019-08-14T21:16:21.123Z");
590+
auto timestamp = internal::TimestampFromRFC3339("2019-08-14T21:16:21.123Z");
592591
ASSERT_STATUS_OK(timestamp);
593592

594593
auto conn = std::make_shared<MockConnection>();
@@ -731,7 +730,7 @@ TEST(ClientTest, CommitMutatorSessionAffinity) {
731730
// should see the same session in a new transaction on every rerun.
732731
std::string const session_name = "CommitMutatorLockPriority.Session";
733732

734-
auto timestamp = internal::TimestampFromString("2019-11-11T20:05:36.345Z");
733+
auto timestamp = internal::TimestampFromRFC3339("2019-11-11T20:05:36.345Z");
735734
ASSERT_STATUS_OK(timestamp);
736735

737736
auto conn = std::make_shared<MockConnection>();
@@ -773,7 +772,7 @@ TEST(ClientTest, CommitMutatorSessionAffinity) {
773772
}
774773

775774
TEST(ClientTest, CommitMutatorSessionNotFound) {
776-
auto timestamp = internal::TimestampFromString("2019-08-14T21:16:21.123Z");
775+
auto timestamp = internal::TimestampFromRFC3339("2019-08-14T21:16:21.123Z");
777776
ASSERT_STATUS_OK(timestamp);
778777

779778
auto conn = std::make_shared<MockConnection>();
@@ -798,7 +797,7 @@ TEST(ClientTest, CommitMutatorSessionNotFound) {
798797
}
799798

800799
TEST(ClientTest, CommitSessionNotFound) {
801-
auto timestamp = internal::TimestampFromString("2019-08-14T21:16:21.123Z");
800+
auto timestamp = internal::TimestampFromRFC3339("2019-08-14T21:16:21.123Z");
802801
ASSERT_STATUS_OK(timestamp);
803802

804803
auto conn = std::make_shared<MockConnection>();

google/cloud/spanner/integration_tests/client_integration_test.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -433,7 +433,7 @@ TEST_F(ClientIntegrationTest, Read_ExactStaleness_Timestamp) {
433433
TEST_F(ClientIntegrationTest, Read_ExactStaleness_Duration) {
434434
CheckReadWithOptions(*client_, [](CommitResult const&) {
435435
return Transaction::SingleUseOptions(Transaction::ReadOnlyOptions(
436-
/*exact_staleness=*/Timestamp::duration(0)));
436+
/*exact_staleness=*/std::chrono::nanoseconds(0)));
437437
});
438438
}
439439

@@ -519,7 +519,7 @@ TEST_F(ClientIntegrationTest, ExecuteQuery_ExactStaleness_Timestamp) {
519519
TEST_F(ClientIntegrationTest, ExecuteQuery_ExactStaleness_Duration) {
520520
CheckExecuteQueryWithSingleUseOptions(*client_, [](CommitResult const&) {
521521
return Transaction::SingleUseOptions(Transaction::ReadOnlyOptions(
522-
/*exact_staleness=*/Timestamp::duration(0)));
522+
/*exact_staleness=*/std::chrono::nanoseconds(0)));
523523
});
524524
}
525525

google/cloud/spanner/integration_tests/data_types_integration_test.cc

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
#include "google/cloud/spanner/client.h"
1616
#include "google/cloud/spanner/database.h"
1717
#include "google/cloud/spanner/database_admin_client.h"
18-
#include "google/cloud/spanner/internal/time.h"
1918
#include "google/cloud/spanner/mutations.h"
2019
#include "google/cloud/spanner/testing/database_environment.h"
2120
#include "google/cloud/internal/getenv.h"
2221
#include "google/cloud/testing_util/assert_ok.h"
2322
#include "google/cloud/testing_util/init_google_mock.h"
2423
#include <gmock/gmock.h>
24+
#include <chrono>
2525

2626
namespace google {
2727
namespace cloud {
@@ -173,22 +173,22 @@ TEST_F(DataTypeIntegrationTest, WriteReadBytes) {
173173
}
174174

175175
TEST_F(DataTypeIntegrationTest, WriteReadTimestamp) {
176-
// TODO(#1098): `Timestamp` cannot represent these extreme values.
177-
// auto min = internal::TimestampFromString("0001-01-01T00:00:00Z");
178-
// auto max = internal::TimestampFromString("9999-12-31T23:59:59.999999999Z");
179-
180-
// ASSERT_STATUS_OK(min);
181-
// ASSERT_STATUS_OK(max);
176+
auto min = internal::TimestampFromRFC3339("0001-01-01T00:00:00Z");
177+
ASSERT_STATUS_OK(min);
178+
auto max = internal::TimestampFromRFC3339("9999-12-31T23:59:59.999999999Z");
179+
ASSERT_STATUS_OK(max);
180+
auto now = MakeTimestamp(std::chrono::system_clock::now());
181+
ASSERT_STATUS_OK(now);
182182

183183
std::vector<Timestamp> const data = {
184-
// *min, // TODO(#1098)
185-
Timestamp(std::chrono::seconds(-1)),
186-
Timestamp(std::chrono::nanoseconds(-1)),
187-
Timestamp(std::chrono::seconds(0)),
188-
Timestamp(std::chrono::nanoseconds(1)),
189-
Timestamp(std::chrono::seconds(1)),
190-
Timestamp(std::chrono::system_clock::now()),
191-
// *max, // TODO(#1098)
184+
*min,
185+
internal::TimestampFromCounts(-1, 0).value(),
186+
internal::TimestampFromCounts(0, -1).value(),
187+
internal::TimestampFromCounts(0, 0).value(),
188+
internal::TimestampFromCounts(0, 1).value(),
189+
internal::TimestampFromCounts(1, 0).value(),
190+
*now,
191+
*max,
192192
};
193193
auto result = WriteReadData(*client_, data, "TimestampValue");
194194
ASSERT_STATUS_OK(result);
@@ -268,11 +268,11 @@ TEST_F(DataTypeIntegrationTest, WriteReadArrayBytes) {
268268
TEST_F(DataTypeIntegrationTest, WriteReadArrayTimestamp) {
269269
std::vector<std::vector<Timestamp>> const data = {
270270
std::vector<Timestamp>{},
271-
std::vector<Timestamp>{Timestamp(std::chrono::seconds(-1))},
271+
std::vector<Timestamp>{internal::TimestampFromCounts(-1, 0).value()},
272272
std::vector<Timestamp>{
273-
Timestamp(std::chrono::seconds(-1)),
274-
Timestamp(),
275-
Timestamp(std::chrono::seconds(1)),
273+
internal::TimestampFromCounts(-1, 0).value(),
274+
internal::TimestampFromCounts(0, 0).value(),
275+
internal::TimestampFromCounts(1, 0).value(),
276276
},
277277
};
278278
auto result = WriteReadData(*client_, data, "ArrayTimestampValue");

google/cloud/spanner/internal/connection_impl.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
#include "google/cloud/spanner/internal/partial_result_set_source.h"
1919
#include "google/cloud/spanner/internal/retry_loop.h"
2020
#include "google/cloud/spanner/internal/status_utils.h"
21-
#include "google/cloud/spanner/internal/time.h"
2221
#include "google/cloud/spanner/query_partition.h"
2322
#include "google/cloud/spanner/read_partition.h"
2423
#include "google/cloud/grpc_utils/grpc_error_delegate.h"
@@ -779,7 +778,8 @@ StatusOr<CommitResult> ConnectionImpl::CommitImpl(
779778
return status;
780779
}
781780
CommitResult r;
782-
r.commit_timestamp = internal::FromProto(response->commit_timestamp());
781+
r.commit_timestamp =
782+
internal::TimestampFromProto(response->commit_timestamp());
783783
return r;
784784
}
785785

google/cloud/spanner/internal/connection_impl_test.cc

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
#include "google/cloud/spanner/internal/connection_impl.h"
1616
#include "google/cloud/spanner/client.h"
1717
#include "google/cloud/spanner/internal/spanner_stub.h"
18-
#include "google/cloud/spanner/internal/time.h"
1918
#include "google/cloud/spanner/testing/matchers.h"
2019
#include "google/cloud/spanner/testing/mock_spanner_stub.h"
2120
#include "google/cloud/internal/make_unique.h"
@@ -1355,14 +1354,15 @@ TEST(ConnectionImplTest, CommitBeginTransactionRetry) {
13551354
EXPECT_EQ("test-session-name", request.session());
13561355
EXPECT_EQ(txn.id(), request.transaction_id());
13571356
spanner_proto::CommitResponse response;
1358-
*response.mutable_commit_timestamp() =
1359-
internal::ToProto(Timestamp{std::chrono::seconds(123)});
1357+
*response.mutable_commit_timestamp() = internal::TimestampToProto(
1358+
internal::TimestampFromCounts(123, 0).value());
13601359
return response;
13611360
});
13621361

13631362
auto commit = conn->Commit({MakeReadWriteTransaction(), {}});
13641363
EXPECT_STATUS_OK(commit);
1365-
EXPECT_EQ(Timestamp(std::chrono::seconds(123)), commit->commit_timestamp);
1364+
EXPECT_EQ(internal::TimestampFromCounts(123, 0).value(),
1365+
commit->commit_timestamp);
13661366
}
13671367

13681368
TEST(ConnectionImplTest, CommitBeginTransactionSessionNotFound) {
@@ -1464,8 +1464,8 @@ TEST(ConnectionImplTest, CommitCommitIdempotentTransientSuccess) {
14641464
EXPECT_EQ("test-session-name", request.session());
14651465
EXPECT_EQ("test-txn-id", request.transaction_id());
14661466
spanner_proto::CommitResponse response;
1467-
*response.mutable_commit_timestamp() =
1468-
internal::ToProto(Timestamp{std::chrono::seconds(123)});
1467+
*response.mutable_commit_timestamp() = internal::TimestampToProto(
1468+
internal::TimestampFromCounts(123, 0).value());
14691469
return response;
14701470
});
14711471

@@ -1475,7 +1475,8 @@ TEST(ConnectionImplTest, CommitCommitIdempotentTransientSuccess) {
14751475

14761476
auto commit = conn->Commit({txn, {}});
14771477
EXPECT_STATUS_OK(commit);
1478-
EXPECT_EQ(Timestamp(std::chrono::seconds(123)), commit->commit_timestamp);
1478+
EXPECT_EQ(internal::TimestampFromCounts(123, 0).value(),
1479+
commit->commit_timestamp);
14791480
}
14801481

14811482
TEST(ConnectionImplTest, CommitSuccessWithTransactionId) {
@@ -1496,8 +1497,8 @@ TEST(ConnectionImplTest, CommitSuccessWithTransactionId) {
14961497
EXPECT_EQ("test-session-name", request.session());
14971498
EXPECT_EQ("test-txn-id", request.transaction_id());
14981499
spanner_proto::CommitResponse response;
1499-
*response.mutable_commit_timestamp() =
1500-
internal::ToProto(Timestamp{std::chrono::seconds(123)});
1500+
*response.mutable_commit_timestamp() = internal::TimestampToProto(
1501+
internal::TimestampFromCounts(123, 0).value());
15011502
return response;
15021503
});
15031504

0 commit comments

Comments
 (0)