@@ -77,6 +77,7 @@ using ::testing::Contains;
7777using ::testing::ElementsAre;
7878using ::testing::ElementsAreArray;
7979using ::testing::Eq;
80+ using ::testing::HasSubstr;
8081using ::testing::Matcher;
8182using ::testing::MockFunction;
8283using ::testing::Pair;
@@ -3695,6 +3696,92 @@ TEST_F(DataConnectionTest,
36953696 EXPECT_THAT (row2.values ().at (1 ).get <std::string>(), IsOkAndHolds (" v2" ));
36963697}
36973698
3699+ TEST_F (DataConnectionTest, ExecuteQueryFailureWithSchemaChange) {
3700+ auto factory = std::make_unique<SimpleOperationContextFactory>();
3701+
3702+ auto mock = std::make_shared<MockBigtableStub>();
3703+ auto fake_cq_impl = std::make_shared<FakeCompletionQueueImpl>();
3704+ auto mock_bg = std::make_unique<MockBackgroundThreads>();
3705+ EXPECT_CALL (*mock_bg, cq).WillRepeatedly ([&]() {
3706+ return CompletionQueue{fake_cq_impl};
3707+ });
3708+ auto constexpr kResultMetadataText = R"pb(
3709+ proto_schema {
3710+ columns {
3711+ name: "row_key"
3712+ type { string_type {} }
3713+ }
3714+ columns {
3715+ name: "value"
3716+ type { string_type {} }
3717+ }
3718+ }
3719+ )pb" ;
3720+ v2::PrepareQueryResponse pq_response;
3721+ pq_response.set_prepared_query (" test-pq-id-54321" );
3722+ ASSERT_TRUE (google::protobuf::TextFormat::ParseFromString (
3723+ kResultMetadataText , pq_response.mutable_metadata ()));
3724+ *pq_response.mutable_valid_until () = internal::ToProtoTimestamp (
3725+ std::chrono::system_clock::now () + std::chrono::seconds (3600 ));
3726+
3727+ auto constexpr kExecuteQueryResultMetadataText = R"pb(
3728+ proto_schema {
3729+ columns {
3730+ name: "row_key"
3731+ type { string_type {} }
3732+ }
3733+ columns {
3734+ name: "different_value"
3735+ type { string_type {} }
3736+ }
3737+ }
3738+ )pb" ;
3739+ v2::ExecuteQueryResponse eq_response;
3740+ ASSERT_TRUE (google::protobuf::TextFormat::ParseFromString (
3741+ kExecuteQueryResultMetadataText , eq_response.mutable_metadata ()));
3742+
3743+ auto refresh_fn = []() {
3744+ return make_ready_future (
3745+ StatusOr<google::bigtable::v2::PrepareQueryResponse>(
3746+ Status{StatusCode::kUnimplemented , " not implemented" }));
3747+ };
3748+ EXPECT_CALL (*mock, ExecuteQuery)
3749+ .Times (3 )
3750+ .WillRepeatedly (
3751+ [&](auto , auto const &,
3752+ google::bigtable::v2::ExecuteQueryRequest const & request) {
3753+ EXPECT_EQ (request.app_profile_id (), kAppProfile );
3754+ EXPECT_EQ (request.instance_name (),
3755+ " projects/test-project/instances/test-instance" );
3756+ auto stream = std::make_unique<MockExecuteQueryStream>();
3757+ EXPECT_CALL (*stream, Read)
3758+ .WillOnce ([&](google::bigtable::v2::ExecuteQueryResponse* r) {
3759+ *r = eq_response;
3760+ return absl::nullopt ;
3761+ });
3762+ return stream;
3763+ });
3764+
3765+ auto conn = TestConnection (std::move (mock), std::move (factory));
3766+ internal::OptionsSpan span (CallOptions ());
3767+ Project p (" test-project" );
3768+ bigtable::SqlStatement statement (" SELECT * FROM the-table" );
3769+ bigtable::InstanceResource instance (p, " test-instance" );
3770+ auto query_plan =
3771+ QueryPlan::Create (CompletionQueue (fake_cq_impl), std::move (pq_response),
3772+ std::move (refresh_fn));
3773+ auto prepared_query =
3774+ bigtable::PreparedQuery (instance, statement, std::move (query_plan));
3775+ auto bq = prepared_query.BindParameters ({});
3776+ bigtable::ExecuteQueryParams params{std::move (bq)};
3777+ auto row_stream = conn->ExecuteQuery (std::move (params));
3778+ for (auto const & row : row_stream) {
3779+ EXPECT_THAT (row,
3780+ StatusIs (StatusCode::kAborted , HasSubstr (" Schema changed" )));
3781+ }
3782+ fake_cq_impl->SimulateCompletion (false );
3783+ }
3784+
36983785} // namespace
36993786GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
37003787} // namespace bigtable_internal
0 commit comments