-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
171 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
samples/snippets/golang-snippets/update_data_with_transaction.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
/* | ||
Copyright 2024 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. | ||
*/ | ||
|
||
package golang_snippets | ||
|
||
// [START spanner_dml_getting_started_update] | ||
import ( | ||
"context" | ||
"fmt" | ||
|
||
"github.com/jackc/pgx/v5" | ||
) | ||
|
||
func writeWithTransactionUsingDml(host string, port int, database string) error { | ||
ctx := context.Background() | ||
connString := fmt.Sprintf( | ||
"postgres://uid:pwd@%s:%d/%s?sslmode=disable", | ||
host, port, database) | ||
conn, err := pgx.Connect(ctx, connString) | ||
if err != nil { | ||
return err | ||
} | ||
defer conn.Close(ctx) | ||
|
||
// Transfer marketing budget from one album to another. We do it in a | ||
// transaction to ensure that the transfer is atomic. | ||
tx, err := conn.Begin(ctx) | ||
if err != nil { | ||
return err | ||
} | ||
const selectSql = "SELECT marketing_budget " + | ||
"from albums " + | ||
"WHERE singer_id = $1 and album_id = $2" | ||
// Get the marketing_budget of singer 2 / album 2. | ||
row := tx.QueryRow(ctx, selectSql, 2, 2) | ||
var budget2 int64 | ||
if err := row.Scan(&budget2); err != nil { | ||
tx.Rollback(ctx) | ||
return err | ||
} | ||
const transfer = 20000 | ||
// The transaction will only be committed if this condition still holds | ||
// at the time of commit. Otherwise, the transaction will be aborted. | ||
if budget2 >= transfer { | ||
// Get the marketing_budget of singer 1 / album 1. | ||
row := tx.QueryRow(ctx, selectSql, 1, 1) | ||
var budget1 int64 | ||
if err := row.Scan(&budget1); err != nil { | ||
tx.Rollback(ctx) | ||
return err | ||
} | ||
// Transfer part of the marketing budget of Album 2 to Album 1. | ||
budget1 += transfer | ||
budget2 -= transfer | ||
const updateSql = "UPDATE albums " + | ||
"SET marketing_budget = $1 " + | ||
"WHERE singer_id = $2 and album_id = $3" | ||
// Start a DML batch and execute it as part of the current transaction. | ||
batch := &pgx.Batch{} | ||
batch.Queue(updateSql, budget1, 1, 1) | ||
batch.Queue(updateSql, budget2, 2, 2) | ||
br := tx.SendBatch(ctx, batch) | ||
_, err = br.Exec() | ||
if err := br.Close(); err != nil { | ||
tx.Rollback(ctx) | ||
return err | ||
} | ||
} | ||
// Commit the current transaction. | ||
tx.Commit(ctx) | ||
fmt.Println("Transferred marketing budget from Album 2 to Album 1") | ||
|
||
return nil | ||
} | ||
|
||
// [END spanner_dml_getting_started_update] |
65 changes: 65 additions & 0 deletions
65
samples/snippets/nodejs-snippets/src/update_data_with_transaction.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
// Copyright 2024 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. | ||
|
||
// [START spanner_dml_getting_started_update] | ||
import { Client } from 'pg'; | ||
|
||
async function writeWithTransactionUsingDml(host: string, port: number, database: string): Promise<void> { | ||
const connection = new Client({ | ||
host: host, | ||
port: port, | ||
database: database, | ||
}); | ||
await connection.connect(); | ||
|
||
// Transfer marketing budget from one album to another. We do it in a | ||
// transaction to ensure that the transfer is atomic. node-postgres | ||
// requires you to explicitly start the transaction by executing 'begin'. | ||
await connection.query("begin"); | ||
const selectMarketingBudgetSql = "SELECT marketing_budget " + | ||
"from albums " + | ||
"WHERE singer_id = $1 and album_id = $2"; | ||
// Get the marketing_budget of singer 2 / album 2. | ||
const album2BudgetResult = await connection.query(selectMarketingBudgetSql, [2, 2]); | ||
let album2Budget = album2BudgetResult.rows[0]["marketing_budget"]; | ||
const transfer = 200000; | ||
// The transaction will only be committed if this condition still holds | ||
// at the time of commit. Otherwise, the transaction will be aborted. | ||
if (album2Budget >= transfer) { | ||
// Get the marketing budget of singer 1 / album 1. | ||
const album1BudgetResult = await connection.query(selectMarketingBudgetSql, [1, 1]); | ||
let album1Budget = album1BudgetResult.rows[0]["marketing_budget"]; | ||
// Transfer part of the marketing budget of Album 2 to Album 1. | ||
album1Budget += transfer; | ||
album2Budget -= transfer; | ||
const updateSql = "UPDATE albums " + | ||
"SET marketing_budget = $1 " + | ||
"WHERE singer_id = $2 and album_id = $3"; | ||
// Start a DML batch. This batch will become part of the current transaction. | ||
await connection.query("start batch dml"); | ||
// Update the marketing budget of both albums. | ||
await connection.query(updateSql, [album1Budget, 1, 1]); | ||
await connection.query(updateSql, [album2Budget, 2, 2]); | ||
await connection.query("run batch"); | ||
} | ||
// Commit the current transaction. | ||
await connection.query("commit"); | ||
console.log("Transferred marketing budget from Album 2 to Album 1"); | ||
|
||
// Close the connection. | ||
await connection.end(); | ||
} | ||
// [END spanner_dml_getting_started_update] | ||
|
||
export = writeWithTransactionUsingDml; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters