diff --git a/spanner/spanner_snippets/spanner/integration_test.go b/spanner/spanner_snippets/spanner/integration_test.go index 20e7d1e443..d8ba74ede0 100644 --- a/spanner/spanner_snippets/spanner/integration_test.go +++ b/spanner/spanner_snippets/spanner/integration_test.go @@ -1332,6 +1332,44 @@ func TestAddSplitPointsSample(t *testing.T) { assertContains(t, out, "Added split points") } +func TestDmlWithLastStatementSample(t *testing.T) { + _ = testutil.SystemTest(t) + t.Parallel() + + _, dbName, cleanup := initTest(t, randomID()) + defer cleanup() + + _, cancel := context.WithTimeout(context.Background(), time.Hour) + defer cancel() + mustRunSample(t, createDatabase, dbName, "failed to create a database") + + out := runSample(t, insertAndUpdateDmlWithLastStatement, dbName, "failed to insert and then update using DML with last statement option") + assertContains(t, out, "1 record(s) inserted.") + assertContains(t, out, "1 record(s) updated.") +} + +func TestPgDmlWithLastStatementSample(t *testing.T) { + _ = testutil.SystemTest(t) + t.Parallel() + + _, dbName, cleanup := initTest(t, randomID()) + defer cleanup() + dbCleanup, err := createTestPgDatabase(dbName, + `CREATE TABLE Singers ( + SingerId bigint NOT NULL PRIMARY KEY, + FirstName varchar(1024), + LastName varchar(1024) + )`) + if err != nil { + t.Fatalf("failed to create test database: %v", err) + } + defer dbCleanup() + + out := runSample(t, pgInsertAndUpdateDmlWithLastStatement, dbName, "failed to insert and then update using DML with last statement option") + assertContains(t, out, "1 record(s) inserted.") + assertContains(t, out, "1 record(s) updated.") +} + func maybeCreateKey(projectId, locationId, keyRingId, keyId string) error { client, err := kms.NewKeyManagementClient(context.Background()) if err != nil { diff --git a/spanner/spanner_snippets/spanner/pg_spanner_dml_last_statement.go b/spanner/spanner_snippets/spanner/pg_spanner_dml_last_statement.go new file mode 100644 index 0000000000..efdf624d41 --- /dev/null +++ b/spanner/spanner_snippets/spanner/pg_spanner_dml_last_statement.go @@ -0,0 +1,67 @@ +// Copyright 2025 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 +// +// https://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. + +package spanner + +// [START spanner_postgresql_dml_last_statement] + +import ( + "context" + "fmt" + "io" + + "cloud.google.com/go/spanner" +) + +// Inserts a record into the Singers table and then updates +// the row while also setting the update DML as the last +// statement. +func pgInsertAndUpdateDmlWithLastStatement(w io.Writer, db string) error { + ctx := context.Background() + client, err := spanner.NewClient(ctx, db) + if err != nil { + return err + } + defer client.Close() + + _, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error { + insertStmt := spanner.Statement{ + SQL: `INSERT INTO Singers (SingerId, FirstName, LastName) + VALUES (54214, 'John', 'Do')`, + } + insertRowCount, err := txn.Update(ctx, insertStmt) + if err != nil { + return err + } + fmt.Fprintf(w, "%d record(s) inserted.\n", insertRowCount) + + updateStmt := spanner.Statement{ + SQL: `UPDATE Singers SET LastName = 'Doe' WHERE SingerId = 54214`, + } + opts := spanner.QueryOptions{LastStatement: true} + updateRowCount, err := txn.UpdateWithOptions(ctx, updateStmt, opts) + if err != nil { + return err + } + fmt.Fprintf(w, "%d record(s) updated.\n", updateRowCount) + return nil + }) + if err != nil { + return err + } + + return nil +} + +// [END spanner_postgresql_dml_last_statement] diff --git a/spanner/spanner_snippets/spanner/spanner_dml_last_statement.go b/spanner/spanner_snippets/spanner/spanner_dml_last_statement.go new file mode 100644 index 0000000000..aaf9b5ccd5 --- /dev/null +++ b/spanner/spanner_snippets/spanner/spanner_dml_last_statement.go @@ -0,0 +1,67 @@ +// Copyright 2025 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 +// +// https://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. + +package spanner + +// [START spanner_dml_last_statement] + +import ( + "context" + "fmt" + "io" + + "cloud.google.com/go/spanner" +) + +// Inserts a record into the Singers table and then updates +// the row while also setting the update DML as the last +// statement. +func insertAndUpdateDmlWithLastStatement(w io.Writer, db string) error { + ctx := context.Background() + client, err := spanner.NewClient(ctx, db) + if err != nil { + return err + } + defer client.Close() + + _, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, txn *spanner.ReadWriteTransaction) error { + insertStmt := spanner.Statement{ + SQL: `INSERT Singers (SingerId, FirstName, LastName) + VALUES (54213, 'John', 'Do')`, + } + insertRowCount, err := txn.Update(ctx, insertStmt) + if err != nil { + return err + } + fmt.Fprintf(w, "%d record(s) inserted.\n", insertRowCount) + + updateStmt := spanner.Statement{ + SQL: `UPDATE Singers SET LastName = 'Doe' WHERE SingerId = 54213`, + } + opts := spanner.QueryOptions{LastStatement: true} + updateRowCount, err := txn.UpdateWithOptions(ctx, updateStmt, opts) + if err != nil { + return err + } + fmt.Fprintf(w, "%d record(s) updated.\n", updateRowCount) + return nil + }) + if err != nil { + return err + } + + return nil +} + +// [END spanner_dml_last_statement]