-
Notifications
You must be signed in to change notification settings - Fork 5
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
6 changed files
with
306 additions
and
39 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
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,77 @@ | ||
// 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 snippets | ||
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
spannergorm "github.com/googleapis/go-gorm-spanner" | ||
"github.com/googleapis/go-gorm-spanner/samples/snippets/sample_model" | ||
_ "github.com/googleapis/go-sql-spanner" | ||
"gorm.io/gorm" | ||
) | ||
|
||
// BatchDml shows how to use the START BATCH DML / RUN BATCH feature in Spanner to buffer | ||
// multiple update statements and execute these in one round-trip to Spanner. | ||
// | ||
// Execute the sample with the command `go run run_sample.go batch_dml` from this directory. | ||
func BatchDml(projectId, instanceId, databaseId string) error { | ||
db, err := gorm.Open(spannergorm.New(spannergorm.Config{ | ||
DriverName: "spanner", | ||
DSN: fmt.Sprintf("projects/%s/instances/%s/databases/%s", projectId, instanceId, databaseId), | ||
}), &gorm.Config{}) | ||
if err != nil { | ||
return fmt.Errorf("failed to open database connection: %v\n", err) | ||
} | ||
|
||
// Insert 50 test singer records. | ||
if err := insertTestSingers(db); err != nil { | ||
return err | ||
} | ||
|
||
// Run a read/write transaction on Spanner that fetches all singers, and updates the Active | ||
// flag of each singer as a separate statement. | ||
// The START BATCH DML / RUN BATCH statements ensure that these single statements are sent | ||
// to Spanner as a single batch. This happens in the following way: | ||
// 1. START BATCH DML creates a DML batch on the transaction. | ||
// 2. All DML statements on the same transaction are now buffered in memory instead of being sent | ||
// directly to Spanner. | ||
// 3. RUN BATCH flushes all statements that have been buffered. | ||
var singers []*sample_model.Singer | ||
return spannergorm.RunTransaction(context.Background(), db, func(tx *gorm.DB) error { | ||
if err := tx.Order("last_name").Find(&singers).Error; err != nil { | ||
return err | ||
} | ||
// Start a DML batch. This will buffer all DML statements in memory until | ||
// RUN BATCH is executed. | ||
if err := tx.Exec("START BATCH DML").Error; err != nil { | ||
return err | ||
} | ||
for _, singer := range singers { | ||
singer.Active = false | ||
if err := tx.Save(singer).Error; err != nil { | ||
tx.Rollback() | ||
return err | ||
} | ||
} | ||
// Execute RUN BATCH. This flushes all buffered DML statements to Spanner. | ||
if err := tx.Exec("RUN BATCH").Error; err != nil { | ||
return err | ||
} | ||
fmt.Println("Executed 50 updates in a single DML batch on Spanner") | ||
return nil | ||
}) | ||
} |
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,94 @@ | ||
// 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 snippets | ||
|
||
import ( | ||
"fmt" | ||
|
||
spannergorm "github.com/googleapis/go-gorm-spanner" | ||
"gorm.io/gorm" | ||
) | ||
|
||
type blog struct { | ||
// gorm automatically assumes that the field with the name ID is the primary | ||
// key of the table. It also assumes that it is auto-generated if the type | ||
// is an integer of any type. | ||
ID int64 | ||
Title string | ||
} | ||
|
||
// BitReversedSequence shows how to use a bit-reversed sequence to generate | ||
// the primary key value in gorm. Using a primary key that is generated by | ||
// Spanner, means that gorm must use a THEN RETURN clause to return the | ||
// primary key from the server. As a new primary key value is generated for | ||
// each transaction attempt, it means that transactions must be defined using | ||
// a transaction runner, or in some other way must be retried using a retry | ||
// loop. | ||
// | ||
// Execute the sample with the command `go run run_sample.go bit_reversed_sequence` | ||
// from the samples directory. | ||
func BitReversedSequence(projectId, instanceId, databaseId string) error { | ||
db, err := gorm.Open(spannergorm.New(spannergorm.Config{ | ||
DriverName: "spanner", | ||
DSN: fmt.Sprintf("projects/%s/instances/%s/databases/%s", projectId, instanceId, databaseId), | ||
}), &gorm.Config{PrepareStmt: true}) | ||
if err != nil { | ||
return fmt.Errorf("failed to open database connection: %v\n", err) | ||
} | ||
|
||
// Dry-run the migration to verify the DDL statements that will be executed. | ||
m := db.Migrator() | ||
migrator, ok := m.(spannergorm.SpannerMigrator) | ||
if !ok { | ||
return fmt.Errorf("unexpected migrator type: %v", m) | ||
} | ||
// Dry-run the migrations and print the generated statements. | ||
statements, err := migrator.AutoMigrateDryRun(&blog{}) | ||
if err != nil { | ||
return fmt.Errorf("could not dry-run migrations: %v", err) | ||
} | ||
fmt.Print("\nMigrations dry-run generated these statements:\n\n") | ||
for _, statement := range statements { | ||
fmt.Printf("%s;\n", statement.SQL) | ||
} | ||
fmt.Println() | ||
|
||
// Create the `blogs` table. This table uses an auto-generated primary key with a backing | ||
// bit-reversed sequence. | ||
if err := db.Migrator().AutoMigrate(&blog{}); err != nil { | ||
return fmt.Errorf("could not execute migrations: %v", err) | ||
} | ||
// Insert some blog records in the database. | ||
if err := db.CreateInBatches([]*blog{ | ||
{Title: "Blog 1"}, | ||
{Title: "Blog 2"}, | ||
{Title: "Blog 3"}, | ||
{Title: "Blog 4"}, | ||
}, 100).Error; err != nil { | ||
return err | ||
} | ||
|
||
// Verify that the records were created. | ||
var blogs []blog | ||
if err := db.Model(&blog{}).Order("title").Find(&blogs).Error; err != nil { | ||
return err | ||
} | ||
fmt.Println("Found these blogs:") | ||
for _, blog := range blogs { | ||
fmt.Printf("%d %s\n", blog.ID, blog.Title) | ||
} | ||
|
||
return nil | ||
} |
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
Oops, something went wrong.