in spanner/spanner_snippets/spanner/pg_spanner_numeric_data_type.go [32:165]
func pgNumericDataType(w io.Writer, db string) error {
// db := "projects/my-project/instances/my-instance/databases/my-database"
ctx := context.Background()
adminClient, err := database.NewDatabaseAdminClient(ctx)
if err != nil {
return err
}
defer adminClient.Close()
// Create a table that includes a column with data type NUMERIC. As the database has been
// created with the PostgreSQL dialect, the data type that is used will be the PostgreSQL
// NUMERIC / DECIMAL data type.
op, err := adminClient.UpdateDatabaseDdl(ctx, &adminpb.UpdateDatabaseDdlRequest{
Database: db,
Statements: []string{
`CREATE TABLE Venues (
VenueId bigint NOT NULL PRIMARY KEY,
Name varchar(1024) NOT NULL,
Revenues numeric
)`},
})
if err != nil {
return err
}
if err := op.Wait(ctx); err != nil {
return err
}
fmt.Fprintf(w, "Created Venues table\n")
client, err := spanner.NewClient(ctx, db)
if err != nil {
return err
}
defer client.Close()
var updateCount int64
insertSQL := `INSERT INTO Venues (VenueId, Name, Revenues) VALUES ($1, $2, $3)`
// Insert a Venue using DML.
insertStmt := spanner.Statement{
SQL: insertSQL,
Params: map[string]interface{}{
"p1": 1,
"p2": "Venue 1",
"p3": spanner.PGNumeric{Numeric: "3150.25", Valid: true},
},
}
_, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, transaction *spanner.ReadWriteTransaction) error {
updateCount, err = transaction.Update(ctx, insertStmt)
return err
})
if err != nil {
return err
}
fmt.Fprintf(w, "Inserted %d venue(s)\n", updateCount)
// Insert a Venue with a NULL value for the Revenues column.
nullRevenueStmt := spanner.Statement{
SQL: insertSQL,
Params: map[string]interface{}{
"p1": 2,
"p2": "Venue 2",
"p3": spanner.PGNumeric{Valid: false},
},
}
_, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, transaction *spanner.ReadWriteTransaction) error {
updateCount, err = transaction.Update(ctx, nullRevenueStmt)
return err
})
if err != nil {
return err
}
fmt.Fprintf(w, "Inserted %d venue(s) with NULL revenues\n", updateCount)
// Insert a Venue with a NaN (Not a Number) value for the Revenues column.
nanRevenueStmt := spanner.Statement{
SQL: insertSQL,
Params: map[string]interface{}{
"p1": 3,
"p2": "Venue 3",
"p3": spanner.PGNumeric{Numeric: "NaN", Valid: true},
},
}
_, err = client.ReadWriteTransaction(ctx, func(ctx context.Context, transaction *spanner.ReadWriteTransaction) error {
updateCount, err = transaction.Update(ctx, nanRevenueStmt)
return err
})
if err != nil {
return err
}
fmt.Fprintf(w, "Inserted %d venue(s) with NaN revenues\n", updateCount)
// Get all Venues and inspect the Revenues values.
iter := client.Single().Query(ctx, spanner.Statement{
SQL: "SELECT Name, Revenues FROM Venues",
})
defer iter.Stop()
for {
row, err := iter.Next()
if err == iterator.Done {
break
}
if err != nil {
return err
}
var name string
var revenues spanner.PGNumeric
if err := row.Columns(&name, &revenues); err != nil {
return err
}
fmt.Fprintf(w, "Revenues of %s: %s\n", name, revenues)
}
// Mutations can also be used to insert/update NUMERIC values, including NaN values.
ts, err := client.Apply(ctx, []*spanner.Mutation{
spanner.InsertMap("Venues", map[string]interface{}{
"VenueId": 4,
"Name": "Venue 4",
"Revenues": spanner.PGNumeric{Numeric: "125.10", Valid: true},
}),
spanner.InsertMap("Venues", map[string]interface{}{
"VenueId": 5,
"Name": "Venue 5",
"Revenues": spanner.PGNumeric{Numeric: "NaN", Valid: true},
}),
})
if err != nil {
return err
}
fmt.Fprintf(w, "Inserted 2 Venues using mutations at %s\n", ts)
return nil
}