Google Cloud Spanner C++ Client  1.32.0
A C++ Client Library for Google Cloud Spanner
mutations.h
Go to the documentation of this file.
1 // Copyright 2019 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 // http://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_SPANNER_MUTATIONS_H
16 #define GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_MUTATIONS_H
17 
18 #include "google/cloud/spanner/keys.h"
19 #include "google/cloud/spanner/value.h"
20 #include "google/cloud/spanner/version.h"
21 #include <google/spanner/v1/mutation.pb.h>
22 #include <string>
23 #include <vector>
24 
25 namespace google {
26 namespace cloud {
27 namespace spanner_internal {
28 inline namespace SPANNER_CLIENT_NS {
29 template <typename Op>
30 class WriteMutationBuilder;
31 class DeleteMutationBuilder;
32 } // namespace SPANNER_CLIENT_NS
33 } // namespace spanner_internal
34 
35 namespace spanner {
36 inline namespace SPANNER_CLIENT_NS {
37 
38 /**
39  * A wrapper for Cloud Spanner mutations.
40  *
41  * In addition to the Data Manipulation Language (DML) based APIs, Cloud Spanner
42  * supports the mutation API, where the application describes data modification
43  * using a data structure instead of a SQL statement.
44  *
45  * This class serves as a wrapper for all mutations types. Use the builders,
46  * such as `InsertMutationBuilder` or `UpdateMutationBuilder` to create objects
47  * of this class.
48  *
49  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
50  * for more information about the Cloud Spanner mutation API.
51  */
52 class Mutation {
53  public:
54  /**
55  * Creates an empty mutation.
56  *
57  * @note Empty mutations are not usable with the Cloud Spanner mutation API.
58  */
59  Mutation() = default;
60 
61  Mutation(Mutation&&) = default;
62  Mutation& operator=(Mutation&&) = default;
63  Mutation(Mutation const&) = default;
64  Mutation& operator=(Mutation const&) = default;
65 
66  friend bool operator==(Mutation const& lhs, Mutation const& rhs);
67  friend bool operator!=(Mutation const& lhs, Mutation const& rhs) {
68  return !(lhs == rhs);
69  }
70 
71  /// Convert the mutation to the underlying proto.
72  google::spanner::v1::Mutation as_proto() && { return std::move(m_); }
73  google::spanner::v1::Mutation as_proto() const& { return m_; }
74 
75  /**
76  * Allows Google Test to print internal debugging information when test
77  * assertions fail.
78  *
79  * @warning This is intended for debugging and human consumption only, not
80  * machine consumption as the output format may change without notice.
81  */
82  friend void PrintTo(Mutation const& m, std::ostream* os);
83 
84  private:
85  google::spanner::v1::Mutation& proto() & { return m_; }
86 
87  template <typename Op>
88  friend class spanner_internal::SPANNER_CLIENT_NS::WriteMutationBuilder;
89  friend class spanner_internal::SPANNER_CLIENT_NS::DeleteMutationBuilder;
90  explicit Mutation(google::spanner::v1::Mutation m) : m_(std::move(m)) {}
91 
92  google::spanner::v1::Mutation m_;
93 };
94 
95 /**
96  * An ordered sequence of mutations to pass to `Client::Commit()` or return
97  * from the `Client::Commit()` mutator.
98  */
99 using Mutations = std::vector<Mutation>;
100 
101 } // namespace SPANNER_CLIENT_NS
102 } // namespace spanner
103 
104 // This namespace contains implementation details. It is not part of the public
105 // API, and subject to change without notice.
106 namespace spanner_internal {
107 inline namespace SPANNER_CLIENT_NS {
108 
109 template <typename Op>
110 class WriteMutationBuilder {
111  public:
112  WriteMutationBuilder(std::string table_name,
113  std::vector<std::string> column_names) {
114  auto& field = Op::mutable_field(m_.proto());
115  field.set_table(std::move(table_name));
116  field.mutable_columns()->Reserve(static_cast<int>(column_names.size()));
117  for (auto& name : column_names) {
118  field.add_columns(std::move(name));
119  }
120  }
121 
122  spanner::Mutation Build() const& { return m_; }
123  spanner::Mutation&& Build() && { return std::move(m_); }
124 
125  WriteMutationBuilder& AddRow(std::vector<spanner::Value> values) & {
126  auto& lv = *Op::mutable_field(m_.proto()).add_values();
127  for (auto& v : values) {
128  std::tie(std::ignore, *lv.add_values()) =
129  spanner_internal::ToProto(std::move(v));
130  }
131  return *this;
132  }
133 
134  WriteMutationBuilder&& AddRow(std::vector<spanner::Value> values) && {
135  return std::move(AddRow(std::move(values)));
136  }
137 
138  template <typename... Ts>
139  WriteMutationBuilder& EmplaceRow(Ts&&... values) & {
140  return AddRow({spanner::Value(std::forward<Ts>(values))...});
141  }
142 
143  template <typename... Ts>
144  WriteMutationBuilder&& EmplaceRow(Ts&&... values) && {
145  return std::move(EmplaceRow(std::forward<Ts>(values)...));
146  }
147 
148  private:
149  spanner::Mutation m_;
150 };
151 
152 struct InsertOp {
153  static google::spanner::v1::Mutation::Write& mutable_field(
154  google::spanner::v1::Mutation& m) {
155  return *m.mutable_insert();
156  }
157 };
158 
159 struct UpdateOp {
160  static google::spanner::v1::Mutation::Write& mutable_field(
161  google::spanner::v1::Mutation& m) {
162  return *m.mutable_update();
163  }
164 };
165 
166 struct InsertOrUpdateOp {
167  static google::spanner::v1::Mutation::Write& mutable_field(
168  google::spanner::v1::Mutation& m) {
169  return *m.mutable_insert_or_update();
170  }
171 };
172 
173 struct ReplaceOp {
174  static google::spanner::v1::Mutation::Write& mutable_field(
175  google::spanner::v1::Mutation& m) {
176  return *m.mutable_replace();
177  }
178 };
179 
180 class DeleteMutationBuilder {
181  public:
182  DeleteMutationBuilder(std::string table_name, spanner::KeySet keys) {
183  auto& field = *m_.proto().mutable_delete_();
184  field.set_table(std::move(table_name));
185  *field.mutable_key_set() = spanner_internal::ToProto(std::move(keys));
186  }
187 
188  spanner::Mutation Build() const& { return m_; }
189  spanner::Mutation&& Build() && { return std::move(m_); }
190 
191  private:
192  spanner::Mutation m_;
193 };
194 
195 } // namespace SPANNER_CLIENT_NS
196 } // namespace spanner_internal
197 
198 namespace spanner {
199 inline namespace SPANNER_CLIENT_NS {
200 
201 /**
202  * A helper class to construct "insert" mutations.
203  *
204  * @par Example
205  * @snippet samples.cc insert-mutation-builder
206  *
207  * @see The Mutation class documentation for an overview of the Cloud Spanner
208  * mutation API
209  *
210  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
211  * for more information about the Cloud Spanner mutation API.
212  */
213 using InsertMutationBuilder =
214  spanner_internal::WriteMutationBuilder<spanner_internal::InsertOp>;
215 
216 /**
217  * Creates a simple insert mutation for the values in @p values.
218  *
219  * @par Example
220  * @snippet samples.cc make-insert-mutation
221  *
222  * @see The Mutation class documentation for an overview of the Cloud Spanner
223  * mutation API
224  *
225  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
226  * for more information about the Cloud Spanner mutation API.
227  */
228 template <typename... Ts>
229 Mutation MakeInsertMutation(std::string table_name,
230  std::vector<std::string> columns, Ts&&... values) {
231  return InsertMutationBuilder(std::move(table_name), std::move(columns))
232  .EmplaceRow(std::forward<Ts>(values)...)
233  .Build();
234 }
235 
236 /**
237  * A helper class to construct "update" mutations.
238  *
239  * @par Example
240  * @snippet samples.cc update-mutation-builder
241  *
242  * @see The Mutation class documentation for an overview of the Cloud Spanner
243  * mutation API
244  *
245  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
246  * for more information about the Cloud Spanner mutation API.
247  */
248 using UpdateMutationBuilder =
249  spanner_internal::WriteMutationBuilder<spanner_internal::UpdateOp>;
250 
251 /**
252  * Creates a simple update mutation for the values in @p values.
253  *
254  * @par Example
255  * @snippet samples.cc make-update-mutation
256  *
257  * @see The Mutation class documentation for an overview of the Cloud Spanner
258  * mutation API
259  *
260  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
261  * for more information about the Cloud Spanner mutation API.
262  */
263 template <typename... Ts>
264 Mutation MakeUpdateMutation(std::string table_name,
265  std::vector<std::string> columns, Ts&&... values) {
266  return UpdateMutationBuilder(std::move(table_name), std::move(columns))
267  .EmplaceRow(std::forward<Ts>(values)...)
268  .Build();
269 }
270 
271 /**
272  * A helper class to construct "insert_or_update" mutations.
273  *
274  * @par Example
275  * @snippet samples.cc insert-or-update-mutation-builder
276  *
277  * @see The Mutation class documentation for an overview of the Cloud Spanner
278  * mutation API
279  *
280  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
281  * for more information about the Cloud Spanner mutation API.
282  */
283 using InsertOrUpdateMutationBuilder =
284  spanner_internal::WriteMutationBuilder<spanner_internal::InsertOrUpdateOp>;
285 
286 /**
287  * Creates a simple "insert or update" mutation for the values in @p values.
288  *
289  * @par Example
290  * @snippet samples.cc make-insert-or-update-mutation
291  *
292  * @see The Mutation class documentation for an overview of the Cloud Spanner
293  * mutation API
294  *
295  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
296  * for more information about the Cloud Spanner mutation API.
297  */
298 template <typename... Ts>
299 Mutation MakeInsertOrUpdateMutation(std::string table_name,
300  std::vector<std::string> columns,
301  Ts&&... values) {
302  return InsertOrUpdateMutationBuilder(std::move(table_name),
303  std::move(columns))
304  .EmplaceRow(std::forward<Ts>(values)...)
305  .Build();
306 }
307 
308 /**
309  * A helper class to construct "replace" mutations.
310  *
311  * @par Example
312  * @snippet samples.cc replace-mutation-builder
313  *
314  * @see The Mutation class documentation for an overview of the Cloud Spanner
315  * mutation API
316  *
317  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
318  * for more information about the Cloud Spanner mutation API.
319  */
320 using ReplaceMutationBuilder =
321  spanner_internal::WriteMutationBuilder<spanner_internal::ReplaceOp>;
322 
323 /**
324  * Creates a simple "replace" mutation for the values in @p values.
325  *
326  * @par Example
327  * @snippet samples.cc make-replace-mutation
328  *
329  * @see The Mutation class documentation for an overview of the Cloud Spanner
330  * mutation API
331  *
332  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
333  * for more information about the Cloud Spanner mutation API.
334  */
335 template <typename... Ts>
336 Mutation MakeReplaceMutation(std::string table_name,
337  std::vector<std::string> columns, Ts&&... values) {
338  return ReplaceMutationBuilder(std::move(table_name), std::move(columns))
339  .EmplaceRow(std::forward<Ts>(values)...)
340  .Build();
341 }
342 
343 /**
344  * A helper class to construct "delete" mutations.
345  *
346  * @par Example
347  * @snippet samples.cc delete-mutation-builder
348  *
349  * @see The Mutation class documentation for an overview of the Cloud Spanner
350  * mutation API
351  *
352  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
353  * for more information about the Cloud Spanner mutation API.
354  */
355 using DeleteMutationBuilder = spanner_internal::DeleteMutationBuilder;
356 
357 /**
358  * Creates a simple "delete" mutation for the values in @p keys.
359  *
360  * @par Example
361  * @snippet samples.cc make-delete-mutation
362  *
363  * @see The Mutation class documentation for an overview of the Cloud Spanner
364  * mutation API
365  *
366  * @see https://cloud.google.com/spanner/docs/modify-mutation-api
367  * for more information about the Cloud Spanner mutation API.
368  */
369 inline Mutation MakeDeleteMutation(std::string table_name, KeySet keys) {
370  return DeleteMutationBuilder(std::move(table_name), std::move(keys)).Build();
371 }
372 
373 } // namespace SPANNER_CLIENT_NS
374 } // namespace spanner
375 } // namespace cloud
376 } // namespace google
377 
378 #endif // GOOGLE_CLOUD_CPP_GOOGLE_CLOUD_SPANNER_MUTATIONS_H