diff --git a/.github/workflows/spanner-lib-tests.yml b/.github/workflows/spanner-lib-tests.yml
new file mode 100644
index 00000000..8a51445d
--- /dev/null
+++ b/.github/workflows/spanner-lib-tests.yml
@@ -0,0 +1,89 @@
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+permissions:
+ contents: read
+ pull-requests: write
+name: Spanner Lib Tests
+jobs:
+ test:
+ strategy:
+ matrix:
+ go-version: [1.24.x]
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: ${{ matrix.go-version }}
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Run unit tests
+ working-directory: spannerlib/lib
+ run: go test -race -short
+
+ build-lib:
+ strategy:
+ matrix:
+ go-version: [1.24.x]
+ os: [ubuntu-latest, macos-latest, windows-latest]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: ${{ matrix.go-version }}
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Build shared lib
+ working-directory: spannerlib/shared
+ run: go build -o spannerlib.so -buildmode=c-shared shared_lib.go
+
+ test-dotnet-ubuntu:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Install Go
+ uses: actions/setup-go@v5
+ with:
+ go-version: 1.24
+ - name: Checkout code
+ uses: actions/checkout@v4
+ - name: Build shared lib
+ working-directory: spannerlib/shared
+ run: go build -o spannerlib.so -buildmode=c-shared shared_lib.go
+ - name: Copy lib to dotnet folder
+ working-directory: spannerlib
+ run: |
+ mkdir -p dotnet-spannerlib/Google.Cloud.SpannerLib.Native/libraries/any
+ cp shared/spannerlib.so dotnet-spannerlib/Google.Cloud.SpannerLib.Native/libraries/any/spannerlib.so
+ - name: Build gRPC server
+ working-directory: spannerlib/grpc-server
+ run: go build grpc_server.go
+ - name: Copy gRPC server to dotnet folder
+ working-directory: spannerlib
+ run: |
+ mkdir -p dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/binaries/any
+ cp grpc-server/grpc_server dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/binaries/any/grpc_server
+ - name: Install dotnet
+ uses: actions/setup-dotnet@v4
+ with:
+ dotnet-version: '9.0.x'
+ - name: dotnet version
+ run: dotnet --version
+ - name: Build native library package
+ run: dotnet pack
+ working-directory: spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Native
+ - name: Add package source
+ run: dotnet nuget add source "$PWD"/bin/Release --name local
+ working-directory: spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Native
+ - name: Restore dependencies
+ run: dotnet restore
+ working-directory: spannerlib/dotnet-spannerlib
+ - name: Build
+ run: dotnet build --no-restore
+ working-directory: spannerlib/dotnet-spannerlib
+ - name: Unit Tests
+ working-directory: spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Tests
+ run: dotnet test --no-build --verbosity normal
diff --git a/checksum_row_iterator.go b/checksum_row_iterator.go
index 623832a1..c6980a27 100644
--- a/checksum_row_iterator.go
+++ b/checksum_row_iterator.go
@@ -23,6 +23,7 @@ import (
"cloud.google.com/go/spanner"
sppb "cloud.google.com/go/spanner/apiv1/spannerpb"
+ "github.com/googleapis/go-sql-spanner/parser"
"google.golang.org/api/iterator"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
@@ -51,10 +52,11 @@ type checksumRowIterator struct {
*spanner.RowIterator
metadata *sppb.ResultSetMetadata
- ctx context.Context
- tx *readWriteTransaction
- stmt spanner.Statement
- options spanner.QueryOptions
+ ctx context.Context
+ tx *readWriteTransaction
+ stmt spanner.Statement
+ stmtType parser.StatementType
+ options spanner.QueryOptions
// nc (nextCount) indicates the number of times that next has been called
// on the iterator. Next() will be called the same number of times during
// a retry.
@@ -253,10 +255,5 @@ func (it *checksumRowIterator) Metadata() (*sppb.ResultSetMetadata, error) {
}
func (it *checksumRowIterator) ResultSetStats() *sppb.ResultSetStats {
- // TODO: The Spanner client library should offer an option to get the full
- // ResultSetStats, instead of only the RowCount and QueryPlan.
- return &sppb.ResultSetStats{
- RowCount: &sppb.ResultSetStats_RowCountExact{RowCountExact: it.RowIterator.RowCount},
- QueryPlan: it.RowIterator.QueryPlan,
- }
+ return createResultSetStats(it.RowIterator, it.stmtType)
}
diff --git a/conn.go b/conn.go
index 7f9ece77..36adb89d 100644
--- a/conn.go
+++ b/conn.go
@@ -222,6 +222,9 @@ type SpannerConn interface {
// return the same Spanner client.
UnderlyingClient() (client *spanner.Client, err error)
+ // DetectStatementType returns the type of SQL statement.
+ DetectStatementType(query string) parser.StatementType
+
// resetTransactionForRetry resets the current transaction after it has
// been aborted by Spanner. Calling this function on a transaction that
// has not been aborted is not supported and will cause an error to be
@@ -280,12 +283,18 @@ type conn struct {
// tempBatchReadOnlyTransactionOptions are temporarily set right before a
// batch read-only transaction is started on a Spanner connection.
tempBatchReadOnlyTransactionOptions *BatchReadOnlyTransactionOptions
+ tempProtoTransactionOptions *spannerpb.TransactionOptions
}
func (c *conn) UnderlyingClient() (*spanner.Client, error) {
return c.client, nil
}
+func (c *conn) DetectStatementType(query string) parser.StatementType {
+ info := c.parser.DetectStatementType(query)
+ return info.StatementType
+}
+
func (c *conn) CommitTimestamp() (time.Time, error) {
ts := propertyCommitTimestamp.GetValueOrDefault(c.state)
if ts == nil {
@@ -389,6 +398,16 @@ func (c *conn) ReadOnlyStaleness() spanner.TimestampBound {
return propertyReadOnlyStaleness.GetValueOrDefault(c.state)
}
+func (c *conn) readOnlyStalenessPointer() *spanner.TimestampBound {
+ val := propertyReadOnlyStaleness.GetConnectionPropertyValue(c.state)
+ if val == nil || !val.HasValue() {
+ return nil
+ }
+ staleness, _ := val.GetValue()
+ timestampBound := staleness.(spanner.TimestampBound)
+ return ×tampBound
+}
+
func (c *conn) SetReadOnlyStaleness(staleness spanner.TimestampBound) error {
_, err := c.setReadOnlyStaleness(staleness)
return err
@@ -675,6 +694,17 @@ func sum(affected []int64) int64 {
return sum
}
+func (c *conn) WriteMutations(ctx context.Context, ms []*spanner.Mutation) (*spanner.CommitResponse, error) {
+ if c.inTransaction() {
+ return nil, c.BufferWrite(ms)
+ }
+ ts, err := c.Apply(ctx, ms)
+ if err != nil {
+ return nil, err
+ }
+ return &spanner.CommitResponse{CommitTs: ts}, nil
+}
+
func (c *conn) Apply(ctx context.Context, ms []*spanner.Mutation, opts ...spanner.ApplyOption) (commitTimestamp time.Time, err error) {
if c.inTransaction() {
return time.Time{}, spanner.ToSpannerError(
@@ -858,13 +888,13 @@ func (c *conn) queryContext(ctx context.Context, query string, execOptions *Exec
// The statement was either detected as being a query, or potentially not recognized at all.
// In that case, just default to using a single-use read-only transaction and let Spanner
// return an error if the statement is not suited for that type of transaction.
- iter = &readOnlyRowIterator{c.execSingleQuery(ctx, c.client, stmt, c.ReadOnlyStaleness(), execOptions)}
+ iter = &readOnlyRowIterator{c.execSingleQuery(ctx, c.client, stmt, c.ReadOnlyStaleness(), execOptions), statementType.StatementType}
}
} else {
if execOptions.PartitionedQueryOptions.PartitionQuery {
return c.tx.partitionQuery(ctx, stmt, execOptions)
}
- iter, err = c.tx.Query(ctx, stmt, execOptions)
+ iter, err = c.tx.Query(ctx, stmt, statementType.StatementType, execOptions)
if err != nil {
return nil, err
}
@@ -987,6 +1017,7 @@ func (c *conn) options(reset bool) *ExecOptions {
},
},
PartitionedQueryOptions: PartitionedQueryOptions{},
+ TimestampBound: c.readOnlyStalenessPointer(),
}
if c.tempExecOptions != nil {
effectiveOptions.merge(c.tempExecOptions)
@@ -1071,6 +1102,26 @@ func (c *conn) getBatchReadOnlyTransactionOptions() BatchReadOnlyTransactionOpti
return BatchReadOnlyTransactionOptions{TimestampBound: c.ReadOnlyStaleness()}
}
+func (c *conn) BeginReadOnlyTransaction(ctx context.Context, options *ReadOnlyTransactionOptions) (driver.Tx, error) {
+ c.withTempReadOnlyTransactionOptions(options)
+ tx, err := c.BeginTx(ctx, driver.TxOptions{ReadOnly: true})
+ if err != nil {
+ c.withTempReadOnlyTransactionOptions(nil)
+ return nil, err
+ }
+ return tx, nil
+}
+
+func (c *conn) BeginReadWriteTransaction(ctx context.Context, options *ReadWriteTransactionOptions) (driver.Tx, error) {
+ c.withTempTransactionOptions(options)
+ tx, err := c.BeginTx(ctx, driver.TxOptions{})
+ if err != nil {
+ c.withTempTransactionOptions(nil)
+ return nil, err
+ }
+ return tx, nil
+}
+
func (c *conn) Begin() (driver.Tx, error) {
return c.BeginTx(context.Background(), driver.TxOptions{})
}
@@ -1254,7 +1305,7 @@ func (c *conn) inReadWriteTransaction() bool {
return false
}
-func (c *conn) commit(ctx context.Context) (*spanner.CommitResponse, error) {
+func (c *conn) Commit(ctx context.Context) (*spanner.CommitResponse, error) {
if !c.inTransaction() {
return nil, status.Errorf(codes.FailedPrecondition, "this connection does not have a transaction")
}
@@ -1262,10 +1313,13 @@ func (c *conn) commit(ctx context.Context) (*spanner.CommitResponse, error) {
if err := c.tx.Commit(); err != nil {
return nil, err
}
- return c.CommitResponse()
+
+ // This will return either the commit response or nil, depending on whether the transaction was a
+ // read/write transaction or a read-only transaction.
+ return propertyCommitResponse.GetValueOrDefault(c.state), nil
}
-func (c *conn) rollback(ctx context.Context) error {
+func (c *conn) Rollback(ctx context.Context) error {
if !c.inTransaction() {
return status.Errorf(codes.FailedPrecondition, "this connection does not have a transaction")
}
@@ -1274,6 +1328,9 @@ func (c *conn) rollback(ctx context.Context) error {
}
func queryInSingleUse(ctx context.Context, c *spanner.Client, statement spanner.Statement, tb spanner.TimestampBound, options *ExecOptions) *spanner.RowIterator {
+ if options.TimestampBound != nil {
+ tb = *options.TimestampBound
+ }
return c.Single().WithTimestampBound(tb).QueryWithOptions(ctx, statement, options.QueryOptions)
}
diff --git a/driver.go b/driver.go
index 15cec71a..50cfc7dc 100644
--- a/driver.go
+++ b/driver.go
@@ -173,6 +173,10 @@ type ExecOptions struct {
TransactionOptions spanner.TransactionOptions
// QueryOptions are the query options that will be used for the statement.
QueryOptions spanner.QueryOptions
+ // TimestampBound is the timestamp bound that will be used for the statement
+ // if it is a query outside a transaction. Setting this option will override
+ // the default TimestampBound that is set on the connection.
+ TimestampBound *spanner.TimestampBound
// PartitionedQueryOptions are used for partitioned queries, and ignored
// for all other statements.
@@ -234,6 +238,9 @@ func (dest *ExecOptions) merge(src *ExecOptions) {
if src.AutocommitDMLMode != Unspecified {
dest.AutocommitDMLMode = src.AutocommitDMLMode
}
+ if src.TimestampBound != nil {
+ dest.TimestampBound = src.TimestampBound
+ }
(&dest.PartitionedQueryOptions).merge(&src.PartitionedQueryOptions)
mergeQueryOptions(&dest.QueryOptions, &src.QueryOptions)
mergeTransactionOptions(&dest.TransactionOptions, &src.TransactionOptions)
@@ -1143,6 +1150,10 @@ func BeginReadWriteTransaction(ctx context.Context, db *sql.DB, options ReadWrit
// be active when we hit this point.
go conn.Close()
}
+ return BeginReadWriteTransactionOnConn(ctx, conn, options)
+}
+
+func BeginReadWriteTransactionOnConn(ctx context.Context, conn *sql.Conn, options ReadWriteTransactionOptions) (*sql.Tx, error) {
if err := withTempReadWriteTransactionOptions(conn, &options); err != nil {
return nil, err
}
@@ -1195,6 +1206,10 @@ func BeginReadOnlyTransaction(ctx context.Context, db *sql.DB, options ReadOnlyT
// be active when we hit this point.
go conn.Close()
}
+ return BeginReadOnlyTransactionOnConn(ctx, conn, options)
+}
+
+func BeginReadOnlyTransactionOnConn(ctx context.Context, conn *sql.Conn, options ReadOnlyTransactionOptions) (*sql.Tx, error) {
if err := withTempReadOnlyTransactionOptions(conn, &options); err != nil {
return nil, err
}
diff --git a/driver_test.go b/driver_test.go
index 8e62281a..f095f0e8 100644
--- a/driver_test.go
+++ b/driver_test.go
@@ -631,7 +631,9 @@ func TestConn_NonDdlStatementsInDdlBatch(t *testing.T) {
state: createInitialConnectionState(connectionstate.TypeNonTransactional, map[string]connectionstate.ConnectionPropertyValue{}),
batch: &batch{tp: parser.BatchTypeDdl},
execSingleQuery: func(ctx context.Context, c *spanner.Client, statement spanner.Statement, tb spanner.TimestampBound, options *ExecOptions) *spanner.RowIterator {
- return &spanner.RowIterator{}
+ return &spanner.RowIterator{
+ Metadata: &spannerpb.ResultSetMetadata{},
+ }
},
execSingleDMLTransactional: func(ctx context.Context, c *spanner.Client, statement spanner.Statement, statementInfo *parser.StatementInfo, options *ExecOptions) (*result, *spanner.CommitResponse, error) {
return &result{}, &spanner.CommitResponse{}, nil
diff --git a/driver_with_mockserver_test.go b/driver_with_mockserver_test.go
index a8787d3b..8ebe91dc 100644
--- a/driver_with_mockserver_test.go
+++ b/driver_with_mockserver_test.go
@@ -5531,9 +5531,8 @@ func setupTestDBConnectionWithParams(t *testing.T, params string) (db *sql.DB, s
func setupTestDBConnectionWithParamsAndDialect(t *testing.T, params string, dialect databasepb.DatabaseDialect) (db *sql.DB, server *testutil.MockedSpannerInMemTestServer, teardown func()) {
server, _, serverTeardown := setupMockedTestServerWithDialect(t, dialect)
- db, err := sql.Open(
- "spanner",
- fmt.Sprintf("%s/projects/p/instances/i/databases/d?useplaintext=true;%s", server.Address, params))
+ dsn := fmt.Sprintf("%s/projects/p/instances/i/databases/d?useplaintext=true;%s", server.Address, params)
+ db, err := sql.Open("spanner", dsn)
if err != nil {
serverTeardown()
t.Fatal(err)
diff --git a/partitioned_query.go b/partitioned_query.go
index 77fe8240..018f7b7d 100644
--- a/partitioned_query.go
+++ b/partitioned_query.go
@@ -22,6 +22,7 @@ import (
"io"
"cloud.google.com/go/spanner"
+ "github.com/googleapis/go-sql-spanner/parser"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
@@ -231,7 +232,7 @@ func (pq *PartitionedQuery) execute(ctx context.Context, index int) (*rows, erro
return nil, spanner.ToSpannerError(status.Errorf(codes.InvalidArgument, "invalid partition index: %d", index))
}
spannerIter := pq.tx.Execute(ctx, pq.Partitions[index])
- iter := &readOnlyRowIterator{spannerIter}
+ iter := &readOnlyRowIterator{spannerIter, parser.StatementTypeQuery}
return &rows{it: iter, decodeOption: pq.execOptions.DecodeOption}, nil
}
diff --git a/spannerlib/.gitignore b/spannerlib/.gitignore
new file mode 100644
index 00000000..f6dbcd3d
--- /dev/null
+++ b/spannerlib/.gitignore
@@ -0,0 +1,3 @@
+spannerlib.h
+spannerlib.so
+grpc_server
diff --git a/spannerlib/README.md b/spannerlib/README.md
new file mode 100644
index 00000000..e84043c7
--- /dev/null
+++ b/spannerlib/README.md
@@ -0,0 +1,6 @@
+# Shared Library (Internal)
+
+__This module can receive breaking changes without prior notice.__
+
+This is an internal module that is used to expose the features in the database/sql driver
+to drivers in other programming languages.
diff --git a/spannerlib/api/README.md b/spannerlib/api/README.md
new file mode 100644
index 00000000..9642ee56
--- /dev/null
+++ b/spannerlib/api/README.md
@@ -0,0 +1,6 @@
+# Shared Library (Internal)
+
+__This module can receive breaking changes without prior notice.__
+
+This is the common internal API for the various external APIs for exposing the
+features in the database/sql driver to drivers in other programming languages.
diff --git a/spannerlib/api/connection.go b/spannerlib/api/connection.go
new file mode 100644
index 00000000..1c8d5093
--- /dev/null
+++ b/spannerlib/api/connection.go
@@ -0,0 +1,407 @@
+package api
+
+import (
+ "context"
+ "database/sql"
+ "database/sql/driver"
+ "fmt"
+ "strings"
+ "sync"
+ "sync/atomic"
+
+ "cloud.google.com/go/spanner"
+ "cloud.google.com/go/spanner/apiv1/spannerpb"
+ spannerdriver "github.com/googleapis/go-sql-spanner"
+ "github.com/googleapis/go-sql-spanner/parser"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+func CloseConnection(poolId, connId int64) error {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return err
+ }
+ return conn.close()
+}
+
+func WriteMutations(poolId, connId int64, mutations *spannerpb.BatchWriteRequest_MutationGroup) (*spannerpb.CommitResponse, error) {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return nil, err
+ }
+ return conn.writeMutations(mutations)
+}
+
+func BeginTransaction(poolId, connId int64, txOpts *spannerpb.TransactionOptions) error {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return err
+ }
+ return conn.BeginTransaction(txOpts)
+}
+
+func Execute(poolId, connId int64, executeSqlRequest *spannerpb.ExecuteSqlRequest) (int64, error) {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return 0, err
+ }
+ return conn.Execute(executeSqlRequest)
+}
+
+func ExecuteBatch(poolId, connId int64, statements *spannerpb.ExecuteBatchDmlRequest) (*spannerpb.ExecuteBatchDmlResponse, error) {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return nil, err
+ }
+ return conn.ExecuteBatch(statements.Statements)
+}
+
+type Connection struct {
+ results *sync.Map
+ resultsIdx atomic.Int64
+
+ backend *sql.Conn
+}
+
+// spannerConn is an internal interface that contains the internal functions that are used by this API.
+type spannerConn interface {
+ WriteMutations(ctx context.Context, ms []*spanner.Mutation) (*spanner.CommitResponse, error)
+ BeginReadOnlyTransaction(ctx context.Context, options *spannerdriver.ReadOnlyTransactionOptions) (driver.Tx, error)
+ BeginReadWriteTransaction(ctx context.Context, options *spannerdriver.ReadWriteTransactionOptions) (driver.Tx, error)
+ Commit(ctx context.Context) (*spanner.CommitResponse, error)
+ Rollback(ctx context.Context) error
+}
+
+type queryExecutor interface {
+ ExecContext(ctx context.Context, query string, args ...any) (sql.Result, error)
+ QueryContext(ctx context.Context, query string, args ...any) (*sql.Rows, error)
+}
+
+func (conn *Connection) close() error {
+ conn.results.Range(func(key, value interface{}) bool {
+ res := value.(*rows)
+ _ = res.Close()
+ return true
+ })
+ err := conn.backend.Close()
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (conn *Connection) writeMutations(mutation *spannerpb.BatchWriteRequest_MutationGroup) (*spannerpb.CommitResponse, error) {
+ ctx := context.Background()
+ mutations := make([]*spanner.Mutation, 0, len(mutation.Mutations))
+ for _, m := range mutation.Mutations {
+ spannerMutation, err := spanner.WrapMutation(m)
+ if err != nil {
+ return nil, err
+ }
+ mutations = append(mutations, spannerMutation)
+ }
+ var commitResponse *spanner.CommitResponse
+ if err := conn.backend.Raw(func(driverConn any) (err error) {
+ sc, _ := driverConn.(spannerConn)
+ commitResponse, err = sc.WriteMutations(ctx, mutations)
+ return err
+ }); err != nil {
+ return nil, err
+ }
+
+ // The commit response is nil if the connection is currently in a transaction.
+ if commitResponse == nil {
+ return nil, nil
+ }
+ response := spannerpb.CommitResponse{
+ CommitTimestamp: timestamppb.New(commitResponse.CommitTs),
+ }
+ return &response, nil
+}
+
+func (conn *Connection) BeginTransaction(txOpts *spannerpb.TransactionOptions) error {
+ var err error
+ ctx := context.Background()
+ if txOpts.GetReadOnly() != nil {
+ return conn.beginReadOnlyTransaction(ctx, convertToReadOnlyOpts(txOpts))
+ } else if txOpts.GetPartitionedDml() != nil {
+ err = spanner.ToSpannerError(status.Error(codes.InvalidArgument, "transaction type not supported"))
+ } else {
+ return conn.beginReadWriteTransaction(ctx, convertToReadWriteTransactionOptions(txOpts))
+ }
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (conn *Connection) beginReadOnlyTransaction(ctx context.Context, opts *spannerdriver.ReadOnlyTransactionOptions) error {
+ return conn.backend.Raw(func(driverConn any) (err error) {
+ sc, _ := driverConn.(spannerConn)
+ _, err = sc.BeginReadOnlyTransaction(ctx, opts)
+ return err
+ })
+}
+
+func (conn *Connection) beginReadWriteTransaction(ctx context.Context, opts *spannerdriver.ReadWriteTransactionOptions) error {
+ return conn.backend.Raw(func(driverConn any) (err error) {
+ sc, _ := driverConn.(spannerConn)
+ _, err = sc.BeginReadWriteTransaction(ctx, opts)
+ return err
+ })
+}
+
+func convertToReadOnlyOpts(txOpts *spannerpb.TransactionOptions) *spannerdriver.ReadOnlyTransactionOptions {
+ return &spannerdriver.ReadOnlyTransactionOptions{
+ TimestampBound: convertTimestampBound(txOpts),
+ }
+}
+
+func convertTimestampBound(txOpts *spannerpb.TransactionOptions) spanner.TimestampBound {
+ ro := txOpts.GetReadOnly()
+ if ro.GetStrong() {
+ return spanner.StrongRead()
+ } else if ro.GetReadTimestamp() != nil {
+ return spanner.ReadTimestamp(ro.GetReadTimestamp().AsTime())
+ } else if ro.GetMinReadTimestamp() != nil {
+ return spanner.ReadTimestamp(ro.GetMinReadTimestamp().AsTime())
+ } else if ro.GetExactStaleness() != nil {
+ return spanner.ExactStaleness(ro.GetExactStaleness().AsDuration())
+ } else if ro.GetMaxStaleness() != nil {
+ return spanner.MaxStaleness(ro.GetMaxStaleness().AsDuration())
+ }
+ return spanner.TimestampBound{}
+}
+
+func convertToReadWriteTransactionOptions(txOpts *spannerpb.TransactionOptions) *spannerdriver.ReadWriteTransactionOptions {
+ readLockMode := spannerpb.TransactionOptions_ReadWrite_READ_LOCK_MODE_UNSPECIFIED
+ if txOpts.GetReadWrite() != nil {
+ readLockMode = txOpts.GetReadWrite().GetReadLockMode()
+ }
+ return &spannerdriver.ReadWriteTransactionOptions{
+ TransactionOptions: spanner.TransactionOptions{
+ IsolationLevel: txOpts.GetIsolationLevel(),
+ ReadLockMode: readLockMode,
+ },
+ }
+}
+
+func convertIsolationLevel(level spannerpb.TransactionOptions_IsolationLevel) sql.IsolationLevel {
+ switch level {
+ case spannerpb.TransactionOptions_SERIALIZABLE:
+ return sql.LevelSerializable
+ case spannerpb.TransactionOptions_REPEATABLE_READ:
+ return sql.LevelRepeatableRead
+ }
+ return sql.LevelDefault
+}
+
+func (conn *Connection) Execute(statement *spannerpb.ExecuteSqlRequest) (int64, error) {
+ return execute(conn, conn.backend, statement)
+}
+
+func (conn *Connection) ExecuteBatch(statements []*spannerpb.ExecuteBatchDmlRequest_Statement) (*spannerpb.ExecuteBatchDmlResponse, error) {
+ return executeBatch(conn, conn.backend, statements)
+}
+
+func execute(conn *Connection, executor queryExecutor, statement *spannerpb.ExecuteSqlRequest) (int64, error) {
+ params := extractParams(statement)
+ it, err := executor.QueryContext(context.Background(), statement.Sql, params...)
+ if err != nil {
+ return 0, err
+ }
+ // The first result set should contain the metadata.
+ if !it.Next() {
+ return 0, fmt.Errorf("query returned no metadata")
+ }
+ metadata := &spannerpb.ResultSetMetadata{}
+ if err := it.Scan(&metadata); err != nil {
+ return 0, err
+ }
+ // Move to the next result set, which contains the normal data.
+ if !it.NextResultSet() {
+ return 0, fmt.Errorf("no results found after metadata")
+ }
+ id := conn.resultsIdx.Add(1)
+ res := &rows{
+ backend: it,
+ metadata: metadata,
+ }
+ if len(metadata.RowType.Fields) == 0 {
+ // No rows returned. Read the stats now.
+ res.readStats()
+ }
+ conn.results.Store(id, res)
+ return id, nil
+}
+
+func executeBatch(conn *Connection, executor queryExecutor, statements []*spannerpb.ExecuteBatchDmlRequest_Statement) (*spannerpb.ExecuteBatchDmlResponse, error) {
+ // Determine the type of batch that should be executed based on the type of statements.
+ batchType, err := determineBatchType(conn, statements)
+ if err != nil {
+ return nil, err
+ }
+ switch batchType {
+ case parser.BatchTypeDml:
+ return executeBatchDml(conn, executor, statements)
+ case parser.BatchTypeDdl:
+ return executeBatchDdl(conn, executor, statements)
+ default:
+ return nil, status.Errorf(codes.InvalidArgument, "unsupported batch type: %v", batchType)
+ }
+}
+
+func executeBatchDdl(conn *Connection, executor queryExecutor, statements []*spannerpb.ExecuteBatchDmlRequest_Statement) (*spannerpb.ExecuteBatchDmlResponse, error) {
+ if err := conn.backend.Raw(func(driverConn any) error {
+ spannerConn, _ := driverConn.(spannerdriver.SpannerConn)
+ return spannerConn.StartBatchDDL()
+ }); err != nil {
+ return nil, err
+ }
+ for _, statement := range statements {
+ _, err := executor.ExecContext(context.Background(), statement.Sql)
+ if err != nil {
+ return nil, err
+ }
+ }
+ // TODO: Add support for getting the actual Batch DDL response.
+ if err := conn.backend.Raw(func(driverConn any) (err error) {
+ spannerConn, _ := driverConn.(spannerdriver.SpannerConn)
+ return spannerConn.RunBatch(context.Background())
+ }); err != nil {
+ return nil, err
+ }
+
+ response := spannerpb.ExecuteBatchDmlResponse{}
+ response.ResultSets = make([]*spannerpb.ResultSet, len(statements))
+ for i := range statements {
+ response.ResultSets[i] = &spannerpb.ResultSet{Stats: &spannerpb.ResultSetStats{RowCount: &spannerpb.ResultSetStats_RowCountExact{RowCountExact: 0}}}
+ }
+ return &response, nil
+}
+
+func executeBatchDml(conn *Connection, executor queryExecutor, statements []*spannerpb.ExecuteBatchDmlRequest_Statement) (*spannerpb.ExecuteBatchDmlResponse, error) {
+ if err := conn.backend.Raw(func(driverConn any) error {
+ spannerConn, _ := driverConn.(spannerdriver.SpannerConn)
+ return spannerConn.StartBatchDML()
+ }); err != nil {
+ return nil, err
+ }
+ for _, statement := range statements {
+ request := &spannerpb.ExecuteSqlRequest{
+ Sql: statement.Sql,
+ Params: statement.Params,
+ ParamTypes: statement.ParamTypes,
+ }
+ params := extractParams(request)
+ _, err := executor.ExecContext(context.Background(), statement.Sql, params...)
+ if err != nil {
+ return nil, err
+ }
+ }
+ var spannerResult spannerdriver.SpannerResult
+ if err := conn.backend.Raw(func(driverConn any) (err error) {
+ spannerConn, _ := driverConn.(spannerdriver.SpannerConn)
+ spannerResult, err = spannerConn.RunDmlBatch(context.Background())
+ return err
+ }); err != nil {
+ return nil, err
+ }
+ affected, err := spannerResult.BatchRowsAffected()
+ if err != nil {
+ return nil, err
+ }
+ response := spannerpb.ExecuteBatchDmlResponse{}
+ response.ResultSets = make([]*spannerpb.ResultSet, len(affected))
+ for i, aff := range affected {
+ response.ResultSets[i] = &spannerpb.ResultSet{Stats: &spannerpb.ResultSetStats{RowCount: &spannerpb.ResultSetStats_RowCountExact{RowCountExact: aff}}}
+ }
+ return &response, nil
+}
+
+func extractParams(statement *spannerpb.ExecuteSqlRequest) []any {
+ paramsLen := 1
+ if statement.Params != nil {
+ paramsLen = 1 + len(statement.Params.Fields)
+ }
+ params := make([]any, paramsLen)
+ params = append(params, spannerdriver.ExecOptions{
+ DecodeOption: spannerdriver.DecodeOptionProto,
+ TimestampBound: extractTimestampBound(statement),
+ ReturnResultSetMetadata: true,
+ ReturnResultSetStats: true,
+ DirectExecuteQuery: true,
+ })
+ if statement.Params != nil {
+ if statement.ParamTypes == nil {
+ statement.ParamTypes = make(map[string]*spannerpb.Type)
+ }
+ for param, value := range statement.Params.Fields {
+ genericValue := spanner.GenericColumnValue{
+ Value: value,
+ Type: statement.ParamTypes[param],
+ }
+ if strings.HasPrefix(param, "_") {
+ // Prefix the parameter name with a 'p' to work around the fact that database/sql does not allow
+ // named arguments to start with anything else than a letter.
+ params = append(params, sql.Named("p"+param, spannerdriver.SpannerNamedArg{NameInQuery: param, Value: genericValue}))
+ } else {
+ params = append(params, sql.Named(param, genericValue))
+ }
+ }
+ }
+ return params
+}
+
+func determineBatchType(conn *Connection, statements []*spannerpb.ExecuteBatchDmlRequest_Statement) (parser.BatchType, error) {
+ if len(statements) == 0 {
+ return parser.BatchTypeDdl, status.Errorf(codes.InvalidArgument, "cannot determine type of an empty batch")
+ }
+ var batchType parser.BatchType
+ if err := conn.backend.Raw(func(driverConn any) error {
+ spannerConn, _ := driverConn.(spannerdriver.SpannerConn)
+ firstStatementType := spannerConn.DetectStatementType(statements[0].Sql)
+ if firstStatementType == parser.StatementTypeDml {
+ batchType = parser.BatchTypeDml
+ } else if firstStatementType == parser.StatementTypeDdl {
+ batchType = parser.BatchTypeDdl
+ } else {
+ return status.Errorf(codes.InvalidArgument, "unsupported statement type for batching: %v", firstStatementType)
+ }
+ for i, statement := range statements {
+ if i > 0 {
+ tp := spannerConn.DetectStatementType(statement.Sql)
+ if tp != firstStatementType {
+ return status.Errorf(codes.InvalidArgument, "Batches may not contain different types of statements. The first statement is of type %v. The statement on position %d is of type %v.", firstStatementType, i, tp)
+ }
+ }
+ }
+ return nil
+ }); err != nil {
+ return parser.BatchTypeDdl, err
+ }
+
+ return batchType, nil
+}
+
+func extractTimestampBound(statement *spannerpb.ExecuteSqlRequest) *spanner.TimestampBound {
+ if statement.Transaction != nil && statement.Transaction.GetSingleUse() != nil && statement.Transaction.GetSingleUse().GetReadOnly() != nil {
+ ro := statement.Transaction.GetSingleUse().GetReadOnly()
+ var t spanner.TimestampBound
+ if ro.GetStrong() {
+ t = spanner.StrongRead()
+ } else if ro.GetMaxStaleness() != nil {
+ t = spanner.MaxStaleness(ro.GetMaxStaleness().AsDuration())
+ } else if ro.GetExactStaleness() != nil {
+ t = spanner.ExactStaleness(ro.GetExactStaleness().AsDuration())
+ } else if ro.GetMinReadTimestamp() != nil {
+ t = spanner.MinReadTimestamp(ro.GetMinReadTimestamp().AsTime())
+ } else if ro.GetReadTimestamp() != nil {
+ t = spanner.ReadTimestamp(ro.GetReadTimestamp().AsTime())
+ }
+ return &t
+ }
+ return nil
+}
diff --git a/spannerlib/api/pool.go b/spannerlib/api/pool.go
new file mode 100644
index 00000000..c41f075b
--- /dev/null
+++ b/spannerlib/api/pool.go
@@ -0,0 +1,105 @@
+package api
+
+import (
+ "context"
+ "database/sql"
+ "fmt"
+ "sync"
+ "sync/atomic"
+
+ spannerdriver "github.com/googleapis/go-sql-spanner"
+)
+
+var pools = sync.Map{}
+var poolsIdx = atomic.Int64{}
+
+// Pool is the equivalent of a sql.DB. It contains a pool of connections to the same database.
+type Pool struct {
+ db *sql.DB
+ connections *sync.Map
+ connectionsIdx atomic.Int64
+}
+
+func CreatePool(dsn string) (int64, error) {
+ config, err := spannerdriver.ExtractConnectorConfig(dsn)
+ if err != nil {
+ return 0, err
+ }
+ connector, err := spannerdriver.CreateConnector(config)
+ if err != nil {
+ return 0, err
+ }
+ db := sql.OpenDB(connector)
+
+ id := poolsIdx.Add(1)
+ pool := &Pool{
+ db: db,
+ connections: &sync.Map{},
+ }
+ pools.Store(id, pool)
+ return id, nil
+}
+
+func ClosePool(id int64) error {
+ p, ok := pools.LoadAndDelete(id)
+ if !ok {
+ return fmt.Errorf("pool %v not found", id)
+ }
+ pool := p.(*Pool)
+ pool.connections.Range(func(key, value interface{}) bool {
+ conn := value.(*Connection)
+ _ = conn.close()
+ return true
+ })
+ if err := pool.db.Close(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func CreateConnection(poolId int64) (int64, error) {
+ p, ok := pools.Load(poolId)
+ if !ok {
+ return 0, fmt.Errorf("pool %v not found", poolId)
+ }
+ pool := p.(*Pool)
+ sqlConn, err := pool.db.Conn(context.Background())
+ if err != nil {
+ return 0, err
+ }
+ id := poolsIdx.Add(1)
+ conn := &Connection{
+ backend: sqlConn,
+ results: &sync.Map{},
+ }
+ pool.connections.Store(id, conn)
+
+ return id, nil
+}
+
+func findConnection(poolId, connId int64) (*Connection, error) {
+ p, ok := pools.Load(poolId)
+ if !ok {
+ return nil, fmt.Errorf("pool %v not found", poolId)
+ }
+ pool := p.(*Pool)
+ c, ok := pool.connections.Load(connId)
+ if !ok {
+ return nil, fmt.Errorf("connection %v not found", connId)
+ }
+ conn := c.(*Connection)
+ return conn, nil
+}
+
+func findRows(poolId, connId, rowsId int64) (*rows, error) {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return nil, err
+ }
+ r, ok := conn.results.Load(rowsId)
+ if !ok {
+ return nil, fmt.Errorf("rows %v not found", rowsId)
+ }
+ res := r.(*rows)
+ return res, nil
+}
diff --git a/spannerlib/api/rows.go b/spannerlib/api/rows.go
new file mode 100644
index 00000000..18e3efc5
--- /dev/null
+++ b/spannerlib/api/rows.go
@@ -0,0 +1,181 @@
+package api
+
+import (
+ "database/sql"
+ "encoding/base64"
+ "errors"
+
+ "cloud.google.com/go/spanner"
+ "cloud.google.com/go/spanner/apiv1/spannerpb"
+ "google.golang.org/grpc/codes"
+ "google.golang.org/grpc/status"
+ "google.golang.org/protobuf/proto"
+ "google.golang.org/protobuf/types/known/structpb"
+)
+
+type EncodeRowOption int32
+
+const (
+ EncodeRowOptionProto EncodeRowOption = iota
+)
+
+func Metadata(poolId, connId, rowsId int64) (*spannerpb.ResultSetMetadata, error) {
+ res, err := findRows(poolId, connId, rowsId)
+ if err != nil {
+ return nil, err
+ }
+ return res.Metadata()
+}
+
+func ResultSetStats(poolId, connId, rowsId int64) (*spannerpb.ResultSetStats, error) {
+ res, err := findRows(poolId, connId, rowsId)
+ if err != nil {
+ return nil, err
+ }
+ return res.ResultSetStats()
+}
+
+func NextEncoded(poolId, connId, rowsId int64) ([]byte, error) {
+ _, bytes, err := next(poolId, connId, rowsId, true)
+ if err != nil {
+ return nil, err
+ }
+ return bytes, nil
+}
+
+func Next(poolId, connId, rowsId int64) (*structpb.ListValue, error) {
+ values, _, err := next(poolId, connId, rowsId, false)
+ if err != nil {
+ return nil, err
+ }
+ return values, nil
+}
+
+func next(poolId, connId, rowsId int64, marshalResult bool) (*structpb.ListValue, []byte, error) {
+ rows, err := findRows(poolId, connId, rowsId)
+ if err != nil {
+ return nil, nil, err
+ }
+ values, err := rows.Next()
+ if err != nil {
+ return nil, nil, err
+ }
+ if !marshalResult || values == nil {
+ return values, nil, nil
+ }
+
+ rows.marshalBuffer, err = proto.MarshalOptions{}.MarshalAppend(rows.marshalBuffer[:0], rows.values)
+ if err != nil {
+ return nil, nil, err
+ }
+ return values, rows.marshalBuffer, nil
+}
+
+func CloseRows(poolId, connId, rowsId int64) error {
+ res, err := findRows(poolId, connId, rowsId)
+ if err != nil {
+ return err
+ }
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return err
+ }
+ conn.results.Delete(rowsId)
+ return res.Close()
+}
+
+type rows struct {
+ backend *sql.Rows
+ metadata *spannerpb.ResultSetMetadata
+ stats *spannerpb.ResultSetStats
+ done bool
+
+ buffer []any
+ values *structpb.ListValue
+ marshalBuffer []byte
+}
+
+func (rows *rows) Close() error {
+ err := rows.backend.Close()
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+func (rows *rows) metadataBytes() ([]byte, error) {
+ colTypes, err := rows.backend.ColumnTypes()
+ if err != nil {
+ return nil, err
+ }
+ return base64.StdEncoding.DecodeString(colTypes[0].DatabaseTypeName())
+}
+
+func (rows *rows) Metadata() (*spannerpb.ResultSetMetadata, error) {
+ return rows.metadata, nil
+}
+
+func (rows *rows) ResultSetStats() (*spannerpb.ResultSetStats, error) {
+ if rows.stats == nil {
+ rows.readStats()
+ }
+ return rows.stats, nil
+}
+
+type genericValue struct {
+ v *structpb.Value
+}
+
+func (gv *genericValue) Scan(src any) error {
+ if v, ok := src.(spanner.GenericColumnValue); ok {
+ gv.v = v.Value
+ return nil
+ }
+ return errors.New("cannot convert value to generic column value")
+}
+
+func (rows *rows) Next() (*structpb.ListValue, error) {
+ // No columns means no rows, so just return nil to indicate that there are no (more) rows.
+ if len(rows.metadata.RowType.Fields) == 0 || rows.done {
+ return nil, nil
+ }
+ if rows.stats != nil {
+ return nil, spanner.ToSpannerError(status.Error(codes.FailedPrecondition, "cannot read more data after returning stats"))
+ }
+ ok := rows.backend.Next()
+ if !ok {
+ rows.done = true
+ // No more rows. Read stats and return nil.
+ rows.readStats()
+ // nil indicates no more rows.
+ return nil, nil
+ }
+
+ if rows.buffer == nil {
+ rows.buffer = make([]any, len(rows.metadata.RowType.Fields))
+ for i := range rows.buffer {
+ rows.buffer[i] = &genericValue{}
+ }
+ rows.values = &structpb.ListValue{
+ Values: make([]*structpb.Value, len(rows.buffer)),
+ }
+ rows.marshalBuffer = make([]byte, 0)
+ }
+ if err := rows.backend.Scan(rows.buffer...); err != nil {
+ return nil, err
+ }
+ for i := range rows.buffer {
+ rows.values.Values[i] = rows.buffer[i].(*genericValue).v
+ }
+ return rows.values, nil
+}
+
+func (rows *rows) readStats() {
+ rows.stats = &spannerpb.ResultSetStats{}
+ if !rows.backend.NextResultSet() {
+ return
+ }
+ if rows.backend.Next() {
+ _ = rows.backend.Scan(&rows.stats)
+ }
+}
diff --git a/spannerlib/api/transaction.go b/spannerlib/api/transaction.go
new file mode 100644
index 00000000..5d668d29
--- /dev/null
+++ b/spannerlib/api/transaction.go
@@ -0,0 +1,95 @@
+package api
+
+import (
+ "context"
+ "database/sql"
+
+ "cloud.google.com/go/spanner"
+ "cloud.google.com/go/spanner/apiv1/spannerpb"
+ spannerdriver "github.com/googleapis/go-sql-spanner"
+ "google.golang.org/protobuf/types/known/timestamppb"
+)
+
+func Commit(poolId, connId int64) (*spannerpb.CommitResponse, error) {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return nil, err
+ }
+ return commit(conn)
+}
+
+func Rollback(poolId, connId int64) error {
+ conn, err := findConnection(poolId, connId)
+ if err != nil {
+ return err
+ }
+ return rollback(conn)
+}
+
+type transaction struct {
+ backend *sql.Tx
+ conn *Connection
+ txOpts *spannerpb.TransactionOptions
+ closed bool
+}
+
+func (tx *transaction) Close() error {
+ if tx.closed {
+ return nil
+ }
+ tx.closed = true
+ if err := tx.backend.Rollback(); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (tx *transaction) bufferWrite(mutation *spannerpb.BatchWriteRequest_MutationGroup) error {
+ mutations := make([]*spanner.Mutation, 0, len(mutation.Mutations))
+ for _, m := range mutation.Mutations {
+ spannerMutation, err := spanner.WrapMutation(m)
+ if err != nil {
+ return err
+ }
+ mutations = append(mutations, spannerMutation)
+ }
+ if err := tx.conn.backend.Raw(func(driverConn any) error {
+ spannerConn, _ := driverConn.(spannerdriver.SpannerConn)
+ return spannerConn.BufferWrite(mutations)
+ }); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (tx *transaction) Execute(statement *spannerpb.ExecuteSqlRequest) (int64, error) {
+ return execute(tx.conn, tx.backend, statement)
+}
+
+func commit(conn *Connection) (*spannerpb.CommitResponse, error) {
+ var response *spanner.CommitResponse
+ if err := conn.backend.Raw(func(driverConn any) (err error) {
+ spannerConn, _ := driverConn.(spannerConn)
+ response, err = spannerConn.Commit(context.Background())
+ if err != nil {
+ return err
+ }
+ return nil
+ }); err != nil {
+ return nil, err
+ }
+
+ // The commit response is nil for read-only transactions.
+ if response == nil {
+ return nil, nil
+ }
+ // TODO: Include commit stats
+ return &spannerpb.CommitResponse{CommitTimestamp: timestamppb.New(response.CommitTs)}, nil
+}
+
+func rollback(conn *Connection) error {
+ return conn.backend.Raw(func(driverConn any) (err error) {
+ spannerConn, _ := driverConn.(spannerConn)
+ return spannerConn.Rollback(context.Background())
+ })
+}
diff --git a/spannerlib/build.sh b/spannerlib/build.sh
new file mode 100755
index 00000000..f9f96578
--- /dev/null
+++ b/spannerlib/build.sh
@@ -0,0 +1,20 @@
+go build -o shared/spannerlib.so -buildmode=c-shared shared/shared_lib.go
+mkdir -p dotnet-spannerlib/Google.Cloud.SpannerLib.Native/libraries/any
+cp shared/spannerlib.so dotnet-spannerlib/Google.Cloud.SpannerLib.Native/libraries/any/spannerlib.so
+
+go build grpc-server/grpc_server.go
+mkdir -p dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/binaries/any
+cp grpc-server/grpc_server dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/binaries/any/grpc_server
+
+cd dotnet-spannerlib/Google.Cloud.SpannerLib.Native || exit 1
+dotnet pack
+dotnet nuget add source "$PWD"/bin/Release --name local || true
+
+cd .. || exit 1
+dotnet restore
+dotnet build --no-restore
+
+cd Google.Cloud.SpannerLib.Tests || exit 1
+dotnet test --no-build --verbosity normal
+
+cd ../..
diff --git a/spannerlib/build_protos.sh b/spannerlib/build_protos.sh
new file mode 100644
index 00000000..434fdf2e
--- /dev/null
+++ b/spannerlib/build_protos.sh
@@ -0,0 +1,6 @@
+protoc \
+ --go_out=/Users/loite/GolandProjects/go-sql-spanner/spannerlib/ \
+ --go_opt=paths=source_relative \
+ --go-grpc_out=/Users/loite/GolandProjects/go-sql-spanner/spannerlib/ \
+ --go-grpc_opt=paths=source_relative \
+ google/spannerlib/v1/spannerlib.proto
diff --git a/spannerlib/dotnet-spannerlib/.gitignore b/spannerlib/dotnet-spannerlib/.gitignore
new file mode 100644
index 00000000..fd9decc3
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/.gitignore
@@ -0,0 +1,34 @@
+bin/
+obj/
+packages/
+*.suo
+.nuget/
+TestResults/
+*TestResults.xml
+*sponge_log.xml
+*.csproj.user
+.idea/
+*.iml
+PublishProfiles/
+*.sln.DotSettings.user
+.vs/
+*~
+*.xproj.user
+project.lock.json
+.vscode/
+secrets.ps1
+google_application_credentials.json
+**/Properties/launchSettings.json
+**/wwwroot/lib/
+**/kmsCipher.key
+/tmpB19A.tmp
+/dlp/tmp6849.tmp
+env/
+applications/liftAndShiftPetshop/PrecompiledWeb/
+applications/liftAndShiftPetshop/Web/
+*.leu
+.cr/
+BenchmarkDotNet.Artifacts
+.DS_Store
+
+!spannerlib.so
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/.gitignore b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/.gitignore
new file mode 100644
index 00000000..e935fd38
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/.gitignore
@@ -0,0 +1 @@
+binaries
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/Google.Cloud.SpannerLib.Grpc.csproj b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/Google.Cloud.SpannerLib.Grpc.csproj
new file mode 100644
index 00000000..562cb07d
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/Google.Cloud.SpannerLib.Grpc.csproj
@@ -0,0 +1,32 @@
+
+
+
+ net8.0
+ enable
+ default
+ Experimental.SpannerLib.Grpc
+ Experimental gRPC library for Spanner
+ 1.0.3
+
+
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/SpannerLib.cs b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/SpannerLib.cs
new file mode 100644
index 00000000..72bb7932
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/SpannerLib.cs
@@ -0,0 +1,266 @@
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Net.Http;
+using System.Net.Sockets;
+using System.Runtime.InteropServices;
+using System.Threading;
+using Google.Cloud.Spanner.V1;
+using Google.Cloud.SpannerLib.V1;
+using Google.Protobuf.WellKnownTypes;
+using Grpc.Core;
+using Grpc.Net.Client;
+using BeginTransactionRequest = Google.Cloud.SpannerLib.V1.BeginTransactionRequest;
+using ExecuteBatchDmlRequest = Google.Cloud.Spanner.V1.ExecuteBatchDmlRequest;
+using Transaction = Google.Cloud.SpannerLib.V1.Transaction;
+
+namespace Google.Cloud.SpannerLib.Grpc
+{
+ public class SpannerLib : IDisposable
+ {
+ private readonly Process _process;
+ private readonly string _fileName;
+ private readonly V1.SpannerLib.SpannerLibClient _client;
+ private readonly GrpcChannel _channel;
+
+ private bool _disposed;
+
+ public SpannerLib()
+ {
+ (_fileName, _process) = StartGrpcServer();
+ (_client, _channel) = CreateClient(_fileName);
+ }
+
+ ~SpannerLib()
+ {
+ Dispose(false);
+ }
+
+ private static string GetBinaryFileName()
+ {
+ if (File.Exists("runtimes/any/native/grpc_server"))
+ {
+ return "runtimes/any/native/grpc_server";
+ }
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
+ {
+ switch (RuntimeInformation.OSArchitecture)
+ {
+ case Architecture.X64:
+ return "runtimes/linux-x64/native/grpc_server";
+ }
+ }
+ else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
+ {
+ switch (RuntimeInformation.ProcessArchitecture)
+ {
+ case Architecture.Arm64:
+ return "runtimes/osx-arm64/native/grpc_server";
+ }
+ }
+ throw new PlatformNotSupportedException();
+ }
+
+ private static Tuple StartGrpcServer()
+ {
+ // Generate a random temp file name that will be used for the Unix domain socket communication.
+ var unixDomainSocketFileName = Path.GetTempPath() + Guid.NewGuid();
+ var binaryFileName = GetBinaryFileName();
+ var info = new ProcessStartInfo
+ {
+ Arguments = unixDomainSocketFileName,
+ UseShellExecute = false,
+ FileName = binaryFileName,
+ RedirectStandardOutput = true,
+ };
+ // Start the process as a child process. The process will automatically stop when the
+ // parent process stops.
+ var process = Process.Start(info);
+ if (process == null)
+ {
+ throw new InvalidOperationException("Failed to start spanner");
+ }
+ while (!File.Exists(unixDomainSocketFileName))
+ {
+ Thread.Sleep(1);
+ }
+ // Return the name of the Unix domain socket.
+ return Tuple.Create(unixDomainSocketFileName, process);
+ }
+
+ private static Tuple CreateClient(string file)
+ {
+ var channel = ForUnixSocket(file);
+ return Tuple.Create(new V1.SpannerLib.SpannerLibClient(channel), channel);
+ }
+
+ private static GrpcChannel ForUnixSocket(string fileName)
+ {
+ var endpoint = new UnixDomainSocketEndPoint(fileName);
+ return GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions {
+ HttpHandler = new SocketsHttpHandler {
+ EnableMultipleHttp2Connections = true,
+ ConnectCallback = async (_, cancellationToken) => {
+ var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified);
+ try {
+ await socket.ConnectAsync(endpoint, cancellationToken).ConfigureAwait(false);
+ return new NetworkStream(socket, true);
+ } catch {
+ socket.Dispose();
+ throw;
+ }
+ }
+ }
+ });
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ public void Close()
+ {
+ Dispose(true);
+ GC.SuppressFinalize(this);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (_disposed)
+ {
+ return;
+ }
+ try
+ {
+ _channel.Dispose();
+ _process.Dispose();
+ }
+ finally
+ {
+ _disposed = true;
+ }
+ }
+
+ private void CheckDisposed()
+ {
+ if (_disposed)
+ {
+ throw new ObjectDisposedException(GetType().Name);
+ }
+ }
+
+ public Pool CreatePool(string dsn)
+ {
+ CheckDisposed();
+ return _client.CreatePool(new CreatePoolRequest { Dsn = dsn });
+ }
+
+ public void ClosePool(Pool pool)
+ {
+ CheckDisposed();
+ _client.ClosePool(pool);
+ }
+
+ public Connection CreateConnection(Pool pool)
+ {
+ CheckDisposed();
+ return _client.CreateConnection(new CreateConnectionRequest { Pool = pool });
+ }
+
+ public void CloseConnection(Connection connection)
+ {
+ CheckDisposed();
+ _client.CloseConnection(connection);
+ }
+
+ public CommitResponse Apply(Connection connection, BatchWriteRequest.Types.MutationGroup mutations)
+ {
+ CheckDisposed();
+ return _client.Apply(new ApplyRequest { Connection = connection, Mutations = mutations });
+ }
+
+ public void BufferWrite(Transaction transaction, BatchWriteRequest.Types.MutationGroup mutations)
+ {
+ CheckDisposed();
+ _client.BufferWrite(new BufferWriteRequest { Transaction = transaction, Mutations = mutations });
+ }
+
+ public Rows Execute(Connection connection, ExecuteSqlRequest statement)
+ {
+ CheckDisposed();
+ return _client.Execute(new ExecuteRequest { Connection = connection, ExecuteSqlRequest = statement });
+ }
+
+ public AsyncServerStreamingCall ExecuteStreaming(Connection connection, ExecuteSqlRequest statement)
+ {
+ CheckDisposed();
+ return _client.ExecuteStreaming(new ExecuteRequest { Connection = connection, ExecuteSqlRequest = statement });
+ }
+
+ public Rows ExecuteTransaction(Transaction transaction, ExecuteSqlRequest statement)
+ {
+ CheckDisposed();
+ return _client.ExecuteTransaction(new ExecuteTransactionRequest { Transaction = transaction, ExecuteSqlRequest = statement });
+ }
+
+ public ExecuteBatchDmlResponse ExecuteBatchDml(Connection connection, ExecuteBatchDmlRequest statements)
+ {
+ CheckDisposed();
+ return _client.ExecuteBatchDml(new V1.ExecuteBatchDmlRequest { Connection = connection, ExecuteBatchDmlRequest_ = statements });
+ }
+
+ public ResultSetMetadata Metadata(Rows rows)
+ {
+ CheckDisposed();
+ return _client.Metadata(rows);
+ }
+
+ public ListValue Next(Rows rows)
+ {
+ CheckDisposed();
+ return _client.Next(rows);
+ }
+
+ public ResultSetStats ResultSetStats(Rows rows)
+ {
+ CheckDisposed();
+ return _client.ResultSetStats(rows);
+ }
+
+ public void CloseRows(Rows rows)
+ {
+ CheckDisposed();
+ _client.CloseRows(rows);
+ }
+
+ public Transaction BeginTransaction(Connection connection, TransactionOptions transactionOptions)
+ {
+ CheckDisposed();
+ return _client.BeginTransaction(new BeginTransactionRequest
+ { Connection = connection, TransactionOptions = transactionOptions });
+ }
+
+ public CommitResponse Commit(Transaction transaction)
+ {
+ CheckDisposed();
+ return _client.Commit(transaction);
+ }
+
+ public void Rollback(Transaction transaction)
+ {
+ CheckDisposed();
+ _client.Rollback(transaction);
+ }
+
+ public AsyncDuplexStreamingCall CreateStream()
+ {
+ CheckDisposed();
+ return _client.ConnectionStream();
+ }
+ }
+}
\ No newline at end of file
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/annotations.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/annotations.proto
new file mode 100644
index 00000000..417edd8f
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/annotations.proto
@@ -0,0 +1,31 @@
+// 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
+//
+// 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.api;
+
+import "google/api/http.proto";
+import "google/protobuf/descriptor.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "AnnotationsProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+extend google.protobuf.MethodOptions {
+ // See `HttpRule`.
+ HttpRule http = 72295728;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/client.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/client.proto
new file mode 100644
index 00000000..3d692560
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/client.proto
@@ -0,0 +1,486 @@
+// 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
+//
+// 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.api;
+
+import "google/api/launch_stage.proto";
+import "google/protobuf/descriptor.proto";
+import "google/protobuf/duration.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "ClientProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+extend google.protobuf.MethodOptions {
+ // A definition of a client library method signature.
+ //
+ // In client libraries, each proto RPC corresponds to one or more methods
+ // which the end user is able to call, and calls the underlying RPC.
+ // Normally, this method receives a single argument (a struct or instance
+ // corresponding to the RPC request object). Defining this field will
+ // add one or more overloads providing flattened or simpler method signatures
+ // in some languages.
+ //
+ // The fields on the method signature are provided as a comma-separated
+ // string.
+ //
+ // For example, the proto RPC and annotation:
+ //
+ // rpc CreateSubscription(CreateSubscriptionRequest)
+ // returns (Subscription) {
+ // option (google.api.method_signature) = "name,topic";
+ // }
+ //
+ // Would add the following Java overload (in addition to the method accepting
+ // the request object):
+ //
+ // public final Subscription createSubscription(String name, String topic)
+ //
+ // The following backwards-compatibility guidelines apply:
+ //
+ // * Adding this annotation to an unannotated method is backwards
+ // compatible.
+ // * Adding this annotation to a method which already has existing
+ // method signature annotations is backwards compatible if and only if
+ // the new method signature annotation is last in the sequence.
+ // * Modifying or removing an existing method signature annotation is
+ // a breaking change.
+ // * Re-ordering existing method signature annotations is a breaking
+ // change.
+ repeated string method_signature = 1051;
+}
+
+extend google.protobuf.ServiceOptions {
+ // The hostname for this service.
+ // This should be specified with no prefix or protocol.
+ //
+ // Example:
+ //
+ // service Foo {
+ // option (google.api.default_host) = "foo.googleapi.com";
+ // ...
+ // }
+ string default_host = 1049;
+
+ // OAuth scopes needed for the client.
+ //
+ // Example:
+ //
+ // service Foo {
+ // option (google.api.oauth_scopes) = \
+ // "https://www.googleapis.com/auth/cloud-platform";
+ // ...
+ // }
+ //
+ // If there is more than one scope, use a comma-separated string:
+ //
+ // Example:
+ //
+ // service Foo {
+ // option (google.api.oauth_scopes) = \
+ // "https://www.googleapis.com/auth/cloud-platform,"
+ // "https://www.googleapis.com/auth/monitoring";
+ // ...
+ // }
+ string oauth_scopes = 1050;
+
+ // The API version of this service, which should be sent by version-aware
+ // clients to the service. This allows services to abide by the schema and
+ // behavior of the service at the time this API version was deployed.
+ // The format of the API version must be treated as opaque by clients.
+ // Services may use a format with an apparent structure, but clients must
+ // not rely on this to determine components within an API version, or attempt
+ // to construct other valid API versions. Note that this is for upcoming
+ // functionality and may not be implemented for all services.
+ //
+ // Example:
+ //
+ // service Foo {
+ // option (google.api.api_version) = "v1_20230821_preview";
+ // }
+ string api_version = 525000001;
+}
+
+// Required information for every language.
+message CommonLanguageSettings {
+ // Link to automatically generated reference documentation. Example:
+ // https://cloud.google.com/nodejs/docs/reference/asset/latest
+ string reference_docs_uri = 1 [deprecated = true];
+
+ // The destination where API teams want this client library to be published.
+ repeated ClientLibraryDestination destinations = 2;
+
+ // Configuration for which RPCs should be generated in the GAPIC client.
+ SelectiveGapicGeneration selective_gapic_generation = 3;
+}
+
+// Details about how and where to publish client libraries.
+message ClientLibrarySettings {
+ // Version of the API to apply these settings to. This is the full protobuf
+ // package for the API, ending in the version element.
+ // Examples: "google.cloud.speech.v1" and "google.spanner.admin.database.v1".
+ string version = 1;
+
+ // Launch stage of this version of the API.
+ LaunchStage launch_stage = 2;
+
+ // When using transport=rest, the client request will encode enums as
+ // numbers rather than strings.
+ bool rest_numeric_enums = 3;
+
+ // Settings for legacy Java features, supported in the Service YAML.
+ JavaSettings java_settings = 21;
+
+ // Settings for C++ client libraries.
+ CppSettings cpp_settings = 22;
+
+ // Settings for PHP client libraries.
+ PhpSettings php_settings = 23;
+
+ // Settings for Python client libraries.
+ PythonSettings python_settings = 24;
+
+ // Settings for Node client libraries.
+ NodeSettings node_settings = 25;
+
+ // Settings for .NET client libraries.
+ DotnetSettings dotnet_settings = 26;
+
+ // Settings for Ruby client libraries.
+ RubySettings ruby_settings = 27;
+
+ // Settings for Go client libraries.
+ GoSettings go_settings = 28;
+}
+
+// This message configures the settings for publishing [Google Cloud Client
+// libraries](https://cloud.google.com/apis/docs/cloud-client-libraries)
+// generated from the service config.
+message Publishing {
+ // A list of API method settings, e.g. the behavior for methods that use the
+ // long-running operation pattern.
+ repeated MethodSettings method_settings = 2;
+
+ // Link to a *public* URI where users can report issues. Example:
+ // https://issuetracker.google.com/issues/new?component=190865&template=1161103
+ string new_issue_uri = 101;
+
+ // Link to product home page. Example:
+ // https://cloud.google.com/asset-inventory/docs/overview
+ string documentation_uri = 102;
+
+ // Used as a tracking tag when collecting data about the APIs developer
+ // relations artifacts like docs, packages delivered to package managers,
+ // etc. Example: "speech".
+ string api_short_name = 103;
+
+ // GitHub label to apply to issues and pull requests opened for this API.
+ string github_label = 104;
+
+ // GitHub teams to be added to CODEOWNERS in the directory in GitHub
+ // containing source code for the client libraries for this API.
+ repeated string codeowner_github_teams = 105;
+
+ // A prefix used in sample code when demarking regions to be included in
+ // documentation.
+ string doc_tag_prefix = 106;
+
+ // For whom the client library is being published.
+ ClientLibraryOrganization organization = 107;
+
+ // Client library settings. If the same version string appears multiple
+ // times in this list, then the last one wins. Settings from earlier
+ // settings with the same version string are discarded.
+ repeated ClientLibrarySettings library_settings = 109;
+
+ // Optional link to proto reference documentation. Example:
+ // https://cloud.google.com/pubsub/lite/docs/reference/rpc
+ string proto_reference_documentation_uri = 110;
+
+ // Optional link to REST reference documentation. Example:
+ // https://cloud.google.com/pubsub/lite/docs/reference/rest
+ string rest_reference_documentation_uri = 111;
+}
+
+// Settings for Java client libraries.
+message JavaSettings {
+ // The package name to use in Java. Clobbers the java_package option
+ // set in the protobuf. This should be used **only** by APIs
+ // who have already set the language_settings.java.package_name" field
+ // in gapic.yaml. API teams should use the protobuf java_package option
+ // where possible.
+ //
+ // Example of a YAML configuration::
+ //
+ // publishing:
+ // java_settings:
+ // library_package: com.google.cloud.pubsub.v1
+ string library_package = 1;
+
+ // Configure the Java class name to use instead of the service's for its
+ // corresponding generated GAPIC client. Keys are fully-qualified
+ // service names as they appear in the protobuf (including the full
+ // the language_settings.java.interface_names" field in gapic.yaml. API
+ // teams should otherwise use the service name as it appears in the
+ // protobuf.
+ //
+ // Example of a YAML configuration::
+ //
+ // publishing:
+ // java_settings:
+ // service_class_names:
+ // - google.pubsub.v1.Publisher: TopicAdmin
+ // - google.pubsub.v1.Subscriber: SubscriptionAdmin
+ map service_class_names = 2;
+
+ // Some settings.
+ CommonLanguageSettings common = 3;
+}
+
+// Settings for C++ client libraries.
+message CppSettings {
+ // Some settings.
+ CommonLanguageSettings common = 1;
+}
+
+// Settings for Php client libraries.
+message PhpSettings {
+ // Some settings.
+ CommonLanguageSettings common = 1;
+}
+
+// Settings for Python client libraries.
+message PythonSettings {
+ // Experimental features to be included during client library generation.
+ // These fields will be deprecated once the feature graduates and is enabled
+ // by default.
+ message ExperimentalFeatures {
+ // Enables generation of asynchronous REST clients if `rest` transport is
+ // enabled. By default, asynchronous REST clients will not be generated.
+ // This feature will be enabled by default 1 month after launching the
+ // feature in preview packages.
+ bool rest_async_io_enabled = 1;
+
+ // Enables generation of protobuf code using new types that are more
+ // Pythonic which are included in `protobuf>=5.29.x`. This feature will be
+ // enabled by default 1 month after launching the feature in preview
+ // packages.
+ bool protobuf_pythonic_types_enabled = 2;
+
+ // Disables generation of an unversioned Python package for this client
+ // library. This means that the module names will need to be versioned in
+ // import statements. For example `import google.cloud.library_v2` instead
+ // of `import google.cloud.library`.
+ bool unversioned_package_disabled = 3;
+ }
+
+ // Some settings.
+ CommonLanguageSettings common = 1;
+
+ // Experimental features to be included during client library generation.
+ ExperimentalFeatures experimental_features = 2;
+}
+
+// Settings for Node client libraries.
+message NodeSettings {
+ // Some settings.
+ CommonLanguageSettings common = 1;
+}
+
+// Settings for Dotnet client libraries.
+message DotnetSettings {
+ // Some settings.
+ CommonLanguageSettings common = 1;
+
+ // Map from original service names to renamed versions.
+ // This is used when the default generated types
+ // would cause a naming conflict. (Neither name is
+ // fully-qualified.)
+ // Example: Subscriber to SubscriberServiceApi.
+ map renamed_services = 2;
+
+ // Map from full resource types to the effective short name
+ // for the resource. This is used when otherwise resource
+ // named from different services would cause naming collisions.
+ // Example entry:
+ // "datalabeling.googleapis.com/Dataset": "DataLabelingDataset"
+ map renamed_resources = 3;
+
+ // List of full resource types to ignore during generation.
+ // This is typically used for API-specific Location resources,
+ // which should be handled by the generator as if they were actually
+ // the common Location resources.
+ // Example entry: "documentai.googleapis.com/Location"
+ repeated string ignored_resources = 4;
+
+ // Namespaces which must be aliased in snippets due to
+ // a known (but non-generator-predictable) naming collision
+ repeated string forced_namespace_aliases = 5;
+
+ // Method signatures (in the form "service.method(signature)")
+ // which are provided separately, so shouldn't be generated.
+ // Snippets *calling* these methods are still generated, however.
+ repeated string handwritten_signatures = 6;
+}
+
+// Settings for Ruby client libraries.
+message RubySettings {
+ // Some settings.
+ CommonLanguageSettings common = 1;
+}
+
+// Settings for Go client libraries.
+message GoSettings {
+ // Some settings.
+ CommonLanguageSettings common = 1;
+
+ // Map of service names to renamed services. Keys are the package relative
+ // service names and values are the name to be used for the service client
+ // and call options.
+ //
+ // publishing:
+ // go_settings:
+ // renamed_services:
+ // Publisher: TopicAdmin
+ map renamed_services = 2;
+}
+
+// Describes the generator configuration for a method.
+message MethodSettings {
+ // Describes settings to use when generating API methods that use the
+ // long-running operation pattern.
+ // All default values below are from those used in the client library
+ // generators (e.g.
+ // [Java](https://github.com/googleapis/gapic-generator-java/blob/04c2faa191a9b5a10b92392fe8482279c4404803/src/main/java/com/google/api/generator/gapic/composer/common/RetrySettingsComposer.java)).
+ message LongRunning {
+ // Initial delay after which the first poll request will be made.
+ // Default value: 5 seconds.
+ google.protobuf.Duration initial_poll_delay = 1;
+
+ // Multiplier to gradually increase delay between subsequent polls until it
+ // reaches max_poll_delay.
+ // Default value: 1.5.
+ float poll_delay_multiplier = 2;
+
+ // Maximum time between two subsequent poll requests.
+ // Default value: 45 seconds.
+ google.protobuf.Duration max_poll_delay = 3;
+
+ // Total polling timeout.
+ // Default value: 5 minutes.
+ google.protobuf.Duration total_poll_timeout = 4;
+ }
+
+ // The fully qualified name of the method, for which the options below apply.
+ // This is used to find the method to apply the options.
+ //
+ // Example:
+ //
+ // publishing:
+ // method_settings:
+ // - selector: google.storage.control.v2.StorageControl.CreateFolder
+ // # method settings for CreateFolder...
+ string selector = 1;
+
+ // Describes settings to use for long-running operations when generating
+ // API methods for RPCs. Complements RPCs that use the annotations in
+ // google/longrunning/operations.proto.
+ //
+ // Example of a YAML configuration::
+ //
+ // publishing:
+ // method_settings:
+ // - selector: google.cloud.speech.v2.Speech.BatchRecognize
+ // long_running:
+ // initial_poll_delay: 60s # 1 minute
+ // poll_delay_multiplier: 1.5
+ // max_poll_delay: 360s # 6 minutes
+ // total_poll_timeout: 54000s # 90 minutes
+ LongRunning long_running = 2;
+
+ // List of top-level fields of the request message, that should be
+ // automatically populated by the client libraries based on their
+ // (google.api.field_info).format. Currently supported format: UUID4.
+ //
+ // Example of a YAML configuration:
+ //
+ // publishing:
+ // method_settings:
+ // - selector: google.example.v1.ExampleService.CreateExample
+ // auto_populated_fields:
+ // - request_id
+ repeated string auto_populated_fields = 3;
+}
+
+// The organization for which the client libraries are being published.
+// Affects the url where generated docs are published, etc.
+enum ClientLibraryOrganization {
+ // Not useful.
+ CLIENT_LIBRARY_ORGANIZATION_UNSPECIFIED = 0;
+
+ // Google Cloud Platform Org.
+ CLOUD = 1;
+
+ // Ads (Advertising) Org.
+ ADS = 2;
+
+ // Photos Org.
+ PHOTOS = 3;
+
+ // Street View Org.
+ STREET_VIEW = 4;
+
+ // Shopping Org.
+ SHOPPING = 5;
+
+ // Geo Org.
+ GEO = 6;
+
+ // Generative AI - https://developers.generativeai.google
+ GENERATIVE_AI = 7;
+}
+
+// To where should client libraries be published?
+enum ClientLibraryDestination {
+ // Client libraries will neither be generated nor published to package
+ // managers.
+ CLIENT_LIBRARY_DESTINATION_UNSPECIFIED = 0;
+
+ // Generate the client library in a repo under github.com/googleapis,
+ // but don't publish it to package managers.
+ GITHUB = 10;
+
+ // Publish the library to package managers like nuget.org and npmjs.com.
+ PACKAGE_MANAGER = 20;
+}
+
+// This message is used to configure the generation of a subset of the RPCs in
+// a service for client libraries.
+message SelectiveGapicGeneration {
+ // An allowlist of the fully qualified names of RPCs that should be included
+ // on public client surfaces.
+ repeated string methods = 1;
+
+ // Setting this to true indicates to the client generators that methods
+ // that would be excluded from the generation should instead be generated
+ // in a way that indicates these methods should not be consumed by
+ // end users. How this is expressed is up to individual language
+ // implementations to decide. Some examples may be: added annotations,
+ // obfuscated identifiers, or other language idiomatic patterns.
+ bool generate_omitted_as_internal = 2;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/field_behavior.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/field_behavior.proto
new file mode 100644
index 00000000..1fdaaed1
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/field_behavior.proto
@@ -0,0 +1,104 @@
+// 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
+//
+// 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.api;
+
+import "google/protobuf/descriptor.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "FieldBehaviorProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+extend google.protobuf.FieldOptions {
+ // A designation of a specific field behavior (required, output only, etc.)
+ // in protobuf messages.
+ //
+ // Examples:
+ //
+ // string name = 1 [(google.api.field_behavior) = REQUIRED];
+ // State state = 1 [(google.api.field_behavior) = OUTPUT_ONLY];
+ // google.protobuf.Duration ttl = 1
+ // [(google.api.field_behavior) = INPUT_ONLY];
+ // google.protobuf.Timestamp expire_time = 1
+ // [(google.api.field_behavior) = OUTPUT_ONLY,
+ // (google.api.field_behavior) = IMMUTABLE];
+ repeated google.api.FieldBehavior field_behavior = 1052 [packed = false];
+}
+
+// An indicator of the behavior of a given field (for example, that a field
+// is required in requests, or given as output but ignored as input).
+// This **does not** change the behavior in protocol buffers itself; it only
+// denotes the behavior and may affect how API tooling handles the field.
+//
+// Note: This enum **may** receive new values in the future.
+enum FieldBehavior {
+ // Conventional default for enums. Do not use this.
+ FIELD_BEHAVIOR_UNSPECIFIED = 0;
+
+ // Specifically denotes a field as optional.
+ // While all fields in protocol buffers are optional, this may be specified
+ // for emphasis if appropriate.
+ OPTIONAL = 1;
+
+ // Denotes a field as required.
+ // This indicates that the field **must** be provided as part of the request,
+ // and failure to do so will cause an error (usually `INVALID_ARGUMENT`).
+ REQUIRED = 2;
+
+ // Denotes a field as output only.
+ // This indicates that the field is provided in responses, but including the
+ // field in a request does nothing (the server *must* ignore it and
+ // *must not* throw an error as a result of the field's presence).
+ OUTPUT_ONLY = 3;
+
+ // Denotes a field as input only.
+ // This indicates that the field is provided in requests, and the
+ // corresponding field is not included in output.
+ INPUT_ONLY = 4;
+
+ // Denotes a field as immutable.
+ // This indicates that the field may be set once in a request to create a
+ // resource, but may not be changed thereafter.
+ IMMUTABLE = 5;
+
+ // Denotes that a (repeated) field is an unordered list.
+ // This indicates that the service may provide the elements of the list
+ // in any arbitrary order, rather than the order the user originally
+ // provided. Additionally, the list's order may or may not be stable.
+ UNORDERED_LIST = 6;
+
+ // Denotes that this field returns a non-empty default value if not set.
+ // This indicates that if the user provides the empty value in a request,
+ // a non-empty value will be returned. The user will not be aware of what
+ // non-empty value to expect.
+ NON_EMPTY_DEFAULT = 7;
+
+ // Denotes that the field in a resource (a message annotated with
+ // google.api.resource) is used in the resource name to uniquely identify the
+ // resource. For AIP-compliant APIs, this should only be applied to the
+ // `name` field on the resource.
+ //
+ // This behavior should not be applied to references to other resources within
+ // the message.
+ //
+ // The identifier field of resources often have different field behavior
+ // depending on the request it is embedded in (e.g. for Create methods name
+ // is optional and unused, while for Update methods it is required). Instead
+ // of method-specific annotations, only `IDENTIFIER` is required.
+ IDENTIFIER = 8;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/http.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/http.proto
new file mode 100644
index 00000000..57621b53
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/http.proto
@@ -0,0 +1,370 @@
+// 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
+//
+// 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.api;
+
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "HttpProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+// Defines the HTTP configuration for an API service. It contains a list of
+// [HttpRule][google.api.HttpRule], each specifying the mapping of an RPC method
+// to one or more HTTP REST API methods.
+message Http {
+ // A list of HTTP configuration rules that apply to individual API methods.
+ //
+ // **NOTE:** All service configuration rules follow "last one wins" order.
+ repeated HttpRule rules = 1;
+
+ // When set to true, URL path parameters will be fully URI-decoded except in
+ // cases of single segment matches in reserved expansion, where "%2F" will be
+ // left encoded.
+ //
+ // The default behavior is to not decode RFC 6570 reserved characters in multi
+ // segment matches.
+ bool fully_decode_reserved_expansion = 2;
+}
+
+// gRPC Transcoding
+//
+// gRPC Transcoding is a feature for mapping between a gRPC method and one or
+// more HTTP REST endpoints. It allows developers to build a single API service
+// that supports both gRPC APIs and REST APIs. Many systems, including [Google
+// APIs](https://github.com/googleapis/googleapis),
+// [Cloud Endpoints](https://cloud.google.com/endpoints), [gRPC
+// Gateway](https://github.com/grpc-ecosystem/grpc-gateway),
+// and [Envoy](https://github.com/envoyproxy/envoy) proxy support this feature
+// and use it for large scale production services.
+//
+// `HttpRule` defines the schema of the gRPC/REST mapping. The mapping specifies
+// how different portions of the gRPC request message are mapped to the URL
+// path, URL query parameters, and HTTP request body. It also controls how the
+// gRPC response message is mapped to the HTTP response body. `HttpRule` is
+// typically specified as an `google.api.http` annotation on the gRPC method.
+//
+// Each mapping specifies a URL path template and an HTTP method. The path
+// template may refer to one or more fields in the gRPC request message, as long
+// as each field is a non-repeated field with a primitive (non-message) type.
+// The path template controls how fields of the request message are mapped to
+// the URL path.
+//
+// Example:
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// get: "/v1/{name=messages/*}"
+// };
+// }
+// }
+// message GetMessageRequest {
+// string name = 1; // Mapped to URL path.
+// }
+// message Message {
+// string text = 1; // The resource content.
+// }
+//
+// This enables an HTTP REST to gRPC mapping as below:
+//
+// - HTTP: `GET /v1/messages/123456`
+// - gRPC: `GetMessage(name: "messages/123456")`
+//
+// Any fields in the request message which are not bound by the path template
+// automatically become HTTP query parameters if there is no HTTP request body.
+// For example:
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// get:"/v1/messages/{message_id}"
+// };
+// }
+// }
+// message GetMessageRequest {
+// message SubMessage {
+// string subfield = 1;
+// }
+// string message_id = 1; // Mapped to URL path.
+// int64 revision = 2; // Mapped to URL query parameter `revision`.
+// SubMessage sub = 3; // Mapped to URL query parameter `sub.subfield`.
+// }
+//
+// This enables a HTTP JSON to RPC mapping as below:
+//
+// - HTTP: `GET /v1/messages/123456?revision=2&sub.subfield=foo`
+// - gRPC: `GetMessage(message_id: "123456" revision: 2 sub:
+// SubMessage(subfield: "foo"))`
+//
+// Note that fields which are mapped to URL query parameters must have a
+// primitive type or a repeated primitive type or a non-repeated message type.
+// In the case of a repeated type, the parameter can be repeated in the URL
+// as `...?param=A¶m=B`. In the case of a message type, each field of the
+// message is mapped to a separate parameter, such as
+// `...?foo.a=A&foo.b=B&foo.c=C`.
+//
+// For HTTP methods that allow a request body, the `body` field
+// specifies the mapping. Consider a REST update method on the
+// message resource collection:
+//
+// service Messaging {
+// rpc UpdateMessage(UpdateMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// patch: "/v1/messages/{message_id}"
+// body: "message"
+// };
+// }
+// }
+// message UpdateMessageRequest {
+// string message_id = 1; // mapped to the URL
+// Message message = 2; // mapped to the body
+// }
+//
+// The following HTTP JSON to RPC mapping is enabled, where the
+// representation of the JSON in the request body is determined by
+// protos JSON encoding:
+//
+// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }`
+// - gRPC: `UpdateMessage(message_id: "123456" message { text: "Hi!" })`
+//
+// The special name `*` can be used in the body mapping to define that
+// every field not bound by the path template should be mapped to the
+// request body. This enables the following alternative definition of
+// the update method:
+//
+// service Messaging {
+// rpc UpdateMessage(Message) returns (Message) {
+// option (google.api.http) = {
+// patch: "/v1/messages/{message_id}"
+// body: "*"
+// };
+// }
+// }
+// message Message {
+// string message_id = 1;
+// string text = 2;
+// }
+//
+//
+// The following HTTP JSON to RPC mapping is enabled:
+//
+// - HTTP: `PATCH /v1/messages/123456 { "text": "Hi!" }`
+// - gRPC: `UpdateMessage(message_id: "123456" text: "Hi!")`
+//
+// Note that when using `*` in the body mapping, it is not possible to
+// have HTTP parameters, as all fields not bound by the path end in
+// the body. This makes this option more rarely used in practice when
+// defining REST APIs. The common usage of `*` is in custom methods
+// which don't use the URL at all for transferring data.
+//
+// It is possible to define multiple HTTP methods for one RPC by using
+// the `additional_bindings` option. Example:
+//
+// service Messaging {
+// rpc GetMessage(GetMessageRequest) returns (Message) {
+// option (google.api.http) = {
+// get: "/v1/messages/{message_id}"
+// additional_bindings {
+// get: "/v1/users/{user_id}/messages/{message_id}"
+// }
+// };
+// }
+// }
+// message GetMessageRequest {
+// string message_id = 1;
+// string user_id = 2;
+// }
+//
+// This enables the following two alternative HTTP JSON to RPC mappings:
+//
+// - HTTP: `GET /v1/messages/123456`
+// - gRPC: `GetMessage(message_id: "123456")`
+//
+// - HTTP: `GET /v1/users/me/messages/123456`
+// - gRPC: `GetMessage(user_id: "me" message_id: "123456")`
+//
+// Rules for HTTP mapping
+//
+// 1. Leaf request fields (recursive expansion nested messages in the request
+// message) are classified into three categories:
+// - Fields referred by the path template. They are passed via the URL path.
+// - Fields referred by the [HttpRule.body][google.api.HttpRule.body]. They
+// are passed via the HTTP
+// request body.
+// - All other fields are passed via the URL query parameters, and the
+// parameter name is the field path in the request message. A repeated
+// field can be represented as multiple query parameters under the same
+// name.
+// 2. If [HttpRule.body][google.api.HttpRule.body] is "*", there is no URL
+// query parameter, all fields
+// are passed via URL path and HTTP request body.
+// 3. If [HttpRule.body][google.api.HttpRule.body] is omitted, there is no HTTP
+// request body, all
+// fields are passed via URL path and URL query parameters.
+//
+// Path template syntax
+//
+// Template = "/" Segments [ Verb ] ;
+// Segments = Segment { "/" Segment } ;
+// Segment = "*" | "**" | LITERAL | Variable ;
+// Variable = "{" FieldPath [ "=" Segments ] "}" ;
+// FieldPath = IDENT { "." IDENT } ;
+// Verb = ":" LITERAL ;
+//
+// The syntax `*` matches a single URL path segment. The syntax `**` matches
+// zero or more URL path segments, which must be the last part of the URL path
+// except the `Verb`.
+//
+// The syntax `Variable` matches part of the URL path as specified by its
+// template. A variable template must not contain other variables. If a variable
+// matches a single path segment, its template may be omitted, e.g. `{var}`
+// is equivalent to `{var=*}`.
+//
+// The syntax `LITERAL` matches literal text in the URL path. If the `LITERAL`
+// contains any reserved character, such characters should be percent-encoded
+// before the matching.
+//
+// If a variable contains exactly one path segment, such as `"{var}"` or
+// `"{var=*}"`, when such a variable is expanded into a URL path on the client
+// side, all characters except `[-_.~0-9a-zA-Z]` are percent-encoded. The
+// server side does the reverse decoding. Such variables show up in the
+// [Discovery
+// Document](https://developers.google.com/discovery/v1/reference/apis) as
+// `{var}`.
+//
+// If a variable contains multiple path segments, such as `"{var=foo/*}"`
+// or `"{var=**}"`, when such a variable is expanded into a URL path on the
+// client side, all characters except `[-_.~/0-9a-zA-Z]` are percent-encoded.
+// The server side does the reverse decoding, except "%2F" and "%2f" are left
+// unchanged. Such variables show up in the
+// [Discovery
+// Document](https://developers.google.com/discovery/v1/reference/apis) as
+// `{+var}`.
+//
+// Using gRPC API Service Configuration
+//
+// gRPC API Service Configuration (service config) is a configuration language
+// for configuring a gRPC service to become a user-facing product. The
+// service config is simply the YAML representation of the `google.api.Service`
+// proto message.
+//
+// As an alternative to annotating your proto file, you can configure gRPC
+// transcoding in your service config YAML files. You do this by specifying a
+// `HttpRule` that maps the gRPC method to a REST endpoint, achieving the same
+// effect as the proto annotation. This can be particularly useful if you
+// have a proto that is reused in multiple services. Note that any transcoding
+// specified in the service config will override any matching transcoding
+// configuration in the proto.
+//
+// The following example selects a gRPC method and applies an `HttpRule` to it:
+//
+// http:
+// rules:
+// - selector: example.v1.Messaging.GetMessage
+// get: /v1/messages/{message_id}/{sub.subfield}
+//
+// Special notes
+//
+// When gRPC Transcoding is used to map a gRPC to JSON REST endpoints, the
+// proto to JSON conversion must follow the [proto3
+// specification](https://developers.google.com/protocol-buffers/docs/proto3#json).
+//
+// While the single segment variable follows the semantics of
+// [RFC 6570](https://tools.ietf.org/html/rfc6570) Section 3.2.2 Simple String
+// Expansion, the multi segment variable **does not** follow RFC 6570 Section
+// 3.2.3 Reserved Expansion. The reason is that the Reserved Expansion
+// does not expand special characters like `?` and `#`, which would lead
+// to invalid URLs. As the result, gRPC Transcoding uses a custom encoding
+// for multi segment variables.
+//
+// The path variables **must not** refer to any repeated or mapped field,
+// because client libraries are not capable of handling such variable expansion.
+//
+// The path variables **must not** capture the leading "/" character. The reason
+// is that the most common use case "{var}" does not capture the leading "/"
+// character. For consistency, all path variables must share the same behavior.
+//
+// Repeated message fields must not be mapped to URL query parameters, because
+// no client library can support such complicated mapping.
+//
+// If an API needs to use a JSON array for request or response body, it can map
+// the request or response body to a repeated field. However, some gRPC
+// Transcoding implementations may not support this feature.
+message HttpRule {
+ // Selects a method to which this rule applies.
+ //
+ // Refer to [selector][google.api.DocumentationRule.selector] for syntax
+ // details.
+ string selector = 1;
+
+ // Determines the URL pattern is matched by this rules. This pattern can be
+ // used with any of the {get|put|post|delete|patch} methods. A custom method
+ // can be defined using the 'custom' field.
+ oneof pattern {
+ // Maps to HTTP GET. Used for listing and getting information about
+ // resources.
+ string get = 2;
+
+ // Maps to HTTP PUT. Used for replacing a resource.
+ string put = 3;
+
+ // Maps to HTTP POST. Used for creating a resource or performing an action.
+ string post = 4;
+
+ // Maps to HTTP DELETE. Used for deleting a resource.
+ string delete = 5;
+
+ // Maps to HTTP PATCH. Used for updating a resource.
+ string patch = 6;
+
+ // The custom pattern is used for specifying an HTTP method that is not
+ // included in the `pattern` field, such as HEAD, or "*" to leave the
+ // HTTP method unspecified for this rule. The wild-card rule is useful
+ // for services that provide content to Web (HTML) clients.
+ CustomHttpPattern custom = 8;
+ }
+
+ // The name of the request field whose value is mapped to the HTTP request
+ // body, or `*` for mapping all request fields not captured by the path
+ // pattern to the HTTP body, or omitted for not having any HTTP request body.
+ //
+ // NOTE: the referred field must be present at the top-level of the request
+ // message type.
+ string body = 7;
+
+ // Optional. The name of the response field whose value is mapped to the HTTP
+ // response body. When omitted, the entire response message will be used
+ // as the HTTP response body.
+ //
+ // NOTE: The referred field must be present at the top-level of the response
+ // message type.
+ string response_body = 12;
+
+ // Additional HTTP bindings for the selector. Nested bindings must
+ // not contain an `additional_bindings` field themselves (that is,
+ // the nesting may only be one level deep).
+ repeated HttpRule additional_bindings = 11;
+}
+
+// A custom pattern is used for defining custom HTTP verb.
+message CustomHttpPattern {
+ // The name of this custom HTTP verb.
+ string kind = 1;
+
+ // The path matched by this custom verb.
+ string path = 2;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/launch_stage.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/launch_stage.proto
new file mode 100644
index 00000000..1e86c1ad
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/launch_stage.proto
@@ -0,0 +1,72 @@
+// 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
+//
+// 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.api;
+
+option go_package = "google.golang.org/genproto/googleapis/api;api";
+option java_multiple_files = true;
+option java_outer_classname = "LaunchStageProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+// The launch stage as defined by [Google Cloud Platform
+// Launch Stages](https://cloud.google.com/terms/launch-stages).
+enum LaunchStage {
+ // Do not use this default value.
+ LAUNCH_STAGE_UNSPECIFIED = 0;
+
+ // The feature is not yet implemented. Users can not use it.
+ UNIMPLEMENTED = 6;
+
+ // Prelaunch features are hidden from users and are only visible internally.
+ PRELAUNCH = 7;
+
+ // Early Access features are limited to a closed group of testers. To use
+ // these features, you must sign up in advance and sign a Trusted Tester
+ // agreement (which includes confidentiality provisions). These features may
+ // be unstable, changed in backward-incompatible ways, and are not
+ // guaranteed to be released.
+ EARLY_ACCESS = 1;
+
+ // Alpha is a limited availability test for releases before they are cleared
+ // for widespread use. By Alpha, all significant design issues are resolved
+ // and we are in the process of verifying functionality. Alpha customers
+ // need to apply for access, agree to applicable terms, and have their
+ // projects allowlisted. Alpha releases don't have to be feature complete,
+ // no SLAs are provided, and there are no technical support obligations, but
+ // they will be far enough along that customers can actually use them in
+ // test environments or for limited-use tests -- just like they would in
+ // normal production cases.
+ ALPHA = 2;
+
+ // Beta is the point at which we are ready to open a release for any
+ // customer to use. There are no SLA or technical support obligations in a
+ // Beta release. Products will be complete from a feature perspective, but
+ // may have some open outstanding issues. Beta releases are suitable for
+ // limited production use cases.
+ BETA = 3;
+
+ // GA features are open to all developers and are considered stable and
+ // fully qualified for production use.
+ GA = 4;
+
+ // Deprecated features are scheduled to be shut down and removed. For more
+ // information, see the "Deprecation Policy" section of our [Terms of
+ // Service](https://cloud.google.com/terms/)
+ // and the [Google Cloud Platform Subject to the Deprecation
+ // Policy](https://cloud.google.com/terms/deprecation) documentation.
+ DEPRECATED = 5;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/resource.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/resource.proto
new file mode 100644
index 00000000..5669cbc9
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/api/resource.proto
@@ -0,0 +1,242 @@
+// 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
+//
+// 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.api;
+
+import "google/protobuf/descriptor.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/api/annotations;annotations";
+option java_multiple_files = true;
+option java_outer_classname = "ResourceProto";
+option java_package = "com.google.api";
+option objc_class_prefix = "GAPI";
+
+extend google.protobuf.FieldOptions {
+ // An annotation that describes a resource reference, see
+ // [ResourceReference][].
+ google.api.ResourceReference resource_reference = 1055;
+}
+
+extend google.protobuf.FileOptions {
+ // An annotation that describes a resource definition without a corresponding
+ // message; see [ResourceDescriptor][].
+ repeated google.api.ResourceDescriptor resource_definition = 1053;
+}
+
+extend google.protobuf.MessageOptions {
+ // An annotation that describes a resource definition, see
+ // [ResourceDescriptor][].
+ google.api.ResourceDescriptor resource = 1053;
+}
+
+// A simple descriptor of a resource type.
+//
+// ResourceDescriptor annotates a resource message (either by means of a
+// protobuf annotation or use in the service config), and associates the
+// resource's schema, the resource type, and the pattern of the resource name.
+//
+// Example:
+//
+// message Topic {
+// // Indicates this message defines a resource schema.
+// // Declares the resource type in the format of {service}/{kind}.
+// // For Kubernetes resources, the format is {api group}/{kind}.
+// option (google.api.resource) = {
+// type: "pubsub.googleapis.com/Topic"
+// pattern: "projects/{project}/topics/{topic}"
+// };
+// }
+//
+// The ResourceDescriptor Yaml config will look like:
+//
+// resources:
+// - type: "pubsub.googleapis.com/Topic"
+// pattern: "projects/{project}/topics/{topic}"
+//
+// Sometimes, resources have multiple patterns, typically because they can
+// live under multiple parents.
+//
+// Example:
+//
+// message LogEntry {
+// option (google.api.resource) = {
+// type: "logging.googleapis.com/LogEntry"
+// pattern: "projects/{project}/logs/{log}"
+// pattern: "folders/{folder}/logs/{log}"
+// pattern: "organizations/{organization}/logs/{log}"
+// pattern: "billingAccounts/{billing_account}/logs/{log}"
+// };
+// }
+//
+// The ResourceDescriptor Yaml config will look like:
+//
+// resources:
+// - type: 'logging.googleapis.com/LogEntry'
+// pattern: "projects/{project}/logs/{log}"
+// pattern: "folders/{folder}/logs/{log}"
+// pattern: "organizations/{organization}/logs/{log}"
+// pattern: "billingAccounts/{billing_account}/logs/{log}"
+message ResourceDescriptor {
+ // A description of the historical or future-looking state of the
+ // resource pattern.
+ enum History {
+ // The "unset" value.
+ HISTORY_UNSPECIFIED = 0;
+
+ // The resource originally had one pattern and launched as such, and
+ // additional patterns were added later.
+ ORIGINALLY_SINGLE_PATTERN = 1;
+
+ // The resource has one pattern, but the API owner expects to add more
+ // later. (This is the inverse of ORIGINALLY_SINGLE_PATTERN, and prevents
+ // that from being necessary once there are multiple patterns.)
+ FUTURE_MULTI_PATTERN = 2;
+ }
+
+ // A flag representing a specific style that a resource claims to conform to.
+ enum Style {
+ // The unspecified value. Do not use.
+ STYLE_UNSPECIFIED = 0;
+
+ // This resource is intended to be "declarative-friendly".
+ //
+ // Declarative-friendly resources must be more strictly consistent, and
+ // setting this to true communicates to tools that this resource should
+ // adhere to declarative-friendly expectations.
+ //
+ // Note: This is used by the API linter (linter.aip.dev) to enable
+ // additional checks.
+ DECLARATIVE_FRIENDLY = 1;
+ }
+
+ // The resource type. It must be in the format of
+ // {service_name}/{resource_type_kind}. The `resource_type_kind` must be
+ // singular and must not include version numbers.
+ //
+ // Example: `storage.googleapis.com/Bucket`
+ //
+ // The value of the resource_type_kind must follow the regular expression
+ // /[A-Za-z][a-zA-Z0-9]+/. It should start with an upper case character and
+ // should use PascalCase (UpperCamelCase). The maximum number of
+ // characters allowed for the `resource_type_kind` is 100.
+ string type = 1;
+
+ // Optional. The relative resource name pattern associated with this resource
+ // type. The DNS prefix of the full resource name shouldn't be specified here.
+ //
+ // The path pattern must follow the syntax, which aligns with HTTP binding
+ // syntax:
+ //
+ // Template = Segment { "/" Segment } ;
+ // Segment = LITERAL | Variable ;
+ // Variable = "{" LITERAL "}" ;
+ //
+ // Examples:
+ //
+ // - "projects/{project}/topics/{topic}"
+ // - "projects/{project}/knowledgeBases/{knowledge_base}"
+ //
+ // The components in braces correspond to the IDs for each resource in the
+ // hierarchy. It is expected that, if multiple patterns are provided,
+ // the same component name (e.g. "project") refers to IDs of the same
+ // type of resource.
+ repeated string pattern = 2;
+
+ // Optional. The field on the resource that designates the resource name
+ // field. If omitted, this is assumed to be "name".
+ string name_field = 3;
+
+ // Optional. The historical or future-looking state of the resource pattern.
+ //
+ // Example:
+ //
+ // // The InspectTemplate message originally only supported resource
+ // // names with organization, and project was added later.
+ // message InspectTemplate {
+ // option (google.api.resource) = {
+ // type: "dlp.googleapis.com/InspectTemplate"
+ // pattern:
+ // "organizations/{organization}/inspectTemplates/{inspect_template}"
+ // pattern: "projects/{project}/inspectTemplates/{inspect_template}"
+ // history: ORIGINALLY_SINGLE_PATTERN
+ // };
+ // }
+ History history = 4;
+
+ // The plural name used in the resource name and permission names, such as
+ // 'projects' for the resource name of 'projects/{project}' and the permission
+ // name of 'cloudresourcemanager.googleapis.com/projects.get'. One exception
+ // to this is for Nested Collections that have stuttering names, as defined
+ // in [AIP-122](https://google.aip.dev/122#nested-collections), where the
+ // collection ID in the resource name pattern does not necessarily directly
+ // match the `plural` value.
+ //
+ // It is the same concept of the `plural` field in k8s CRD spec
+ // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/
+ //
+ // Note: The plural form is required even for singleton resources. See
+ // https://aip.dev/156
+ string plural = 5;
+
+ // The same concept of the `singular` field in k8s CRD spec
+ // https://kubernetes.io/docs/tasks/access-kubernetes-api/custom-resources/custom-resource-definitions/
+ // Such as "project" for the `resourcemanager.googleapis.com/Project` type.
+ string singular = 6;
+
+ // Style flag(s) for this resource.
+ // These indicate that a resource is expected to conform to a given
+ // style. See the specific style flags for additional information.
+ repeated Style style = 10;
+}
+
+// Defines a proto annotation that describes a string field that refers to
+// an API resource.
+message ResourceReference {
+ // The resource type that the annotated field references.
+ //
+ // Example:
+ //
+ // message Subscription {
+ // string topic = 2 [(google.api.resource_reference) = {
+ // type: "pubsub.googleapis.com/Topic"
+ // }];
+ // }
+ //
+ // Occasionally, a field may reference an arbitrary resource. In this case,
+ // APIs use the special value * in their resource reference.
+ //
+ // Example:
+ //
+ // message GetIamPolicyRequest {
+ // string resource = 2 [(google.api.resource_reference) = {
+ // type: "*"
+ // }];
+ // }
+ string type = 1;
+
+ // The resource type of a child collection that the annotated field
+ // references. This is useful for annotating the `parent` field that
+ // doesn't have a fixed resource type.
+ //
+ // Example:
+ //
+ // message ListLogEntriesRequest {
+ // string parent = 1 [(google.api.resource_reference) = {
+ // child_type: "logging.googleapis.com/LogEntry"
+ // };
+ // }
+ string child_type = 2;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/BUILD.bazel
new file mode 100644
index 00000000..31fd6457
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/BUILD.bazel
@@ -0,0 +1,167 @@
+##############################################################################
+# Java
+##############################################################################
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "cc_proto_library",
+ "go_proto_library",
+ "java_gapic_assembly_gradle_pkg",
+ "java_proto_library",
+ "php_gapic_assembly_pkg",
+ "php_proto_library",
+ "py_gapic_assembly_pkg",
+ "py_proto_library",
+ "upb_c_proto_library",
+)
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+# This is an API workspace, having public visibility by default makes perfect sense.
+package(default_visibility = ["//visibility:public"])
+
+##############################################################################
+# Common
+##############################################################################
+proto_library(
+ name = "code_proto",
+ srcs = ["code.proto"],
+ deps = [],
+)
+
+proto_library(
+ name = "error_details_proto",
+ srcs = ["error_details.proto"],
+ deps = [
+ "@com_google_protobuf//:duration_proto",
+ ],
+)
+
+proto_library(
+ name = "http_proto",
+ srcs = ["http.proto"],
+)
+
+proto_library(
+ name = "status_proto",
+ srcs = ["status.proto"],
+ deps = [
+ "@com_google_protobuf//:any_proto",
+ ],
+)
+
+java_proto_library(
+ name = "rpc_java_proto",
+ deps = [
+ ":code_proto",
+ ":error_details_proto",
+ ":status_proto",
+ ],
+)
+
+# Please DO-NOT-REMOVE this section.
+# This is required to generate java files for these protos.
+# Open Source Packages
+java_gapic_assembly_gradle_pkg(
+ name = "google-rpc-java",
+ transport = "grpc+rest",
+ deps = [
+ "error_details_proto",
+ "status_proto",
+ ":code_proto",
+ ":rpc_java_proto",
+ ],
+)
+
+go_proto_library(
+ name = "code_go_proto",
+ importpath = "google.golang.org/genproto/googleapis/rpc/code",
+ protos = [":code_proto"],
+)
+
+go_proto_library(
+ name = "errdetails_go_proto",
+ importpath = "google.golang.org/genproto/googleapis/rpc/errdetails",
+ protos = [":error_details_proto"],
+)
+
+go_proto_library(
+ name = "status_go_proto",
+ importpath = "google.golang.org/genproto/googleapis/rpc/status",
+ protos = [":status_proto"],
+)
+
+cc_proto_library(
+ name = "code_cc_proto",
+ deps = [":code_proto"],
+)
+
+cc_proto_library(
+ name = "error_details_cc_proto",
+ deps = [":error_details_proto"],
+)
+
+cc_proto_library(
+ name = "status_cc_proto",
+ deps = [":status_proto"],
+)
+
+upb_c_proto_library(
+ name = "code_upb_proto",
+ deps = [":code_proto"],
+)
+
+upb_c_proto_library(
+ name = "status_upb_proto",
+ deps = [":status_proto"],
+)
+
+py_proto_library(
+ name = "code_py_proto",
+ deps = [":code_proto"],
+)
+
+py_proto_library(
+ name = "error_details_py_proto",
+ deps = [":error_details_proto"],
+)
+
+py_proto_library(
+ name = "http_py_proto",
+ deps = [":http_proto"],
+)
+
+py_proto_library(
+ name = "status_py_proto",
+ deps = [":status_proto"],
+)
+
+# Open Source Packages
+py_gapic_assembly_pkg(
+ name = "rpc-py",
+ deps = [
+ ":code_proto",
+ ":code_py_proto",
+ ":error_details_proto",
+ ":error_details_py_proto",
+ ":http_proto",
+ ":http_py_proto",
+ ":status_proto",
+ ":status_py_proto",
+ ],
+)
+
+php_proto_library(
+ name = "rpc_php_proto",
+ deps = [
+ ":code_proto",
+ ":error_details_proto",
+ ":status_proto",
+ ],
+)
+
+# Please DO-NOT-REMOVE this section.
+# This is required to generate php files for these protos.
+# Open Source Packages
+php_gapic_assembly_pkg(
+ name = "google-rpc-php",
+ deps = [":rpc_php_proto"],
+)
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/README.md b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/README.md
new file mode 100644
index 00000000..b4775007
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/README.md
@@ -0,0 +1,18 @@
+## RPC (Remote Procedure Call) Types
+
+This package contains [protocol buffer][protobuf] types that represent remote procedure
+call concepts. While [gRPC](https://grpc.io) uses these types, we encourage their
+use in any interested RPC implementation to promote compatibility and consistency.
+
+### Key Concepts
+
+- **Code**: An enum that represents an error code returned by an RPC. These error codes
+ map to HTTP codes, but are slightly finer-grained. Every gRPC code has exactly one
+ corresponding HTTP code; however, some HTTP codes have more than one corresponding
+ gRPC code.
+- **Error details**: Any of the types contained in `error_details.proto` which provide
+ extra details about particular types of failures.
+- **Status**: Combines a code, message, and error details to represent the success or
+ failure details of an RPC call.
+
+[protobuf]: https://developers.google.com/protocol-buffers/
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/code.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/code.proto
new file mode 100644
index 00000000..aa6ce153
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/code.proto
@@ -0,0 +1,186 @@
+// 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
+//
+// 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.rpc;
+
+option go_package = "google.golang.org/genproto/googleapis/rpc/code;code";
+option java_multiple_files = true;
+option java_outer_classname = "CodeProto";
+option java_package = "com.google.rpc";
+option objc_class_prefix = "RPC";
+
+// The canonical error codes for gRPC APIs.
+//
+//
+// Sometimes multiple error codes may apply. Services should return
+// the most specific error code that applies. For example, prefer
+// `OUT_OF_RANGE` over `FAILED_PRECONDITION` if both codes apply.
+// Similarly prefer `NOT_FOUND` or `ALREADY_EXISTS` over `FAILED_PRECONDITION`.
+enum Code {
+ // Not an error; returned on success.
+ //
+ // HTTP Mapping: 200 OK
+ OK = 0;
+
+ // The operation was cancelled, typically by the caller.
+ //
+ // HTTP Mapping: 499 Client Closed Request
+ CANCELLED = 1;
+
+ // Unknown error. For example, this error may be returned when
+ // a `Status` value received from another address space belongs to
+ // an error space that is not known in this address space. Also
+ // errors raised by APIs that do not return enough error information
+ // may be converted to this error.
+ //
+ // HTTP Mapping: 500 Internal Server Error
+ UNKNOWN = 2;
+
+ // The client specified an invalid argument. Note that this differs
+ // from `FAILED_PRECONDITION`. `INVALID_ARGUMENT` indicates arguments
+ // that are problematic regardless of the state of the system
+ // (e.g., a malformed file name).
+ //
+ // HTTP Mapping: 400 Bad Request
+ INVALID_ARGUMENT = 3;
+
+ // The deadline expired before the operation could complete. For operations
+ // that change the state of the system, this error may be returned
+ // even if the operation has completed successfully. For example, a
+ // successful response from a server could have been delayed long
+ // enough for the deadline to expire.
+ //
+ // HTTP Mapping: 504 Gateway Timeout
+ DEADLINE_EXCEEDED = 4;
+
+ // Some requested entity (e.g., file or directory) was not found.
+ //
+ // Note to server developers: if a request is denied for an entire class
+ // of users, such as gradual feature rollout or undocumented allowlist,
+ // `NOT_FOUND` may be used. If a request is denied for some users within
+ // a class of users, such as user-based access control, `PERMISSION_DENIED`
+ // must be used.
+ //
+ // HTTP Mapping: 404 Not Found
+ NOT_FOUND = 5;
+
+ // The entity that a client attempted to create (e.g., file or directory)
+ // already exists.
+ //
+ // HTTP Mapping: 409 Conflict
+ ALREADY_EXISTS = 6;
+
+ // The caller does not have permission to execute the specified
+ // operation. `PERMISSION_DENIED` must not be used for rejections
+ // caused by exhausting some resource (use `RESOURCE_EXHAUSTED`
+ // instead for those errors). `PERMISSION_DENIED` must not be
+ // used if the caller can not be identified (use `UNAUTHENTICATED`
+ // instead for those errors). This error code does not imply the
+ // request is valid or the requested entity exists or satisfies
+ // other pre-conditions.
+ //
+ // HTTP Mapping: 403 Forbidden
+ PERMISSION_DENIED = 7;
+
+ // The request does not have valid authentication credentials for the
+ // operation.
+ //
+ // HTTP Mapping: 401 Unauthorized
+ UNAUTHENTICATED = 16;
+
+ // Some resource has been exhausted, perhaps a per-user quota, or
+ // perhaps the entire file system is out of space.
+ //
+ // HTTP Mapping: 429 Too Many Requests
+ RESOURCE_EXHAUSTED = 8;
+
+ // The operation was rejected because the system is not in a state
+ // required for the operation's execution. For example, the directory
+ // to be deleted is non-empty, an rmdir operation is applied to
+ // a non-directory, etc.
+ //
+ // Service implementors can use the following guidelines to decide
+ // between `FAILED_PRECONDITION`, `ABORTED`, and `UNAVAILABLE`:
+ // (a) Use `UNAVAILABLE` if the client can retry just the failing call.
+ // (b) Use `ABORTED` if the client should retry at a higher level. For
+ // example, when a client-specified test-and-set fails, indicating the
+ // client should restart a read-modify-write sequence.
+ // (c) Use `FAILED_PRECONDITION` if the client should not retry until
+ // the system state has been explicitly fixed. For example, if an "rmdir"
+ // fails because the directory is non-empty, `FAILED_PRECONDITION`
+ // should be returned since the client should not retry unless
+ // the files are deleted from the directory.
+ //
+ // HTTP Mapping: 400 Bad Request
+ FAILED_PRECONDITION = 9;
+
+ // The operation was aborted, typically due to a concurrency issue such as
+ // a sequencer check failure or transaction abort.
+ //
+ // See the guidelines above for deciding between `FAILED_PRECONDITION`,
+ // `ABORTED`, and `UNAVAILABLE`.
+ //
+ // HTTP Mapping: 409 Conflict
+ ABORTED = 10;
+
+ // The operation was attempted past the valid range. E.g., seeking or
+ // reading past end-of-file.
+ //
+ // Unlike `INVALID_ARGUMENT`, this error indicates a problem that may
+ // be fixed if the system state changes. For example, a 32-bit file
+ // system will generate `INVALID_ARGUMENT` if asked to read at an
+ // offset that is not in the range [0,2^32-1], but it will generate
+ // `OUT_OF_RANGE` if asked to read from an offset past the current
+ // file size.
+ //
+ // There is a fair bit of overlap between `FAILED_PRECONDITION` and
+ // `OUT_OF_RANGE`. We recommend using `OUT_OF_RANGE` (the more specific
+ // error) when it applies so that callers who are iterating through
+ // a space can easily look for an `OUT_OF_RANGE` error to detect when
+ // they are done.
+ //
+ // HTTP Mapping: 400 Bad Request
+ OUT_OF_RANGE = 11;
+
+ // The operation is not implemented or is not supported/enabled in this
+ // service.
+ //
+ // HTTP Mapping: 501 Not Implemented
+ UNIMPLEMENTED = 12;
+
+ // Internal errors. This means that some invariants expected by the
+ // underlying system have been broken. This error code is reserved
+ // for serious errors.
+ //
+ // HTTP Mapping: 500 Internal Server Error
+ INTERNAL = 13;
+
+ // The service is currently unavailable. This is most likely a
+ // transient condition, which can be corrected by retrying with
+ // a backoff. Note that it is not always safe to retry
+ // non-idempotent operations.
+ //
+ // See the guidelines above for deciding between `FAILED_PRECONDITION`,
+ // `ABORTED`, and `UNAVAILABLE`.
+ //
+ // HTTP Mapping: 503 Service Unavailable
+ UNAVAILABLE = 14;
+
+ // Unrecoverable data loss or corruption.
+ //
+ // HTTP Mapping: 500 Internal Server Error
+ DATA_LOSS = 15;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/error_details.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/error_details.proto
new file mode 100644
index 00000000..4f9ecff0
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/error_details.proto
@@ -0,0 +1,363 @@
+// 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
+//
+// 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.rpc;
+
+import "google/protobuf/duration.proto";
+
+option go_package = "google.golang.org/genproto/googleapis/rpc/errdetails;errdetails";
+option java_multiple_files = true;
+option java_outer_classname = "ErrorDetailsProto";
+option java_package = "com.google.rpc";
+option objc_class_prefix = "RPC";
+
+// Describes the cause of the error with structured details.
+//
+// Example of an error when contacting the "pubsub.googleapis.com" API when it
+// is not enabled:
+//
+// { "reason": "API_DISABLED"
+// "domain": "googleapis.com"
+// "metadata": {
+// "resource": "projects/123",
+// "service": "pubsub.googleapis.com"
+// }
+// }
+//
+// This response indicates that the pubsub.googleapis.com API is not enabled.
+//
+// Example of an error that is returned when attempting to create a Spanner
+// instance in a region that is out of stock:
+//
+// { "reason": "STOCKOUT"
+// "domain": "spanner.googleapis.com",
+// "metadata": {
+// "availableRegions": "us-central1,us-east2"
+// }
+// }
+message ErrorInfo {
+ // The reason of the error. This is a constant value that identifies the
+ // proximate cause of the error. Error reasons are unique within a particular
+ // domain of errors. This should be at most 63 characters and match a
+ // regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`, which represents
+ // UPPER_SNAKE_CASE.
+ string reason = 1;
+
+ // The logical grouping to which the "reason" belongs. The error domain
+ // is typically the registered service name of the tool or product that
+ // generates the error. Example: "pubsub.googleapis.com". If the error is
+ // generated by some common infrastructure, the error domain must be a
+ // globally unique value that identifies the infrastructure. For Google API
+ // infrastructure, the error domain is "googleapis.com".
+ string domain = 2;
+
+ // Additional structured details about this error.
+ //
+ // Keys must match a regular expression of `[a-z][a-zA-Z0-9-_]+` but should
+ // ideally be lowerCamelCase. Also, they must be limited to 64 characters in
+ // length. When identifying the current value of an exceeded limit, the units
+ // should be contained in the key, not the value. For example, rather than
+ // `{"instanceLimit": "100/request"}`, should be returned as,
+ // `{"instanceLimitPerRequest": "100"}`, if the client exceeds the number of
+ // instances that can be created in a single (batch) request.
+ map metadata = 3;
+}
+
+// Describes when the clients can retry a failed request. Clients could ignore
+// the recommendation here or retry when this information is missing from error
+// responses.
+//
+// It's always recommended that clients should use exponential backoff when
+// retrying.
+//
+// Clients should wait until `retry_delay` amount of time has passed since
+// receiving the error response before retrying. If retrying requests also
+// fail, clients should use an exponential backoff scheme to gradually increase
+// the delay between retries based on `retry_delay`, until either a maximum
+// number of retries have been reached or a maximum retry delay cap has been
+// reached.
+message RetryInfo {
+ // Clients should wait at least this long between retrying the same request.
+ google.protobuf.Duration retry_delay = 1;
+}
+
+// Describes additional debugging info.
+message DebugInfo {
+ // The stack trace entries indicating where the error occurred.
+ repeated string stack_entries = 1;
+
+ // Additional debugging information provided by the server.
+ string detail = 2;
+}
+
+// Describes how a quota check failed.
+//
+// For example if a daily limit was exceeded for the calling project,
+// a service could respond with a QuotaFailure detail containing the project
+// id and the description of the quota limit that was exceeded. If the
+// calling project hasn't enabled the service in the developer console, then
+// a service could respond with the project id and set `service_disabled`
+// to true.
+//
+// Also see RetryInfo and Help types for other details about handling a
+// quota failure.
+message QuotaFailure {
+ // A message type used to describe a single quota violation. For example, a
+ // daily quota or a custom quota that was exceeded.
+ message Violation {
+ // The subject on which the quota check failed.
+ // For example, "clientip:" or "project:".
+ string subject = 1;
+
+ // A description of how the quota check failed. Clients can use this
+ // description to find more about the quota configuration in the service's
+ // public documentation, or find the relevant quota limit to adjust through
+ // developer console.
+ //
+ // For example: "Service disabled" or "Daily Limit for read operations
+ // exceeded".
+ string description = 2;
+
+ // The API Service from which the `QuotaFailure.Violation` orginates. In
+ // some cases, Quota issues originate from an API Service other than the one
+ // that was called. In other words, a dependency of the called API Service
+ // could be the cause of the `QuotaFailure`, and this field would have the
+ // dependency API service name.
+ //
+ // For example, if the called API is Kubernetes Engine API
+ // (container.googleapis.com), and a quota violation occurs in the
+ // Kubernetes Engine API itself, this field would be
+ // "container.googleapis.com". On the other hand, if the quota violation
+ // occurs when the Kubernetes Engine API creates VMs in the Compute Engine
+ // API (compute.googleapis.com), this field would be
+ // "compute.googleapis.com".
+ string api_service = 3;
+
+ // The metric of the violated quota. A quota metric is a named counter to
+ // measure usage, such as API requests or CPUs. When an activity occurs in a
+ // service, such as Virtual Machine allocation, one or more quota metrics
+ // may be affected.
+ //
+ // For example, "compute.googleapis.com/cpus_per_vm_family",
+ // "storage.googleapis.com/internet_egress_bandwidth".
+ string quota_metric = 4;
+
+ // The id of the violated quota. Also know as "limit name", this is the
+ // unique identifier of a quota in the context of an API service.
+ //
+ // For example, "CPUS-PER-VM-FAMILY-per-project-region".
+ string quota_id = 5;
+
+ // The dimensions of the violated quota. Every non-global quota is enforced
+ // on a set of dimensions. While quota metric defines what to count, the
+ // dimensions specify for what aspects the counter should be increased.
+ //
+ // For example, the quota "CPUs per region per VM family" enforces a limit
+ // on the metric "compute.googleapis.com/cpus_per_vm_family" on dimensions
+ // "region" and "vm_family". And if the violation occurred in region
+ // "us-central1" and for VM family "n1", the quota_dimensions would be,
+ //
+ // {
+ // "region": "us-central1",
+ // "vm_family": "n1",
+ // }
+ //
+ // When a quota is enforced globally, the quota_dimensions would always be
+ // empty.
+ map quota_dimensions = 6;
+
+ // The enforced quota value at the time of the `QuotaFailure`.
+ //
+ // For example, if the enforced quota value at the time of the
+ // `QuotaFailure` on the number of CPUs is "10", then the value of this
+ // field would reflect this quantity.
+ int64 quota_value = 7;
+
+ // The new quota value being rolled out at the time of the violation. At the
+ // completion of the rollout, this value will be enforced in place of
+ // quota_value. If no rollout is in progress at the time of the violation,
+ // this field is not set.
+ //
+ // For example, if at the time of the violation a rollout is in progress
+ // changing the number of CPUs quota from 10 to 20, 20 would be the value of
+ // this field.
+ optional int64 future_quota_value = 8;
+ }
+
+ // Describes all quota violations.
+ repeated Violation violations = 1;
+}
+
+// Describes what preconditions have failed.
+//
+// For example, if an RPC failed because it required the Terms of Service to be
+// acknowledged, it could list the terms of service violation in the
+// PreconditionFailure message.
+message PreconditionFailure {
+ // A message type used to describe a single precondition failure.
+ message Violation {
+ // The type of PreconditionFailure. We recommend using a service-specific
+ // enum type to define the supported precondition violation subjects. For
+ // example, "TOS" for "Terms of Service violation".
+ string type = 1;
+
+ // The subject, relative to the type, that failed.
+ // For example, "google.com/cloud" relative to the "TOS" type would indicate
+ // which terms of service is being referenced.
+ string subject = 2;
+
+ // A description of how the precondition failed. Developers can use this
+ // description to understand how to fix the failure.
+ //
+ // For example: "Terms of service not accepted".
+ string description = 3;
+ }
+
+ // Describes all precondition violations.
+ repeated Violation violations = 1;
+}
+
+// Describes violations in a client request. This error type focuses on the
+// syntactic aspects of the request.
+message BadRequest {
+ // A message type used to describe a single bad request field.
+ message FieldViolation {
+ // A path that leads to a field in the request body. The value will be a
+ // sequence of dot-separated identifiers that identify a protocol buffer
+ // field.
+ //
+ // Consider the following:
+ //
+ // message CreateContactRequest {
+ // message EmailAddress {
+ // enum Type {
+ // TYPE_UNSPECIFIED = 0;
+ // HOME = 1;
+ // WORK = 2;
+ // }
+ //
+ // optional string email = 1;
+ // repeated EmailType type = 2;
+ // }
+ //
+ // string full_name = 1;
+ // repeated EmailAddress email_addresses = 2;
+ // }
+ //
+ // In this example, in proto `field` could take one of the following values:
+ //
+ // * `full_name` for a violation in the `full_name` value
+ // * `email_addresses[1].email` for a violation in the `email` field of the
+ // first `email_addresses` message
+ // * `email_addresses[3].type[2]` for a violation in the second `type`
+ // value in the third `email_addresses` message.
+ //
+ // In JSON, the same values are represented as:
+ //
+ // * `fullName` for a violation in the `fullName` value
+ // * `emailAddresses[1].email` for a violation in the `email` field of the
+ // first `emailAddresses` message
+ // * `emailAddresses[3].type[2]` for a violation in the second `type`
+ // value in the third `emailAddresses` message.
+ string field = 1;
+
+ // A description of why the request element is bad.
+ string description = 2;
+
+ // The reason of the field-level error. This is a constant value that
+ // identifies the proximate cause of the field-level error. It should
+ // uniquely identify the type of the FieldViolation within the scope of the
+ // google.rpc.ErrorInfo.domain. This should be at most 63
+ // characters and match a regular expression of `[A-Z][A-Z0-9_]+[A-Z0-9]`,
+ // which represents UPPER_SNAKE_CASE.
+ string reason = 3;
+
+ // Provides a localized error message for field-level errors that is safe to
+ // return to the API consumer.
+ LocalizedMessage localized_message = 4;
+ }
+
+ // Describes all violations in a client request.
+ repeated FieldViolation field_violations = 1;
+}
+
+// Contains metadata about the request that clients can attach when filing a bug
+// or providing other forms of feedback.
+message RequestInfo {
+ // An opaque string that should only be interpreted by the service generating
+ // it. For example, it can be used to identify requests in the service's logs.
+ string request_id = 1;
+
+ // Any data that was used to serve this request. For example, an encrypted
+ // stack trace that can be sent back to the service provider for debugging.
+ string serving_data = 2;
+}
+
+// Describes the resource that is being accessed.
+message ResourceInfo {
+ // A name for the type of resource being accessed, e.g. "sql table",
+ // "cloud storage bucket", "file", "Google calendar"; or the type URL
+ // of the resource: e.g. "type.googleapis.com/google.pubsub.v1.Topic".
+ string resource_type = 1;
+
+ // The name of the resource being accessed. For example, a shared calendar
+ // name: "example.com_4fghdhgsrgh@group.calendar.google.com", if the current
+ // error is
+ // [google.rpc.Code.PERMISSION_DENIED][google.rpc.Code.PERMISSION_DENIED].
+ string resource_name = 2;
+
+ // The owner of the resource (optional).
+ // For example, "user:" or "project:".
+ string owner = 3;
+
+ // Describes what error is encountered when accessing this resource.
+ // For example, updating a cloud project may require the `writer` permission
+ // on the developer console project.
+ string description = 4;
+}
+
+// Provides links to documentation or for performing an out of band action.
+//
+// For example, if a quota check failed with an error indicating the calling
+// project hasn't enabled the accessed service, this can contain a URL pointing
+// directly to the right place in the developer console to flip the bit.
+message Help {
+ // Describes a URL link.
+ message Link {
+ // Describes what the link offers.
+ string description = 1;
+
+ // The URL of the link.
+ string url = 2;
+ }
+
+ // URL(s) pointing to additional information on handling the current error.
+ repeated Link links = 1;
+}
+
+// Provides a localized error message that is safe to return to the user
+// which can be attached to an RPC error.
+message LocalizedMessage {
+ // The locale used following the specification defined at
+ // https://www.rfc-editor.org/rfc/bcp/bcp47.txt.
+ // Examples are: "en-US", "fr-CH", "es-MX"
+ string locale = 1;
+
+ // The localized error message in the above locale.
+ string message = 2;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/http.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/http.proto
new file mode 100644
index 00000000..ba59c2b7
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/http.proto
@@ -0,0 +1,64 @@
+// 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
+//
+// 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.rpc;
+
+option go_package = "google.golang.org/genproto/googleapis/rpc/http;http";
+option java_multiple_files = true;
+option java_outer_classname = "HttpProto";
+option java_package = "com.google.rpc";
+option objc_class_prefix = "RPC";
+
+// Represents an HTTP request.
+message HttpRequest {
+ // The HTTP request method.
+ string method = 1;
+
+ // The HTTP request URI.
+ string uri = 2;
+
+ // The HTTP request headers. The ordering of the headers is significant.
+ // Multiple headers with the same key may present for the request.
+ repeated HttpHeader headers = 3;
+
+ // The HTTP request body. If the body is not expected, it should be empty.
+ bytes body = 4;
+}
+
+// Represents an HTTP response.
+message HttpResponse {
+ // The HTTP status code, such as 200 or 404.
+ int32 status = 1;
+
+ // The HTTP reason phrase, such as "OK" or "Not Found".
+ string reason = 2;
+
+ // The HTTP response headers. The ordering of the headers is significant.
+ // Multiple headers with the same key may present for the response.
+ repeated HttpHeader headers = 3;
+
+ // The HTTP response body. If the body is not expected, it should be empty.
+ bytes body = 4;
+}
+
+// Represents an HTTP header.
+message HttpHeader {
+ // The HTTP header key. It is case insensitive.
+ string key = 1;
+
+ // The HTTP header value.
+ string value = 2;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/rpc_publish.yaml b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/rpc_publish.yaml
new file mode 100644
index 00000000..90a91e07
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/rpc_publish.yaml
@@ -0,0 +1,28 @@
+type: google.api.Service
+config_version: 1
+name: rpc.googleapis.com
+title: Google RPC Types
+
+types:
+- name: google.rpc.Status
+- name: google.rpc.RetryInfo
+- name: google.rpc.DebugInfo
+- name: google.rpc.QuotaFailure
+- name: google.rpc.BadRequest
+- name: google.rpc.PreconditionFailure
+- name: google.rpc.RequestInfo
+- name: google.rpc.ResourceInfo
+- name: google.rpc.Help
+- name: google.rpc.LocalizedMessage
+
+enums:
+- name: google.rpc.Code
+
+documentation:
+ summary: Defines RPC types.
+ overview: |-
+ # Google RPC
+
+ This package contains type definitions for general RPC systems. While
+ [gRPC](https://github.com/grpc) is using these defintions, they are not
+ designed specifically to support gRPC.
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/status.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/status.proto
new file mode 100644
index 00000000..dc14c943
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/rpc/status.proto
@@ -0,0 +1,49 @@
+// 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
+//
+// 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.rpc;
+
+import "google/protobuf/any.proto";
+
+option cc_enable_arenas = true;
+option go_package = "google.golang.org/genproto/googleapis/rpc/status;status";
+option java_multiple_files = true;
+option java_outer_classname = "StatusProto";
+option java_package = "com.google.rpc";
+option objc_class_prefix = "RPC";
+
+// The `Status` type defines a logical error model that is suitable for
+// different programming environments, including REST APIs and RPC APIs. It is
+// used by [gRPC](https://github.com/grpc). Each `Status` message contains
+// three pieces of data: error code, error message, and error details.
+//
+// You can find out more about this error model and how to work with it in the
+// [API Design Guide](https://cloud.google.com/apis/design/errors).
+message Status {
+ // The status code, which should be an enum value of
+ // [google.rpc.Code][google.rpc.Code].
+ int32 code = 1;
+
+ // A developer-facing error message, which should be in English. Any
+ // user-facing error message should be localized and sent in the
+ // [google.rpc.Status.details][google.rpc.Status.details] field, or localized
+ // by the client.
+ string message = 2;
+
+ // A list of messages that carry the error details. There is a common set of
+ // message types for APIs to use.
+ repeated google.protobuf.Any details = 3;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/BUILD.bazel
new file mode 100644
index 00000000..a87c57fe
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/BUILD.bazel
@@ -0,0 +1 @@
+exports_files(glob(["*.yaml"]))
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/BUILD.bazel
new file mode 100644
index 00000000..541f34cf
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/BUILD.bazel
@@ -0,0 +1,380 @@
+# This file was automatically generated by BuildFileGenerator
+# https://github.com/googleapis/rules_gapic/tree/master/bazel
+
+# Most of the manual changes to this file will be overwritten.
+# It's **only** allowed to change the following rule attribute values:
+# - names of *_gapic_assembly_* rules
+# - certain parameters of *_gapic_library rules, including but not limited to:
+# * extra_protoc_parameters
+# * extra_protoc_file_parameters
+# The complete list of preserved parameters can be found in the source code.
+
+# buildifier: disable=load-on-top
+
+# This is an API workspace, having public visibility by default makes perfect sense.
+package(default_visibility = ["//visibility:public"])
+
+##############################################################################
+# Common
+##############################################################################
+# buildifier: disable=same-origin-load
+load("@com_google_googleapis_imports//:imports.bzl", "proto_library_with_info")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+proto_library(
+ name = "adapter_proto",
+ srcs = [
+ "adapter.proto",
+ ],
+ deps = [
+ "//google/api:annotations_proto",
+ "//google/api:client_proto",
+ "//google/api:field_behavior_proto",
+ "//google/api:resource_proto",
+ ],
+)
+
+proto_library_with_info(
+ name = "adapter_proto_with_info",
+ deps = [
+ ":adapter_proto",
+ "//google/cloud:common_resources_proto",
+ ],
+)
+
+##############################################################################
+# Java
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "java_gapic_assembly_gradle_pkg",
+ "java_gapic_library",
+ "java_gapic_test",
+ "java_grpc_library",
+ "java_proto_library",
+)
+
+java_proto_library(
+ name = "adapter_java_proto",
+ deps = [":adapter_proto"],
+)
+
+java_grpc_library(
+ name = "adapter_java_grpc",
+ srcs = [":adapter_proto"],
+ deps = [":adapter_java_proto"],
+)
+
+java_gapic_library(
+ name = "adapter_java_gapic",
+ srcs = [":adapter_proto_with_info"],
+ gapic_yaml = None,
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ test_deps = [
+ ":adapter_java_grpc",
+ ],
+ transport = "grpc+rest",
+ deps = [
+ ":adapter_java_proto",
+ "//google/api:api_java_proto",
+ ],
+)
+
+java_gapic_test(
+ name = "adapter_java_gapic_test_suite",
+ test_classes = [
+ "com.google.spanner.adapter.v1.AdapterClientHttpJsonTest",
+ "com.google.spanner.adapter.v1.AdapterClientTest",
+ ],
+ runtime_deps = [":adapter_java_gapic_test"],
+)
+
+# Open Source Packages
+java_gapic_assembly_gradle_pkg(
+ name = "google-cloud-spanner-adapter-v1-java",
+ include_samples = True,
+ transport = "grpc+rest",
+ deps = [
+ ":adapter_java_gapic",
+ ":adapter_java_grpc",
+ ":adapter_java_proto",
+ ":adapter_proto",
+ ],
+)
+
+##############################################################################
+# Go
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "go_gapic_assembly_pkg",
+ "go_gapic_library",
+ "go_proto_library",
+)
+
+go_proto_library(
+ name = "adapter_go_proto",
+ compilers = ["@io_bazel_rules_go//proto:go_grpc"],
+ importpath = "cloud.google.com/go/spanner/adapter/apiv1/adapterpb",
+ protos = [":adapter_proto"],
+ deps = [
+ "//google/api:annotations_go_proto",
+ ],
+)
+
+go_gapic_library(
+ name = "adapter_go_gapic",
+ srcs = [":adapter_proto_with_info"],
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ importpath = "cloud.google.com/go/spanner/adapter/apiv1;adapter",
+ metadata = True,
+ release_level = "beta",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":adapter_go_proto",
+ ],
+)
+
+# Open Source Packages
+go_gapic_assembly_pkg(
+ name = "gapi-cloud-spanner-adapter-v1-go",
+ deps = [
+ ":adapter_go_gapic",
+ ":adapter_go_gapic_srcjar-metadata.srcjar",
+ ":adapter_go_gapic_srcjar-snippets.srcjar",
+ ":adapter_go_gapic_srcjar-test.srcjar",
+ ":adapter_go_proto",
+ ],
+)
+
+##############################################################################
+# Python
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "py_gapic_assembly_pkg",
+ "py_gapic_library",
+ "py_test",
+)
+
+py_gapic_library(
+ name = "adapter_py_gapic",
+ srcs = [":adapter_proto"],
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ],
+)
+
+py_test(
+ name = "adapter_py_gapic_test",
+ srcs = [
+ "adapter_py_gapic_pytest.py",
+ "adapter_py_gapic_test.py",
+ ],
+ legacy_create_init = False,
+ deps = [":adapter_py_gapic"],
+)
+
+# Open Source Packages
+py_gapic_assembly_pkg(
+ name = "spanner-adapter-v1-py",
+ deps = [
+ ":adapter_py_gapic",
+ ],
+)
+
+##############################################################################
+# PHP
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "php_gapic_assembly_pkg",
+ "php_gapic_library",
+ "php_proto_library",
+)
+
+php_proto_library(
+ name = "adapter_php_proto",
+ deps = [":adapter_proto"],
+)
+
+php_gapic_library(
+ name = "adapter_php_gapic",
+ srcs = [":adapter_proto_with_info"],
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ migration_mode = "NEW_SURFACE_ONLY",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":adapter_php_proto",
+ ],
+)
+
+# Open Source Packages
+php_gapic_assembly_pkg(
+ name = "google-cloud-spanner-adapter-v1-php",
+ deps = [
+ ":adapter_php_gapic",
+ ":adapter_php_proto",
+ ],
+)
+
+##############################################################################
+# Node.js
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "nodejs_gapic_assembly_pkg",
+ "nodejs_gapic_library",
+)
+
+nodejs_gapic_library(
+ name = "adapter_nodejs_gapic",
+ package_name = "@google-cloud/adapter",
+ src = ":adapter_proto_with_info",
+ extra_protoc_parameters = ["metadata"],
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ package = "google.spanner.adapter.v1",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [],
+)
+
+nodejs_gapic_assembly_pkg(
+ name = "spanner-adapter-v1-nodejs",
+ deps = [
+ ":adapter_nodejs_gapic",
+ ":adapter_proto",
+ ],
+)
+
+##############################################################################
+# Ruby
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "ruby_cloud_gapic_library",
+ "ruby_gapic_assembly_pkg",
+ "ruby_grpc_library",
+ "ruby_proto_library",
+)
+
+ruby_proto_library(
+ name = "adapter_ruby_proto",
+ deps = [":adapter_proto"],
+)
+
+ruby_grpc_library(
+ name = "adapter_ruby_grpc",
+ srcs = [":adapter_proto"],
+ deps = [":adapter_ruby_proto"],
+)
+
+ruby_cloud_gapic_library(
+ name = "adapter_ruby_gapic",
+ srcs = [":adapter_proto_with_info"],
+ extra_protoc_parameters = ["ruby-cloud-gem-name=google-cloud-spanner-adapter-v1"],
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":adapter_ruby_grpc",
+ ":adapter_ruby_proto",
+ ],
+)
+
+# Open Source Packages
+ruby_gapic_assembly_pkg(
+ name = "google-cloud-spanner-adapter-v1-ruby",
+ deps = [
+ ":adapter_ruby_gapic",
+ ":adapter_ruby_grpc",
+ ":adapter_ruby_proto",
+ ],
+)
+
+##############################################################################
+# C#
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "csharp_gapic_assembly_pkg",
+ "csharp_gapic_library",
+ "csharp_grpc_library",
+ "csharp_proto_library",
+)
+
+csharp_proto_library(
+ name = "adapter_csharp_proto",
+ extra_opts = [],
+ deps = [":adapter_proto"],
+)
+
+csharp_grpc_library(
+ name = "adapter_csharp_grpc",
+ srcs = [":adapter_proto"],
+ deps = [":adapter_csharp_proto"],
+)
+
+csharp_gapic_library(
+ name = "adapter_csharp_gapic",
+ srcs = [":adapter_proto_with_info"],
+ common_resources_config = "@gax_dotnet//:Google.Api.Gax/ResourceNames/CommonResourcesConfig.json",
+ grpc_service_config = "spanner_adapter_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":adapter_csharp_grpc",
+ ":adapter_csharp_proto",
+ ],
+)
+
+# Open Source Packages
+csharp_gapic_assembly_pkg(
+ name = "google-cloud-spanner-adapter-v1-csharp",
+ deps = [
+ ":adapter_csharp_gapic",
+ ":adapter_csharp_grpc",
+ ":adapter_csharp_proto",
+ ],
+)
+
+##############################################################################
+# C++
+##############################################################################
+# buildifier: disable=same-origin-load
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "cc_grpc_library",
+ "cc_proto_library",
+)
+
+cc_proto_library(
+ name = "adapter_cc_proto",
+ deps = [":adapter_proto"],
+)
+
+cc_grpc_library(
+ name = "adapter_cc_grpc",
+ srcs = [":adapter_proto"],
+ grpc_only = True,
+ deps = [":adapter_cc_proto"],
+)
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/adapter.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/adapter.proto
new file mode 100644
index 00000000..bc3afa35
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/adapter.proto
@@ -0,0 +1,123 @@
+// 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
+//
+// 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.adapter.v1;
+
+import "google/api/annotations.proto";
+import "google/api/client.proto";
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Adapter.V1";
+option go_package = "cloud.google.com/go/spanner/adapter/apiv1/adapterpb;adapterpb";
+option java_multiple_files = true;
+option java_outer_classname = "AdapterProto";
+option java_package = "com.google.spanner.adapter.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Adapter\\V1";
+option ruby_package = "Google::Cloud::Spanner::Adapter::V1";
+option (google.api.resource_definition) = {
+ type: "spanner.googleapis.com/Database"
+ pattern: "projects/{project}/instances/{instance}/databases/{database}"
+};
+
+// Cloud Spanner Adapter API
+//
+// The Cloud Spanner Adapter service allows native drivers of supported database
+// dialects to interact directly with Cloud Spanner by wrapping the underlying
+// wire protocol used by the driver in a gRPC stream.
+service Adapter {
+ option (google.api.default_host) = "spanner.googleapis.com";
+ option (google.api.oauth_scopes) =
+ "https://www.googleapis.com/auth/cloud-platform,"
+ "https://www.googleapis.com/auth/spanner.data";
+
+ // Creates a new session to be used for requests made by the adapter.
+ // A session identifies a specific incarnation of a database resource and is
+ // meant to be reused across many `AdaptMessage` calls.
+ rpc CreateSession(CreateSessionRequest) returns (Session) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*/databases/*}/sessions:adapter"
+ body: "session"
+ };
+ option (google.api.method_signature) = "parent,session";
+ }
+
+ // Handles a single message from the client and returns the result as a
+ // stream. The server will interpret the message frame and respond with
+ // message frames to the client.
+ rpc AdaptMessage(AdaptMessageRequest) returns (stream AdaptMessageResponse) {
+ option (google.api.http) = {
+ post: "/v1/{name=projects/*/instances/*/databases/*/sessions/*}:adaptMessage"
+ body: "*"
+ };
+ }
+}
+
+// Message sent by the client to the adapter.
+message AdaptMessageRequest {
+ // Required. The database session in which the adapter request is processed.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Session" }
+ ];
+
+ // Required. Identifier for the underlying wire protocol.
+ string protocol = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. Uninterpreted bytes from the underlying wire protocol.
+ bytes payload = 3 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. Opaque request state passed by the client to the server.
+ map attachments = 4 [(google.api.field_behavior) = OPTIONAL];
+}
+
+// Message sent by the adapter to the client.
+message AdaptMessageResponse {
+ // Optional. Uninterpreted bytes from the underlying wire protocol.
+ bytes payload = 1 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. Opaque state updates to be applied by the client.
+ map state_updates = 2
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// A session in the Cloud Spanner Adapter API.
+message Session {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/Session"
+ pattern: "projects/{project}/instances/{instance}/databases/{database}/sessions/{session}"
+ plural: "sessions"
+ singular: "session"
+ };
+
+ // Identifier. The name of the session. This is always system-assigned.
+ string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+}
+
+// The request for
+// [CreateSessionRequest][Adapter.CreateSessionRequest].
+message CreateSessionRequest {
+ // Required. The database in which the new session is created.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Required. The session to create.
+ Session session = 2 [(google.api.field_behavior) = REQUIRED];
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/spanner.yaml b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/spanner.yaml
new file mode 100644
index 00000000..dad94006
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/spanner.yaml
@@ -0,0 +1,69 @@
+type: google.api.Service
+config_version: 3
+name: spanner.googleapis.com
+title: Cloud Spanner API
+
+apis:
+- name: google.spanner.adapter.v1.Adapter
+
+documentation:
+ summary: |-
+ Cloud Spanner is a managed, mission-critical, globally consistent and
+ scalable relational database service.
+
+http:
+ rules:
+ - selector: google.longrunning.Operations.CancelOperation
+ post: '/v1/{name=projects/*/instances/*/databases/*/operations/*}:cancel'
+ additional_bindings:
+ - post: '/v1/{name=projects/*/instances/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instances/*/backups/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instanceConfigs/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}:cancel'
+ - selector: google.longrunning.Operations.DeleteOperation
+ delete: '/v1/{name=projects/*/instances/*/databases/*/operations/*}'
+ additional_bindings:
+ - delete: '/v1/{name=projects/*/instances/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instances/*/backups/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instanceConfigs/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}'
+ - selector: google.longrunning.Operations.GetOperation
+ get: '/v1/{name=projects/*/instances/*/databases/*/operations/*}'
+ additional_bindings:
+ - get: '/v1/{name=projects/*/instances/*/operations/*}'
+ - get: '/v1/{name=projects/*/instances/*/backups/*/operations/*}'
+ - get: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/operations/*}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}'
+ - selector: google.longrunning.Operations.ListOperations
+ get: '/v1/{name=projects/*/instances/*/databases/*/operations}'
+ additional_bindings:
+ - get: '/v1/{name=projects/*/instances/*/operations}'
+ - get: '/v1/{name=projects/*/instances/*/backups/*/operations}'
+ - get: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/operations}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations}'
+
+authentication:
+ rules:
+ - selector: 'google.longrunning.Operations.*'
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.admin
+ - selector: google.spanner.adapter.v1.Adapter.AdaptMessage
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.data
+ - selector: google.spanner.adapter.v1.Adapter.CreateSession
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.data
+
+publishing:
+ new_issue_uri: https://issuetracker.google.com/issues/new?component=190851&template=0
+ documentation_uri: https://cloud.google.com/spanner/
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/spanner_adapter_grpc_service_config.json b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/spanner_adapter_grpc_service_config.json
new file mode 100644
index 00000000..11e16d5f
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/adapter/v1/spanner_adapter_grpc_service_config.json
@@ -0,0 +1,31 @@
+{
+ "methodConfig": [
+ {
+ "name": [
+ {
+ "service": "google.spanner.adapter.v1.Adapter",
+ "method": "AdaptMessage"
+ }
+ ],
+ "timeout": "3600s"
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.adapter.v1.Adapter",
+ "method": "CreateSession"
+ }
+ ],
+ "timeout": "30s",
+ "retryPolicy": {
+ "initialBackoff": "0.250s",
+ "maxBackoff": "32s",
+ "backoffMultiplier": 1.3,
+ "retryableStatusCodes": [
+ "UNAVAILABLE",
+ "RESOURCE_EXHAUSTED"
+ ]
+ }
+ }
+ ]
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/BUILD.bazel
new file mode 100644
index 00000000..a87c57fe
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/BUILD.bazel
@@ -0,0 +1 @@
+exports_files(glob(["*.yaml"]))
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/BUILD.bazel
new file mode 100644
index 00000000..86189f7e
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/BUILD.bazel
@@ -0,0 +1,351 @@
+# This file was automatically generated by BuildFileGenerator
+# https://github.com/googleapis/rules_gapic/tree/master/bazel
+
+# Most of the manual changes to this file will be overwritten.
+# It's **only** allowed to change the following rule attribute values:
+# - names of *_gapic_assembly_* rules
+# - certain parameters of *_gapic_library rules, including but not limited to:
+# * extra_protoc_parameters
+# * extra_protoc_file_parameters
+# The complete list of preserved parameters can be found in the source code.
+
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "cc_grpc_library",
+ "cc_proto_library",
+ "csharp_gapic_assembly_pkg",
+ "csharp_gapic_library",
+ "csharp_grpc_library",
+ "csharp_proto_library",
+ "go_gapic_assembly_pkg",
+ "go_gapic_library",
+ "go_proto_library",
+ "java_gapic_assembly_gradle_pkg",
+ "java_gapic_library",
+ "java_gapic_test",
+ "java_grpc_library",
+ "java_proto_library",
+ "nodejs_gapic_assembly_pkg",
+ "nodejs_gapic_library",
+ "php_gapic_assembly_pkg",
+ "php_gapic_library",
+ "php_proto_library",
+ "proto_library_with_info",
+ "py_gapic_assembly_pkg",
+ "py_gapic_library",
+ "py_test",
+ "ruby_cloud_gapic_library",
+ "ruby_gapic_assembly_pkg",
+ "ruby_grpc_library",
+ "ruby_proto_library",
+)
+
+##############################################################################
+# Common
+##############################################################################
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+# This is an API workspace, having public visibility by default makes perfect sense.
+package(default_visibility = ["//visibility:public"])
+
+proto_library(
+ name = "database_proto",
+ srcs = [
+ "backup.proto",
+ "backup_schedule.proto",
+ "common.proto",
+ "spanner_database_admin.proto",
+ ],
+ deps = [
+ "//google/api:annotations_proto",
+ "//google/api:client_proto",
+ "//google/api:field_behavior_proto",
+ "//google/api:resource_proto",
+ "//google/iam/v1:iam_policy_proto",
+ "//google/iam/v1:policy_proto",
+ "//google/longrunning:operations_proto",
+ "//google/rpc:status_proto",
+ "@com_google_protobuf//:duration_proto",
+ "@com_google_protobuf//:empty_proto",
+ "@com_google_protobuf//:field_mask_proto",
+ "@com_google_protobuf//:struct_proto",
+ "@com_google_protobuf//:timestamp_proto",
+ ],
+)
+
+proto_library_with_info(
+ name = "database_proto_with_info",
+ deps = [
+ ":database_proto",
+ "//google/cloud:common_resources_proto",
+ ],
+)
+
+java_proto_library(
+ name = "database_java_proto",
+ deps = [":database_proto"],
+)
+
+java_grpc_library(
+ name = "database_java_grpc",
+ srcs = [":database_proto"],
+ deps = [":database_java_proto"],
+)
+
+java_gapic_library(
+ name = "database_java_gapic",
+ srcs = [":database_proto_with_info"],
+ gapic_yaml = "spanner_gapic.yaml",
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ test_deps = [
+ ":database_java_grpc",
+ "//google/iam/v1:iam_java_grpc",
+ ],
+ transport = "grpc+rest",
+ deps = [
+ ":database_java_proto",
+ "//google/api:api_java_proto",
+ "//google/iam/v1:iam_java_proto",
+ ],
+)
+
+java_gapic_test(
+ name = "database_java_gapic_test_suite",
+ test_classes = [
+ "com.google.cloud.spanner.admin.database.v1.DatabaseAdminClientHttpJsonTest",
+ "com.google.cloud.spanner.admin.database.v1.DatabaseAdminClientTest",
+ ],
+ runtime_deps = [":database_java_gapic_test"],
+)
+
+# Open Source Packages
+java_gapic_assembly_gradle_pkg(
+ name = "google-cloud-admin-database-v1-java",
+ include_samples = True,
+ transport = "grpc+rest",
+ deps = [
+ ":database_java_gapic",
+ ":database_java_grpc",
+ ":database_java_proto",
+ ":database_proto",
+ ],
+)
+
+go_proto_library(
+ name = "database_go_proto",
+ compilers = ["@io_bazel_rules_go//proto:go_grpc"],
+ importpath = "cloud.google.com/go/spanner/admin/database/apiv1/databasepb",
+ protos = [":database_proto"],
+ deps = [
+ "//google/api:annotations_go_proto",
+ "//google/iam/v1:iam_go_proto",
+ "//google/longrunning:longrunning_go_proto",
+ "//google/rpc:status_go_proto",
+ ],
+)
+
+go_gapic_library(
+ name = "database_go_gapic",
+ srcs = [":database_proto_with_info"],
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ importpath = "cloud.google.com/go/spanner/admin/database/apiv1;database",
+ release_level = "ga",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":database_go_proto",
+ "//google/iam/v1:iam_go_proto",
+ "//google/longrunning:longrunning_go_proto",
+ "@com_google_cloud_go_longrunning//:go_default_library",
+ "@com_google_cloud_go_longrunning//autogen:go_default_library",
+ ],
+)
+
+# Open Source Packages
+go_gapic_assembly_pkg(
+ name = "gapi-cloud-admin-database-v1-go",
+ deps = [
+ ":database_go_gapic",
+ ":database_go_gapic_srcjar-snippets.srcjar",
+ ":database_go_gapic_srcjar-test.srcjar",
+ ":database_go_proto",
+ ],
+)
+
+py_gapic_library(
+ name = "database_py_gapic",
+ srcs = [":database_proto"],
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ opt_args = [
+ "python-gapic-namespace=google.cloud",
+ "python-gapic-name=spanner_admin_database",
+ ],
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ "//google/iam/v1:iam_policy_py_proto",
+ ],
+)
+
+py_test(
+ name = "database_py_gapic_test",
+ srcs = [
+ "database_py_gapic_pytest.py",
+ "database_py_gapic_test.py",
+ ],
+ legacy_create_init = False,
+ deps = [":database_py_gapic"],
+)
+
+py_gapic_assembly_pkg(
+ name = "admin-database-v1-py",
+ deps = [
+ ":database_py_gapic",
+ ],
+)
+
+php_proto_library(
+ name = "database_php_proto",
+ deps = [":database_proto"],
+)
+
+php_gapic_library(
+ name = "database_php_gapic",
+ srcs = [":database_proto_with_info"],
+ gapic_yaml = "spanner_gapic.yaml",
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ migration_mode = "MIGRATING",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [":database_php_proto"],
+)
+
+# Open Source Packages
+php_gapic_assembly_pkg(
+ name = "google-cloud-admin-database-v1-php",
+ deps = [
+ ":database_php_gapic",
+ ":database_php_proto",
+ ],
+)
+
+nodejs_gapic_library(
+ name = "database_nodejs_gapic",
+ package_name = "@google-cloud/spanner",
+ src = ":database_proto_with_info",
+ extra_protoc_parameters = [
+ "metadata",
+ "template=typescript_gapic",
+ ],
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ handwritten_layer = True,
+ package = "google.spanner.admin.database.v1",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [],
+)
+
+nodejs_gapic_assembly_pkg(
+ name = "admin-database-v1-nodejs",
+ deps = [
+ ":database_nodejs_gapic",
+ ":database_proto",
+ ],
+)
+
+ruby_proto_library(
+ name = "database_ruby_proto",
+ deps = [":database_proto"],
+)
+
+ruby_grpc_library(
+ name = "database_ruby_grpc",
+ srcs = [":database_proto"],
+ deps = [":database_ruby_proto"],
+)
+
+ruby_cloud_gapic_library(
+ name = "database_ruby_gapic",
+ srcs = [":database_proto_with_info"],
+ extra_protoc_parameters = [
+ "ruby-cloud-gem-name=google-cloud-spanner-admin-database-v1",
+ "ruby-cloud-env-prefix=SPANNER",
+ "ruby-cloud-product-url=https://cloud.google.com/spanner",
+ "ruby-cloud-api-id=spanner.googleapis.com",
+ "ruby-cloud-api-shortname=spanner",
+ "ruby-cloud-wrapper-gem-override=google-cloud-spanner",
+ ],
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ rest_numeric_enums = True,
+ ruby_cloud_description = "Cloud Spanner is a managed, mission-critical, globally consistent and scalable relational database service.",
+ ruby_cloud_title = "Cloud Spanner Database Admin V1",
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":database_ruby_grpc",
+ ":database_ruby_proto",
+ ],
+)
+
+# Open Source Packages
+ruby_gapic_assembly_pkg(
+ name = "google-cloud-admin-database-v1-ruby",
+ deps = [
+ ":database_ruby_gapic",
+ ":database_ruby_grpc",
+ ":database_ruby_proto",
+ ],
+)
+
+csharp_proto_library(
+ name = "database_csharp_proto",
+ deps = [":database_proto"],
+)
+
+csharp_grpc_library(
+ name = "database_csharp_grpc",
+ srcs = [":database_proto"],
+ deps = [":database_csharp_proto"],
+)
+
+csharp_gapic_library(
+ name = "database_csharp_gapic",
+ srcs = [":database_proto_with_info"],
+ common_resources_config = "@gax_dotnet//:Google.Api.Gax/ResourceNames/CommonResourcesConfig.json",
+ grpc_service_config = "spanner_admin_database_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":database_csharp_grpc",
+ ":database_csharp_proto",
+ ],
+)
+
+# Open Source Packages
+csharp_gapic_assembly_pkg(
+ name = "google-cloud-admin-database-v1-csharp",
+ deps = [
+ ":database_csharp_gapic",
+ ":database_csharp_grpc",
+ ":database_csharp_proto",
+ ],
+)
+
+cc_proto_library(
+ name = "database_cc_proto",
+ deps = [":database_proto"],
+)
+
+cc_grpc_library(
+ name = "database_cc_grpc",
+ srcs = [":database_proto"],
+ grpc_only = True,
+ deps = [":database_cc_proto"],
+)
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/backup.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/backup.proto
new file mode 100644
index 00000000..6898814c
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/backup.proto
@@ -0,0 +1,773 @@
+// 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
+//
+// 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.admin.database.v1;
+
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/longrunning/operations.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/timestamp.proto";
+import "google/spanner/admin/database/v1/common.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Admin.Database.V1";
+option go_package = "cloud.google.com/go/spanner/admin/database/apiv1/databasepb;databasepb";
+option java_multiple_files = true;
+option java_outer_classname = "BackupProto";
+option java_package = "com.google.spanner.admin.database.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Database\\V1";
+option ruby_package = "Google::Cloud::Spanner::Admin::Database::V1";
+
+// A backup of a Cloud Spanner database.
+message Backup {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/Backup"
+ pattern: "projects/{project}/instances/{instance}/backups/{backup}"
+ };
+
+ // Indicates the current state of the backup.
+ enum State {
+ // Not specified.
+ STATE_UNSPECIFIED = 0;
+
+ // The pending backup is still being created. Operations on the
+ // backup may fail with `FAILED_PRECONDITION` in this state.
+ CREATING = 1;
+
+ // The backup is complete and ready for use.
+ READY = 2;
+ }
+
+ // Required for the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // operation. Name of the database from which this backup was created. This
+ // needs to be in the same instance as the backup. Values are of the form
+ // `projects//instances//databases/`.
+ string database = 2 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+
+ // The backup will contain an externally consistent copy of the database at
+ // the timestamp specified by `version_time`. If `version_time` is not
+ // specified, the system will set `version_time` to the `create_time` of the
+ // backup.
+ google.protobuf.Timestamp version_time = 9;
+
+ // Required for the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // operation. The expiration time of the backup, with microseconds
+ // granularity that must be at least 6 hours and at most 366 days
+ // from the time the CreateBackup request is processed. Once the `expire_time`
+ // has passed, the backup is eligible to be automatically deleted by Cloud
+ // Spanner to free the resources used by the backup.
+ google.protobuf.Timestamp expire_time = 3;
+
+ // Output only for the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // operation. Required for the
+ // [UpdateBackup][google.spanner.admin.database.v1.DatabaseAdmin.UpdateBackup]
+ // operation.
+ //
+ // A globally unique identifier for the backup which cannot be
+ // changed. Values are of the form
+ // `projects//instances//backups/[a-z][a-z0-9_\-]*[a-z0-9]`
+ // The final segment of the name must be between 2 and 60 characters
+ // in length.
+ //
+ // The backup is stored in the location(s) specified in the instance
+ // configuration of the instance containing the backup, identified
+ // by the prefix of the backup name of the form
+ // `projects//instances/`.
+ string name = 1;
+
+ // Output only. The time the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // request is received. If the request does not specify `version_time`, the
+ // `version_time` of the backup will be equivalent to the `create_time`.
+ google.protobuf.Timestamp create_time = 4
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Size of the backup in bytes.
+ int64 size_bytes = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The number of bytes that will be freed by deleting this
+ // backup. This value will be zero if, for example, this backup is part of an
+ // incremental backup chain and younger backups in the chain require that we
+ // keep its data. For backups not in an incremental backup chain, this is
+ // always the size of the backup. This value may change if backups on the same
+ // chain get created, deleted or expired.
+ int64 freeable_size_bytes = 15 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. For a backup in an incremental backup chain, this is the
+ // storage space needed to keep the data that has changed since the previous
+ // backup. For all other backups, this is always the size of the backup. This
+ // value may change if backups on the same chain get deleted or expired.
+ //
+ // This field can be used to calculate the total storage space used by a set
+ // of backups. For example, the total space used by all backups of a database
+ // can be computed by summing up this field.
+ int64 exclusive_size_bytes = 16 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The current state of the backup.
+ State state = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The names of the restored databases that reference the backup.
+ // The database names are of
+ // the form `projects//instances//databases/`.
+ // Referencing databases may exist in different instances. The existence of
+ // any referencing database prevents the backup from being deleted. When a
+ // restored database from the backup enters the `READY` state, the reference
+ // to the backup is removed.
+ repeated string referencing_databases = 7 [
+ (google.api.field_behavior) = OUTPUT_ONLY,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Output only. The encryption information for the backup.
+ EncryptionInfo encryption_info = 8
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The encryption information for the backup, whether it is
+ // protected by one or more KMS keys. The information includes all Cloud
+ // KMS key versions used to encrypt the backup. The `encryption_status' field
+ // inside of each `EncryptionInfo` is not populated. At least one of the key
+ // versions must be available for the backup to be restored. If a key version
+ // is revoked in the middle of a restore, the restore behavior is undefined.
+ repeated EncryptionInfo encryption_information = 13
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The database dialect information for the backup.
+ DatabaseDialect database_dialect = 10
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The names of the destination backups being created by copying
+ // this source backup. The backup names are of the form
+ // `projects//instances//backups/`.
+ // Referencing backups may exist in different instances. The existence of
+ // any referencing backup prevents the backup from being deleted. When the
+ // copy operation is done (either successfully completed or cancelled or the
+ // destination backup is deleted), the reference to the backup is removed.
+ repeated string referencing_backups = 11 [
+ (google.api.field_behavior) = OUTPUT_ONLY,
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+
+ // Output only. The max allowed expiration time of the backup, with
+ // microseconds granularity. A backup's expiration time can be configured in
+ // multiple APIs: CreateBackup, UpdateBackup, CopyBackup. When updating or
+ // copying an existing backup, the expiration time specified must be
+ // less than `Backup.max_expire_time`.
+ google.protobuf.Timestamp max_expire_time = 12
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. List of backup schedule URIs that are associated with
+ // creating this backup. This is only applicable for scheduled backups, and
+ // is empty for on-demand backups.
+ //
+ // To optimize for storage, whenever possible, multiple schedules are
+ // collapsed together to create one backup. In such cases, this field captures
+ // the list of all backup schedule URIs that are associated with creating
+ // this backup. If collapsing is not done, then this field captures the
+ // single backup schedule URI associated with creating this backup.
+ repeated string backup_schedules = 14 [
+ (google.api.field_behavior) = OUTPUT_ONLY,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/BackupSchedule"
+ }
+ ];
+
+ // Output only. Populated only for backups in an incremental backup chain.
+ // Backups share the same chain id if and only if they belong to the same
+ // incremental backup chain. Use this field to determine which backups are
+ // part of the same incremental backup chain. The ordering of backups in the
+ // chain can be determined by ordering the backup `version_time`.
+ string incremental_backup_chain_id = 17
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Data deleted at a time older than this is guaranteed not to be
+ // retained in order to support this backup. For a backup in an incremental
+ // backup chain, this is the version time of the oldest backup that exists or
+ // ever existed in the chain. For all other backups, this is the version time
+ // of the backup. This field can be used to understand what data is being
+ // retained by the backup system.
+ google.protobuf.Timestamp oldest_version_time = 18
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The instance partition(s) storing the backup.
+ //
+ // This is the same as the list of the instance partition(s) that the database
+ // had footprint in at the backup's `version_time`.
+ repeated BackupInstancePartition instance_partitions = 19
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+// The request for
+// [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup].
+message CreateBackupRequest {
+ // Required. The name of the instance in which the backup will be
+ // created. This must be the same instance that contains the database the
+ // backup will be created from. The backup will be stored in the
+ // location(s) specified in the instance configuration of this
+ // instance. Values are of the form
+ // `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Required. The id of the backup to be created. The `backup_id` appended to
+ // `parent` forms the full backup name of the form
+ // `projects//instances//backups/`.
+ string backup_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The backup to create.
+ Backup backup = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The encryption configuration used to encrypt the backup. If this
+ // field is not specified, the backup will use the same encryption
+ // configuration as the database by default, namely
+ // [encryption_type][google.spanner.admin.database.v1.CreateBackupEncryptionConfig.encryption_type]
+ // = `USE_DATABASE_ENCRYPTION`.
+ CreateBackupEncryptionConfig encryption_config = 4
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// Metadata type for the operation returned by
+// [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup].
+message CreateBackupMetadata {
+ // The name of the backup being created.
+ string name = 1 [
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+
+ // The name of the database the backup is created from.
+ string database = 2 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+
+ // The progress of the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // operation.
+ OperationProgress progress = 3;
+
+ // The time at which cancellation of this operation was received.
+ // [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]
+ // starts asynchronous cancellation on a long-running operation. The server
+ // makes a best effort to cancel the operation, but success is not guaranteed.
+ // Clients can use
+ // [Operations.GetOperation][google.longrunning.Operations.GetOperation] or
+ // other methods to check whether the cancellation succeeded or whether the
+ // operation completed despite cancellation. On successful cancellation,
+ // the operation is not deleted; instead, it becomes an operation with
+ // an [Operation.error][google.longrunning.Operation.error] value with a
+ // [google.rpc.Status.code][google.rpc.Status.code] of 1,
+ // corresponding to `Code.CANCELLED`.
+ google.protobuf.Timestamp cancel_time = 4;
+}
+
+// The request for
+// [CopyBackup][google.spanner.admin.database.v1.DatabaseAdmin.CopyBackup].
+message CopyBackupRequest {
+ // Required. The name of the destination instance that will contain the backup
+ // copy. Values are of the form: `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Required. The id of the backup copy.
+ // The `backup_id` appended to `parent` forms the full backup_uri of the form
+ // `projects//instances//backups/`.
+ string backup_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The source backup to be copied.
+ // The source backup needs to be in READY state for it to be copied.
+ // Once CopyBackup is in progress, the source backup cannot be deleted or
+ // cleaned up on expiration until CopyBackup is finished.
+ // Values are of the form:
+ // `projects//instances//backups/`.
+ string source_backup = 3 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+
+ // Required. The expiration time of the backup in microsecond granularity.
+ // The expiration time must be at least 6 hours and at most 366 days
+ // from the `create_time` of the source backup. Once the `expire_time` has
+ // passed, the backup is eligible to be automatically deleted by Cloud Spanner
+ // to free the resources used by the backup.
+ google.protobuf.Timestamp expire_time = 4
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The encryption configuration used to encrypt the backup. If this
+ // field is not specified, the backup will use the same encryption
+ // configuration as the source backup by default, namely
+ // [encryption_type][google.spanner.admin.database.v1.CopyBackupEncryptionConfig.encryption_type]
+ // = `USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION`.
+ CopyBackupEncryptionConfig encryption_config = 5
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// Metadata type for the operation returned by
+// [CopyBackup][google.spanner.admin.database.v1.DatabaseAdmin.CopyBackup].
+message CopyBackupMetadata {
+ // The name of the backup being created through the copy operation.
+ // Values are of the form
+ // `projects//instances//backups/`.
+ string name = 1 [
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+
+ // The name of the source backup that is being copied.
+ // Values are of the form
+ // `projects//instances//backups/`.
+ string source_backup = 2 [
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+
+ // The progress of the
+ // [CopyBackup][google.spanner.admin.database.v1.DatabaseAdmin.CopyBackup]
+ // operation.
+ OperationProgress progress = 3;
+
+ // The time at which cancellation of CopyBackup operation was received.
+ // [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]
+ // starts asynchronous cancellation on a long-running operation. The server
+ // makes a best effort to cancel the operation, but success is not guaranteed.
+ // Clients can use
+ // [Operations.GetOperation][google.longrunning.Operations.GetOperation] or
+ // other methods to check whether the cancellation succeeded or whether the
+ // operation completed despite cancellation. On successful cancellation,
+ // the operation is not deleted; instead, it becomes an operation with
+ // an [Operation.error][google.longrunning.Operation.error] value with a
+ // [google.rpc.Status.code][google.rpc.Status.code] of 1,
+ // corresponding to `Code.CANCELLED`.
+ google.protobuf.Timestamp cancel_time = 4;
+}
+
+// The request for
+// [UpdateBackup][google.spanner.admin.database.v1.DatabaseAdmin.UpdateBackup].
+message UpdateBackupRequest {
+ // Required. The backup to update. `backup.name`, and the fields to be updated
+ // as specified by `update_mask` are required. Other fields are ignored.
+ // Update is only supported for the following fields:
+ // * `backup.expire_time`.
+ Backup backup = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. A mask specifying which fields (e.g. `expire_time`) in the
+ // Backup resource should be updated. This mask is relative to the Backup
+ // resource, not to the request message. The field mask must always be
+ // specified; this prevents any future fields from being erased accidentally
+ // by clients that do not know about them.
+ google.protobuf.FieldMask update_mask = 2
+ [(google.api.field_behavior) = REQUIRED];
+}
+
+// The request for
+// [GetBackup][google.spanner.admin.database.v1.DatabaseAdmin.GetBackup].
+message GetBackupRequest {
+ // Required. Name of the backup.
+ // Values are of the form
+ // `projects//instances//backups/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+}
+
+// The request for
+// [DeleteBackup][google.spanner.admin.database.v1.DatabaseAdmin.DeleteBackup].
+message DeleteBackupRequest {
+ // Required. Name of the backup to delete.
+ // Values are of the form
+ // `projects//instances//backups/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+}
+
+// The request for
+// [ListBackups][google.spanner.admin.database.v1.DatabaseAdmin.ListBackups].
+message ListBackupsRequest {
+ // Required. The instance to list backups from. Values are of the
+ // form `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // An expression that filters the list of returned backups.
+ //
+ // A filter expression consists of a field name, a comparison operator, and a
+ // value for filtering.
+ // The value must be a string, a number, or a boolean. The comparison operator
+ // must be one of: `<`, `>`, `<=`, `>=`, `!=`, `=`, or `:`.
+ // Colon `:` is the contains operator. Filter rules are not case sensitive.
+ //
+ // The following fields in the
+ // [Backup][google.spanner.admin.database.v1.Backup] are eligible for
+ // filtering:
+ //
+ // * `name`
+ // * `database`
+ // * `state`
+ // * `create_time` (and values are of the format YYYY-MM-DDTHH:MM:SSZ)
+ // * `expire_time` (and values are of the format YYYY-MM-DDTHH:MM:SSZ)
+ // * `version_time` (and values are of the format YYYY-MM-DDTHH:MM:SSZ)
+ // * `size_bytes`
+ // * `backup_schedules`
+ //
+ // You can combine multiple expressions by enclosing each expression in
+ // parentheses. By default, expressions are combined with AND logic, but
+ // you can specify AND, OR, and NOT logic explicitly.
+ //
+ // Here are a few examples:
+ //
+ // * `name:Howl` - The backup's name contains the string "howl".
+ // * `database:prod`
+ // - The database's name contains the string "prod".
+ // * `state:CREATING` - The backup is pending creation.
+ // * `state:READY` - The backup is fully created and ready for use.
+ // * `(name:howl) AND (create_time < \"2018-03-28T14:50:00Z\")`
+ // - The backup name contains the string "howl" and `create_time`
+ // of the backup is before 2018-03-28T14:50:00Z.
+ // * `expire_time < \"2018-03-28T14:50:00Z\"`
+ // - The backup `expire_time` is before 2018-03-28T14:50:00Z.
+ // * `size_bytes > 10000000000` - The backup's size is greater than 10GB
+ // * `backup_schedules:daily`
+ // - The backup is created from a schedule with "daily" in its name.
+ string filter = 2;
+
+ // Number of backups to be returned in the response. If 0 or
+ // less, defaults to the server's maximum allowed page size.
+ int32 page_size = 3;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.database.v1.ListBackupsResponse.next_page_token]
+ // from a previous
+ // [ListBackupsResponse][google.spanner.admin.database.v1.ListBackupsResponse]
+ // to the same `parent` and with the same `filter`.
+ string page_token = 4;
+}
+
+// The response for
+// [ListBackups][google.spanner.admin.database.v1.DatabaseAdmin.ListBackups].
+message ListBackupsResponse {
+ // The list of matching backups. Backups returned are ordered by `create_time`
+ // in descending order, starting from the most recent `create_time`.
+ repeated Backup backups = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListBackups][google.spanner.admin.database.v1.DatabaseAdmin.ListBackups]
+ // call to fetch more of the matching backups.
+ string next_page_token = 2;
+}
+
+// The request for
+// [ListBackupOperations][google.spanner.admin.database.v1.DatabaseAdmin.ListBackupOperations].
+message ListBackupOperationsRequest {
+ // Required. The instance of the backup operations. Values are of
+ // the form `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // An expression that filters the list of returned backup operations.
+ //
+ // A filter expression consists of a field name, a
+ // comparison operator, and a value for filtering.
+ // The value must be a string, a number, or a boolean. The comparison operator
+ // must be one of: `<`, `>`, `<=`, `>=`, `!=`, `=`, or `:`.
+ // Colon `:` is the contains operator. Filter rules are not case sensitive.
+ //
+ // The following fields in the [operation][google.longrunning.Operation]
+ // are eligible for filtering:
+ //
+ // * `name` - The name of the long-running operation
+ // * `done` - False if the operation is in progress, else true.
+ // * `metadata.@type` - the type of metadata. For example, the type string
+ // for
+ // [CreateBackupMetadata][google.spanner.admin.database.v1.CreateBackupMetadata]
+ // is
+ // `type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata`.
+ // * `metadata.` - any field in metadata.value.
+ // `metadata.@type` must be specified first if filtering on metadata
+ // fields.
+ // * `error` - Error associated with the long-running operation.
+ // * `response.@type` - the type of response.
+ // * `response.` - any field in response.value.
+ //
+ // You can combine multiple expressions by enclosing each expression in
+ // parentheses. By default, expressions are combined with AND logic, but
+ // you can specify AND, OR, and NOT logic explicitly.
+ //
+ // Here are a few examples:
+ //
+ // * `done:true` - The operation is complete.
+ // * `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata) AND` \
+ // `metadata.database:prod` - Returns operations where:
+ // * The operation's metadata type is
+ // [CreateBackupMetadata][google.spanner.admin.database.v1.CreateBackupMetadata].
+ // * The source database name of backup contains the string "prod".
+ // * `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata) AND` \
+ // `(metadata.name:howl) AND` \
+ // `(metadata.progress.start_time < \"2018-03-28T14:50:00Z\") AND` \
+ // `(error:*)` - Returns operations where:
+ // * The operation's metadata type is
+ // [CreateBackupMetadata][google.spanner.admin.database.v1.CreateBackupMetadata].
+ // * The backup name contains the string "howl".
+ // * The operation started before 2018-03-28T14:50:00Z.
+ // * The operation resulted in an error.
+ // * `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CopyBackupMetadata) AND` \
+ // `(metadata.source_backup:test) AND` \
+ // `(metadata.progress.start_time < \"2022-01-18T14:50:00Z\") AND` \
+ // `(error:*)` - Returns operations where:
+ // * The operation's metadata type is
+ // [CopyBackupMetadata][google.spanner.admin.database.v1.CopyBackupMetadata].
+ // * The source backup name contains the string "test".
+ // * The operation started before 2022-01-18T14:50:00Z.
+ // * The operation resulted in an error.
+ // * `((metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CreateBackupMetadata) AND` \
+ // `(metadata.database:test_db)) OR` \
+ // `((metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.CopyBackupMetadata)
+ // AND` \
+ // `(metadata.source_backup:test_bkp)) AND` \
+ // `(error:*)` - Returns operations where:
+ // * The operation's metadata matches either of criteria:
+ // * The operation's metadata type is
+ // [CreateBackupMetadata][google.spanner.admin.database.v1.CreateBackupMetadata]
+ // AND the source database name of the backup contains the string
+ // "test_db"
+ // * The operation's metadata type is
+ // [CopyBackupMetadata][google.spanner.admin.database.v1.CopyBackupMetadata]
+ // AND the source backup name contains the string "test_bkp"
+ // * The operation resulted in an error.
+ string filter = 2;
+
+ // Number of operations to be returned in the response. If 0 or
+ // less, defaults to the server's maximum allowed page size.
+ int32 page_size = 3;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.database.v1.ListBackupOperationsResponse.next_page_token]
+ // from a previous
+ // [ListBackupOperationsResponse][google.spanner.admin.database.v1.ListBackupOperationsResponse]
+ // to the same `parent` and with the same `filter`.
+ string page_token = 4;
+}
+
+// The response for
+// [ListBackupOperations][google.spanner.admin.database.v1.DatabaseAdmin.ListBackupOperations].
+message ListBackupOperationsResponse {
+ // The list of matching backup [long-running
+ // operations][google.longrunning.Operation]. Each operation's name will be
+ // prefixed by the backup's name. The operation's
+ // [metadata][google.longrunning.Operation.metadata] field type
+ // `metadata.type_url` describes the type of the metadata. Operations returned
+ // include those that are pending or have completed/failed/canceled within the
+ // last 7 days. Operations returned are ordered by
+ // `operation.metadata.value.progress.start_time` in descending order starting
+ // from the most recently started operation.
+ repeated google.longrunning.Operation operations = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListBackupOperations][google.spanner.admin.database.v1.DatabaseAdmin.ListBackupOperations]
+ // call to fetch more of the matching metadata.
+ string next_page_token = 2;
+}
+
+// Information about a backup.
+message BackupInfo {
+ // Name of the backup.
+ string backup = 1 [
+ (google.api.resource_reference) = { type: "spanner.googleapis.com/Backup" }
+ ];
+
+ // The backup contains an externally consistent copy of `source_database` at
+ // the timestamp specified by `version_time`. If the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // request did not specify `version_time`, the `version_time` of the backup is
+ // equivalent to the `create_time`.
+ google.protobuf.Timestamp version_time = 4;
+
+ // The time the
+ // [CreateBackup][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackup]
+ // request was received.
+ google.protobuf.Timestamp create_time = 2;
+
+ // Name of the database the backup was created from.
+ string source_database = 3 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+}
+
+// Encryption configuration for the backup to create.
+message CreateBackupEncryptionConfig {
+ // Encryption types for the backup.
+ enum EncryptionType {
+ // Unspecified. Do not use.
+ ENCRYPTION_TYPE_UNSPECIFIED = 0;
+
+ // Use the same encryption configuration as the database. This is the
+ // default option when
+ // [encryption_config][google.spanner.admin.database.v1.CreateBackupEncryptionConfig]
+ // is empty. For example, if the database is using
+ // `Customer_Managed_Encryption`, the backup will be using the same Cloud
+ // KMS key as the database.
+ USE_DATABASE_ENCRYPTION = 1;
+
+ // Use Google default encryption.
+ GOOGLE_DEFAULT_ENCRYPTION = 2;
+
+ // Use customer managed encryption. If specified, `kms_key_name`
+ // must contain a valid Cloud KMS key.
+ CUSTOMER_MANAGED_ENCRYPTION = 3;
+ }
+
+ // Required. The encryption type of the backup.
+ EncryptionType encryption_type = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The Cloud KMS key that will be used to protect the backup.
+ // This field should be set only when
+ // [encryption_type][google.spanner.admin.database.v1.CreateBackupEncryptionConfig.encryption_type]
+ // is `CUSTOMER_MANAGED_ENCRYPTION`. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ string kms_key_name = 2 [
+ (google.api.field_behavior) = OPTIONAL,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }
+ ];
+
+ // Optional. Specifies the KMS configuration for the one or more keys used to
+ // protect the backup. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ //
+ // The keys referenced by kms_key_names must fully cover all
+ // regions of the backup's instance configuration. Some examples:
+ // * For single region instance configs, specify a single regional
+ // location KMS key.
+ // * For multi-regional instance configs of type GOOGLE_MANAGED,
+ // either specify a multi-regional location KMS key or multiple regional
+ // location KMS keys that cover all regions in the instance config.
+ // * For an instance config of type USER_MANAGED, please specify only
+ // regional location KMS keys to cover each region in the instance config.
+ // Multi-regional location KMS keys are not supported for USER_MANAGED
+ // instance configs.
+ repeated string kms_key_names = 3 [
+ (google.api.field_behavior) = OPTIONAL,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }
+ ];
+}
+
+// Encryption configuration for the copied backup.
+message CopyBackupEncryptionConfig {
+ // Encryption types for the backup.
+ enum EncryptionType {
+ // Unspecified. Do not use.
+ ENCRYPTION_TYPE_UNSPECIFIED = 0;
+
+ // This is the default option for
+ // [CopyBackup][google.spanner.admin.database.v1.DatabaseAdmin.CopyBackup]
+ // when
+ // [encryption_config][google.spanner.admin.database.v1.CopyBackupEncryptionConfig]
+ // is not specified. For example, if the source backup is using
+ // `Customer_Managed_Encryption`, the backup will be using the same Cloud
+ // KMS key as the source backup.
+ USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION = 1;
+
+ // Use Google default encryption.
+ GOOGLE_DEFAULT_ENCRYPTION = 2;
+
+ // Use customer managed encryption. If specified, either `kms_key_name` or
+ // `kms_key_names` must contain valid Cloud KMS key(s).
+ CUSTOMER_MANAGED_ENCRYPTION = 3;
+ }
+
+ // Required. The encryption type of the backup.
+ EncryptionType encryption_type = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The Cloud KMS key that will be used to protect the backup.
+ // This field should be set only when
+ // [encryption_type][google.spanner.admin.database.v1.CopyBackupEncryptionConfig.encryption_type]
+ // is `CUSTOMER_MANAGED_ENCRYPTION`. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ string kms_key_name = 2 [
+ (google.api.field_behavior) = OPTIONAL,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }
+ ];
+
+ // Optional. Specifies the KMS configuration for the one or more keys used to
+ // protect the backup. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ // Kms keys specified can be in any order.
+ //
+ // The keys referenced by kms_key_names must fully cover all
+ // regions of the backup's instance configuration. Some examples:
+ // * For single region instance configs, specify a single regional
+ // location KMS key.
+ // * For multi-regional instance configs of type GOOGLE_MANAGED,
+ // either specify a multi-regional location KMS key or multiple regional
+ // location KMS keys that cover all regions in the instance config.
+ // * For an instance config of type USER_MANAGED, please specify only
+ // regional location KMS keys to cover each region in the instance config.
+ // Multi-regional location KMS keys are not supported for USER_MANAGED
+ // instance configs.
+ repeated string kms_key_names = 3 [
+ (google.api.field_behavior) = OPTIONAL,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }
+ ];
+}
+
+// The specification for full backups.
+// A full backup stores the entire contents of the database at a given
+// version time.
+message FullBackupSpec {}
+
+// The specification for incremental backup chains.
+// An incremental backup stores the delta of changes between a previous
+// backup and the database contents at a given version time. An
+// incremental backup chain consists of a full backup and zero or more
+// successive incremental backups. The first backup created for an
+// incremental backup chain is always a full backup.
+message IncrementalBackupSpec {}
+
+// Instance partition information for the backup.
+message BackupInstancePartition {
+ // A unique identifier for the instance partition. Values are of the form
+ // `projects//instances//instancePartitions/`
+ string instance_partition = 1 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstancePartition"
+ }];
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/backup_schedule.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/backup_schedule.proto
new file mode 100644
index 00000000..c273516a
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/backup_schedule.proto
@@ -0,0 +1,230 @@
+// 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
+//
+// 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.admin.database.v1;
+
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/protobuf/duration.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/timestamp.proto";
+import "google/spanner/admin/database/v1/backup.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Admin.Database.V1";
+option go_package = "cloud.google.com/go/spanner/admin/database/apiv1/databasepb;databasepb";
+option java_multiple_files = true;
+option java_outer_classname = "BackupScheduleProto";
+option java_package = "com.google.spanner.admin.database.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Database\\V1";
+option ruby_package = "Google::Cloud::Spanner::Admin::Database::V1";
+
+// Defines specifications of the backup schedule.
+message BackupScheduleSpec {
+ // Required.
+ oneof schedule_spec {
+ // Cron style schedule specification.
+ CrontabSpec cron_spec = 1;
+ }
+}
+
+// BackupSchedule expresses the automated backup creation specification for a
+// Spanner database.
+// Next ID: 10
+message BackupSchedule {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/BackupSchedule"
+ pattern: "projects/{project}/instances/{instance}/databases/{database}/backupSchedules/{schedule}"
+ plural: "backupSchedules"
+ singular: "backupSchedule"
+ };
+
+ // Identifier. Output only for the
+ // [CreateBackupSchedule][DatabaseAdmin.CreateBackupSchededule] operation.
+ // Required for the
+ // [UpdateBackupSchedule][google.spanner.admin.database.v1.DatabaseAdmin.UpdateBackupSchedule]
+ // operation. A globally unique identifier for the backup schedule which
+ // cannot be changed. Values are of the form
+ // `projects//instances//databases//backupSchedules/[a-z][a-z0-9_\-]*[a-z0-9]`
+ // The final segment of the name must be between 2 and 60 characters in
+ // length.
+ string name = 1 [(google.api.field_behavior) = IDENTIFIER];
+
+ // Optional. The schedule specification based on which the backup creations
+ // are triggered.
+ BackupScheduleSpec spec = 6 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. The retention duration of a backup that must be at least 6 hours
+ // and at most 366 days. The backup is eligible to be automatically deleted
+ // once the retention period has elapsed.
+ google.protobuf.Duration retention_duration = 3
+ [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. The encryption configuration that will be used to encrypt the
+ // backup. If this field is not specified, the backup will use the same
+ // encryption configuration as the database.
+ CreateBackupEncryptionConfig encryption_config = 4
+ [(google.api.field_behavior) = OPTIONAL];
+
+ // Required. Backup type spec determines the type of backup that is created by
+ // the backup schedule. Currently, only full backups are supported.
+ oneof backup_type_spec {
+ // The schedule creates only full backups.
+ FullBackupSpec full_backup_spec = 7;
+
+ // The schedule creates incremental backup chains.
+ IncrementalBackupSpec incremental_backup_spec = 8;
+ }
+
+ // Output only. The timestamp at which the schedule was last updated.
+ // If the schedule has never been updated, this field contains the timestamp
+ // when the schedule was first created.
+ google.protobuf.Timestamp update_time = 9
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+// CrontabSpec can be used to specify the version time and frequency at
+// which the backup should be created.
+message CrontabSpec {
+ // Required. Textual representation of the crontab. User can customize the
+ // backup frequency and the backup version time using the cron
+ // expression. The version time must be in UTC timezone.
+ //
+ // The backup will contain an externally consistent copy of the
+ // database at the version time. Allowed frequencies are 12 hour, 1 day,
+ // 1 week and 1 month. Examples of valid cron specifications:
+ // * `0 2/12 * * * ` : every 12 hours at (2, 14) hours past midnight in UTC.
+ // * `0 2,14 * * * ` : every 12 hours at (2,14) hours past midnight in UTC.
+ // * `0 2 * * * ` : once a day at 2 past midnight in UTC.
+ // * `0 2 * * 0 ` : once a week every Sunday at 2 past midnight in UTC.
+ // * `0 2 8 * * ` : once a month on 8th day at 2 past midnight in UTC.
+ string text = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Output only. The time zone of the times in `CrontabSpec.text`. Currently
+ // only UTC is supported.
+ string time_zone = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Schedule backups will contain an externally consistent copy
+ // of the database at the version time specified in
+ // `schedule_spec.cron_spec`. However, Spanner may not initiate the creation
+ // of the scheduled backups at that version time. Spanner will initiate
+ // the creation of scheduled backups within the time window bounded by the
+ // version_time specified in `schedule_spec.cron_spec` and version_time +
+ // `creation_window`.
+ google.protobuf.Duration creation_window = 3
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+// The request for
+// [CreateBackupSchedule][google.spanner.admin.database.v1.DatabaseAdmin.CreateBackupSchedule].
+message CreateBackupScheduleRequest {
+ // Required. The name of the database that this backup schedule applies to.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Required. The Id to use for the backup schedule. The `backup_schedule_id`
+ // appended to `parent` forms the full backup schedule name of the form
+ // `projects//instances//databases//backupSchedules/`.
+ string backup_schedule_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The backup schedule to create.
+ BackupSchedule backup_schedule = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+// The request for
+// [GetBackupSchedule][google.spanner.admin.database.v1.DatabaseAdmin.GetBackupSchedule].
+message GetBackupScheduleRequest {
+ // Required. The name of the schedule to retrieve.
+ // Values are of the form
+ // `projects//instances//databases//backupSchedules/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/BackupSchedule"
+ }
+ ];
+}
+
+// The request for
+// [DeleteBackupSchedule][google.spanner.admin.database.v1.DatabaseAdmin.DeleteBackupSchedule].
+message DeleteBackupScheduleRequest {
+ // Required. The name of the schedule to delete.
+ // Values are of the form
+ // `projects//instances//databases//backupSchedules/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/BackupSchedule"
+ }
+ ];
+}
+
+// The request for
+// [ListBackupSchedules][google.spanner.admin.database.v1.DatabaseAdmin.ListBackupSchedules].
+message ListBackupSchedulesRequest {
+ // Required. Database is the parent resource whose backup schedules should be
+ // listed. Values are of the form
+ // projects//instances//databases/
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Optional. Number of backup schedules to be returned in the response. If 0
+ // or less, defaults to the server's maximum allowed page size.
+ int32 page_size = 2 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.database.v1.ListBackupSchedulesResponse.next_page_token]
+ // from a previous
+ // [ListBackupSchedulesResponse][google.spanner.admin.database.v1.ListBackupSchedulesResponse]
+ // to the same `parent`.
+ string page_token = 4 [(google.api.field_behavior) = OPTIONAL];
+}
+
+// The response for
+// [ListBackupSchedules][google.spanner.admin.database.v1.DatabaseAdmin.ListBackupSchedules].
+message ListBackupSchedulesResponse {
+ // The list of backup schedules for a database.
+ repeated BackupSchedule backup_schedules = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListBackupSchedules][google.spanner.admin.database.v1.DatabaseAdmin.ListBackupSchedules]
+ // call to fetch more of the schedules.
+ string next_page_token = 2;
+}
+
+// The request for
+// [UpdateBackupScheduleRequest][google.spanner.admin.database.v1.DatabaseAdmin.UpdateBackupSchedule].
+message UpdateBackupScheduleRequest {
+ // Required. The backup schedule to update. `backup_schedule.name`, and the
+ // fields to be updated as specified by `update_mask` are required. Other
+ // fields are ignored.
+ BackupSchedule backup_schedule = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. A mask specifying which fields in the BackupSchedule resource
+ // should be updated. This mask is relative to the BackupSchedule resource,
+ // not to the request message. The field mask must always be
+ // specified; this prevents any future fields from being erased
+ // accidentally.
+ google.protobuf.FieldMask update_mask = 2
+ [(google.api.field_behavior) = REQUIRED];
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/common.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/common.proto
new file mode 100644
index 00000000..c494b8cf
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/common.proto
@@ -0,0 +1,132 @@
+// 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
+//
+// 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.admin.database.v1;
+
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/protobuf/timestamp.proto";
+import "google/rpc/status.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Admin.Database.V1";
+option go_package = "cloud.google.com/go/spanner/admin/database/apiv1/databasepb;databasepb";
+option java_multiple_files = true;
+option java_outer_classname = "CommonProto";
+option java_package = "com.google.spanner.admin.database.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Database\\V1";
+option ruby_package = "Google::Cloud::Spanner::Admin::Database::V1";
+option (google.api.resource_definition) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ pattern: "projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}"
+};
+option (google.api.resource_definition) = {
+ type: "cloudkms.googleapis.com/CryptoKeyVersion"
+ pattern: "projects/{project}/locations/{location}/keyRings/{key_ring}/cryptoKeys/{crypto_key}/cryptoKeyVersions/{crypto_key_version}"
+};
+
+// Encapsulates progress related information for a Cloud Spanner long
+// running operation.
+message OperationProgress {
+ // Percent completion of the operation.
+ // Values are between 0 and 100 inclusive.
+ int32 progress_percent = 1;
+
+ // Time the request was received.
+ google.protobuf.Timestamp start_time = 2;
+
+ // If set, the time at which this operation failed or was completed
+ // successfully.
+ google.protobuf.Timestamp end_time = 3;
+}
+
+// Encryption configuration for a Cloud Spanner database.
+message EncryptionConfig {
+ // The Cloud KMS key to be used for encrypting and decrypting
+ // the database. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ string kms_key_name = 2 [(google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }];
+
+ // Specifies the KMS configuration for the one or more keys used to encrypt
+ // the database. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ //
+ // The keys referenced by kms_key_names must fully cover all
+ // regions of the database instance configuration. Some examples:
+ // * For single region database instance configs, specify a single regional
+ // location KMS key.
+ // * For multi-regional database instance configs of type GOOGLE_MANAGED,
+ // either specify a multi-regional location KMS key or multiple regional
+ // location KMS keys that cover all regions in the instance config.
+ // * For a database instance config of type USER_MANAGED, please specify only
+ // regional location KMS keys to cover each region in the instance config.
+ // Multi-regional location KMS keys are not supported for USER_MANAGED
+ // instance configs.
+ repeated string kms_key_names = 3 [(google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }];
+}
+
+// Encryption information for a Cloud Spanner database or backup.
+message EncryptionInfo {
+ // Possible encryption types.
+ enum Type {
+ // Encryption type was not specified, though data at rest remains encrypted.
+ TYPE_UNSPECIFIED = 0;
+
+ // The data is encrypted at rest with a key that is
+ // fully managed by Google. No key version or status will be populated.
+ // This is the default state.
+ GOOGLE_DEFAULT_ENCRYPTION = 1;
+
+ // The data is encrypted at rest with a key that is
+ // managed by the customer. The active version of the key. `kms_key_version`
+ // will be populated, and `encryption_status` may be populated.
+ CUSTOMER_MANAGED_ENCRYPTION = 2;
+ }
+
+ // Output only. The type of encryption.
+ Type encryption_type = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. If present, the status of a recent encrypt/decrypt call on
+ // underlying data for this database or backup. Regardless of status, data is
+ // always encrypted at rest.
+ google.rpc.Status encryption_status = 4
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. A Cloud KMS key version that is being used to protect the
+ // database or backup.
+ string kms_key_version = 2 [
+ (google.api.field_behavior) = OUTPUT_ONLY,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKeyVersion"
+ }
+ ];
+}
+
+// Indicates the dialect type of a database.
+enum DatabaseDialect {
+ // Default value. This value will create a database with the
+ // GOOGLE_STANDARD_SQL dialect.
+ DATABASE_DIALECT_UNSPECIFIED = 0;
+
+ // GoogleSQL supported SQL.
+ GOOGLE_STANDARD_SQL = 1;
+
+ // PostgreSQL supported SQL.
+ POSTGRESQL = 2;
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner.yaml b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner.yaml
new file mode 100644
index 00000000..9d85286a
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner.yaml
@@ -0,0 +1,69 @@
+type: google.api.Service
+config_version: 3
+name: spanner.googleapis.com
+title: Cloud Spanner API
+
+apis:
+- name: google.longrunning.Operations
+- name: google.spanner.admin.database.v1.DatabaseAdmin
+
+types:
+- name: google.spanner.admin.database.v1.CopyBackupMetadata
+- name: google.spanner.admin.database.v1.CreateBackupMetadata
+- name: google.spanner.admin.database.v1.CreateDatabaseMetadata
+- name: google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata
+- name: google.spanner.admin.database.v1.RestoreDatabaseMetadata
+- name: google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata
+- name: google.spanner.admin.database.v1.UpdateDatabaseMetadata
+
+documentation:
+ summary: |-
+ Cloud Spanner is a managed, mission-critical, globally consistent and
+ scalable relational database service.
+
+backend:
+ rules:
+ - selector: 'google.longrunning.Operations.*'
+ deadline: 3600.0
+ - selector: 'google.spanner.admin.database.v1.DatabaseAdmin.*'
+ deadline: 3600.0
+
+http:
+ rules:
+ - selector: google.longrunning.Operations.CancelOperation
+ post: '/v1/{name=projects/*/instances/*/databases/*/operations/*}:cancel'
+ additional_bindings:
+ - post: '/v1/{name=projects/*/instances/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instances/*/backups/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instanceConfigs/*/operations/*}:cancel'
+ - selector: google.longrunning.Operations.DeleteOperation
+ delete: '/v1/{name=projects/*/instances/*/databases/*/operations/*}'
+ additional_bindings:
+ - delete: '/v1/{name=projects/*/instances/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instances/*/backups/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instanceConfigs/*/operations/*}'
+ - selector: google.longrunning.Operations.GetOperation
+ get: '/v1/{name=projects/*/instances/*/databases/*/operations/*}'
+ additional_bindings:
+ - get: '/v1/{name=projects/*/instances/*/operations/*}'
+ - get: '/v1/{name=projects/*/instances/*/backups/*/operations/*}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/operations/*}'
+ - selector: google.longrunning.Operations.ListOperations
+ get: '/v1/{name=projects/*/instances/*/databases/*/operations}'
+ additional_bindings:
+ - get: '/v1/{name=projects/*/instances/*/operations}'
+ - get: '/v1/{name=projects/*/instances/*/backups/*/operations}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/operations}'
+
+authentication:
+ rules:
+ - selector: 'google.longrunning.Operations.*'
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.admin
+ - selector: 'google.spanner.admin.database.v1.DatabaseAdmin.*'
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.admin
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_admin_database_grpc_service_config.json b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_admin_database_grpc_service_config.json
new file mode 100755
index 00000000..f6d532ec
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_admin_database_grpc_service_config.json
@@ -0,0 +1,146 @@
+{
+ "methodConfig": [
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "ListDatabases"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "GetDatabase"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "UpdateDatabase"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "UpdateDatabaseDdl"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "DropDatabase"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "GetDatabaseDdl"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "GetBackup"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "ListBackups"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "DeleteBackup"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "UpdateBackup"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "ListDatabaseOperations"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "ListBackupOperations"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "ListDatabaseRoles"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "CreateBackupSchedule"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "GetBackupSchedule"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "UpdateBackupSchedule"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "DeleteBackupSchedule"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "ListBackupSchedules"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "AddSplitPoints"
+ }
+ ],
+ "timeout": "3600s",
+ "retryPolicy": {
+ "initialBackoff": "1s",
+ "maxBackoff": "32s",
+ "backoffMultiplier": 1.3,
+ "retryableStatusCodes": [
+ "UNAVAILABLE",
+ "DEADLINE_EXCEEDED"
+ ]
+ }
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "GetIamPolicy"
+ }
+ ],
+ "timeout": "30s",
+ "retryPolicy": {
+ "initialBackoff": "1s",
+ "maxBackoff": "32s",
+ "backoffMultiplier": 1.3,
+ "retryableStatusCodes": [
+ "UNAVAILABLE",
+ "DEADLINE_EXCEEDED"
+ ]
+ }
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "CreateDatabase"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "CreateBackup"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "CopyBackup"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "RestoreDatabase"
+ }
+ ],
+ "timeout": "3600s"
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "SetIamPolicy"
+ },
+ {
+ "service": "google.spanner.admin.database.v1.DatabaseAdmin",
+ "method": "TestIamPermissions"
+ }
+ ],
+ "timeout": "30s"
+ }
+ ]
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_database_admin.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_database_admin.proto
new file mode 100644
index 00000000..36e06f1e
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_database_admin.proto
@@ -0,0 +1,1284 @@
+// 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
+//
+// 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.admin.database.v1;
+
+import "google/api/annotations.proto";
+import "google/api/client.proto";
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/iam/v1/iam_policy.proto";
+import "google/iam/v1/policy.proto";
+import "google/longrunning/operations.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/struct.proto";
+import "google/protobuf/timestamp.proto";
+import "google/spanner/admin/database/v1/backup.proto";
+import "google/spanner/admin/database/v1/backup_schedule.proto";
+import "google/spanner/admin/database/v1/common.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Admin.Database.V1";
+option go_package = "cloud.google.com/go/spanner/admin/database/apiv1/databasepb;databasepb";
+option java_multiple_files = true;
+option java_outer_classname = "SpannerDatabaseAdminProto";
+option java_package = "com.google.spanner.admin.database.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Database\\V1";
+option ruby_package = "Google::Cloud::Spanner::Admin::Database::V1";
+option (google.api.resource_definition) = {
+ type: "spanner.googleapis.com/Instance"
+ pattern: "projects/{project}/instances/{instance}"
+};
+option (google.api.resource_definition) = {
+ type: "spanner.googleapis.com/InstancePartition"
+ pattern: "projects/{project}/instances/{instance}/instancePartitions/{instance_partition}"
+};
+
+// Cloud Spanner Database Admin API
+//
+// The Cloud Spanner Database Admin API can be used to:
+// * create, drop, and list databases
+// * update the schema of pre-existing databases
+// * create, delete, copy and list backups for a database
+// * restore a database from an existing backup
+service DatabaseAdmin {
+ option (google.api.default_host) = "spanner.googleapis.com";
+ option (google.api.oauth_scopes) =
+ "https://www.googleapis.com/auth/cloud-platform,"
+ "https://www.googleapis.com/auth/spanner.admin";
+
+ // Lists Cloud Spanner databases.
+ rpc ListDatabases(ListDatabasesRequest) returns (ListDatabasesResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*}/databases"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Creates a new Cloud Spanner database and starts to prepare it for serving.
+ // The returned [long-running operation][google.longrunning.Operation] will
+ // have a name of the format `/operations/` and
+ // can be used to track preparation of the database. The
+ // [metadata][google.longrunning.Operation.metadata] field type is
+ // [CreateDatabaseMetadata][google.spanner.admin.database.v1.CreateDatabaseMetadata].
+ // The [response][google.longrunning.Operation.response] field type is
+ // [Database][google.spanner.admin.database.v1.Database], if successful.
+ rpc CreateDatabase(CreateDatabaseRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*}/databases"
+ body: "*"
+ };
+ option (google.api.method_signature) = "parent,create_statement";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.database.v1.Database"
+ metadata_type: "google.spanner.admin.database.v1.CreateDatabaseMetadata"
+ };
+ }
+
+ // Gets the state of a Cloud Spanner database.
+ rpc GetDatabase(GetDatabaseRequest) returns (Database) {
+ option (google.api.http) = {
+ get: "/v1/{name=projects/*/instances/*/databases/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Updates a Cloud Spanner database. The returned
+ // [long-running operation][google.longrunning.Operation] can be used to track
+ // the progress of updating the database. If the named database does not
+ // exist, returns `NOT_FOUND`.
+ //
+ // While the operation is pending:
+ //
+ // * The database's
+ // [reconciling][google.spanner.admin.database.v1.Database.reconciling]
+ // field is set to true.
+ // * Cancelling the operation is best-effort. If the cancellation succeeds,
+ // the operation metadata's
+ // [cancel_time][google.spanner.admin.database.v1.UpdateDatabaseMetadata.cancel_time]
+ // is set, the updates are reverted, and the operation terminates with a
+ // `CANCELLED` status.
+ // * New UpdateDatabase requests will return a `FAILED_PRECONDITION` error
+ // until the pending operation is done (returns successfully or with
+ // error).
+ // * Reading the database via the API continues to give the pre-request
+ // values.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * The new values are in effect and readable via the API.
+ // * The database's
+ // [reconciling][google.spanner.admin.database.v1.Database.reconciling]
+ // field becomes false.
+ //
+ // The returned [long-running operation][google.longrunning.Operation] will
+ // have a name of the format
+ // `projects//instances//databases//operations/`
+ // and can be used to track the database modification. The
+ // [metadata][google.longrunning.Operation.metadata] field type is
+ // [UpdateDatabaseMetadata][google.spanner.admin.database.v1.UpdateDatabaseMetadata].
+ // The [response][google.longrunning.Operation.response] field type is
+ // [Database][google.spanner.admin.database.v1.Database], if successful.
+ rpc UpdateDatabase(UpdateDatabaseRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ patch: "/v1/{database.name=projects/*/instances/*/databases/*}"
+ body: "database"
+ };
+ option (google.api.method_signature) = "database,update_mask";
+ option (google.longrunning.operation_info) = {
+ response_type: "Database"
+ metadata_type: "UpdateDatabaseMetadata"
+ };
+ }
+
+ // Updates the schema of a Cloud Spanner database by
+ // creating/altering/dropping tables, columns, indexes, etc. The returned
+ // [long-running operation][google.longrunning.Operation] will have a name of
+ // the format `/operations/` and can be used to
+ // track execution of the schema change(s). The
+ // [metadata][google.longrunning.Operation.metadata] field type is
+ // [UpdateDatabaseDdlMetadata][google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata].
+ // The operation has no response.
+ rpc UpdateDatabaseDdl(UpdateDatabaseDdlRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ patch: "/v1/{database=projects/*/instances/*/databases/*}/ddl"
+ body: "*"
+ };
+ option (google.api.method_signature) = "database,statements";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.protobuf.Empty"
+ metadata_type: "google.spanner.admin.database.v1.UpdateDatabaseDdlMetadata"
+ };
+ }
+
+ // Drops (aka deletes) a Cloud Spanner database.
+ // Completed backups for the database will be retained according to their
+ // `expire_time`.
+ // Note: Cloud Spanner might continue to accept requests for a few seconds
+ // after the database has been deleted.
+ rpc DropDatabase(DropDatabaseRequest) returns (google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/v1/{database=projects/*/instances/*/databases/*}"
+ };
+ option (google.api.method_signature) = "database";
+ }
+
+ // Returns the schema of a Cloud Spanner database as a list of formatted
+ // DDL statements. This method does not show pending schema updates, those may
+ // be queried using the [Operations][google.longrunning.Operations] API.
+ rpc GetDatabaseDdl(GetDatabaseDdlRequest) returns (GetDatabaseDdlResponse) {
+ option (google.api.http) = {
+ get: "/v1/{database=projects/*/instances/*/databases/*}/ddl"
+ };
+ option (google.api.method_signature) = "database";
+ }
+
+ // Sets the access control policy on a database or backup resource.
+ // Replaces any existing policy.
+ //
+ // Authorization requires `spanner.databases.setIamPolicy`
+ // permission on [resource][google.iam.v1.SetIamPolicyRequest.resource].
+ // For backups, authorization requires `spanner.backups.setIamPolicy`
+ // permission on [resource][google.iam.v1.SetIamPolicyRequest.resource].
+ rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest)
+ returns (google.iam.v1.Policy) {
+ option (google.api.http) = {
+ post: "/v1/{resource=projects/*/instances/*/databases/*}:setIamPolicy"
+ body: "*"
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/backups/*}:setIamPolicy"
+ body: "*"
+ }
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/databases/*/backupSchedules/*}:setIamPolicy"
+ body: "*"
+ }
+ };
+ option (google.api.method_signature) = "resource,policy";
+ }
+
+ // Gets the access control policy for a database or backup resource.
+ // Returns an empty policy if a database or backup exists but does not have a
+ // policy set.
+ //
+ // Authorization requires `spanner.databases.getIamPolicy` permission on
+ // [resource][google.iam.v1.GetIamPolicyRequest.resource].
+ // For backups, authorization requires `spanner.backups.getIamPolicy`
+ // permission on [resource][google.iam.v1.GetIamPolicyRequest.resource].
+ rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest)
+ returns (google.iam.v1.Policy) {
+ option (google.api.http) = {
+ post: "/v1/{resource=projects/*/instances/*/databases/*}:getIamPolicy"
+ body: "*"
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/backups/*}:getIamPolicy"
+ body: "*"
+ }
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/databases/*/backupSchedules/*}:getIamPolicy"
+ body: "*"
+ }
+ };
+ option (google.api.method_signature) = "resource";
+ }
+
+ // Returns permissions that the caller has on the specified database or backup
+ // resource.
+ //
+ // Attempting this RPC on a non-existent Cloud Spanner database will
+ // result in a NOT_FOUND error if the user has
+ // `spanner.databases.list` permission on the containing Cloud
+ // Spanner instance. Otherwise returns an empty set of permissions.
+ // Calling this method on a backup that does not exist will
+ // result in a NOT_FOUND error if the user has
+ // `spanner.backups.list` permission on the containing instance.
+ rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest)
+ returns (google.iam.v1.TestIamPermissionsResponse) {
+ option (google.api.http) = {
+ post: "/v1/{resource=projects/*/instances/*/databases/*}:testIamPermissions"
+ body: "*"
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/backups/*}:testIamPermissions"
+ body: "*"
+ }
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/databases/*/backupSchedules/*}:testIamPermissions"
+ body: "*"
+ }
+ additional_bindings {
+ post: "/v1/{resource=projects/*/instances/*/databases/*/databaseRoles/*}:testIamPermissions"
+ body: "*"
+ }
+ };
+ option (google.api.method_signature) = "resource,permissions";
+ }
+
+ // Starts creating a new Cloud Spanner Backup.
+ // The returned backup [long-running operation][google.longrunning.Operation]
+ // will have a name of the format
+ // `projects//instances//backups//operations/`
+ // and can be used to track creation of the backup. The
+ // [metadata][google.longrunning.Operation.metadata] field type is
+ // [CreateBackupMetadata][google.spanner.admin.database.v1.CreateBackupMetadata].
+ // The [response][google.longrunning.Operation.response] field type is
+ // [Backup][google.spanner.admin.database.v1.Backup], if successful.
+ // Cancelling the returned operation will stop the creation and delete the
+ // backup. There can be only one pending backup creation per database. Backup
+ // creation of different databases can run concurrently.
+ rpc CreateBackup(CreateBackupRequest) returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*}/backups"
+ body: "backup"
+ };
+ option (google.api.method_signature) = "parent,backup,backup_id";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.database.v1.Backup"
+ metadata_type: "google.spanner.admin.database.v1.CreateBackupMetadata"
+ };
+ }
+
+ // Starts copying a Cloud Spanner Backup.
+ // The returned backup [long-running operation][google.longrunning.Operation]
+ // will have a name of the format
+ // `projects//instances//backups//operations/`
+ // and can be used to track copying of the backup. The operation is associated
+ // with the destination backup.
+ // The [metadata][google.longrunning.Operation.metadata] field type is
+ // [CopyBackupMetadata][google.spanner.admin.database.v1.CopyBackupMetadata].
+ // The [response][google.longrunning.Operation.response] field type is
+ // [Backup][google.spanner.admin.database.v1.Backup], if successful.
+ // Cancelling the returned operation will stop the copying and delete the
+ // destination backup. Concurrent CopyBackup requests can run on the same
+ // source backup.
+ rpc CopyBackup(CopyBackupRequest) returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*}/backups:copy"
+ body: "*"
+ };
+ option (google.api.method_signature) =
+ "parent,backup_id,source_backup,expire_time";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.database.v1.Backup"
+ metadata_type: "google.spanner.admin.database.v1.CopyBackupMetadata"
+ };
+ }
+
+ // Gets metadata on a pending or completed
+ // [Backup][google.spanner.admin.database.v1.Backup].
+ rpc GetBackup(GetBackupRequest) returns (Backup) {
+ option (google.api.http) = {
+ get: "/v1/{name=projects/*/instances/*/backups/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Updates a pending or completed
+ // [Backup][google.spanner.admin.database.v1.Backup].
+ rpc UpdateBackup(UpdateBackupRequest) returns (Backup) {
+ option (google.api.http) = {
+ patch: "/v1/{backup.name=projects/*/instances/*/backups/*}"
+ body: "backup"
+ };
+ option (google.api.method_signature) = "backup,update_mask";
+ }
+
+ // Deletes a pending or completed
+ // [Backup][google.spanner.admin.database.v1.Backup].
+ rpc DeleteBackup(DeleteBackupRequest) returns (google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/v1/{name=projects/*/instances/*/backups/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Lists completed and pending backups.
+ // Backups returned are ordered by `create_time` in descending order,
+ // starting from the most recent `create_time`.
+ rpc ListBackups(ListBackupsRequest) returns (ListBackupsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*}/backups"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Create a new database by restoring from a completed backup. The new
+ // database must be in the same project and in an instance with the same
+ // instance configuration as the instance containing
+ // the backup. The returned database [long-running
+ // operation][google.longrunning.Operation] has a name of the format
+ // `projects//instances//databases//operations/`,
+ // and can be used to track the progress of the operation, and to cancel it.
+ // The [metadata][google.longrunning.Operation.metadata] field type is
+ // [RestoreDatabaseMetadata][google.spanner.admin.database.v1.RestoreDatabaseMetadata].
+ // The [response][google.longrunning.Operation.response] type
+ // is [Database][google.spanner.admin.database.v1.Database], if
+ // successful. Cancelling the returned operation will stop the restore and
+ // delete the database.
+ // There can be only one database being restored into an instance at a time.
+ // Once the restore operation completes, a new restore operation can be
+ // initiated, without waiting for the optimize operation associated with the
+ // first restore to complete.
+ rpc RestoreDatabase(RestoreDatabaseRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*}/databases:restore"
+ body: "*"
+ };
+ option (google.api.method_signature) = "parent,database_id,backup";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.database.v1.Database"
+ metadata_type: "google.spanner.admin.database.v1.RestoreDatabaseMetadata"
+ };
+ }
+
+ // Lists database [longrunning-operations][google.longrunning.Operation].
+ // A database operation has a name of the form
+ // `projects//instances//databases//operations/`.
+ // The long-running operation
+ // [metadata][google.longrunning.Operation.metadata] field type
+ // `metadata.type_url` describes the type of the metadata. Operations returned
+ // include those that have completed/failed/canceled within the last 7 days,
+ // and pending operations.
+ rpc ListDatabaseOperations(ListDatabaseOperationsRequest)
+ returns (ListDatabaseOperationsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*}/databaseOperations"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Lists the backup [long-running operations][google.longrunning.Operation] in
+ // the given instance. A backup operation has a name of the form
+ // `projects//instances//backups//operations/`.
+ // The long-running operation
+ // [metadata][google.longrunning.Operation.metadata] field type
+ // `metadata.type_url` describes the type of the metadata. Operations returned
+ // include those that have completed/failed/canceled within the last 7 days,
+ // and pending operations. Operations returned are ordered by
+ // `operation.metadata.value.progress.start_time` in descending order starting
+ // from the most recently started operation.
+ rpc ListBackupOperations(ListBackupOperationsRequest)
+ returns (ListBackupOperationsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*}/backupOperations"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Lists Cloud Spanner database roles.
+ rpc ListDatabaseRoles(ListDatabaseRolesRequest)
+ returns (ListDatabaseRolesResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*/databases/*}/databaseRoles"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Adds split points to specified tables, indexes of a database.
+ rpc AddSplitPoints(AddSplitPointsRequest) returns (AddSplitPointsResponse) {
+ option (google.api.http) = {
+ post: "/v1/{database=projects/*/instances/*/databases/*}:addSplitPoints"
+ body: "*"
+ };
+ option (google.api.method_signature) = "database,split_points";
+ }
+
+ // Creates a new backup schedule.
+ rpc CreateBackupSchedule(CreateBackupScheduleRequest)
+ returns (BackupSchedule) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*/databases/*}/backupSchedules"
+ body: "backup_schedule"
+ };
+ option (google.api.method_signature) =
+ "parent,backup_schedule,backup_schedule_id";
+ }
+
+ // Gets backup schedule for the input schedule name.
+ rpc GetBackupSchedule(GetBackupScheduleRequest) returns (BackupSchedule) {
+ option (google.api.http) = {
+ get: "/v1/{name=projects/*/instances/*/databases/*/backupSchedules/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Updates a backup schedule.
+ rpc UpdateBackupSchedule(UpdateBackupScheduleRequest)
+ returns (BackupSchedule) {
+ option (google.api.http) = {
+ patch: "/v1/{backup_schedule.name=projects/*/instances/*/databases/*/backupSchedules/*}"
+ body: "backup_schedule"
+ };
+ option (google.api.method_signature) = "backup_schedule,update_mask";
+ }
+
+ // Deletes a backup schedule.
+ rpc DeleteBackupSchedule(DeleteBackupScheduleRequest)
+ returns (google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/v1/{name=projects/*/instances/*/databases/*/backupSchedules/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Lists all the backup schedules for the database.
+ rpc ListBackupSchedules(ListBackupSchedulesRequest)
+ returns (ListBackupSchedulesResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*/databases/*}/backupSchedules"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+}
+
+// Information about the database restore.
+message RestoreInfo {
+ // The type of the restore source.
+ RestoreSourceType source_type = 1;
+
+ // Information about the source used to restore the database.
+ oneof source_info {
+ // Information about the backup used to restore the database. The backup
+ // may no longer exist.
+ BackupInfo backup_info = 2;
+ }
+}
+
+// A Cloud Spanner database.
+message Database {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/Database"
+ pattern: "projects/{project}/instances/{instance}/databases/{database}"
+ };
+
+ // Indicates the current state of the database.
+ enum State {
+ // Not specified.
+ STATE_UNSPECIFIED = 0;
+
+ // The database is still being created. Operations on the database may fail
+ // with `FAILED_PRECONDITION` in this state.
+ CREATING = 1;
+
+ // The database is fully created and ready for use.
+ READY = 2;
+
+ // The database is fully created and ready for use, but is still
+ // being optimized for performance and cannot handle full load.
+ //
+ // In this state, the database still references the backup
+ // it was restore from, preventing the backup
+ // from being deleted. When optimizations are complete, the full performance
+ // of the database will be restored, and the database will transition to
+ // `READY` state.
+ READY_OPTIMIZING = 3;
+ }
+
+ // Required. The name of the database. Values are of the form
+ // `projects//instances//databases/`,
+ // where `` is as specified in the `CREATE DATABASE`
+ // statement. This name can be passed to other API methods to
+ // identify the database.
+ string name = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Output only. The current database state.
+ State state = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. If exists, the time at which the database creation started.
+ google.protobuf.Timestamp create_time = 3
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Applicable only for restored databases. Contains information
+ // about the restore source.
+ RestoreInfo restore_info = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. For databases that are using customer managed encryption, this
+ // field contains the encryption configuration for the database.
+ // For databases that are using Google default or other types of encryption,
+ // this field is empty.
+ EncryptionConfig encryption_config = 5
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. For databases that are using customer managed encryption, this
+ // field contains the encryption information for the database, such as
+ // all Cloud KMS key versions that are in use. The `encryption_status' field
+ // inside of each `EncryptionInfo` is not populated.
+ //
+ // For databases that are using Google default or other types of encryption,
+ // this field is empty.
+ //
+ // This field is propagated lazily from the backend. There might be a delay
+ // from when a key version is being used and when it appears in this field.
+ repeated EncryptionInfo encryption_info = 8
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The period in which Cloud Spanner retains all versions of data
+ // for the database. This is the same as the value of version_retention_period
+ // database option set using
+ // [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl].
+ // Defaults to 1 hour, if not set.
+ string version_retention_period = 6
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Earliest timestamp at which older versions of the data can be
+ // read. This value is continuously updated by Cloud Spanner and becomes stale
+ // the moment it is queried. If you are using this value to recover data, make
+ // sure to account for the time from the moment when the value is queried to
+ // the moment when you initiate the recovery.
+ google.protobuf.Timestamp earliest_version_time = 7
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The read-write region which contains the database's leader
+ // replicas.
+ //
+ // This is the same as the value of default_leader
+ // database option set using DatabaseAdmin.CreateDatabase or
+ // DatabaseAdmin.UpdateDatabaseDdl. If not explicitly set, this is empty.
+ string default_leader = 9 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The dialect of the Cloud Spanner Database.
+ DatabaseDialect database_dialect = 10
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Whether drop protection is enabled for this database. Defaults to false,
+ // if not set. For more details, please see how to [prevent accidental
+ // database
+ // deletion](https://cloud.google.com/spanner/docs/prevent-database-deletion).
+ bool enable_drop_protection = 11;
+
+ // Output only. If true, the database is being updated. If false, there are no
+ // ongoing update operations for the database.
+ bool reconciling = 12 [(google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+// The request for
+// [ListDatabases][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabases].
+message ListDatabasesRequest {
+ // Required. The instance whose databases should be listed.
+ // Values are of the form `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Number of databases to be returned in the response. If 0 or less,
+ // defaults to the server's maximum allowed page size.
+ int32 page_size = 3;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.database.v1.ListDatabasesResponse.next_page_token]
+ // from a previous
+ // [ListDatabasesResponse][google.spanner.admin.database.v1.ListDatabasesResponse].
+ string page_token = 4;
+}
+
+// The response for
+// [ListDatabases][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabases].
+message ListDatabasesResponse {
+ // Databases that matched the request.
+ repeated Database databases = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListDatabases][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabases]
+ // call to fetch more of the matching databases.
+ string next_page_token = 2;
+}
+
+// The request for
+// [CreateDatabase][google.spanner.admin.database.v1.DatabaseAdmin.CreateDatabase].
+message CreateDatabaseRequest {
+ // Required. The name of the instance that will serve the new database.
+ // Values are of the form `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Required. A `CREATE DATABASE` statement, which specifies the ID of the
+ // new database. The database ID must conform to the regular expression
+ // `[a-z][a-z0-9_\-]*[a-z0-9]` and be between 2 and 30 characters in length.
+ // If the database ID is a reserved word or if it contains a hyphen, the
+ // database ID must be enclosed in backticks (`` ` ``).
+ string create_statement = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. A list of DDL statements to run inside the newly created
+ // database. Statements can create tables, indexes, etc. These
+ // statements execute atomically with the creation of the database:
+ // if there is an error in any statement, the database is not created.
+ repeated string extra_statements = 3 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. The encryption configuration for the database. If this field is
+ // not specified, Cloud Spanner will encrypt/decrypt all data at rest using
+ // Google default encryption.
+ EncryptionConfig encryption_config = 4
+ [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. The dialect of the Cloud Spanner Database.
+ DatabaseDialect database_dialect = 5 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements in
+ // 'extra_statements' above.
+ // Contains a protobuf-serialized
+ // [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+ // To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+ // run `protoc` with --include_imports and --descriptor_set_out. For example,
+ // to generate for moon/shot/app.proto, run
+ // ```
+ // $protoc --proto_path=/app_path --proto_path=/lib_path \
+ // --include_imports \
+ // --descriptor_set_out=descriptors.data \
+ // moon/shot/app.proto
+ // ```
+ // For more details, see protobuffer [self
+ // description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+ bytes proto_descriptors = 6 [(google.api.field_behavior) = OPTIONAL];
+}
+
+// Metadata type for the operation returned by
+// [CreateDatabase][google.spanner.admin.database.v1.DatabaseAdmin.CreateDatabase].
+message CreateDatabaseMetadata {
+ // The database being created.
+ string database = 1 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+}
+
+// The request for
+// [GetDatabase][google.spanner.admin.database.v1.DatabaseAdmin.GetDatabase].
+message GetDatabaseRequest {
+ // Required. The name of the requested database. Values are of the form
+ // `projects//instances//databases/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+}
+
+// The request for
+// [UpdateDatabase][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase].
+message UpdateDatabaseRequest {
+ // Required. The database to update.
+ // The `name` field of the database is of the form
+ // `projects//instances//databases/`.
+ Database database = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The list of fields to update. Currently, only
+ // `enable_drop_protection` field can be updated.
+ google.protobuf.FieldMask update_mask = 2
+ [(google.api.field_behavior) = REQUIRED];
+}
+
+// Metadata type for the operation returned by
+// [UpdateDatabase][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase].
+message UpdateDatabaseMetadata {
+ // The request for
+ // [UpdateDatabase][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase].
+ UpdateDatabaseRequest request = 1;
+
+ // The progress of the
+ // [UpdateDatabase][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabase]
+ // operation.
+ OperationProgress progress = 2;
+
+ // The time at which this operation was cancelled. If set, this operation is
+ // in the process of undoing itself (which is best-effort).
+ google.protobuf.Timestamp cancel_time = 3;
+}
+
+// Enqueues the given DDL statements to be applied, in order but not
+// necessarily all at once, to the database schema at some point (or
+// points) in the future. The server checks that the statements
+// are executable (syntactically valid, name tables that exist, etc.)
+// before enqueueing them, but they may still fail upon
+// later execution (e.g., if a statement from another batch of
+// statements is applied first and it conflicts in some way, or if
+// there is some data-related problem like a `NULL` value in a column to
+// which `NOT NULL` would be added). If a statement fails, all
+// subsequent statements in the batch are automatically cancelled.
+//
+// Each batch of statements is assigned a name which can be used with
+// the [Operations][google.longrunning.Operations] API to monitor
+// progress. See the
+// [operation_id][google.spanner.admin.database.v1.UpdateDatabaseDdlRequest.operation_id]
+// field for more details.
+message UpdateDatabaseDdlRequest {
+ // Required. The database to update.
+ string database = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Required. DDL statements to be applied to the database.
+ repeated string statements = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // If empty, the new update request is assigned an
+ // automatically-generated operation ID. Otherwise, `operation_id`
+ // is used to construct the name of the resulting
+ // [Operation][google.longrunning.Operation].
+ //
+ // Specifying an explicit operation ID simplifies determining
+ // whether the statements were executed in the event that the
+ // [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl]
+ // call is replayed, or the return value is otherwise lost: the
+ // [database][google.spanner.admin.database.v1.UpdateDatabaseDdlRequest.database]
+ // and `operation_id` fields can be combined to form the
+ // [name][google.longrunning.Operation.name] of the resulting
+ // [longrunning.Operation][google.longrunning.Operation]:
+ // `/operations/`.
+ //
+ // `operation_id` should be unique within the database, and must be
+ // a valid identifier: `[a-z][a-z0-9_]*`. Note that
+ // automatically-generated operation IDs always begin with an
+ // underscore. If the named operation already exists,
+ // [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl]
+ // returns `ALREADY_EXISTS`.
+ string operation_id = 3;
+
+ // Optional. Proto descriptors used by CREATE/ALTER PROTO BUNDLE statements.
+ // Contains a protobuf-serialized
+ // [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+ // To generate it, [install](https://grpc.io/docs/protoc-installation/) and
+ // run `protoc` with --include_imports and --descriptor_set_out. For example,
+ // to generate for moon/shot/app.proto, run
+ // ```
+ // $protoc --proto_path=/app_path --proto_path=/lib_path \
+ // --include_imports \
+ // --descriptor_set_out=descriptors.data \
+ // moon/shot/app.proto
+ // ```
+ // For more details, see protobuffer [self
+ // description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+ bytes proto_descriptors = 4 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. This field is exposed to be used by the Spanner Migration Tool.
+ // For more details, see
+ // [SMT](https://github.com/GoogleCloudPlatform/spanner-migration-tool).
+ bool throughput_mode = 5 [(google.api.field_behavior) = OPTIONAL];
+}
+
+// Action information extracted from a DDL statement. This proto is used to
+// display the brief info of the DDL statement for the operation
+// [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl].
+message DdlStatementActionInfo {
+ // The action for the DDL statement, e.g. CREATE, ALTER, DROP, GRANT, etc.
+ // This field is a non-empty string.
+ string action = 1;
+
+ // The entity type for the DDL statement, e.g. TABLE, INDEX, VIEW, etc.
+ // This field can be empty string for some DDL statement,
+ // e.g. for statement "ANALYZE", `entity_type` = "".
+ string entity_type = 2;
+
+ // The entity name(s) being operated on the DDL statement.
+ // E.g.
+ // 1. For statement "CREATE TABLE t1(...)", `entity_names` = ["t1"].
+ // 2. For statement "GRANT ROLE r1, r2 ...", `entity_names` = ["r1", "r2"].
+ // 3. For statement "ANALYZE", `entity_names` = [].
+ repeated string entity_names = 3;
+}
+
+// Metadata type for the operation returned by
+// [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl].
+message UpdateDatabaseDdlMetadata {
+ // The database being modified.
+ string database = 1 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+
+ // For an update this list contains all the statements. For an
+ // individual statement, this list contains only that statement.
+ repeated string statements = 2;
+
+ // Reports the commit timestamps of all statements that have
+ // succeeded so far, where `commit_timestamps[i]` is the commit
+ // timestamp for the statement `statements[i]`.
+ repeated google.protobuf.Timestamp commit_timestamps = 3;
+
+ // Output only. When true, indicates that the operation is throttled e.g.
+ // due to resource constraints. When resources become available the operation
+ // will resume and this field will be false again.
+ bool throttled = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // The progress of the
+ // [UpdateDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.UpdateDatabaseDdl]
+ // operations. All DDL statements will have continuously updating progress,
+ // and `progress[i]` is the operation progress for `statements[i]`. Also,
+ // `progress[i]` will have start time and end time populated with commit
+ // timestamp of operation, as well as a progress of 100% once the operation
+ // has completed.
+ repeated OperationProgress progress = 5;
+
+ // The brief action info for the DDL statements.
+ // `actions[i]` is the brief info for `statements[i]`.
+ repeated DdlStatementActionInfo actions = 6;
+}
+
+// The request for
+// [DropDatabase][google.spanner.admin.database.v1.DatabaseAdmin.DropDatabase].
+message DropDatabaseRequest {
+ // Required. The database to be dropped.
+ string database = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+}
+
+// The request for
+// [GetDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.GetDatabaseDdl].
+message GetDatabaseDdlRequest {
+ // Required. The database whose schema we wish to get.
+ // Values are of the form
+ // `projects//instances//databases/`
+ string database = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+}
+
+// The response for
+// [GetDatabaseDdl][google.spanner.admin.database.v1.DatabaseAdmin.GetDatabaseDdl].
+message GetDatabaseDdlResponse {
+ // A list of formatted DDL statements defining the schema of the database
+ // specified in the request.
+ repeated string statements = 1;
+
+ // Proto descriptors stored in the database.
+ // Contains a protobuf-serialized
+ // [google.protobuf.FileDescriptorSet](https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/descriptor.proto).
+ // For more details, see protobuffer [self
+ // description](https://developers.google.com/protocol-buffers/docs/techniques#self-description).
+ bytes proto_descriptors = 2;
+}
+
+// The request for
+// [ListDatabaseOperations][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabaseOperations].
+message ListDatabaseOperationsRequest {
+ // Required. The instance of the database operations.
+ // Values are of the form `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // An expression that filters the list of returned operations.
+ //
+ // A filter expression consists of a field name, a
+ // comparison operator, and a value for filtering.
+ // The value must be a string, a number, or a boolean. The comparison operator
+ // must be one of: `<`, `>`, `<=`, `>=`, `!=`, `=`, or `:`.
+ // Colon `:` is the contains operator. Filter rules are not case sensitive.
+ //
+ // The following fields in the [Operation][google.longrunning.Operation]
+ // are eligible for filtering:
+ //
+ // * `name` - The name of the long-running operation
+ // * `done` - False if the operation is in progress, else true.
+ // * `metadata.@type` - the type of metadata. For example, the type string
+ // for
+ // [RestoreDatabaseMetadata][google.spanner.admin.database.v1.RestoreDatabaseMetadata]
+ // is
+ // `type.googleapis.com/google.spanner.admin.database.v1.RestoreDatabaseMetadata`.
+ // * `metadata.` - any field in metadata.value.
+ // `metadata.@type` must be specified first, if filtering on metadata
+ // fields.
+ // * `error` - Error associated with the long-running operation.
+ // * `response.@type` - the type of response.
+ // * `response.` - any field in response.value.
+ //
+ // You can combine multiple expressions by enclosing each expression in
+ // parentheses. By default, expressions are combined with AND logic. However,
+ // you can specify AND, OR, and NOT logic explicitly.
+ //
+ // Here are a few examples:
+ //
+ // * `done:true` - The operation is complete.
+ // * `(metadata.@type=type.googleapis.com/google.spanner.admin.database.v1.RestoreDatabaseMetadata) AND` \
+ // `(metadata.source_type:BACKUP) AND` \
+ // `(metadata.backup_info.backup:backup_howl) AND` \
+ // `(metadata.name:restored_howl) AND` \
+ // `(metadata.progress.start_time < \"2018-03-28T14:50:00Z\") AND` \
+ // `(error:*)` - Return operations where:
+ // * The operation's metadata type is
+ // [RestoreDatabaseMetadata][google.spanner.admin.database.v1.RestoreDatabaseMetadata].
+ // * The database is restored from a backup.
+ // * The backup name contains "backup_howl".
+ // * The restored database's name contains "restored_howl".
+ // * The operation started before 2018-03-28T14:50:00Z.
+ // * The operation resulted in an error.
+ string filter = 2;
+
+ // Number of operations to be returned in the response. If 0 or
+ // less, defaults to the server's maximum allowed page size.
+ int32 page_size = 3;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.database.v1.ListDatabaseOperationsResponse.next_page_token]
+ // from a previous
+ // [ListDatabaseOperationsResponse][google.spanner.admin.database.v1.ListDatabaseOperationsResponse]
+ // to the same `parent` and with the same `filter`.
+ string page_token = 4;
+}
+
+// The response for
+// [ListDatabaseOperations][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabaseOperations].
+message ListDatabaseOperationsResponse {
+ // The list of matching database [long-running
+ // operations][google.longrunning.Operation]. Each operation's name will be
+ // prefixed by the database's name. The operation's
+ // [metadata][google.longrunning.Operation.metadata] field type
+ // `metadata.type_url` describes the type of the metadata.
+ repeated google.longrunning.Operation operations = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListDatabaseOperations][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabaseOperations]
+ // call to fetch more of the matching metadata.
+ string next_page_token = 2;
+}
+
+// The request for
+// [RestoreDatabase][google.spanner.admin.database.v1.DatabaseAdmin.RestoreDatabase].
+message RestoreDatabaseRequest {
+ // Required. The name of the instance in which to create the
+ // restored database. This instance must be in the same project and
+ // have the same instance configuration as the instance containing
+ // the source backup. Values are of the form
+ // `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Required. The id of the database to create and restore to. This
+ // database must not already exist. The `database_id` appended to
+ // `parent` forms the full database name of the form
+ // `projects//instances//databases/`.
+ string database_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The source from which to restore.
+ oneof source {
+ // Name of the backup from which to restore. Values are of the form
+ // `projects//instances//backups/`.
+ string backup = 3 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Backup"
+ }];
+ }
+
+ // Optional. An encryption configuration describing the encryption type and
+ // key resources in Cloud KMS used to encrypt/decrypt the database to restore
+ // to. If this field is not specified, the restored database will use the same
+ // encryption configuration as the backup by default, namely
+ // [encryption_type][google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig.encryption_type]
+ // = `USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION`.
+ RestoreDatabaseEncryptionConfig encryption_config = 4
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// Encryption configuration for the restored database.
+message RestoreDatabaseEncryptionConfig {
+ // Encryption types for the database to be restored.
+ enum EncryptionType {
+ // Unspecified. Do not use.
+ ENCRYPTION_TYPE_UNSPECIFIED = 0;
+
+ // This is the default option when
+ // [encryption_config][google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig]
+ // is not specified.
+ USE_CONFIG_DEFAULT_OR_BACKUP_ENCRYPTION = 1;
+
+ // Use Google default encryption.
+ GOOGLE_DEFAULT_ENCRYPTION = 2;
+
+ // Use customer managed encryption. If specified, `kms_key_name` must
+ // must contain a valid Cloud KMS key.
+ CUSTOMER_MANAGED_ENCRYPTION = 3;
+ }
+
+ // Required. The encryption type of the restored database.
+ EncryptionType encryption_type = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The Cloud KMS key that will be used to encrypt/decrypt the
+ // restored database. This field should be set only when
+ // [encryption_type][google.spanner.admin.database.v1.RestoreDatabaseEncryptionConfig.encryption_type]
+ // is `CUSTOMER_MANAGED_ENCRYPTION`. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ string kms_key_name = 2 [
+ (google.api.field_behavior) = OPTIONAL,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }
+ ];
+
+ // Optional. Specifies the KMS configuration for the one or more keys used to
+ // encrypt the database. Values are of the form
+ // `projects//locations//keyRings//cryptoKeys/`.
+ //
+ // The keys referenced by kms_key_names must fully cover all
+ // regions of the database instance configuration. Some examples:
+ // * For single region database instance configs, specify a single regional
+ // location KMS key.
+ // * For multi-regional database instance configs of type GOOGLE_MANAGED,
+ // either specify a multi-regional location KMS key or multiple regional
+ // location KMS keys that cover all regions in the instance config.
+ // * For a database instance config of type USER_MANAGED, please specify only
+ // regional location KMS keys to cover each region in the instance config.
+ // Multi-regional location KMS keys are not supported for USER_MANAGED
+ // instance configs.
+ repeated string kms_key_names = 3 [
+ (google.api.field_behavior) = OPTIONAL,
+ (google.api.resource_reference) = {
+ type: "cloudkms.googleapis.com/CryptoKey"
+ }
+ ];
+}
+
+// Metadata type for the long-running operation returned by
+// [RestoreDatabase][google.spanner.admin.database.v1.DatabaseAdmin.RestoreDatabase].
+message RestoreDatabaseMetadata {
+ // Name of the database being created and restored to.
+ string name = 1 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+
+ // The type of the restore source.
+ RestoreSourceType source_type = 2;
+
+ // Information about the source used to restore the database, as specified by
+ // `source` in
+ // [RestoreDatabaseRequest][google.spanner.admin.database.v1.RestoreDatabaseRequest].
+ oneof source_info {
+ // Information about the backup used to restore the database.
+ BackupInfo backup_info = 3;
+ }
+
+ // The progress of the
+ // [RestoreDatabase][google.spanner.admin.database.v1.DatabaseAdmin.RestoreDatabase]
+ // operation.
+ OperationProgress progress = 4;
+
+ // The time at which cancellation of this operation was received.
+ // [Operations.CancelOperation][google.longrunning.Operations.CancelOperation]
+ // starts asynchronous cancellation on a long-running operation. The server
+ // makes a best effort to cancel the operation, but success is not guaranteed.
+ // Clients can use
+ // [Operations.GetOperation][google.longrunning.Operations.GetOperation] or
+ // other methods to check whether the cancellation succeeded or whether the
+ // operation completed despite cancellation. On successful cancellation,
+ // the operation is not deleted; instead, it becomes an operation with
+ // an [Operation.error][google.longrunning.Operation.error] value with a
+ // [google.rpc.Status.code][google.rpc.Status.code] of 1, corresponding to
+ // `Code.CANCELLED`.
+ google.protobuf.Timestamp cancel_time = 5;
+
+ // If exists, the name of the long-running operation that will be used to
+ // track the post-restore optimization process to optimize the performance of
+ // the restored database, and remove the dependency on the restore source.
+ // The name is of the form
+ // `projects//instances//databases//operations/`
+ // where the is the name of database being created and restored to.
+ // The metadata type of the long-running operation is
+ // [OptimizeRestoredDatabaseMetadata][google.spanner.admin.database.v1.OptimizeRestoredDatabaseMetadata].
+ // This long-running operation will be automatically created by the system
+ // after the RestoreDatabase long-running operation completes successfully.
+ // This operation will not be created if the restore was not successful.
+ string optimize_database_operation_name = 6;
+}
+
+// Metadata type for the long-running operation used to track the progress
+// of optimizations performed on a newly restored database. This long-running
+// operation is automatically created by the system after the successful
+// completion of a database restore, and cannot be cancelled.
+message OptimizeRestoredDatabaseMetadata {
+ // Name of the restored database being optimized.
+ string name = 1 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }];
+
+ // The progress of the post-restore optimizations.
+ OperationProgress progress = 2;
+}
+
+// Indicates the type of the restore source.
+enum RestoreSourceType {
+ // No restore associated.
+ TYPE_UNSPECIFIED = 0;
+
+ // A backup was used as the source of the restore.
+ BACKUP = 1;
+}
+
+// A Cloud Spanner database role.
+message DatabaseRole {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/DatabaseRole"
+ pattern: "projects/{project}/instances/{instance}/databases/{database}/databaseRoles/{role}"
+ };
+
+ // Required. The name of the database role. Values are of the form
+ // `projects//instances//databases//databaseRoles/`
+ // where `` is as specified in the `CREATE ROLE` DDL statement.
+ string name = 1 [(google.api.field_behavior) = REQUIRED];
+}
+
+// The request for
+// [ListDatabaseRoles][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabaseRoles].
+message ListDatabaseRolesRequest {
+ // Required. The database whose roles should be listed.
+ // Values are of the form
+ // `projects//instances//databases/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Number of database roles to be returned in the response. If 0 or less,
+ // defaults to the server's maximum allowed page size.
+ int32 page_size = 2;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.database.v1.ListDatabaseRolesResponse.next_page_token]
+ // from a previous
+ // [ListDatabaseRolesResponse][google.spanner.admin.database.v1.ListDatabaseRolesResponse].
+ string page_token = 3;
+}
+
+// The response for
+// [ListDatabaseRoles][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabaseRoles].
+message ListDatabaseRolesResponse {
+ // Database roles that matched the request.
+ repeated DatabaseRole database_roles = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListDatabaseRoles][google.spanner.admin.database.v1.DatabaseAdmin.ListDatabaseRoles]
+ // call to fetch more of the matching roles.
+ string next_page_token = 2;
+}
+
+// The request for
+// [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+message AddSplitPointsRequest {
+ // Required. The database on whose tables/indexes split points are to be
+ // added. Values are of the form
+ // `projects//instances//databases/`.
+ string database = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Database"
+ }
+ ];
+
+ // Required. The split points to add.
+ repeated SplitPoints split_points = 2
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. A user-supplied tag associated with the split points.
+ // For example, "intital_data_load", "special_event_1".
+ // Defaults to "CloudAddSplitPointsAPI" if not specified.
+ // The length of the tag must not exceed 50 characters,else will be trimmed.
+ // Only valid UTF8 characters are allowed.
+ string initiator = 3 [(google.api.field_behavior) = OPTIONAL];
+}
+
+// The response for
+// [AddSplitPoints][google.spanner.admin.database.v1.DatabaseAdmin.AddSplitPoints].
+message AddSplitPointsResponse {}
+
+// The split points of a table/index.
+message SplitPoints {
+ // A split key.
+ message Key {
+ // Required. The column values making up the split key.
+ google.protobuf.ListValue key_parts = 1
+ [(google.api.field_behavior) = REQUIRED];
+ }
+
+ // The table to split.
+ string table = 1;
+
+ // The index to split.
+ // If specified, the `table` field must refer to the index's base table.
+ string index = 2;
+
+ // Required. The list of split keys, i.e., the split boundaries.
+ repeated Key keys = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. The expiration timestamp of the split points.
+ // A timestamp in the past means immediate expiration.
+ // The maximum value can be 30 days in the future.
+ // Defaults to 10 days in the future if not specified.
+ google.protobuf.Timestamp expire_time = 5
+ [(google.api.field_behavior) = OPTIONAL];
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_gapic.yaml b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_gapic.yaml
new file mode 100644
index 00000000..7ea1f7e8
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/database/v1/spanner_gapic.yaml
@@ -0,0 +1,32 @@
+type: com.google.api.codegen.ConfigProto
+config_schema_version: 2.0.0
+language_settings:
+ java:
+ package_name: com.google.cloud.spanner.admin.database.v1
+interfaces:
+- name: google.spanner.admin.database.v1.DatabaseAdmin
+ methods:
+ - name: CreateDatabase
+ long_running:
+ initial_poll_delay_millis: 20000
+ poll_delay_multiplier: 1.5
+ max_poll_delay_millis: 45000
+ total_poll_timeout_millis: 86400000
+ - name: UpdateDatabaseDdl
+ long_running:
+ initial_poll_delay_millis: 20000
+ poll_delay_multiplier: 1.5
+ max_poll_delay_millis: 45000
+ total_poll_timeout_millis: 86400000
+ - name: CreateBackup
+ long_running:
+ initial_poll_delay_millis: 20000
+ poll_delay_multiplier: 1.5
+ max_poll_delay_millis: 45000
+ total_poll_timeout_millis: 172800000
+ - name: RestoreDatabase
+ long_running:
+ initial_poll_delay_millis: 20000
+ poll_delay_multiplier: 1.5
+ max_poll_delay_millis: 45000
+ total_poll_timeout_millis: 86400000
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/BUILD.bazel
new file mode 100644
index 00000000..a87c57fe
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/BUILD.bazel
@@ -0,0 +1 @@
+exports_files(glob(["*.yaml"]))
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/BUILD.bazel b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/BUILD.bazel
new file mode 100644
index 00000000..e0fb900e
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/BUILD.bazel
@@ -0,0 +1,336 @@
+# This file was automatically generated by BuildFileGenerator
+
+load(
+ "@com_google_googleapis_imports//:imports.bzl",
+ "cc_grpc_library",
+ "cc_proto_library",
+ "csharp_gapic_assembly_pkg",
+ "csharp_gapic_library",
+ "csharp_grpc_library",
+ "csharp_proto_library",
+ "go_gapic_assembly_pkg",
+ "go_gapic_library",
+ "go_proto_library",
+ "java_gapic_assembly_gradle_pkg",
+ "java_gapic_library",
+ "java_gapic_test",
+ "java_grpc_library",
+ "java_proto_library",
+ "nodejs_gapic_assembly_pkg",
+ "nodejs_gapic_library",
+ "php_gapic_assembly_pkg",
+ "php_gapic_library",
+ "php_proto_library",
+ "proto_library_with_info",
+ "py_gapic_assembly_pkg",
+ "py_gapic_library",
+ "py_test",
+ "ruby_cloud_gapic_library",
+ "ruby_gapic_assembly_pkg",
+ "ruby_grpc_library",
+ "ruby_proto_library",
+)
+
+##############################################################################
+# Common
+##############################################################################
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+# This is an API workspace, having public visibility by default makes perfect sense.
+package(default_visibility = ["//visibility:public"])
+
+proto_library(
+ name = "instance_proto",
+ srcs = [
+ "common.proto",
+ "spanner_instance_admin.proto",
+ ],
+ deps = [
+ "//google/api:annotations_proto",
+ "//google/api:client_proto",
+ "//google/api:field_behavior_proto",
+ "//google/api:resource_proto",
+ "//google/iam/v1:iam_policy_proto",
+ "//google/iam/v1:policy_proto",
+ "//google/longrunning:operations_proto",
+ "@com_google_protobuf//:empty_proto",
+ "@com_google_protobuf//:field_mask_proto",
+ "@com_google_protobuf//:timestamp_proto",
+ ],
+)
+
+proto_library_with_info(
+ name = "instance_proto_with_info",
+ deps = [
+ ":instance_proto",
+ "//google/cloud:common_resources_proto",
+ ],
+)
+
+java_proto_library(
+ name = "instance_java_proto",
+ deps = [":instance_proto"],
+)
+
+java_grpc_library(
+ name = "instance_java_grpc",
+ srcs = [":instance_proto"],
+ deps = [":instance_java_proto"],
+)
+
+java_gapic_library(
+ name = "instance_java_gapic",
+ srcs = [":instance_proto_with_info"],
+ gapic_yaml = "spanner_gapic.yaml",
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ test_deps = [
+ ":instance_java_grpc",
+ "//google/iam/v1:iam_java_grpc",
+ ],
+ transport = "grpc+rest",
+ deps = [
+ ":instance_java_proto",
+ "//google/api:api_java_proto",
+ "//google/iam/v1:iam_java_proto",
+ ],
+)
+
+java_gapic_test(
+ name = "instance_java_gapic_test_suite",
+ test_classes = [
+ "com.google.cloud.spanner.admin.instance.v1.InstanceAdminClientHttpJsonTest",
+ "com.google.cloud.spanner.admin.instance.v1.InstanceAdminClientTest",
+ ],
+ runtime_deps = [":instance_java_gapic_test"],
+)
+
+# Open Source Packages
+java_gapic_assembly_gradle_pkg(
+ name = "google-cloud-admin-instance-v1-java",
+ include_samples = True,
+ transport = "grpc+rest",
+ deps = [
+ ":instance_java_gapic",
+ ":instance_java_grpc",
+ ":instance_java_proto",
+ ":instance_proto",
+ ],
+)
+
+go_proto_library(
+ name = "instance_go_proto",
+ compilers = ["@io_bazel_rules_go//proto:go_grpc"],
+ importpath = "cloud.google.com/go/spanner/admin/instance/apiv1/instancepb",
+ protos = [":instance_proto"],
+ deps = [
+ "//google/api:annotations_go_proto",
+ "//google/iam/v1:iam_go_proto",
+ "//google/longrunning:longrunning_go_proto",
+ ],
+)
+
+go_gapic_library(
+ name = "instance_go_gapic",
+ srcs = [":instance_proto_with_info"],
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ importpath = "cloud.google.com/go/spanner/admin/instance/apiv1;instance",
+ release_level = "ga",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":instance_go_proto",
+ "//google/iam/v1:iam_go_proto",
+ "//google/longrunning:longrunning_go_proto",
+ "@com_google_cloud_go_longrunning//:go_default_library",
+ "@com_google_cloud_go_longrunning//autogen:go_default_library",
+ ],
+)
+
+# Open Source Packages
+go_gapic_assembly_pkg(
+ name = "gapi-cloud-admin-instance-v1-go",
+ deps = [
+ ":instance_go_gapic",
+ ":instance_go_gapic_srcjar-snippets.srcjar",
+ ":instance_go_gapic_srcjar-test.srcjar",
+ ":instance_go_proto",
+ ],
+)
+
+py_gapic_library(
+ name = "instance_py_gapic",
+ srcs = [":instance_proto"],
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ opt_args = [
+ "python-gapic-namespace=google.cloud",
+ "python-gapic-name=spanner_admin_instance",
+ ],
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ "//google/iam/v1:iam_policy_py_proto",
+ ],
+)
+
+py_test(
+ name = "instance_py_gapic_test",
+ srcs = [
+ "instance_py_gapic_pytest.py",
+ "instance_py_gapic_test.py",
+ ],
+ legacy_create_init = False,
+ deps = [":instance_py_gapic"],
+)
+
+py_gapic_assembly_pkg(
+ name = "admin-instance-v1-py",
+ deps = [
+ ":instance_py_gapic",
+ ],
+)
+
+php_proto_library(
+ name = "instance_php_proto",
+ deps = [":instance_proto"],
+)
+
+php_gapic_library(
+ name = "instance_php_gapic",
+ srcs = [":instance_proto_with_info"],
+ gapic_yaml = "spanner_gapic.yaml",
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ migration_mode = "MIGRATING",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [":instance_php_proto"],
+)
+
+# Open Source Packages
+php_gapic_assembly_pkg(
+ name = "google-cloud-admin-instance-v1-php",
+ deps = [
+ ":instance_php_gapic",
+ ":instance_php_proto",
+ ],
+)
+
+nodejs_gapic_library(
+ name = "instance_nodejs_gapic",
+ package_name = "@google-cloud/spanner",
+ src = ":instance_proto_with_info",
+ extra_protoc_parameters = [
+ "metadata",
+ "template=typescript_gapic",
+ ],
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ handwritten_layer = True,
+ package = "google.spanner.admin.instance.v1",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [],
+)
+
+nodejs_gapic_assembly_pkg(
+ name = "admin-instance-v1-nodejs",
+ deps = [
+ ":instance_nodejs_gapic",
+ ":instance_proto",
+ ],
+)
+
+ruby_proto_library(
+ name = "instance_ruby_proto",
+ deps = [":instance_proto"],
+)
+
+ruby_grpc_library(
+ name = "instance_ruby_grpc",
+ srcs = [":instance_proto"],
+ deps = [":instance_ruby_proto"],
+)
+
+ruby_cloud_gapic_library(
+ name = "instance_ruby_gapic",
+ srcs = [":instance_proto_with_info"],
+ extra_protoc_parameters = [
+ "ruby-cloud-gem-name=google-cloud-spanner-admin-instance-v1",
+ "ruby-cloud-env-prefix=SPANNER",
+ "ruby-cloud-product-url=https://cloud.google.com/spanner",
+ "ruby-cloud-api-id=spanner.googleapis.com",
+ "ruby-cloud-api-shortname=spanner",
+ "ruby-cloud-wrapper-gem-override=google-cloud-spanner",
+ ],
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ rest_numeric_enums = True,
+ ruby_cloud_description = "Cloud Spanner is a managed, mission-critical, globally consistent and scalable relational database service.",
+ ruby_cloud_title = "Cloud Spanner Instance Admin V1",
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":instance_ruby_grpc",
+ ":instance_ruby_proto",
+ ],
+)
+
+# Open Source Packages
+ruby_gapic_assembly_pkg(
+ name = "google-cloud-admin-instance-v1-ruby",
+ deps = [
+ ":instance_ruby_gapic",
+ ":instance_ruby_grpc",
+ ":instance_ruby_proto",
+ ],
+)
+
+csharp_proto_library(
+ name = "instance_csharp_proto",
+ deps = [":instance_proto"],
+)
+
+csharp_grpc_library(
+ name = "instance_csharp_grpc",
+ srcs = [":instance_proto"],
+ deps = [":instance_csharp_proto"],
+)
+
+csharp_gapic_library(
+ name = "instance_csharp_gapic",
+ srcs = [":instance_proto_with_info"],
+ common_resources_config = "@gax_dotnet//:Google.Api.Gax/ResourceNames/CommonResourcesConfig.json",
+ grpc_service_config = "spanner_admin_instance_grpc_service_config.json",
+ rest_numeric_enums = True,
+ service_yaml = "spanner.yaml",
+ transport = "grpc+rest",
+ deps = [
+ ":instance_csharp_grpc",
+ ":instance_csharp_proto",
+ ],
+)
+
+# Open Source Packages
+csharp_gapic_assembly_pkg(
+ name = "google-cloud-admin-instance-v1-csharp",
+ deps = [
+ ":instance_csharp_gapic",
+ ":instance_csharp_grpc",
+ ":instance_csharp_proto",
+ ],
+)
+
+cc_proto_library(
+ name = "instance_cc_proto",
+ deps = [":instance_proto"],
+)
+
+cc_grpc_library(
+ name = "instance_cc_grpc",
+ srcs = [":instance_proto"],
+ grpc_only = True,
+ deps = [":instance_cc_proto"],
+)
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/common.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/common.proto
new file mode 100644
index 00000000..0b5282c7
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/common.proto
@@ -0,0 +1,64 @@
+// 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
+//
+// 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.admin.instance.v1;
+
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/protobuf/timestamp.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Admin.Instance.V1";
+option go_package = "cloud.google.com/go/spanner/admin/instance/apiv1/instancepb;instancepb";
+option java_multiple_files = true;
+option java_outer_classname = "CommonProto";
+option java_package = "com.google.spanner.admin.instance.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Instance\\V1";
+option ruby_package = "Google::Cloud::Spanner::Admin::Instance::V1";
+
+// Encapsulates progress related information for a Cloud Spanner long
+// running instance operations.
+message OperationProgress {
+ // Percent completion of the operation.
+ // Values are between 0 and 100 inclusive.
+ int32 progress_percent = 1;
+
+ // Time the request was received.
+ google.protobuf.Timestamp start_time = 2;
+
+ // If set, the time at which this operation failed or was completed
+ // successfully.
+ google.protobuf.Timestamp end_time = 3;
+}
+
+// Indicates the expected fulfillment period of an operation.
+enum FulfillmentPeriod {
+ // Not specified.
+ FULFILLMENT_PERIOD_UNSPECIFIED = 0;
+
+ // Normal fulfillment period. The operation is expected to complete within
+ // minutes.
+ FULFILLMENT_PERIOD_NORMAL = 1;
+
+ // Extended fulfillment period. It can take up to an hour for the operation
+ // to complete.
+ FULFILLMENT_PERIOD_EXTENDED = 2;
+}
+
+// ReplicaSelection identifies replicas with common properties.
+message ReplicaSelection {
+ // Required. Name of the location of the replicas (e.g., "us-central1").
+ string location = 1 [(google.api.field_behavior) = REQUIRED];
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner.yaml b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner.yaml
new file mode 100644
index 00000000..04941812
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner.yaml
@@ -0,0 +1,73 @@
+type: google.api.Service
+config_version: 3
+name: spanner.googleapis.com
+title: Cloud Spanner API
+
+apis:
+- name: google.longrunning.Operations
+- name: google.spanner.admin.instance.v1.InstanceAdmin
+
+types:
+- name: google.spanner.admin.instance.v1.CreateInstanceConfigMetadata
+- name: google.spanner.admin.instance.v1.CreateInstanceMetadata
+- name: google.spanner.admin.instance.v1.CreateInstancePartitionMetadata
+- name: google.spanner.admin.instance.v1.UpdateInstanceConfigMetadata
+- name: google.spanner.admin.instance.v1.UpdateInstanceMetadata
+- name: google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata
+
+documentation:
+ summary: |-
+ Cloud Spanner is a managed, mission-critical, globally consistent and
+ scalable relational database service.
+
+http:
+ rules:
+ - selector: google.longrunning.Operations.CancelOperation
+ post: '/v1/{name=projects/*/instances/*/databases/*/operations/*}:cancel'
+ additional_bindings:
+ - post: '/v1/{name=projects/*/instances/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instances/*/backups/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instanceConfigs/*/operations/*}:cancel'
+ - post: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}:cancel'
+ - selector: google.longrunning.Operations.DeleteOperation
+ delete: '/v1/{name=projects/*/instances/*/databases/*/operations/*}'
+ additional_bindings:
+ - delete: '/v1/{name=projects/*/instances/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instances/*/backups/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instanceConfigs/*/operations/*}'
+ - delete: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}'
+ - selector: google.longrunning.Operations.GetOperation
+ get: '/v1/{name=projects/*/instances/*/databases/*/operations/*}'
+ additional_bindings:
+ - get: '/v1/{name=projects/*/instances/*/operations/*}'
+ - get: '/v1/{name=projects/*/instances/*/backups/*/operations/*}'
+ - get: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations/*}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/operations/*}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations/*}'
+ - selector: google.longrunning.Operations.ListOperations
+ get: '/v1/{name=projects/*/instances/*/databases/*/operations}'
+ additional_bindings:
+ - get: '/v1/{name=projects/*/instances/*/operations}'
+ - get: '/v1/{name=projects/*/instances/*/backups/*/operations}'
+ - get: '/v1/{name=projects/*/instances/*/instancePartitions/*/operations}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/operations}'
+ - get: '/v1/{name=projects/*/instanceConfigs/*/ssdCaches/*/operations}'
+
+authentication:
+ rules:
+ - selector: 'google.longrunning.Operations.*'
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.admin
+ - selector: 'google.spanner.admin.instance.v1.InstanceAdmin.*'
+ oauth:
+ canonical_scopes: |-
+ https://www.googleapis.com/auth/cloud-platform,
+ https://www.googleapis.com/auth/spanner.admin
+
+publishing:
+ new_issue_uri: https://issuetracker.google.com/issues/new?component=190851&template=0
+ documentation_uri: https://cloud.google.com/spanner/
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_admin_instance_grpc_service_config.json b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_admin_instance_grpc_service_config.json
new file mode 100755
index 00000000..f1241560
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_admin_instance_grpc_service_config.json
@@ -0,0 +1,82 @@
+{
+ "methodConfig": [
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "ListInstanceConfigs"
+ },
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "GetInstanceConfig"
+ },
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "ListInstances"
+ },
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "GetInstance"
+ },
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "DeleteInstance"
+ }
+ ],
+ "timeout": "3600s",
+ "retryPolicy": {
+ "initialBackoff": "1s",
+ "maxBackoff": "32s",
+ "backoffMultiplier": 1.3,
+ "retryableStatusCodes": [
+ "UNAVAILABLE",
+ "DEADLINE_EXCEEDED"
+ ]
+ }
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "GetIamPolicy"
+ }
+ ],
+ "timeout": "30s",
+ "retryPolicy": {
+ "initialBackoff": "1s",
+ "maxBackoff": "32s",
+ "backoffMultiplier": 1.3,
+ "retryableStatusCodes": [
+ "UNAVAILABLE",
+ "DEADLINE_EXCEEDED"
+ ]
+ }
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "CreateInstance"
+ },
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "UpdateInstance"
+ }
+ ],
+ "timeout": "3600s"
+ },
+ {
+ "name": [
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "SetIamPolicy"
+ },
+ {
+ "service": "google.spanner.admin.instance.v1.InstanceAdmin",
+ "method": "TestIamPermissions"
+ }
+ ],
+ "timeout": "30s"
+ }
+ ]
+}
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_gapic.yaml b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_gapic.yaml
new file mode 100644
index 00000000..89d4488b
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_gapic.yaml
@@ -0,0 +1,20 @@
+type: com.google.api.codegen.ConfigProto
+config_schema_version: 2.0.0
+language_settings:
+ java:
+ package_name: com.google.cloud.spanner.admin.instance.v1
+interfaces:
+- name: google.spanner.admin.instance.v1.InstanceAdmin
+ methods:
+ - name: CreateInstance
+ long_running:
+ initial_poll_delay_millis: 20000
+ poll_delay_multiplier: 1.5
+ max_poll_delay_millis: 45000
+ total_poll_timeout_millis: 86400000
+ - name: UpdateInstance
+ long_running:
+ initial_poll_delay_millis: 20000
+ poll_delay_multiplier: 1.5
+ max_poll_delay_millis: 45000
+ total_poll_timeout_millis: 86400000
diff --git a/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_instance_admin.proto b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_instance_admin.proto
new file mode 100644
index 00000000..d3e60257
--- /dev/null
+++ b/spannerlib/dotnet-spannerlib/Google.Cloud.SpannerLib.Grpc/google/spanner/admin/instance/v1/spanner_instance_admin.proto
@@ -0,0 +1,2110 @@
+// 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
+//
+// 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.admin.instance.v1;
+
+import "google/api/annotations.proto";
+import "google/api/client.proto";
+import "google/api/field_behavior.proto";
+import "google/api/resource.proto";
+import "google/iam/v1/iam_policy.proto";
+import "google/iam/v1/policy.proto";
+import "google/longrunning/operations.proto";
+import "google/protobuf/empty.proto";
+import "google/protobuf/field_mask.proto";
+import "google/protobuf/timestamp.proto";
+import "google/spanner/admin/instance/v1/common.proto";
+
+option csharp_namespace = "Google.Cloud.Spanner.Admin.Instance.V1";
+option go_package = "cloud.google.com/go/spanner/admin/instance/apiv1/instancepb;instancepb";
+option java_multiple_files = true;
+option java_outer_classname = "SpannerInstanceAdminProto";
+option java_package = "com.google.spanner.admin.instance.v1";
+option php_namespace = "Google\\Cloud\\Spanner\\Admin\\Instance\\V1";
+option ruby_package = "Google::Cloud::Spanner::Admin::Instance::V1";
+
+// Cloud Spanner Instance Admin API
+//
+// The Cloud Spanner Instance Admin API can be used to create, delete,
+// modify and list instances. Instances are dedicated Cloud Spanner serving
+// and storage resources to be used by Cloud Spanner databases.
+//
+// Each instance has a "configuration", which dictates where the
+// serving resources for the Cloud Spanner instance are located (e.g.,
+// US-central, Europe). Configurations are created by Google based on
+// resource availability.
+//
+// Cloud Spanner billing is based on the instances that exist and their
+// sizes. After an instance exists, there are no additional
+// per-database or per-operation charges for use of the instance
+// (though there may be additional network bandwidth charges).
+// Instances offer isolation: problems with databases in one instance
+// will not affect other instances. However, within an instance
+// databases can affect each other. For example, if one database in an
+// instance receives a lot of requests and consumes most of the
+// instance resources, fewer resources are available for other
+// databases in that instance, and their performance may suffer.
+service InstanceAdmin {
+ option (google.api.default_host) = "spanner.googleapis.com";
+ option (google.api.oauth_scopes) =
+ "https://www.googleapis.com/auth/cloud-platform,"
+ "https://www.googleapis.com/auth/spanner.admin";
+
+ // Lists the supported instance configurations for a given project.
+ //
+ // Returns both Google-managed configurations and user-managed
+ // configurations.
+ rpc ListInstanceConfigs(ListInstanceConfigsRequest)
+ returns (ListInstanceConfigsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*}/instanceConfigs"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Gets information about a particular instance configuration.
+ rpc GetInstanceConfig(GetInstanceConfigRequest) returns (InstanceConfig) {
+ option (google.api.http) = {
+ get: "/v1/{name=projects/*/instanceConfigs/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Creates an instance configuration and begins preparing it to be used. The
+ // returned long-running operation
+ // can be used to track the progress of preparing the new
+ // instance configuration. The instance configuration name is assigned by the
+ // caller. If the named instance configuration already exists,
+ // `CreateInstanceConfig` returns `ALREADY_EXISTS`.
+ //
+ // Immediately after the request returns:
+ //
+ // * The instance configuration is readable via the API, with all requested
+ // attributes. The instance configuration's
+ // [reconciling][google.spanner.admin.instance.v1.InstanceConfig.reconciling]
+ // field is set to true. Its state is `CREATING`.
+ //
+ // While the operation is pending:
+ //
+ // * Cancelling the operation renders the instance configuration immediately
+ // unreadable via the API.
+ // * Except for deleting the creating resource, all other attempts to modify
+ // the instance configuration are rejected.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * Instances can be created using the instance configuration.
+ // * The instance configuration's
+ // [reconciling][google.spanner.admin.instance.v1.InstanceConfig.reconciling]
+ // field becomes false. Its state becomes `READY`.
+ //
+ // The returned long-running operation will
+ // have a name of the format
+ // `/operations/` and can be used to track
+ // creation of the instance configuration. The
+ // metadata field type is
+ // [CreateInstanceConfigMetadata][google.spanner.admin.instance.v1.CreateInstanceConfigMetadata].
+ // The response field type is
+ // [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig], if
+ // successful.
+ //
+ // Authorization requires `spanner.instanceConfigs.create` permission on
+ // the resource
+ // [parent][google.spanner.admin.instance.v1.CreateInstanceConfigRequest.parent].
+ rpc CreateInstanceConfig(CreateInstanceConfigRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*}/instanceConfigs"
+ body: "*"
+ };
+ option (google.api.method_signature) =
+ "parent,instance_config,instance_config_id";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.InstanceConfig"
+ metadata_type: "google.spanner.admin.instance.v1.CreateInstanceConfigMetadata"
+ };
+ }
+
+ // Updates an instance configuration. The returned
+ // long-running operation can be used to track
+ // the progress of updating the instance. If the named instance configuration
+ // does not exist, returns `NOT_FOUND`.
+ //
+ // Only user-managed configurations can be updated.
+ //
+ // Immediately after the request returns:
+ //
+ // * The instance configuration's
+ // [reconciling][google.spanner.admin.instance.v1.InstanceConfig.reconciling]
+ // field is set to true.
+ //
+ // While the operation is pending:
+ //
+ // * Cancelling the operation sets its metadata's
+ // [cancel_time][google.spanner.admin.instance.v1.UpdateInstanceConfigMetadata.cancel_time].
+ // The operation is guaranteed to succeed at undoing all changes, after
+ // which point it terminates with a `CANCELLED` status.
+ // * All other attempts to modify the instance configuration are rejected.
+ // * Reading the instance configuration via the API continues to give the
+ // pre-request values.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * Creating instances using the instance configuration uses the new
+ // values.
+ // * The new values of the instance configuration are readable via the API.
+ // * The instance configuration's
+ // [reconciling][google.spanner.admin.instance.v1.InstanceConfig.reconciling]
+ // field becomes false.
+ //
+ // The returned long-running operation will
+ // have a name of the format
+ // `/operations/` and can be used to track
+ // the instance configuration modification. The
+ // metadata field type is
+ // [UpdateInstanceConfigMetadata][google.spanner.admin.instance.v1.UpdateInstanceConfigMetadata].
+ // The response field type is
+ // [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig], if
+ // successful.
+ //
+ // Authorization requires `spanner.instanceConfigs.update` permission on
+ // the resource [name][google.spanner.admin.instance.v1.InstanceConfig.name].
+ rpc UpdateInstanceConfig(UpdateInstanceConfigRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ patch: "/v1/{instance_config.name=projects/*/instanceConfigs/*}"
+ body: "*"
+ };
+ option (google.api.method_signature) = "instance_config,update_mask";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.InstanceConfig"
+ metadata_type: "google.spanner.admin.instance.v1.UpdateInstanceConfigMetadata"
+ };
+ }
+
+ // Deletes the instance configuration. Deletion is only allowed when no
+ // instances are using the configuration. If any instances are using
+ // the configuration, returns `FAILED_PRECONDITION`.
+ //
+ // Only user-managed configurations can be deleted.
+ //
+ // Authorization requires `spanner.instanceConfigs.delete` permission on
+ // the resource [name][google.spanner.admin.instance.v1.InstanceConfig.name].
+ rpc DeleteInstanceConfig(DeleteInstanceConfigRequest)
+ returns (google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/v1/{name=projects/*/instanceConfigs/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Lists the user-managed instance configuration long-running
+ // operations in the given project. An instance
+ // configuration operation has a name of the form
+ // `projects//instanceConfigs//operations/`.
+ // The long-running operation
+ // metadata field type
+ // `metadata.type_url` describes the type of the metadata. Operations returned
+ // include those that have completed/failed/canceled within the last 7 days,
+ // and pending operations. Operations returned are ordered by
+ // `operation.metadata.value.start_time` in descending order starting
+ // from the most recently started operation.
+ rpc ListInstanceConfigOperations(ListInstanceConfigOperationsRequest)
+ returns (ListInstanceConfigOperationsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*}/instanceConfigOperations"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Lists all instances in the given project.
+ rpc ListInstances(ListInstancesRequest) returns (ListInstancesResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*}/instances"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Lists all instance partitions for the given instance.
+ rpc ListInstancePartitions(ListInstancePartitionsRequest)
+ returns (ListInstancePartitionsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*}/instancePartitions"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Gets information about a particular instance.
+ rpc GetInstance(GetInstanceRequest) returns (Instance) {
+ option (google.api.http) = {
+ get: "/v1/{name=projects/*/instances/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Creates an instance and begins preparing it to begin serving. The
+ // returned long-running operation
+ // can be used to track the progress of preparing the new
+ // instance. The instance name is assigned by the caller. If the
+ // named instance already exists, `CreateInstance` returns
+ // `ALREADY_EXISTS`.
+ //
+ // Immediately upon completion of this request:
+ //
+ // * The instance is readable via the API, with all requested attributes
+ // but no allocated resources. Its state is `CREATING`.
+ //
+ // Until completion of the returned operation:
+ //
+ // * Cancelling the operation renders the instance immediately unreadable
+ // via the API.
+ // * The instance can be deleted.
+ // * All other attempts to modify the instance are rejected.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * Billing for all successfully-allocated resources begins (some types
+ // may have lower than the requested levels).
+ // * Databases can be created in the instance.
+ // * The instance's allocated resource levels are readable via the API.
+ // * The instance's state becomes `READY`.
+ //
+ // The returned long-running operation will
+ // have a name of the format `/operations/` and
+ // can be used to track creation of the instance. The
+ // metadata field type is
+ // [CreateInstanceMetadata][google.spanner.admin.instance.v1.CreateInstanceMetadata].
+ // The response field type is
+ // [Instance][google.spanner.admin.instance.v1.Instance], if successful.
+ rpc CreateInstance(CreateInstanceRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*}/instances"
+ body: "*"
+ };
+ option (google.api.method_signature) = "parent,instance_id,instance";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.Instance"
+ metadata_type: "google.spanner.admin.instance.v1.CreateInstanceMetadata"
+ };
+ }
+
+ // Updates an instance, and begins allocating or releasing resources
+ // as requested. The returned long-running operation can be used to track the
+ // progress of updating the instance. If the named instance does not
+ // exist, returns `NOT_FOUND`.
+ //
+ // Immediately upon completion of this request:
+ //
+ // * For resource types for which a decrease in the instance's allocation
+ // has been requested, billing is based on the newly-requested level.
+ //
+ // Until completion of the returned operation:
+ //
+ // * Cancelling the operation sets its metadata's
+ // [cancel_time][google.spanner.admin.instance.v1.UpdateInstanceMetadata.cancel_time],
+ // and begins restoring resources to their pre-request values. The
+ // operation is guaranteed to succeed at undoing all resource changes,
+ // after which point it terminates with a `CANCELLED` status.
+ // * All other attempts to modify the instance are rejected.
+ // * Reading the instance via the API continues to give the pre-request
+ // resource levels.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * Billing begins for all successfully-allocated resources (some types
+ // may have lower than the requested levels).
+ // * All newly-reserved resources are available for serving the instance's
+ // tables.
+ // * The instance's new resource levels are readable via the API.
+ //
+ // The returned long-running operation will
+ // have a name of the format `/operations/` and
+ // can be used to track the instance modification. The
+ // metadata field type is
+ // [UpdateInstanceMetadata][google.spanner.admin.instance.v1.UpdateInstanceMetadata].
+ // The response field type is
+ // [Instance][google.spanner.admin.instance.v1.Instance], if successful.
+ //
+ // Authorization requires `spanner.instances.update` permission on
+ // the resource [name][google.spanner.admin.instance.v1.Instance.name].
+ rpc UpdateInstance(UpdateInstanceRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ patch: "/v1/{instance.name=projects/*/instances/*}"
+ body: "*"
+ };
+ option (google.api.method_signature) = "instance,field_mask";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.Instance"
+ metadata_type: "google.spanner.admin.instance.v1.UpdateInstanceMetadata"
+ };
+ }
+
+ // Deletes an instance.
+ //
+ // Immediately upon completion of the request:
+ //
+ // * Billing ceases for all of the instance's reserved resources.
+ //
+ // Soon afterward:
+ //
+ // * The instance and *all of its databases* immediately and
+ // irrevocably disappear from the API. All data in the databases
+ // is permanently deleted.
+ rpc DeleteInstance(DeleteInstanceRequest) returns (google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/v1/{name=projects/*/instances/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Sets the access control policy on an instance resource. Replaces any
+ // existing policy.
+ //
+ // Authorization requires `spanner.instances.setIamPolicy` on
+ // [resource][google.iam.v1.SetIamPolicyRequest.resource].
+ rpc SetIamPolicy(google.iam.v1.SetIamPolicyRequest)
+ returns (google.iam.v1.Policy) {
+ option (google.api.http) = {
+ post: "/v1/{resource=projects/*/instances/*}:setIamPolicy"
+ body: "*"
+ };
+ option (google.api.method_signature) = "resource,policy";
+ }
+
+ // Gets the access control policy for an instance resource. Returns an empty
+ // policy if an instance exists but does not have a policy set.
+ //
+ // Authorization requires `spanner.instances.getIamPolicy` on
+ // [resource][google.iam.v1.GetIamPolicyRequest.resource].
+ rpc GetIamPolicy(google.iam.v1.GetIamPolicyRequest)
+ returns (google.iam.v1.Policy) {
+ option (google.api.http) = {
+ post: "/v1/{resource=projects/*/instances/*}:getIamPolicy"
+ body: "*"
+ };
+ option (google.api.method_signature) = "resource";
+ }
+
+ // Returns permissions that the caller has on the specified instance resource.
+ //
+ // Attempting this RPC on a non-existent Cloud Spanner instance resource will
+ // result in a NOT_FOUND error if the user has `spanner.instances.list`
+ // permission on the containing Google Cloud Project. Otherwise returns an
+ // empty set of permissions.
+ rpc TestIamPermissions(google.iam.v1.TestIamPermissionsRequest)
+ returns (google.iam.v1.TestIamPermissionsResponse) {
+ option (google.api.http) = {
+ post: "/v1/{resource=projects/*/instances/*}:testIamPermissions"
+ body: "*"
+ };
+ option (google.api.method_signature) = "resource,permissions";
+ }
+
+ // Gets information about a particular instance partition.
+ rpc GetInstancePartition(GetInstancePartitionRequest)
+ returns (InstancePartition) {
+ option (google.api.http) = {
+ get: "/v1/{name=projects/*/instances/*/instancePartitions/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Creates an instance partition and begins preparing it to be used. The
+ // returned long-running operation
+ // can be used to track the progress of preparing the new instance partition.
+ // The instance partition name is assigned by the caller. If the named
+ // instance partition already exists, `CreateInstancePartition` returns
+ // `ALREADY_EXISTS`.
+ //
+ // Immediately upon completion of this request:
+ //
+ // * The instance partition is readable via the API, with all requested
+ // attributes but no allocated resources. Its state is `CREATING`.
+ //
+ // Until completion of the returned operation:
+ //
+ // * Cancelling the operation renders the instance partition immediately
+ // unreadable via the API.
+ // * The instance partition can be deleted.
+ // * All other attempts to modify the instance partition are rejected.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * Billing for all successfully-allocated resources begins (some types
+ // may have lower than the requested levels).
+ // * Databases can start using this instance partition.
+ // * The instance partition's allocated resource levels are readable via the
+ // API.
+ // * The instance partition's state becomes `READY`.
+ //
+ // The returned long-running operation will
+ // have a name of the format
+ // `/operations/` and can be used to
+ // track creation of the instance partition. The
+ // metadata field type is
+ // [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata].
+ // The response field type is
+ // [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], if
+ // successful.
+ rpc CreateInstancePartition(CreateInstancePartitionRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{parent=projects/*/instances/*}/instancePartitions"
+ body: "*"
+ };
+ option (google.api.method_signature) =
+ "parent,instance_partition,instance_partition_id";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.InstancePartition"
+ metadata_type: "google.spanner.admin.instance.v1.CreateInstancePartitionMetadata"
+ };
+ }
+
+ // Deletes an existing instance partition. Requires that the
+ // instance partition is not used by any database or backup and is not the
+ // default instance partition of an instance.
+ //
+ // Authorization requires `spanner.instancePartitions.delete` permission on
+ // the resource
+ // [name][google.spanner.admin.instance.v1.InstancePartition.name].
+ rpc DeleteInstancePartition(DeleteInstancePartitionRequest)
+ returns (google.protobuf.Empty) {
+ option (google.api.http) = {
+ delete: "/v1/{name=projects/*/instances/*/instancePartitions/*}"
+ };
+ option (google.api.method_signature) = "name";
+ }
+
+ // Updates an instance partition, and begins allocating or releasing resources
+ // as requested. The returned long-running operation can be used to track the
+ // progress of updating the instance partition. If the named instance
+ // partition does not exist, returns `NOT_FOUND`.
+ //
+ // Immediately upon completion of this request:
+ //
+ // * For resource types for which a decrease in the instance partition's
+ // allocation has been requested, billing is based on the newly-requested
+ // level.
+ //
+ // Until completion of the returned operation:
+ //
+ // * Cancelling the operation sets its metadata's
+ // [cancel_time][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata.cancel_time],
+ // and begins restoring resources to their pre-request values. The
+ // operation is guaranteed to succeed at undoing all resource changes,
+ // after which point it terminates with a `CANCELLED` status.
+ // * All other attempts to modify the instance partition are rejected.
+ // * Reading the instance partition via the API continues to give the
+ // pre-request resource levels.
+ //
+ // Upon completion of the returned operation:
+ //
+ // * Billing begins for all successfully-allocated resources (some types
+ // may have lower than the requested levels).
+ // * All newly-reserved resources are available for serving the instance
+ // partition's tables.
+ // * The instance partition's new resource levels are readable via the API.
+ //
+ // The returned long-running operation will
+ // have a name of the format
+ // `/operations/` and can be used to
+ // track the instance partition modification. The
+ // metadata field type is
+ // [UpdateInstancePartitionMetadata][google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata].
+ // The response field type is
+ // [InstancePartition][google.spanner.admin.instance.v1.InstancePartition], if
+ // successful.
+ //
+ // Authorization requires `spanner.instancePartitions.update` permission on
+ // the resource
+ // [name][google.spanner.admin.instance.v1.InstancePartition.name].
+ rpc UpdateInstancePartition(UpdateInstancePartitionRequest)
+ returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ patch: "/v1/{instance_partition.name=projects/*/instances/*/instancePartitions/*}"
+ body: "*"
+ };
+ option (google.api.method_signature) = "instance_partition,field_mask";
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.InstancePartition"
+ metadata_type: "google.spanner.admin.instance.v1.UpdateInstancePartitionMetadata"
+ };
+ }
+
+ // Lists instance partition long-running operations in the given instance.
+ // An instance partition operation has a name of the form
+ // `projects//instances//instancePartitions//operations/`.
+ // The long-running operation
+ // metadata field type
+ // `metadata.type_url` describes the type of the metadata. Operations returned
+ // include those that have completed/failed/canceled within the last 7 days,
+ // and pending operations. Operations returned are ordered by
+ // `operation.metadata.value.start_time` in descending order starting from the
+ // most recently started operation.
+ //
+ // Authorization requires `spanner.instancePartitionOperations.list`
+ // permission on the resource
+ // [parent][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.parent].
+ rpc ListInstancePartitionOperations(ListInstancePartitionOperationsRequest)
+ returns (ListInstancePartitionOperationsResponse) {
+ option (google.api.http) = {
+ get: "/v1/{parent=projects/*/instances/*}/instancePartitionOperations"
+ };
+ option (google.api.method_signature) = "parent";
+ }
+
+ // Moves an instance to the target instance configuration. You can use the
+ // returned long-running operation to track
+ // the progress of moving the instance.
+ //
+ // `MoveInstance` returns `FAILED_PRECONDITION` if the instance meets any of
+ // the following criteria:
+ //
+ // * Is undergoing a move to a different instance configuration
+ // * Has backups
+ // * Has an ongoing update
+ // * Contains any CMEK-enabled databases
+ // * Is a free trial instance
+ //
+ // While the operation is pending:
+ //
+ // * All other attempts to modify the instance, including changes to its
+ // compute capacity, are rejected.
+ // * The following database and backup admin operations are rejected:
+ //
+ // * `DatabaseAdmin.CreateDatabase`
+ // * `DatabaseAdmin.UpdateDatabaseDdl` (disabled if default_leader is
+ // specified in the request.)
+ // * `DatabaseAdmin.RestoreDatabase`
+ // * `DatabaseAdmin.CreateBackup`
+ // * `DatabaseAdmin.CopyBackup`
+ //
+ // * Both the source and target instance configurations are subject to
+ // hourly compute and storage charges.
+ // * The instance might experience higher read-write latencies and a higher
+ // transaction abort rate. However, moving an instance doesn't cause any
+ // downtime.
+ //
+ // The returned long-running operation has
+ // a name of the format
+ // `/operations/` and can be used to track
+ // the move instance operation. The
+ // metadata field type is
+ // [MoveInstanceMetadata][google.spanner.admin.instance.v1.MoveInstanceMetadata].
+ // The response field type is
+ // [Instance][google.spanner.admin.instance.v1.Instance],
+ // if successful.
+ // Cancelling the operation sets its metadata's
+ // [cancel_time][google.spanner.admin.instance.v1.MoveInstanceMetadata.cancel_time].
+ // Cancellation is not immediate because it involves moving any data
+ // previously moved to the target instance configuration back to the original
+ // instance configuration. You can use this operation to track the progress of
+ // the cancellation. Upon successful completion of the cancellation, the
+ // operation terminates with `CANCELLED` status.
+ //
+ // If not cancelled, upon completion of the returned operation:
+ //
+ // * The instance successfully moves to the target instance
+ // configuration.
+ // * You are billed for compute and storage in target instance
+ // configuration.
+ //
+ // Authorization requires the `spanner.instances.update` permission on
+ // the resource [instance][google.spanner.admin.instance.v1.Instance].
+ //
+ // For more details, see
+ // [Move an instance](https://cloud.google.com/spanner/docs/move-instance).
+ rpc MoveInstance(MoveInstanceRequest) returns (google.longrunning.Operation) {
+ option (google.api.http) = {
+ post: "/v1/{name=projects/*/instances/*}:move"
+ body: "*"
+ };
+ option (google.longrunning.operation_info) = {
+ response_type: "google.spanner.admin.instance.v1.MoveInstanceResponse"
+ metadata_type: "google.spanner.admin.instance.v1.MoveInstanceMetadata"
+ };
+ }
+}
+
+message ReplicaInfo {
+ // Indicates the type of replica. See the [replica types
+ // documentation](https://cloud.google.com/spanner/docs/replication#replica_types)
+ // for more details.
+ enum ReplicaType {
+ // Not specified.
+ TYPE_UNSPECIFIED = 0;
+
+ // Read-write replicas support both reads and writes. These replicas:
+ //
+ // * Maintain a full copy of your data.
+ // * Serve reads.
+ // * Can vote whether to commit a write.
+ // * Participate in leadership election.
+ // * Are eligible to become a leader.
+ READ_WRITE = 1;
+
+ // Read-only replicas only support reads (not writes). Read-only replicas:
+ //
+ // * Maintain a full copy of your data.
+ // * Serve reads.
+ // * Do not participate in voting to commit writes.
+ // * Are not eligible to become a leader.
+ READ_ONLY = 2;
+
+ // Witness replicas don't support reads but do participate in voting to
+ // commit writes. Witness replicas:
+ //
+ // * Do not maintain a full copy of data.
+ // * Do not serve reads.
+ // * Vote whether to commit writes.
+ // * Participate in leader election but are not eligible to become leader.
+ WITNESS = 3;
+ }
+
+ // The location of the serving resources, e.g., "us-central1".
+ string location = 1;
+
+ // The type of replica.
+ ReplicaType type = 2;
+
+ // If true, this location is designated as the default leader location where
+ // leader replicas are placed. See the [region types
+ // documentation](https://cloud.google.com/spanner/docs/instances#region_types)
+ // for more details.
+ bool default_leader_location = 3;
+}
+
+// A possible configuration for a Cloud Spanner instance. Configurations
+// define the geographic placement of nodes and their replication.
+message InstanceConfig {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/InstanceConfig"
+ pattern: "projects/{project}/instanceConfigs/{instance_config}"
+ plural: "instanceConfigs"
+ singular: "instanceConfig"
+ };
+
+ // The type of this configuration.
+ enum Type {
+ // Unspecified.
+ TYPE_UNSPECIFIED = 0;
+
+ // Google-managed configuration.
+ GOOGLE_MANAGED = 1;
+
+ // User-managed configuration.
+ USER_MANAGED = 2;
+ }
+
+ // Indicates the current state of the instance configuration.
+ enum State {
+ // Not specified.
+ STATE_UNSPECIFIED = 0;
+
+ // The instance configuration is still being created.
+ CREATING = 1;
+
+ // The instance configuration is fully created and ready to be used to
+ // create instances.
+ READY = 2;
+ }
+
+ // Describes the availability for free instances to be created in an instance
+ // configuration.
+ enum FreeInstanceAvailability {
+ // Not specified.
+ FREE_INSTANCE_AVAILABILITY_UNSPECIFIED = 0;
+
+ // Indicates that free instances are available to be created in this
+ // instance configuration.
+ AVAILABLE = 1;
+
+ // Indicates that free instances are not supported in this instance
+ // configuration.
+ UNSUPPORTED = 2;
+
+ // Indicates that free instances are currently not available to be created
+ // in this instance configuration.
+ DISABLED = 3;
+
+ // Indicates that additional free instances cannot be created in this
+ // instance configuration because the project has reached its limit of free
+ // instances.
+ QUOTA_EXCEEDED = 4;
+ }
+
+ // Indicates the quorum type of this instance configuration.
+ enum QuorumType {
+ // Quorum type not specified.
+ QUORUM_TYPE_UNSPECIFIED = 0;
+
+ // An instance configuration tagged with `REGION` quorum type forms a write
+ // quorum in a single region.
+ REGION = 1;
+
+ // An instance configuration tagged with the `DUAL_REGION` quorum type forms
+ // a write quorum with exactly two read-write regions in a multi-region
+ // configuration.
+ //
+ // This instance configuration requires failover in the event of
+ // regional failures.
+ DUAL_REGION = 2;
+
+ // An instance configuration tagged with the `MULTI_REGION` quorum type
+ // forms a write quorum from replicas that are spread across more than one
+ // region in a multi-region configuration.
+ MULTI_REGION = 3;
+ }
+
+ // A unique identifier for the instance configuration. Values
+ // are of the form
+ // `projects//instanceConfigs/[a-z][-a-z0-9]*`.
+ //
+ // User instance configuration must start with `custom-`.
+ string name = 1;
+
+ // The name of this instance configuration as it appears in UIs.
+ string display_name = 2;
+
+ // Output only. Whether this instance configuration is a Google-managed or
+ // user-managed configuration.
+ Type config_type = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // The geographic placement of nodes in this instance configuration and their
+ // replication properties.
+ //
+ // To create user-managed configurations, input
+ // `replicas` must include all replicas in `replicas` of the `base_config`
+ // and include one or more replicas in the `optional_replicas` of the
+ // `base_config`.
+ repeated ReplicaInfo replicas = 3;
+
+ // Output only. The available optional replicas to choose from for
+ // user-managed configurations. Populated for Google-managed configurations.
+ repeated ReplicaInfo optional_replicas = 6
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Base configuration name, e.g. projects//instanceConfigs/nam3,
+ // based on which this configuration is created. Only set for user-managed
+ // configurations. `base_config` must refer to a configuration of type
+ // `GOOGLE_MANAGED` in the same project as this configuration.
+ string base_config = 7 [(google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstanceConfig"
+ }];
+
+ // Cloud Labels are a flexible and lightweight mechanism for organizing cloud
+ // resources into groups that reflect a customer's organizational needs and
+ // deployment strategies. Cloud Labels can be used to filter collections of
+ // resources. They can be used to control how resource metrics are aggregated.
+ // And they can be used as arguments to policy management rules (e.g. route,
+ // firewall, load balancing, etc.).
+ //
+ // * Label keys must be between 1 and 63 characters long and must conform to
+ // the following regular expression: `[a-z][a-z0-9_-]{0,62}`.
+ // * Label values must be between 0 and 63 characters long and must conform
+ // to the regular expression `[a-z0-9_-]{0,63}`.
+ // * No more than 64 labels can be associated with a given resource.
+ //
+ // See https://goo.gl/xmQnxf for more information on and examples of labels.
+ //
+ // If you plan to use labels in your own code, please note that additional
+ // characters may be allowed in the future. Therefore, you are advised to use
+ // an internal label representation, such as JSON, which doesn't rely upon
+ // specific characters being disallowed. For example, representing labels
+ // as the string: name + "_" + value would prove problematic if we were to
+ // allow "_" in a future release.
+ map labels = 8;
+
+ // etag is used for optimistic concurrency control as a way
+ // to help prevent simultaneous updates of a instance configuration from
+ // overwriting each other. It is strongly suggested that systems make use of
+ // the etag in the read-modify-write cycle to perform instance configuration
+ // updates in order to avoid race conditions: An etag is returned in the
+ // response which contains instance configurations, and systems are expected
+ // to put that etag in the request to update instance configuration to ensure
+ // that their change is applied to the same version of the instance
+ // configuration. If no etag is provided in the call to update the instance
+ // configuration, then the existing instance configuration is overwritten
+ // blindly.
+ string etag = 9;
+
+ // Allowed values of the "default_leader" schema option for databases in
+ // instances that use this instance configuration.
+ repeated string leader_options = 4;
+
+ // Output only. If true, the instance configuration is being created or
+ // updated. If false, there are no ongoing operations for the instance
+ // configuration.
+ bool reconciling = 10 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The current instance configuration state. Applicable only for
+ // `USER_MANAGED` configurations.
+ State state = 11 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Describes whether free instances are available to be created
+ // in this instance configuration.
+ FreeInstanceAvailability free_instance_availability = 12
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The `QuorumType` of the instance configuration.
+ QuorumType quorum_type = 18 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The storage limit in bytes per processing unit.
+ int64 storage_limit_per_processing_unit = 19
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+}
+
+// ReplicaComputeCapacity describes the amount of server resources that are
+// allocated to each replica identified by the replica selection.
+message ReplicaComputeCapacity {
+ // Required. Identifies replicas by specified properties.
+ // All replicas in the selection have the same amount of compute capacity.
+ ReplicaSelection replica_selection = 1
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Compute capacity allocated to each replica identified by the specified
+ // selection.
+ // The unit is selected based on the unit used to specify the instance size
+ // for non-autoscaling instances, or the unit used in autoscaling limit for
+ // autoscaling instances.
+ oneof compute_capacity {
+ // The number of nodes allocated to each replica.
+ //
+ // This may be zero in API responses for instances that are not yet in
+ // state `READY`.
+ int32 node_count = 2;
+
+ // The number of processing units allocated to each replica.
+ //
+ // This may be zero in API responses for instances that are not yet in
+ // state `READY`.
+ int32 processing_units = 3;
+ }
+}
+
+// Autoscaling configuration for an instance.
+message AutoscalingConfig {
+ // The autoscaling limits for the instance. Users can define the minimum and
+ // maximum compute capacity allocated to the instance, and the autoscaler will
+ // only scale within that range. Users can either use nodes or processing
+ // units to specify the limits, but should use the same unit to set both the
+ // min_limit and max_limit.
+ message AutoscalingLimits {
+ // The minimum compute capacity for the instance.
+ oneof min_limit {
+ // Minimum number of nodes allocated to the instance. If set, this number
+ // should be greater than or equal to 1.
+ int32 min_nodes = 1;
+
+ // Minimum number of processing units allocated to the instance. If set,
+ // this number should be multiples of 1000.
+ int32 min_processing_units = 2;
+ }
+
+ // The maximum compute capacity for the instance. The maximum compute
+ // capacity should be less than or equal to 10X the minimum compute
+ // capacity.
+ oneof max_limit {
+ // Maximum number of nodes allocated to the instance. If set, this number
+ // should be greater than or equal to min_nodes.
+ int32 max_nodes = 3;
+
+ // Maximum number of processing units allocated to the instance. If set,
+ // this number should be multiples of 1000 and be greater than or equal to
+ // min_processing_units.
+ int32 max_processing_units = 4;
+ }
+ }
+
+ // The autoscaling targets for an instance.
+ message AutoscalingTargets {
+ // Required. The target high priority cpu utilization percentage that the
+ // autoscaler should be trying to achieve for the instance. This number is
+ // on a scale from 0 (no utilization) to 100 (full utilization). The valid
+ // range is [10, 90] inclusive.
+ int32 high_priority_cpu_utilization_percent = 1
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The target storage utilization percentage that the autoscaler
+ // should be trying to achieve for the instance. This number is on a scale
+ // from 0 (no utilization) to 100 (full utilization). The valid range is
+ // [10, 99] inclusive.
+ int32 storage_utilization_percent = 2
+ [(google.api.field_behavior) = REQUIRED];
+ }
+
+ // AsymmetricAutoscalingOption specifies the scaling of replicas identified by
+ // the given selection.
+ message AsymmetricAutoscalingOption {
+ // Overrides the top-level autoscaling configuration for the replicas
+ // identified by `replica_selection`. All fields in this message are
+ // optional. Any unspecified fields will use the corresponding values from
+ // the top-level autoscaling configuration.
+ message AutoscalingConfigOverrides {
+ // Optional. If specified, overrides the min/max limit in the top-level
+ // autoscaling configuration for the selected replicas.
+ AutoscalingLimits autoscaling_limits = 1
+ [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. If specified, overrides the autoscaling target
+ // high_priority_cpu_utilization_percent in the top-level autoscaling
+ // configuration for the selected replicas.
+ int32 autoscaling_target_high_priority_cpu_utilization_percent = 2
+ [(google.api.field_behavior) = OPTIONAL];
+ }
+
+ // Required. Selects the replicas to which this AsymmetricAutoscalingOption
+ // applies. Only read-only replicas are supported.
+ ReplicaSelection replica_selection = 1
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. Overrides applied to the top-level autoscaling configuration
+ // for the selected replicas.
+ AutoscalingConfigOverrides overrides = 2
+ [(google.api.field_behavior) = OPTIONAL];
+ }
+
+ // Required. Autoscaling limits for an instance.
+ AutoscalingLimits autoscaling_limits = 1
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The autoscaling targets for an instance.
+ AutoscalingTargets autoscaling_targets = 2
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Optional. Optional asymmetric autoscaling options.
+ // Replicas matching the replica selection criteria will be autoscaled
+ // independently from other replicas. The autoscaler will scale the replicas
+ // based on the utilization of replicas identified by the replica selection.
+ // Replica selections should not overlap with each other.
+ //
+ // Other replicas (those do not match any replica selection) will be
+ // autoscaled together and will have the same compute capacity allocated to
+ // them.
+ repeated AsymmetricAutoscalingOption asymmetric_autoscaling_options = 3
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// An isolated set of Cloud Spanner resources on which databases can be hosted.
+message Instance {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/Instance"
+ pattern: "projects/{project}/instances/{instance}"
+ plural: "instances"
+ singular: "instance"
+ };
+
+ // Indicates the current state of the instance.
+ enum State {
+ // Not specified.
+ STATE_UNSPECIFIED = 0;
+
+ // The instance is still being created. Resources may not be
+ // available yet, and operations such as database creation may not
+ // work.
+ CREATING = 1;
+
+ // The instance is fully created and ready to do work such as
+ // creating databases.
+ READY = 2;
+ }
+
+ // The type of this instance. The type can be used to distinguish product
+ // variants, that can affect aspects like: usage restrictions, quotas and
+ // billing. Currently this is used to distinguish FREE_INSTANCE vs PROVISIONED
+ // instances.
+ enum InstanceType {
+ // Not specified.
+ INSTANCE_TYPE_UNSPECIFIED = 0;
+
+ // Provisioned instances have dedicated resources, standard usage limits and
+ // support.
+ PROVISIONED = 1;
+
+ // Free instances provide no guarantee for dedicated resources,
+ // [node_count, processing_units] should be 0. They come
+ // with stricter usage limits and limited support.
+ FREE_INSTANCE = 2;
+ }
+
+ // The edition selected for this instance. Different editions provide
+ // different capabilities at different price points.
+ enum Edition {
+ // Edition not specified.
+ EDITION_UNSPECIFIED = 0;
+
+ // Standard edition.
+ STANDARD = 1;
+
+ // Enterprise edition.
+ ENTERPRISE = 2;
+
+ // Enterprise Plus edition.
+ ENTERPRISE_PLUS = 3;
+ }
+
+ // Indicates the
+ // [default backup
+ // schedule](https://cloud.google.com/spanner/docs/backup#default-backup-schedules)
+ // behavior for new databases within the instance.
+ enum DefaultBackupScheduleType {
+ // Not specified.
+ DEFAULT_BACKUP_SCHEDULE_TYPE_UNSPECIFIED = 0;
+
+ // A default backup schedule isn't created automatically when a new database
+ // is created in the instance.
+ NONE = 1;
+
+ // A default backup schedule is created automatically when a new database
+ // is created in the instance. The default backup schedule creates a full
+ // backup every 24 hours. These full backups are retained for 7 days.
+ // You can edit or delete the default backup schedule once it's created.
+ AUTOMATIC = 2;
+ }
+
+ // Required. A unique identifier for the instance, which cannot be changed
+ // after the instance is created. Values are of the form
+ // `projects//instances/[a-z][-a-z0-9]*[a-z0-9]`. The final
+ // segment of the name must be between 2 and 64 characters in length.
+ string name = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The name of the instance's configuration. Values are of the form
+ // `projects//instanceConfigs/`. See
+ // also [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] and
+ // [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
+ string config = 2 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstanceConfig"
+ }
+ ];
+
+ // Required. The descriptive name for this instance as it appears in UIs.
+ // Must be unique per project and between 4 and 30 characters in length.
+ string display_name = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // The number of nodes allocated to this instance. At most, one of either
+ // `node_count` or `processing_units` should be present in the message.
+ //
+ // Users can set the `node_count` field to specify the target number of nodes
+ // allocated to the instance.
+ //
+ // If autoscaling is enabled, `node_count` is treated as an `OUTPUT_ONLY`
+ // field and reflects the current number of nodes allocated to the instance.
+ //
+ // This might be zero in API responses for instances that are not yet in the
+ // `READY` state.
+ //
+ //
+ // For more information, see
+ // [Compute capacity, nodes, and processing
+ // units](https://cloud.google.com/spanner/docs/compute-capacity).
+ int32 node_count = 5;
+
+ // The number of processing units allocated to this instance. At most, one of
+ // either `processing_units` or `node_count` should be present in the message.
+ //
+ // Users can set the `processing_units` field to specify the target number of
+ // processing units allocated to the instance.
+ //
+ // If autoscaling is enabled, `processing_units` is treated as an
+ // `OUTPUT_ONLY` field and reflects the current number of processing units
+ // allocated to the instance.
+ //
+ // This might be zero in API responses for instances that are not yet in the
+ // `READY` state.
+ //
+ //
+ // For more information, see
+ // [Compute capacity, nodes and processing
+ // units](https://cloud.google.com/spanner/docs/compute-capacity).
+ int32 processing_units = 9;
+
+ // Output only. Lists the compute capacity per ReplicaSelection. A replica
+ // selection identifies a set of replicas with common properties. Replicas
+ // identified by a ReplicaSelection are scaled with the same compute capacity.
+ repeated ReplicaComputeCapacity replica_compute_capacity = 19
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Optional. The autoscaling configuration. Autoscaling is enabled if this
+ // field is set. When autoscaling is enabled, node_count and processing_units
+ // are treated as OUTPUT_ONLY fields and reflect the current compute capacity
+ // allocated to the instance.
+ AutoscalingConfig autoscaling_config = 17
+ [(google.api.field_behavior) = OPTIONAL];
+
+ // Output only. The current instance state. For
+ // [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance],
+ // the state must be either omitted or set to `CREATING`. For
+ // [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance],
+ // the state must be either omitted or set to `READY`.
+ State state = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Cloud Labels are a flexible and lightweight mechanism for organizing cloud
+ // resources into groups that reflect a customer's organizational needs and
+ // deployment strategies. Cloud Labels can be used to filter collections of
+ // resources. They can be used to control how resource metrics are aggregated.
+ // And they can be used as arguments to policy management rules (e.g. route,
+ // firewall, load balancing, etc.).
+ //
+ // * Label keys must be between 1 and 63 characters long and must conform to
+ // the following regular expression: `[a-z][a-z0-9_-]{0,62}`.
+ // * Label values must be between 0 and 63 characters long and must conform
+ // to the regular expression `[a-z0-9_-]{0,63}`.
+ // * No more than 64 labels can be associated with a given resource.
+ //
+ // See https://goo.gl/xmQnxf for more information on and examples of labels.
+ //
+ // If you plan to use labels in your own code, please note that additional
+ // characters may be allowed in the future. And so you are advised to use an
+ // internal label representation, such as JSON, which doesn't rely upon
+ // specific characters being disallowed. For example, representing labels
+ // as the string: name + "_" + value would prove problematic if we were to
+ // allow "_" in a future release.
+ map labels = 7;
+
+ // The `InstanceType` of the current instance.
+ InstanceType instance_type = 10;
+
+ // Deprecated. This field is not populated.
+ repeated string endpoint_uris = 8;
+
+ // Output only. The time at which the instance was created.
+ google.protobuf.Timestamp create_time = 11
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The time at which the instance was most recently updated.
+ google.protobuf.Timestamp update_time = 12
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Free instance metadata. Only populated for free instances.
+ FreeInstanceMetadata free_instance_metadata = 13;
+
+ // Optional. The `Edition` of the current instance.
+ Edition edition = 20 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. Controls the default backup schedule behavior for new databases
+ // within the instance. By default, a backup schedule is created automatically
+ // when a new database is created in a new instance.
+ //
+ // Note that the `AUTOMATIC` value isn't permitted for free instances,
+ // as backups and backup schedules aren't supported for free instances.
+ //
+ // In the `GetInstance` or `ListInstances` response, if the value of
+ // `default_backup_schedule_type` isn't set, or set to `NONE`, Spanner doesn't
+ // create a default backup schedule for new databases in the instance.
+ DefaultBackupScheduleType default_backup_schedule_type = 23
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// The request for
+// [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
+message ListInstanceConfigsRequest {
+ // Required. The name of the project for which a list of supported instance
+ // configurations is requested. Values are of the form
+ // `projects/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "cloudresourcemanager.googleapis.com/Project"
+ }
+ ];
+
+ // Number of instance configurations to be returned in the response. If 0 or
+ // less, defaults to the server's maximum allowed page size.
+ int32 page_size = 2;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.instance.v1.ListInstanceConfigsResponse.next_page_token]
+ // from a previous
+ // [ListInstanceConfigsResponse][google.spanner.admin.instance.v1.ListInstanceConfigsResponse].
+ string page_token = 3;
+}
+
+// The response for
+// [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
+message ListInstanceConfigsResponse {
+ // The list of requested instance configurations.
+ repeated InstanceConfig instance_configs = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs]
+ // call to fetch more of the matching instance configurations.
+ string next_page_token = 2;
+}
+
+// The request for
+// [GetInstanceConfigRequest][google.spanner.admin.instance.v1.InstanceAdmin.GetInstanceConfig].
+message GetInstanceConfigRequest {
+ // Required. The name of the requested instance configuration. Values are of
+ // the form `projects//instanceConfigs/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstanceConfig"
+ }
+ ];
+}
+
+// The request for
+// [CreateInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstanceConfig].
+message CreateInstanceConfigRequest {
+ // Required. The name of the project in which to create the instance
+ // configuration. Values are of the form `projects/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "cloudresourcemanager.googleapis.com/Project"
+ }
+ ];
+
+ // Required. The ID of the instance configuration to create. Valid identifiers
+ // are of the form `custom-[-a-z0-9]*[a-z0-9]` and must be between 2 and 64
+ // characters in length. The `custom-` prefix is required to avoid name
+ // conflicts with Google-managed configurations.
+ string instance_config_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The `InstanceConfig` proto of the configuration to create.
+ // `instance_config.name` must be
+ // `/instanceConfigs/`.
+ // `instance_config.base_config` must be a Google-managed configuration name,
+ // e.g. /instanceConfigs/us-east1, /instanceConfigs/nam3.
+ InstanceConfig instance_config = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // An option to validate, but not actually execute, a request,
+ // and provide the same response.
+ bool validate_only = 4;
+}
+
+// The request for
+// [UpdateInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstanceConfig].
+message UpdateInstanceConfigRequest {
+ // Required. The user instance configuration to update, which must always
+ // include the instance configuration name. Otherwise, only fields mentioned
+ // in
+ // [update_mask][google.spanner.admin.instance.v1.UpdateInstanceConfigRequest.update_mask]
+ // need be included. To prevent conflicts of concurrent updates,
+ // [etag][google.spanner.admin.instance.v1.InstanceConfig.reconciling] can
+ // be used.
+ InstanceConfig instance_config = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. A mask specifying which fields in
+ // [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] should be
+ // updated. The field mask must always be specified; this prevents any future
+ // fields in [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig]
+ // from being erased accidentally by clients that do not know about them. Only
+ // display_name and labels can be updated.
+ google.protobuf.FieldMask update_mask = 2
+ [(google.api.field_behavior) = REQUIRED];
+
+ // An option to validate, but not actually execute, a request,
+ // and provide the same response.
+ bool validate_only = 3;
+}
+
+// The request for
+// [DeleteInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstanceConfig].
+message DeleteInstanceConfigRequest {
+ // Required. The name of the instance configuration to be deleted.
+ // Values are of the form
+ // `projects//instanceConfigs/`
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstanceConfig"
+ }
+ ];
+
+ // Used for optimistic concurrency control as a way to help prevent
+ // simultaneous deletes of an instance configuration from overwriting each
+ // other. If not empty, the API
+ // only deletes the instance configuration when the etag provided matches the
+ // current status of the requested instance configuration. Otherwise, deletes
+ // the instance configuration without checking the current status of the
+ // requested instance configuration.
+ string etag = 2;
+
+ // An option to validate, but not actually execute, a request,
+ // and provide the same response.
+ bool validate_only = 3;
+}
+
+// The request for
+// [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations].
+message ListInstanceConfigOperationsRequest {
+ // Required. The project of the instance configuration operations.
+ // Values are of the form `projects/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "cloudresourcemanager.googleapis.com/Project"
+ }
+ ];
+
+ // An expression that filters the list of returned operations.
+ //
+ // A filter expression consists of a field name, a
+ // comparison operator, and a value for filtering.
+ // The value must be a string, a number, or a boolean. The comparison operator
+ // must be one of: `<`, `>`, `<=`, `>=`, `!=`, `=`, or `:`.
+ // Colon `:` is the contains operator. Filter rules are not case sensitive.
+ //
+ // The following fields in the Operation are eligible for filtering:
+ //
+ // * `name` - The name of the long-running operation
+ // * `done` - False if the operation is in progress, else true.
+ // * `metadata.@type` - the type of metadata. For example, the type string
+ // for
+ // [CreateInstanceConfigMetadata][google.spanner.admin.instance.v1.CreateInstanceConfigMetadata]
+ // is
+ // `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstanceConfigMetadata`.
+ // * `metadata.` - any field in metadata.value.
+ // `metadata.@type` must be specified first, if filtering on metadata
+ // fields.
+ // * `error` - Error associated with the long-running operation.
+ // * `response.@type` - the type of response.
+ // * `response.` - any field in response.value.
+ //
+ // You can combine multiple expressions by enclosing each expression in
+ // parentheses. By default, expressions are combined with AND logic. However,
+ // you can specify AND, OR, and NOT logic explicitly.
+ //
+ // Here are a few examples:
+ //
+ // * `done:true` - The operation is complete.
+ // * `(metadata.@type=` \
+ // `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstanceConfigMetadata)
+ // AND` \
+ // `(metadata.instance_config.name:custom-config) AND` \
+ // `(metadata.progress.start_time < \"2021-03-28T14:50:00Z\") AND` \
+ // `(error:*)` - Return operations where:
+ // * The operation's metadata type is
+ // [CreateInstanceConfigMetadata][google.spanner.admin.instance.v1.CreateInstanceConfigMetadata].
+ // * The instance configuration name contains "custom-config".
+ // * The operation started before 2021-03-28T14:50:00Z.
+ // * The operation resulted in an error.
+ string filter = 2;
+
+ // Number of operations to be returned in the response. If 0 or
+ // less, defaults to the server's maximum allowed page size.
+ int32 page_size = 3;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.instance.v1.ListInstanceConfigOperationsResponse.next_page_token]
+ // from a previous
+ // [ListInstanceConfigOperationsResponse][google.spanner.admin.instance.v1.ListInstanceConfigOperationsResponse]
+ // to the same `parent` and with the same `filter`.
+ string page_token = 4;
+}
+
+// The response for
+// [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations].
+message ListInstanceConfigOperationsResponse {
+ // The list of matching instance configuration long-running operations. Each
+ // operation's name will be
+ // prefixed by the name of the instance configuration. The operation's
+ // metadata field type
+ // `metadata.type_url` describes the type of the metadata.
+ repeated google.longrunning.Operation operations = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListInstanceConfigOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigOperations]
+ // call to fetch more of the matching metadata.
+ string next_page_token = 2;
+}
+
+// The request for
+// [GetInstance][google.spanner.admin.instance.v1.InstanceAdmin.GetInstance].
+message GetInstanceRequest {
+ // Required. The name of the requested instance. Values are of the form
+ // `projects//instances/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // If field_mask is present, specifies the subset of
+ // [Instance][google.spanner.admin.instance.v1.Instance] fields that should be
+ // returned. If absent, all
+ // [Instance][google.spanner.admin.instance.v1.Instance] fields are returned.
+ google.protobuf.FieldMask field_mask = 2;
+}
+
+// The request for
+// [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance].
+message CreateInstanceRequest {
+ // Required. The name of the project in which to create the instance. Values
+ // are of the form `projects/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "cloudresourcemanager.googleapis.com/Project"
+ }
+ ];
+
+ // Required. The ID of the instance to create. Valid identifiers are of the
+ // form `[a-z][-a-z0-9]*[a-z0-9]` and must be between 2 and 64 characters in
+ // length.
+ string instance_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The instance to create. The name may be omitted, but if
+ // specified must be `/instances/`.
+ Instance instance = 3 [(google.api.field_behavior) = REQUIRED];
+}
+
+// The request for
+// [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances].
+message ListInstancesRequest {
+ // Required. The name of the project for which a list of instances is
+ // requested. Values are of the form `projects/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "cloudresourcemanager.googleapis.com/Project"
+ }
+ ];
+
+ // Number of instances to be returned in the response. If 0 or less, defaults
+ // to the server's maximum allowed page size.
+ int32 page_size = 2;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.instance.v1.ListInstancesResponse.next_page_token]
+ // from a previous
+ // [ListInstancesResponse][google.spanner.admin.instance.v1.ListInstancesResponse].
+ string page_token = 3;
+
+ // An expression for filtering the results of the request. Filter rules are
+ // case insensitive. The fields eligible for filtering are:
+ //
+ // * `name`
+ // * `display_name`
+ // * `labels.key` where key is the name of a label
+ //
+ // Some examples of using filters are:
+ //
+ // * `name:*` --> The instance has a name.
+ // * `name:Howl` --> The instance's name contains the string "howl".
+ // * `name:HOWL` --> Equivalent to above.
+ // * `NAME:howl` --> Equivalent to above.
+ // * `labels.env:*` --> The instance has the label "env".
+ // * `labels.env:dev` --> The instance has the label "env" and the value of
+ // the label contains the string "dev".
+ // * `name:howl labels.env:dev` --> The instance's name contains "howl" and
+ // it has the label "env" with its value
+ // containing "dev".
+ string filter = 4;
+
+ // Deadline used while retrieving metadata for instances.
+ // Instances whose metadata cannot be retrieved within this deadline will be
+ // added to
+ // [unreachable][google.spanner.admin.instance.v1.ListInstancesResponse.unreachable]
+ // in
+ // [ListInstancesResponse][google.spanner.admin.instance.v1.ListInstancesResponse].
+ google.protobuf.Timestamp instance_deadline = 5;
+}
+
+// The response for
+// [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances].
+message ListInstancesResponse {
+ // The list of requested instances.
+ repeated Instance instances = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListInstances][google.spanner.admin.instance.v1.InstanceAdmin.ListInstances]
+ // call to fetch more of the matching instances.
+ string next_page_token = 2;
+
+ // The list of unreachable instances.
+ // It includes the names of instances whose metadata could not be retrieved
+ // within
+ // [instance_deadline][google.spanner.admin.instance.v1.ListInstancesRequest.instance_deadline].
+ repeated string unreachable = 3;
+}
+
+// The request for
+// [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance].
+message UpdateInstanceRequest {
+ // Required. The instance to update, which must always include the instance
+ // name. Otherwise, only fields mentioned in
+ // [field_mask][google.spanner.admin.instance.v1.UpdateInstanceRequest.field_mask]
+ // need be included.
+ Instance instance = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. A mask specifying which fields in
+ // [Instance][google.spanner.admin.instance.v1.Instance] should be updated.
+ // The field mask must always be specified; this prevents any future fields in
+ // [Instance][google.spanner.admin.instance.v1.Instance] from being erased
+ // accidentally by clients that do not know about them.
+ google.protobuf.FieldMask field_mask = 2
+ [(google.api.field_behavior) = REQUIRED];
+}
+
+// The request for
+// [DeleteInstance][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstance].
+message DeleteInstanceRequest {
+ // Required. The name of the instance to be deleted. Values are of the form
+ // `projects//instances/`
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+}
+
+// Metadata type for the operation returned by
+// [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance].
+message CreateInstanceMetadata {
+ // The instance being created.
+ Instance instance = 1;
+
+ // The time at which the
+ // [CreateInstance][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstance]
+ // request was received.
+ google.protobuf.Timestamp start_time = 2;
+
+ // The time at which this operation was cancelled. If set, this operation is
+ // in the process of undoing itself (which is guaranteed to succeed) and
+ // cannot be cancelled again.
+ google.protobuf.Timestamp cancel_time = 3;
+
+ // The time at which this operation failed or was completed successfully.
+ google.protobuf.Timestamp end_time = 4;
+
+ // The expected fulfillment period of this create operation.
+ FulfillmentPeriod expected_fulfillment_period = 5;
+}
+
+// Metadata type for the operation returned by
+// [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance].
+message UpdateInstanceMetadata {
+ // The desired end state of the update.
+ Instance instance = 1;
+
+ // The time at which
+ // [UpdateInstance][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstance]
+ // request was received.
+ google.protobuf.Timestamp start_time = 2;
+
+ // The time at which this operation was cancelled. If set, this operation is
+ // in the process of undoing itself (which is guaranteed to succeed) and
+ // cannot be cancelled again.
+ google.protobuf.Timestamp cancel_time = 3;
+
+ // The time at which this operation failed or was completed successfully.
+ google.protobuf.Timestamp end_time = 4;
+
+ // The expected fulfillment period of this update operation.
+ FulfillmentPeriod expected_fulfillment_period = 5;
+}
+
+// Free instance specific metadata that is kept even after an instance has been
+// upgraded for tracking purposes.
+message FreeInstanceMetadata {
+ // Allows users to change behavior when a free instance expires.
+ enum ExpireBehavior {
+ // Not specified.
+ EXPIRE_BEHAVIOR_UNSPECIFIED = 0;
+
+ // When the free instance expires, upgrade the instance to a provisioned
+ // instance.
+ FREE_TO_PROVISIONED = 1;
+
+ // When the free instance expires, disable the instance, and delete it
+ // after the grace period passes if it has not been upgraded.
+ REMOVE_AFTER_GRACE_PERIOD = 2;
+ }
+
+ // Output only. Timestamp after which the instance will either be upgraded or
+ // scheduled for deletion after a grace period. ExpireBehavior is used to
+ // choose between upgrading or scheduling the free instance for deletion. This
+ // timestamp is set during the creation of a free instance.
+ google.protobuf.Timestamp expire_time = 1
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. If present, the timestamp at which the free instance was
+ // upgraded to a provisioned instance.
+ google.protobuf.Timestamp upgrade_time = 2
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Specifies the expiration behavior of a free instance. The default of
+ // ExpireBehavior is `REMOVE_AFTER_GRACE_PERIOD`. This can be modified during
+ // or after creation, and before expiration.
+ ExpireBehavior expire_behavior = 3;
+}
+
+// Metadata type for the operation returned by
+// [CreateInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstanceConfig].
+message CreateInstanceConfigMetadata {
+ // The target instance configuration end state.
+ InstanceConfig instance_config = 1;
+
+ // The progress of the
+ // [CreateInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstanceConfig]
+ // operation.
+ OperationProgress progress = 2;
+
+ // The time at which this operation was cancelled.
+ google.protobuf.Timestamp cancel_time = 3;
+}
+
+// Metadata type for the operation returned by
+// [UpdateInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstanceConfig].
+message UpdateInstanceConfigMetadata {
+ // The desired instance configuration after updating.
+ InstanceConfig instance_config = 1;
+
+ // The progress of the
+ // [UpdateInstanceConfig][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstanceConfig]
+ // operation.
+ OperationProgress progress = 2;
+
+ // The time at which this operation was cancelled.
+ google.protobuf.Timestamp cancel_time = 3;
+}
+
+// An isolated set of Cloud Spanner resources that databases can define
+// placements on.
+message InstancePartition {
+ option (google.api.resource) = {
+ type: "spanner.googleapis.com/InstancePartition"
+ pattern: "projects/{project}/instances/{instance}/instancePartitions/{instance_partition}"
+ plural: "instancePartitions"
+ singular: "instancePartition"
+ };
+
+ // Indicates the current state of the instance partition.
+ enum State {
+ // Not specified.
+ STATE_UNSPECIFIED = 0;
+
+ // The instance partition is still being created. Resources may not be
+ // available yet, and operations such as creating placements using this
+ // instance partition may not work.
+ CREATING = 1;
+
+ // The instance partition is fully created and ready to do work such as
+ // creating placements and using in databases.
+ READY = 2;
+ }
+
+ // Required. A unique identifier for the instance partition. Values are of the
+ // form
+ // `projects//instances//instancePartitions/[a-z][-a-z0-9]*[a-z0-9]`.
+ // The final segment of the name must be between 2 and 64 characters in
+ // length. An instance partition's name cannot be changed after the instance
+ // partition is created.
+ string name = 1 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The name of the instance partition's configuration. Values are of
+ // the form `projects//instanceConfigs/`. See also
+ // [InstanceConfig][google.spanner.admin.instance.v1.InstanceConfig] and
+ // [ListInstanceConfigs][google.spanner.admin.instance.v1.InstanceAdmin.ListInstanceConfigs].
+ string config = 2 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstanceConfig"
+ }
+ ];
+
+ // Required. The descriptive name for this instance partition as it appears in
+ // UIs. Must be unique per project and between 4 and 30 characters in length.
+ string display_name = 3 [(google.api.field_behavior) = REQUIRED];
+
+ // Compute capacity defines amount of server and storage resources that are
+ // available to the databases in an instance partition. At most, one of either
+ // `node_count` or` processing_units` should be present in the message. For
+ // more information, see
+ // [Compute capacity, nodes, and processing
+ // units](https://cloud.google.com/spanner/docs/compute-capacity).
+ oneof compute_capacity {
+ // The number of nodes allocated to this instance partition.
+ //
+ // Users can set the `node_count` field to specify the target number of
+ // nodes allocated to the instance partition.
+ //
+ // This may be zero in API responses for instance partitions that are not
+ // yet in state `READY`.
+ int32 node_count = 5;
+
+ // The number of processing units allocated to this instance partition.
+ //
+ // Users can set the `processing_units` field to specify the target number
+ // of processing units allocated to the instance partition.
+ //
+ // This might be zero in API responses for instance partitions that are not
+ // yet in the `READY` state.
+ int32 processing_units = 6;
+ }
+
+ // Output only. The current instance partition state.
+ State state = 7 [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The time at which the instance partition was created.
+ google.protobuf.Timestamp create_time = 8
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The time at which the instance partition was most recently
+ // updated.
+ google.protobuf.Timestamp update_time = 9
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. The names of the databases that reference this
+ // instance partition. Referencing databases should share the parent instance.
+ // The existence of any referencing database prevents the instance partition
+ // from being deleted.
+ repeated string referencing_databases = 10
+ [(google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Output only. Deprecated: This field is not populated.
+ // Output only. The names of the backups that reference this instance
+ // partition. Referencing backups should share the parent instance. The
+ // existence of any referencing backup prevents the instance partition from
+ // being deleted.
+ repeated string referencing_backups = 11
+ [deprecated = true, (google.api.field_behavior) = OUTPUT_ONLY];
+
+ // Used for optimistic concurrency control as a way
+ // to help prevent simultaneous updates of a instance partition from
+ // overwriting each other. It is strongly suggested that systems make use of
+ // the etag in the read-modify-write cycle to perform instance partition
+ // updates in order to avoid race conditions: An etag is returned in the
+ // response which contains instance partitions, and systems are expected to
+ // put that etag in the request to update instance partitions to ensure that
+ // their change will be applied to the same version of the instance partition.
+ // If no etag is provided in the call to update instance partition, then the
+ // existing instance partition is overwritten blindly.
+ string etag = 12;
+}
+
+// Metadata type for the operation returned by
+// [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition].
+message CreateInstancePartitionMetadata {
+ // The instance partition being created.
+ InstancePartition instance_partition = 1;
+
+ // The time at which the
+ // [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition]
+ // request was received.
+ google.protobuf.Timestamp start_time = 2;
+
+ // The time at which this operation was cancelled. If set, this operation is
+ // in the process of undoing itself (which is guaranteed to succeed) and
+ // cannot be cancelled again.
+ google.protobuf.Timestamp cancel_time = 3;
+
+ // The time at which this operation failed or was completed successfully.
+ google.protobuf.Timestamp end_time = 4;
+}
+
+// The request for
+// [CreateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.CreateInstancePartition].
+message CreateInstancePartitionRequest {
+ // Required. The name of the instance in which to create the instance
+ // partition. Values are of the form
+ // `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Required. The ID of the instance partition to create. Valid identifiers are
+ // of the form `[a-z][-a-z0-9]*[a-z0-9]` and must be between 2 and 64
+ // characters in length.
+ string instance_partition_id = 2 [(google.api.field_behavior) = REQUIRED];
+
+ // Required. The instance partition to create. The instance_partition.name may
+ // be omitted, but if specified must be
+ // `/instancePartitions/`.
+ InstancePartition instance_partition = 3
+ [(google.api.field_behavior) = REQUIRED];
+}
+
+// The request for
+// [DeleteInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.DeleteInstancePartition].
+message DeleteInstancePartitionRequest {
+ // Required. The name of the instance partition to be deleted.
+ // Values are of the form
+ // `projects/{project}/instances/{instance}/instancePartitions/{instance_partition}`
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstancePartition"
+ }
+ ];
+
+ // Optional. If not empty, the API only deletes the instance partition when
+ // the etag provided matches the current status of the requested instance
+ // partition. Otherwise, deletes the instance partition without checking the
+ // current status of the requested instance partition.
+ string etag = 2;
+}
+
+// The request for
+// [GetInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.GetInstancePartition].
+message GetInstancePartitionRequest {
+ // Required. The name of the requested instance partition. Values are of
+ // the form
+ // `projects/{project}/instances/{instance}/instancePartitions/{instance_partition}`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/InstancePartition"
+ }
+ ];
+}
+
+// The request for
+// [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition].
+message UpdateInstancePartitionRequest {
+ // Required. The instance partition to update, which must always include the
+ // instance partition name. Otherwise, only fields mentioned in
+ // [field_mask][google.spanner.admin.instance.v1.UpdateInstancePartitionRequest.field_mask]
+ // need be included.
+ InstancePartition instance_partition = 1
+ [(google.api.field_behavior) = REQUIRED];
+
+ // Required. A mask specifying which fields in
+ // [InstancePartition][google.spanner.admin.instance.v1.InstancePartition]
+ // should be updated. The field mask must always be specified; this prevents
+ // any future fields in
+ // [InstancePartition][google.spanner.admin.instance.v1.InstancePartition]
+ // from being erased accidentally by clients that do not know about them.
+ google.protobuf.FieldMask field_mask = 2
+ [(google.api.field_behavior) = REQUIRED];
+}
+
+// Metadata type for the operation returned by
+// [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition].
+message UpdateInstancePartitionMetadata {
+ // The desired end state of the update.
+ InstancePartition instance_partition = 1;
+
+ // The time at which
+ // [UpdateInstancePartition][google.spanner.admin.instance.v1.InstanceAdmin.UpdateInstancePartition]
+ // request was received.
+ google.protobuf.Timestamp start_time = 2;
+
+ // The time at which this operation was cancelled. If set, this operation is
+ // in the process of undoing itself (which is guaranteed to succeed) and
+ // cannot be cancelled again.
+ google.protobuf.Timestamp cancel_time = 3;
+
+ // The time at which this operation failed or was completed successfully.
+ google.protobuf.Timestamp end_time = 4;
+}
+
+// The request for
+// [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions].
+message ListInstancePartitionsRequest {
+ // Required. The instance whose instance partitions should be listed. Values
+ // are of the form `projects//instances/`. Use `{instance}
+ // = '-'` to list instance partitions for all Instances in a project, e.g.,
+ // `projects/myproject/instances/-`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Number of instance partitions to be returned in the response. If 0 or less,
+ // defaults to the server's maximum allowed page size.
+ int32 page_size = 2;
+
+ // If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.instance.v1.ListInstancePartitionsResponse.next_page_token]
+ // from a previous
+ // [ListInstancePartitionsResponse][google.spanner.admin.instance.v1.ListInstancePartitionsResponse].
+ string page_token = 3;
+
+ // Optional. Deadline used while retrieving metadata for instance partitions.
+ // Instance partitions whose metadata cannot be retrieved within this deadline
+ // will be added to
+ // [unreachable][google.spanner.admin.instance.v1.ListInstancePartitionsResponse.unreachable]
+ // in
+ // [ListInstancePartitionsResponse][google.spanner.admin.instance.v1.ListInstancePartitionsResponse].
+ google.protobuf.Timestamp instance_partition_deadline = 4
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// The response for
+// [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions].
+message ListInstancePartitionsResponse {
+ // The list of requested instancePartitions.
+ repeated InstancePartition instance_partitions = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListInstancePartitions][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitions]
+ // call to fetch more of the matching instance partitions.
+ string next_page_token = 2;
+
+ // The list of unreachable instances or instance partitions.
+ // It includes the names of instances or instance partitions whose metadata
+ // could not be retrieved within
+ // [instance_partition_deadline][google.spanner.admin.instance.v1.ListInstancePartitionsRequest.instance_partition_deadline].
+ repeated string unreachable = 3;
+}
+
+// The request for
+// [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations].
+message ListInstancePartitionOperationsRequest {
+ // Required. The parent instance of the instance partition operations.
+ // Values are of the form `projects//instances/`.
+ string parent = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Optional. An expression that filters the list of returned operations.
+ //
+ // A filter expression consists of a field name, a
+ // comparison operator, and a value for filtering.
+ // The value must be a string, a number, or a boolean. The comparison operator
+ // must be one of: `<`, `>`, `<=`, `>=`, `!=`, `=`, or `:`.
+ // Colon `:` is the contains operator. Filter rules are not case sensitive.
+ //
+ // The following fields in the Operation are eligible for filtering:
+ //
+ // * `name` - The name of the long-running operation
+ // * `done` - False if the operation is in progress, else true.
+ // * `metadata.@type` - the type of metadata. For example, the type string
+ // for
+ // [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata]
+ // is
+ // `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstancePartitionMetadata`.
+ // * `metadata.` - any field in metadata.value.
+ // `metadata.@type` must be specified first, if filtering on metadata
+ // fields.
+ // * `error` - Error associated with the long-running operation.
+ // * `response.@type` - the type of response.
+ // * `response.` - any field in response.value.
+ //
+ // You can combine multiple expressions by enclosing each expression in
+ // parentheses. By default, expressions are combined with AND logic. However,
+ // you can specify AND, OR, and NOT logic explicitly.
+ //
+ // Here are a few examples:
+ //
+ // * `done:true` - The operation is complete.
+ // * `(metadata.@type=` \
+ // `type.googleapis.com/google.spanner.admin.instance.v1.CreateInstancePartitionMetadata)
+ // AND` \
+ // `(metadata.instance_partition.name:custom-instance-partition) AND` \
+ // `(metadata.start_time < \"2021-03-28T14:50:00Z\") AND` \
+ // `(error:*)` - Return operations where:
+ // * The operation's metadata type is
+ // [CreateInstancePartitionMetadata][google.spanner.admin.instance.v1.CreateInstancePartitionMetadata].
+ // * The instance partition name contains "custom-instance-partition".
+ // * The operation started before 2021-03-28T14:50:00Z.
+ // * The operation resulted in an error.
+ string filter = 2 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. Number of operations to be returned in the response. If 0 or
+ // less, defaults to the server's maximum allowed page size.
+ int32 page_size = 3 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. If non-empty, `page_token` should contain a
+ // [next_page_token][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse.next_page_token]
+ // from a previous
+ // [ListInstancePartitionOperationsResponse][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse]
+ // to the same `parent` and with the same `filter`.
+ string page_token = 4 [(google.api.field_behavior) = OPTIONAL];
+
+ // Optional. Deadline used while retrieving metadata for instance partition
+ // operations. Instance partitions whose operation metadata cannot be
+ // retrieved within this deadline will be added to
+ // [unreachable_instance_partitions][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse.unreachable_instance_partitions]
+ // in
+ // [ListInstancePartitionOperationsResponse][google.spanner.admin.instance.v1.ListInstancePartitionOperationsResponse].
+ google.protobuf.Timestamp instance_partition_deadline = 5
+ [(google.api.field_behavior) = OPTIONAL];
+}
+
+// The response for
+// [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations].
+message ListInstancePartitionOperationsResponse {
+ // The list of matching instance partition long-running operations. Each
+ // operation's name will be
+ // prefixed by the instance partition's name. The operation's
+ // metadata field type
+ // `metadata.type_url` describes the type of the metadata.
+ repeated google.longrunning.Operation operations = 1;
+
+ // `next_page_token` can be sent in a subsequent
+ // [ListInstancePartitionOperations][google.spanner.admin.instance.v1.InstanceAdmin.ListInstancePartitionOperations]
+ // call to fetch more of the matching metadata.
+ string next_page_token = 2;
+
+ // The list of unreachable instance partitions.
+ // It includes the names of instance partitions whose operation metadata could
+ // not be retrieved within
+ // [instance_partition_deadline][google.spanner.admin.instance.v1.ListInstancePartitionOperationsRequest.instance_partition_deadline].
+ repeated string unreachable_instance_partitions = 3;
+}
+
+// The request for
+// [MoveInstance][google.spanner.admin.instance.v1.InstanceAdmin.MoveInstance].
+message MoveInstanceRequest {
+ // Required. The instance to move.
+ // Values are of the form `projects//instances/`.
+ string name = 1 [
+ (google.api.field_behavior) = REQUIRED,
+ (google.api.resource_reference) = {
+ type: "spanner.googleapis.com/Instance"
+ }
+ ];
+
+ // Required. The target instance configuration where to move the instance.
+ // Values are of the form `projects//instanceConfigs/