@@ -40,6 +40,7 @@ using ::std::chrono::milliseconds;
4040using ::testing::Contains;
4141using ::testing::ElementsAre;
4242using ::testing::HasSubstr;
43+ using ::testing::UnorderedElementsAre;
4344using ms = std::chrono::milliseconds;
4445
4546class DataIntegrationTest : public TableIntegrationTest ,
@@ -841,6 +842,71 @@ TEST_P(DataIntegrationTest, SingleColumnQueryWithHistory) {
841842 EXPECT_EQ (std::get<1 >(entry1), value_old);
842843}
843844
845+ TEST_P (DataIntegrationTest, MultiColumnQuery) {
846+ if (UsingCloudBigtableEmulator ()) GTEST_SKIP ();
847+ auto const table_id = testing::TableTestEnvironment::table_id ();
848+ auto retry_policy_option = DataLimitedErrorCountRetryPolicy (0 ).clone ();
849+ auto backoff_policy_option =
850+ google::cloud::internal::ExponentialBackoffPolicy (ms (0 ), ms (0 ), 2.0 )
851+ .clone ();
852+ auto query_refresh_option =
853+ bigtable::experimental::QueryPlanRefreshLimitedErrorCountRetryPolicy (0 )
854+ .clone ();
855+ auto opts =
856+ Options{}
857+ .set <DataRetryPolicyOption>(std::move (retry_policy_option))
858+ .set <DataBackoffPolicyOption>(std::move (backoff_policy_option))
859+ .set <bigtable::experimental::QueryPlanRefreshRetryPolicyOption>(
860+ std::move (query_refresh_option));
861+ auto connection = google::cloud::bigtable::MakeDataConnection (opts);
862+ auto table =
863+ Table (connection, TableResource (project_id (), instance_id (), table_id));
864+ std::string const row_key1 = " multi-column-query-row-1" ;
865+ std::string const row_key2 = " multi-column-query-row-2" ;
866+ std::string const family = kFamily4 ;
867+ std::string const column1 = " c1" ;
868+ std::string const column2 = " c2" ;
869+ std::string const value11 = " v11" ;
870+ std::string const value12 = " v12" ;
871+ std::string const value21 = " v21" ;
872+ std::string const value22 = " v22" ;
873+ std::vector<Cell> created = {
874+ {row_key1, family, column1, 0 , value11},
875+ {row_key1, family, column2, 0 , value12},
876+ {row_key2, family, column1, 0 , value21},
877+ {row_key2, family, column2, 0 , value22},
878+ };
879+
880+ BulkApply (table, created);
881+ auto client = Client (connection, opts);
882+ std::vector<std::string> full_table_path =
883+ absl::StrSplit (table.table_name (), ' /' );
884+ auto table_name = full_table_path.back ();
885+ std::string quoted_table_name = " `" + table_name + " `" ;
886+ Project project (project_id ());
887+ InstanceResource instance_resource (project, instance_id ());
888+ auto prepared_query = client.PrepareQuery (
889+ instance_resource,
890+ SqlStatement (" SELECT CAST(_key AS STRING) AS _key, "
891+ " CAST(family4['c1'] AS STRING) AS c1, "
892+ " CAST(family4['c2'] AS STRING) AS c2 FROM " +
893+ quoted_table_name + " WHERE _key IN ('" + row_key1 + " ', '" +
894+ row_key2 + " ')" ));
895+ ASSERT_STATUS_OK (prepared_query);
896+ auto bound_query = prepared_query->BindParameters ({});
897+ auto row_stream = client.ExecuteQuery (std::move (bound_query));
898+ using RowType = std::tuple<std::string, std::string, std::string>;
899+ std::vector<RowType> rows;
900+ for (auto & row : StreamOf<RowType>(row_stream)) {
901+ ASSERT_STATUS_OK (row);
902+ rows.push_back (*std::move (row));
903+ }
904+
905+ EXPECT_THAT (rows, UnorderedElementsAre (
906+ RowType (" multi-column-query-row-1" , " v11" , " v12" ),
907+ RowType (" multi-column-query-row-2" , " v21" , " v22" )));
908+ }
909+
844910// TODO(#8800) - remove after deprecation is complete
845911#include " google/cloud/internal/diagnostics_pop.inc"
846912
0 commit comments