// Copyright 2026 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; package google.spanner.v1; import "google/api/field_behavior.proto"; import "google/protobuf/struct.proto"; import "google/protobuf/timestamp.proto"; import "google/spanner/v1/keys.proto"; option csharp_namespace = "Google.Cloud.Spanner.V1"; option go_package = "cloud.google.com/go/spanner/apiv1/spannerpb;spannerpb"; option java_multiple_files = true; option java_outer_classname = "MutationProto"; option java_package = "com.google.spanner.v1"; option php_namespace = "Google\\Cloud\\Spanner\\V1"; option ruby_package = "Google::Cloud::Spanner::V1"; // A modification to one or more Cloud Spanner rows. Mutations can be // applied to a Cloud Spanner database by sending them in a // [Commit][google.spanner.v1.Spanner.Commit] call. message Mutation { // Arguments to [insert][google.spanner.v1.Mutation.insert], // [update][google.spanner.v1.Mutation.update], // [insert_or_update][google.spanner.v1.Mutation.insert_or_update], and // [replace][google.spanner.v1.Mutation.replace] operations. message Write { // Required. The table whose rows will be written. string table = 1 [(google.api.field_behavior) = REQUIRED]; // The names of the columns in // [table][google.spanner.v1.Mutation.Write.table] to be written. // // The list of columns must contain enough columns to allow // Cloud Spanner to derive values for all primary key columns in the // row(s) to be modified. repeated string columns = 2; // The values to be written. `values` can contain more than one // list of values. If it does, then multiple rows are written, one // for each entry in `values`. Each list in `values` must have // exactly as many entries as there are entries in // [columns][google.spanner.v1.Mutation.Write.columns] above. Sending // multiple lists is equivalent to sending multiple `Mutation`s, each // containing one `values` entry and repeating // [table][google.spanner.v1.Mutation.Write.table] and // [columns][google.spanner.v1.Mutation.Write.columns]. Individual values in // each list are encoded as described [here][google.spanner.v1.TypeCode]. repeated google.protobuf.ListValue values = 3; } // Arguments to [delete][google.spanner.v1.Mutation.delete] operations. message Delete { // Required. The table whose rows will be deleted. string table = 1 [(google.api.field_behavior) = REQUIRED]; // Required. The primary keys of the rows within // [table][google.spanner.v1.Mutation.Delete.table] to delete. The primary // keys must be specified in the order in which they appear in the `PRIMARY // KEY()` clause of the table's equivalent DDL statement (the DDL statement // used to create the table). Delete is idempotent. The transaction will // succeed even if some or all rows do not exist. KeySet key_set = 2 [(google.api.field_behavior) = REQUIRED]; } // Arguments to [send][google.spanner.v1.Mutation.send] operations. message Send { // Required. The queue to which the message will be sent. string queue = 1 [(google.api.field_behavior) = REQUIRED]; // Required. The primary key of the message to be sent. google.protobuf.ListValue key = 2 [(google.api.field_behavior) = REQUIRED]; // The time at which Spanner will begin attempting to deliver the message. // If `deliver_time` is not set, Spanner will deliver the message // immediately. If `deliver_time` is in the past, Spanner will replace it // with a value closer to the current time. google.protobuf.Timestamp deliver_time = 3; // The payload of the message. google.protobuf.Value payload = 4; } // Arguments to [ack][google.spanner.v1.Mutation.ack] operations. message Ack { // Required. The queue where the message to be acked is stored. string queue = 1 [(google.api.field_behavior) = REQUIRED]; // Required. The primary key of the message to be acked. google.protobuf.ListValue key = 2 [(google.api.field_behavior) = REQUIRED]; // By default, an attempt to ack a message that does not exist will fail // with a `NOT_FOUND` error. With `ignore_not_found` set to true, the ack // will succeed even if the message does not exist. This is useful for // unconditionally acking a message, even if it is missing or has already // been acked. bool ignore_not_found = 3; } // Required. The operation to perform. oneof operation { // Insert new rows in a table. If any of the rows already exist, // the write or transaction fails with error `ALREADY_EXISTS`. Write insert = 1; // Update existing rows in a table. If any of the rows does not // already exist, the transaction fails with error `NOT_FOUND`. Write update = 2; // Like [insert][google.spanner.v1.Mutation.insert], except that if the row // already exists, then its column values are overwritten with the ones // provided. Any column values not explicitly written are preserved. // // When using // [insert_or_update][google.spanner.v1.Mutation.insert_or_update], just as // when using [insert][google.spanner.v1.Mutation.insert], all `NOT NULL` // columns in the table must be given a value. This holds true even when the // row already exists and will therefore actually be updated. Write insert_or_update = 3; // Like [insert][google.spanner.v1.Mutation.insert], except that if the row // already exists, it is deleted, and the column values provided are // inserted instead. Unlike // [insert_or_update][google.spanner.v1.Mutation.insert_or_update], this // means any values not explicitly written become `NULL`. // // In an interleaved table, if you create the child table with the // `ON DELETE CASCADE` annotation, then replacing a parent row // also deletes the child rows. Otherwise, you must delete the // child rows before you replace the parent row. Write replace = 4; // Delete rows from a table. Succeeds whether or not the named // rows were present. Delete delete = 5; // Send a message to a queue. Send send = 6; // Ack a message from a queue. Ack ack = 7; } }