diff options
| author | Taras Madan <tarasmadan@google.com> | 2024-09-10 12:16:33 +0200 |
|---|---|---|
| committer | Taras Madan <tarasmadan@google.com> | 2024-09-10 14:05:26 +0000 |
| commit | c97c816133b42257d0bcf1ee4bd178bb2a7a2b9e (patch) | |
| tree | 0bcbc2e540bbf8f62f6c17887cdd53b8c2cee637 /vendor/cloud.google.com/go/spanner | |
| parent | 54e657429ab892ad06c90cd7c1a4eb33ba93a3dc (diff) | |
vendor: update
Diffstat (limited to 'vendor/cloud.google.com/go/spanner')
30 files changed, 2236 insertions, 745 deletions
diff --git a/vendor/cloud.google.com/go/spanner/CHANGES.md b/vendor/cloud.google.com/go/spanner/CHANGES.md index c7ba9674f..05453b9d0 100644 --- a/vendor/cloud.google.com/go/spanner/CHANGES.md +++ b/vendor/cloud.google.com/go/spanner/CHANGES.md @@ -1,5 +1,115 @@ # Changes +## [1.67.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.66.0...spanner/v1.67.0) (2024-08-15) + + +### Features + +* **spanner/admin/database:** Add resource reference annotation to backup schedules ([#10677](https://github.com/googleapis/google-cloud-go/issues/10677)) ([6593c0d](https://github.com/googleapis/google-cloud-go/commit/6593c0d62d48751c857bce3d3f858127467a4489)) +* **spanner/admin/instance:** Add edition field to the instance proto ([6593c0d](https://github.com/googleapis/google-cloud-go/commit/6593c0d62d48751c857bce3d3f858127467a4489)) +* **spanner:** Support commit options in mutation operations. ([#10668](https://github.com/googleapis/google-cloud-go/issues/10668)) ([62a56f9](https://github.com/googleapis/google-cloud-go/commit/62a56f953d3b8fe82083c42926831c2728312b9c)) + + +### Bug Fixes + +* **spanner/test/opentelemetry/test:** Update google.golang.org/api to v0.191.0 ([5b32644](https://github.com/googleapis/google-cloud-go/commit/5b32644eb82eb6bd6021f80b4fad471c60fb9d73)) +* **spanner:** Update google.golang.org/api to v0.191.0 ([5b32644](https://github.com/googleapis/google-cloud-go/commit/5b32644eb82eb6bd6021f80b4fad471c60fb9d73)) + + +### Documentation + +* **spanner/admin/database:** Add an example to filter backups based on schedule name ([6593c0d](https://github.com/googleapis/google-cloud-go/commit/6593c0d62d48751c857bce3d3f858127467a4489)) + +## [1.66.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.65.0...spanner/v1.66.0) (2024-08-07) + + +### Features + +* **spanner/admin/database:** Add support for Cloud Spanner Incremental Backups ([d949cc0](https://github.com/googleapis/google-cloud-go/commit/d949cc0e5d44af62154d9d5fd393f25a852f93ed)) +* **spanner:** Add support of multiplexed session support in writeAtleastOnce mutations ([#10646](https://github.com/googleapis/google-cloud-go/issues/10646)) ([54009ea](https://github.com/googleapis/google-cloud-go/commit/54009eab1c3b11a28531ad9e621917d01c9e5339)) +* **spanner:** Add support of using multiplexed session with ReadOnlyTransactions ([#10269](https://github.com/googleapis/google-cloud-go/issues/10269)) ([7797022](https://github.com/googleapis/google-cloud-go/commit/7797022e51d1ac07b8d919c421a8bfdf34a1d53c)) + +## [1.65.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.64.0...spanner/v1.65.0) (2024-07-29) + + +### Features + +* **spanner/admin/database:** Add support for Cloud Spanner Scheduled Backups ([3b15f9d](https://github.com/googleapis/google-cloud-go/commit/3b15f9db9e0ee3bff3d8d5aafc82cdc2a31d60fc)) +* **spanner:** Add RESOURCE_EXHAUSTED to retryable transaction codes ([#10412](https://github.com/googleapis/google-cloud-go/issues/10412)) ([29b52dc](https://github.com/googleapis/google-cloud-go/commit/29b52dc40f3d1a6ffe7fa40e6142d8035c0d95ee)) + + +### Bug Fixes + +* **spanner/test:** Bump google.golang.org/api@v0.187.0 ([8fa9e39](https://github.com/googleapis/google-cloud-go/commit/8fa9e398e512fd8533fd49060371e61b5725a85b)) +* **spanner/test:** Bump google.golang.org/grpc@v1.64.1 ([8ecc4e9](https://github.com/googleapis/google-cloud-go/commit/8ecc4e9622e5bbe9b90384d5848ab816027226c5)) +* **spanner/test:** Update dependencies ([257c40b](https://github.com/googleapis/google-cloud-go/commit/257c40bd6d7e59730017cf32bda8823d7a232758)) +* **spanner:** Bump google.golang.org/api@v0.187.0 ([8fa9e39](https://github.com/googleapis/google-cloud-go/commit/8fa9e398e512fd8533fd49060371e61b5725a85b)) +* **spanner:** Bump google.golang.org/grpc@v1.64.1 ([8ecc4e9](https://github.com/googleapis/google-cloud-go/commit/8ecc4e9622e5bbe9b90384d5848ab816027226c5)) +* **spanner:** Fix negative values for max_in_use_sessions metrics [#10449](https://github.com/googleapis/google-cloud-go/issues/10449) ([#10508](https://github.com/googleapis/google-cloud-go/issues/10508)) ([4e180f4](https://github.com/googleapis/google-cloud-go/commit/4e180f4539012eb6e3d1d2788e68b291ef7230c3)) +* **spanner:** HealthCheck should not decrement num_in_use sessions ([#10480](https://github.com/googleapis/google-cloud-go/issues/10480)) ([9b2b47f](https://github.com/googleapis/google-cloud-go/commit/9b2b47f107153d624d56709d9a8e6a6b72c39447)) +* **spanner:** Update dependencies ([257c40b](https://github.com/googleapis/google-cloud-go/commit/257c40bd6d7e59730017cf32bda8823d7a232758)) + +## [1.64.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.63.0...spanner/v1.64.0) (2024-06-29) + + +### Features + +* **spanner:** Add field lock_hint in spanner.proto ([3df3c04](https://github.com/googleapis/google-cloud-go/commit/3df3c04f0dffad3fa2fe272eb7b2c263801b9ada)) +* **spanner:** Add field order_by in spanner.proto ([3df3c04](https://github.com/googleapis/google-cloud-go/commit/3df3c04f0dffad3fa2fe272eb7b2c263801b9ada)) +* **spanner:** Add LockHint feature ([#10382](https://github.com/googleapis/google-cloud-go/issues/10382)) ([64bdcb1](https://github.com/googleapis/google-cloud-go/commit/64bdcb1a6a462d41a62d3badea6814425e271f22)) +* **spanner:** Add OrderBy feature ([#10289](https://github.com/googleapis/google-cloud-go/issues/10289)) ([07b8bd2](https://github.com/googleapis/google-cloud-go/commit/07b8bd2f5dc738e0293305dfc459c13632d5ea65)) +* **spanner:** Add support of checking row not found errors from ReadRow and ReadRowUsingIndex ([#10405](https://github.com/googleapis/google-cloud-go/issues/10405)) ([5cb0c26](https://github.com/googleapis/google-cloud-go/commit/5cb0c26013eeb3bbe51174bee628a20c2ec775e0)) + + +### Bug Fixes + +* **spanner:** Fix data-race caused by TrackSessionHandle ([#10321](https://github.com/googleapis/google-cloud-go/issues/10321)) ([23c5fff](https://github.com/googleapis/google-cloud-go/commit/23c5fffd06bcde408db50a981c015921cd4ecf0e)), refs [#10320](https://github.com/googleapis/google-cloud-go/issues/10320) +* **spanner:** Fix negative values for max_in_use_sessions metrics ([#10449](https://github.com/googleapis/google-cloud-go/issues/10449)) ([a1e198a](https://github.com/googleapis/google-cloud-go/commit/a1e198a9b18bd2f92c3438e4f609412047f8ccf4)) +* **spanner:** Prevent possible panic for Session not found errors ([#10386](https://github.com/googleapis/google-cloud-go/issues/10386)) ([ba9711f](https://github.com/googleapis/google-cloud-go/commit/ba9711f87ec871153ae00cfd0827bce17c31ee9c)), refs [#10385](https://github.com/googleapis/google-cloud-go/issues/10385) + +## [1.63.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.62.0...spanner/v1.63.0) (2024-05-24) + + +### Features + +* **spanner:** Fix schema naming ([#10194](https://github.com/googleapis/google-cloud-go/issues/10194)) ([215e0c8](https://github.com/googleapis/google-cloud-go/commit/215e0c8125ea05246c834984bde1ca698c7dde4c)) +* **spanner:** Update go mod to use latest grpc lib ([#10218](https://github.com/googleapis/google-cloud-go/issues/10218)) ([adf91f9](https://github.com/googleapis/google-cloud-go/commit/adf91f9fd37faa39ec7c6f9200273220f65d2a82)) + +## [1.62.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.61.0...spanner/v1.62.0) (2024-05-15) + + +### Features + +* **spanner/admin/database:** Add support for multi region encryption config ([3e25053](https://github.com/googleapis/google-cloud-go/commit/3e250530567ee81ed4f51a3856c5940dbec35289)) +* **spanner/executor:** Add QueryCancellationAction message in executor protos ([292e812](https://github.com/googleapis/google-cloud-go/commit/292e81231b957ae7ac243b47b8926564cee35920)) +* **spanner:** Add `RESOURCE_EXHAUSTED` to the list of retryable error codes ([1d757c6](https://github.com/googleapis/google-cloud-go/commit/1d757c66478963d6cbbef13fee939632c742759c)) +* **spanner:** Add support for Proto Columns ([#9315](https://github.com/googleapis/google-cloud-go/issues/9315)) ([3ffbbbe](https://github.com/googleapis/google-cloud-go/commit/3ffbbbe50225684f4211c6dbe3ca25acb3d02b8e)) + + +### Bug Fixes + +* **spanner:** Add ARRAY keywords to keywords ([#10079](https://github.com/googleapis/google-cloud-go/issues/10079)) ([8e675cd](https://github.com/googleapis/google-cloud-go/commit/8e675cd0ccf12c6912209aa5c56092db3716c40d)) +* **spanner:** Handle unused errors ([#10067](https://github.com/googleapis/google-cloud-go/issues/10067)) ([a0c097c](https://github.com/googleapis/google-cloud-go/commit/a0c097c724b609cfa428e69f89075f02a3782a7b)) +* **spanner:** Remove json-iterator dependency ([#10099](https://github.com/googleapis/google-cloud-go/issues/10099)) ([3917cca](https://github.com/googleapis/google-cloud-go/commit/3917ccac57c403b3b4d07514ac10a66a86e298c0)), refs [#9380](https://github.com/googleapis/google-cloud-go/issues/9380) +* **spanner:** Update staleness bound ([#10118](https://github.com/googleapis/google-cloud-go/issues/10118)) ([c07f1e4](https://github.com/googleapis/google-cloud-go/commit/c07f1e47c06387b696abb1edbfa339b391ec1fd5)) + +## [1.61.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.60.0...spanner/v1.61.0) (2024-04-30) + + +### Features + +* **spanner/admin/instance:** Adding `EXPECTED_FULFILLMENT_PERIOD` to the indicate instance creation times (with `FULFILLMENT_PERIOD_NORMAL` or `FULFILLMENT_PERIOD_EXTENDED` ENUM) with the extended instance creation time triggered by On-Demand Capacity... ([#9693](https://github.com/googleapis/google-cloud-go/issues/9693)) ([aa93790](https://github.com/googleapis/google-cloud-go/commit/aa93790132ba830b4c97d217ef02764e2fb1b8ea)) +* **spanner/executor:** Add SessionPoolOptions, SpannerOptions protos in executor protos ([2cdc40a](https://github.com/googleapis/google-cloud-go/commit/2cdc40a0b4288f5ab5f2b2b8f5c1d6453a9c81ec)) +* **spanner:** Add support for change streams transaction exclusion option ([#9779](https://github.com/googleapis/google-cloud-go/issues/9779)) ([979ce94](https://github.com/googleapis/google-cloud-go/commit/979ce94758442b1224a78a4f3b1f5d592ab51660)) +* **spanner:** Support MultiEndpoint ([#9565](https://github.com/googleapis/google-cloud-go/issues/9565)) ([0ac0d26](https://github.com/googleapis/google-cloud-go/commit/0ac0d265abedf946b05294ef874a892b2c5d6067)) + + +### Bug Fixes + +* **spanner/test/opentelemetry/test:** Bump x/net to v0.24.0 ([ba31ed5](https://github.com/googleapis/google-cloud-go/commit/ba31ed5fda2c9664f2e1cf972469295e63deb5b4)) +* **spanner:** Bump x/net to v0.24.0 ([ba31ed5](https://github.com/googleapis/google-cloud-go/commit/ba31ed5fda2c9664f2e1cf972469295e63deb5b4)) +* **spanner:** Fix uint8 conversion ([9221c7f](https://github.com/googleapis/google-cloud-go/commit/9221c7fa12cef9d5fb7ddc92f41f1d6204971c7b)) + ## [1.60.0](https://github.com/googleapis/google-cloud-go/compare/spanner/v1.59.0...spanner/v1.60.0) (2024-03-19) diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spanner_client.go b/vendor/cloud.google.com/go/spanner/apiv1/spanner_client.go index af48f11c0..ccc6aa769 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spanner_client.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spanner_client.go @@ -19,6 +19,7 @@ package spanner import ( "bytes" "context" + "errors" "fmt" "io" "math" @@ -84,6 +85,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -96,6 +98,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -108,6 +111,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -120,6 +124,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -132,6 +137,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -144,6 +150,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -157,6 +164,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -169,6 +177,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -182,6 +191,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -194,6 +204,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -206,6 +217,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -218,6 +230,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -230,6 +243,7 @@ func defaultCallOptions() *CallOptions { gax.WithRetry(func() gax.Retryer { return gax.OnCodes([]codes.Code{ codes.Unavailable, + codes.ResourceExhausted, }, gax.Backoff{ Initial: 250 * time.Millisecond, Max: 32000 * time.Millisecond, @@ -251,7 +265,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, BatchCreateSessions: []gax.CallOption{ @@ -262,7 +277,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, GetSession: []gax.CallOption{ @@ -273,7 +289,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, ListSessions: []gax.CallOption{ @@ -284,7 +301,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, DeleteSession: []gax.CallOption{ @@ -295,7 +313,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, ExecuteSql: []gax.CallOption{ @@ -306,7 +325,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, ExecuteStreamingSql: []gax.CallOption{ @@ -320,7 +340,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, Read: []gax.CallOption{ @@ -331,7 +352,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, StreamingRead: []gax.CallOption{ @@ -345,7 +367,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, Commit: []gax.CallOption{ @@ -356,7 +379,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, Rollback: []gax.CallOption{ @@ -367,7 +391,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, PartitionQuery: []gax.CallOption{ @@ -378,7 +403,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, PartitionRead: []gax.CallOption{ @@ -389,7 +415,8 @@ func defaultRESTCallOptions() *CallOptions { Max: 32000 * time.Millisecond, Multiplier: 1.30, }, - http.StatusServiceUnavailable) + http.StatusServiceUnavailable, + http.StatusTooManyRequests) }), }, BatchWrite: []gax.CallOption{ @@ -737,7 +764,9 @@ func (c *gRPCClient) Connection() *grpc.ClientConn { func (c *gRPCClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "grpc", grpc.Version) - c.xGoogHeaders = []string{"x-goog-api-client", gax.XGoogHeader(kv...)} + c.xGoogHeaders = []string{ + "x-goog-api-client", gax.XGoogHeader(kv...), + } } // Close closes the connection to the API service. The user should invoke this when @@ -802,7 +831,9 @@ func defaultRESTClientOptions() []option.ClientOption { func (c *restClient) setGoogleClientInfo(keyval ...string) { kv := append([]string{"gl-go", gax.GoVersion}, keyval...) kv = append(kv, "gapic", getVersionClient(), "gax", gax.Version, "rest", "UNKNOWN") - c.xGoogHeaders = []string{"x-goog-api-client", gax.XGoogHeader(kv...)} + c.xGoogHeaders = []string{ + "x-goog-api-client", gax.XGoogHeader(kv...), + } } // Close closes the connection to the API service. The user should invoke this when @@ -1649,7 +1680,7 @@ func (c *executeStreamingSqlRESTClient) Trailer() metadata.MD { func (c *executeStreamingSqlRESTClient) CloseSend() error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented for a server-stream") + return errors.New("this method is not implemented for a server-stream") } func (c *executeStreamingSqlRESTClient) Context() context.Context { @@ -1658,12 +1689,12 @@ func (c *executeStreamingSqlRESTClient) Context() context.Context { func (c *executeStreamingSqlRESTClient) SendMsg(m interface{}) error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented for a server-stream") + return errors.New("this method is not implemented for a server-stream") } func (c *executeStreamingSqlRESTClient) RecvMsg(m interface{}) error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented, use Recv") + return errors.New("this method is not implemented, use Recv") } // ExecuteBatchDml executes a batch of SQL DML statements. This method allows many statements @@ -1915,7 +1946,7 @@ func (c *streamingReadRESTClient) Trailer() metadata.MD { func (c *streamingReadRESTClient) CloseSend() error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented for a server-stream") + return errors.New("this method is not implemented for a server-stream") } func (c *streamingReadRESTClient) Context() context.Context { @@ -1924,12 +1955,12 @@ func (c *streamingReadRESTClient) Context() context.Context { func (c *streamingReadRESTClient) SendMsg(m interface{}) error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented for a server-stream") + return errors.New("this method is not implemented for a server-stream") } func (c *streamingReadRESTClient) RecvMsg(m interface{}) error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented, use Recv") + return errors.New("this method is not implemented, use Recv") } // BeginTransaction begins a new transaction. This step can often be skipped: @@ -2396,7 +2427,7 @@ func (c *batchWriteRESTClient) Trailer() metadata.MD { func (c *batchWriteRESTClient) CloseSend() error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented for a server-stream") + return errors.New("this method is not implemented for a server-stream") } func (c *batchWriteRESTClient) Context() context.Context { @@ -2405,10 +2436,10 @@ func (c *batchWriteRESTClient) Context() context.Context { func (c *batchWriteRESTClient) SendMsg(m interface{}) error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented for a server-stream") + return errors.New("this method is not implemented for a server-stream") } func (c *batchWriteRESTClient) RecvMsg(m interface{}) error { // This is a no-op to fulfill the interface. - return fmt.Errorf("this method is not implemented, use Recv") + return errors.New("this method is not implemented, use Recv") } diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/commit_response.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/commit_response.pb.go index f038031f3..ccfb44258 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/commit_response.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/commit_response.pb.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/commit_response.proto package spannerpb @@ -201,7 +201,7 @@ func file_google_spanner_v1_commit_response_proto_rawDescGZIP() []byte { } var file_google_spanner_v1_commit_response_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_google_spanner_v1_commit_response_proto_goTypes = []interface{}{ +var file_google_spanner_v1_commit_response_proto_goTypes = []any{ (*CommitResponse)(nil), // 0: google.spanner.v1.CommitResponse (*CommitResponse_CommitStats)(nil), // 1: google.spanner.v1.CommitResponse.CommitStats (*timestamppb.Timestamp)(nil), // 2: google.protobuf.Timestamp @@ -222,7 +222,7 @@ func file_google_spanner_v1_commit_response_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_commit_response_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_commit_response_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*CommitResponse); i { case 0: return &v.state @@ -234,7 +234,7 @@ func file_google_spanner_v1_commit_response_proto_init() { return nil } } - file_google_spanner_v1_commit_response_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_commit_response_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*CommitResponse_CommitStats); i { case 0: return &v.state diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/keys.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/keys.pb.go index 84444aefb..0cfb01a43 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/keys.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/keys.pb.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/keys.proto package spannerpb @@ -399,7 +399,7 @@ func file_google_spanner_v1_keys_proto_rawDescGZIP() []byte { } var file_google_spanner_v1_keys_proto_msgTypes = make([]protoimpl.MessageInfo, 2) -var file_google_spanner_v1_keys_proto_goTypes = []interface{}{ +var file_google_spanner_v1_keys_proto_goTypes = []any{ (*KeyRange)(nil), // 0: google.spanner.v1.KeyRange (*KeySet)(nil), // 1: google.spanner.v1.KeySet (*structpb.ListValue)(nil), // 2: google.protobuf.ListValue @@ -424,7 +424,7 @@ func file_google_spanner_v1_keys_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_keys_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_keys_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*KeyRange); i { case 0: return &v.state @@ -436,7 +436,7 @@ func file_google_spanner_v1_keys_proto_init() { return nil } } - file_google_spanner_v1_keys_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_keys_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*KeySet); i { case 0: return &v.state @@ -449,7 +449,7 @@ func file_google_spanner_v1_keys_proto_init() { } } } - file_google_spanner_v1_keys_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_google_spanner_v1_keys_proto_msgTypes[0].OneofWrappers = []any{ (*KeyRange_StartClosed)(nil), (*KeyRange_StartOpen)(nil), (*KeyRange_EndClosed)(nil), diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/mutation.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/mutation.pb.go index 533114d3a..bdbbac372 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/mutation.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/mutation.pb.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/mutation.proto package spannerpb @@ -403,7 +403,7 @@ func file_google_spanner_v1_mutation_proto_rawDescGZIP() []byte { } var file_google_spanner_v1_mutation_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_google_spanner_v1_mutation_proto_goTypes = []interface{}{ +var file_google_spanner_v1_mutation_proto_goTypes = []any{ (*Mutation)(nil), // 0: google.spanner.v1.Mutation (*Mutation_Write)(nil), // 1: google.spanner.v1.Mutation.Write (*Mutation_Delete)(nil), // 2: google.spanner.v1.Mutation.Delete @@ -432,7 +432,7 @@ func file_google_spanner_v1_mutation_proto_init() { } file_google_spanner_v1_keys_proto_init() if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_mutation_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_mutation_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*Mutation); i { case 0: return &v.state @@ -444,7 +444,7 @@ func file_google_spanner_v1_mutation_proto_init() { return nil } } - file_google_spanner_v1_mutation_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_mutation_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*Mutation_Write); i { case 0: return &v.state @@ -456,7 +456,7 @@ func file_google_spanner_v1_mutation_proto_init() { return nil } } - file_google_spanner_v1_mutation_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_mutation_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*Mutation_Delete); i { case 0: return &v.state @@ -469,7 +469,7 @@ func file_google_spanner_v1_mutation_proto_init() { } } } - file_google_spanner_v1_mutation_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_google_spanner_v1_mutation_proto_msgTypes[0].OneofWrappers = []any{ (*Mutation_Insert)(nil), (*Mutation_Update)(nil), (*Mutation_InsertOrUpdate)(nil), diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/query_plan.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/query_plan.pb.go index 6054ee59c..fe4411080 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/query_plan.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/query_plan.pb.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/query_plan.proto package spannerpb @@ -494,7 +494,7 @@ func file_google_spanner_v1_query_plan_proto_rawDescGZIP() []byte { var file_google_spanner_v1_query_plan_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_google_spanner_v1_query_plan_proto_msgTypes = make([]protoimpl.MessageInfo, 5) -var file_google_spanner_v1_query_plan_proto_goTypes = []interface{}{ +var file_google_spanner_v1_query_plan_proto_goTypes = []any{ (PlanNode_Kind)(0), // 0: google.spanner.v1.PlanNode.Kind (*PlanNode)(nil), // 1: google.spanner.v1.PlanNode (*QueryPlan)(nil), // 2: google.spanner.v1.QueryPlan @@ -524,7 +524,7 @@ func file_google_spanner_v1_query_plan_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_query_plan_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_query_plan_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*PlanNode); i { case 0: return &v.state @@ -536,7 +536,7 @@ func file_google_spanner_v1_query_plan_proto_init() { return nil } } - file_google_spanner_v1_query_plan_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_query_plan_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*QueryPlan); i { case 0: return &v.state @@ -548,7 +548,7 @@ func file_google_spanner_v1_query_plan_proto_init() { return nil } } - file_google_spanner_v1_query_plan_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_query_plan_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*PlanNode_ChildLink); i { case 0: return &v.state @@ -560,7 +560,7 @@ func file_google_spanner_v1_query_plan_proto_init() { return nil } } - file_google_spanner_v1_query_plan_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_query_plan_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*PlanNode_ShortRepresentation); i { case 0: return &v.state diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/result_set.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/result_set.pb.go index 1f6ca2783..57b2cb401 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/result_set.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/result_set.pb.go @@ -1,4 +1,4 @@ -// Copyright 2022 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/result_set.proto package spannerpb @@ -584,7 +584,7 @@ func file_google_spanner_v1_result_set_proto_rawDescGZIP() []byte { } var file_google_spanner_v1_result_set_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_google_spanner_v1_result_set_proto_goTypes = []interface{}{ +var file_google_spanner_v1_result_set_proto_goTypes = []any{ (*ResultSet)(nil), // 0: google.spanner.v1.ResultSet (*PartialResultSet)(nil), // 1: google.spanner.v1.PartialResultSet (*ResultSetMetadata)(nil), // 2: google.spanner.v1.ResultSetMetadata @@ -624,7 +624,7 @@ func file_google_spanner_v1_result_set_proto_init() { file_google_spanner_v1_transaction_proto_init() file_google_spanner_v1_type_proto_init() if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_result_set_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_result_set_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*ResultSet); i { case 0: return &v.state @@ -636,7 +636,7 @@ func file_google_spanner_v1_result_set_proto_init() { return nil } } - file_google_spanner_v1_result_set_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_result_set_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*PartialResultSet); i { case 0: return &v.state @@ -648,7 +648,7 @@ func file_google_spanner_v1_result_set_proto_init() { return nil } } - file_google_spanner_v1_result_set_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_result_set_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*ResultSetMetadata); i { case 0: return &v.state @@ -660,7 +660,7 @@ func file_google_spanner_v1_result_set_proto_init() { return nil } } - file_google_spanner_v1_result_set_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_result_set_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*ResultSetStats); i { case 0: return &v.state @@ -673,7 +673,7 @@ func file_google_spanner_v1_result_set_proto_init() { } } } - file_google_spanner_v1_result_set_proto_msgTypes[3].OneofWrappers = []interface{}{ + file_google_spanner_v1_result_set_proto_msgTypes[3].OneofWrappers = []any{ (*ResultSetStats_RowCountExact)(nil), (*ResultSetStats_RowCountLowerBound)(nil), } diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/spanner.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/spanner.pb.go index c4f656d33..6831ecbc7 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/spanner.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/spanner.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/spanner.proto package spannerpb @@ -225,6 +225,153 @@ func (ExecuteSqlRequest_QueryMode) EnumDescriptor() ([]byte, []int) { return file_google_spanner_v1_spanner_proto_rawDescGZIP(), []int{10, 0} } +// An option to control the order in which rows are returned from a read. +type ReadRequest_OrderBy int32 + +const ( + // Default value. + // + // ORDER_BY_UNSPECIFIED is equivalent to ORDER_BY_PRIMARY_KEY. + ReadRequest_ORDER_BY_UNSPECIFIED ReadRequest_OrderBy = 0 + // Read rows are returned in primary key order. + // + // In the event that this option is used in conjunction with the + // `partition_token` field, the API will return an `INVALID_ARGUMENT` error. + ReadRequest_ORDER_BY_PRIMARY_KEY ReadRequest_OrderBy = 1 + // Read rows are returned in any order. + ReadRequest_ORDER_BY_NO_ORDER ReadRequest_OrderBy = 2 +) + +// Enum value maps for ReadRequest_OrderBy. +var ( + ReadRequest_OrderBy_name = map[int32]string{ + 0: "ORDER_BY_UNSPECIFIED", + 1: "ORDER_BY_PRIMARY_KEY", + 2: "ORDER_BY_NO_ORDER", + } + ReadRequest_OrderBy_value = map[string]int32{ + "ORDER_BY_UNSPECIFIED": 0, + "ORDER_BY_PRIMARY_KEY": 1, + "ORDER_BY_NO_ORDER": 2, + } +) + +func (x ReadRequest_OrderBy) Enum() *ReadRequest_OrderBy { + p := new(ReadRequest_OrderBy) + *p = x + return p +} + +func (x ReadRequest_OrderBy) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ReadRequest_OrderBy) Descriptor() protoreflect.EnumDescriptor { + return file_google_spanner_v1_spanner_proto_enumTypes[3].Descriptor() +} + +func (ReadRequest_OrderBy) Type() protoreflect.EnumType { + return &file_google_spanner_v1_spanner_proto_enumTypes[3] +} + +func (x ReadRequest_OrderBy) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ReadRequest_OrderBy.Descriptor instead. +func (ReadRequest_OrderBy) EnumDescriptor() ([]byte, []int) { + return file_google_spanner_v1_spanner_proto_rawDescGZIP(), []int{18, 0} +} + +// A lock hint mechanism for reads done within a transaction. +type ReadRequest_LockHint int32 + +const ( + // Default value. + // + // LOCK_HINT_UNSPECIFIED is equivalent to LOCK_HINT_SHARED. + ReadRequest_LOCK_HINT_UNSPECIFIED ReadRequest_LockHint = 0 + // Acquire shared locks. + // + // By default when you perform a read as part of a read-write transaction, + // Spanner acquires shared read locks, which allows other reads to still + // access the data until your transaction is ready to commit. When your + // transaction is committing and writes are being applied, the transaction + // attempts to upgrade to an exclusive lock for any data you are writing. + // For more information about locks, see [Lock + // modes](https://cloud.google.com/spanner/docs/introspection/lock-statistics#explain-lock-modes). + ReadRequest_LOCK_HINT_SHARED ReadRequest_LockHint = 1 + // Acquire exclusive locks. + // + // Requesting exclusive locks is beneficial if you observe high write + // contention, which means you notice that multiple transactions are + // concurrently trying to read and write to the same data, resulting in a + // large number of aborts. This problem occurs when two transactions + // initially acquire shared locks and then both try to upgrade to exclusive + // locks at the same time. In this situation both transactions are waiting + // for the other to give up their lock, resulting in a deadlocked situation. + // Spanner is able to detect this occurring and force one of the + // transactions to abort. However, this is a slow and expensive operation + // and results in lower performance. In this case it makes sense to acquire + // exclusive locks at the start of the transaction because then when + // multiple transactions try to act on the same data, they automatically get + // serialized. Each transaction waits its turn to acquire the lock and + // avoids getting into deadlock situations. + // + // Because the exclusive lock hint is just a hint, it should not be + // considered equivalent to a mutex. In other words, you should not use + // Spanner exclusive locks as a mutual exclusion mechanism for the execution + // of code outside of Spanner. + // + // **Note:** Request exclusive locks judiciously because they block others + // from reading that data for the entire transaction, rather than just when + // the writes are being performed. Unless you observe high write contention, + // you should use the default of shared read locks so you don't prematurely + // block other clients from reading the data that you're writing to. + ReadRequest_LOCK_HINT_EXCLUSIVE ReadRequest_LockHint = 2 +) + +// Enum value maps for ReadRequest_LockHint. +var ( + ReadRequest_LockHint_name = map[int32]string{ + 0: "LOCK_HINT_UNSPECIFIED", + 1: "LOCK_HINT_SHARED", + 2: "LOCK_HINT_EXCLUSIVE", + } + ReadRequest_LockHint_value = map[string]int32{ + "LOCK_HINT_UNSPECIFIED": 0, + "LOCK_HINT_SHARED": 1, + "LOCK_HINT_EXCLUSIVE": 2, + } +) + +func (x ReadRequest_LockHint) Enum() *ReadRequest_LockHint { + p := new(ReadRequest_LockHint) + *p = x + return p +} + +func (x ReadRequest_LockHint) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (ReadRequest_LockHint) Descriptor() protoreflect.EnumDescriptor { + return file_google_spanner_v1_spanner_proto_enumTypes[4].Descriptor() +} + +func (ReadRequest_LockHint) Type() protoreflect.EnumType { + return &file_google_spanner_v1_spanner_proto_enumTypes[4] +} + +func (x ReadRequest_LockHint) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use ReadRequest_LockHint.Descriptor instead. +func (ReadRequest_LockHint) EnumDescriptor() ([]byte, []int) { + return file_google_spanner_v1_spanner_proto_rawDescGZIP(), []int{18, 1} +} + // The request for [CreateSession][google.spanner.v1.Spanner.CreateSession]. type CreateSessionRequest struct { state protoimpl.MessageState @@ -1851,6 +1998,17 @@ type ReadRequest struct { // If the field is set to `true` but the request does not set // `partition_token`, the API returns an `INVALID_ARGUMENT` error. DataBoostEnabled bool `protobuf:"varint,15,opt,name=data_boost_enabled,json=dataBoostEnabled,proto3" json:"data_boost_enabled,omitempty"` + // Optional. Order for the returned rows. + // + // By default, Spanner will return result rows in primary key order except for + // PartitionRead requests. For applications that do not require rows to be + // returned in primary key (`ORDER_BY_PRIMARY_KEY`) order, setting + // `ORDER_BY_NO_ORDER` option allows Spanner to optimize row retrieval, + // resulting in lower latencies in certain cases (e.g. bulk point lookups). + OrderBy ReadRequest_OrderBy `protobuf:"varint,16,opt,name=order_by,json=orderBy,proto3,enum=google.spanner.v1.ReadRequest_OrderBy" json:"order_by,omitempty"` + // Optional. Lock Hint for the request, it can only be used with read-write + // transactions. + LockHint ReadRequest_LockHint `protobuf:"varint,17,opt,name=lock_hint,json=lockHint,proto3,enum=google.spanner.v1.ReadRequest_LockHint" json:"lock_hint,omitempty"` } func (x *ReadRequest) Reset() { @@ -1969,6 +2127,20 @@ func (x *ReadRequest) GetDataBoostEnabled() bool { return false } +func (x *ReadRequest) GetOrderBy() ReadRequest_OrderBy { + if x != nil { + return x.OrderBy + } + return ReadRequest_ORDER_BY_UNSPECIFIED +} + +func (x *ReadRequest) GetLockHint() ReadRequest_LockHint { + if x != nil { + return x.LockHint + } + return ReadRequest_LOCK_HINT_UNSPECIFIED +} + // The request for // [BeginTransaction][google.spanner.v1.Spanner.BeginTransaction]. type BeginTransactionRequest struct { @@ -3204,7 +3376,7 @@ var file_google_spanner_v1_spanner_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x22, 0xda, 0x04, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x6e, 0x22, 0x99, 0x07, 0x0a, 0x0b, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, @@ -3241,308 +3413,328 @@ var file_google_spanner_v1_spanner_proto_rawDesc = []byte{ 0x65, 0x63, 0x74, 0x65, 0x64, 0x52, 0x65, 0x61, 0x64, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2c, 0x0a, 0x12, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x62, 0x6f, 0x6f, 0x73, 0x74, 0x5f, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x64, 0x61, - 0x74, 0x61, 0x42, 0x6f, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x22, 0xed, - 0x01, 0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe0, 0x41, 0x02, - 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x07, - 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x12, 0x4a, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0e, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe9, - 0x03, 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x74, 0x61, 0x42, 0x6f, 0x6f, 0x73, 0x74, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x46, + 0x0a, 0x08, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x62, 0x79, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0e, + 0x32, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, + 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x2e, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x07, 0x6f, + 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x49, 0x0a, 0x09, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, + 0x69, 0x6e, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, + 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4c, 0x6f, 0x63, 0x6b, 0x48, 0x69, + 0x6e, 0x74, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x69, 0x6e, + 0x74, 0x22, 0x54, 0x0a, 0x07, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x42, 0x79, 0x12, 0x18, 0x0a, 0x14, + 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x42, 0x59, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, + 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x18, 0x0a, 0x14, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, + 0x42, 0x59, 0x5f, 0x50, 0x52, 0x49, 0x4d, 0x41, 0x52, 0x59, 0x5f, 0x4b, 0x45, 0x59, 0x10, 0x01, + 0x12, 0x15, 0x0a, 0x11, 0x4f, 0x52, 0x44, 0x45, 0x52, 0x5f, 0x42, 0x59, 0x5f, 0x4e, 0x4f, 0x5f, + 0x4f, 0x52, 0x44, 0x45, 0x52, 0x10, 0x02, 0x22, 0x54, 0x0a, 0x08, 0x4c, 0x6f, 0x63, 0x6b, 0x48, + 0x69, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x15, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x49, 0x4e, 0x54, + 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x14, + 0x0a, 0x10, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x49, 0x4e, 0x54, 0x5f, 0x53, 0x48, 0x41, 0x52, + 0x45, 0x44, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x4c, 0x4f, 0x43, 0x4b, 0x5f, 0x48, 0x49, 0x4e, + 0x54, 0x5f, 0x45, 0x58, 0x43, 0x4c, 0x55, 0x53, 0x49, 0x56, 0x45, 0x10, 0x02, 0x22, 0xed, 0x01, + 0x0a, 0x17, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe0, 0x41, 0x02, 0xfa, + 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x44, 0x0a, 0x07, 0x6f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x73, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x07, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x12, 0x4a, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0e, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xe9, 0x03, + 0x0a, 0x0d, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, + 0x40, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x42, 0x26, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, + 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, + 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0d, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x5d, 0x0a, 0x16, 0x73, 0x69, + 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x54, + 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x48, 0x00, 0x52, 0x14, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x54, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09, 0x6d, 0x75, 0x74, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6d, 0x75, 0x74, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, 0x63, + 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x11, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x53, + 0x74, 0x61, 0x74, 0x73, 0x12, 0x48, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, + 0x69, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x0e, + 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x4a, + 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0e, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x74, 0x72, + 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7f, 0x0a, 0x0f, 0x52, 0x6f, 0x6c, + 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x07, + 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe0, + 0x41, 0x02, 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, + 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0d, 0x74, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x9f, 0x03, 0x0a, 0x11, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x12, 0x27, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x48, 0x00, 0x52, 0x0d, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x5d, 0x0a, 0x16, 0x73, - 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x25, 0x2e, 0x67, 0x6f, + 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x70, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x48, 0x00, 0x52, 0x14, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x55, 0x73, 0x65, 0x54, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x09, 0x6d, 0x75, - 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1b, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6d, 0x75, 0x74, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2e, 0x0a, 0x13, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x73, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x11, 0x72, 0x65, 0x74, 0x75, 0x72, 0x6e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x48, 0x0a, 0x10, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x6d, - 0x6d, 0x69, 0x74, 0x5f, 0x64, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x19, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x44, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, - 0x0e, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x44, 0x65, 0x6c, 0x61, 0x79, 0x12, - 0x4a, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0e, 0x72, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x42, 0x0d, 0x0a, 0x0b, 0x74, - 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x7f, 0x0a, 0x0f, 0x52, 0x6f, - 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x40, 0x0a, - 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x26, - 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x2a, 0x0a, 0x0e, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x03, 0xe0, 0x41, 0x02, 0x52, 0x0d, 0x74, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x9f, 0x03, 0x0a, 0x11, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x40, 0x0a, 0x07, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x42, 0x26, 0xe0, 0x41, 0x02, 0xfa, 0x41, 0x20, 0x0a, 0x1e, 0x73, 0x70, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, - 0x6f, 0x6d, 0x2f, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x4a, 0x0a, 0x0f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, - 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, - 0x60, 0x0a, 0x0f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, - 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x03, 0xe0, 0x41, - 0x02, 0x52, 0x0e, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, - 0x73, 0x12, 0x49, 0x0a, 0x1f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x78, 0x6e, - 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, - 0x1b, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x78, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x1a, 0x4f, 0x0a, 0x0d, - 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x3e, 0x0a, - 0x09, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, - 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x03, 0xe0, - 0x41, 0x02, 0x52, 0x09, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa1, 0x01, - 0x0a, 0x12, 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x18, - 0x01, 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x2a, - 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, - 0x75, 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x45, 0x0a, 0x10, 0x63, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x32, 0x8b, 0x18, 0x0a, 0x07, 0x53, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0xa6, 0x01, - 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, - 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x50, 0xda, 0x41, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3f, 0x3a, 0x01, 0x2a, 0x22, 0x3a, 0x2f, 0x76, 0x31, 0x2f, - 0x7b, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, - 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, - 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xe0, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2d, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x0e, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x60, + 0x0a, 0x0f, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x32, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x75, + 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x03, 0xe0, 0x41, 0x02, + 0x52, 0x0e, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, + 0x12, 0x49, 0x0a, 0x1f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x74, 0x78, 0x6e, 0x5f, + 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x5f, 0x73, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x42, 0x03, 0xe0, 0x41, 0x01, 0x52, 0x1b, + 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x54, 0x78, 0x6e, 0x46, 0x72, 0x6f, 0x6d, 0x43, 0x68, + 0x61, 0x6e, 0x67, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x73, 0x1a, 0x4f, 0x0a, 0x0d, 0x4d, + 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x3e, 0x0a, 0x09, + 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x03, 0xe0, 0x41, + 0x02, 0x52, 0x09, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xa1, 0x01, 0x0a, + 0x12, 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x18, 0x01, + 0x20, 0x03, 0x28, 0x05, 0x52, 0x07, 0x69, 0x6e, 0x64, 0x65, 0x78, 0x65, 0x73, 0x12, 0x2a, 0x0a, + 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x45, 0x0a, 0x10, 0x63, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x0f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, + 0x32, 0x8b, 0x18, 0x0a, 0x07, 0x53, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0xa6, 0x01, 0x0a, + 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x22, 0x50, 0xda, 0x41, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3f, 0x3a, 0x01, 0x2a, 0x22, 0x3a, 0x2f, 0x76, 0x31, 0x2f, 0x7b, + 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, + 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0xe0, 0x01, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x2d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6a, 0xda, - 0x41, 0x16, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2c, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x3a, 0x01, - 0x2a, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6a, 0xda, 0x41, + 0x16, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x2c, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x3a, 0x01, 0x2a, + 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x3d, + 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, + 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, + 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x62, 0x61, 0x74, + 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x53, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x47, 0xda, 0x41, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x12, 0x38, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, + 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, + 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, + 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, + 0x2a, 0x7d, 0x12, 0xae, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, + 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4d, 0xda, 0x41, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, + 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x12, 0x3a, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x64, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, + 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, + 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, + 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x47, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x2a, 0x38, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, - 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x3a, 0x62, 0x61, - 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x12, 0x97, 0x01, 0x0a, 0x0a, 0x47, 0x65, - 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x47, 0xda, 0x41, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x12, 0x38, 0x2f, 0x76, 0x31, 0x2f, 0x7b, - 0x6e, 0x61, 0x6d, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, - 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, - 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, - 0x2f, 0x2a, 0x7d, 0x12, 0xae, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x26, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, - 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x4d, 0xda, 0x41, 0x08, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3c, 0x12, 0x3a, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x64, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x7d, 0x2f, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x99, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x53, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, - 0x65, 0x53, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x47, 0xda, 0x41, 0x04, 0x6e, 0x61, 0x6d, 0x65, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x3a, 0x2a, 0x38, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x6e, 0x61, 0x6d, - 0x65, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, - 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, - 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, - 0x12, 0xa3, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x12, - 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, - 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, - 0x53, 0x65, 0x74, 0x22, 0x51, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x3a, 0x01, 0x2a, 0x22, 0x46, - 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, - 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, - 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, - 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x65, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x12, 0xbe, 0x01, 0x0a, 0x13, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x71, 0x6c, 0x12, 0x24, + 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x12, + 0xa3, 0x01, 0x0a, 0x0a, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, - 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x74, 0x22, 0x5a, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x54, 0x3a, 0x01, 0x2a, 0x22, 0x4f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, - 0x7d, 0x3a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, - 0x6e, 0x67, 0x53, 0x71, 0x6c, 0x30, 0x01, 0x12, 0xc0, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, - 0x75, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x12, 0x29, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, - 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x22, 0x56, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x3a, 0x01, 0x2a, 0x22, 0x4b, 0x2f, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, + 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, + 0x65, 0x74, 0x22, 0x51, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x3a, 0x01, 0x2a, 0x22, 0x46, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x65, 0x78, 0x65, 0x63, 0x75, - 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x12, 0x91, 0x01, 0x0a, 0x04, 0x52, - 0x65, 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, - 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, - 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x65, - 0x74, 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x45, 0x3a, 0x01, 0x2a, 0x22, 0x40, 0x2f, 0x76, + 0x74, 0x65, 0x53, 0x71, 0x6c, 0x12, 0xbe, 0x01, 0x0a, 0x13, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x53, 0x71, 0x6c, 0x12, 0x24, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x71, 0x6c, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x52, + 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x74, 0x22, 0x5a, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x54, + 0x3a, 0x01, 0x2a, 0x22, 0x4f, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, + 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, + 0x3a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, + 0x67, 0x53, 0x71, 0x6c, 0x30, 0x01, 0x12, 0xc0, 0x01, 0x0a, 0x0f, 0x45, 0x78, 0x65, 0x63, 0x75, + 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x12, 0x29, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, + 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x22, 0x56, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x50, 0x3a, 0x01, 0x2a, 0x22, 0x4b, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x72, 0x65, 0x61, 0x64, 0x12, 0xac, - 0x01, 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, - 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x75, - 0x6c, 0x74, 0x53, 0x65, 0x74, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x3a, 0x01, 0x2a, - 0x22, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, - 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x73, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x30, 0x01, 0x12, 0xc9, 0x01, - 0x0a, 0x10, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, - 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, - 0x76, 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x69, - 0xda, 0x41, 0x0f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x51, 0x3a, 0x01, 0x2a, 0x22, 0x4c, 0x2f, 0x76, 0x31, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x65, 0x78, 0x65, 0x63, 0x75, 0x74, + 0x65, 0x42, 0x61, 0x74, 0x63, 0x68, 0x44, 0x6d, 0x6c, 0x12, 0x91, 0x01, 0x0a, 0x04, 0x52, 0x65, + 0x61, 0x64, 0x12, 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, + 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, + 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x73, 0x75, 0x6c, 0x74, 0x53, 0x65, 0x74, + 0x22, 0x4b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x45, 0x3a, 0x01, 0x2a, 0x22, 0x40, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, - 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, - 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xeb, 0x01, 0x0a, 0x06, 0x43, 0x6f, - 0x6d, 0x6d, 0x69, 0x74, 0x12, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9b, 0x01, 0xda, 0x41, 0x20, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x2c, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xda, - 0x41, 0x28, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, - 0x5f, 0x75, 0x73, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x2c, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, - 0x3a, 0x01, 0x2a, 0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x72, 0x65, 0x61, 0x64, 0x12, 0xac, 0x01, + 0x0a, 0x0d, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x12, + 0x1e, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x23, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x61, 0x6c, 0x52, 0x65, 0x73, 0x75, 0x6c, + 0x74, 0x53, 0x65, 0x74, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x3a, 0x01, 0x2a, 0x22, + 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, + 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x73, 0x74, 0x72, + 0x65, 0x61, 0x6d, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x61, 0x64, 0x30, 0x01, 0x12, 0xc9, 0x01, 0x0a, + 0x10, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x2a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, + 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, + 0x31, 0x2e, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x69, 0xda, + 0x41, 0x0f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x51, 0x3a, 0x01, 0x2a, 0x22, 0x4c, 0x2f, 0x76, 0x31, 0x2f, + 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, + 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, + 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, + 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x62, 0x65, 0x67, 0x69, 0x6e, 0x54, 0x72, 0x61, + 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xeb, 0x01, 0x0a, 0x06, 0x43, 0x6f, 0x6d, + 0x6d, 0x69, 0x74, 0x12, 0x20, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, + 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x9b, 0x01, 0xda, 0x41, 0x20, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x5f, 0x69, 0x64, 0x2c, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0xda, 0x41, + 0x28, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x5f, + 0x75, 0x73, 0x65, 0x5f, 0x74, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2c, + 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x47, 0x3a, + 0x01, 0x2a, 0x22, 0x42, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, + 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, + 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0xb0, 0x01, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x6c, 0x62, + 0x61, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, + 0x68, 0xda, 0x41, 0x16, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x74, 0x72, 0x61, 0x6e, + 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x49, + 0x3a, 0x01, 0x2a, 0x22, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, - 0x3a, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x12, 0xb0, 0x01, 0x0a, 0x08, 0x52, 0x6f, 0x6c, 0x6c, - 0x62, 0x61, 0x63, 0x6b, 0x12, 0x22, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x52, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, - 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x22, 0x68, 0xda, 0x41, 0x16, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x2c, 0x74, 0x72, 0x61, - 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x49, 0x3a, 0x01, 0x2a, 0x22, 0x44, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, - 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, - 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, - 0x7d, 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0xb7, 0x01, 0x0a, 0x0e, 0x50, - 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x28, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, - 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, - 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x4f, 0x3a, 0x01, 0x2a, 0x22, 0x4a, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, - 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, - 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, - 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x51, - 0x75, 0x65, 0x72, 0x79, 0x12, 0xb4, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x3a, 0x72, 0x6f, 0x6c, 0x6c, 0x62, 0x61, 0x63, 0x6b, 0x12, 0xb7, 0x01, 0x0a, 0x0e, 0x50, 0x61, + 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x28, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, + 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, - 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x3a, 0x01, 0x2a, - 0x22, 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, - 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, - 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, - 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x70, 0x61, - 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x12, 0xc8, 0x01, 0x0a, 0x0a, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6b, 0xda, 0x41, 0x17, 0x73, 0x65, 0x73, 0x73, - 0x69, 0x6f, 0x6e, 0x2c, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x3a, 0x01, 0x2a, 0x22, 0x46, 0x2f, 0x76, - 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, - 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, - 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x62, 0x61, 0x74, 0x63, 0x68, 0x57, - 0x72, 0x69, 0x74, 0x65, 0x30, 0x01, 0x1a, 0x77, 0xca, 0x41, 0x16, 0x73, 0x70, 0x61, 0x6e, 0x6e, - 0x65, 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, - 0x6d, 0xd2, 0x41, 0x5b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, - 0x75, 0x74, 0x68, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, - 0x72, 0x6d, 0x2c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x67, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x55, 0x82, 0xd3, + 0xe4, 0x93, 0x02, 0x4f, 0x3a, 0x01, 0x2a, 0x22, 0x4a, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, + 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, + 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, + 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x70, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x12, 0xb4, 0x01, 0x0a, 0x0d, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, + 0x6e, 0x52, 0x65, 0x61, 0x64, 0x12, 0x27, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, + 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x24, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, + 0x76, 0x31, 0x2e, 0x50, 0x61, 0x72, 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x54, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4e, 0x3a, 0x01, 0x2a, 0x22, + 0x49, 0x2f, 0x76, 0x31, 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, + 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, + 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, + 0x2f, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x70, 0x61, 0x72, + 0x74, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x61, 0x64, 0x12, 0xc8, 0x01, 0x0a, 0x0a, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x12, 0x24, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, + 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x25, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x2e, 0x76, 0x31, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, 0x69, 0x74, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6b, 0xda, 0x41, 0x17, 0x73, 0x65, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x2c, 0x6d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x67, 0x72, 0x6f, 0x75, + 0x70, 0x73, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4b, 0x3a, 0x01, 0x2a, 0x22, 0x46, 0x2f, 0x76, 0x31, + 0x2f, 0x7b, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x3d, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, + 0x74, 0x73, 0x2f, 0x2a, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x2a, + 0x2f, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x2a, 0x7d, 0x3a, 0x62, 0x61, 0x74, 0x63, 0x68, 0x57, 0x72, + 0x69, 0x74, 0x65, 0x30, 0x01, 0x1a, 0x77, 0xca, 0x41, 0x16, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, + 0x72, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, + 0xd2, 0x41, 0x5b, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, - 0x74, 0x68, 0x2f, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x42, - 0x91, 0x02, 0xea, 0x41, 0x5f, 0x0a, 0x1f, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x44, 0x61, - 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x3c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, - 0x2f, 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x7d, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, - 0x6e, 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x7d, 0x2f, - 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x61, 0x74, 0x61, 0x62, - 0x61, 0x73, 0x65, 0x7d, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x70, 0x61, - 0x6e, 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x63, 0x6c, 0x6f, - 0x75, 0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, - 0x2f, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x76, 0x31, 0x2f, 0x73, - 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x70, 0x62, 0x3b, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, - 0x70, 0x62, 0xaa, 0x02, 0x17, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x43, 0x6c, 0x6f, 0x75, - 0x64, 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x17, 0x47, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x5c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x5c, 0x53, 0x70, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x5c, 0x56, 0x31, 0xea, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, - 0x3a, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x3a, 0x53, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x3a, - 0x3a, 0x56, 0x31, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x74, 0x68, 0x2f, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, + 0x6d, 0x2c, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3a, 0x2f, 0x2f, 0x77, 0x77, 0x77, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x75, 0x74, + 0x68, 0x2f, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x64, 0x61, 0x74, 0x61, 0x42, 0x91, + 0x02, 0xea, 0x41, 0x5f, 0x0a, 0x1f, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x61, 0x70, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x44, 0x61, 0x74, + 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x3c, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x73, 0x2f, + 0x7b, 0x70, 0x72, 0x6f, 0x6a, 0x65, 0x63, 0x74, 0x7d, 0x2f, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, + 0x63, 0x65, 0x73, 0x2f, 0x7b, 0x69, 0x6e, 0x73, 0x74, 0x61, 0x6e, 0x63, 0x65, 0x7d, 0x2f, 0x64, + 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x73, 0x2f, 0x7b, 0x64, 0x61, 0x74, 0x61, 0x62, 0x61, + 0x73, 0x65, 0x7d, 0x0a, 0x15, 0x63, 0x6f, 0x6d, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x76, 0x31, 0x42, 0x0c, 0x53, 0x70, 0x61, 0x6e, + 0x6e, 0x65, 0x72, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x35, 0x63, 0x6c, 0x6f, 0x75, + 0x64, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x6f, 0x2f, + 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x76, 0x31, 0x2f, 0x73, 0x70, + 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x70, 0x62, 0x3b, 0x73, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x70, + 0x62, 0xaa, 0x02, 0x17, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x43, 0x6c, 0x6f, 0x75, 0x64, + 0x2e, 0x53, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x17, 0x47, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x5c, 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x5c, 0x53, 0x70, 0x61, 0x6e, 0x6e, + 0x65, 0x72, 0x5c, 0x56, 0x31, 0xea, 0x02, 0x1a, 0x47, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x3a, 0x3a, + 0x43, 0x6c, 0x6f, 0x75, 0x64, 0x3a, 0x3a, 0x53, 0x70, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x3a, 0x3a, + 0x56, 0x31, 0x50, 0x00, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3557,153 +3749,157 @@ func file_google_spanner_v1_spanner_proto_rawDescGZIP() []byte { return file_google_spanner_v1_spanner_proto_rawDescData } -var file_google_spanner_v1_spanner_proto_enumTypes = make([]protoimpl.EnumInfo, 3) +var file_google_spanner_v1_spanner_proto_enumTypes = make([]protoimpl.EnumInfo, 5) var file_google_spanner_v1_spanner_proto_msgTypes = make([]protoimpl.MessageInfo, 34) -var file_google_spanner_v1_spanner_proto_goTypes = []interface{}{ +var file_google_spanner_v1_spanner_proto_goTypes = []any{ (RequestOptions_Priority)(0), // 0: google.spanner.v1.RequestOptions.Priority (DirectedReadOptions_ReplicaSelection_Type)(0), // 1: google.spanner.v1.DirectedReadOptions.ReplicaSelection.Type (ExecuteSqlRequest_QueryMode)(0), // 2: google.spanner.v1.ExecuteSqlRequest.QueryMode - (*CreateSessionRequest)(nil), // 3: google.spanner.v1.CreateSessionRequest - (*BatchCreateSessionsRequest)(nil), // 4: google.spanner.v1.BatchCreateSessionsRequest - (*BatchCreateSessionsResponse)(nil), // 5: google.spanner.v1.BatchCreateSessionsResponse - (*Session)(nil), // 6: google.spanner.v1.Session - (*GetSessionRequest)(nil), // 7: google.spanner.v1.GetSessionRequest - (*ListSessionsRequest)(nil), // 8: google.spanner.v1.ListSessionsRequest - (*ListSessionsResponse)(nil), // 9: google.spanner.v1.ListSessionsResponse - (*DeleteSessionRequest)(nil), // 10: google.spanner.v1.DeleteSessionRequest - (*RequestOptions)(nil), // 11: google.spanner.v1.RequestOptions - (*DirectedReadOptions)(nil), // 12: google.spanner.v1.DirectedReadOptions - (*ExecuteSqlRequest)(nil), // 13: google.spanner.v1.ExecuteSqlRequest - (*ExecuteBatchDmlRequest)(nil), // 14: google.spanner.v1.ExecuteBatchDmlRequest - (*ExecuteBatchDmlResponse)(nil), // 15: google.spanner.v1.ExecuteBatchDmlResponse - (*PartitionOptions)(nil), // 16: google.spanner.v1.PartitionOptions - (*PartitionQueryRequest)(nil), // 17: google.spanner.v1.PartitionQueryRequest - (*PartitionReadRequest)(nil), // 18: google.spanner.v1.PartitionReadRequest - (*Partition)(nil), // 19: google.spanner.v1.Partition - (*PartitionResponse)(nil), // 20: google.spanner.v1.PartitionResponse - (*ReadRequest)(nil), // 21: google.spanner.v1.ReadRequest - (*BeginTransactionRequest)(nil), // 22: google.spanner.v1.BeginTransactionRequest - (*CommitRequest)(nil), // 23: google.spanner.v1.CommitRequest - (*RollbackRequest)(nil), // 24: google.spanner.v1.RollbackRequest - (*BatchWriteRequest)(nil), // 25: google.spanner.v1.BatchWriteRequest - (*BatchWriteResponse)(nil), // 26: google.spanner.v1.BatchWriteResponse - nil, // 27: google.spanner.v1.Session.LabelsEntry - (*DirectedReadOptions_ReplicaSelection)(nil), // 28: google.spanner.v1.DirectedReadOptions.ReplicaSelection - (*DirectedReadOptions_IncludeReplicas)(nil), // 29: google.spanner.v1.DirectedReadOptions.IncludeReplicas - (*DirectedReadOptions_ExcludeReplicas)(nil), // 30: google.spanner.v1.DirectedReadOptions.ExcludeReplicas - (*ExecuteSqlRequest_QueryOptions)(nil), // 31: google.spanner.v1.ExecuteSqlRequest.QueryOptions - nil, // 32: google.spanner.v1.ExecuteSqlRequest.ParamTypesEntry - (*ExecuteBatchDmlRequest_Statement)(nil), // 33: google.spanner.v1.ExecuteBatchDmlRequest.Statement - nil, // 34: google.spanner.v1.ExecuteBatchDmlRequest.Statement.ParamTypesEntry - nil, // 35: google.spanner.v1.PartitionQueryRequest.ParamTypesEntry - (*BatchWriteRequest_MutationGroup)(nil), // 36: google.spanner.v1.BatchWriteRequest.MutationGroup - (*timestamppb.Timestamp)(nil), // 37: google.protobuf.Timestamp - (*TransactionSelector)(nil), // 38: google.spanner.v1.TransactionSelector - (*structpb.Struct)(nil), // 39: google.protobuf.Struct - (*ResultSet)(nil), // 40: google.spanner.v1.ResultSet - (*status.Status)(nil), // 41: google.rpc.Status - (*KeySet)(nil), // 42: google.spanner.v1.KeySet - (*Transaction)(nil), // 43: google.spanner.v1.Transaction - (*TransactionOptions)(nil), // 44: google.spanner.v1.TransactionOptions - (*Mutation)(nil), // 45: google.spanner.v1.Mutation - (*durationpb.Duration)(nil), // 46: google.protobuf.Duration - (*Type)(nil), // 47: google.spanner.v1.Type - (*emptypb.Empty)(nil), // 48: google.protobuf.Empty - (*PartialResultSet)(nil), // 49: google.spanner.v1.PartialResultSet - (*CommitResponse)(nil), // 50: google.spanner.v1.CommitResponse + (ReadRequest_OrderBy)(0), // 3: google.spanner.v1.ReadRequest.OrderBy + (ReadRequest_LockHint)(0), // 4: google.spanner.v1.ReadRequest.LockHint + (*CreateSessionRequest)(nil), // 5: google.spanner.v1.CreateSessionRequest + (*BatchCreateSessionsRequest)(nil), // 6: google.spanner.v1.BatchCreateSessionsRequest + (*BatchCreateSessionsResponse)(nil), // 7: google.spanner.v1.BatchCreateSessionsResponse + (*Session)(nil), // 8: google.spanner.v1.Session + (*GetSessionRequest)(nil), // 9: google.spanner.v1.GetSessionRequest + (*ListSessionsRequest)(nil), // 10: google.spanner.v1.ListSessionsRequest + (*ListSessionsResponse)(nil), // 11: google.spanner.v1.ListSessionsResponse + (*DeleteSessionRequest)(nil), // 12: google.spanner.v1.DeleteSessionRequest + (*RequestOptions)(nil), // 13: google.spanner.v1.RequestOptions + (*DirectedReadOptions)(nil), // 14: google.spanner.v1.DirectedReadOptions + (*ExecuteSqlRequest)(nil), // 15: google.spanner.v1.ExecuteSqlRequest + (*ExecuteBatchDmlRequest)(nil), // 16: google.spanner.v1.ExecuteBatchDmlRequest + (*ExecuteBatchDmlResponse)(nil), // 17: google.spanner.v1.ExecuteBatchDmlResponse + (*PartitionOptions)(nil), // 18: google.spanner.v1.PartitionOptions + (*PartitionQueryRequest)(nil), // 19: google.spanner.v1.PartitionQueryRequest + (*PartitionReadRequest)(nil), // 20: google.spanner.v1.PartitionReadRequest + (*Partition)(nil), // 21: google.spanner.v1.Partition + (*PartitionResponse)(nil), // 22: google.spanner.v1.PartitionResponse + (*ReadRequest)(nil), // 23: google.spanner.v1.ReadRequest + (*BeginTransactionRequest)(nil), // 24: google.spanner.v1.BeginTransactionRequest + (*CommitRequest)(nil), // 25: google.spanner.v1.CommitRequest + (*RollbackRequest)(nil), // 26: google.spanner.v1.RollbackRequest + (*BatchWriteRequest)(nil), // 27: google.spanner.v1.BatchWriteRequest + (*BatchWriteResponse)(nil), // 28: google.spanner.v1.BatchWriteResponse + nil, // 29: google.spanner.v1.Session.LabelsEntry + (*DirectedReadOptions_ReplicaSelection)(nil), // 30: google.spanner.v1.DirectedReadOptions.ReplicaSelection + (*DirectedReadOptions_IncludeReplicas)(nil), // 31: google.spanner.v1.DirectedReadOptions.IncludeReplicas + (*DirectedReadOptions_ExcludeReplicas)(nil), // 32: google.spanner.v1.DirectedReadOptions.ExcludeReplicas + (*ExecuteSqlRequest_QueryOptions)(nil), // 33: google.spanner.v1.ExecuteSqlRequest.QueryOptions + nil, // 34: google.spanner.v1.ExecuteSqlRequest.ParamTypesEntry + (*ExecuteBatchDmlRequest_Statement)(nil), // 35: google.spanner.v1.ExecuteBatchDmlRequest.Statement + nil, // 36: google.spanner.v1.ExecuteBatchDmlRequest.Statement.ParamTypesEntry + nil, // 37: google.spanner.v1.PartitionQueryRequest.ParamTypesEntry + (*BatchWriteRequest_MutationGroup)(nil), // 38: google.spanner.v1.BatchWriteRequest.MutationGroup + (*timestamppb.Timestamp)(nil), // 39: google.protobuf.Timestamp + (*TransactionSelector)(nil), // 40: google.spanner.v1.TransactionSelector + (*structpb.Struct)(nil), // 41: google.protobuf.Struct + (*ResultSet)(nil), // 42: google.spanner.v1.ResultSet + (*status.Status)(nil), // 43: google.rpc.Status + (*KeySet)(nil), // 44: google.spanner.v1.KeySet + (*Transaction)(nil), // 45: google.spanner.v1.Transaction + (*TransactionOptions)(nil), // 46: google.spanner.v1.TransactionOptions + (*Mutation)(nil), // 47: google.spanner.v1.Mutation + (*durationpb.Duration)(nil), // 48: google.protobuf.Duration + (*Type)(nil), // 49: google.spanner.v1.Type + (*emptypb.Empty)(nil), // 50: google.protobuf.Empty + (*PartialResultSet)(nil), // 51: google.spanner.v1.PartialResultSet + (*CommitResponse)(nil), // 52: google.spanner.v1.CommitResponse } var file_google_spanner_v1_spanner_proto_depIdxs = []int32{ - 6, // 0: google.spanner.v1.CreateSessionRequest.session:type_name -> google.spanner.v1.Session - 6, // 1: google.spanner.v1.BatchCreateSessionsRequest.session_template:type_name -> google.spanner.v1.Session - 6, // 2: google.spanner.v1.BatchCreateSessionsResponse.session:type_name -> google.spanner.v1.Session - 27, // 3: google.spanner.v1.Session.labels:type_name -> google.spanner.v1.Session.LabelsEntry - 37, // 4: google.spanner.v1.Session.create_time:type_name -> google.protobuf.Timestamp - 37, // 5: google.spanner.v1.Session.approximate_last_use_time:type_name -> google.protobuf.Timestamp - 6, // 6: google.spanner.v1.ListSessionsResponse.sessions:type_name -> google.spanner.v1.Session + 8, // 0: google.spanner.v1.CreateSessionRequest.session:type_name -> google.spanner.v1.Session + 8, // 1: google.spanner.v1.BatchCreateSessionsRequest.session_template:type_name -> google.spanner.v1.Session + 8, // 2: google.spanner.v1.BatchCreateSessionsResponse.session:type_name -> google.spanner.v1.Session + 29, // 3: google.spanner.v1.Session.labels:type_name -> google.spanner.v1.Session.LabelsEntry + 39, // 4: google.spanner.v1.Session.create_time:type_name -> google.protobuf.Timestamp + 39, // 5: google.spanner.v1.Session.approximate_last_use_time:type_name -> google.protobuf.Timestamp + 8, // 6: google.spanner.v1.ListSessionsResponse.sessions:type_name -> google.spanner.v1.Session 0, // 7: google.spanner.v1.RequestOptions.priority:type_name -> google.spanner.v1.RequestOptions.Priority - 29, // 8: google.spanner.v1.DirectedReadOptions.include_replicas:type_name -> google.spanner.v1.DirectedReadOptions.IncludeReplicas - 30, // 9: google.spanner.v1.DirectedReadOptions.exclude_replicas:type_name -> google.spanner.v1.DirectedReadOptions.ExcludeReplicas - 38, // 10: google.spanner.v1.ExecuteSqlRequest.transaction:type_name -> google.spanner.v1.TransactionSelector - 39, // 11: google.spanner.v1.ExecuteSqlRequest.params:type_name -> google.protobuf.Struct - 32, // 12: google.spanner.v1.ExecuteSqlRequest.param_types:type_name -> google.spanner.v1.ExecuteSqlRequest.ParamTypesEntry + 31, // 8: google.spanner.v1.DirectedReadOptions.include_replicas:type_name -> google.spanner.v1.DirectedReadOptions.IncludeReplicas + 32, // 9: google.spanner.v1.DirectedReadOptions.exclude_replicas:type_name -> google.spanner.v1.DirectedReadOptions.ExcludeReplicas + 40, // 10: google.spanner.v1.ExecuteSqlRequest.transaction:type_name -> google.spanner.v1.TransactionSelector + 41, // 11: google.spanner.v1.ExecuteSqlRequest.params:type_name -> google.protobuf.Struct + 34, // 12: google.spanner.v1.ExecuteSqlRequest.param_types:type_name -> google.spanner.v1.ExecuteSqlRequest.ParamTypesEntry 2, // 13: google.spanner.v1.ExecuteSqlRequest.query_mode:type_name -> google.spanner.v1.ExecuteSqlRequest.QueryMode - 31, // 14: google.spanner.v1.ExecuteSqlRequest.query_options:type_name -> google.spanner.v1.ExecuteSqlRequest.QueryOptions - 11, // 15: google.spanner.v1.ExecuteSqlRequest.request_options:type_name -> google.spanner.v1.RequestOptions - 12, // 16: google.spanner.v1.ExecuteSqlRequest.directed_read_options:type_name -> google.spanner.v1.DirectedReadOptions - 38, // 17: google.spanner.v1.ExecuteBatchDmlRequest.transaction:type_name -> google.spanner.v1.TransactionSelector - 33, // 18: google.spanner.v1.ExecuteBatchDmlRequest.statements:type_name -> google.spanner.v1.ExecuteBatchDmlRequest.Statement - 11, // 19: google.spanner.v1.ExecuteBatchDmlRequest.request_options:type_name -> google.spanner.v1.RequestOptions - 40, // 20: google.spanner.v1.ExecuteBatchDmlResponse.result_sets:type_name -> google.spanner.v1.ResultSet - 41, // 21: google.spanner.v1.ExecuteBatchDmlResponse.status:type_name -> google.rpc.Status - 38, // 22: google.spanner.v1.PartitionQueryRequest.transaction:type_name -> google.spanner.v1.TransactionSelector - 39, // 23: google.spanner.v1.PartitionQueryRequest.params:type_name -> google.protobuf.Struct - 35, // 24: google.spanner.v1.PartitionQueryRequest.param_types:type_name -> google.spanner.v1.PartitionQueryRequest.ParamTypesEntry - 16, // 25: google.spanner.v1.PartitionQueryRequest.partition_options:type_name -> google.spanner.v1.PartitionOptions - 38, // 26: google.spanner.v1.PartitionReadRequest.transaction:type_name -> google.spanner.v1.TransactionSelector - 42, // 27: google.spanner.v1.PartitionReadRequest.key_set:type_name -> google.spanner.v1.KeySet - 16, // 28: google.spanner.v1.PartitionReadRequest.partition_options:type_name -> google.spanner.v1.PartitionOptions - 19, // 29: google.spanner.v1.PartitionResponse.partitions:type_name -> google.spanner.v1.Partition - 43, // 30: google.spanner.v1.PartitionResponse.transaction:type_name -> google.spanner.v1.Transaction - 38, // 31: google.spanner.v1.ReadRequest.transaction:type_name -> google.spanner.v1.TransactionSelector - 42, // 32: google.spanner.v1.ReadRequest.key_set:type_name -> google.spanner.v1.KeySet - 11, // 33: google.spanner.v1.ReadRequest.request_options:type_name -> google.spanner.v1.RequestOptions - 12, // 34: google.spanner.v1.ReadRequest.directed_read_options:type_name -> google.spanner.v1.DirectedReadOptions - 44, // 35: google.spanner.v1.BeginTransactionRequest.options:type_name -> google.spanner.v1.TransactionOptions - 11, // 36: google.spanner.v1.BeginTransactionRequest.request_options:type_name -> google.spanner.v1.RequestOptions - 44, // 37: google.spanner.v1.CommitRequest.single_use_transaction:type_name -> google.spanner.v1.TransactionOptions - 45, // 38: google.spanner.v1.CommitRequest.mutations:type_name -> google.spanner.v1.Mutation - 46, // 39: google.spanner.v1.CommitRequest.max_commit_delay:type_name -> google.protobuf.Duration - 11, // 40: google.spanner.v1.CommitRequest.request_options:type_name -> google.spanner.v1.RequestOptions - 11, // 41: google.spanner.v1.BatchWriteRequest.request_options:type_name -> google.spanner.v1.RequestOptions - 36, // 42: google.spanner.v1.BatchWriteRequest.mutation_groups:type_name -> google.spanner.v1.BatchWriteRequest.MutationGroup - 41, // 43: google.spanner.v1.BatchWriteResponse.status:type_name -> google.rpc.Status - 37, // 44: google.spanner.v1.BatchWriteResponse.commit_timestamp:type_name -> google.protobuf.Timestamp - 1, // 45: google.spanner.v1.DirectedReadOptions.ReplicaSelection.type:type_name -> google.spanner.v1.DirectedReadOptions.ReplicaSelection.Type - 28, // 46: google.spanner.v1.DirectedReadOptions.IncludeReplicas.replica_selections:type_name -> google.spanner.v1.DirectedReadOptions.ReplicaSelection - 28, // 47: google.spanner.v1.DirectedReadOptions.ExcludeReplicas.replica_selections:type_name -> google.spanner.v1.DirectedReadOptions.ReplicaSelection - 47, // 48: google.spanner.v1.ExecuteSqlRequest.ParamTypesEntry.value:type_name -> google.spanner.v1.Type - 39, // 49: google.spanner.v1.ExecuteBatchDmlRequest.Statement.params:type_name -> google.protobuf.Struct - 34, // 50: google.spanner.v1.ExecuteBatchDmlRequest.Statement.param_types:type_name -> google.spanner.v1.ExecuteBatchDmlRequest.Statement.ParamTypesEntry - 47, // 51: google.spanner.v1.ExecuteBatchDmlRequest.Statement.ParamTypesEntry.value:type_name -> google.spanner.v1.Type - 47, // 52: google.spanner.v1.PartitionQueryRequest.ParamTypesEntry.value:type_name -> google.spanner.v1.Type - 45, // 53: google.spanner.v1.BatchWriteRequest.MutationGroup.mutations:type_name -> google.spanner.v1.Mutation - 3, // 54: google.spanner.v1.Spanner.CreateSession:input_type -> google.spanner.v1.CreateSessionRequest - 4, // 55: google.spanner.v1.Spanner.BatchCreateSessions:input_type -> google.spanner.v1.BatchCreateSessionsRequest - 7, // 56: google.spanner.v1.Spanner.GetSession:input_type -> google.spanner.v1.GetSessionRequest - 8, // 57: google.spanner.v1.Spanner.ListSessions:input_type -> google.spanner.v1.ListSessionsRequest - 10, // 58: google.spanner.v1.Spanner.DeleteSession:input_type -> google.spanner.v1.DeleteSessionRequest - 13, // 59: google.spanner.v1.Spanner.ExecuteSql:input_type -> google.spanner.v1.ExecuteSqlRequest - 13, // 60: google.spanner.v1.Spanner.ExecuteStreamingSql:input_type -> google.spanner.v1.ExecuteSqlRequest - 14, // 61: google.spanner.v1.Spanner.ExecuteBatchDml:input_type -> google.spanner.v1.ExecuteBatchDmlRequest - 21, // 62: google.spanner.v1.Spanner.Read:input_type -> google.spanner.v1.ReadRequest - 21, // 63: google.spanner.v1.Spanner.StreamingRead:input_type -> google.spanner.v1.ReadRequest - 22, // 64: google.spanner.v1.Spanner.BeginTransaction:input_type -> google.spanner.v1.BeginTransactionRequest - 23, // 65: google.spanner.v1.Spanner.Commit:input_type -> google.spanner.v1.CommitRequest - 24, // 66: google.spanner.v1.Spanner.Rollback:input_type -> google.spanner.v1.RollbackRequest - 17, // 67: google.spanner.v1.Spanner.PartitionQuery:input_type -> google.spanner.v1.PartitionQueryRequest - 18, // 68: google.spanner.v1.Spanner.PartitionRead:input_type -> google.spanner.v1.PartitionReadRequest - 25, // 69: google.spanner.v1.Spanner.BatchWrite:input_type -> google.spanner.v1.BatchWriteRequest - 6, // 70: google.spanner.v1.Spanner.CreateSession:output_type -> google.spanner.v1.Session - 5, // 71: google.spanner.v1.Spanner.BatchCreateSessions:output_type -> google.spanner.v1.BatchCreateSessionsResponse - 6, // 72: google.spanner.v1.Spanner.GetSession:output_type -> google.spanner.v1.Session - 9, // 73: google.spanner.v1.Spanner.ListSessions:output_type -> google.spanner.v1.ListSessionsResponse - 48, // 74: google.spanner.v1.Spanner.DeleteSession:output_type -> google.protobuf.Empty - 40, // 75: google.spanner.v1.Spanner.ExecuteSql:output_type -> google.spanner.v1.ResultSet - 49, // 76: google.spanner.v1.Spanner.ExecuteStreamingSql:output_type -> google.spanner.v1.PartialResultSet - 15, // 77: google.spanner.v1.Spanner.ExecuteBatchDml:output_type -> google.spanner.v1.ExecuteBatchDmlResponse - 40, // 78: google.spanner.v1.Spanner.Read:output_type -> google.spanner.v1.ResultSet - 49, // 79: google.spanner.v1.Spanner.StreamingRead:output_type -> google.spanner.v1.PartialResultSet - 43, // 80: google.spanner.v1.Spanner.BeginTransaction:output_type -> google.spanner.v1.Transaction - 50, // 81: google.spanner.v1.Spanner.Commit:output_type -> google.spanner.v1.CommitResponse - 48, // 82: google.spanner.v1.Spanner.Rollback:output_type -> google.protobuf.Empty - 20, // 83: google.spanner.v1.Spanner.PartitionQuery:output_type -> google.spanner.v1.PartitionResponse - 20, // 84: google.spanner.v1.Spanner.PartitionRead:output_type -> google.spanner.v1.PartitionResponse - 26, // 85: google.spanner.v1.Spanner.BatchWrite:output_type -> google.spanner.v1.BatchWriteResponse - 70, // [70:86] is the sub-list for method output_type - 54, // [54:70] is the sub-list for method input_type - 54, // [54:54] is the sub-list for extension type_name - 54, // [54:54] is the sub-list for extension extendee - 0, // [0:54] is the sub-list for field type_name + 33, // 14: google.spanner.v1.ExecuteSqlRequest.query_options:type_name -> google.spanner.v1.ExecuteSqlRequest.QueryOptions + 13, // 15: google.spanner.v1.ExecuteSqlRequest.request_options:type_name -> google.spanner.v1.RequestOptions + 14, // 16: google.spanner.v1.ExecuteSqlRequest.directed_read_options:type_name -> google.spanner.v1.DirectedReadOptions + 40, // 17: google.spanner.v1.ExecuteBatchDmlRequest.transaction:type_name -> google.spanner.v1.TransactionSelector + 35, // 18: google.spanner.v1.ExecuteBatchDmlRequest.statements:type_name -> google.spanner.v1.ExecuteBatchDmlRequest.Statement + 13, // 19: google.spanner.v1.ExecuteBatchDmlRequest.request_options:type_name -> google.spanner.v1.RequestOptions + 42, // 20: google.spanner.v1.ExecuteBatchDmlResponse.result_sets:type_name -> google.spanner.v1.ResultSet + 43, // 21: google.spanner.v1.ExecuteBatchDmlResponse.status:type_name -> google.rpc.Status + 40, // 22: google.spanner.v1.PartitionQueryRequest.transaction:type_name -> google.spanner.v1.TransactionSelector + 41, // 23: google.spanner.v1.PartitionQueryRequest.params:type_name -> google.protobuf.Struct + 37, // 24: google.spanner.v1.PartitionQueryRequest.param_types:type_name -> google.spanner.v1.PartitionQueryRequest.ParamTypesEntry + 18, // 25: google.spanner.v1.PartitionQueryRequest.partition_options:type_name -> google.spanner.v1.PartitionOptions + 40, // 26: google.spanner.v1.PartitionReadRequest.transaction:type_name -> google.spanner.v1.TransactionSelector + 44, // 27: google.spanner.v1.PartitionReadRequest.key_set:type_name -> google.spanner.v1.KeySet + 18, // 28: google.spanner.v1.PartitionReadRequest.partition_options:type_name -> google.spanner.v1.PartitionOptions + 21, // 29: google.spanner.v1.PartitionResponse.partitions:type_name -> google.spanner.v1.Partition + 45, // 30: google.spanner.v1.PartitionResponse.transaction:type_name -> google.spanner.v1.Transaction + 40, // 31: google.spanner.v1.ReadRequest.transaction:type_name -> google.spanner.v1.TransactionSelector + 44, // 32: google.spanner.v1.ReadRequest.key_set:type_name -> google.spanner.v1.KeySet + 13, // 33: google.spanner.v1.ReadRequest.request_options:type_name -> google.spanner.v1.RequestOptions + 14, // 34: google.spanner.v1.ReadRequest.directed_read_options:type_name -> google.spanner.v1.DirectedReadOptions + 3, // 35: google.spanner.v1.ReadRequest.order_by:type_name -> google.spanner.v1.ReadRequest.OrderBy + 4, // 36: google.spanner.v1.ReadRequest.lock_hint:type_name -> google.spanner.v1.ReadRequest.LockHint + 46, // 37: google.spanner.v1.BeginTransactionRequest.options:type_name -> google.spanner.v1.TransactionOptions + 13, // 38: google.spanner.v1.BeginTransactionRequest.request_options:type_name -> google.spanner.v1.RequestOptions + 46, // 39: google.spanner.v1.CommitRequest.single_use_transaction:type_name -> google.spanner.v1.TransactionOptions + 47, // 40: google.spanner.v1.CommitRequest.mutations:type_name -> google.spanner.v1.Mutation + 48, // 41: google.spanner.v1.CommitRequest.max_commit_delay:type_name -> google.protobuf.Duration + 13, // 42: google.spanner.v1.CommitRequest.request_options:type_name -> google.spanner.v1.RequestOptions + 13, // 43: google.spanner.v1.BatchWriteRequest.request_options:type_name -> google.spanner.v1.RequestOptions + 38, // 44: google.spanner.v1.BatchWriteRequest.mutation_groups:type_name -> google.spanner.v1.BatchWriteRequest.MutationGroup + 43, // 45: google.spanner.v1.BatchWriteResponse.status:type_name -> google.rpc.Status + 39, // 46: google.spanner.v1.BatchWriteResponse.commit_timestamp:type_name -> google.protobuf.Timestamp + 1, // 47: google.spanner.v1.DirectedReadOptions.ReplicaSelection.type:type_name -> google.spanner.v1.DirectedReadOptions.ReplicaSelection.Type + 30, // 48: google.spanner.v1.DirectedReadOptions.IncludeReplicas.replica_selections:type_name -> google.spanner.v1.DirectedReadOptions.ReplicaSelection + 30, // 49: google.spanner.v1.DirectedReadOptions.ExcludeReplicas.replica_selections:type_name -> google.spanner.v1.DirectedReadOptions.ReplicaSelection + 49, // 50: google.spanner.v1.ExecuteSqlRequest.ParamTypesEntry.value:type_name -> google.spanner.v1.Type + 41, // 51: google.spanner.v1.ExecuteBatchDmlRequest.Statement.params:type_name -> google.protobuf.Struct + 36, // 52: google.spanner.v1.ExecuteBatchDmlRequest.Statement.param_types:type_name -> google.spanner.v1.ExecuteBatchDmlRequest.Statement.ParamTypesEntry + 49, // 53: google.spanner.v1.ExecuteBatchDmlRequest.Statement.ParamTypesEntry.value:type_name -> google.spanner.v1.Type + 49, // 54: google.spanner.v1.PartitionQueryRequest.ParamTypesEntry.value:type_name -> google.spanner.v1.Type + 47, // 55: google.spanner.v1.BatchWriteRequest.MutationGroup.mutations:type_name -> google.spanner.v1.Mutation + 5, // 56: google.spanner.v1.Spanner.CreateSession:input_type -> google.spanner.v1.CreateSessionRequest + 6, // 57: google.spanner.v1.Spanner.BatchCreateSessions:input_type -> google.spanner.v1.BatchCreateSessionsRequest + 9, // 58: google.spanner.v1.Spanner.GetSession:input_type -> google.spanner.v1.GetSessionRequest + 10, // 59: google.spanner.v1.Spanner.ListSessions:input_type -> google.spanner.v1.ListSessionsRequest + 12, // 60: google.spanner.v1.Spanner.DeleteSession:input_type -> google.spanner.v1.DeleteSessionRequest + 15, // 61: google.spanner.v1.Spanner.ExecuteSql:input_type -> google.spanner.v1.ExecuteSqlRequest + 15, // 62: google.spanner.v1.Spanner.ExecuteStreamingSql:input_type -> google.spanner.v1.ExecuteSqlRequest + 16, // 63: google.spanner.v1.Spanner.ExecuteBatchDml:input_type -> google.spanner.v1.ExecuteBatchDmlRequest + 23, // 64: google.spanner.v1.Spanner.Read:input_type -> google.spanner.v1.ReadRequest + 23, // 65: google.spanner.v1.Spanner.StreamingRead:input_type -> google.spanner.v1.ReadRequest + 24, // 66: google.spanner.v1.Spanner.BeginTransaction:input_type -> google.spanner.v1.BeginTransactionRequest + 25, // 67: google.spanner.v1.Spanner.Commit:input_type -> google.spanner.v1.CommitRequest + 26, // 68: google.spanner.v1.Spanner.Rollback:input_type -> google.spanner.v1.RollbackRequest + 19, // 69: google.spanner.v1.Spanner.PartitionQuery:input_type -> google.spanner.v1.PartitionQueryRequest + 20, // 70: google.spanner.v1.Spanner.PartitionRead:input_type -> google.spanner.v1.PartitionReadRequest + 27, // 71: google.spanner.v1.Spanner.BatchWrite:input_type -> google.spanner.v1.BatchWriteRequest + 8, // 72: google.spanner.v1.Spanner.CreateSession:output_type -> google.spanner.v1.Session + 7, // 73: google.spanner.v1.Spanner.BatchCreateSessions:output_type -> google.spanner.v1.BatchCreateSessionsResponse + 8, // 74: google.spanner.v1.Spanner.GetSession:output_type -> google.spanner.v1.Session + 11, // 75: google.spanner.v1.Spanner.ListSessions:output_type -> google.spanner.v1.ListSessionsResponse + 50, // 76: google.spanner.v1.Spanner.DeleteSession:output_type -> google.protobuf.Empty + 42, // 77: google.spanner.v1.Spanner.ExecuteSql:output_type -> google.spanner.v1.ResultSet + 51, // 78: google.spanner.v1.Spanner.ExecuteStreamingSql:output_type -> google.spanner.v1.PartialResultSet + 17, // 79: google.spanner.v1.Spanner.ExecuteBatchDml:output_type -> google.spanner.v1.ExecuteBatchDmlResponse + 42, // 80: google.spanner.v1.Spanner.Read:output_type -> google.spanner.v1.ResultSet + 51, // 81: google.spanner.v1.Spanner.StreamingRead:output_type -> google.spanner.v1.PartialResultSet + 45, // 82: google.spanner.v1.Spanner.BeginTransaction:output_type -> google.spanner.v1.Transaction + 52, // 83: google.spanner.v1.Spanner.Commit:output_type -> google.spanner.v1.CommitResponse + 50, // 84: google.spanner.v1.Spanner.Rollback:output_type -> google.protobuf.Empty + 22, // 85: google.spanner.v1.Spanner.PartitionQuery:output_type -> google.spanner.v1.PartitionResponse + 22, // 86: google.spanner.v1.Spanner.PartitionRead:output_type -> google.spanner.v1.PartitionResponse + 28, // 87: google.spanner.v1.Spanner.BatchWrite:output_type -> google.spanner.v1.BatchWriteResponse + 72, // [72:88] is the sub-list for method output_type + 56, // [56:72] is the sub-list for method input_type + 56, // [56:56] is the sub-list for extension type_name + 56, // [56:56] is the sub-list for extension extendee + 0, // [0:56] is the sub-list for field type_name } func init() { file_google_spanner_v1_spanner_proto_init() } @@ -3718,7 +3914,7 @@ func file_google_spanner_v1_spanner_proto_init() { file_google_spanner_v1_transaction_proto_init() file_google_spanner_v1_type_proto_init() if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_spanner_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*CreateSessionRequest); i { case 0: return &v.state @@ -3730,7 +3926,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*BatchCreateSessionsRequest); i { case 0: return &v.state @@ -3742,7 +3938,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*BatchCreateSessionsResponse); i { case 0: return &v.state @@ -3754,7 +3950,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*Session); i { case 0: return &v.state @@ -3766,7 +3962,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*GetSessionRequest); i { case 0: return &v.state @@ -3778,7 +3974,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*ListSessionsRequest); i { case 0: return &v.state @@ -3790,7 +3986,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[6].Exporter = func(v any, i int) any { switch v := v.(*ListSessionsResponse); i { case 0: return &v.state @@ -3802,7 +3998,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[7].Exporter = func(v any, i int) any { switch v := v.(*DeleteSessionRequest); i { case 0: return &v.state @@ -3814,7 +4010,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[8].Exporter = func(v any, i int) any { switch v := v.(*RequestOptions); i { case 0: return &v.state @@ -3826,7 +4022,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[9].Exporter = func(v any, i int) any { switch v := v.(*DirectedReadOptions); i { case 0: return &v.state @@ -3838,7 +4034,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[10].Exporter = func(v any, i int) any { switch v := v.(*ExecuteSqlRequest); i { case 0: return &v.state @@ -3850,7 +4046,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[11].Exporter = func(v any, i int) any { switch v := v.(*ExecuteBatchDmlRequest); i { case 0: return &v.state @@ -3862,7 +4058,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[12].Exporter = func(v any, i int) any { switch v := v.(*ExecuteBatchDmlResponse); i { case 0: return &v.state @@ -3874,7 +4070,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[13].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[13].Exporter = func(v any, i int) any { switch v := v.(*PartitionOptions); i { case 0: return &v.state @@ -3886,7 +4082,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[14].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[14].Exporter = func(v any, i int) any { switch v := v.(*PartitionQueryRequest); i { case 0: return &v.state @@ -3898,7 +4094,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[15].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[15].Exporter = func(v any, i int) any { switch v := v.(*PartitionReadRequest); i { case 0: return &v.state @@ -3910,7 +4106,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[16].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[16].Exporter = func(v any, i int) any { switch v := v.(*Partition); i { case 0: return &v.state @@ -3922,7 +4118,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[17].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[17].Exporter = func(v any, i int) any { switch v := v.(*PartitionResponse); i { case 0: return &v.state @@ -3934,7 +4130,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[18].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[18].Exporter = func(v any, i int) any { switch v := v.(*ReadRequest); i { case 0: return &v.state @@ -3946,7 +4142,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[19].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[19].Exporter = func(v any, i int) any { switch v := v.(*BeginTransactionRequest); i { case 0: return &v.state @@ -3958,7 +4154,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[20].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[20].Exporter = func(v any, i int) any { switch v := v.(*CommitRequest); i { case 0: return &v.state @@ -3970,7 +4166,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[21].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[21].Exporter = func(v any, i int) any { switch v := v.(*RollbackRequest); i { case 0: return &v.state @@ -3982,7 +4178,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[22].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[22].Exporter = func(v any, i int) any { switch v := v.(*BatchWriteRequest); i { case 0: return &v.state @@ -3994,7 +4190,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[23].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[23].Exporter = func(v any, i int) any { switch v := v.(*BatchWriteResponse); i { case 0: return &v.state @@ -4006,7 +4202,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[25].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[25].Exporter = func(v any, i int) any { switch v := v.(*DirectedReadOptions_ReplicaSelection); i { case 0: return &v.state @@ -4018,7 +4214,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[26].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[26].Exporter = func(v any, i int) any { switch v := v.(*DirectedReadOptions_IncludeReplicas); i { case 0: return &v.state @@ -4030,7 +4226,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[27].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[27].Exporter = func(v any, i int) any { switch v := v.(*DirectedReadOptions_ExcludeReplicas); i { case 0: return &v.state @@ -4042,7 +4238,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[28].Exporter = func(v any, i int) any { switch v := v.(*ExecuteSqlRequest_QueryOptions); i { case 0: return &v.state @@ -4054,7 +4250,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[30].Exporter = func(v any, i int) any { switch v := v.(*ExecuteBatchDmlRequest_Statement); i { case 0: return &v.state @@ -4066,7 +4262,7 @@ func file_google_spanner_v1_spanner_proto_init() { return nil } } - file_google_spanner_v1_spanner_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_spanner_proto_msgTypes[33].Exporter = func(v any, i int) any { switch v := v.(*BatchWriteRequest_MutationGroup); i { case 0: return &v.state @@ -4079,11 +4275,11 @@ func file_google_spanner_v1_spanner_proto_init() { } } } - file_google_spanner_v1_spanner_proto_msgTypes[9].OneofWrappers = []interface{}{ + file_google_spanner_v1_spanner_proto_msgTypes[9].OneofWrappers = []any{ (*DirectedReadOptions_IncludeReplicas_)(nil), (*DirectedReadOptions_ExcludeReplicas_)(nil), } - file_google_spanner_v1_spanner_proto_msgTypes[20].OneofWrappers = []interface{}{ + file_google_spanner_v1_spanner_proto_msgTypes[20].OneofWrappers = []any{ (*CommitRequest_TransactionId)(nil), (*CommitRequest_SingleUseTransaction)(nil), } @@ -4092,7 +4288,7 @@ func file_google_spanner_v1_spanner_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_google_spanner_v1_spanner_proto_rawDesc, - NumEnums: 3, + NumEnums: 5, NumMessages: 34, NumExtensions: 0, NumServices: 1, diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/transaction.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/transaction.pb.go index 507bb4214..829120c1c 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/transaction.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/transaction.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/transaction.proto package spannerpb @@ -1130,7 +1130,7 @@ func file_google_spanner_v1_transaction_proto_rawDescGZIP() []byte { var file_google_spanner_v1_transaction_proto_enumTypes = make([]protoimpl.EnumInfo, 1) var file_google_spanner_v1_transaction_proto_msgTypes = make([]protoimpl.MessageInfo, 6) -var file_google_spanner_v1_transaction_proto_goTypes = []interface{}{ +var file_google_spanner_v1_transaction_proto_goTypes = []any{ (TransactionOptions_ReadWrite_ReadLockMode)(0), // 0: google.spanner.v1.TransactionOptions.ReadWrite.ReadLockMode (*TransactionOptions)(nil), // 1: google.spanner.v1.TransactionOptions (*Transaction)(nil), // 2: google.spanner.v1.Transaction @@ -1166,7 +1166,7 @@ func file_google_spanner_v1_transaction_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_transaction_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_transaction_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*TransactionOptions); i { case 0: return &v.state @@ -1178,7 +1178,7 @@ func file_google_spanner_v1_transaction_proto_init() { return nil } } - file_google_spanner_v1_transaction_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_transaction_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*Transaction); i { case 0: return &v.state @@ -1190,7 +1190,7 @@ func file_google_spanner_v1_transaction_proto_init() { return nil } } - file_google_spanner_v1_transaction_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_transaction_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*TransactionSelector); i { case 0: return &v.state @@ -1202,7 +1202,7 @@ func file_google_spanner_v1_transaction_proto_init() { return nil } } - file_google_spanner_v1_transaction_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_transaction_proto_msgTypes[3].Exporter = func(v any, i int) any { switch v := v.(*TransactionOptions_ReadWrite); i { case 0: return &v.state @@ -1214,7 +1214,7 @@ func file_google_spanner_v1_transaction_proto_init() { return nil } } - file_google_spanner_v1_transaction_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_transaction_proto_msgTypes[4].Exporter = func(v any, i int) any { switch v := v.(*TransactionOptions_PartitionedDml); i { case 0: return &v.state @@ -1226,7 +1226,7 @@ func file_google_spanner_v1_transaction_proto_init() { return nil } } - file_google_spanner_v1_transaction_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_transaction_proto_msgTypes[5].Exporter = func(v any, i int) any { switch v := v.(*TransactionOptions_ReadOnly); i { case 0: return &v.state @@ -1239,17 +1239,17 @@ func file_google_spanner_v1_transaction_proto_init() { } } } - file_google_spanner_v1_transaction_proto_msgTypes[0].OneofWrappers = []interface{}{ + file_google_spanner_v1_transaction_proto_msgTypes[0].OneofWrappers = []any{ (*TransactionOptions_ReadWrite_)(nil), (*TransactionOptions_PartitionedDml_)(nil), (*TransactionOptions_ReadOnly_)(nil), } - file_google_spanner_v1_transaction_proto_msgTypes[2].OneofWrappers = []interface{}{ + file_google_spanner_v1_transaction_proto_msgTypes[2].OneofWrappers = []any{ (*TransactionSelector_SingleUse)(nil), (*TransactionSelector_Id)(nil), (*TransactionSelector_Begin)(nil), } - file_google_spanner_v1_transaction_proto_msgTypes[5].OneofWrappers = []interface{}{ + file_google_spanner_v1_transaction_proto_msgTypes[5].OneofWrappers = []any{ (*TransactionOptions_ReadOnly_Strong)(nil), (*TransactionOptions_ReadOnly_MinReadTimestamp)(nil), (*TransactionOptions_ReadOnly_MaxStaleness)(nil), diff --git a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/type.pb.go b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/type.pb.go index a3780def8..0c30a4f54 100644 --- a/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/type.pb.go +++ b/vendor/cloud.google.com/go/spanner/apiv1/spannerpb/type.pb.go @@ -1,4 +1,4 @@ -// Copyright 2023 Google LLC +// Copyright 2024 Google LLC // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. @@ -14,8 +14,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.32.0 -// protoc v4.25.2 +// protoc-gen-go v1.34.2 +// protoc v4.25.3 // source: google/spanner/v1/type.proto package spannerpb @@ -544,7 +544,7 @@ func file_google_spanner_v1_type_proto_rawDescGZIP() []byte { var file_google_spanner_v1_type_proto_enumTypes = make([]protoimpl.EnumInfo, 2) var file_google_spanner_v1_type_proto_msgTypes = make([]protoimpl.MessageInfo, 3) -var file_google_spanner_v1_type_proto_goTypes = []interface{}{ +var file_google_spanner_v1_type_proto_goTypes = []any{ (TypeCode)(0), // 0: google.spanner.v1.TypeCode (TypeAnnotationCode)(0), // 1: google.spanner.v1.TypeAnnotationCode (*Type)(nil), // 2: google.spanner.v1.Type @@ -571,7 +571,7 @@ func file_google_spanner_v1_type_proto_init() { return } if !protoimpl.UnsafeEnabled { - file_google_spanner_v1_type_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_type_proto_msgTypes[0].Exporter = func(v any, i int) any { switch v := v.(*Type); i { case 0: return &v.state @@ -583,7 +583,7 @@ func file_google_spanner_v1_type_proto_init() { return nil } } - file_google_spanner_v1_type_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_type_proto_msgTypes[1].Exporter = func(v any, i int) any { switch v := v.(*StructType); i { case 0: return &v.state @@ -595,7 +595,7 @@ func file_google_spanner_v1_type_proto_init() { return nil } } - file_google_spanner_v1_type_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + file_google_spanner_v1_type_proto_msgTypes[2].Exporter = func(v any, i int) any { switch v := v.(*StructType_Field); i { case 0: return &v.state diff --git a/vendor/cloud.google.com/go/spanner/batch.go b/vendor/cloud.google.com/go/spanner/batch.go index 2046ba1ba..5c20f66fb 100644 --- a/vendor/cloud.google.com/go/spanner/batch.go +++ b/vendor/cloud.google.com/go/spanner/batch.go @@ -25,10 +25,10 @@ import ( "cloud.google.com/go/internal/trace" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - "github.com/golang/protobuf/proto" "github.com/googleapis/gax-go/v2" "google.golang.org/grpc" "google.golang.org/grpc/metadata" + "google.golang.org/protobuf/proto" ) // BatchReadOnlyTransaction is a ReadOnlyTransaction that allows for exporting diff --git a/vendor/cloud.google.com/go/spanner/client.go b/vendor/cloud.google.com/go/spanner/client.go index fe87fafb1..5d3d078a5 100644 --- a/vendor/cloud.google.com/go/spanner/client.go +++ b/vendor/cloud.google.com/go/spanner/client.go @@ -28,6 +28,8 @@ import ( "cloud.google.com/go/internal/trace" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" + "github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp" + grpcgcppb "github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp/grpc_gcp" "github.com/googleapis/gax-go/v2" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" @@ -37,6 +39,7 @@ import ( gtransport "google.golang.org/api/transport/grpc" "google.golang.org/grpc" "google.golang.org/grpc/codes" + "google.golang.org/grpc/credentials/insecure" "google.golang.org/grpc/encoding/gzip" "google.golang.org/grpc/metadata" @@ -121,6 +124,131 @@ func (c *Client) ClientID() string { return c.sc.id } +func createGCPMultiEndpoint(cfg *grpcgcp.GCPMultiEndpointOptions, config ClientConfig, opts ...option.ClientOption) (*grpcgcp.GCPMultiEndpoint, error) { + if cfg.GRPCgcpConfig == nil { + cfg.GRPCgcpConfig = &grpcgcppb.ApiConfig{} + } + if cfg.GRPCgcpConfig.Method == nil || len(cfg.GRPCgcpConfig.Method) == 0 { + cfg.GRPCgcpConfig.Method = []*grpcgcppb.MethodConfig{ + { + Name: []string{"/google.spanner.v1.Spanner/CreateSession"}, + Affinity: &grpcgcppb.AffinityConfig{ + Command: grpcgcppb.AffinityConfig_BIND, + AffinityKey: "name", + }, + }, + { + Name: []string{"/google.spanner.v1.Spanner/BatchCreateSessions"}, + Affinity: &grpcgcppb.AffinityConfig{ + Command: grpcgcppb.AffinityConfig_BIND, + AffinityKey: "session.name", + }, + }, + { + Name: []string{"/google.spanner.v1.Spanner/DeleteSession"}, + Affinity: &grpcgcppb.AffinityConfig{ + Command: grpcgcppb.AffinityConfig_UNBIND, + AffinityKey: "name", + }, + }, + { + Name: []string{"/google.spanner.v1.Spanner/GetSession"}, + Affinity: &grpcgcppb.AffinityConfig{ + Command: grpcgcppb.AffinityConfig_BOUND, + AffinityKey: "name", + }, + }, + { + Name: []string{ + "/google.spanner.v1.Spanner/BeginTransaction", + "/google.spanner.v1.Spanner/Commit", + "/google.spanner.v1.Spanner/ExecuteBatchDml", + "/google.spanner.v1.Spanner/ExecuteSql", + "/google.spanner.v1.Spanner/ExecuteStreamingSql", + "/google.spanner.v1.Spanner/PartitionQuery", + "/google.spanner.v1.Spanner/PartitionRead", + "/google.spanner.v1.Spanner/Read", + "/google.spanner.v1.Spanner/Rollback", + "/google.spanner.v1.Spanner/StreamingRead", + }, + Affinity: &grpcgcppb.AffinityConfig{ + Command: grpcgcppb.AffinityConfig_BOUND, + AffinityKey: "session", + }, + }, + } + } + // Append emulator options if SPANNER_EMULATOR_HOST has been set. + if emulatorAddr := os.Getenv("SPANNER_EMULATOR_HOST"); emulatorAddr != "" { + emulatorOpts := []option.ClientOption{ + option.WithEndpoint(emulatorAddr), + option.WithGRPCDialOption(grpc.WithTransportCredentials(insecure.NewCredentials())), + option.WithoutAuthentication(), + internaloption.SkipDialSettingsValidation(), + } + opts = append(opts, emulatorOpts...) + // Replace all endpoints with emulator target. + for _, meo := range cfg.MultiEndpoints { + meo.Endpoints = []string{emulatorAddr} + } + } + + // Set the number of channels to the default value if not specified. + if cfg.GRPCgcpConfig.GetChannelPool() == nil || cfg.GRPCgcpConfig.GetChannelPool().GetMaxSize() == 0 { + cfg.GRPCgcpConfig.ChannelPool = &grpcgcppb.ChannelPoolConfig{ + MinSize: numChannels, + MaxSize: numChannels, + } + } + // Set MinSize equal to MaxSize to create all the channels beforehand. + cfg.GRPCgcpConfig.ChannelPool.MinSize = cfg.GRPCgcpConfig.ChannelPool.GetMaxSize() + + cfg.GRPCgcpConfig.ChannelPool.BindPickStrategy = grpcgcppb.ChannelPoolConfig_ROUND_ROBIN + + cfg.DialFunc = func(ctx context.Context, target string, dopts ...grpc.DialOption) (*grpc.ClientConn, error) { + copts := opts + + for _, do := range dopts { + copts = append(copts, option.WithGRPCDialOption(do)) + } + + allOpts := allClientOpts(1, config.Compression, copts...) + + // Overwrite endpoint and pool config. + allOpts = append(allOpts, + option.WithEndpoint(target), + option.WithGRPCConnectionPool(1), + option.WithGRPCConn(nil), + ) + + return gtransport.Dial(ctx, allOpts...) + } + + gme, err := grpcgcp.NewGCPMultiEndpoint(cfg) + return gme, err +} + +// To use GCPMultiEndpoint in gtransport.Dial (via gtransport.WithConnPool option) +// we implement gtransport.ConnPool interface using this wrapper. +type gmeWrapper struct { + *grpcgcp.GCPMultiEndpoint +} + +// Make sure gmeWrapper implements ConnPool interface. +var _ gtransport.ConnPool = (*gmeWrapper)(nil) + +func (gw *gmeWrapper) Conn() *grpc.ClientConn { + // GCPMultiEndpoint does not expose any ClientConn. + // This is safe because Cloud Spanner client doesn't use this function and instead + // makes calls directly using Invoke and NewStream from the grpc.ClientConnInterface + // which GCPMultiEndpoint implements. + return nil +} + +func (gw *gmeWrapper) Num() int { + return int(gw.GCPMultiEndpoint.GCPConfig().GetChannelPool().GetMaxSize()) +} + // ClientConfig has configurations for the client. type ClientConfig struct { // NumChannels is the number of gRPC channels. @@ -206,18 +334,20 @@ type ClientConfig struct { } type openTelemetryConfig struct { - meterProvider metric.MeterProvider - attributeMap []attribute.KeyValue - otMetricRegistration metric.Registration - openSessionCount metric.Int64ObservableGauge - maxAllowedSessionsCount metric.Int64ObservableGauge - sessionsCount metric.Int64ObservableGauge - maxInUseSessionsCount metric.Int64ObservableGauge - getSessionTimeoutsCount metric.Int64Counter - acquiredSessionsCount metric.Int64Counter - releasedSessionsCount metric.Int64Counter - gfeLatency metric.Int64Histogram - gfeHeaderMissingCount metric.Int64Counter + meterProvider metric.MeterProvider + attributeMap []attribute.KeyValue + attributeMapWithMultiplexed []attribute.KeyValue + attributeMapWithoutMultiplexed []attribute.KeyValue + otMetricRegistration metric.Registration + openSessionCount metric.Int64ObservableGauge + maxAllowedSessionsCount metric.Int64ObservableGauge + sessionsCount metric.Int64ObservableGauge + maxInUseSessionsCount metric.Int64ObservableGauge + getSessionTimeoutsCount metric.Int64Counter + acquiredSessionsCount metric.Int64Counter + releasedSessionsCount metric.Int64Counter + gfeLatency metric.Int64Histogram + gfeHeaderMissingCount metric.Int64Counter } func contextWithOutgoingMetadata(ctx context.Context, md metadata.MD, disableRouteToLeader bool) context.Context { @@ -241,6 +371,10 @@ func NewClient(ctx context.Context, database string, opts ...option.ClientOption // NewClientWithConfig creates a client to a database. A valid database name has // the form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID. func NewClientWithConfig(ctx context.Context, database string, config ClientConfig, opts ...option.ClientOption) (c *Client, err error) { + return newClientWithConfig(ctx, database, config, nil, opts...) +} + +func newClientWithConfig(ctx context.Context, database string, config ClientConfig, gme *grpcgcp.GCPMultiEndpoint, opts ...option.ClientOption) (c *Client, err error) { // Validate database path. if err := validDatabaseName(database); err != nil { return nil, err @@ -253,7 +387,7 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf if emulatorAddr := os.Getenv("SPANNER_EMULATOR_HOST"); emulatorAddr != "" { emulatorOpts := []option.ClientOption{ option.WithEndpoint(emulatorAddr), - option.WithGRPCDialOption(grpc.WithInsecure()), + option.WithGRPCDialOption(grpc.WithTransportCredentials(insecure.NewCredentials())), option.WithoutAuthentication(), internaloption.SkipDialSettingsValidation(), } @@ -265,16 +399,25 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf if config.NumChannels == 0 { config.NumChannels = numChannels } - // gRPC options. - allOpts := allClientOpts(config.NumChannels, config.Compression, opts...) - pool, err := gtransport.DialPool(ctx, allOpts...) - if err != nil { - return nil, err - } - if hasNumChannelsConfig && pool.Num() != config.NumChannels { - pool.Close() - return nil, spannerErrorf(codes.InvalidArgument, "Connection pool mismatch: NumChannels=%v, WithGRPCConnectionPool=%v. Only set one of these options, or set both to the same value.", config.NumChannels, pool.Num()) + var pool gtransport.ConnPool + + if gme != nil { + // Use GCPMultiEndpoint if provided. + pool = &gmeWrapper{gme} + } else { + // Create gtransport ConnPool as usual if MultiEndpoint is not used. + // gRPC options. + allOpts := allClientOpts(config.NumChannels, config.Compression, opts...) + pool, err = gtransport.DialPool(ctx, allOpts...) + if err != nil { + return nil, err + } + + if hasNumChannelsConfig && pool.Num() != config.NumChannels { + pool.Close() + return nil, spannerErrorf(codes.InvalidArgument, "Connection pool mismatch: NumChannels=%v, WithGRPCConnectionPool=%v. Only set one of these options, or set both to the same value.", config.NumChannels, pool.Num()) + } } // TODO(loite): Remove as the original map cannot be changed by the user @@ -343,6 +486,48 @@ func NewClientWithConfig(ctx context.Context, database string, config ClientConf return c, nil } +// NewMultiEndpointClient is the same as NewMultiEndpointClientWithConfig with +// the default client configuration. +// +// A valid database name has the +// form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID. +func NewMultiEndpointClient(ctx context.Context, database string, gmeCfg *grpcgcp.GCPMultiEndpointOptions, opts ...option.ClientOption) (*Client, *grpcgcp.GCPMultiEndpoint, error) { + return NewMultiEndpointClientWithConfig(ctx, database, ClientConfig{SessionPoolConfig: DefaultSessionPoolConfig, DisableRouteToLeader: false}, gmeCfg, opts...) +} + +// NewMultiEndpointClientWithConfig creates a client to a database using GCPMultiEndpoint. +// +// The purposes of GCPMultiEndpoint are: +// +// - Fallback to an alternative endpoint (host:port) when the original +// endpoint is completely unavailable. +// - Be able to route a Cloud Spanner call to a specific group of endpoints. +// - Be able to reconfigure endpoints in runtime. +// +// The GRPCgcpConfig and DialFunc in the GCPMultiEndpointOptions are optional +// and will be configured automatically. +// +// For GCPMultiEndpoint the number of channels is configured via MaxSize of the +// ChannelPool config in the GRPCgcpConfig. +// +// The GCPMultiEndpoint returned can be used to update the endpoints in runtime. +// +// A valid database name has the +// form projects/PROJECT_ID/instances/INSTANCE_ID/databases/DATABASE_ID. +func NewMultiEndpointClientWithConfig(ctx context.Context, database string, config ClientConfig, gmeCfg *grpcgcp.GCPMultiEndpointOptions, opts ...option.ClientOption) (c *Client, gme *grpcgcp.GCPMultiEndpoint, err error) { + gme, err = createGCPMultiEndpoint(gmeCfg, config, opts...) + if err != nil { + return nil, nil, err + } + // Align number of channels. + config.NumChannels = int(gme.GCPConfig().GetChannelPool().GetMaxSize()) + c, err = newClientWithConfig(ctx, database, config, gme, opts...) + if err != nil { + return nil, nil, err + } + return +} + // Combines the default options from the generated client, the default options // of the hand-written client and the user options to one list of options. // Precedence: userOpts > clientDefaultOpts > generatedDefaultOpts @@ -351,11 +536,10 @@ func allClientOpts(numChannels int, compression string, userOpts ...option.Clien clientDefaultOpts := []option.ClientOption{ option.WithGRPCConnectionPool(numChannels), option.WithUserAgent(fmt.Sprintf("spanner-go/v%s", internal.Version)), - internaloption.EnableDirectPath(true), internaloption.AllowNonDefaultServiceAccount(true), } if enableDirectPathXds, _ := strconv.ParseBool(os.Getenv("GOOGLE_SPANNER_ENABLE_DIRECT_ACCESS")); enableDirectPathXds { - clientDefaultOpts = append(clientDefaultOpts, internaloption.EnableDirectPathXds()) + clientDefaultOpts = append(clientDefaultOpts, internaloption.EnableDirectPath(true), internaloption.EnableDirectPathXds()) } if compression == "gzip" { userOpts = append(userOpts, option.WithGRPCDialOption(grpc.WithDefaultCallOptions( @@ -427,6 +611,7 @@ func (c *Client) Single() *ReadOnlyTransaction { } t.txReadOnly.qo.DirectedReadOptions = c.dro t.txReadOnly.ro.DirectedReadOptions = c.dro + t.txReadOnly.ro.LockHint = sppb.ReadRequest_LOCK_HINT_UNSPECIFIED t.ct = c.ct t.otConfig = c.otConfig return t @@ -453,6 +638,7 @@ func (c *Client) ReadOnlyTransaction() *ReadOnlyTransaction { t.txReadOnly.disableRouteToLeader = true t.txReadOnly.qo.DirectedReadOptions = c.dro t.txReadOnly.ro.DirectedReadOptions = c.dro + t.txReadOnly.ro.LockHint = sppb.ReadRequest_LOCK_HINT_UNSPECIFIED t.ct = c.ct t.otConfig = c.otConfig return t @@ -524,6 +710,7 @@ func (c *Client) BatchReadOnlyTransaction(ctx context.Context, tb TimestampBound t.txReadOnly.disableRouteToLeader = true t.txReadOnly.qo.DirectedReadOptions = c.dro t.txReadOnly.ro.DirectedReadOptions = c.dro + t.txReadOnly.ro.LockHint = sppb.ReadRequest_LOCK_HINT_UNSPECIFIED t.ct = c.ct t.otConfig = c.otConfig return t, nil @@ -558,6 +745,7 @@ func (c *Client) BatchReadOnlyTransactionFromID(tid BatchReadOnlyTransactionID) t.txReadOnly.disableRouteToLeader = true t.txReadOnly.qo.DirectedReadOptions = c.dro t.txReadOnly.ro.DirectedReadOptions = c.dro + t.txReadOnly.ro.LockHint = sppb.ReadRequest_LOCK_HINT_UNSPECIFIED t.ct = c.ct t.otConfig = c.otConfig return t @@ -684,6 +872,12 @@ type applyOption struct { transactionTag string // priority is the RPC priority that is used for the commit operation. priority sppb.RequestOptions_Priority + // If excludeTxnFromChangeStreams == true, mutations from this Client.Apply + // will not be recorded in allowed tracking change streams with DDL option + // allow_txn_exclusion=true. + excludeTxnFromChangeStreams bool + // commitOptions is the commit options to use for the commit operation. + commitOptions CommitOptions } // An ApplyOption is an optional argument to Apply. @@ -722,6 +916,20 @@ func Priority(priority sppb.RequestOptions_Priority) ApplyOption { } } +// ExcludeTxnFromChangeStreams returns an ApplyOptions that sets whether to exclude recording this commit operation from allowed tracking change streams. +func ExcludeTxnFromChangeStreams() ApplyOption { + return func(ao *applyOption) { + ao.excludeTxnFromChangeStreams = true + } +} + +// ApplyCommitOptions returns an ApplyOption that sets the commit options to use for the commit operation. +func ApplyCommitOptions(co CommitOptions) ApplyOption { + return func(ao *applyOption) { + ao.commitOptions = co + } +} + // Apply applies a list of mutations atomically to the database. func (c *Client) Apply(ctx context.Context, ms []*Mutation, opts ...ApplyOption) (commitTimestamp time.Time, err error) { ao := &applyOption{} @@ -740,10 +948,10 @@ func (c *Client) Apply(ctx context.Context, ms []*Mutation, opts ...ApplyOption) if !ao.atLeastOnce { resp, err := c.ReadWriteTransactionWithOptions(ctx, func(ctx context.Context, t *ReadWriteTransaction) error { return t.BufferWrite(ms) - }, TransactionOptions{CommitPriority: ao.priority, TransactionTag: ao.transactionTag}) + }, TransactionOptions{CommitPriority: ao.priority, TransactionTag: ao.transactionTag, ExcludeTxnFromChangeStreams: ao.excludeTxnFromChangeStreams, CommitOptions: ao.commitOptions}) return resp.CommitTs, err } - t := &writeOnlyTransaction{sp: c.idleSessions, commitPriority: ao.priority, transactionTag: ao.transactionTag, disableRouteToLeader: c.disableRouteToLeader} + t := &writeOnlyTransaction{sp: c.idleSessions, commitPriority: ao.priority, transactionTag: ao.transactionTag, disableRouteToLeader: c.disableRouteToLeader, excludeTxnFromChangeStreams: ao.excludeTxnFromChangeStreams, commitOptions: ao.commitOptions} return t.applyAtLeastOnce(ctx, ms...) } @@ -754,14 +962,20 @@ type BatchWriteOptions struct { // The transaction tag to use for this request. TransactionTag string + + // If excludeTxnFromChangeStreams == true, modifications from all transactions + // in this batch write request will not be recorded in allowed tracking + // change treams with DDL option allow_txn_exclusion=true. + ExcludeTxnFromChangeStreams bool } // merge combines two BatchWriteOptions such that the input parameter will have higher // order of precedence. func (bwo BatchWriteOptions) merge(opts BatchWriteOptions) BatchWriteOptions { merged := BatchWriteOptions{ - TransactionTag: bwo.TransactionTag, - Priority: bwo.Priority, + TransactionTag: bwo.TransactionTag, + Priority: bwo.Priority, + ExcludeTxnFromChangeStreams: bwo.ExcludeTxnFromChangeStreams || opts.ExcludeTxnFromChangeStreams, } if opts.TransactionTag != "" { merged.TransactionTag = opts.TransactionTag @@ -916,9 +1130,10 @@ func (c *Client) BatchWriteWithOptions(ctx context.Context, mgs []*MutationGroup var md metadata.MD sh.updateLastUseTime() stream, rpcErr := sh.getClient().BatchWrite(contextWithOutgoingMetadata(ct, sh.getMetadata(), c.disableRouteToLeader), &sppb.BatchWriteRequest{ - Session: sh.getID(), - MutationGroups: mgsPb, - RequestOptions: createRequestOptions(opts.Priority, "", opts.TransactionTag), + Session: sh.getID(), + MutationGroups: mgsPb, + RequestOptions: createRequestOptions(opts.Priority, "", opts.TransactionTag), + ExcludeTxnFromChangeStreams: opts.ExcludeTxnFromChangeStreams, }, gax.WithGRPCOptions(grpc.Header(&md))) if getGFELatencyMetricsFlag() && md != nil && c.ct != nil { diff --git a/vendor/cloud.google.com/go/spanner/emulator_test.sh b/vendor/cloud.google.com/go/spanner/emulator_test.sh index fc326d83f..8fe69dba7 100644 --- a/vendor/cloud.google.com/go/spanner/emulator_test.sh +++ b/vendor/cloud.google.com/go/spanner/emulator_test.sh @@ -44,4 +44,8 @@ function cleanup() { } trap cleanup EXIT -go test -v -timeout 10m ./... -run '^TestIntegration_' 2>&1 | tee -a sponge_log.log +echo "Testing without GCPMultiEnpoint..." | tee -a sponge_log.log +go test -count=1 -v -timeout 10m ./... -run '^TestIntegration_' 2>&1 | tee -a sponge_log.log + +echo "Testing with GCPMultiEnpoint..." | tee -a sponge_log.log +GCLOUD_TESTS_GOLANG_USE_GRPC_GCP=true go test -count=1 -v -timeout 10m ./... -run '^TestIntegration_' 2>&1 | tee -a sponge_log.log diff --git a/vendor/cloud.google.com/go/spanner/errors.go b/vendor/cloud.google.com/go/spanner/errors.go index f44518127..ddf506bd5 100644 --- a/vendor/cloud.google.com/go/spanner/errors.go +++ b/vendor/cloud.google.com/go/spanner/errors.go @@ -18,6 +18,7 @@ package spanner import ( "context" + "errors" "fmt" "github.com/googleapis/gax-go/v2/apierror" @@ -26,6 +27,11 @@ import ( "google.golang.org/grpc/status" ) +var ( + // ErrRowNotFound row not found error + ErrRowNotFound = errors.New("row not found") +) + // Error is the structured error returned by Cloud Spanner client. // // Deprecated: Unwrap any error that is returned by the Spanner client as an APIError diff --git a/vendor/cloud.google.com/go/spanner/internal/version.go b/vendor/cloud.google.com/go/spanner/internal/version.go index 3f0621322..1a70149b3 100644 --- a/vendor/cloud.google.com/go/spanner/internal/version.go +++ b/vendor/cloud.google.com/go/spanner/internal/version.go @@ -15,4 +15,4 @@ package internal // Version is the current tagged release of the library. -const Version = "1.60.0" +const Version = "1.67.0" diff --git a/vendor/cloud.google.com/go/spanner/key.go b/vendor/cloud.google.com/go/spanner/key.go index e6ecfe444..26b1d9ba9 100644 --- a/vendor/cloud.google.com/go/spanner/key.go +++ b/vendor/cloud.google.com/go/spanner/key.go @@ -24,8 +24,9 @@ import ( "cloud.google.com/go/civil" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - proto3 "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/reflect/protoreflect" + proto3 "google.golang.org/protobuf/types/known/structpb" ) // A Key can be either a Cloud Spanner row's primary key or a secondary index @@ -58,6 +59,7 @@ import ( // - string and NullString are mapped to Cloud Spanner's STRING type. // - time.Time and NullTime are mapped to Cloud Spanner's TIMESTAMP type. // - civil.Date and NullDate are mapped to Cloud Spanner's DATE type. +// - protoreflect.Enum and NullProtoEnum are mapped to Cloud Spanner's ENUM type. type Key []interface{} // errInvdKeyPartType returns error for unsupported key part type. @@ -83,7 +85,7 @@ func keyPartValue(part interface{}) (pb *proto3.Value, err error) { pb, _, err = encodeValue(int64(v)) case uint32: pb, _, err = encodeValue(int64(v)) - case int64, float64, float32, NullInt64, NullFloat64, NullFloat32, bool, NullBool, []byte, string, NullString, time.Time, civil.Date, NullTime, NullDate, big.Rat, NullNumeric: + case int64, float64, float32, NullInt64, NullFloat64, NullFloat32, bool, NullBool, []byte, string, NullString, time.Time, civil.Date, NullTime, NullDate, big.Rat, NullNumeric, protoreflect.Enum, NullProtoEnum: pb, _, err = encodeValue(v) case Encoder: part, err = v.EncodeSpanner() @@ -138,7 +140,7 @@ func (key Key) String() string { func (key Key) elemString(b *bytes.Buffer, part interface{}) { switch v := part.(type) { - case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, float32, float64, bool: + case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, float32, float64, bool, protoreflect.Enum: // Use %v to print numeric types and bool. fmt.Fprintf(b, "%v", v) case string: @@ -149,7 +151,7 @@ func (key Key) elemString(b *bytes.Buffer, part interface{}) { } else { fmt.Fprint(b, nullString) } - case NullInt64, NullFloat64, NullBool, NullNumeric: + case NullInt64, NullFloat64, NullBool, NullNumeric, NullProtoEnum: // The above types implement fmt.Stringer. fmt.Fprintf(b, "%s", v) case NullString, NullDate, NullTime: diff --git a/vendor/cloud.google.com/go/spanner/mutation.go b/vendor/cloud.google.com/go/spanner/mutation.go index eb9baba7b..b9909742d 100644 --- a/vendor/cloud.google.com/go/spanner/mutation.go +++ b/vendor/cloud.google.com/go/spanner/mutation.go @@ -20,8 +20,8 @@ import ( "reflect" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - proto3 "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" + proto3 "google.golang.org/protobuf/types/known/structpb" ) // op is the mutation operation. diff --git a/vendor/cloud.google.com/go/spanner/ot_metrics.go b/vendor/cloud.google.com/go/spanner/ot_metrics.go index 2f49cadec..16190860c 100644 --- a/vendor/cloud.google.com/go/spanner/ot_metrics.go +++ b/vendor/cloud.google.com/go/spanner/ot_metrics.go @@ -33,12 +33,13 @@ const OtInstrumentationScope = "cloud.google.com/go" const metricsPrefix = "spanner/" var ( - attributeKeyClientID = attribute.Key("client_id") - attributeKeyDatabase = attribute.Key("database") - attributeKeyInstance = attribute.Key("instance_id") - attributeKeyLibVersion = attribute.Key("library_version") - attributeKeyType = attribute.Key("type") - attributeKeyMethod = attribute.Key("grpc_client_method") + attributeKeyClientID = attribute.Key("client_id") + attributeKeyDatabase = attribute.Key("database") + attributeKeyInstance = attribute.Key("instance_id") + attributeKeyLibVersion = attribute.Key("library_version") + attributeKeyType = attribute.Key("type") + attributeKeyMethod = attribute.Key("grpc_client_method") + attributeKeyIsMultiplexed = attribute.Key("is_multiplexed") attributeNumInUseSessions = attributeKeyType.String("num_in_use_sessions") attributeNumSessions = attributeKeyType.String("num_sessions") @@ -69,6 +70,12 @@ func createOpenTelemetryConfig(mp metric.MeterProvider, logger *log.Logger, sess } config.attributeMap = append(config.attributeMap, attributeMap...) + config.attributeMapWithMultiplexed = append(config.attributeMapWithMultiplexed, attributeMap...) + config.attributeMapWithMultiplexed = append(config.attributeMapWithMultiplexed, attributeKeyIsMultiplexed.String("true")) + + config.attributeMapWithoutMultiplexed = append(config.attributeMapWithoutMultiplexed, attributeMap...) + config.attributeMapWithoutMultiplexed = append(config.attributeMapWithoutMultiplexed, attributeKeyIsMultiplexed.String("false")) + setOpenTelemetryMetricProvider(config, mp, logger) return config, nil } @@ -197,13 +204,14 @@ func registerSessionPoolOTMetrics(pool *sessionPool) error { func(ctx context.Context, o metric.Observer) error { pool.mu.Lock() defer pool.mu.Unlock() - + if pool.multiplexedSession != nil { + o.ObserveInt64(otConfig.openSessionCount, int64(1), metric.WithAttributes(otConfig.attributeMapWithMultiplexed...)) + } o.ObserveInt64(otConfig.openSessionCount, int64(pool.numOpened), metric.WithAttributes(attributes...)) o.ObserveInt64(otConfig.maxAllowedSessionsCount, int64(pool.SessionPoolConfig.MaxOpened), metric.WithAttributes(attributes...)) - o.ObserveInt64(otConfig.sessionsCount, int64(pool.numInUse), metric.WithAttributes(attributesInUseSessions...)) + o.ObserveInt64(otConfig.sessionsCount, int64(pool.numInUse), metric.WithAttributes(append(attributesInUseSessions, attribute.Key("is_multiplexed").String("false"))...)) o.ObserveInt64(otConfig.sessionsCount, int64(pool.numSessions), metric.WithAttributes(attributesAvailableSessions...)) - o.ObserveInt64(otConfig.maxInUseSessionsCount, int64(pool.maxNumInUse), metric.WithAttributes(attributes...)) - + o.ObserveInt64(otConfig.maxInUseSessionsCount, int64(pool.maxNumInUse), metric.WithAttributes(append(attributes, attribute.Key("is_multiplexed").String("false"))...)) return nil }, otConfig.openSessionCount, diff --git a/vendor/cloud.google.com/go/spanner/pdml.go b/vendor/cloud.google.com/go/spanner/pdml.go index ac3b5b0fe..bb33ef291 100644 --- a/vendor/cloud.google.com/go/spanner/pdml.go +++ b/vendor/cloud.google.com/go/spanner/pdml.go @@ -84,7 +84,7 @@ func (c *Client) partitionedUpdate(ctx context.Context, statement Statement, opt // Execute the PDML and retry if the transaction is aborted. executePdmlWithRetry := func(ctx context.Context) (int64, error) { for { - count, err := executePdml(contextWithOutgoingMetadata(ctx, sh.getMetadata(), c.disableRouteToLeader), sh, req) + count, err := executePdml(contextWithOutgoingMetadata(ctx, sh.getMetadata(), c.disableRouteToLeader), sh, req, options) if err == nil { return count, nil } @@ -106,14 +106,15 @@ func (c *Client) partitionedUpdate(ctx context.Context, statement Statement, opt // 3. Execute the update statement on the PDML transaction // // Note that PDML transactions cannot be committed or rolled back. -func executePdml(ctx context.Context, sh *sessionHandle, req *sppb.ExecuteSqlRequest) (count int64, err error) { +func executePdml(ctx context.Context, sh *sessionHandle, req *sppb.ExecuteSqlRequest, options QueryOptions) (count int64, err error) { var md metadata.MD sh.updateLastUseTime() // Begin transaction. res, err := sh.getClient().BeginTransaction(ctx, &sppb.BeginTransactionRequest{ Session: sh.getID(), Options: &sppb.TransactionOptions{ - Mode: &sppb.TransactionOptions_PartitionedDml_{PartitionedDml: &sppb.TransactionOptions_PartitionedDml{}}, + Mode: &sppb.TransactionOptions_PartitionedDml_{PartitionedDml: &sppb.TransactionOptions_PartitionedDml{}}, + ExcludeTxnFromChangeStreams: options.ExcludeTxnFromChangeStreams, }, }) if err != nil { diff --git a/vendor/cloud.google.com/go/spanner/protoutils.go b/vendor/cloud.google.com/go/spanner/protoutils.go index 83af997ca..988e71594 100644 --- a/vendor/cloud.google.com/go/spanner/protoutils.go +++ b/vendor/cloud.google.com/go/spanner/protoutils.go @@ -24,7 +24,9 @@ import ( "cloud.google.com/go/civil" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - proto3 "github.com/golang/protobuf/ptypes/struct" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/reflect/protoreflect" + proto3 "google.golang.org/protobuf/types/known/structpb" ) // Helpers to generate protobuf values and Cloud Spanner types. @@ -85,6 +87,10 @@ func pgNumericType() *sppb.Type { return &sppb.Type{Code: sppb.TypeCode_NUMERIC, TypeAnnotation: sppb.TypeAnnotationCode_PG_NUMERIC} } +func pgOidType() *sppb.Type { + return &sppb.Type{Code: sppb.TypeCode_INT64, TypeAnnotation: sppb.TypeAnnotationCode_PG_OID} +} + func jsonType() *sppb.Type { return &sppb.Type{Code: sppb.TypeCode_JSON} } @@ -140,3 +146,20 @@ func structType(fields ...*sppb.StructType_Field) *sppb.Type { func nullProto() *proto3.Value { return &proto3.Value{Kind: &proto3.Value_NullValue{NullValue: proto3.NullValue_NULL_VALUE}} } + +func protoMessageType(fqn string) *sppb.Type { + return &sppb.Type{Code: sppb.TypeCode_PROTO, ProtoTypeFqn: fqn} +} + +func protoEnumType(fqn string) *sppb.Type { + return &sppb.Type{Code: sppb.TypeCode_ENUM, ProtoTypeFqn: fqn} +} + +func protoMessageProto(m proto.Message) *proto3.Value { + var b, _ = proto.Marshal(m) + return &proto3.Value{Kind: &proto3.Value_StringValue{StringValue: base64.StdEncoding.EncodeToString(b)}} +} + +func protoEnumProto(e protoreflect.Enum) *proto3.Value { + return &proto3.Value{Kind: &proto3.Value_StringValue{StringValue: strconv.FormatInt(int64(e.Number()), 10)}} +} diff --git a/vendor/cloud.google.com/go/spanner/read.go b/vendor/cloud.google.com/go/spanner/read.go index 50578b740..83755722e 100644 --- a/vendor/cloud.google.com/go/spanner/read.go +++ b/vendor/cloud.google.com/go/spanner/read.go @@ -27,11 +27,11 @@ import ( "cloud.google.com/go/internal/protostruct" "cloud.google.com/go/internal/trace" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - "github.com/golang/protobuf/proto" - proto3 "github.com/golang/protobuf/ptypes/struct" "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/proto" + proto3 "google.golang.org/protobuf/types/known/structpb" ) // streamingReceiver is the interface for receiving data from a client side @@ -498,7 +498,7 @@ var ( ) func (d *resumableStreamDecoder) next() bool { - retryer := onCodes(d.backoff, codes.Unavailable, codes.Internal) + retryer := onCodes(d.backoff, codes.Unavailable, codes.ResourceExhausted, codes.Internal) for { switch d.state { case unConnected: diff --git a/vendor/cloud.google.com/go/spanner/retry.go b/vendor/cloud.google.com/go/spanner/retry.go index 752e8933e..a140ce62e 100644 --- a/vendor/cloud.google.com/go/spanner/retry.go +++ b/vendor/cloud.google.com/go/spanner/retry.go @@ -22,7 +22,6 @@ import ( "time" "cloud.google.com/go/internal/trace" - "github.com/golang/protobuf/ptypes" "github.com/googleapis/gax-go/v2" "google.golang.org/genproto/googleapis/rpc/errdetails" "google.golang.org/grpc/codes" @@ -86,7 +85,7 @@ func (r *spannerRetryer) Retry(err error) (time.Duration, bool) { // a minimum of 10ms and maximum of 32s. There is no delay before the retry if // the error was Session not found or failed inline begin transaction. func runWithRetryOnAbortedOrFailedInlineBeginOrSessionNotFound(ctx context.Context, f func(context.Context) error) error { - retryer := onCodes(DefaultRetryBackoff, codes.Aborted, codes.Internal) + retryer := onCodes(DefaultRetryBackoff, codes.Aborted, codes.ResourceExhausted, codes.Internal) funcWithRetry := func(ctx context.Context) error { for { err := f(ctx) @@ -147,11 +146,10 @@ func ExtractRetryDelay(err error) (time.Duration, bool) { } for _, detail := range s.Details() { if retryInfo, ok := detail.(*errdetails.RetryInfo); ok { - delay, err := ptypes.Duration(retryInfo.RetryDelay) - if err != nil { + if !retryInfo.GetRetryDelay().IsValid() { return 0, false } - return delay, true + return retryInfo.GetRetryDelay().AsDuration(), true } } return 0, false diff --git a/vendor/cloud.google.com/go/spanner/row.go b/vendor/cloud.google.com/go/spanner/row.go index 5905bc9b2..f61350435 100644 --- a/vendor/cloud.google.com/go/spanner/row.go +++ b/vendor/cloud.google.com/go/spanner/row.go @@ -22,8 +22,8 @@ import ( "strings" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - proto3 "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" + proto3 "google.golang.org/protobuf/types/known/structpb" ) // A Row is a view of a row of data returned by a Cloud Spanner read. diff --git a/vendor/cloud.google.com/go/spanner/session.go b/vendor/cloud.google.com/go/spanner/session.go index a201b5ff5..3e587095a 100644 --- a/vendor/cloud.google.com/go/spanner/session.go +++ b/vendor/cloud.google.com/go/spanner/session.go @@ -24,6 +24,7 @@ import ( "log" "math" "math/rand" + "os" "runtime/debug" "strings" "sync" @@ -36,12 +37,16 @@ import ( "go.opencensus.io/stats" "go.opencensus.io/tag" octrace "go.opencensus.io/trace" + "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/metric" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" ) -const healthCheckIntervalMins = 50 +const ( + healthCheckIntervalMins = 50 + multiplexSessionRefreshInterval = 7 * 24 * time.Hour +) // ActionOnInactiveTransactionKind describes the kind of action taken when there are inactive transactions. type ActionOnInactiveTransactionKind int @@ -85,6 +90,8 @@ type sessionHandle struct { // session is a pointer to a session object. Transactions never need to // access it directly. session *session + // client is the RPC channel to Cloud Spanner. It is set only once during session acquisition. + client *vkit.Client // checkoutTime is the time the session was checked out of the pool. checkoutTime time.Time // lastUseTime is the time the session was last used after checked out of the pool. @@ -115,6 +122,7 @@ func (sh *sessionHandle) recycle() { tracked := sh.trackedSessionHandle s := sh.session sh.session = nil + sh.client = nil sh.trackedSessionHandle = nil sh.checkoutTime = time.Time{} sh.lastUseTime = time.Time{} @@ -149,6 +157,10 @@ func (sh *sessionHandle) getClient() *vkit.Client { if sh.session == nil { return nil } + if sh.client != nil { + // Use the gRPC connection from the session handle + return sh.client + } return sh.session.client } @@ -185,6 +197,7 @@ func (sh *sessionHandle) destroy() { } tracked := sh.trackedSessionHandle sh.session = nil + sh.client = nil sh.trackedSessionHandle = nil sh.checkoutTime = time.Time{} sh.lastUseTime = time.Time{} @@ -197,7 +210,8 @@ func (sh *sessionHandle) destroy() { p.trackedSessionHandles.Remove(tracked) p.mu.Unlock() } - s.destroy(false) + // since sessionHandle is always used by Transactions we can safely destroy the session with wasInUse=true + s.destroy(false, true) } func (sh *sessionHandle) updateLastUseTime() { @@ -252,6 +266,8 @@ type session struct { tx transactionID // firstHCDone indicates whether the first health check is done or not. firstHCDone bool + // isMultiplexed is true if the session is multiplexed. + isMultiplexed bool } // isValid returns true if the session is still valid for use. @@ -370,11 +386,16 @@ func (s *session) getNextCheck() time.Time { func (s *session) recycle() { s.setTransactionID(nil) s.pool.mu.Lock() + if s.isMultiplexed { + s.pool.decNumMultiplexedInUseLocked(context.Background()) + s.pool.mu.Unlock() + return + } if !s.pool.recycleLocked(s) { // s is rejected by its home session pool because it expired and the // session pool currently has enough open sessions. s.pool.mu.Unlock() - s.destroy(false) + s.destroy(false, true) s.pool.mu.Lock() } s.pool.decNumInUseLocked(context.Background()) @@ -383,15 +404,15 @@ func (s *session) recycle() { // destroy removes the session from its home session pool, healthcheck queue // and Cloud Spanner service. -func (s *session) destroy(isExpire bool) bool { +func (s *session) destroy(isExpire, wasInUse bool) bool { ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) defer cancel() - return s.destroyWithContext(ctx, isExpire) + return s.destroyWithContext(ctx, isExpire, wasInUse) } -func (s *session) destroyWithContext(ctx context.Context, isExpire bool) bool { +func (s *session) destroyWithContext(ctx context.Context, isExpire, wasInUse bool) bool { // Remove s from session pool. - if !s.pool.remove(s, isExpire) { + if !s.pool.remove(s, isExpire, wasInUse) { return false } // Unregister s from healthcheck queue. @@ -475,6 +496,11 @@ type SessionPoolConfig struct { // Defaults to 50m. HealthCheckInterval time.Duration + // MultiplexSessionCheckInterval is the interval at which the multiplexed session is checked whether it needs to be refreshed. + // + // Defaults to 10 mins. + MultiplexSessionCheckInterval time.Duration + // TrackSessionHandles determines whether the session pool will keep track // of the stacktrace of the goroutines that take sessions from the pool. // This setting can be used to track down session leak problems. @@ -554,6 +580,11 @@ func (spc *SessionPoolConfig) validate() error { return nil } +type muxSessionCreateRequest struct { + ctx context.Context + force bool +} + // sessionPool creates and caches Cloud Spanner sessions. type sessionPool struct { // mu protects sessionPool from concurrent access. @@ -569,12 +600,25 @@ type sessionPool struct { // idleList caches idle session IDs. Session IDs in this list can be // allocated for use. idleList list.List + // multiplexSessionClientCounter is the counter for the multiplexed session client. + multiplexSessionClientCounter int + // clientPool is a pool of Cloud Spanner grpc clients. + clientPool []*vkit.Client + // multiplexedSession contains the multiplexed session + multiplexedSession *session // mayGetSession is for broadcasting that session retrival/creation may // proceed. mayGetSession chan struct{} + // multiplexedSessionReq is the ongoing multiplexed session creation request (if any). + multiplexedSessionReq chan muxSessionCreateRequest + // mayGetMultiplexedSession is for broadcasting that multiplexed session retrieval is possible. + mayGetMultiplexedSession chan bool // sessionCreationError is the last error that occurred during session // creation and is propagated to any waiters waiting for a session. sessionCreationError error + // multiplexedSessionCreationError is the error that occurred during multiplexed session + // creation for the first time and is propagated to any waiters waiting for a session. + multiplexedSessionCreationError error // numOpened is the total number of open sessions from the session pool. numOpened uint64 // createReqs is the number of ongoing session creation requests. @@ -616,6 +660,9 @@ type sessionPool struct { numOfLeakedSessionsRemoved uint64 otConfig *openTelemetryConfig + + // enableMultiplexSession is a flag to enable multiplexed session. + enableMultiplexSession bool } // newSessionPool creates a new session pool. @@ -650,15 +697,24 @@ func newSessionPool(sc *sessionClient, config SessionPoolConfig) (*sessionPool, if config.usedSessionsRatioThreshold == 0 { config.usedSessionsRatioThreshold = DefaultSessionPoolConfig.usedSessionsRatioThreshold } - + if config.MultiplexSessionCheckInterval == 0 { + config.MultiplexSessionCheckInterval = 10 * time.Minute + } + isMultiplexed := strings.ToLower(os.Getenv("GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS")) + if isMultiplexed != "" && isMultiplexed != "true" && isMultiplexed != "false" { + return nil, spannerErrorf(codes.InvalidArgument, "GOOGLE_CLOUD_SPANNER_MULTIPLEXED_SESSIONS must be either true or false") + } pool := &sessionPool{ - sc: sc, - valid: true, - mayGetSession: make(chan struct{}), - SessionPoolConfig: config, - mw: newMaintenanceWindow(config.MaxOpened), - rand: rand.New(rand.NewSource(time.Now().UnixNano())), - otConfig: sc.otConfig, + sc: sc, + valid: true, + mayGetSession: make(chan struct{}), + mayGetMultiplexedSession: make(chan bool), + multiplexedSessionReq: make(chan muxSessionCreateRequest), + SessionPoolConfig: config, + mw: newMaintenanceWindow(config.MaxOpened), + rand: rand.New(rand.NewSource(time.Now().UnixNano())), + otConfig: sc.otConfig, + enableMultiplexSession: isMultiplexed == "true", } _, instance, database, err := parseDatabaseName(sc.database) @@ -681,7 +737,7 @@ func newSessionPool(sc *sessionClient, config SessionPoolConfig) (*sessionPool, // 10ms to finish, given a 5 minutes interval and 10 healthcheck workers, a // healthChecker can effectively mantain // 100 checks_per_worker/sec * 10 workers * 300 seconds = 300K sessions. - pool.hc = newHealthChecker(config.HealthCheckInterval, config.HealthCheckWorkers, config.healthCheckSampleInterval, pool) + pool.hc = newHealthChecker(config.HealthCheckInterval, config.MultiplexSessionCheckInterval, config.HealthCheckWorkers, config.healthCheckSampleInterval, pool) // First initialize the pool before we indicate that the healthchecker is // ready. This prevents the maintainer from starting before the pool has @@ -693,6 +749,22 @@ func newSessionPool(sc *sessionClient, config SessionPoolConfig) (*sessionPool, return nil, err } } + if pool.enableMultiplexSession { + go pool.createMultiplexedSession() + ctx, cancel := context.WithTimeout(ctx, 30*time.Second) + pool.multiplexedSessionReq <- muxSessionCreateRequest{force: true, ctx: ctx} + // listen for the session to be created + go func() { + select { + case <-ctx.Done(): + cancel() + return + // wait for the session to be created + case <-pool.mayGetMultiplexedSession: + } + return + }() + } pool.recordStat(context.Background(), MaxAllowedSessionsCount, int64(config.MaxOpened)) err = registerSessionPoolOTMetrics(pool) @@ -717,9 +789,17 @@ func (p *sessionPool) recordStat(ctx context.Context, m *stats.Int64Measure, n i recordStat(ctx, m, n) } -func (p *sessionPool) recordOTStat(ctx context.Context, m metric.Int64Counter, val int64) { +type recordOTStatOption struct { + attr []attribute.KeyValue +} + +func (p *sessionPool) recordOTStat(ctx context.Context, m metric.Int64Counter, val int64, option recordOTStatOption) { if m != nil { - m.Add(ctx, val, metric.WithAttributes(p.otConfig.attributeMap...)) + attrs := p.otConfig.attributeMap + if len(option.attr) > 0 { + attrs = option.attr + } + m.Add(ctx, val, metric.WithAttributes(attrs...)) } } @@ -746,7 +826,7 @@ func (p *sessionPool) getLongRunningSessionsLocked() []*sessionHandle { element = element.Next() continue } - diff := time.Now().Sub(sh.lastUseTime) + diff := time.Since(sh.lastUseTime) if !sh.eligibleForLongRunning && diff.Seconds() >= p.idleTimeThreshold.Seconds() { if (p.ActionOnInactiveTransaction == Warn || p.ActionOnInactiveTransaction == WarnAndClose) && !sh.isSessionLeakLogged { if p.ActionOnInactiveTransaction == Warn { @@ -812,13 +892,57 @@ func (p *sessionPool) growPoolLocked(numSessions uint64, distributeOverChannels return p.sc.batchCreateSessions(int32(numSessions), distributeOverChannels, p) } +func (p *sessionPool) createMultiplexedSession() { + for c := range p.multiplexedSessionReq { + p.mu.Lock() + sess := p.multiplexedSession + p.mu.Unlock() + if c.force || sess == nil { + p.mu.Lock() + p.sc.mu.Lock() + client, err := p.sc.nextClient() + p.sc.mu.Unlock() + p.mu.Unlock() + if err != nil { + // If we can't get a client, we can't create a session. + p.mu.Lock() + p.multiplexedSessionCreationError = err + p.mu.Unlock() + p.mayGetMultiplexedSession <- true + continue + } + p.sc.executeCreateMultiplexedSession(c.ctx, client, p.sc.md, p) + continue + } + select { + case p.mayGetMultiplexedSession <- true: + case <-c.ctx.Done(): + return + } + } +} + // sessionReady is executed by the SessionClient when a session has been // created and is ready to use. This method will add the new session to the // pool and decrease the number of sessions that is being created. -func (p *sessionPool) sessionReady(s *session) { +func (p *sessionPool) sessionReady(ctx context.Context, s *session) { p.mu.Lock() defer p.mu.Unlock() // Clear any session creation error. + if s.isMultiplexed { + s.pool = p + p.multiplexedSession = s + p.multiplexedSessionCreationError = nil + p.recordStat(context.Background(), OpenSessionCount, int64(1), tag.Tag{Key: tagKeyIsMultiplexed, Value: "true"}) + p.recordStat(context.Background(), SessionsCount, 1, tagNumSessions, tag.Tag{Key: tagKeyIsMultiplexed, Value: "true"}) + // either notify the waiting goroutine or skip if no one is waiting + select { + case p.mayGetMultiplexedSession <- true: + case <-ctx.Done(): + return + } + return + } p.sessionCreationError = nil // Set this pool as the home pool of the session and register it with the // health checker. @@ -848,12 +972,32 @@ func (p *sessionPool) sessionReady(s *session) { // or more requested sessions finished with an error. sessionCreationFailed will // decrease the number of sessions being created and notify any waiters that // the session creation failed. -func (p *sessionPool) sessionCreationFailed(err error, numSessions int32) { +func (p *sessionPool) sessionCreationFailed(ctx context.Context, err error, numSessions int32, isMultiplexed bool) { p.mu.Lock() defer p.mu.Unlock() + if isMultiplexed { + // Ignore the error if multiplexed session already present + if p.multiplexedSession != nil { + p.multiplexedSessionCreationError = nil + select { + case p.mayGetMultiplexedSession <- true: + case <-ctx.Done(): + return + } + return + } + p.recordStat(context.Background(), OpenSessionCount, int64(0), tag.Tag{Key: tagKeyIsMultiplexed, Value: "true"}) + p.multiplexedSessionCreationError = err + select { + case p.mayGetMultiplexedSession <- true: + case <-ctx.Done(): + return + } + return + } p.createReqs -= uint64(numSessions) p.numOpened -= uint64(numSessions) - p.recordStat(context.Background(), OpenSessionCount, int64(p.numOpened)) + p.recordStat(context.Background(), OpenSessionCount, int64(p.numOpened), tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) // Notify other waiters blocking on session creation. p.sessionCreationError = err close(p.mayGetSession) @@ -900,14 +1044,14 @@ func (p *sessionPool) close(ctx context.Context) { wg := sync.WaitGroup{} for _, s := range allSessions { wg.Add(1) - go deleteSession(ctx, s, &wg) + go closeSession(ctx, s, &wg) } wg.Wait() } -func deleteSession(ctx context.Context, s *session, wg *sync.WaitGroup) { +func closeSession(ctx context.Context, s *session, wg *sync.WaitGroup) { defer wg.Done() - s.destroyWithContext(ctx, false) + s.destroyWithContext(ctx, false, false) } // errInvalidSessionPool is the error for using an invalid session pool. @@ -923,19 +1067,46 @@ var errGetSessionTimeout = spannerErrorf(codes.Canceled, "timeout / context canc // sessions being checked out of the pool. func (p *sessionPool) newSessionHandle(s *session) (sh *sessionHandle) { sh = &sessionHandle{session: s, checkoutTime: time.Now(), lastUseTime: time.Now()} + if s.isMultiplexed { + p.mu.Lock() + sh.client = p.getRoundRobinClient() + p.mu.Unlock() + return sh + } if p.TrackSessionHandles || p.ActionOnInactiveTransaction == Warn || p.ActionOnInactiveTransaction == WarnAndClose || p.ActionOnInactiveTransaction == Close { p.mu.Lock() sh.trackedSessionHandle = p.trackedSessionHandles.PushBack(sh) - p.mu.Unlock() if p.TrackSessionHandles { sh.stack = debug.Stack() } + p.mu.Unlock() } return sh } +func (p *sessionPool) getRoundRobinClient() *vkit.Client { + p.sc.mu.Lock() + defer func() { + p.multiplexSessionClientCounter++ + p.sc.mu.Unlock() + }() + if len(p.clientPool) == 0 { + p.clientPool = make([]*vkit.Client, p.sc.connPool.Num()) + for i := 0; i < p.sc.connPool.Num(); i++ { + c, err := p.sc.nextClient() + if err != nil { + // If we can't get a client, use the session's client. + return nil + } + p.clientPool[i] = c + } + } + p.multiplexSessionClientCounter = p.multiplexSessionClientCounter % len(p.clientPool) + return p.clientPool[p.multiplexSessionClientCounter] +} + // errGetSessionTimeout returns error for context timeout during -// sessionPool.take(). +// sessionPool.take() or sessionPool.takeMultiplexed(). func (p *sessionPool) errGetSessionTimeout(ctx context.Context) error { var code codes.Code if ctx.Err() == context.DeadlineExceeded { @@ -987,42 +1158,11 @@ func (p *sessionPool) getTrackedSessionHandleStacksLocked() string { return stackTraces } -func (p *sessionPool) createSession(ctx context.Context) (*session, error) { - trace.TracePrintf(ctx, nil, "Creating a new session") - doneCreate := func(done bool) { - p.mu.Lock() - if !done { - // Session creation failed, give budget back. - p.numOpened-- - p.recordStat(ctx, OpenSessionCount, int64(p.numOpened)) - } - p.createReqs-- - // Notify other waiters blocking on session creation. - close(p.mayGetSession) - p.mayGetSession = make(chan struct{}) - p.mu.Unlock() - } - s, err := p.sc.createSession(ctx) - if err != nil { - doneCreate(false) - // Should return error directly because of the previous retries on - // CreateSession RPC. - // If the error is a timeout, there is a chance that the session was - // created on the server but is not known to the session pool. This - // session will then be garbage collected by the server after 1 hour. - return nil, err - } - s.pool = p - p.hc.register(s) - doneCreate(true) - return s, nil -} - func (p *sessionPool) isHealthy(s *session) bool { if s.getNextCheck().Add(2 * p.hc.getInterval()).Before(time.Now()) { if err := s.ping(); isSessionNotFoundError(err) { // The session is already bad, continue to fetch/create a new one. - s.destroy(false) + s.destroy(false, false) return false } p.hc.scheduledHC(s) @@ -1084,9 +1224,9 @@ func (p *sessionPool) take(ctx context.Context) (*sessionHandle, error) { select { case <-ctx.Done(): trace.TracePrintf(ctx, nil, "Context done waiting for session") - p.recordStat(ctx, GetSessionTimeoutsCount, 1) + p.recordStat(ctx, GetSessionTimeoutsCount, 1, tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) if p.otConfig != nil { - p.recordOTStat(ctx, p.otConfig.getSessionTimeoutsCount, 1) + p.recordOTStat(ctx, p.otConfig.getSessionTimeoutsCount, 1, recordOTStatOption{attr: p.otConfig.attributeMapWithoutMultiplexed}) } p.mu.Lock() p.numWaiters-- @@ -1106,6 +1246,63 @@ func (p *sessionPool) take(ctx context.Context) (*sessionHandle, error) { } } +// takeMultiplexed returns a cached session if there is available one; if there isn't +// any, it tries to allocate a new one. +func (p *sessionPool) takeMultiplexed(ctx context.Context) (*sessionHandle, error) { + trace.TracePrintf(ctx, nil, "Acquiring a multiplexed session") + for { + var s *session + p.mu.Lock() + if !p.valid { + p.mu.Unlock() + return nil, errInvalidSessionPool + } + if !p.enableMultiplexSession { + p.mu.Unlock() + return p.take(ctx) + } + // use the multiplex session if it is available + if p.multiplexedSession != nil { + // Multiplexed session is available, get it. + s = p.multiplexedSession + trace.TracePrintf(ctx, map[string]interface{}{"sessionID": s.getID()}, + "Acquired multiplexed session") + p.mu.Unlock() + p.incNumMultiplexedInUse(ctx) + return p.newSessionHandle(s), nil + } + mayGetSession := p.mayGetMultiplexedSession + p.mu.Unlock() + p.multiplexedSessionReq <- muxSessionCreateRequest{force: false, ctx: ctx} + select { + case <-ctx.Done(): + trace.TracePrintf(ctx, nil, "Context done waiting for multiplexed session") + p.recordStat(ctx, GetSessionTimeoutsCount, 1, tag.Tag{Key: tagKeyIsMultiplexed, Value: "true"}) + if p.otConfig != nil { + p.recordOTStat(ctx, p.otConfig.getSessionTimeoutsCount, 1, recordOTStatOption{attr: p.otConfig.attributeMapWithMultiplexed}) + } + return nil, p.errGetSessionTimeout(ctx) + case <-mayGetSession: // Block until multiplexed session is created. + p.mu.Lock() + if p.multiplexedSessionCreationError != nil { + trace.TracePrintf(ctx, nil, "Error creating multiplexed session: %v", p.multiplexedSessionCreationError) + err := p.multiplexedSessionCreationError + if isUnimplementedError(err) { + logf(p.sc.logger, "Multiplexed session is not enabled on this project, continuing with regular sessions") + p.enableMultiplexSession = false + } else { + p.mu.Unlock() + // If the error is a timeout, there is a chance that the session was + // created on the server but is not known to the session pool. In this + // case, we should retry to get the session. + return nil, err + } + } + p.mu.Unlock() + } + } +} + // recycle puts session s back to the session pool's idle list, it returns true // if the session pool successfully recycles session s. func (p *sessionPool) recycle(s *session) bool { @@ -1133,7 +1330,10 @@ func (p *sessionPool) recycleLocked(s *session) bool { // remove atomically removes session s from the session pool and invalidates s. // If isExpire == true, the removal is triggered by session expiration and in // such cases, only idle sessions can be removed. -func (p *sessionPool) remove(s *session, isExpire bool) bool { +func (p *sessionPool) remove(s *session, isExpire bool, wasInUse bool) bool { + if s.isMultiplexed { + return false + } p.mu.Lock() defer p.mu.Unlock() if isExpire && (p.numOpened <= p.MinOpened || s.getIdleList() == nil) { @@ -1141,6 +1341,7 @@ func (p *sessionPool) remove(s *session, isExpire bool) bool { // if number of open sessions is going below p.MinOpened. return false } + ol := s.setIdleList(nil) ctx := context.Background() // If the session is in the idlelist, remove it. @@ -1152,10 +1353,11 @@ func (p *sessionPool) remove(s *session, isExpire bool) bool { if s.invalidate() { // Decrease the number of opened sessions. p.numOpened-- - // Decrease the number of sessions in use. - p.decNumInUseLocked(ctx) + // Decrease the number of sessions in use, only when not from idle list. + if wasInUse { + p.decNumInUseLocked(ctx) + } p.recordStat(ctx, OpenSessionCount, int64(p.numOpened)) - // Broadcast that a session has been destroyed. close(p.mayGetSession) p.mayGetSession = make(chan struct{}) return true @@ -1175,23 +1377,42 @@ func (p *sessionPool) incNumInUse(ctx context.Context) { func (p *sessionPool) incNumInUseLocked(ctx context.Context) { p.numInUse++ - p.recordStat(ctx, SessionsCount, int64(p.numInUse), tagNumInUseSessions) - p.recordStat(ctx, AcquiredSessionsCount, 1) + p.recordStat(ctx, SessionsCount, int64(p.numInUse), tagNumInUseSessions, tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) + p.recordStat(ctx, AcquiredSessionsCount, 1, tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) if p.otConfig != nil { - p.recordOTStat(ctx, p.otConfig.acquiredSessionsCount, 1) + p.recordOTStat(ctx, p.otConfig.acquiredSessionsCount, 1, recordOTStatOption{attr: p.otConfig.attributeMapWithoutMultiplexed}) } if p.numInUse > p.maxNumInUse { p.maxNumInUse = p.numInUse - p.recordStat(ctx, MaxInUseSessionsCount, int64(p.maxNumInUse)) + p.recordStat(ctx, MaxInUseSessionsCount, int64(p.maxNumInUse), tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) + } +} + +func (p *sessionPool) incNumMultiplexedInUse(ctx context.Context) { + p.recordStat(ctx, AcquiredSessionsCount, 1, tag.Tag{Key: tagKeyIsMultiplexed, Value: "true"}) + if p.otConfig != nil { + p.recordOTStat(ctx, p.otConfig.acquiredSessionsCount, 1, recordOTStatOption{attr: p.otConfig.attributeMapWithMultiplexed}) } } func (p *sessionPool) decNumInUseLocked(ctx context.Context) { p.numInUse-- - p.recordStat(ctx, SessionsCount, int64(p.numInUse), tagNumInUseSessions) - p.recordStat(ctx, ReleasedSessionsCount, 1) + if int64(p.numInUse) < 0 { + // print whole call stack trace + logf(p.sc.logger, "Number of sessions in use is negative, resetting it to currSessionsCheckedOutLocked. Stack trace: %s", string(debug.Stack())) + p.numInUse = p.currSessionsCheckedOutLocked() + } + p.recordStat(ctx, SessionsCount, int64(p.numInUse), tagNumInUseSessions, tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) + p.recordStat(ctx, ReleasedSessionsCount, 1, tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) + if p.otConfig != nil { + p.recordOTStat(ctx, p.otConfig.releasedSessionsCount, 1, recordOTStatOption{attr: p.otConfig.attributeMapWithoutMultiplexed}) + } +} + +func (p *sessionPool) decNumMultiplexedInUseLocked(ctx context.Context) { + p.recordStat(ctx, ReleasedSessionsCount, 1, tag.Tag{Key: tagKeyIsMultiplexed, Value: "true"}) if p.otConfig != nil { - p.recordOTStat(ctx, p.otConfig.releasedSessionsCount, 1) + p.recordOTStat(ctx, p.otConfig.releasedSessionsCount, 1, recordOTStatOption{attr: p.otConfig.attributeMapWithMultiplexed}) } } @@ -1334,6 +1555,8 @@ type healthChecker struct { pool *sessionPool // sampleInterval is the interval of sampling by the maintainer. sampleInterval time.Duration + // multiplexSessionRefreshInterval is the interval of refreshing multiplexed session. + multiplexSessionRefreshInterval time.Duration // ready is used to signal that maintainer can start running. ready chan struct{} // done is used to signal that health checker should be closed. @@ -1344,18 +1567,19 @@ type healthChecker struct { } // newHealthChecker initializes new instance of healthChecker. -func newHealthChecker(interval time.Duration, workers int, sampleInterval time.Duration, pool *sessionPool) *healthChecker { +func newHealthChecker(interval, multiplexSessionRefreshInterval time.Duration, workers int, sampleInterval time.Duration, pool *sessionPool) *healthChecker { if workers <= 0 { workers = 1 } hc := &healthChecker{ - interval: interval, - workers: workers, - pool: pool, - sampleInterval: sampleInterval, - ready: make(chan struct{}), - done: make(chan struct{}), - maintainerCancel: func() {}, + interval: interval, + multiplexSessionRefreshInterval: multiplexSessionRefreshInterval, + workers: workers, + pool: pool, + sampleInterval: sampleInterval, + ready: make(chan struct{}), + done: make(chan struct{}), + maintainerCancel: func() {}, } hc.waitWorkers.Add(1) go hc.maintainer() @@ -1363,6 +1587,9 @@ func newHealthChecker(interval time.Duration, workers int, sampleInterval time.D hc.waitWorkers.Add(1) go hc.worker(i) } + if hc.pool.enableMultiplexSession { + go hc.multiplexSessionWorker() + } return hc } @@ -1454,14 +1681,17 @@ func (hc *healthChecker) markDone(s *session) { // healthCheck checks the health of the session and pings it if needed. func (hc *healthChecker) healthCheck(s *session) { defer hc.markDone(s) + if s.isMultiplexed { + return + } if !s.pool.isValid() { // Session pool is closed, perform a garbage collection. - s.destroy(false) + s.destroy(false, false) return } if err := s.ping(); isSessionNotFoundError(err) { // Ping failed, destroy the session. - s.destroy(false) + s.destroy(false, false) } } @@ -1543,7 +1773,7 @@ func (hc *healthChecker) maintainer() { now := time.Now() if now.After(hc.pool.lastResetTime.Add(10 * time.Minute)) { hc.pool.maxNumInUse = hc.pool.numInUse - hc.pool.recordStat(context.Background(), MaxInUseSessionsCount, int64(hc.pool.maxNumInUse)) + hc.pool.recordStat(context.Background(), MaxInUseSessionsCount, int64(hc.pool.maxNumInUse), tag.Tag{Key: tagKeyIsMultiplexed, Value: "false"}) hc.pool.lastResetTime = now } hc.pool.mu.Unlock() @@ -1643,13 +1873,43 @@ func (hc *healthChecker) shrinkPool(ctx context.Context, shrinkToNumSessions uin if s != nil { deleted++ // destroy session as expire. - s.destroy(true) + s.destroy(true, false) } else { break } } } +func (hc *healthChecker) multiplexSessionWorker() { + for { + if hc.isClosing() { + return + } + hc.pool.mu.Lock() + createTime := time.Now() + s := hc.pool.multiplexedSession + if s != nil { + createTime = hc.pool.multiplexedSession.createTime + } + hc.pool.mu.Unlock() + ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second) + if createTime.Add(multiplexSessionRefreshInterval).Before(time.Now()) { + // Multiplexed session is idle for more than 7 days, replace it. + hc.pool.multiplexedSessionReq <- muxSessionCreateRequest{force: true, ctx: ctx} + // wait for the new multiplexed session to be created. + <-hc.pool.mayGetMultiplexedSession + } + // Sleep for a while to avoid burning CPU. + select { + case <-time.After(hc.multiplexSessionRefreshInterval): + cancel() + case <-hc.done: + cancel() + return + } + } +} + // maxUint64 returns the maximum of two uint64. func maxUint64(a, b uint64) uint64 { if a > b { @@ -1683,6 +1943,17 @@ func isSessionNotFoundError(err error) bool { return strings.Contains(err.Error(), "Session not found") } +// isUnimplementedError returns true if the gRPC error code is Unimplemented. +func isUnimplementedError(err error) bool { + if err == nil { + return false + } + if ErrCode(err) == codes.Unimplemented { + return true + } + return false +} + func isFailedInlineBeginTransaction(err error) bool { if err == nil { return false diff --git a/vendor/cloud.google.com/go/spanner/sessionclient.go b/vendor/cloud.google.com/go/spanner/sessionclient.go index edbf82a80..e0a56f9af 100644 --- a/vendor/cloud.google.com/go/spanner/sessionclient.go +++ b/vendor/cloud.google.com/go/spanner/sessionclient.go @@ -71,13 +71,13 @@ func (cg *clientIDGenerator) nextID(database string) string { type sessionConsumer interface { // sessionReady is called when a session has been created and is ready for // use. - sessionReady(s *session) + sessionReady(ctx context.Context, s *session) // sessionCreationFailed is called when the creation of a sub-batch of // sessions failed. The numSessions argument specifies the number of // sessions that could not be created as a result of this error. A // consumer may receive multiple errors per batch. - sessionCreationFailed(err error, numSessions int32) + sessionCreationFailed(ctx context.Context, err error, numSessions int32, isMultiplexed bool) } // sessionClient creates sessions for a database, either in batches or one at a @@ -254,12 +254,12 @@ func (sc *sessionClient) executeBatchCreateSessions(client *vkit.Client, createC if closed { err := spannerErrorf(codes.Canceled, "Session client closed") trace.TracePrintf(ctx, nil, "Session client closed while creating a batch of %d sessions: %v", createCount, err) - consumer.sessionCreationFailed(err, remainingCreateCount) + consumer.sessionCreationFailed(ctx, err, remainingCreateCount, false) break } if ctx.Err() != nil { trace.TracePrintf(ctx, nil, "Context error while creating a batch of %d sessions: %v", createCount, ctx.Err()) - consumer.sessionCreationFailed(ToSpannerError(ctx.Err()), remainingCreateCount) + consumer.sessionCreationFailed(ctx, ToSpannerError(ctx.Err()), remainingCreateCount, false) break } var mdForGFELatency metadata.MD @@ -294,13 +294,13 @@ func (sc *sessionClient) executeBatchCreateSessions(client *vkit.Client, createC } if err != nil { trace.TracePrintf(ctx, nil, "Error creating a batch of %d sessions: %v", remainingCreateCount, err) - consumer.sessionCreationFailed(ToSpannerError(err), remainingCreateCount) + consumer.sessionCreationFailed(ctx, ToSpannerError(err), remainingCreateCount, false) break } actuallyCreated := int32(len(response.Session)) trace.TracePrintf(ctx, nil, "Received a batch of %d sessions", actuallyCreated) for _, s := range response.Session { - consumer.sessionReady(&session{valid: true, client: client, id: s.Name, createTime: time.Now(), md: md, logger: sc.logger}) + consumer.sessionReady(ctx, &session{valid: true, client: client, id: s.Name, createTime: time.Now(), md: md, logger: sc.logger}) } if actuallyCreated < remainingCreateCount { // Spanner could return less sessions than requested. In that case, we @@ -313,6 +313,62 @@ func (sc *sessionClient) executeBatchCreateSessions(client *vkit.Client, createC } } +func (sc *sessionClient) executeCreateMultiplexedSession(ctx context.Context, client *vkit.Client, md metadata.MD, consumer sessionConsumer) { + ctx = trace.StartSpan(ctx, "cloud.google.com/go/spanner.CreateSession") + defer func() { trace.EndSpan(ctx, nil) }() + trace.TracePrintf(ctx, nil, "Creating a multiplexed session") + sc.mu.Lock() + closed := sc.closed + sc.mu.Unlock() + if closed { + err := spannerErrorf(codes.Canceled, "Session client closed") + trace.TracePrintf(ctx, nil, "Session client closed while creating a multiplexed session: %v", err) + return + } + if ctx.Err() != nil { + trace.TracePrintf(ctx, nil, "Context error while creating a multiplexed session: %v", ctx.Err()) + consumer.sessionCreationFailed(ctx, ToSpannerError(ctx.Err()), 1, true) + return + } + var mdForGFELatency metadata.MD + response, err := client.CreateSession(contextWithOutgoingMetadata(ctx, sc.md, sc.disableRouteToLeader), &sppb.CreateSessionRequest{ + Database: sc.database, + // Multiplexed sessions do not support labels. + Session: &sppb.Session{CreatorRole: sc.databaseRole, Multiplexed: true}, + }, gax.WithGRPCOptions(grpc.Header(&mdForGFELatency))) + + if getGFELatencyMetricsFlag() && mdForGFELatency != nil { + _, instance, database, err := parseDatabaseName(sc.database) + if err != nil { + trace.TracePrintf(ctx, nil, "Error getting instance and database name: %v", err) + } + // Errors should not prevent initializing the session pool. + ctxGFE, err := tag.New(ctx, + tag.Upsert(tagKeyClientID, sc.id), + tag.Upsert(tagKeyDatabase, database), + tag.Upsert(tagKeyInstance, instance), + tag.Upsert(tagKeyLibVersion, internal.Version), + ) + if err != nil { + trace.TracePrintf(ctx, nil, "Error in adding tags in CreateSession for GFE Latency: %v", err) + } + err = captureGFELatencyStats(ctxGFE, mdForGFELatency, "executeCreateSession") + if err != nil { + trace.TracePrintf(ctx, nil, "Error in Capturing GFE Latency and Header Missing count. Try disabling and rerunning. Error: %v", err) + } + } + if metricErr := recordGFELatencyMetricsOT(ctx, mdForGFELatency, "executeCreateSession", sc.otConfig); metricErr != nil { + trace.TracePrintf(ctx, nil, "Error in recording GFE Latency through OpenTelemetry. Error: %v", metricErr) + } + if err != nil { + trace.TracePrintf(ctx, nil, "Error creating a multiplexed sessions: %v", err) + consumer.sessionCreationFailed(ctx, ToSpannerError(err), 1, true) + return + } + consumer.sessionReady(ctx, &session{valid: true, client: client, id: response.Name, createTime: time.Now(), md: md, logger: sc.logger, isMultiplexed: response.Multiplexed}) + trace.TracePrintf(ctx, nil, "Finished creating multiplexed sessions") +} + func (sc *sessionClient) sessionWithID(id string) (*session, error) { sc.mu.Lock() defer sc.mu.Unlock() @@ -328,9 +384,15 @@ func (sc *sessionClient) sessionWithID(id string) (*session, error) { // session. Using the same channel for all gRPC calls for a session ensures the // optimal usage of server side caches. func (sc *sessionClient) nextClient() (*vkit.Client, error) { - // This call should never return an error as we are passing in an existing - // connection, so we can safely ignore it. - client, err := vkit.NewClient(context.Background(), option.WithGRPCConn(sc.connPool.Conn())) + var clientOpt option.ClientOption + if _, ok := sc.connPool.(*gmeWrapper); ok { + // Pass GCPMultiEndpoint as a pool. + clientOpt = gtransport.WithConnPool(sc.connPool) + } else { + // Pick a grpc.ClientConn from a regular pool. + clientOpt = option.WithGRPCConn(sc.connPool.Conn()) + } + client, err := vkit.NewClient(context.Background(), clientOpt) if err != nil { return nil, err } diff --git a/vendor/cloud.google.com/go/spanner/statement.go b/vendor/cloud.google.com/go/spanner/statement.go index f08af2e77..407036312 100644 --- a/vendor/cloud.google.com/go/spanner/statement.go +++ b/vendor/cloud.google.com/go/spanner/statement.go @@ -20,9 +20,9 @@ import ( "fmt" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - proto3 "github.com/golang/protobuf/ptypes/struct" - structpb "github.com/golang/protobuf/ptypes/struct" "google.golang.org/grpc/codes" + proto3 "google.golang.org/protobuf/types/known/structpb" + structpb "google.golang.org/protobuf/types/known/structpb" ) // A Statement is a SQL query with named parameters. diff --git a/vendor/cloud.google.com/go/spanner/stats.go b/vendor/cloud.google.com/go/spanner/stats.go index 8e77ecf3d..bc8176b6d 100644 --- a/vendor/cloud.google.com/go/spanner/stats.go +++ b/vendor/cloud.google.com/go/spanner/stats.go @@ -31,12 +31,14 @@ const statsPrefix = "cloud.google.com/go/spanner/" // Deprecated: OpenCensus project is deprecated. Use OpenTelemetry for capturing metrics. var ( - tagKeyClientID = tag.MustNewKey("client_id") - tagKeyDatabase = tag.MustNewKey("database") - tagKeyInstance = tag.MustNewKey("instance_id") - tagKeyLibVersion = tag.MustNewKey("library_version") - tagKeyType = tag.MustNewKey("type") - tagCommonKeys = []tag.Key{tagKeyClientID, tagKeyDatabase, tagKeyInstance, tagKeyLibVersion} + tagKeyClientID = tag.MustNewKey("client_id") + tagKeyDatabase = tag.MustNewKey("database") + tagKeyInstance = tag.MustNewKey("instance_id") + tagKeyLibVersion = tag.MustNewKey("library_version") + tagKeyType = tag.MustNewKey("type") + tagKeyIsMultiplexed = tag.MustNewKey("is_multiplexed") + + tagCommonKeys = []tag.Key{tagKeyClientID, tagKeyDatabase, tagKeyInstance, tagKeyLibVersion} tagNumInUseSessions = tag.Tag{Key: tagKeyType, Value: "num_in_use_sessions"} tagNumSessions = tag.Tag{Key: tagKeyType, Value: "num_sessions"} diff --git a/vendor/cloud.google.com/go/spanner/timestampbound.go b/vendor/cloud.google.com/go/spanner/timestampbound.go index f488b2994..00a1396a1 100644 --- a/vendor/cloud.google.com/go/spanner/timestampbound.go +++ b/vendor/cloud.google.com/go/spanner/timestampbound.go @@ -21,8 +21,8 @@ import ( "time" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - pbd "github.com/golang/protobuf/ptypes/duration" - pbt "github.com/golang/protobuf/ptypes/timestamp" + pbd "google.golang.org/protobuf/types/known/durationpb" + pbt "google.golang.org/protobuf/types/known/timestamppb" ) // timestampBoundType specifies the timestamp bound mode. diff --git a/vendor/cloud.google.com/go/spanner/transaction.go b/vendor/cloud.google.com/go/spanner/transaction.go index 79427e782..f251adca1 100644 --- a/vendor/cloud.google.com/go/spanner/transaction.go +++ b/vendor/cloud.google.com/go/spanner/transaction.go @@ -24,13 +24,13 @@ import ( "cloud.google.com/go/internal/trace" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - "github.com/golang/protobuf/proto" "github.com/googleapis/gax-go/v2" "google.golang.org/api/iterator" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/metadata" "google.golang.org/grpc/status" + "google.golang.org/protobuf/proto" vkit "cloud.google.com/go/spanner/apiv1" durationpb "google.golang.org/protobuf/types/known/durationpb" @@ -115,15 +115,20 @@ type TransactionOptions struct { // the transaction lock mode is used to specify a concurrency mode for the // read/query operations. It works for a read/write transaction only. ReadLockMode sppb.TransactionOptions_ReadWrite_ReadLockMode + + // Controls whether to exclude recording modifications in current transaction + // from the allowed tracking change streams(with DDL option allow_txn_exclusion=true). + ExcludeTxnFromChangeStreams bool } // merge combines two TransactionOptions that the input parameter will have higher // order of precedence. func (to TransactionOptions) merge(opts TransactionOptions) TransactionOptions { merged := TransactionOptions{ - CommitOptions: to.CommitOptions.merge(opts.CommitOptions), - TransactionTag: to.TransactionTag, - CommitPriority: to.CommitPriority, + CommitOptions: to.CommitOptions.merge(opts.CommitOptions), + TransactionTag: to.TransactionTag, + CommitPriority: to.CommitPriority, + ExcludeTxnFromChangeStreams: to.ExcludeTxnFromChangeStreams || opts.ExcludeTxnFromChangeStreams, } if opts.TransactionTag != "" { merged.TransactionTag = opts.TransactionTag @@ -177,6 +182,13 @@ type ReadOptions struct { // ReadOptions option used to set the DirectedReadOptions for all ReadRequests which indicate // which replicas or regions should be used for running read operations. DirectedReadOptions *sppb.DirectedReadOptions + + // An option to control the order in which rows are returned from a read. + OrderBy sppb.ReadRequest_OrderBy + + // A lock hint mechanism to use for this request. This setting is only applicable for + // read-write transaction as as read-only transactions do not take locks. + LockHint sppb.ReadRequest_LockHint } // merge combines two ReadOptions that the input parameter will have higher @@ -189,6 +201,8 @@ func (ro ReadOptions) merge(opts ReadOptions) ReadOptions { RequestTag: ro.RequestTag, DataBoostEnabled: ro.DataBoostEnabled, DirectedReadOptions: ro.DirectedReadOptions, + OrderBy: ro.OrderBy, + LockHint: ro.LockHint, } if opts.Index != "" { merged.Index = opts.Index @@ -208,6 +222,12 @@ func (ro ReadOptions) merge(opts ReadOptions) ReadOptions { if opts.DirectedReadOptions != nil { merged.DirectedReadOptions = opts.DirectedReadOptions } + if opts.OrderBy != sppb.ReadRequest_ORDER_BY_UNSPECIFIED { + merged.OrderBy = opts.OrderBy + } + if opts.LockHint != sppb.ReadRequest_LOCK_HINT_UNSPECIFIED { + merged.LockHint = opts.LockHint + } return merged } @@ -240,6 +260,8 @@ func (t *txReadOnly) ReadWithOptions(ctx context.Context, table string, keys Key requestTag := t.ro.RequestTag dataBoostEnabled := t.ro.DataBoostEnabled directedReadOptions := t.ro.DirectedReadOptions + orderBy := t.ro.OrderBy + lockHint := t.ro.LockHint if opts != nil { index = opts.Index if opts.Limit > 0 { @@ -253,6 +275,13 @@ func (t *txReadOnly) ReadWithOptions(ctx context.Context, table string, keys Key if opts.DirectedReadOptions != nil { directedReadOptions = opts.DirectedReadOptions } + if opts.OrderBy != sppb.ReadRequest_ORDER_BY_UNSPECIFIED { + orderBy = opts.OrderBy + } + if opts.LockHint != sppb.ReadRequest_LOCK_HINT_UNSPECIFIED { + lockHint = opts.LockHint + } + } var setTransactionID func(transactionID) if _, ok := ts.Selector.(*sppb.TransactionSelector_Begin); ok { @@ -280,6 +309,8 @@ func (t *txReadOnly) ReadWithOptions(ctx context.Context, table string, keys Key RequestOptions: createRequestOptions(prio, requestTag, t.txOpts.TransactionTag), DataBoostEnabled: dataBoostEnabled, DirectedReadOptions: directedReadOptions, + OrderBy: orderBy, + LockHint: lockHint, }) if err != nil { if _, ok := t.getTransactionSelector().GetSelector().(*sppb.TransactionSelector_Begin); ok { @@ -309,12 +340,16 @@ func (t *txReadOnly) ReadWithOptions(ctx context.Context, table string, keys Key // errRowNotFound returns error for not being able to read the row identified by // key. func errRowNotFound(table string, key Key) error { - return spannerErrorf(codes.NotFound, "row not found(Table: %v, PrimaryKey: %v)", table, key) + err := spannerErrorf(codes.NotFound, "row not found(Table: %v, PrimaryKey: %v)", table, key) + err.(*Error).err = ErrRowNotFound + return err } // errRowNotFoundByIndex returns error for not being able to read the row by index. func errRowNotFoundByIndex(table string, key Key, index string) error { - return spannerErrorf(codes.NotFound, "row not found(Table: %v, IndexKey: %v, Index: %v)", table, key, index) + err := spannerErrorf(codes.NotFound, "row not found(Table: %v, IndexKey: %v, Index: %v)", table, key, index) + err.(*Error).err = ErrRowNotFound + return err } // errMultipleRowsFound returns error for receiving more than one row when reading a single row using an index. @@ -329,8 +364,14 @@ func errInlineBeginTransactionFailed() error { // ReadRow reads a single row from the database. // -// If no row is present with the given key, then ReadRow returns an error where +// If no row is present with the given key, then ReadRow returns an error(spanner.ErrRowNotFound) where // spanner.ErrCode(err) is codes.NotFound. +// +// To check if the error is spanner.ErrRowNotFound: +// +// if errors.Is(err, spanner.ErrRowNotFound) { +// ... +// } func (t *txReadOnly) ReadRow(ctx context.Context, table string, key Key, columns []string) (*Row, error) { return t.ReadRowWithOptions(ctx, table, key, columns, nil) } @@ -339,6 +380,12 @@ func (t *txReadOnly) ReadRow(ctx context.Context, table string, key Key, columns // // If no row is present with the given key, then ReadRowWithOptions returns an error where // spanner.ErrCode(err) is codes.NotFound. +// +// To check if the error is spanner.ErrRowNotFound: +// +// if errors.Is(err, spanner.ErrRowNotFound) { +// ... +// } func (t *txReadOnly) ReadRowWithOptions(ctx context.Context, table string, key Key, columns []string, opts *ReadOptions) (*Row, error) { iter := t.ReadWithOptions(ctx, table, key, columns, opts) defer iter.Stop() @@ -356,7 +403,13 @@ func (t *txReadOnly) ReadRowWithOptions(ctx context.Context, table string, key K // ReadRowUsingIndex reads a single row from the database using an index. // // If no row is present with the given index, then ReadRowUsingIndex returns an -// error where spanner.ErrCode(err) is codes.NotFound. +// error(spanner.ErrRowNotFound) where spanner.ErrCode(err) is codes.NotFound. +// +// To check if the error is spanner.ErrRowNotFound: +// +// if errors.Is(err, spanner.ErrRowNotFound) { +// ... +// } // // If more than one row received with the given index, then ReadRowUsingIndex // returns an error where spanner.ErrCode(err) is codes.FailedPrecondition. @@ -401,18 +454,24 @@ type QueryOptions struct { // QueryOptions option used to set the DirectedReadOptions for all ExecuteSqlRequests which indicate // which replicas or regions should be used for executing queries. DirectedReadOptions *sppb.DirectedReadOptions + + // Controls whether to exclude recording modifications in current partitioned update operation + // from the allowed tracking change streams(with DDL option allow_txn_exclusion=true). Setting + // this value for any sql/dml requests other than partitioned udpate will receive an error. + ExcludeTxnFromChangeStreams bool } // merge combines two QueryOptions that the input parameter will have higher // order of precedence. func (qo QueryOptions) merge(opts QueryOptions) QueryOptions { merged := QueryOptions{ - Mode: qo.Mode, - Options: &sppb.ExecuteSqlRequest_QueryOptions{}, - RequestTag: qo.RequestTag, - Priority: qo.Priority, - DataBoostEnabled: qo.DataBoostEnabled, - DirectedReadOptions: qo.DirectedReadOptions, + Mode: qo.Mode, + Options: &sppb.ExecuteSqlRequest_QueryOptions{}, + RequestTag: qo.RequestTag, + Priority: qo.Priority, + DataBoostEnabled: qo.DataBoostEnabled, + DirectedReadOptions: qo.DirectedReadOptions, + ExcludeTxnFromChangeStreams: qo.ExcludeTxnFromChangeStreams || opts.ExcludeTxnFromChangeStreams, } if opts.Mode != nil { merged.Mode = opts.Mode @@ -622,6 +681,13 @@ func errUnexpectedTxState(ts txState) error { return spannerErrorf(codes.FailedPrecondition, "unexpected transaction state: %v", ts) } +// errExcludeRequestLevelDmlFromChangeStreams returns error for passing +// QueryOptions.ExcludeTxnFromChangeStreams to request-level DML functions. This +// options should only be used for partitioned update. +func errExcludeRequestLevelDmlFromChangeStreams() error { + return spannerErrorf(codes.InvalidArgument, "cannot set exclude transaction from change streams for a request-level DML statement.") +} + // ReadOnlyTransaction provides a snapshot transaction with guaranteed // consistency across reads, but does not allow writes. Read-only transactions // can be configured to read at timestamps in the past. @@ -710,7 +776,7 @@ func (t *ReadOnlyTransaction) begin(ctx context.Context) error { }() // Retry the BeginTransaction call if a 'Session not found' is returned. for { - sh, err = t.sp.take(ctx) + sh, err = t.sp.takeMultiplexed(ctx) if err != nil { return err } @@ -800,7 +866,7 @@ func (t *ReadOnlyTransaction) acquireSingleUse(ctx context.Context) (*sessionHan }, }, } - sh, err := t.sp.take(ctx) + sh, err := t.sp.takeMultiplexed(ctx) if err != nil { return nil, nil, err } @@ -1104,6 +1170,10 @@ func (t *ReadWriteTransaction) Update(ctx context.Context, stmt Statement) (rowC // the number of affected rows. The given QueryOptions will be used for the // execution of this statement. func (t *ReadWriteTransaction) UpdateWithOptions(ctx context.Context, stmt Statement, opts QueryOptions) (rowCount int64, err error) { + if opts.ExcludeTxnFromChangeStreams { + return 0, errExcludeRequestLevelDmlFromChangeStreams() + } + return t.update(ctx, stmt, t.qo.merge(opts)) } @@ -1176,6 +1246,9 @@ func (t *ReadWriteTransaction) BatchUpdate(ctx context.Context, stmts []Statemen // The request tag and priority given in the QueryOptions are included with the // RPC. Any other options that are set in the QueryOptions struct are ignored. func (t *ReadWriteTransaction) BatchUpdateWithOptions(ctx context.Context, stmts []Statement, opts QueryOptions) (_ []int64, err error) { + if opts.ExcludeTxnFromChangeStreams { + return nil, errExcludeRequestLevelDmlFromChangeStreams() + } return t.batchUpdateWithOptions(ctx, stmts, t.qo.merge(opts)) } @@ -1296,6 +1369,7 @@ func (t *ReadWriteTransaction) acquire(ctx context.Context) (*sessionHandle, *sp Mode: &sppb.TransactionOptions_ReadWrite_{ ReadWrite: &sppb.TransactionOptions_ReadWrite{}, }, + ExcludeTxnFromChangeStreams: t.txOpts.ExcludeTxnFromChangeStreams, }, }, } @@ -1355,6 +1429,7 @@ func (t *ReadWriteTransaction) getTransactionSelector() *sppb.TransactionSelecto ReadLockMode: t.txOpts.ReadLockMode, }, }, + ExcludeTxnFromChangeStreams: t.txOpts.ExcludeTxnFromChangeStreams, }, }, } @@ -1411,6 +1486,7 @@ func beginTransaction(ctx context.Context, sid string, client *vkit.Client, opts ReadLockMode: opts.ReadLockMode, }, }, + ExcludeTxnFromChangeStreams: opts.ExcludeTxnFromChangeStreams, }, }) if err != nil { @@ -1716,6 +1792,7 @@ func NewReadWriteStmtBasedTransactionWithOptions(ctx context.Context, c *Client, txReadyOrClosed: make(chan struct{}), }, } + t.txReadOnly.sp = c.idleSessions t.txReadOnly.sh = sh t.txReadOnly.txReadEnv = t t.txReadOnly.qo = c.qo @@ -1778,6 +1855,12 @@ type writeOnlyTransaction struct { commitPriority sppb.RequestOptions_Priority // disableRouteToLeader specifies if we want to disable RW/PDML requests to be routed to leader. disableRouteToLeader bool + // ExcludeTxnFromChangeStreams controls whether to exclude recording modifications in + // current transaction from the allowed tracking change streams with DDL option + // allow_txn_exclusion=true. + excludeTxnFromChangeStreams bool + // commitOptions are applied to the Commit request for the writeOnlyTransaction.. + commitOptions CommitOptions } // applyAtLeastOnce commits a list of mutations to Cloud Spanner at least once, @@ -1802,6 +1885,11 @@ func (t *writeOnlyTransaction) applyAtLeastOnce(ctx context.Context, ms ...*Muta return ts, err } + var maxCommitDelay *durationpb.Duration + if t.commitOptions.MaxCommitDelay != nil { + maxCommitDelay = durationpb.New(*(t.commitOptions.MaxCommitDelay)) + } + // Make a retryer for Aborted and certain Internal errors. retryer := onCodes(DefaultRetryBackoff, codes.Aborted, codes.Internal) // Apply the mutation and retry if the commit is aborted. @@ -1809,7 +1897,7 @@ func (t *writeOnlyTransaction) applyAtLeastOnce(ctx context.Context, ms ...*Muta for { if sh == nil || sh.getID() == "" || sh.getClient() == nil { // No usable session for doing the commit, take one from pool. - sh, err = t.sp.take(ctx) + sh, err = t.sp.takeMultiplexed(ctx) if err != nil { // sessionPool.Take already retries for session // creations/retrivals. @@ -1824,12 +1912,15 @@ func (t *writeOnlyTransaction) applyAtLeastOnce(ctx context.Context, ms ...*Muta Mode: &sppb.TransactionOptions_ReadWrite_{ ReadWrite: &sppb.TransactionOptions_ReadWrite{}, }, + ExcludeTxnFromChangeStreams: t.excludeTxnFromChangeStreams, }, }, Mutations: mPb, RequestOptions: createRequestOptions(t.commitPriority, "", t.transactionTag), + MaxCommitDelay: maxCommitDelay, }) if err != nil && !isAbortedErr(err) { + // should not be the case with multiplexed sessions if isSessionNotFoundError(err) { // Discard the bad session. sh.destroy() diff --git a/vendor/cloud.google.com/go/spanner/value.go b/vendor/cloud.google.com/go/spanner/value.go index 1d4e4ea67..b25867874 100644 --- a/vendor/cloud.google.com/go/spanner/value.go +++ b/vendor/cloud.google.com/go/spanner/value.go @@ -21,6 +21,7 @@ import ( "database/sql" "database/sql/driver" "encoding/base64" + "encoding/json" "fmt" "math" "math/big" @@ -32,10 +33,11 @@ import ( "cloud.google.com/go/civil" "cloud.google.com/go/internal/fields" sppb "cloud.google.com/go/spanner/apiv1/spannerpb" - "github.com/golang/protobuf/proto" - proto3 "github.com/golang/protobuf/ptypes/struct" - jsoniter "github.com/json-iterator/go" "google.golang.org/grpc/codes" + "google.golang.org/protobuf/proto" + "google.golang.org/protobuf/protoadapt" + "google.golang.org/protobuf/reflect/protoreflect" + proto3 "google.golang.org/protobuf/types/known/structpb" ) const ( @@ -114,7 +116,10 @@ var ( jsonNullBytes = []byte("null") - jsonProvider = jsoniter.ConfigCompatibleWithStandardLibrary + jsonUseNumber bool + + protoMsgReflectType = reflect.TypeOf((*proto.Message)(nil)).Elem() + protoEnumReflectType = reflect.TypeOf((*protoreflect.Enum)(nil)).Elem() ) // UseNumberWithJSONDecoderEncoder specifies whether Cloud Spanner JSON numbers are decoded @@ -124,11 +129,15 @@ var ( // NOTE 1: Calling this method affects the behavior of all clients created by this library, both existing and future instances. // NOTE 2: This method sets a global variable that is used by the client to encode/decode JSON numbers. Access to the global variable is not synchronized. You should only call this method when there are no goroutines encoding/decoding Cloud Spanner JSON values. It is recommended to only call this method during the initialization of your application, and preferably before you create any Cloud Spanner clients, and/or in tests when there are no queries being executed. func UseNumberWithJSONDecoderEncoder(useNumber bool) { - jsonProvider = jsoniter.Config{ - EscapeHTML: true, - SortMapKeys: true, // Sort map keys to ensure deterministic output, to be consistent with encoding. - UseNumber: useNumber, - }.Froze() + jsonUseNumber = useNumber +} + +func jsonUnmarshal(data []byte, v any) error { + dec := json.NewDecoder(bytes.NewReader(data)) + if jsonUseNumber { + dec.UseNumber() + } + return dec.Decode(v) } // Encoder is the interface implemented by a custom type that can be encoded to @@ -297,7 +306,7 @@ func (n *NullString) UnmarshalJSON(payload []byte) error { return nil } var s *string - if err := jsonProvider.Unmarshal(payload, &s); err != nil { + if err := jsonUnmarshal(payload, &s); err != nil { return err } if s != nil { @@ -866,7 +875,7 @@ func (n NullJSON) String() string { if !n.Valid { return nullString } - b, err := jsonProvider.Marshal(n.Value) + b, err := json.Marshal(n.Value) if err != nil { return fmt.Sprintf("error: %v", err) } @@ -888,7 +897,7 @@ func (n *NullJSON) UnmarshalJSON(payload []byte) error { return nil } var v interface{} - err := jsonProvider.Unmarshal(payload, &v) + err := jsonUnmarshal(payload, &v) if err != nil { return fmt.Errorf("payload cannot be converted to a struct: got %v, err: %w", string(payload), err) } @@ -945,6 +954,102 @@ func (n *PGNumeric) UnmarshalJSON(payload []byte) error { return nil } +// NullProtoMessage represents a Cloud Spanner PROTO that may be NULL. +// To write a NULL value using NullProtoMessage set ProtoMessageVal to typed nil and set Valid to true. +type NullProtoMessage struct { + ProtoMessageVal proto.Message // ProtoMessageVal contains the value when Valid is true, and nil when NULL. + Valid bool // Valid is true if ProtoMessageVal is not NULL. +} + +// IsNull implements NullableValue.IsNull for NullProtoMessage. +func (n NullProtoMessage) IsNull() bool { + return !n.Valid +} + +// String implements Stringer.String for NullProtoMessage. +func (n NullProtoMessage) String() string { + if !n.Valid { + return nullString + } + return protoadapt.MessageV1Of(n.ProtoMessageVal).String() +} + +// MarshalJSON implements json.Marshaler.MarshalJSON for NullProtoMessage. +func (n NullProtoMessage) MarshalJSON() ([]byte, error) { + if n.Valid { + return json.Marshal(n.ProtoMessageVal) + } + return jsonNullBytes, nil +} + +// UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullProtoMessage. +func (n *NullProtoMessage) UnmarshalJSON(payload []byte) error { + if payload == nil { + return fmt.Errorf("payload should not be nil") + } + if bytes.Equal(payload, jsonNullBytes) { + n.ProtoMessageVal = nil + n.Valid = false + return nil + } + err := jsonUnmarshal(payload, n.ProtoMessageVal) + if err != nil { + return fmt.Errorf("payload cannot be converted to a proto message: err: %s", err) + } + n.Valid = true + return nil +} + +// NullProtoEnum represents a Cloud Spanner ENUM that may be NULL. +// To write a NULL value using NullProtoEnum set ProtoEnumVal to typed nil and set Valid to true. +type NullProtoEnum struct { + ProtoEnumVal protoreflect.Enum // ProtoEnumVal contains the value when Valid is true, and nil when NULL. + Valid bool // Valid is true if ProtoEnumVal is not NULL. +} + +// IsNull implements NullableValue.IsNull for NullProtoEnum. +func (n NullProtoEnum) IsNull() bool { + return !n.Valid +} + +// String implements Stringer.String for NullProtoEnum. +func (n NullProtoEnum) String() string { + if !n.Valid { + return nullString + } + return fmt.Sprintf("%v", n.ProtoEnumVal) +} + +// MarshalJSON implements json.Marshaler.MarshalJSON for NullProtoEnum. +func (n NullProtoEnum) MarshalJSON() ([]byte, error) { + if n.Valid && n.ProtoEnumVal != nil { + return []byte(fmt.Sprintf("%v", n.ProtoEnumVal.Number())), nil + } + return jsonNullBytes, nil +} + +// UnmarshalJSON implements json.Unmarshaler.UnmarshalJSON for NullProtoEnum. +func (n *NullProtoEnum) UnmarshalJSON(payload []byte) error { + if payload == nil { + return fmt.Errorf("payload should not be nil") + } + if bytes.Equal(payload, jsonNullBytes) { + n.ProtoEnumVal = nil + n.Valid = false + return nil + } + if reflect.ValueOf(n.ProtoEnumVal).Kind() != reflect.Ptr { + return errNotAPointerField(n, n.ProtoEnumVal) + } + num, err := strconv.ParseInt(string(payload), 10, 64) + if err != nil { + return fmt.Errorf("payload cannot be converted to Enum: got %v", string(payload)) + } + reflect.ValueOf(n.ProtoEnumVal).Elem().SetInt(num) + n.Valid = true + return nil +} + // NullRow represents a Cloud Spanner STRUCT that may be NULL. // See also the document for Row. // Note that NullRow is not a valid Cloud Spanner column Type. @@ -972,7 +1077,7 @@ func (n PGJsonB) String() string { if !n.Valid { return nullString } - b, err := jsonProvider.Marshal(n.Value) + b, err := json.Marshal(n.Value) if err != nil { return fmt.Sprintf("error: %v", err) } @@ -994,7 +1099,7 @@ func (n *PGJsonB) UnmarshalJSON(payload []byte) error { return nil } var v interface{} - err := jsonProvider.Unmarshal(payload, &v) + err := jsonUnmarshal(payload, &v) if err != nil { return fmt.Errorf("payload cannot be converted to a struct: got %v, err: %w", string(payload), err) } @@ -1007,7 +1112,7 @@ func nulljson(valid bool, v interface{}) ([]byte, error) { if !valid { return jsonNullBytes, nil } - return jsonProvider.Marshal(v) + return json.Marshal(v) } // GenericColumnValue represents the generic encoded value and type of the @@ -1063,12 +1168,22 @@ func errNilDst(dst interface{}) error { return spannerErrorf(codes.InvalidArgument, "cannot decode into nil type %T", dst) } +// errNilDstField returns error for decoding into nil interface{} of Value field in NullProtoMessage or NullProtoEnum. +func errNilDstField(dst interface{}, field string) error { + return spannerErrorf(codes.InvalidArgument, "field %s in %T cannot be nil", field, dst) +} + // errNilArrElemType returns error for input Cloud Spanner data type being a array but without a // non-nil array element type. func errNilArrElemType(t *sppb.Type) error { return spannerErrorf(codes.FailedPrecondition, "array type %v is with nil array element type", t) } +// errNotValidSrc returns error if Valid field is false for NullProtoMessage and NullProtoEnum +func errNotValidSrc(dst interface{}) error { + return spannerErrorf(codes.InvalidArgument, "field \"Valid\" of %T cannot be set to false when writing data to Cloud Spanner. Use typed nil in %T to write null values to Cloud Spanner", dst, dst) +} + func errUnsupportedEmbeddedStructFields(fname string) error { return spannerErrorf(codes.InvalidArgument, "Embedded field: %s. Embedded and anonymous fields are not allowed "+ "when converting Go structs to Cloud Spanner STRUCT values. To create a STRUCT value with an "+ @@ -1086,6 +1201,20 @@ func errBadEncoding(v *proto3.Value, err error) error { return spannerErrorf(codes.FailedPrecondition, "%v wasn't correctly encoded: <%v>", v, err) } +// errNotAPointer returns error for decoding a non pointer type. +func errNotAPointer(dst interface{}) error { + return spannerErrorf(codes.InvalidArgument, "destination %T must be a pointer", dst) +} + +// errNotAPointerField returns error for decoding a non pointer type. +func errNotAPointerField(dst interface{}, dstField interface{}) error { + return spannerErrorf(codes.InvalidArgument, "destination %T in %T must be a pointer", dstField, dst) +} + +func errNilNotAllowed(dst interface{}, name string) error { + return spannerErrorf(codes.InvalidArgument, "destination %T does not support Null values. Use %s, an array with pointer type elements to read Null values", dst, name) +} + func parseNullTime(v *proto3.Value, p *NullTime, code sppb.TypeCode, isNull bool) error { if p == nil { return errNilDst(p) @@ -1246,7 +1375,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO if p == nil { return errNilDst(p) } - if code != sppb.TypeCode_BYTES { + if code != sppb.TypeCode_BYTES && code != sppb.TypeCode_PROTO { return errTypeMismatch(code, acode, ptr) } if isNull { @@ -1266,7 +1395,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO if p == nil { return errNilDst(p) } - if acode != sppb.TypeCode_BYTES { + if acode != sppb.TypeCode_BYTES && acode != sppb.TypeCode_PROTO { return errTypeMismatch(code, acode, ptr) } if isNull { @@ -1286,7 +1415,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO if p == nil { return errNilDst(p) } - if code != sppb.TypeCode_INT64 { + if code != sppb.TypeCode_INT64 && code != sppb.TypeCode_ENUM { return errTypeMismatch(code, acode, ptr) } if isNull { @@ -1305,7 +1434,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO if p == nil { return errNilDst(p) } - if code != sppb.TypeCode_INT64 { + if code != sppb.TypeCode_INT64 && code != sppb.TypeCode_ENUM { return errTypeMismatch(code, acode, ptr) } if isNull { @@ -1336,7 +1465,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO if p == nil { return errNilDst(p) } - if acode != sppb.TypeCode_INT64 { + if acode != sppb.TypeCode_INT64 && acode != sppb.TypeCode_ENUM { return errTypeMismatch(code, acode, ptr) } if isNull { @@ -1370,7 +1499,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO if p == nil { return errNilDst(p) } - if acode != sppb.TypeCode_INT64 { + if acode != sppb.TypeCode_INT64 && acode != sppb.TypeCode_ENUM { return errTypeMismatch(code, acode, ptr) } if isNull { @@ -1714,7 +1843,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO } x := v.GetStringValue() var y interface{} - err := jsonProvider.Unmarshal([]byte(x), &y) + err := jsonUnmarshal([]byte(x), &y) if err != nil { return err } @@ -1873,7 +2002,7 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO } x := v.GetStringValue() var y interface{} - err := jsonProvider.Unmarshal([]byte(x), &y) + err := jsonUnmarshal([]byte(x), &y) if err != nil { return err } @@ -2104,6 +2233,94 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO *p = y case *GenericColumnValue: *p = GenericColumnValue{Type: t, Value: v} + case protoreflect.Enum: + if p == nil { + return errNilDst(p) + } + if reflect.ValueOf(p).Kind() != reflect.Ptr { + return errNotAPointer(p) + } + if code != sppb.TypeCode_ENUM && code != sppb.TypeCode_INT64 { + return errTypeMismatch(code, acode, ptr) + } + if isNull { + return errDstNotForNull(ptr) + } + y, err := getIntegerFromStringValue(v) + if err != nil { + return err + } + reflect.ValueOf(p).Elem().SetInt(y) + case *NullProtoEnum: + if p == nil { + return errNilDst(p) + } + if p.ProtoEnumVal == nil { + return errNilDstField(p, "ProtoEnumVal") + } + if reflect.ValueOf(p.ProtoEnumVal).Kind() != reflect.Ptr { + return errNotAPointer(p) + } + if code != sppb.TypeCode_ENUM && code != sppb.TypeCode_INT64 { + return errTypeMismatch(code, acode, ptr) + } + if isNull { + *p = NullProtoEnum{} + break + } + y, err := getIntegerFromStringValue(v) + if err != nil { + return err + } + reflect.ValueOf(p.ProtoEnumVal).Elem().SetInt(y) + p.Valid = true + case proto.Message: + if p == nil { + return errNilDst(p) + } + if reflect.ValueOf(p).Kind() != reflect.Ptr { + return errNotAPointer(p) + } + if code != sppb.TypeCode_PROTO && code != sppb.TypeCode_BYTES { + return errTypeMismatch(code, acode, ptr) + } + if isNull { + return errDstNotForNull(ptr) + } + y, err := getBytesFromStringValue(v) + if err != nil { + return err + } + err = proto.Unmarshal(y, p) + if err != nil { + return err + } + case *NullProtoMessage: + if p == nil { + return errNilDst(p) + } + if p.ProtoMessageVal == nil { + return errNilDstField(p, "ProtoMessageVal") + } + if reflect.ValueOf(p.ProtoMessageVal).Kind() != reflect.Ptr { + return errNotAPointer(p.ProtoMessageVal) + } + if code != sppb.TypeCode_PROTO && code != sppb.TypeCode_BYTES { + return errTypeMismatch(code, acode, ptr) + } + if isNull { + *p = NullProtoMessage{} + break + } + y, err := getBytesFromStringValue(v) + if err != nil { + return err + } + err = proto.Unmarshal(y, p.ProtoMessageVal) + if err != nil { + return err + } + p.Valid = true default: // Check if the pointer is a custom type that implements spanner.Decoder // interface. @@ -2124,6 +2341,42 @@ func decodeValue(v *proto3.Value, t *sppb.Type, ptr interface{}, opts ...DecodeO return decodableType.decodeValueToCustomType(v, t, acode, atypeAnnotation, ptr) } + rv := reflect.ValueOf(ptr) + typ := rv.Type() + // Check if the interface{} is a pointer and is of type array of proto columns + if typ.Kind() == reflect.Ptr && isAnArrayOfProtoColumn(ptr) && code == sppb.TypeCode_ARRAY { + if isNull { + rv.Elem().Set(reflect.Zero(rv.Elem().Type())) + break + } + // Get the user-defined type of the proto array + etyp := typ.Elem().Elem() + switch acode { + case sppb.TypeCode_PROTO, sppb.TypeCode_BYTES: + if etyp.Implements(protoMsgReflectType) { + if etyp.Kind() == reflect.Ptr { + x, err := getListValue(v) + if err != nil { + return err + } + return decodeProtoMessagePtrArray(x, t.ArrayElementType, rv) + } + return errTypeMismatch(code, acode, ptr) + } + case sppb.TypeCode_ENUM, sppb.TypeCode_INT64: + if etyp.Implements(protoEnumReflectType) { + x, err := getListValue(v) + if err != nil { + return err + } + if etyp.Kind() == reflect.Ptr { + return decodeProtoEnumPtrArray(x, t.ArrayElementType, rv) + } + return decodeProtoEnumArray(x, t.ArrayElementType, rv, ptr) + } + } + } + // Check if the proto encoding is for an array of structs. if !(code == sppb.TypeCode_ARRAY && acode == sppb.TypeCode_STRUCT) { return errTypeMismatch(code, acode, ptr) @@ -2566,7 +2819,7 @@ func (dsc decodableSpannerType) decodeValueToCustomType(v *proto3.Value, t *sppb } x := v.GetStringValue() var y interface{} - err := jsonProvider.Unmarshal([]byte(x), &y) + err := jsonUnmarshal([]byte(x), &y) if err != nil { return err } @@ -2581,7 +2834,7 @@ func (dsc decodableSpannerType) decodeValueToCustomType(v *proto3.Value, t *sppb } x := v.GetStringValue() var y interface{} - err := jsonProvider.Unmarshal([]byte(x), &y) + err := jsonUnmarshal([]byte(x), &y) if err != nil { return err } @@ -2838,6 +3091,32 @@ func errSrcVal(v *proto3.Value, want string) error { v, v.GetKind(), want) } +// getIntegerFromStringValue returns the integer value of the string value encoded in proto3.Value v +func getIntegerFromStringValue(v *proto3.Value) (int64, error) { + x, err := getStringValue(v) + if err != nil { + return 0, err + } + y, err := strconv.ParseInt(x, 10, 64) + if err != nil { + return 0, errBadEncoding(v, err) + } + return y, nil +} + +// getBytesFromStringValue returns the bytes value of the string value encoded in proto3.Value v +func getBytesFromStringValue(v *proto3.Value) ([]byte, error) { + x, err := getStringValue(v) + if err != nil { + return nil, err + } + y, err := base64.StdEncoding.DecodeString(x) + if err != nil { + return nil, errBadEncoding(v, err) + } + return y, nil +} + // getStringValue returns the string value encoded in proto3.Value v whose // kind is proto3.Value_StringValue. func getStringValue(v *proto3.Value) (string, error) { @@ -3272,7 +3551,7 @@ func decodeNullJSONArrayToNullJSON(pb *proto3.ListValue) (*NullJSON, error) { } s := fmt.Sprintf("[%s]", strings.Join(strs, ",")) var y interface{} - err := jsonProvider.Unmarshal([]byte(s), &y) + err := jsonUnmarshal([]byte(s), &y) if err != nil { return nil, err } @@ -3335,6 +3614,83 @@ func decodeByteArray(pb *proto3.ListValue) ([][]byte, error) { return a, nil } +// decodeProtoMessagePtrArray decodes proto3.ListValue pb into a *proto.Message slice. +// The elements in the array implements proto.Message interface only if the element is a pointer (e.g. *ProtoMessage). +// However, if the element is a value (e.g. ProtoMessage), then it does not implement proto.Message. +// Therefore, decodeProtoMessagePtrArray allows decoding of proto message array if the array element is a pointer only. +func decodeProtoMessagePtrArray(pb *proto3.ListValue, t *sppb.Type, rv reflect.Value) error { + if pb == nil { + return errNilListValue("PROTO") + } + etyp := rv.Type().Elem().Elem().Elem() + a := reflect.MakeSlice(rv.Type().Elem(), len(pb.Values), len(pb.Values)) + for i, v := range pb.Values { + _, isNull := v.Kind.(*proto3.Value_NullValue) + if isNull { + continue + } + msg := reflect.New(etyp).Interface().(proto.Message) + if err := decodeValue(v, t, msg); err != nil { + return errDecodeArrayElement(i, v, "PROTO", err) + } + a.Index(i).Set(reflect.ValueOf(msg)) + } + rv.Elem().Set(a) + return nil +} + +// decodeProtoEnumPtrArray decodes proto3.ListValue pb into a *protoreflect.Enum slice. +func decodeProtoEnumPtrArray(pb *proto3.ListValue, t *sppb.Type, rv reflect.Value) error { + if pb == nil { + return errNilListValue("ENUM") + } + etyp := rv.Type().Elem().Elem().Elem() + a := reflect.MakeSlice(rv.Type().Elem(), len(pb.Values), len(pb.Values)) + for i, v := range pb.Values { + _, isNull := v.Kind.(*proto3.Value_NullValue) + if isNull { + continue + } + enum := reflect.New(etyp).Interface().(protoreflect.Enum) + if err := decodeValue(v, t, enum); err != nil { + return errDecodeArrayElement(i, v, "ENUM", err) + } + a.Index(i).Set(reflect.ValueOf(enum)) + } + rv.Elem().Set(a) + return nil +} + +// decodeProtoEnumArray decodes proto3.ListValue pb into a protoreflect.Enum slice. +func decodeProtoEnumArray(pb *proto3.ListValue, t *sppb.Type, rv reflect.Value, ptr interface{}) error { + if pb == nil { + return errNilListValue("ENUM") + } + a := reflect.MakeSlice(rv.Type().Elem(), len(pb.Values), len(pb.Values)) + // decodeValue method can decode only if ENUM is a pointer type. + // As the ENUM element in the Array is not a pointer type we cannot use decodeValue method + // and hence handle it separately. + for i, v := range pb.Values { + _, isNull := v.Kind.(*proto3.Value_NullValue) + // As the ENUM elements in the array are value type and not pointer type, + // we cannot support NULL values in the array + if isNull { + return errNilNotAllowed(ptr, "*[]*protoreflect.Enum") + } + x, err := getStringValue(v) + if err != nil { + return err + } + y, err := strconv.ParseInt(x, 10, 64) + if err != nil { + return errBadEncoding(v, err) + } + a.Index(i).SetInt(y) + } + rv.Elem().Set(a) + return nil +} + // decodeNullTimeArray decodes proto3.ListValue pb into a NullTime slice. func decodeNullTimeArray(pb *proto3.ListValue) ([]NullTime, error) { if pb == nil { @@ -3929,7 +4285,7 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) { pt = listType(pgNumericType()) case NullJSON: if v.Valid { - b, err := jsonProvider.Marshal(v.Value) + b, err := json.Marshal(v.Value) if err != nil { return nil, nil, err } @@ -3946,7 +4302,7 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) { pt = listType(jsonType()) case PGJsonB: if v.Valid { - b, err := jsonProvider.Marshal(v.Value) + b, err := json.Marshal(v.Value) if err != nil { return nil, nil, err } @@ -4068,6 +4424,41 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) { pt = proto.Clone(v.Type).(*sppb.Type) case []GenericColumnValue: return nil, nil, errEncoderUnsupportedType(v) + case protoreflect.Enum: + if v != nil { + var protoEnumfqn string + rv := reflect.ValueOf(v) + if rv.Kind() != reflect.Ptr || !rv.IsNil() { + pb.Kind = stringKind(strconv.FormatInt(int64(v.Number()), 10)) + protoEnumfqn = string(v.Descriptor().FullName()) + } else { + defaultType := reflect.Zero(rv.Type().Elem()).Interface().(protoreflect.Enum) + protoEnumfqn = string(defaultType.Descriptor().FullName()) + } + pt = protoEnumType(protoEnumfqn) + } + case NullProtoEnum: + if v.Valid { + return encodeValue(v.ProtoEnumVal) + } + return nil, nil, errNotValidSrc(v) + case proto.Message: + if v != nil { + if v.ProtoReflect().IsValid() { + bytes, err := proto.Marshal(v) + if err != nil { + return nil, nil, err + } + pb.Kind = stringKind(base64.StdEncoding.EncodeToString(bytes)) + } + protoMessagefqn := string(v.ProtoReflect().Descriptor().FullName()) + pt = protoMessageType(protoMessagefqn) + } + case NullProtoMessage: + if v.Valid { + return encodeValue(v.ProtoMessageVal) + } + return nil, nil, errNotValidSrc(v) default: // Check if the value is a custom type that implements spanner.Encoder // interface. @@ -4089,7 +4480,7 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) { return encodeValue(converted) } - if !isStructOrArrayOfStructValue(v) { + if !isStructOrArrayOfStructValue(v) && !isAnArrayOfProtoColumn(v) { return nil, nil, errEncoderUnsupportedType(v) } typ := reflect.TypeOf(v) @@ -4102,6 +4493,9 @@ func encodeValue(v interface{}) (*proto3.Value, *sppb.Type, error) { // Value is a slice of Go struct values/ptrs. if typ.Kind() == reflect.Slice { + if isAnArrayOfProtoColumn(v) { + return encodeProtoArray(v) + } return encodeStructArray(v) } } @@ -4376,6 +4770,42 @@ func encodeStructArray(v interface{}) (*proto3.Value, *sppb.Type, error) { return listProto(values...), listType(elemTyp), nil } +// Encodes a slice of proto messages or enum in v to the spanner Value and Type +// protos. +func encodeProtoArray(v interface{}) (*proto3.Value, *sppb.Type, error) { + pb := nullProto() + var pt *sppb.Type + var err error + sliceval := reflect.ValueOf(v) + etyp := reflect.TypeOf(v).Elem() + + if etyp.Implements(protoMsgReflectType) { + if !sliceval.IsNil() { + pb, err = encodeProtoMessageArray(sliceval.Len(), func(i int) reflect.Value { return sliceval.Index(i) }) + if err != nil { + return nil, nil, err + } + } + defaultInstance := reflect.Zero(etyp).Interface().(proto.Message) + protoMessagefqn := string(defaultInstance.ProtoReflect().Descriptor().FullName()) + pt = listType(protoMessageType(protoMessagefqn)) + } else if etyp.Implements(protoEnumReflectType) { + if !sliceval.IsNil() { + pb, err = encodeProtoEnumArray(sliceval.Len(), func(i int) reflect.Value { return sliceval.Index(i) }) + if err != nil { + return nil, nil, err + } + } + if etyp.Kind() == reflect.Ptr { + etyp = etyp.Elem() + } + defaultInstance := reflect.Zero(etyp).Interface().(protoreflect.Enum) + protoEnumfqn := string(defaultInstance.Descriptor().FullName()) + pt = listType(protoEnumType(protoEnumfqn)) + } + return pb, pt, nil +} + func isStructOrArrayOfStructValue(v interface{}) bool { typ := reflect.TypeOf(v) if typ.Kind() == reflect.Slice { @@ -4387,6 +4817,17 @@ func isStructOrArrayOfStructValue(v interface{}) bool { return typ.Kind() == reflect.Struct } +func isAnArrayOfProtoColumn(v interface{}) bool { + typ := reflect.TypeOf(v) + if typ.Kind() == reflect.Ptr { + typ = typ.Elem() + } + if typ.Kind() == reflect.Slice { + typ = typ.Elem() + } + return typ.Implements(protoMsgReflectType) || typ.Implements(protoEnumReflectType) +} + func isSupportedMutationType(v interface{}) bool { switch v.(type) { case nil, string, *string, NullString, []string, []*string, []NullString, @@ -4398,7 +4839,7 @@ func isSupportedMutationType(v interface{}) bool { time.Time, *time.Time, []time.Time, []*time.Time, NullTime, []NullTime, civil.Date, *civil.Date, []civil.Date, []*civil.Date, NullDate, []NullDate, big.Rat, *big.Rat, []big.Rat, []*big.Rat, NullNumeric, []NullNumeric, - GenericColumnValue: + GenericColumnValue, proto.Message, protoreflect.Enum, NullProtoMessage, NullProtoEnum: return true default: // Check if the custom type implements spanner.Encoder interface. @@ -4406,6 +4847,10 @@ func isSupportedMutationType(v interface{}) bool { return true } + if isAnArrayOfProtoColumn(v) { + return true + } + decodableType := getDecodableSpannerType(v, false) return decodableType != spannerTypeUnknown && decodableType != spannerTypeInvalid } @@ -4442,6 +4887,32 @@ func encodeArray(len int, at func(int) interface{}) (*proto3.Value, error) { return listProto(vs...), nil } +func encodeProtoMessageArray(len int, at func(int) reflect.Value) (*proto3.Value, error) { + vs := make([]*proto3.Value, len) + var err error + for i := 0; i < len; i++ { + v := at(i).Interface().(proto.Message) + vs[i], _, err = encodeValue(v) + if err != nil { + return nil, err + } + } + return listProto(vs...), nil +} + +func encodeProtoEnumArray(len int, at func(int) reflect.Value) (*proto3.Value, error) { + vs := make([]*proto3.Value, len) + var err error + for i := 0; i < len; i++ { + v := at(i).Interface().(protoreflect.Enum) + vs[i], _, err = encodeValue(v) + if err != nil { + return nil, err + } + } + return listProto(vs...), nil +} + func spannerTagParser(t reflect.StructTag) (name string, keep bool, other interface{}, err error) { if s := t.Get("spanner"); s != "" { if s == "-" { |
