Skip to content

Commit 66b9132

Browse files
feat(bigtable): add support for Prepared and Bound query (#15650)
* feat(bigtable): add support for Prepared and Bound query * chore: decompose BasicInputs for readability * chore: separate into respective files * chore: configure bazel and makefile * chore: fix compilation error
1 parent f149191 commit 66b9132

File tree

10 files changed

+394
-1
lines changed

10 files changed

+394
-1
lines changed

google/cloud/bigtable/CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,8 @@ add_library(
109109
app_profile_config.cc
110110
app_profile_config.h
111111
async_row_reader.h
112+
bound_query.cc
113+
bound_query.h
112114
bytes.cc
113115
bytes.h
114116
cell.h
@@ -236,6 +238,8 @@ add_library(
236238
options.h
237239
polling_policy.cc
238240
polling_policy.h
241+
prepared_query.cc
242+
prepared_query.h
239243
query_row.cc
240244
query_row.h
241245
read_modify_write_rule.h
@@ -437,6 +441,7 @@ if (BUILD_TESTING)
437441
app_profile_config_test.cc
438442
async_read_stream_test.cc
439443
bigtable_version_test.cc
444+
bound_query_test.cc
440445
bytes_test.cc
441446
cell_test.cc
442447
client_options_test.cc
@@ -494,6 +499,7 @@ if (BUILD_TESTING)
494499
mutation_batcher_test.cc
495500
mutations_test.cc
496501
polling_policy_test.cc
502+
prepared_query_test.cc
497503
query_row_test.cc
498504
read_modify_write_rule_test.cc
499505
row_range_test.cc

google/cloud/bigtable/bigtable_client_unit_tests.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ bigtable_client_unit_tests = [
2121
"app_profile_config_test.cc",
2222
"async_read_stream_test.cc",
2323
"bigtable_version_test.cc",
24+
"bound_query_test.cc",
2425
"bytes_test.cc",
2526
"cell_test.cc",
2627
"client_options_test.cc",
@@ -78,6 +79,7 @@ bigtable_client_unit_tests = [
7879
"mutation_batcher_test.cc",
7980
"mutations_test.cc",
8081
"polling_policy_test.cc",
82+
"prepared_query_test.cc",
8183
"query_row_test.cc",
8284
"read_modify_write_rule_test.cc",
8385
"row_range_test.cc",
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/bigtable/bound_query.h"
16+
17+
namespace google {
18+
namespace cloud {
19+
namespace bigtable {
20+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
21+
22+
StatusOr<std::string> BoundQuery::prepared_query() const {
23+
return query_plan_->prepared_query();
24+
}
25+
26+
StatusOr<google::bigtable::v2::ResultSetMetadata> BoundQuery::metadata() const {
27+
return query_plan_->metadata();
28+
}
29+
30+
std::unordered_map<std::string, Value> const& BoundQuery::parameters() const {
31+
return parameters_;
32+
}
33+
34+
InstanceResource const& BoundQuery::instance() const { return instance_; }
35+
36+
google::bigtable::v2::ExecuteQueryRequest BoundQuery::ToRequestProto() {
37+
google::bigtable::v2::ExecuteQueryRequest result;
38+
*result.mutable_instance_name() = instance_.FullName();
39+
auto prepared_query = query_plan_->prepared_query();
40+
if (prepared_query.ok()) {
41+
*result.mutable_prepared_query() = query_plan_->prepared_query().value();
42+
}
43+
44+
google::protobuf::Map<std::string, google::bigtable::v2::Value> parameters;
45+
for (auto const& kv : parameters_) {
46+
parameters[kv.first] =
47+
bigtable_internal::ValueInternals::ToProto(kv.second).second;
48+
}
49+
*result.mutable_params() = parameters;
50+
return result;
51+
}
52+
53+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
54+
} // namespace bigtable
55+
} // namespace cloud
56+
} // namespace google
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#ifndef GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_BOUND_QUERY_H
16+
#define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_BOUND_QUERY_H
17+
18+
#include "google/cloud/bigtable/instance_resource.h"
19+
#include "google/cloud/bigtable/internal/query_plan.h"
20+
#include "google/cloud/bigtable/value.h"
21+
#include "google/cloud/bigtable/version.h"
22+
#include "google/cloud/completion_queue.h"
23+
#include <google/bigtable/v2/bigtable.pb.h>
24+
#include <string>
25+
#include <unordered_map>
26+
27+
namespace google {
28+
namespace cloud {
29+
namespace bigtable {
30+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
31+
32+
/**
33+
* Move only type representing a PreparedQuery with parameter values.
34+
* Created by calling PreparedQuery::BindParameters.
35+
*/
36+
class BoundQuery {
37+
public:
38+
// Copy and move.
39+
BoundQuery(BoundQuery const&) = delete;
40+
BoundQuery(BoundQuery&&) = default;
41+
BoundQuery& operator=(BoundQuery const&) = delete;
42+
BoundQuery& operator=(BoundQuery&&) = default;
43+
44+
// Accessors
45+
StatusOr<std::string> prepared_query() const;
46+
StatusOr<google::bigtable::v2::ResultSetMetadata> metadata() const;
47+
std::unordered_map<std::string, Value> const& parameters() const;
48+
InstanceResource const& instance() const;
49+
50+
google::bigtable::v2::ExecuteQueryRequest ToRequestProto();
51+
52+
private:
53+
friend class PreparedQuery;
54+
BoundQuery(InstanceResource instance,
55+
std::shared_ptr<bigtable_internal::QueryPlan> query_plan,
56+
std::unordered_map<std::string, Value> parameters)
57+
: instance_(std::move(instance)),
58+
query_plan_(std::move(query_plan)),
59+
parameters_(std::move(parameters)) {}
60+
61+
InstanceResource instance_;
62+
// Copy of the query_plan_ contained by the PreparedQuery that created
63+
// this BoundQuery.
64+
std::shared_ptr<bigtable_internal::QueryPlan> query_plan_;
65+
std::unordered_map<std::string, Value> parameters_;
66+
};
67+
68+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
69+
} // namespace bigtable
70+
} // namespace cloud
71+
} // namespace google
72+
#endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_BIGTABLE_BOUND_QUERY_H
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/bigtable/bound_query.h"
16+
#include "google/cloud/bigtable/prepared_query.h"
17+
#include "google/cloud/bigtable/sql_statement.h"
18+
#include "google/cloud/bigtable/value.h"
19+
#include "google/cloud/testing_util/status_matchers.h"
20+
#include <algorithm>
21+
22+
namespace google {
23+
namespace cloud {
24+
namespace bigtable {
25+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
26+
namespace {
27+
using ::google::bigtable::v2::PrepareQueryResponse;
28+
29+
TEST(BoundQuery, FromPreparedQuery) {
30+
CompletionQueue cq;
31+
Project p("dummy-project");
32+
InstanceResource instance(p, "dummy-instance");
33+
std::string statement_contents(
34+
"SELECT * FROM my_table WHERE col1 = @val1 and col2 = @val2;");
35+
SqlStatement sql_statement(statement_contents);
36+
PrepareQueryResponse response;
37+
std::unordered_map<std::string, Value> parameters = {{"val1", Value(true)},
38+
{"val2", Value(2.0)}};
39+
40+
// The following variables are only meant to confirm the metadata is correctly
41+
// passed down to the BoundQuery.
42+
auto metadata = std::make_unique<google::bigtable::v2::ResultSetMetadata>();
43+
auto schema = std::make_unique<google::bigtable::v2::ProtoSchema>();
44+
auto column = google::bigtable::v2::ColumnMetadata();
45+
*column.mutable_name() = "col1";
46+
schema->mutable_columns()->Add(std::move(column));
47+
metadata->set_allocated_proto_schema(schema.release());
48+
response.set_allocated_metadata(metadata.release());
49+
50+
PreparedQuery pq(cq, instance, sql_statement, response);
51+
auto bq = pq.BindParameters(parameters);
52+
EXPECT_EQ(instance.FullName(), bq.instance().FullName());
53+
EXPECT_STATUS_OK(bq.prepared_query());
54+
EXPECT_EQ(statement_contents, bq.prepared_query().value());
55+
EXPECT_EQ(parameters, bq.parameters());
56+
EXPECT_STATUS_OK(bq.metadata());
57+
EXPECT_TRUE(bq.metadata().value().has_proto_schema());
58+
EXPECT_EQ(1, bq.metadata().value().proto_schema().columns_size());
59+
EXPECT_EQ("col1", bq.metadata().value().proto_schema().columns()[0].name());
60+
}
61+
62+
TEST(BoundQuery, ToRequestProto) {
63+
CompletionQueue cq;
64+
Project p("dummy-project");
65+
InstanceResource instance(p, "dummy-instance");
66+
std::string statement_contents(
67+
"SELECT * FROM my_table WHERE col1 = @val1 and col2 = @val2;");
68+
SqlStatement sql_statement(statement_contents);
69+
PrepareQueryResponse response;
70+
std::unordered_map<std::string, Value> parameters = {{"val1", Value(true)},
71+
{"val2", Value(2.0)}};
72+
73+
PreparedQuery pq(cq, instance, sql_statement, response);
74+
auto bq = pq.BindParameters(parameters);
75+
google::bigtable::v2::ExecuteQueryRequest proto = bq.ToRequestProto();
76+
EXPECT_EQ(instance.FullName(), proto.instance_name());
77+
EXPECT_EQ(statement_contents, proto.prepared_query());
78+
79+
// Test param contents.
80+
EXPECT_EQ(parameters.size(), proto.mutable_params()->size());
81+
82+
// The first parameter is a boolean.
83+
EXPECT_TRUE(proto.params().contains("val1"));
84+
auto val1 = proto.params().find("val1")->second;
85+
EXPECT_TRUE(val1.has_bool_value());
86+
EXPECT_EQ(true, val1.bool_value());
87+
88+
// The second parameter is a double.
89+
EXPECT_TRUE(proto.params().contains("val2"));
90+
auto val2 = proto.params().find("val2")->second;
91+
EXPECT_TRUE(val2.has_float_value());
92+
EXPECT_EQ(2.0, val2.float_value());
93+
}
94+
} // namespace
95+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
96+
} // namespace bigtable
97+
} // namespace cloud
98+
} // namespace google

google/cloud/bigtable/google_cloud_cpp_bigtable.bzl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ google_cloud_cpp_bigtable_hdrs = [
4848
"admin_client.h",
4949
"app_profile_config.h",
5050
"async_row_reader.h",
51+
"bound_query.h",
5152
"bytes.h",
5253
"cell.h",
5354
"client_options.h",
@@ -121,6 +122,7 @@ google_cloud_cpp_bigtable_hdrs = [
121122
"mutations.h",
122123
"options.h",
123124
"polling_policy.h",
125+
"prepared_query.h",
124126
"query_row.h",
125127
"read_modify_write_rule.h",
126128
"resource_names.h",
@@ -173,6 +175,7 @@ google_cloud_cpp_bigtable_srcs = [
173175
"admin/internal/bigtable_table_admin_tracing_stub.cc",
174176
"admin_client.cc",
175177
"app_profile_config.cc",
178+
"bound_query.cc",
176179
"bytes.cc",
177180
"client_options.cc",
178181
"cluster_config.cc",
@@ -227,6 +230,7 @@ google_cloud_cpp_bigtable_srcs = [
227230
"mutation_batcher.cc",
228231
"mutations.cc",
229232
"polling_policy.cc",
233+
"prepared_query.cc",
230234
"query_row.cc",
231235
"resource_names.cc",
232236
"row_range.cc",
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Copyright 2025 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "google/cloud/bigtable/prepared_query.h"
16+
#include "google/cloud/bigtable/sql_statement.h"
17+
18+
namespace google {
19+
namespace cloud {
20+
namespace bigtable {
21+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_BEGIN
22+
23+
BoundQuery PreparedQuery::BindParameters(
24+
std::unordered_map<std::string, Value> params) const {
25+
return BoundQuery(instance_, query_plan_, std::move(params));
26+
}
27+
28+
InstanceResource const& PreparedQuery::instance() const { return instance_; }
29+
SqlStatement const& PreparedQuery::sql_statement() const {
30+
return sql_statement_;
31+
}
32+
33+
GOOGLE_CLOUD_CPP_INLINE_NAMESPACE_END
34+
} // namespace bigtable
35+
} // namespace cloud
36+
} // namespace google

0 commit comments

Comments
 (0)