From 61cc7e81908e9b5eef42ce2d1e6dec2ec7c044e9 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 23 Sep 2025 16:16:48 +0200 Subject: [PATCH 01/15] fix: update dependency net.java.dev.jna:jna to v5.18.0 (#538) --- spannerlib/wrappers/spannerlib-java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spannerlib/wrappers/spannerlib-java/pom.xml b/spannerlib/wrappers/spannerlib-java/pom.xml index 2b303271..8a09fb50 100644 --- a/spannerlib/wrappers/spannerlib-java/pom.xml +++ b/spannerlib/wrappers/spannerlib-java/pom.xml @@ -39,7 +39,7 @@ net.java.dev.jna jna - 5.17.0 + 5.18.0 From dad79fd5291a872ca002520d6e6d23e1991b5f9e Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 23 Sep 2025 16:17:10 +0200 Subject: [PATCH 02/15] chore: update all dependencies (#537) --- .github/workflows/spanner-lib-tests.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/spanner-lib-tests.yml b/.github/workflows/spanner-lib-tests.yml index d39c4785..a0a960c0 100644 --- a/.github/workflows/spanner-lib-tests.yml +++ b/.github/workflows/spanner-lib-tests.yml @@ -15,11 +15,11 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Install Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.go-version }} - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Run unit tests working-directory: spannerlib run: go test ./... -race -short @@ -32,17 +32,17 @@ jobs: runs-on: ${{ matrix.os }} steps: - name: Install Java - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: distribution: temurin java-version: 21 - name: Checkout code - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Check Java formatting run: mvn com.spotify.fmt:fmt-maven-plugin:check working-directory: spannerlib/wrappers/spannerlib-java - name: Install Go - uses: actions/setup-go@v5 + uses: actions/setup-go@v6 with: go-version: ${{ matrix.go-version }} - name: Build shared library From 13bda8dae03e8af663450e21a888808521857c81 Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Tue, 23 Sep 2025 16:26:19 +0200 Subject: [PATCH 03/15] fix: update all dependencies (#536) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: update all dependencies * chore: go mod tidy --------- Co-authored-by: Knut Olav Løite --- benchmarks/go.mod | 4 ++-- benchmarks/go.sum | 8 ++++---- examples/go.mod | 4 ++-- examples/go.sum | 8 ++++---- go.mod | 4 ++-- go.sum | 8 ++++---- snippets/go.mod | 4 ++-- snippets/go.sum | 8 ++++---- spannerlib/go.mod | 6 +++--- spannerlib/go.sum | 8 ++++---- spannerlib/wrappers/spannerlib-java/pom.xml | 4 ++-- 11 files changed, 33 insertions(+), 33 deletions(-) diff --git a/benchmarks/go.mod b/benchmarks/go.mod index aafed8da..9592b614 100644 --- a/benchmarks/go.mod +++ b/benchmarks/go.mod @@ -7,7 +7,7 @@ toolchain go1.25.1 replace github.com/googleapis/go-sql-spanner => ../ require ( - cloud.google.com/go v0.122.0 + cloud.google.com/go v0.123.0 cloud.google.com/go/spanner v1.85.1 github.com/google/uuid v1.6.0 github.com/googleapis/go-sql-spanner v1.18.0 @@ -61,5 +61,5 @@ require ( golang.org/x/time v0.12.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect ) diff --git a/benchmarks/go.sum b/benchmarks/go.sum index facf0032..c8f84b25 100644 --- a/benchmarks/go.sum +++ b/benchmarks/go.sum @@ -38,8 +38,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc= -cloud.google.com/go v0.122.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/examples/go.mod b/examples/go.mod index e74467ed..b44c738f 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -7,7 +7,7 @@ toolchain go1.24.3 replace github.com/googleapis/go-sql-spanner => ../ require ( - cloud.google.com/go v0.122.0 + cloud.google.com/go v0.123.0 cloud.google.com/go/spanner v1.85.1 github.com/docker/docker v28.3.3+incompatible github.com/docker/go-connections v0.5.0 @@ -100,7 +100,7 @@ require ( golang.org/x/time v0.12.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect google.golang.org/grpc v1.75.1 // indirect google.golang.org/protobuf v1.36.9 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/examples/go.sum b/examples/go.sum index 52c55eb2..f5e3c65d 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -38,8 +38,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc= -cloud.google.com/go v0.122.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -1621,8 +1621,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/go.mod b/go.mod index a0bdb3ca..64d30a41 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.24.0 toolchain go1.25.1 require ( - cloud.google.com/go v0.122.0 + cloud.google.com/go v0.123.0 cloud.google.com/go/longrunning v0.6.7 cloud.google.com/go/spanner v1.85.1 github.com/golang/protobuf v1.5.4 @@ -14,7 +14,7 @@ require ( github.com/googleapis/gax-go/v2 v2.15.0 github.com/hashicorp/golang-lru/v2 v2.0.7 google.golang.org/api v0.249.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 + google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 google.golang.org/grpc v1.75.1 google.golang.org/protobuf v1.36.9 ) diff --git a/go.sum b/go.sum index facf0032..c8f84b25 100644 --- a/go.sum +++ b/go.sum @@ -38,8 +38,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc= -cloud.google.com/go v0.122.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/snippets/go.mod b/snippets/go.mod index fb8c5767..cf9c0047 100644 --- a/snippets/go.mod +++ b/snippets/go.mod @@ -15,7 +15,7 @@ require ( require ( cel.dev/expr v0.24.0 // indirect - cloud.google.com/go v0.122.0 // indirect + cloud.google.com/go v0.123.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.8.0 // indirect @@ -100,7 +100,7 @@ require ( google.golang.org/api v0.249.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect google.golang.org/grpc v1.75.1 // indirect google.golang.org/protobuf v1.36.9 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/snippets/go.sum b/snippets/go.sum index f9b4e46c..a3288fd3 100644 --- a/snippets/go.sum +++ b/snippets/go.sum @@ -38,8 +38,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc= -cloud.google.com/go v0.122.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -1615,8 +1615,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/spannerlib/go.mod b/spannerlib/go.mod index 6d6912b0..5dd3bc3e 100644 --- a/spannerlib/go.mod +++ b/spannerlib/go.mod @@ -7,6 +7,7 @@ toolchain go1.25.1 replace github.com/googleapis/go-sql-spanner => .. require ( + cloud.google.com/go/longrunning v0.6.7 cloud.google.com/go/spanner v1.85.1 github.com/google/go-cmp v0.7.0 github.com/googleapis/go-sql-spanner v1.18.0 @@ -16,12 +17,11 @@ require ( require ( cel.dev/expr v0.24.0 // indirect - cloud.google.com/go v0.122.0 // indirect + cloud.google.com/go v0.123.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect cloud.google.com/go/compute/metadata v0.8.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect - cloud.google.com/go/longrunning v0.6.7 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.29.0 // indirect @@ -63,5 +63,5 @@ require ( google.golang.org/api v0.249.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect ) diff --git a/spannerlib/go.sum b/spannerlib/go.sum index facf0032..c8f84b25 100644 --- a/spannerlib/go.sum +++ b/spannerlib/go.sum @@ -38,8 +38,8 @@ cloud.google.com/go v0.104.0/go.mod h1:OO6xxXdJyvuJPcEPBLN9BJPD+jep5G1+2U5B5gkRY cloud.google.com/go v0.105.0/go.mod h1:PrLgOJNe5nfE9UMxKxgXj4mD3voiP+YQ6gdt6KMFOKM= cloud.google.com/go v0.107.0/go.mod h1:wpc2eNrD7hXUTy8EKS10jkxpZBjASrORK7goS+3YX2I= cloud.google.com/go v0.110.0/go.mod h1:SJnCLqQ0FCFGSZMUNUf84MV3Aia54kn7pi8st7tMzaY= -cloud.google.com/go v0.122.0 h1:0JTLGrcSIs3HIGsgVPvTx3cfyFSP/k9CI8vLPHTd6Wc= -cloud.google.com/go v0.122.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= +cloud.google.com/go v0.123.0 h1:2NAUJwPR47q+E35uaJeYoNhuNEM9kM8SjgRgdeOJUSE= +cloud.google.com/go v0.123.0/go.mod h1:xBoMV08QcqUGuPW65Qfm1o9Y4zKZBpGS+7bImXLTAZU= cloud.google.com/go/accessapproval v1.4.0/go.mod h1:zybIuC3KpDOvotz59lFe5qxRZx6C75OtwbisN56xYB4= cloud.google.com/go/accessapproval v1.5.0/go.mod h1:HFy3tuiGvMdcd/u+Cu5b9NkO1pEICJ46IR82PoUdplw= cloud.google.com/go/accessapproval v1.6.0/go.mod h1:R0EiYnwV5fsRFiKZkPHr6mwyk2wxUJ30nL4j2pcFY2E= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090 h1:/OQuEa4YWtDt7uQWHd3q3sUMb+QOLQUg1xa8CEsRv5w= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250908214217-97024824d090/go.mod h1:GmFNa4BdJZ2a8G+wCe9Bg3wwThLrJun751XstdJt5Og= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= diff --git a/spannerlib/wrappers/spannerlib-java/pom.xml b/spannerlib/wrappers/spannerlib-java/pom.xml index 8a09fb50..098402d0 100644 --- a/spannerlib/wrappers/spannerlib-java/pom.xml +++ b/spannerlib/wrappers/spannerlib-java/pom.xml @@ -16,7 +16,7 @@ com.google.cloud sdk-platform-java-config - 3.52.1 + 3.52.2 @@ -59,7 +59,7 @@ gax-grpc testlib test - 2.70.0 + 2.70.2 junit From f29032e5d597d2369c656e7c58f41b5eba7dc63a Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Wed, 24 Sep 2025 09:09:32 +0200 Subject: [PATCH 04/15] chore(main): release 1.18.1 (#525) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGES.md | 11 +++++++++++ driver.go | 2 +- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 4ce109ae..aa06f863 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.18.0" + ".": "1.18.1" } \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index 021fe111..58343eb9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,16 @@ # Changelog +## [1.18.1](https://github.com/googleapis/go-sql-spanner/compare/v1.18.0...v1.18.1) (2025-09-23) + + +### Bug Fixes + +* Do not return update count for queries ([#524](https://github.com/googleapis/go-sql-spanner/issues/524)) ([4403e52](https://github.com/googleapis/go-sql-spanner/commit/4403e5287515c83fb889f9e7f8a107f9cfdb1ea8)) +* Update all dependencies ([#536](https://github.com/googleapis/go-sql-spanner/issues/536)) ([13bda8d](https://github.com/googleapis/go-sql-spanner/commit/13bda8dae03e8af663450e21a888808521857c81)) +* Update dependency net.java.dev.jna:jna to v5.18.0 ([#538](https://github.com/googleapis/go-sql-spanner/issues/538)) ([61cc7e8](https://github.com/googleapis/go-sql-spanner/commit/61cc7e81908e9b5eef42ce2d1e6dec2ec7c044e9)) +* Update module github.com/googleapis/go-sql-spanner to v1.18.0 ([#528](https://github.com/googleapis/go-sql-spanner/issues/528)) ([f5100ce](https://github.com/googleapis/go-sql-spanner/commit/f5100cec9d99099b3a538e45688f27f0c3dd0376)) +* Update module github.com/testcontainers/testcontainers-go to v0.39.0 ([#535](https://github.com/googleapis/go-sql-spanner/issues/535)) ([c3a8109](https://github.com/googleapis/go-sql-spanner/commit/c3a8109084ee4a876ae5a57aec015d330e25b381)) + ## [1.18.0](https://github.com/googleapis/go-sql-spanner/compare/v1.17.0...v1.18.0) (2025-09-12) diff --git a/driver.go b/driver.go index 15cec71a..735b5e51 100644 --- a/driver.go +++ b/driver.go @@ -51,7 +51,7 @@ import ( "google.golang.org/protobuf/proto" ) -const userAgent = "go-sql-spanner/1.18.0" // x-release-please-version +const userAgent = "go-sql-spanner/1.18.1" // x-release-please-version const gormModule = "github.com/googleapis/go-gorm-spanner" const gormUserAgent = "go-gorm-spanner" From 1eca4414dfddef2c5e9e3642712317c3929738be Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Thu, 25 Sep 2025 11:28:08 +0200 Subject: [PATCH 05/15] fix: update module github.com/googleapis/go-sql-spanner to v1.18.1 (#540) --- benchmarks/go.mod | 2 +- snippets/go.mod | 2 +- spannerlib/go.mod | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmarks/go.mod b/benchmarks/go.mod index 9592b614..5ce60736 100644 --- a/benchmarks/go.mod +++ b/benchmarks/go.mod @@ -10,7 +10,7 @@ require ( cloud.google.com/go v0.123.0 cloud.google.com/go/spanner v1.85.1 github.com/google/uuid v1.6.0 - github.com/googleapis/go-sql-spanner v1.18.0 + github.com/googleapis/go-sql-spanner v1.18.1 google.golang.org/api v0.249.0 google.golang.org/grpc v1.75.1 google.golang.org/protobuf v1.36.9 diff --git a/snippets/go.mod b/snippets/go.mod index cf9c0047..eb9473c5 100644 --- a/snippets/go.mod +++ b/snippets/go.mod @@ -9,7 +9,7 @@ replace github.com/googleapis/go-sql-spanner => ../ require ( cloud.google.com/go/spanner v1.85.1 github.com/docker/docker v28.4.0+incompatible - github.com/googleapis/go-sql-spanner v1.18.0 + github.com/googleapis/go-sql-spanner v1.18.1 github.com/testcontainers/testcontainers-go v0.39.0 ) diff --git a/spannerlib/go.mod b/spannerlib/go.mod index 5dd3bc3e..1c9f5b9f 100644 --- a/spannerlib/go.mod +++ b/spannerlib/go.mod @@ -10,7 +10,7 @@ require ( cloud.google.com/go/longrunning v0.6.7 cloud.google.com/go/spanner v1.85.1 github.com/google/go-cmp v0.7.0 - github.com/googleapis/go-sql-spanner v1.18.0 + github.com/googleapis/go-sql-spanner v1.18.1 google.golang.org/grpc v1.75.1 google.golang.org/protobuf v1.36.9 ) From d2a5b4c047ed5b8f85e2c4b4d938f364be694ae6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 23 Sep 2025 13:29:07 +0200 Subject: [PATCH 06/15] chore: add .NET gRPC wrapper Adds a gRPC wrapper for .NET. This wrapper uses the gRPC API to connect to SpannerLib. The gRPC channel uses a Unix domain socket. --- .github/workflows/spanner-lib-tests.yml | 30 + .../build-dotnet-darwin-aarch64.sh | 4 + .../grpc-server/build-java-darwin-aarch64.sh | 1 + spannerlib/grpc-server/build-protos.sh | 13 +- .../grpc-server/google/spannerlib/spannerlib | 1 + .../google/spannerlib/v1/spannerlib.pb.go | 353 +- .../google/spannerlib/v1/spannerlib.proto | 9 + .../spannerlib/v1/spannerlib_grpc.pb.go | 38 + spannerlib/grpc-server/server.go | 4 + .../GrpcLibSpanner.cs | 403 ++ .../StreamingRows.cs | 131 + .../spannerlib-dotnet-grpc-impl.csproj | 19 + .../spannerlib-dotnet-grpc-server/Server.cs | 191 + .../spannerlib-dotnet-grpc-server/build.sh | 16 + .../spannerlib-dotnet-grpc-server.csproj | 19 + .../ServerTests.cs | 50 + .../spannerlib-dotnet-grpc-tests.csproj | 28 + .../spannerlib-dotnet-grpc-v1/Spannerlib.g.cs | 4102 +++++++++++++++++ .../SpannerlibGrpc.cs | 590 +++ .../spannerlib-dotnet-grpc-v1.csproj | 15 + .../MockSpannerServer.cs | 6 + .../SpannerConverter.cs | 12 +- .../SharedLibSpanner.cs | 32 +- .../AbstractMockServerTests.cs | 66 + .../spannerlib-dotnet-tests/BasicTests.cs | 70 +- .../spannerlib-dotnet-tests/BatchTests.cs | 35 +- .../spannerlib-dotnet-tests/BenchmarkTests.cs | 197 + .../ConnectionTests.cs | 58 +- .../spannerlib-dotnet-tests/PoolTests.cs | 33 +- .../spannerlib-dotnet-tests/RowsTests.cs | 146 +- .../TransactionTests.cs | 71 +- .../spannerlib-dotnet-tests.csproj | 2 + .../spannerlib-dotnet/spannerlib-dotnet.sln | 24 + .../spannerlib-dotnet/AbstractLibObject.cs | 36 +- .../spannerlib-dotnet/Connection.cs | 16 + .../spannerlib-dotnet/ISpannerLib.cs | 51 +- .../spannerlib-dotnet/Rows.cs | 17 +- .../spannerlib-dotnet/SpannerException.cs | 7 + .../spannerlib/GrpcSpannerLibraryImpl.java | 30 + .../cloud/spannerlib/v1/InfoRequest.java | 364 ++ .../spannerlib/v1/InfoRequestOrBuilder.java | 12 + .../cloud/spannerlib/v1/InfoResponse.java | 522 +++ .../spannerlib/v1/InfoResponseOrBuilder.java | 27 + .../cloud/spannerlib/v1/SpannerLibGrpc.java | 124 +- .../cloud/spannerlib/v1/SpannerLibProto.java | 218 +- .../spannerlib/AbstractSpannerLibTest.java | 17 +- .../cloud/spannerlib/BenchmarkTest.java | 155 + 47 files changed, 7871 insertions(+), 494 deletions(-) create mode 100755 spannerlib/grpc-server/build-dotnet-darwin-aarch64.sh create mode 120000 spannerlib/grpc-server/google/spannerlib/spannerlib create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/GrpcLibSpanner.cs create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/StreamingRows.cs create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/spannerlib-dotnet-grpc-impl.csproj create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs create mode 100755 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/build.sh create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/spannerlib-dotnet-grpc-server.csproj create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/ServerTests.cs create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/spannerlib-dotnet-grpc-tests.csproj create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/Spannerlib.g.cs create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/SpannerlibGrpc.cs create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/spannerlib-dotnet-grpc-v1.csproj create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/AbstractMockServerTests.cs create mode 100644 spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BenchmarkTests.cs create mode 100644 spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequest.java create mode 100644 spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequestOrBuilder.java create mode 100644 spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponse.java create mode 100644 spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponseOrBuilder.java create mode 100644 spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/BenchmarkTest.java diff --git a/.github/workflows/spanner-lib-tests.yml b/.github/workflows/spanner-lib-tests.yml index b6df5ccd..468cd3d6 100644 --- a/.github/workflows/spanner-lib-tests.yml +++ b/.github/workflows/spanner-lib-tests.yml @@ -97,6 +97,8 @@ jobs: go-version: ${{ matrix.go-version }} - name: Checkout code uses: actions/checkout@v4 + with: + submodules: 'true' - name: Build shared library working-directory: spannerlib/shared run: go build -o spannerlib.so -buildmode=c-shared shared_lib.go @@ -124,6 +126,34 @@ jobs: fi working-directory: spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-native shell: bash + - name: Build gRPC server + working-directory: spannerlib/grpc-server + run: | + go build -o grpc_server server.go + chmod +x grpc_server + - name: Copy gRPC server to .NET wrapper + working-directory: spannerlib + run: | + mkdir -p wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/binaries/any + if [ "$RUNNER_OS" == "Windows" ]; then + cp grpc-server/grpc_server wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/binaries/any/grpc_server.exe + else + cp grpc-server/grpc_server wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/binaries/any/grpc_server + fi + shell: bash + - name: Build .NET gRPC server package + run: dotnet pack + working-directory: spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server + shell: bash + - name: Add .NET package source + run: | + if [ "$RUNNER_OS" == "Windows" ]; then + dotnet nuget add source ${GITHUB_WORKSPACE}"\spannerlib\wrappers\spannerlib-dotnet\spannerlib-dotnet-grpc-server\bin\Release" --name local-grpc-server + else + dotnet nuget add source "$PWD"/bin/Release --name local-grpc-server + fi + working-directory: spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server + shell: bash - name: Restore dependencies run: dotnet restore working-directory: spannerlib/wrappers/spannerlib-dotnet diff --git a/spannerlib/grpc-server/build-dotnet-darwin-aarch64.sh b/spannerlib/grpc-server/build-dotnet-darwin-aarch64.sh new file mode 100755 index 00000000..3578601b --- /dev/null +++ b/spannerlib/grpc-server/build-dotnet-darwin-aarch64.sh @@ -0,0 +1,4 @@ +go build -o grpc_server server.go +chmod +x grpc_server +cp grpc_server ../wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc/binaries/any/grpc_server +cp grpc_server ../wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc/binaries/osx-arm64/grpc_server diff --git a/spannerlib/grpc-server/build-java-darwin-aarch64.sh b/spannerlib/grpc-server/build-java-darwin-aarch64.sh index 9b5e9d77..a14a7154 100755 --- a/spannerlib/grpc-server/build-java-darwin-aarch64.sh +++ b/spannerlib/grpc-server/build-java-darwin-aarch64.sh @@ -1,3 +1,4 @@ go build -o grpc_server server.go chmod +x grpc_server +mkdir -p ../wrappers/spannerlib-java/src/main/resources/darwin-aarch64 cp grpc_server ../wrappers/spannerlib-java/src/main/resources/darwin-aarch64/grpc_server diff --git a/spannerlib/grpc-server/build-protos.sh b/spannerlib/grpc-server/build-protos.sh index b9214ef3..d3721808 100755 --- a/spannerlib/grpc-server/build-protos.sh +++ b/spannerlib/grpc-server/build-protos.sh @@ -1,6 +1,5 @@ PATH="${PATH}:${HOME}/go/bin" -rm -rf googleapis/google/spannerlib || true -cp -r google/spannerlib googleapis/google/spannerlib +ln -sf "${PWD}"/google/spannerlib googleapis/google/spannerlib cd googleapis || exit 1 protoc \ --go_out=../ \ @@ -14,5 +13,13 @@ protoc \ --java-grpc_out=../../wrappers/spannerlib-java/src/main/java/ \ --java-grpc_opt=paths=source_relative \ google/spannerlib/v1/spannerlib.proto +protoc \ + --csharp_out=../../wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/ \ + --plugin=protoc-gen-csharp_grpc=/Users/loite/.nuget/packages/grpc.tools/2.72.0/tools/macosx_x64/grpc_csharp_plugin \ + --csharp_grpc_out=../../wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/ \ + --csharp_opt=file_extension=.g.cs \ + --csharp_grpc_opt=no_server \ + --proto_path=. \ + google/spannerlib/v1/spannerlib.proto cd .. || exit 1 -rm -rf googleapis/google/spannerlib +rm googleapis/google/spannerlib diff --git a/spannerlib/grpc-server/google/spannerlib/spannerlib b/spannerlib/grpc-server/google/spannerlib/spannerlib new file mode 120000 index 00000000..73970885 --- /dev/null +++ b/spannerlib/grpc-server/google/spannerlib/spannerlib @@ -0,0 +1 @@ +/Users/loite/GolandProjects/go-sql-spanner/spannerlib/grpc-server/google/spannerlib \ No newline at end of file diff --git a/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.pb.go b/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.pb.go index 7c738df4..3707b228 100644 --- a/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.pb.go +++ b/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.pb.go @@ -25,6 +25,86 @@ const ( _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) ) +type InfoRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InfoRequest) Reset() { + *x = InfoRequest{} + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InfoRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InfoRequest) ProtoMessage() {} + +func (x *InfoRequest) ProtoReflect() protoreflect.Message { + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[0] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InfoRequest.ProtoReflect.Descriptor instead. +func (*InfoRequest) Descriptor() ([]byte, []int) { + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{0} +} + +type InfoResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Version string `protobuf:"bytes,1,opt,name=version,proto3" json:"version,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *InfoResponse) Reset() { + *x = InfoResponse{} + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *InfoResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*InfoResponse) ProtoMessage() {} + +func (x *InfoResponse) ProtoReflect() protoreflect.Message { + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[1] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use InfoResponse.ProtoReflect.Descriptor instead. +func (*InfoResponse) Descriptor() ([]byte, []int) { + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{1} +} + +func (x *InfoResponse) GetVersion() string { + if x != nil { + return x.Version + } + return "" +} + type CreatePoolRequest struct { state protoimpl.MessageState `protogen:"open.v1"` ConnectionString string `protobuf:"bytes,1,opt,name=connection_string,json=connectionString,proto3" json:"connection_string,omitempty"` @@ -34,7 +114,7 @@ type CreatePoolRequest struct { func (x *CreatePoolRequest) Reset() { *x = CreatePoolRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[0] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[2] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -46,7 +126,7 @@ func (x *CreatePoolRequest) String() string { func (*CreatePoolRequest) ProtoMessage() {} func (x *CreatePoolRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[0] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[2] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -59,7 +139,7 @@ func (x *CreatePoolRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreatePoolRequest.ProtoReflect.Descriptor instead. func (*CreatePoolRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{0} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{2} } func (x *CreatePoolRequest) GetConnectionString() string { @@ -78,7 +158,7 @@ type CreateConnectionRequest struct { func (x *CreateConnectionRequest) Reset() { *x = CreateConnectionRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[1] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -90,7 +170,7 @@ func (x *CreateConnectionRequest) String() string { func (*CreateConnectionRequest) ProtoMessage() {} func (x *CreateConnectionRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[1] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[3] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -103,7 +183,7 @@ func (x *CreateConnectionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use CreateConnectionRequest.ProtoReflect.Descriptor instead. func (*CreateConnectionRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{1} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{3} } func (x *CreateConnectionRequest) GetPool() *Pool { @@ -123,7 +203,7 @@ type ExecuteRequest struct { func (x *ExecuteRequest) Reset() { *x = ExecuteRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[2] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -135,7 +215,7 @@ func (x *ExecuteRequest) String() string { func (*ExecuteRequest) ProtoMessage() {} func (x *ExecuteRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[2] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[4] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -148,7 +228,7 @@ func (x *ExecuteRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteRequest.ProtoReflect.Descriptor instead. func (*ExecuteRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{2} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{4} } func (x *ExecuteRequest) GetConnection() *Connection { @@ -175,7 +255,7 @@ type ExecuteBatchRequest struct { func (x *ExecuteBatchRequest) Reset() { *x = ExecuteBatchRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[3] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -187,7 +267,7 @@ func (x *ExecuteBatchRequest) String() string { func (*ExecuteBatchRequest) ProtoMessage() {} func (x *ExecuteBatchRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[3] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[5] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -200,7 +280,7 @@ func (x *ExecuteBatchRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ExecuteBatchRequest.ProtoReflect.Descriptor instead. func (*ExecuteBatchRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{3} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{5} } func (x *ExecuteBatchRequest) GetConnection() *Connection { @@ -227,7 +307,7 @@ type BeginTransactionRequest struct { func (x *BeginTransactionRequest) Reset() { *x = BeginTransactionRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[4] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[6] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -239,7 +319,7 @@ func (x *BeginTransactionRequest) String() string { func (*BeginTransactionRequest) ProtoMessage() {} func (x *BeginTransactionRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[4] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[6] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -252,7 +332,7 @@ func (x *BeginTransactionRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use BeginTransactionRequest.ProtoReflect.Descriptor instead. func (*BeginTransactionRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{4} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{6} } func (x *BeginTransactionRequest) GetConnection() *Connection { @@ -279,7 +359,7 @@ type WriteMutationsRequest struct { func (x *WriteMutationsRequest) Reset() { *x = WriteMutationsRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[5] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -291,7 +371,7 @@ func (x *WriteMutationsRequest) String() string { func (*WriteMutationsRequest) ProtoMessage() {} func (x *WriteMutationsRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[5] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[7] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -304,7 +384,7 @@ func (x *WriteMutationsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use WriteMutationsRequest.ProtoReflect.Descriptor instead. func (*WriteMutationsRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{5} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{7} } func (x *WriteMutationsRequest) GetConnection() *Connection { @@ -330,7 +410,7 @@ type Pool struct { func (x *Pool) Reset() { *x = Pool{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[6] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -342,7 +422,7 @@ func (x *Pool) String() string { func (*Pool) ProtoMessage() {} func (x *Pool) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[6] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[8] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -355,7 +435,7 @@ func (x *Pool) ProtoReflect() protoreflect.Message { // Deprecated: Use Pool.ProtoReflect.Descriptor instead. func (*Pool) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{6} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{8} } func (x *Pool) GetId() int64 { @@ -375,7 +455,7 @@ type Connection struct { func (x *Connection) Reset() { *x = Connection{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[7] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[9] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -387,7 +467,7 @@ func (x *Connection) String() string { func (*Connection) ProtoMessage() {} func (x *Connection) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[7] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[9] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -400,7 +480,7 @@ func (x *Connection) ProtoReflect() protoreflect.Message { // Deprecated: Use Connection.ProtoReflect.Descriptor instead. func (*Connection) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{7} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{9} } func (x *Connection) GetPool() *Pool { @@ -427,7 +507,7 @@ type Rows struct { func (x *Rows) Reset() { *x = Rows{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[8] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[10] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -439,7 +519,7 @@ func (x *Rows) String() string { func (*Rows) ProtoMessage() {} func (x *Rows) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[8] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[10] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -452,7 +532,7 @@ func (x *Rows) ProtoReflect() protoreflect.Message { // Deprecated: Use Rows.ProtoReflect.Descriptor instead. func (*Rows) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{8} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{10} } func (x *Rows) GetConnection() *Connection { @@ -480,7 +560,7 @@ type NextRequest struct { func (x *NextRequest) Reset() { *x = NextRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[9] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -492,7 +572,7 @@ func (x *NextRequest) String() string { func (*NextRequest) ProtoMessage() {} func (x *NextRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[9] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[11] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -505,7 +585,7 @@ func (x *NextRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use NextRequest.ProtoReflect.Descriptor instead. func (*NextRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{9} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{11} } func (x *NextRequest) GetRows() *Rows { @@ -541,7 +621,7 @@ type RowData struct { func (x *RowData) Reset() { *x = RowData{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[10] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -553,7 +633,7 @@ func (x *RowData) String() string { func (*RowData) ProtoMessage() {} func (x *RowData) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[10] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[12] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -566,7 +646,7 @@ func (x *RowData) ProtoReflect() protoreflect.Message { // Deprecated: Use RowData.ProtoReflect.Descriptor instead. func (*RowData) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{10} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{12} } func (x *RowData) GetRows() *Rows { @@ -606,7 +686,7 @@ type MetadataRequest struct { func (x *MetadataRequest) Reset() { *x = MetadataRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[11] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[13] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -618,7 +698,7 @@ func (x *MetadataRequest) String() string { func (*MetadataRequest) ProtoMessage() {} func (x *MetadataRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[11] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[13] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -631,7 +711,7 @@ func (x *MetadataRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use MetadataRequest.ProtoReflect.Descriptor instead. func (*MetadataRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{11} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{13} } func (x *MetadataRequest) GetRows() *Rows { @@ -650,7 +730,7 @@ type ResultSetStatsRequest struct { func (x *ResultSetStatsRequest) Reset() { *x = ResultSetStatsRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[12] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[14] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -662,7 +742,7 @@ func (x *ResultSetStatsRequest) String() string { func (*ResultSetStatsRequest) ProtoMessage() {} func (x *ResultSetStatsRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[12] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[14] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -675,7 +755,7 @@ func (x *ResultSetStatsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ResultSetStatsRequest.ProtoReflect.Descriptor instead. func (*ResultSetStatsRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{12} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{14} } func (x *ResultSetStatsRequest) GetRows() *Rows { @@ -697,7 +777,7 @@ type ConnectionStreamRequest struct { func (x *ConnectionStreamRequest) Reset() { *x = ConnectionStreamRequest{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[13] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[15] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -709,7 +789,7 @@ func (x *ConnectionStreamRequest) String() string { func (*ConnectionStreamRequest) ProtoMessage() {} func (x *ConnectionStreamRequest) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[13] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[15] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -722,7 +802,7 @@ func (x *ConnectionStreamRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectionStreamRequest.ProtoReflect.Descriptor instead. func (*ConnectionStreamRequest) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{13} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{15} } func (x *ConnectionStreamRequest) GetRequest() isConnectionStreamRequest_Request { @@ -763,7 +843,7 @@ type ConnectionStreamResponse struct { func (x *ConnectionStreamResponse) Reset() { *x = ConnectionStreamResponse{} - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[14] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[16] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -775,7 +855,7 @@ func (x *ConnectionStreamResponse) String() string { func (*ConnectionStreamResponse) ProtoMessage() {} func (x *ConnectionStreamResponse) ProtoReflect() protoreflect.Message { - mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[14] + mi := &file_google_spannerlib_v1_spannerlib_proto_msgTypes[16] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -788,7 +868,7 @@ func (x *ConnectionStreamResponse) ProtoReflect() protoreflect.Message { // Deprecated: Use ConnectionStreamResponse.ProtoReflect.Descriptor instead. func (*ConnectionStreamResponse) Descriptor() ([]byte, []int) { - return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{14} + return file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP(), []int{16} } func (x *ConnectionStreamResponse) GetResponse() isConnectionStreamResponse_Response { @@ -821,7 +901,10 @@ var File_google_spannerlib_v1_spannerlib_proto protoreflect.FileDescriptor const file_google_spannerlib_v1_spannerlib_proto_rawDesc = "" + "\n" + - "%google/spannerlib/v1/spannerlib.proto\x12\x14google.spannerlib.v1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\"google/spanner/v1/result_set.proto\x1a\x1fgoogle/spanner/v1/spanner.proto\x1a#google/spanner/v1/transaction.proto\"E\n" + + "%google/spannerlib/v1/spannerlib.proto\x12\x14google.spannerlib.v1\x1a\x1fgoogle/api/field_behavior.proto\x1a\x1bgoogle/protobuf/empty.proto\x1a\x1cgoogle/protobuf/struct.proto\x1a\"google/spanner/v1/result_set.proto\x1a\x1fgoogle/spanner/v1/spanner.proto\x1a#google/spanner/v1/transaction.proto\"\r\n" + + "\vInfoRequest\"(\n" + + "\fInfoResponse\x12\x18\n" + + "\aversion\x18\x01 \x01(\tR\aversion\"E\n" + "\x11CreatePoolRequest\x120\n" + "\x11connection_string\x18\x01 \x01(\tB\x03\xe0A\x02R\x10connectionString\"N\n" + "\x17CreateConnectionRequest\x123\n" + @@ -876,10 +959,10 @@ const file_google_spannerlib_v1_spannerlib_proto_rawDesc = "" + "\x18ConnectionStreamResponse\x127\n" + "\x03row\x18\x01 \x01(\v2#.google.spanner.v1.PartialResultSetH\x00R\x03rowB\n" + "\n" + - "\bresponse2\xf1\n" + - "\n" + + "\bresponse2\xc2\v\n" + "\n" + - "SpannerLib\x12S\n" + + "SpannerLib\x12O\n" + + "\x04Info\x12!.google.spannerlib.v1.InfoRequest\x1a\".google.spannerlib.v1.InfoResponse\"\x00\x12S\n" + "\n" + "CreatePool\x12'.google.spannerlib.v1.CreatePoolRequest\x1a\x1a.google.spannerlib.v1.Pool\"\x00\x12A\n" + "\tClosePool\x12\x1a.google.spannerlib.v1.Pool\x1a\x16.google.protobuf.Empty\"\x00\x12e\n" + @@ -911,90 +994,94 @@ func file_google_spannerlib_v1_spannerlib_proto_rawDescGZIP() []byte { return file_google_spannerlib_v1_spannerlib_proto_rawDescData } -var file_google_spannerlib_v1_spannerlib_proto_msgTypes = make([]protoimpl.MessageInfo, 15) +var file_google_spannerlib_v1_spannerlib_proto_msgTypes = make([]protoimpl.MessageInfo, 17) var file_google_spannerlib_v1_spannerlib_proto_goTypes = []any{ - (*CreatePoolRequest)(nil), // 0: google.spannerlib.v1.CreatePoolRequest - (*CreateConnectionRequest)(nil), // 1: google.spannerlib.v1.CreateConnectionRequest - (*ExecuteRequest)(nil), // 2: google.spannerlib.v1.ExecuteRequest - (*ExecuteBatchRequest)(nil), // 3: google.spannerlib.v1.ExecuteBatchRequest - (*BeginTransactionRequest)(nil), // 4: google.spannerlib.v1.BeginTransactionRequest - (*WriteMutationsRequest)(nil), // 5: google.spannerlib.v1.WriteMutationsRequest - (*Pool)(nil), // 6: google.spannerlib.v1.Pool - (*Connection)(nil), // 7: google.spannerlib.v1.Connection - (*Rows)(nil), // 8: google.spannerlib.v1.Rows - (*NextRequest)(nil), // 9: google.spannerlib.v1.NextRequest - (*RowData)(nil), // 10: google.spannerlib.v1.RowData - (*MetadataRequest)(nil), // 11: google.spannerlib.v1.MetadataRequest - (*ResultSetStatsRequest)(nil), // 12: google.spannerlib.v1.ResultSetStatsRequest - (*ConnectionStreamRequest)(nil), // 13: google.spannerlib.v1.ConnectionStreamRequest - (*ConnectionStreamResponse)(nil), // 14: google.spannerlib.v1.ConnectionStreamResponse - (*spannerpb.ExecuteSqlRequest)(nil), // 15: google.spanner.v1.ExecuteSqlRequest - (*spannerpb.ExecuteBatchDmlRequest)(nil), // 16: google.spanner.v1.ExecuteBatchDmlRequest - (*spannerpb.TransactionOptions)(nil), // 17: google.spanner.v1.TransactionOptions - (*spannerpb.BatchWriteRequest_MutationGroup)(nil), // 18: google.spanner.v1.BatchWriteRequest.MutationGroup - (*spannerpb.ResultSetMetadata)(nil), // 19: google.spanner.v1.ResultSetMetadata - (*structpb.ListValue)(nil), // 20: google.protobuf.ListValue - (*spannerpb.ResultSetStats)(nil), // 21: google.spanner.v1.ResultSetStats - (*spannerpb.PartialResultSet)(nil), // 22: google.spanner.v1.PartialResultSet - (*emptypb.Empty)(nil), // 23: google.protobuf.Empty - (*spannerpb.ExecuteBatchDmlResponse)(nil), // 24: google.spanner.v1.ExecuteBatchDmlResponse - (*spannerpb.CommitResponse)(nil), // 25: google.spanner.v1.CommitResponse + (*InfoRequest)(nil), // 0: google.spannerlib.v1.InfoRequest + (*InfoResponse)(nil), // 1: google.spannerlib.v1.InfoResponse + (*CreatePoolRequest)(nil), // 2: google.spannerlib.v1.CreatePoolRequest + (*CreateConnectionRequest)(nil), // 3: google.spannerlib.v1.CreateConnectionRequest + (*ExecuteRequest)(nil), // 4: google.spannerlib.v1.ExecuteRequest + (*ExecuteBatchRequest)(nil), // 5: google.spannerlib.v1.ExecuteBatchRequest + (*BeginTransactionRequest)(nil), // 6: google.spannerlib.v1.BeginTransactionRequest + (*WriteMutationsRequest)(nil), // 7: google.spannerlib.v1.WriteMutationsRequest + (*Pool)(nil), // 8: google.spannerlib.v1.Pool + (*Connection)(nil), // 9: google.spannerlib.v1.Connection + (*Rows)(nil), // 10: google.spannerlib.v1.Rows + (*NextRequest)(nil), // 11: google.spannerlib.v1.NextRequest + (*RowData)(nil), // 12: google.spannerlib.v1.RowData + (*MetadataRequest)(nil), // 13: google.spannerlib.v1.MetadataRequest + (*ResultSetStatsRequest)(nil), // 14: google.spannerlib.v1.ResultSetStatsRequest + (*ConnectionStreamRequest)(nil), // 15: google.spannerlib.v1.ConnectionStreamRequest + (*ConnectionStreamResponse)(nil), // 16: google.spannerlib.v1.ConnectionStreamResponse + (*spannerpb.ExecuteSqlRequest)(nil), // 17: google.spanner.v1.ExecuteSqlRequest + (*spannerpb.ExecuteBatchDmlRequest)(nil), // 18: google.spanner.v1.ExecuteBatchDmlRequest + (*spannerpb.TransactionOptions)(nil), // 19: google.spanner.v1.TransactionOptions + (*spannerpb.BatchWriteRequest_MutationGroup)(nil), // 20: google.spanner.v1.BatchWriteRequest.MutationGroup + (*spannerpb.ResultSetMetadata)(nil), // 21: google.spanner.v1.ResultSetMetadata + (*structpb.ListValue)(nil), // 22: google.protobuf.ListValue + (*spannerpb.ResultSetStats)(nil), // 23: google.spanner.v1.ResultSetStats + (*spannerpb.PartialResultSet)(nil), // 24: google.spanner.v1.PartialResultSet + (*emptypb.Empty)(nil), // 25: google.protobuf.Empty + (*spannerpb.ExecuteBatchDmlResponse)(nil), // 26: google.spanner.v1.ExecuteBatchDmlResponse + (*spannerpb.CommitResponse)(nil), // 27: google.spanner.v1.CommitResponse } var file_google_spannerlib_v1_spannerlib_proto_depIdxs = []int32{ - 6, // 0: google.spannerlib.v1.CreateConnectionRequest.pool:type_name -> google.spannerlib.v1.Pool - 7, // 1: google.spannerlib.v1.ExecuteRequest.connection:type_name -> google.spannerlib.v1.Connection - 15, // 2: google.spannerlib.v1.ExecuteRequest.execute_sql_request:type_name -> google.spanner.v1.ExecuteSqlRequest - 7, // 3: google.spannerlib.v1.ExecuteBatchRequest.connection:type_name -> google.spannerlib.v1.Connection - 16, // 4: google.spannerlib.v1.ExecuteBatchRequest.execute_batch_dml_request:type_name -> google.spanner.v1.ExecuteBatchDmlRequest - 7, // 5: google.spannerlib.v1.BeginTransactionRequest.connection:type_name -> google.spannerlib.v1.Connection - 17, // 6: google.spannerlib.v1.BeginTransactionRequest.transaction_options:type_name -> google.spanner.v1.TransactionOptions - 7, // 7: google.spannerlib.v1.WriteMutationsRequest.connection:type_name -> google.spannerlib.v1.Connection - 18, // 8: google.spannerlib.v1.WriteMutationsRequest.mutations:type_name -> google.spanner.v1.BatchWriteRequest.MutationGroup - 6, // 9: google.spannerlib.v1.Connection.pool:type_name -> google.spannerlib.v1.Pool - 7, // 10: google.spannerlib.v1.Rows.connection:type_name -> google.spannerlib.v1.Connection - 8, // 11: google.spannerlib.v1.NextRequest.rows:type_name -> google.spannerlib.v1.Rows - 8, // 12: google.spannerlib.v1.RowData.rows:type_name -> google.spannerlib.v1.Rows - 19, // 13: google.spannerlib.v1.RowData.metadata:type_name -> google.spanner.v1.ResultSetMetadata - 20, // 14: google.spannerlib.v1.RowData.data:type_name -> google.protobuf.ListValue - 21, // 15: google.spannerlib.v1.RowData.stats:type_name -> google.spanner.v1.ResultSetStats - 8, // 16: google.spannerlib.v1.MetadataRequest.rows:type_name -> google.spannerlib.v1.Rows - 8, // 17: google.spannerlib.v1.ResultSetStatsRequest.rows:type_name -> google.spannerlib.v1.Rows - 2, // 18: google.spannerlib.v1.ConnectionStreamRequest.execute_request:type_name -> google.spannerlib.v1.ExecuteRequest - 22, // 19: google.spannerlib.v1.ConnectionStreamResponse.row:type_name -> google.spanner.v1.PartialResultSet - 0, // 20: google.spannerlib.v1.SpannerLib.CreatePool:input_type -> google.spannerlib.v1.CreatePoolRequest - 6, // 21: google.spannerlib.v1.SpannerLib.ClosePool:input_type -> google.spannerlib.v1.Pool - 1, // 22: google.spannerlib.v1.SpannerLib.CreateConnection:input_type -> google.spannerlib.v1.CreateConnectionRequest - 7, // 23: google.spannerlib.v1.SpannerLib.CloseConnection:input_type -> google.spannerlib.v1.Connection - 2, // 24: google.spannerlib.v1.SpannerLib.Execute:input_type -> google.spannerlib.v1.ExecuteRequest - 2, // 25: google.spannerlib.v1.SpannerLib.ExecuteStreaming:input_type -> google.spannerlib.v1.ExecuteRequest - 3, // 26: google.spannerlib.v1.SpannerLib.ExecuteBatch:input_type -> google.spannerlib.v1.ExecuteBatchRequest - 8, // 27: google.spannerlib.v1.SpannerLib.Metadata:input_type -> google.spannerlib.v1.Rows - 9, // 28: google.spannerlib.v1.SpannerLib.Next:input_type -> google.spannerlib.v1.NextRequest - 8, // 29: google.spannerlib.v1.SpannerLib.ResultSetStats:input_type -> google.spannerlib.v1.Rows - 8, // 30: google.spannerlib.v1.SpannerLib.CloseRows:input_type -> google.spannerlib.v1.Rows - 4, // 31: google.spannerlib.v1.SpannerLib.BeginTransaction:input_type -> google.spannerlib.v1.BeginTransactionRequest - 7, // 32: google.spannerlib.v1.SpannerLib.Commit:input_type -> google.spannerlib.v1.Connection - 7, // 33: google.spannerlib.v1.SpannerLib.Rollback:input_type -> google.spannerlib.v1.Connection - 5, // 34: google.spannerlib.v1.SpannerLib.WriteMutations:input_type -> google.spannerlib.v1.WriteMutationsRequest - 13, // 35: google.spannerlib.v1.SpannerLib.ConnectionStream:input_type -> google.spannerlib.v1.ConnectionStreamRequest - 6, // 36: google.spannerlib.v1.SpannerLib.CreatePool:output_type -> google.spannerlib.v1.Pool - 23, // 37: google.spannerlib.v1.SpannerLib.ClosePool:output_type -> google.protobuf.Empty - 7, // 38: google.spannerlib.v1.SpannerLib.CreateConnection:output_type -> google.spannerlib.v1.Connection - 23, // 39: google.spannerlib.v1.SpannerLib.CloseConnection:output_type -> google.protobuf.Empty - 8, // 40: google.spannerlib.v1.SpannerLib.Execute:output_type -> google.spannerlib.v1.Rows - 10, // 41: google.spannerlib.v1.SpannerLib.ExecuteStreaming:output_type -> google.spannerlib.v1.RowData - 24, // 42: google.spannerlib.v1.SpannerLib.ExecuteBatch:output_type -> google.spanner.v1.ExecuteBatchDmlResponse - 19, // 43: google.spannerlib.v1.SpannerLib.Metadata:output_type -> google.spanner.v1.ResultSetMetadata - 20, // 44: google.spannerlib.v1.SpannerLib.Next:output_type -> google.protobuf.ListValue - 21, // 45: google.spannerlib.v1.SpannerLib.ResultSetStats:output_type -> google.spanner.v1.ResultSetStats - 23, // 46: google.spannerlib.v1.SpannerLib.CloseRows:output_type -> google.protobuf.Empty - 23, // 47: google.spannerlib.v1.SpannerLib.BeginTransaction:output_type -> google.protobuf.Empty - 25, // 48: google.spannerlib.v1.SpannerLib.Commit:output_type -> google.spanner.v1.CommitResponse - 23, // 49: google.spannerlib.v1.SpannerLib.Rollback:output_type -> google.protobuf.Empty - 25, // 50: google.spannerlib.v1.SpannerLib.WriteMutations:output_type -> google.spanner.v1.CommitResponse - 14, // 51: google.spannerlib.v1.SpannerLib.ConnectionStream:output_type -> google.spannerlib.v1.ConnectionStreamResponse - 36, // [36:52] is the sub-list for method output_type - 20, // [20:36] is the sub-list for method input_type + 8, // 0: google.spannerlib.v1.CreateConnectionRequest.pool:type_name -> google.spannerlib.v1.Pool + 9, // 1: google.spannerlib.v1.ExecuteRequest.connection:type_name -> google.spannerlib.v1.Connection + 17, // 2: google.spannerlib.v1.ExecuteRequest.execute_sql_request:type_name -> google.spanner.v1.ExecuteSqlRequest + 9, // 3: google.spannerlib.v1.ExecuteBatchRequest.connection:type_name -> google.spannerlib.v1.Connection + 18, // 4: google.spannerlib.v1.ExecuteBatchRequest.execute_batch_dml_request:type_name -> google.spanner.v1.ExecuteBatchDmlRequest + 9, // 5: google.spannerlib.v1.BeginTransactionRequest.connection:type_name -> google.spannerlib.v1.Connection + 19, // 6: google.spannerlib.v1.BeginTransactionRequest.transaction_options:type_name -> google.spanner.v1.TransactionOptions + 9, // 7: google.spannerlib.v1.WriteMutationsRequest.connection:type_name -> google.spannerlib.v1.Connection + 20, // 8: google.spannerlib.v1.WriteMutationsRequest.mutations:type_name -> google.spanner.v1.BatchWriteRequest.MutationGroup + 8, // 9: google.spannerlib.v1.Connection.pool:type_name -> google.spannerlib.v1.Pool + 9, // 10: google.spannerlib.v1.Rows.connection:type_name -> google.spannerlib.v1.Connection + 10, // 11: google.spannerlib.v1.NextRequest.rows:type_name -> google.spannerlib.v1.Rows + 10, // 12: google.spannerlib.v1.RowData.rows:type_name -> google.spannerlib.v1.Rows + 21, // 13: google.spannerlib.v1.RowData.metadata:type_name -> google.spanner.v1.ResultSetMetadata + 22, // 14: google.spannerlib.v1.RowData.data:type_name -> google.protobuf.ListValue + 23, // 15: google.spannerlib.v1.RowData.stats:type_name -> google.spanner.v1.ResultSetStats + 10, // 16: google.spannerlib.v1.MetadataRequest.rows:type_name -> google.spannerlib.v1.Rows + 10, // 17: google.spannerlib.v1.ResultSetStatsRequest.rows:type_name -> google.spannerlib.v1.Rows + 4, // 18: google.spannerlib.v1.ConnectionStreamRequest.execute_request:type_name -> google.spannerlib.v1.ExecuteRequest + 24, // 19: google.spannerlib.v1.ConnectionStreamResponse.row:type_name -> google.spanner.v1.PartialResultSet + 0, // 20: google.spannerlib.v1.SpannerLib.Info:input_type -> google.spannerlib.v1.InfoRequest + 2, // 21: google.spannerlib.v1.SpannerLib.CreatePool:input_type -> google.spannerlib.v1.CreatePoolRequest + 8, // 22: google.spannerlib.v1.SpannerLib.ClosePool:input_type -> google.spannerlib.v1.Pool + 3, // 23: google.spannerlib.v1.SpannerLib.CreateConnection:input_type -> google.spannerlib.v1.CreateConnectionRequest + 9, // 24: google.spannerlib.v1.SpannerLib.CloseConnection:input_type -> google.spannerlib.v1.Connection + 4, // 25: google.spannerlib.v1.SpannerLib.Execute:input_type -> google.spannerlib.v1.ExecuteRequest + 4, // 26: google.spannerlib.v1.SpannerLib.ExecuteStreaming:input_type -> google.spannerlib.v1.ExecuteRequest + 5, // 27: google.spannerlib.v1.SpannerLib.ExecuteBatch:input_type -> google.spannerlib.v1.ExecuteBatchRequest + 10, // 28: google.spannerlib.v1.SpannerLib.Metadata:input_type -> google.spannerlib.v1.Rows + 11, // 29: google.spannerlib.v1.SpannerLib.Next:input_type -> google.spannerlib.v1.NextRequest + 10, // 30: google.spannerlib.v1.SpannerLib.ResultSetStats:input_type -> google.spannerlib.v1.Rows + 10, // 31: google.spannerlib.v1.SpannerLib.CloseRows:input_type -> google.spannerlib.v1.Rows + 6, // 32: google.spannerlib.v1.SpannerLib.BeginTransaction:input_type -> google.spannerlib.v1.BeginTransactionRequest + 9, // 33: google.spannerlib.v1.SpannerLib.Commit:input_type -> google.spannerlib.v1.Connection + 9, // 34: google.spannerlib.v1.SpannerLib.Rollback:input_type -> google.spannerlib.v1.Connection + 7, // 35: google.spannerlib.v1.SpannerLib.WriteMutations:input_type -> google.spannerlib.v1.WriteMutationsRequest + 15, // 36: google.spannerlib.v1.SpannerLib.ConnectionStream:input_type -> google.spannerlib.v1.ConnectionStreamRequest + 1, // 37: google.spannerlib.v1.SpannerLib.Info:output_type -> google.spannerlib.v1.InfoResponse + 8, // 38: google.spannerlib.v1.SpannerLib.CreatePool:output_type -> google.spannerlib.v1.Pool + 25, // 39: google.spannerlib.v1.SpannerLib.ClosePool:output_type -> google.protobuf.Empty + 9, // 40: google.spannerlib.v1.SpannerLib.CreateConnection:output_type -> google.spannerlib.v1.Connection + 25, // 41: google.spannerlib.v1.SpannerLib.CloseConnection:output_type -> google.protobuf.Empty + 10, // 42: google.spannerlib.v1.SpannerLib.Execute:output_type -> google.spannerlib.v1.Rows + 12, // 43: google.spannerlib.v1.SpannerLib.ExecuteStreaming:output_type -> google.spannerlib.v1.RowData + 26, // 44: google.spannerlib.v1.SpannerLib.ExecuteBatch:output_type -> google.spanner.v1.ExecuteBatchDmlResponse + 21, // 45: google.spannerlib.v1.SpannerLib.Metadata:output_type -> google.spanner.v1.ResultSetMetadata + 22, // 46: google.spannerlib.v1.SpannerLib.Next:output_type -> google.protobuf.ListValue + 23, // 47: google.spannerlib.v1.SpannerLib.ResultSetStats:output_type -> google.spanner.v1.ResultSetStats + 25, // 48: google.spannerlib.v1.SpannerLib.CloseRows:output_type -> google.protobuf.Empty + 25, // 49: google.spannerlib.v1.SpannerLib.BeginTransaction:output_type -> google.protobuf.Empty + 27, // 50: google.spannerlib.v1.SpannerLib.Commit:output_type -> google.spanner.v1.CommitResponse + 25, // 51: google.spannerlib.v1.SpannerLib.Rollback:output_type -> google.protobuf.Empty + 27, // 52: google.spannerlib.v1.SpannerLib.WriteMutations:output_type -> google.spanner.v1.CommitResponse + 16, // 53: google.spannerlib.v1.SpannerLib.ConnectionStream:output_type -> google.spannerlib.v1.ConnectionStreamResponse + 37, // [37:54] is the sub-list for method output_type + 20, // [20:37] is the sub-list for method input_type 20, // [20:20] is the sub-list for extension type_name 20, // [20:20] is the sub-list for extension extendee 0, // [0:20] is the sub-list for field type_name @@ -1005,10 +1092,10 @@ func file_google_spannerlib_v1_spannerlib_proto_init() { if File_google_spannerlib_v1_spannerlib_proto != nil { return } - file_google_spannerlib_v1_spannerlib_proto_msgTypes[13].OneofWrappers = []any{ + file_google_spannerlib_v1_spannerlib_proto_msgTypes[15].OneofWrappers = []any{ (*ConnectionStreamRequest_ExecuteRequest)(nil), } - file_google_spannerlib_v1_spannerlib_proto_msgTypes[14].OneofWrappers = []any{ + file_google_spannerlib_v1_spannerlib_proto_msgTypes[16].OneofWrappers = []any{ (*ConnectionStreamResponse_Row)(nil), } type x struct{} @@ -1017,7 +1104,7 @@ func file_google_spannerlib_v1_spannerlib_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_google_spannerlib_v1_spannerlib_proto_rawDesc), len(file_google_spannerlib_v1_spannerlib_proto_rawDesc)), NumEnums: 0, - NumMessages: 15, + NumMessages: 17, NumExtensions: 0, NumServices: 1, }, diff --git a/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.proto b/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.proto index 22d6e680..57d58b41 100644 --- a/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.proto +++ b/spannerlib/grpc-server/google/spannerlib/v1/spannerlib.proto @@ -18,6 +18,8 @@ option php_namespace = "Google\\Cloud\\SpannerLib\\V1"; option ruby_package = "Google::Cloud::SpannerLib::V1"; service SpannerLib { + rpc Info(InfoRequest) returns (InfoResponse) {} + rpc CreatePool(CreatePoolRequest) returns (Pool) {} rpc ClosePool(Pool) returns (google.protobuf.Empty) {} @@ -41,6 +43,13 @@ service SpannerLib { rpc ConnectionStream(stream ConnectionStreamRequest) returns (stream ConnectionStreamResponse) {} } +message InfoRequest { +} + +message InfoResponse { + string version = 1; +} + message CreatePoolRequest { string connection_string = 1 [ (google.api.field_behavior) = REQUIRED diff --git a/spannerlib/grpc-server/google/spannerlib/v1/spannerlib_grpc.pb.go b/spannerlib/grpc-server/google/spannerlib/v1/spannerlib_grpc.pb.go index a0f8c2bd..b52dd75c 100644 --- a/spannerlib/grpc-server/google/spannerlib/v1/spannerlib_grpc.pb.go +++ b/spannerlib/grpc-server/google/spannerlib/v1/spannerlib_grpc.pb.go @@ -22,6 +22,7 @@ import ( const _ = grpc.SupportPackageIsVersion9 const ( + SpannerLib_Info_FullMethodName = "/google.spannerlib.v1.SpannerLib/Info" SpannerLib_CreatePool_FullMethodName = "/google.spannerlib.v1.SpannerLib/CreatePool" SpannerLib_ClosePool_FullMethodName = "/google.spannerlib.v1.SpannerLib/ClosePool" SpannerLib_CreateConnection_FullMethodName = "/google.spannerlib.v1.SpannerLib/CreateConnection" @@ -44,6 +45,7 @@ const ( // // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type SpannerLibClient interface { + Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) CreatePool(ctx context.Context, in *CreatePoolRequest, opts ...grpc.CallOption) (*Pool, error) ClosePool(ctx context.Context, in *Pool, opts ...grpc.CallOption) (*emptypb.Empty, error) CreateConnection(ctx context.Context, in *CreateConnectionRequest, opts ...grpc.CallOption) (*Connection, error) @@ -70,6 +72,16 @@ func NewSpannerLibClient(cc grpc.ClientConnInterface) SpannerLibClient { return &spannerLibClient{cc} } +func (c *spannerLibClient) Info(ctx context.Context, in *InfoRequest, opts ...grpc.CallOption) (*InfoResponse, error) { + cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out := new(InfoResponse) + err := c.cc.Invoke(ctx, SpannerLib_Info_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *spannerLibClient) CreatePool(ctx context.Context, in *CreatePoolRequest, opts ...grpc.CallOption) (*Pool, error) { cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...) out := new(Pool) @@ -246,6 +258,7 @@ type SpannerLib_ConnectionStreamClient = grpc.BidiStreamingClient[ConnectionStre // All implementations must embed UnimplementedSpannerLibServer // for forward compatibility. type SpannerLibServer interface { + Info(context.Context, *InfoRequest) (*InfoResponse, error) CreatePool(context.Context, *CreatePoolRequest) (*Pool, error) ClosePool(context.Context, *Pool) (*emptypb.Empty, error) CreateConnection(context.Context, *CreateConnectionRequest) (*Connection, error) @@ -272,6 +285,9 @@ type SpannerLibServer interface { // pointer dereference when methods are called. type UnimplementedSpannerLibServer struct{} +func (UnimplementedSpannerLibServer) Info(context.Context, *InfoRequest) (*InfoResponse, error) { + return nil, status.Errorf(codes.Unimplemented, "method Info not implemented") +} func (UnimplementedSpannerLibServer) CreatePool(context.Context, *CreatePoolRequest) (*Pool, error) { return nil, status.Errorf(codes.Unimplemented, "method CreatePool not implemented") } @@ -341,6 +357,24 @@ func RegisterSpannerLibServer(s grpc.ServiceRegistrar, srv SpannerLibServer) { s.RegisterService(&SpannerLib_ServiceDesc, srv) } +func _SpannerLib_Info_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(InfoRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(SpannerLibServer).Info(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: SpannerLib_Info_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(SpannerLibServer).Info(ctx, req.(*InfoRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _SpannerLib_CreatePool_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(CreatePoolRequest) if err := dec(in); err != nil { @@ -618,6 +652,10 @@ var SpannerLib_ServiceDesc = grpc.ServiceDesc{ ServiceName: "google.spannerlib.v1.SpannerLib", HandlerType: (*SpannerLibServer)(nil), Methods: []grpc.MethodDesc{ + { + MethodName: "Info", + Handler: _SpannerLib_Info_Handler, + }, { MethodName: "CreatePool", Handler: _SpannerLib_CreatePool_Handler, diff --git a/spannerlib/grpc-server/server.go b/spannerlib/grpc-server/server.go index a16fc758..0235659b 100644 --- a/spannerlib/grpc-server/server.go +++ b/spannerlib/grpc-server/server.go @@ -48,6 +48,10 @@ type spannerLibServer struct { pb.UnimplementedSpannerLibServer } +func (s *spannerLibServer) Info(_ context.Context, _ *pb.InfoRequest) (*pb.InfoResponse, error) { + return &pb.InfoResponse{}, nil +} + func (s *spannerLibServer) CreatePool(ctx context.Context, request *pb.CreatePoolRequest) (*pb.Pool, error) { id, err := api.CreatePool(ctx, request.ConnectionString) if err != nil { diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/GrpcLibSpanner.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/GrpcLibSpanner.cs new file mode 100644 index 00000000..3b65f917 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/GrpcLibSpanner.cs @@ -0,0 +1,403 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Net.Http; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using Google.Cloud.Spanner.V1; +using Google.Cloud.SpannerLib.V1; +using Google.Protobuf.WellKnownTypes; +using Grpc.Core; +using Grpc.Net.Client; +using BeginTransactionRequest = Google.Cloud.SpannerLib.V1.BeginTransactionRequest; +using Status = Google.Rpc.Status; + +namespace Google.Cloud.SpannerLib.Grpc; + +public class GrpcLibSpanner : ISpannerLib +{ + public static GrpcChannel ForUnixSocket(string fileName) + { + var endpoint = new UnixDomainSocketEndPoint(fileName); + return GrpcChannel.ForAddress("http://localhost", new GrpcChannelOptions { + HttpHandler = new SocketsHttpHandler { + EnableMultipleHttp2Connections = true, + ConnectCallback = async (_, cancellationToken) => { + var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.Unspecified); + try { + await socket.ConnectAsync(endpoint, cancellationToken).ConfigureAwait(false); + return new NetworkStream(socket, true); + } catch { + socket.Dispose(); + throw; + } + } + } + }); + } + + public static GrpcChannel ForTcpSocket(string address) + { + return GrpcChannel.ForAddress($"http://{address}", new GrpcChannelOptions + { + HttpHandler = new SocketsHttpHandler + { + EnableMultipleHttp2Connections = true, + } + }); + } + + private readonly Server _server; + private readonly V1.SpannerLib.SpannerLibClient _client; + private readonly GrpcChannel _channel; + private readonly V1.SpannerLib.SpannerLibClient[] _clients; + private readonly GrpcChannel[] _channels; + private readonly bool _useStreamingRows; + private bool _disposed; + + public GrpcLibSpanner(bool useStreamingRows = true, Server.AddressType addressType = Server.AddressType.UnixDomainSocket) + { + _server = new Server(); + var file = _server.Start(addressType: addressType); + _channel = addressType == Server.AddressType.Tcp ? ForTcpSocket(file) : ForUnixSocket(file); + _client = new V1.SpannerLib.SpannerLibClient(_channel); + _useStreamingRows = useStreamingRows; + + var numChannels = 1; + _channels = new GrpcChannel[numChannels]; + _clients = new V1.SpannerLib.SpannerLibClient[numChannels]; + for (var i = 0; i < numChannels; i++) + { + _channels[i] = addressType == Server.AddressType.Tcp ? ForTcpSocket(file) : ForUnixSocket(file); + _clients[i] = new V1.SpannerLib.SpannerLibClient(_channels[i]); + } + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + try + { + _channel.Dispose(); + foreach (var channel in _channels) + { + channel.Dispose(); + } + _server.Dispose(); + } + finally + { + _disposed = true; + } + } + + T TranslateException(Func f) + { + try + { + return f.Invoke(); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + public Pool CreatePool(string connectionString) + { + return FromProto(TranslateException(() => _client.CreatePool(new CreatePoolRequest + { + ConnectionString = connectionString, + }))); + } + + public void ClosePool(Pool pool) + { + TranslateException(() => _client.ClosePool(ToProto(pool))); + } + + public Connection CreateConnection(Pool pool) + { + return FromProto(pool, TranslateException(() => _client.CreateConnection(new CreateConnectionRequest + { + Pool = ToProto(pool), + }))); + } + + public void CloseConnection(Connection connection) + { + TranslateException(() => _client.CloseConnection(ToProto(connection))); + } + + public async Task CloseConnectionAsync(Connection connection, CancellationToken cancellationToken = default) + { + try + { + await _client.CloseConnectionAsync(ToProto(connection), cancellationToken: cancellationToken); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + public CommitResponse? WriteMutations(Connection connection, BatchWriteRequest.Types.MutationGroup mutations) + { + var response = TranslateException(() => _client.WriteMutations(new WriteMutationsRequest + { + Connection = ToProto(connection), + Mutations = mutations, + })); + return response.CommitTimestamp == null ? null : response; + } + + public Rows Execute(Connection connection, ExecuteSqlRequest statement) + { + if (_useStreamingRows) + { + return ExecuteStreaming(connection, statement); + } + return FromProto(connection, TranslateException(() => _client.Execute(new ExecuteRequest + { + Connection = ToProto(connection), + ExecuteSqlRequest = statement, + }))); + } + + private StreamingRows ExecuteStreaming(Connection connection, ExecuteSqlRequest statement) + { + var client = _clients[Random.Shared.Next(_clients.Length)]; + var stream = TranslateException(() => client.ExecuteStreaming(new ExecuteRequest + { + Connection = ToProto(connection), + ExecuteSqlRequest = statement, + })); + return StreamingRows.Create(connection, stream); + } + + public async Task ExecuteAsync(Connection connection, ExecuteSqlRequest statement, CancellationToken cancellationToken = default) + { + try + { + if (_useStreamingRows) + { + return await ExecuteStreamingAsync(connection, statement, cancellationToken); + } + var rows = await _client.ExecuteAsync(new ExecuteRequest + { + Connection = ToProto(connection), + ExecuteSqlRequest = statement, + }, cancellationToken: cancellationToken); + return FromProto(connection, rows); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + private async Task ExecuteStreamingAsync(Connection connection, ExecuteSqlRequest statement, CancellationToken cancellationToken = default) + { + var client = _clients[Random.Shared.Next(_clients.Length)]; + var stream = TranslateException(() => client.ExecuteStreaming(new ExecuteRequest + { + Connection = ToProto(connection), + ExecuteSqlRequest = statement, + })); + return await StreamingRows.CreateAsync(connection, stream, cancellationToken); + } + + public long[] ExecuteBatch(Connection connection, ExecuteBatchDmlRequest statements) + { + var response = TranslateException(() => _client.ExecuteBatch(new ExecuteBatchRequest + { + Connection = ToProto(connection), + ExecuteBatchDmlRequest = statements, + })); + var result = new long[response.ResultSets.Count]; + for (var i = 0; i < result.Length; i++) + { + if (response.ResultSets[i].Stats.HasRowCountExact) + { + result[i] = response.ResultSets[i].Stats.RowCountExact; + } + else if (response.ResultSets[i].Stats.HasRowCountLowerBound) + { + result[i] = response.ResultSets[i].Stats.RowCountLowerBound; + } + else + { + result[i] = -1; + } + } + return result; + } + + public async Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequest statements, CancellationToken cancellationToken = default) + { + try + { + var stats = await _client.ExecuteBatchAsync(new ExecuteBatchRequest + { + Connection = ToProto(connection), + ExecuteBatchDmlRequest = statements, + }, cancellationToken: cancellationToken); + var result = new long[stats.ResultSets.Count]; + for (var i = 0; i < result.Length; i++) + { + result[i] = stats.ResultSets[i].Stats.RowCountExact; + } + return result; + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + public ResultSetMetadata? Metadata(Rows rows) + { + return TranslateException(() => _client.Metadata(ToProto(rows))); + } + + public async Task MetadataAsync(Rows rows, CancellationToken cancellationToken = default) + { + try + { + return await _client.MetadataAsync(ToProto(rows), cancellationToken: cancellationToken); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + public ResultSetStats? Stats(Rows rows) + { + return TranslateException(() => _client.ResultSetStats(ToProto(rows))); + } + + public ListValue? Next(Rows rows, int numRows, ISpannerLib.RowEncoding encoding) + { + var row = TranslateException(() =>_client.Next(new NextRequest + { + Rows = ToProto(rows), + NumRows = numRows, + Encoding = (long) encoding, + })); + return row.Values.Count == 0 ? null : row; + } + + public async Task NextAsync(Rows rows, int numRows, ISpannerLib.RowEncoding encoding, CancellationToken cancellationToken = default) + { + try + { + return await _client.NextAsync(new NextRequest + { + Rows = ToProto(rows), + NumRows = numRows, + Encoding = (long)encoding, + }, cancellationToken: cancellationToken); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + public void CloseRows(Rows rows) + { + TranslateException(() => _client.CloseRows(ToProto(rows))); + } + + public async Task CloseRowsAsync(Rows rows, CancellationToken cancellationToken = default) + { + try + { + await _client.CloseRowsAsync(ToProto(rows), cancellationToken: cancellationToken); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + public void BeginTransaction(Connection connection, TransactionOptions transactionOptions) + { + TranslateException(() => _client.BeginTransaction(new BeginTransactionRequest + { + Connection = ToProto(connection), + TransactionOptions = transactionOptions, + })); + } + + public CommitResponse? Commit(Connection connection) + { + var response = TranslateException(() => _client.Commit(ToProto(connection))); + return response.CommitTimestamp == null ? null : response; + } + + public async Task CommitAsync(Connection connection, CancellationToken cancellationToken = default) + { + try + { + var response = await _client.CommitAsync(ToProto(connection), cancellationToken: cancellationToken); + return response.CommitTimestamp == null ? null : response; + } + catch (RpcException exception) + { + throw new SpannerException(new Status { Code = (int) exception.Status.StatusCode, Message = exception.Status.Detail }); + } + } + + public void Rollback(Connection connection) + { + TranslateException(() => _client.Rollback(ToProto(connection))); + } + + public async Task RollbackAsync(Connection connection, CancellationToken cancellationToken = default) + { + try + { + await _client.RollbackAsync(ToProto(connection), cancellationToken: cancellationToken); + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } + + Pool FromProto(V1.Pool pool) => new(this, pool.Id); + + V1.Pool ToProto(Pool pool) => new() { Id = pool.Id }; + + Connection FromProto(Pool pool, V1.Connection proto) => new(pool, proto.Id); + + V1.Connection ToProto(Connection connection) => new() { Id = connection.Id, Pool = ToProto(connection.Pool), }; + + Rows FromProto(Connection connection, V1.Rows proto) => new(connection, proto.Id); + + V1.Rows ToProto(Rows rows) => new() { Id = rows.Id, Connection = ToProto(rows.SpannerConnection), }; +} \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/StreamingRows.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/StreamingRows.cs new file mode 100644 index 00000000..1d0c21bf --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/StreamingRows.cs @@ -0,0 +1,131 @@ +using System.Threading; +using System.Threading.Tasks; +using Google.Api.Gax; +using Google.Cloud.Spanner.V1; +using Google.Cloud.SpannerLib.V1; +using Google.Protobuf.WellKnownTypes; +using Grpc.Core; +using Status = Google.Rpc.Status; + +namespace Google.Cloud.SpannerLib.Grpc; + +public class StreamingRows : Rows +{ + private readonly AsyncServerStreamingCall _stream; + private ListValue? _pendingRow; + private ResultSetMetadata? _metadata; + private ResultSetStats? _stats; + private bool _done; + + protected override ResultSetStats? Stats => _stats; + + public override ResultSetMetadata? Metadata => _metadata; + + public static StreamingRows Create(Connection connection, AsyncServerStreamingCall stream) + { + var rows = new StreamingRows(connection, stream); + rows._pendingRow = rows.Next(); + return rows; + } + + public static async Task CreateAsync(Connection connection, AsyncServerStreamingCall stream, CancellationToken cancellationToken = default) + { + var rows = new StreamingRows(connection, stream); + rows._pendingRow = await rows.NextAsync(cancellationToken); + return rows; + } + + private StreamingRows(Connection connection, AsyncServerStreamingCall stream) : base(connection, 0, initMetadata: false) + { + _stream = stream; + } + + protected override void Dispose(bool disposing) + { + if (!_done) + { + MarkDone(); + } + _stream.Dispose(); + base.Dispose(disposing); + } + + private void MarkDone() + { + _done = true; + } + + public override ListValue? Next() + { + if (_pendingRow != null) { + var row = _pendingRow; + _pendingRow = null; + return row; + } + try + { + var hasNext = Task.Run(() => _stream.ResponseStream.MoveNext()).ResultWithUnwrappedExceptions(); + if (!hasNext) + { + MarkDone(); + return null; + } + var rowData = _stream.ResponseStream.Current; + if (rowData.Metadata != null) + { + _metadata = rowData.Metadata; + } + if (rowData.Stats != null) + { + _stats = rowData.Stats; + } + if (rowData.Data.Count == 0) + { + MarkDone(); + return null; + } + return rowData.Data[0]; + } + catch (RpcException exception) + { + throw new SpannerException(new Status { Code = (int) exception.Status.StatusCode, Message = exception.Status.Detail }); + } + } + + public override async Task NextAsync(CancellationToken cancellationToken = default) + { + if (_pendingRow != null) { + var row = _pendingRow; + _pendingRow = null; + return row; + } + try + { + var hasNext = await _stream.ResponseStream.MoveNext(cancellationToken); + if (!hasNext) + { + MarkDone(); + return null; + } + var rowData = _stream.ResponseStream.Current; + if (rowData.Metadata != null) + { + _metadata = rowData.Metadata; + } + if (rowData.Stats != null) + { + _stats = rowData.Stats; + } + if (rowData.Data.Count == 0) + { + MarkDone(); + return null; + } + return rowData.Data[0]; + } + catch (RpcException exception) + { + throw SpannerException.ToSpannerException(exception); + } + } +} \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/spannerlib-dotnet-grpc-impl.csproj b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/spannerlib-dotnet-grpc-impl.csproj new file mode 100644 index 00000000..d892dd9b --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-impl/spannerlib-dotnet-grpc-impl.csproj @@ -0,0 +1,19 @@ + + + + net8.0 + Google.Cloud.SpannerLib.Grpc + enable + default + + + + + + + + + + + + diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs new file mode 100644 index 00000000..436869da --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs @@ -0,0 +1,191 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System; +using System.Diagnostics; +using System.IO; +using System.Runtime.InteropServices; +using System.Threading; + +namespace Google.Cloud.SpannerLib.Grpc; + +public class Server : IDisposable +{ + public enum AddressType + { + UnixDomainSocket, + Tcp, + } + + private Process? _process; + private string? _host; + private bool _disposed; + + public bool IsRunning => _process is { HasExited: false }; + + public Server() + { + } + + public string Start(AddressType addressType = AddressType.UnixDomainSocket) + { + if (_disposed) + { + throw new ObjectDisposedException(nameof(Server)); + } + if (IsRunning) + { + throw new InvalidOperationException("The server is already started."); + } + (_host, _process) = StartGrpcServer(addressType); + return _host; + } + + private static Tuple StartGrpcServer(AddressType addressType) + { + string arguments; + if (addressType == AddressType.UnixDomainSocket) + { + // Generate a random temp file name that will be used for the Unix domain socket communication. + arguments = Path.GetTempPath() + Guid.NewGuid(); + } + else if (addressType == AddressType.Tcp) + { + arguments = "localhost:0 tcp"; + } + else + { + arguments = "localhost:0 tcp"; + } + + var binaryFileName = GetBinaryFileName().Replace('/', Path.DirectorySeparatorChar); + var info = new ProcessStartInfo + { + Arguments = arguments, + UseShellExecute = false, + FileName = binaryFileName, + RedirectStandardOutput = true, + RedirectStandardError = true, + }; + // Start the process as a child process. The process will automatically stop when the + // parent process stops. + var process = Process.Start(info); + if (process == null) + { + throw new InvalidOperationException("Failed to start spanner"); + } + if (addressType == AddressType.UnixDomainSocket) + { + while (!File.Exists(arguments)) + { + Thread.Sleep(1); + } + } + if (addressType == AddressType.UnixDomainSocket) + { + // Return the name of the Unix domain socket. + return Tuple.Create(arguments, process); + } + // Read the dynamically assigned port. + var address = process.StandardError.ReadLine(); + if (address?.Contains("Starting gRPC server on") ?? false) + { + var lastSpace = address.LastIndexOf(" ", StringComparison.Ordinal); + return Tuple.Create(address.Substring(lastSpace + 1), process); + } + throw new InvalidOperationException("Failed to read gRPC address"); + } + + private static string GetBinaryFileName() + { + string? fileName = null; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + switch (RuntimeInformation.OSArchitecture) + { + case Architecture.X64: + fileName = "runtimes/win-x64/native/grpc_server.exe"; + break; + } + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + switch (RuntimeInformation.OSArchitecture) + { + case Architecture.X64: + fileName = "runtimes/linux-x64/native/grpc_server"; + break; + } + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + switch (RuntimeInformation.ProcessArchitecture) + { + case Architecture.Arm64: + fileName = "runtimes/osx-arm64/native/grpc_server"; + break; + } + } + if (fileName != null && File.Exists(fileName)) + { + return fileName; + } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (File.Exists("runtimes/any/native/grpc_server.exe")) + { + return "runtimes/any/native/grpc_server.exe"; + } + } + if (File.Exists("runtimes/any/native/grpc_server")) + { + return "runtimes/any/native/grpc_server"; + } + + throw new PlatformNotSupportedException(); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + public void Stop() + { + if (_process == null || _process.HasExited) + { + return; + } + _process.Kill(); + _process.WaitForExit(); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + try + { + Stop(); + _process?.Dispose(); + } + finally + { + _disposed = true; + } + } +} \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/build.sh b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/build.sh new file mode 100755 index 00000000..308e2328 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/build.sh @@ -0,0 +1,16 @@ +# Builds the gRPC server and the binary .NET wrapper and install the latter in a local nuget repository. + +# Determine OS + Arch +export DEST=binaries/any/grpc_server +mkdir -p binaries/any +mkdir -p binaries/osx-arm64 + +# Clear all local nuget cache +dotnet nuget locals --clear all +go build -o ../../../grpc-server/grpc_server ../../../grpc-server/server.go +cp ../../../grpc-server/grpc_server $DEST +cp ../../../grpc-server/grpc_server binaries/osx-arm64/grpc_server +dotnet pack +dotnet nuget remove source local_grpc_server 2>/dev/null +dotnet nuget add source "$PWD"/bin/Release --name local_grpc_server +dotnet restore ../spannerlib-dotnet-grpc-impl diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/spannerlib-dotnet-grpc-server.csproj b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/spannerlib-dotnet-grpc-server.csproj new file mode 100644 index 00000000..644c78f9 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/spannerlib-dotnet-grpc-server.csproj @@ -0,0 +1,19 @@ + + + + netstandard2.1 + Google.Cloud.SpannerLib.Grpc + enable + default + Google.Cloud.SpannerLib.GrpcServer + SpannerLib Grpc Server + Google + + + + + + + + + diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/ServerTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/ServerTests.cs new file mode 100644 index 00000000..ff243f47 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/ServerTests.cs @@ -0,0 +1,50 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Google.Cloud.SpannerLib.V1; + +namespace Google.Cloud.SpannerLib.Grpc; + +public class Tests +{ + private Server _server; + + [SetUp] + public void Setup() + { + _server = new Server(); + } + + [TearDown] + public void TearDown() + { + _server.Dispose(); + } + + [Test] + public void TestStartStop() + { + Assert.That(_server.IsRunning, Is.False); + var file = _server.Start(); + Assert.That(_server.IsRunning, Is.True); + + using var channel = GrpcLibSpanner.ForUnixSocket(file); + var client = new V1.SpannerLib.SpannerLibClient(channel); + var info = client.Info(new InfoRequest()); + Assert.That(info, Is.Not.Null); + + _server.Stop(); + Assert.That(_server.IsRunning, Is.False); + } +} \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/spannerlib-dotnet-grpc-tests.csproj b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/spannerlib-dotnet-grpc-tests.csproj new file mode 100644 index 00000000..eaca43e4 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-tests/spannerlib-dotnet-grpc-tests.csproj @@ -0,0 +1,28 @@ + + + + net9.0 + Google.Cloud.SpannerLib.Grpc + latest + enable + enable + false + + + + + + + + + + + + + + + + + + + diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/Spannerlib.g.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/Spannerlib.g.cs new file mode 100644 index 00000000..14132a1d --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/Spannerlib.g.cs @@ -0,0 +1,4102 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/spannerlib/v1/spannerlib.proto +// +#pragma warning disable 1591, 0612, 3021, 8981 +#region Designer generated code + +using pb = global::Google.Protobuf; +using pbc = global::Google.Protobuf.Collections; +using pbr = global::Google.Protobuf.Reflection; +using scg = global::System.Collections.Generic; +namespace Google.Cloud.SpannerLib.V1 { + + /// Holder for reflection information generated from google/spannerlib/v1/spannerlib.proto + public static partial class SpannerlibReflection { + + #region Descriptor + /// File descriptor for google/spannerlib/v1/spannerlib.proto + public static pbr::FileDescriptor Descriptor { + get { return descriptor; } + } + private static pbr::FileDescriptor descriptor; + + static SpannerlibReflection() { + byte[] descriptorData = global::System.Convert.FromBase64String( + string.Concat( + "CiVnb29nbGUvc3Bhbm5lcmxpYi92MS9zcGFubmVybGliLnByb3RvEhRnb29n", + "bGUuc3Bhbm5lcmxpYi52MRofZ29vZ2xlL2FwaS9maWVsZF9iZWhhdmlvci5w", + "cm90bxobZ29vZ2xlL3Byb3RvYnVmL2VtcHR5LnByb3RvGhxnb29nbGUvcHJv", + "dG9idWYvc3RydWN0LnByb3RvGiJnb29nbGUvc3Bhbm5lci92MS9yZXN1bHRf", + "c2V0LnByb3RvGh9nb29nbGUvc3Bhbm5lci92MS9zcGFubmVyLnByb3RvGiNn", + "b29nbGUvc3Bhbm5lci92MS90cmFuc2FjdGlvbi5wcm90byINCgtJbmZvUmVx", + "dWVzdCIfCgxJbmZvUmVzcG9uc2USDwoHdmVyc2lvbhgBIAEoCSIzChFDcmVh", + "dGVQb29sUmVxdWVzdBIeChFjb25uZWN0aW9uX3N0cmluZxgBIAEoCUID4EEC", + "IkgKF0NyZWF0ZUNvbm5lY3Rpb25SZXF1ZXN0Ei0KBHBvb2wYASABKAsyGi5n", + "b29nbGUuc3Bhbm5lcmxpYi52MS5Qb29sQgPgQQIikwEKDkV4ZWN1dGVSZXF1", + "ZXN0EjkKCmNvbm5lY3Rpb24YASABKAsyIC5nb29nbGUuc3Bhbm5lcmxpYi52", + "MS5Db25uZWN0aW9uQgPgQQISRgoTZXhlY3V0ZV9zcWxfcmVxdWVzdBgCIAEo", + "CzIkLmdvb2dsZS5zcGFubmVyLnYxLkV4ZWN1dGVTcWxSZXF1ZXN0QgPgQQIi", + "owEKE0V4ZWN1dGVCYXRjaFJlcXVlc3QSOQoKY29ubmVjdGlvbhgBIAEoCzIg", + "Lmdvb2dsZS5zcGFubmVybGliLnYxLkNvbm5lY3Rpb25CA+BBAhJRChlleGVj", + "dXRlX2JhdGNoX2RtbF9yZXF1ZXN0GAIgASgLMikuZ29vZ2xlLnNwYW5uZXIu", + "djEuRXhlY3V0ZUJhdGNoRG1sUmVxdWVzdEID4EECIp0BChdCZWdpblRyYW5z", + "YWN0aW9uUmVxdWVzdBI5Cgpjb25uZWN0aW9uGAEgASgLMiAuZ29vZ2xlLnNw", + "YW5uZXJsaWIudjEuQ29ubmVjdGlvbkID4EECEkcKE3RyYW5zYWN0aW9uX29w", + "dGlvbnMYAiABKAsyJS5nb29nbGUuc3Bhbm5lci52MS5UcmFuc2FjdGlvbk9w", + "dGlvbnNCA+BBAiKeAQoVV3JpdGVNdXRhdGlvbnNSZXF1ZXN0EjkKCmNvbm5l", + "Y3Rpb24YASABKAsyIC5nb29nbGUuc3Bhbm5lcmxpYi52MS5Db25uZWN0aW9u", + "QgPgQQISSgoJbXV0YXRpb25zGAIgASgLMjIuZ29vZ2xlLnNwYW5uZXIudjEu", + "QmF0Y2hXcml0ZVJlcXVlc3QuTXV0YXRpb25Hcm91cEID4EECIhcKBFBvb2wS", + "DwoCaWQYASABKANCA+BBAiJMCgpDb25uZWN0aW9uEi0KBHBvb2wYASABKAsy", + "Gi5nb29nbGUuc3Bhbm5lcmxpYi52MS5Qb29sQgPgQQISDwoCaWQYAiABKANC", + "A+BBAiJSCgRSb3dzEjkKCmNvbm5lY3Rpb24YASABKAsyIC5nb29nbGUuc3Bh", + "bm5lcmxpYi52MS5Db25uZWN0aW9uQgPgQQISDwoCaWQYAiABKANCA+BBAiJq", + "CgtOZXh0UmVxdWVzdBItCgRyb3dzGAEgASgLMhouZ29vZ2xlLnNwYW5uZXJs", + "aWIudjEuUm93c0ID4EECEhUKCG51bV9yb3dzGAIgASgDQgPgQQISFQoIZW5j", + "b2RpbmcYAyABKANCA+BBAiLRAQoHUm93RGF0YRItCgRyb3dzGAEgASgLMhou", + "Z29vZ2xlLnNwYW5uZXJsaWIudjEuUm93c0ID4EECEjYKCG1ldGFkYXRhGAIg", + "ASgLMiQuZ29vZ2xlLnNwYW5uZXIudjEuUmVzdWx0U2V0TWV0YWRhdGESLQoE", + "ZGF0YRgDIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5MaXN0VmFsdWVCA+BBAhIw", + "CgVzdGF0cxgEIAEoCzIhLmdvb2dsZS5zcGFubmVyLnYxLlJlc3VsdFNldFN0", + "YXRzIkAKD01ldGFkYXRhUmVxdWVzdBItCgRyb3dzGAEgASgLMhouZ29vZ2xl", + "LnNwYW5uZXJsaWIudjEuUm93c0ID4EECIkYKFVJlc3VsdFNldFN0YXRzUmVx", + "dWVzdBItCgRyb3dzGAEgASgLMhouZ29vZ2xlLnNwYW5uZXJsaWIudjEuUm93", + "c0ID4EECImUKF0Nvbm5lY3Rpb25TdHJlYW1SZXF1ZXN0Ej8KD2V4ZWN1dGVf", + "cmVxdWVzdBgBIAEoCzIkLmdvb2dsZS5zcGFubmVybGliLnYxLkV4ZWN1dGVS", + "ZXF1ZXN0SABCCQoHcmVxdWVzdCJaChhDb25uZWN0aW9uU3RyZWFtUmVzcG9u", + "c2USMgoDcm93GAEgASgLMiMuZ29vZ2xlLnNwYW5uZXIudjEuUGFydGlhbFJl", + "c3VsdFNldEgAQgoKCHJlc3BvbnNlMsILCgpTcGFubmVyTGliEk8KBEluZm8S", + "IS5nb29nbGUuc3Bhbm5lcmxpYi52MS5JbmZvUmVxdWVzdBoiLmdvb2dsZS5z", + "cGFubmVybGliLnYxLkluZm9SZXNwb25zZSIAElMKCkNyZWF0ZVBvb2wSJy5n", + "b29nbGUuc3Bhbm5lcmxpYi52MS5DcmVhdGVQb29sUmVxdWVzdBoaLmdvb2ds", + "ZS5zcGFubmVybGliLnYxLlBvb2wiABJBCglDbG9zZVBvb2wSGi5nb29nbGUu", + "c3Bhbm5lcmxpYi52MS5Qb29sGhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IgAS", + "ZQoQQ3JlYXRlQ29ubmVjdGlvbhItLmdvb2dsZS5zcGFubmVybGliLnYxLkNy", + "ZWF0ZUNvbm5lY3Rpb25SZXF1ZXN0GiAuZ29vZ2xlLnNwYW5uZXJsaWIudjEu", + "Q29ubmVjdGlvbiIAEk0KD0Nsb3NlQ29ubmVjdGlvbhIgLmdvb2dsZS5zcGFu", + "bmVybGliLnYxLkNvbm5lY3Rpb24aFi5nb29nbGUucHJvdG9idWYuRW1wdHki", + "ABJNCgdFeGVjdXRlEiQuZ29vZ2xlLnNwYW5uZXJsaWIudjEuRXhlY3V0ZVJl", + "cXVlc3QaGi5nb29nbGUuc3Bhbm5lcmxpYi52MS5Sb3dzIgASWwoQRXhlY3V0", + "ZVN0cmVhbWluZxIkLmdvb2dsZS5zcGFubmVybGliLnYxLkV4ZWN1dGVSZXF1", + "ZXN0Gh0uZ29vZ2xlLnNwYW5uZXJsaWIudjEuUm93RGF0YSIAMAESZwoMRXhl", + "Y3V0ZUJhdGNoEikuZ29vZ2xlLnNwYW5uZXJsaWIudjEuRXhlY3V0ZUJhdGNo", + "UmVxdWVzdBoqLmdvb2dsZS5zcGFubmVyLnYxLkV4ZWN1dGVCYXRjaERtbFJl", + "c3BvbnNlIgASTgoITWV0YWRhdGESGi5nb29nbGUuc3Bhbm5lcmxpYi52MS5S", + "b3dzGiQuZ29vZ2xlLnNwYW5uZXIudjEuUmVzdWx0U2V0TWV0YWRhdGEiABJH", + "CgROZXh0EiEuZ29vZ2xlLnNwYW5uZXJsaWIudjEuTmV4dFJlcXVlc3QaGi5n", + "b29nbGUucHJvdG9idWYuTGlzdFZhbHVlIgASUQoOUmVzdWx0U2V0U3RhdHMS", + "Gi5nb29nbGUuc3Bhbm5lcmxpYi52MS5Sb3dzGiEuZ29vZ2xlLnNwYW5uZXIu", + "djEuUmVzdWx0U2V0U3RhdHMiABJBCglDbG9zZVJvd3MSGi5nb29nbGUuc3Bh", + "bm5lcmxpYi52MS5Sb3dzGhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IgASWwoQ", + "QmVnaW5UcmFuc2FjdGlvbhItLmdvb2dsZS5zcGFubmVybGliLnYxLkJlZ2lu", + "VHJhbnNhY3Rpb25SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IgAS", + "TwoGQ29tbWl0EiAuZ29vZ2xlLnNwYW5uZXJsaWIudjEuQ29ubmVjdGlvbhoh", + "Lmdvb2dsZS5zcGFubmVyLnYxLkNvbW1pdFJlc3BvbnNlIgASRgoIUm9sbGJh", + "Y2sSIC5nb29nbGUuc3Bhbm5lcmxpYi52MS5Db25uZWN0aW9uGhYuZ29vZ2xl", + "LnByb3RvYnVmLkVtcHR5IgASYgoOV3JpdGVNdXRhdGlvbnMSKy5nb29nbGUu", + "c3Bhbm5lcmxpYi52MS5Xcml0ZU11dGF0aW9uc1JlcXVlc3QaIS5nb29nbGUu", + "c3Bhbm5lci52MS5Db21taXRSZXNwb25zZSIAEncKEENvbm5lY3Rpb25TdHJl", + "YW0SLS5nb29nbGUuc3Bhbm5lcmxpYi52MS5Db25uZWN0aW9uU3RyZWFtUmVx", + "dWVzdBouLmdvb2dsZS5zcGFubmVybGliLnYxLkNvbm5lY3Rpb25TdHJlYW1S", + "ZXNwb25zZSIAKAEwAULNAQoeY29tLmdvb2dsZS5jbG91ZC5zcGFubmVybGli", + "LnYxQg9TcGFubmVyTGliUHJvdG9QAVo+Y2xvdWQuZ29vZ2xlLmNvbS9nby9z", + "cGFubmVybGliL2FwaXYxL3NwYW5uZXJsaWJwYjtzcGFubmVybGlicGKqAhpH", + "b29nbGUuQ2xvdWQuU3Bhbm5lckxpYi5WMcoCGkdvb2dsZVxDbG91ZFxTcGFu", + "bmVyTGliXFYx6gIdR29vZ2xlOjpDbG91ZDo6U3Bhbm5lckxpYjo6VjFiBnBy", + "b3RvMw==")); + descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData, + new pbr::FileDescriptor[] { global::Google.Api.FieldBehaviorReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.EmptyReflection.Descriptor, global::Google.Protobuf.WellKnownTypes.StructReflection.Descriptor, global::Google.Cloud.Spanner.V1.ResultSetReflection.Descriptor, global::Google.Cloud.Spanner.V1.SpannerReflection.Descriptor, global::Google.Cloud.Spanner.V1.TransactionReflection.Descriptor, }, + new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] { + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.InfoRequest), global::Google.Cloud.SpannerLib.V1.InfoRequest.Parser, null, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.InfoResponse), global::Google.Cloud.SpannerLib.V1.InfoResponse.Parser, new[]{ "Version" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.CreatePoolRequest), global::Google.Cloud.SpannerLib.V1.CreatePoolRequest.Parser, new[]{ "ConnectionString" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest), global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest.Parser, new[]{ "Pool" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.ExecuteRequest), global::Google.Cloud.SpannerLib.V1.ExecuteRequest.Parser, new[]{ "Connection", "ExecuteSqlRequest" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest), global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest.Parser, new[]{ "Connection", "ExecuteBatchDmlRequest" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest), global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest.Parser, new[]{ "Connection", "TransactionOptions" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest), global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest.Parser, new[]{ "Connection", "Mutations" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.Pool), global::Google.Cloud.SpannerLib.V1.Pool.Parser, new[]{ "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.Connection), global::Google.Cloud.SpannerLib.V1.Connection.Parser, new[]{ "Pool", "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.Rows), global::Google.Cloud.SpannerLib.V1.Rows.Parser, new[]{ "Connection", "Id" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.NextRequest), global::Google.Cloud.SpannerLib.V1.NextRequest.Parser, new[]{ "Rows", "NumRows", "Encoding" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.RowData), global::Google.Cloud.SpannerLib.V1.RowData.Parser, new[]{ "Rows", "Metadata", "Data", "Stats" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.MetadataRequest), global::Google.Cloud.SpannerLib.V1.MetadataRequest.Parser, new[]{ "Rows" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.ResultSetStatsRequest), global::Google.Cloud.SpannerLib.V1.ResultSetStatsRequest.Parser, new[]{ "Rows" }, null, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.ConnectionStreamRequest), global::Google.Cloud.SpannerLib.V1.ConnectionStreamRequest.Parser, new[]{ "ExecuteRequest" }, new[]{ "Request" }, null, null, null), + new pbr::GeneratedClrTypeInfo(typeof(global::Google.Cloud.SpannerLib.V1.ConnectionStreamResponse), global::Google.Cloud.SpannerLib.V1.ConnectionStreamResponse.Parser, new[]{ "Row" }, new[]{ "Response" }, null, null, null) + })); + } + #endregion + + } + #region Messages + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class InfoRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new InfoRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[0]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InfoRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InfoRequest(InfoRequest other) : this() { + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InfoRequest Clone() { + return new InfoRequest(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as InfoRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(InfoRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(InfoRequest other) { + if (other == null) { + return; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class InfoResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new InfoResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[1]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InfoResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InfoResponse(InfoResponse other) : this() { + version_ = other.version_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public InfoResponse Clone() { + return new InfoResponse(this); + } + + /// Field number for the "version" field. + public const int VersionFieldNumber = 1; + private string version_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string Version { + get { return version_; } + set { + version_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as InfoResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(InfoResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Version != other.Version) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Version.Length != 0) hash ^= Version.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Version.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Version); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Version.Length != 0) { + output.WriteRawTag(10); + output.WriteString(Version); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Version.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(Version); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(InfoResponse other) { + if (other == null) { + return; + } + if (other.Version.Length != 0) { + Version = other.Version; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + Version = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + Version = input.ReadString(); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class CreatePoolRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CreatePoolRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[2]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CreatePoolRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CreatePoolRequest(CreatePoolRequest other) : this() { + connectionString_ = other.connectionString_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CreatePoolRequest Clone() { + return new CreatePoolRequest(this); + } + + /// Field number for the "connection_string" field. + public const int ConnectionStringFieldNumber = 1; + private string connectionString_ = ""; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public string ConnectionString { + get { return connectionString_; } + set { + connectionString_ = pb::ProtoPreconditions.CheckNotNull(value, "value"); + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as CreatePoolRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(CreatePoolRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (ConnectionString != other.ConnectionString) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (ConnectionString.Length != 0) hash ^= ConnectionString.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (ConnectionString.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ConnectionString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (ConnectionString.Length != 0) { + output.WriteRawTag(10); + output.WriteString(ConnectionString); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (ConnectionString.Length != 0) { + size += 1 + pb::CodedOutputStream.ComputeStringSize(ConnectionString); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(CreatePoolRequest other) { + if (other == null) { + return; + } + if (other.ConnectionString.Length != 0) { + ConnectionString = other.ConnectionString; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + ConnectionString = input.ReadString(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + ConnectionString = input.ReadString(); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class CreateConnectionRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new CreateConnectionRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[3]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CreateConnectionRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CreateConnectionRequest(CreateConnectionRequest other) : this() { + pool_ = other.pool_ != null ? other.pool_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public CreateConnectionRequest Clone() { + return new CreateConnectionRequest(this); + } + + /// Field number for the "pool" field. + public const int PoolFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Pool pool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Pool Pool { + get { return pool_; } + set { + pool_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as CreateConnectionRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(CreateConnectionRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Pool, other.Pool)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (pool_ != null) hash ^= Pool.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (pool_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Pool); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (pool_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Pool); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (pool_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Pool); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(CreateConnectionRequest other) { + if (other == null) { + return; + } + if (other.pool_ != null) { + if (pool_ == null) { + Pool = new global::Google.Cloud.SpannerLib.V1.Pool(); + } + Pool.MergeFrom(other.Pool); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (pool_ == null) { + Pool = new global::Google.Cloud.SpannerLib.V1.Pool(); + } + input.ReadMessage(Pool); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (pool_ == null) { + Pool = new global::Google.Cloud.SpannerLib.V1.Pool(); + } + input.ReadMessage(Pool); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ExecuteRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExecuteRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[4]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExecuteRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExecuteRequest(ExecuteRequest other) : this() { + connection_ = other.connection_ != null ? other.connection_.Clone() : null; + executeSqlRequest_ = other.executeSqlRequest_ != null ? other.executeSqlRequest_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExecuteRequest Clone() { + return new ExecuteRequest(this); + } + + /// Field number for the "connection" field. + public const int ConnectionFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Connection connection_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Connection Connection { + get { return connection_; } + set { + connection_ = value; + } + } + + /// Field number for the "execute_sql_request" field. + public const int ExecuteSqlRequestFieldNumber = 2; + private global::Google.Cloud.Spanner.V1.ExecuteSqlRequest executeSqlRequest_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.ExecuteSqlRequest ExecuteSqlRequest { + get { return executeSqlRequest_; } + set { + executeSqlRequest_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ExecuteRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ExecuteRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Connection, other.Connection)) return false; + if (!object.Equals(ExecuteSqlRequest, other.ExecuteSqlRequest)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (connection_ != null) hash ^= Connection.GetHashCode(); + if (executeSqlRequest_ != null) hash ^= ExecuteSqlRequest.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (executeSqlRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ExecuteSqlRequest); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (executeSqlRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ExecuteSqlRequest); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (connection_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Connection); + } + if (executeSqlRequest_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExecuteSqlRequest); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ExecuteRequest other) { + if (other == null) { + return; + } + if (other.connection_ != null) { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + Connection.MergeFrom(other.Connection); + } + if (other.executeSqlRequest_ != null) { + if (executeSqlRequest_ == null) { + ExecuteSqlRequest = new global::Google.Cloud.Spanner.V1.ExecuteSqlRequest(); + } + ExecuteSqlRequest.MergeFrom(other.ExecuteSqlRequest); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (executeSqlRequest_ == null) { + ExecuteSqlRequest = new global::Google.Cloud.Spanner.V1.ExecuteSqlRequest(); + } + input.ReadMessage(ExecuteSqlRequest); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (executeSqlRequest_ == null) { + ExecuteSqlRequest = new global::Google.Cloud.Spanner.V1.ExecuteSqlRequest(); + } + input.ReadMessage(ExecuteSqlRequest); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ExecuteBatchRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ExecuteBatchRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[5]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExecuteBatchRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExecuteBatchRequest(ExecuteBatchRequest other) : this() { + connection_ = other.connection_ != null ? other.connection_.Clone() : null; + executeBatchDmlRequest_ = other.executeBatchDmlRequest_ != null ? other.executeBatchDmlRequest_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ExecuteBatchRequest Clone() { + return new ExecuteBatchRequest(this); + } + + /// Field number for the "connection" field. + public const int ConnectionFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Connection connection_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Connection Connection { + get { return connection_; } + set { + connection_ = value; + } + } + + /// Field number for the "execute_batch_dml_request" field. + public const int ExecuteBatchDmlRequestFieldNumber = 2; + private global::Google.Cloud.Spanner.V1.ExecuteBatchDmlRequest executeBatchDmlRequest_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.ExecuteBatchDmlRequest ExecuteBatchDmlRequest { + get { return executeBatchDmlRequest_; } + set { + executeBatchDmlRequest_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ExecuteBatchRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ExecuteBatchRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Connection, other.Connection)) return false; + if (!object.Equals(ExecuteBatchDmlRequest, other.ExecuteBatchDmlRequest)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (connection_ != null) hash ^= Connection.GetHashCode(); + if (executeBatchDmlRequest_ != null) hash ^= ExecuteBatchDmlRequest.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (executeBatchDmlRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ExecuteBatchDmlRequest); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (executeBatchDmlRequest_ != null) { + output.WriteRawTag(18); + output.WriteMessage(ExecuteBatchDmlRequest); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (connection_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Connection); + } + if (executeBatchDmlRequest_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExecuteBatchDmlRequest); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ExecuteBatchRequest other) { + if (other == null) { + return; + } + if (other.connection_ != null) { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + Connection.MergeFrom(other.Connection); + } + if (other.executeBatchDmlRequest_ != null) { + if (executeBatchDmlRequest_ == null) { + ExecuteBatchDmlRequest = new global::Google.Cloud.Spanner.V1.ExecuteBatchDmlRequest(); + } + ExecuteBatchDmlRequest.MergeFrom(other.ExecuteBatchDmlRequest); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (executeBatchDmlRequest_ == null) { + ExecuteBatchDmlRequest = new global::Google.Cloud.Spanner.V1.ExecuteBatchDmlRequest(); + } + input.ReadMessage(ExecuteBatchDmlRequest); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (executeBatchDmlRequest_ == null) { + ExecuteBatchDmlRequest = new global::Google.Cloud.Spanner.V1.ExecuteBatchDmlRequest(); + } + input.ReadMessage(ExecuteBatchDmlRequest); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class BeginTransactionRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new BeginTransactionRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[6]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public BeginTransactionRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public BeginTransactionRequest(BeginTransactionRequest other) : this() { + connection_ = other.connection_ != null ? other.connection_.Clone() : null; + transactionOptions_ = other.transactionOptions_ != null ? other.transactionOptions_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public BeginTransactionRequest Clone() { + return new BeginTransactionRequest(this); + } + + /// Field number for the "connection" field. + public const int ConnectionFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Connection connection_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Connection Connection { + get { return connection_; } + set { + connection_ = value; + } + } + + /// Field number for the "transaction_options" field. + public const int TransactionOptionsFieldNumber = 2; + private global::Google.Cloud.Spanner.V1.TransactionOptions transactionOptions_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.TransactionOptions TransactionOptions { + get { return transactionOptions_; } + set { + transactionOptions_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as BeginTransactionRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(BeginTransactionRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Connection, other.Connection)) return false; + if (!object.Equals(TransactionOptions, other.TransactionOptions)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (connection_ != null) hash ^= Connection.GetHashCode(); + if (transactionOptions_ != null) hash ^= TransactionOptions.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (transactionOptions_ != null) { + output.WriteRawTag(18); + output.WriteMessage(TransactionOptions); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (transactionOptions_ != null) { + output.WriteRawTag(18); + output.WriteMessage(TransactionOptions); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (connection_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Connection); + } + if (transactionOptions_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(TransactionOptions); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(BeginTransactionRequest other) { + if (other == null) { + return; + } + if (other.connection_ != null) { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + Connection.MergeFrom(other.Connection); + } + if (other.transactionOptions_ != null) { + if (transactionOptions_ == null) { + TransactionOptions = new global::Google.Cloud.Spanner.V1.TransactionOptions(); + } + TransactionOptions.MergeFrom(other.TransactionOptions); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (transactionOptions_ == null) { + TransactionOptions = new global::Google.Cloud.Spanner.V1.TransactionOptions(); + } + input.ReadMessage(TransactionOptions); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (transactionOptions_ == null) { + TransactionOptions = new global::Google.Cloud.Spanner.V1.TransactionOptions(); + } + input.ReadMessage(TransactionOptions); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class WriteMutationsRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new WriteMutationsRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[7]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public WriteMutationsRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public WriteMutationsRequest(WriteMutationsRequest other) : this() { + connection_ = other.connection_ != null ? other.connection_.Clone() : null; + mutations_ = other.mutations_ != null ? other.mutations_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public WriteMutationsRequest Clone() { + return new WriteMutationsRequest(this); + } + + /// Field number for the "connection" field. + public const int ConnectionFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Connection connection_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Connection Connection { + get { return connection_; } + set { + connection_ = value; + } + } + + /// Field number for the "mutations" field. + public const int MutationsFieldNumber = 2; + private global::Google.Cloud.Spanner.V1.BatchWriteRequest.Types.MutationGroup mutations_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.BatchWriteRequest.Types.MutationGroup Mutations { + get { return mutations_; } + set { + mutations_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as WriteMutationsRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(WriteMutationsRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Connection, other.Connection)) return false; + if (!object.Equals(Mutations, other.Mutations)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (connection_ != null) hash ^= Connection.GetHashCode(); + if (mutations_ != null) hash ^= Mutations.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (mutations_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Mutations); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (mutations_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Mutations); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (connection_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Connection); + } + if (mutations_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Mutations); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(WriteMutationsRequest other) { + if (other == null) { + return; + } + if (other.connection_ != null) { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + Connection.MergeFrom(other.Connection); + } + if (other.mutations_ != null) { + if (mutations_ == null) { + Mutations = new global::Google.Cloud.Spanner.V1.BatchWriteRequest.Types.MutationGroup(); + } + Mutations.MergeFrom(other.Mutations); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (mutations_ == null) { + Mutations = new global::Google.Cloud.Spanner.V1.BatchWriteRequest.Types.MutationGroup(); + } + input.ReadMessage(Mutations); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 18: { + if (mutations_ == null) { + Mutations = new global::Google.Cloud.Spanner.V1.BatchWriteRequest.Types.MutationGroup(); + } + input.ReadMessage(Mutations); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Pool : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Pool()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[8]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Pool() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Pool(Pool other) : this() { + id_ = other.id_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Pool Clone() { + return new Pool(this); + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 1; + private long id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Id { + get { return id_; } + set { + id_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Pool); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Pool other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (Id != other.Id) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (Id != 0L) hash ^= Id.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (Id != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (Id != 0L) { + output.WriteRawTag(8); + output.WriteInt64(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (Id != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Id); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Pool other) { + if (other == null) { + return; + } + if (other.Id != 0L) { + Id = other.Id; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 8: { + Id = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 8: { + Id = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Connection : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Connection()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[9]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Connection() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Connection(Connection other) : this() { + pool_ = other.pool_ != null ? other.pool_.Clone() : null; + id_ = other.id_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Connection Clone() { + return new Connection(this); + } + + /// Field number for the "pool" field. + public const int PoolFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Pool pool_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Pool Pool { + get { return pool_; } + set { + pool_ = value; + } + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 2; + private long id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Id { + get { return id_; } + set { + id_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Connection); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Connection other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Pool, other.Pool)) return false; + if (Id != other.Id) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (pool_ != null) hash ^= Pool.GetHashCode(); + if (Id != 0L) hash ^= Id.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (pool_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Pool); + } + if (Id != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (pool_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Pool); + } + if (Id != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (pool_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Pool); + } + if (Id != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Id); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Connection other) { + if (other == null) { + return; + } + if (other.pool_ != null) { + if (pool_ == null) { + Pool = new global::Google.Cloud.SpannerLib.V1.Pool(); + } + Pool.MergeFrom(other.Pool); + } + if (other.Id != 0L) { + Id = other.Id; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (pool_ == null) { + Pool = new global::Google.Cloud.SpannerLib.V1.Pool(); + } + input.ReadMessage(Pool); + break; + } + case 16: { + Id = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (pool_ == null) { + Pool = new global::Google.Cloud.SpannerLib.V1.Pool(); + } + input.ReadMessage(Pool); + break; + } + case 16: { + Id = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class Rows : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new Rows()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[10]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Rows() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Rows(Rows other) : this() { + connection_ = other.connection_ != null ? other.connection_.Clone() : null; + id_ = other.id_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public Rows Clone() { + return new Rows(this); + } + + /// Field number for the "connection" field. + public const int ConnectionFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Connection connection_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Connection Connection { + get { return connection_; } + set { + connection_ = value; + } + } + + /// Field number for the "id" field. + public const int IdFieldNumber = 2; + private long id_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Id { + get { return id_; } + set { + id_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as Rows); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(Rows other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Connection, other.Connection)) return false; + if (Id != other.Id) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (connection_ != null) hash ^= Connection.GetHashCode(); + if (Id != 0L) hash ^= Id.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (Id != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (connection_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Connection); + } + if (Id != 0L) { + output.WriteRawTag(16); + output.WriteInt64(Id); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (connection_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Connection); + } + if (Id != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Id); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(Rows other) { + if (other == null) { + return; + } + if (other.connection_ != null) { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + Connection.MergeFrom(other.Connection); + } + if (other.Id != 0L) { + Id = other.Id; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 16: { + Id = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (connection_ == null) { + Connection = new global::Google.Cloud.SpannerLib.V1.Connection(); + } + input.ReadMessage(Connection); + break; + } + case 16: { + Id = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class NextRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new NextRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[11]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public NextRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public NextRequest(NextRequest other) : this() { + rows_ = other.rows_ != null ? other.rows_.Clone() : null; + numRows_ = other.numRows_; + encoding_ = other.encoding_; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public NextRequest Clone() { + return new NextRequest(this); + } + + /// Field number for the "rows" field. + public const int RowsFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Rows rows_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Rows Rows { + get { return rows_; } + set { + rows_ = value; + } + } + + /// Field number for the "num_rows" field. + public const int NumRowsFieldNumber = 2; + private long numRows_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long NumRows { + get { return numRows_; } + set { + numRows_ = value; + } + } + + /// Field number for the "encoding" field. + public const int EncodingFieldNumber = 3; + private long encoding_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public long Encoding { + get { return encoding_; } + set { + encoding_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as NextRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(NextRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Rows, other.Rows)) return false; + if (NumRows != other.NumRows) return false; + if (Encoding != other.Encoding) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (rows_ != null) hash ^= Rows.GetHashCode(); + if (NumRows != 0L) hash ^= NumRows.GetHashCode(); + if (Encoding != 0L) hash ^= Encoding.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (NumRows != 0L) { + output.WriteRawTag(16); + output.WriteInt64(NumRows); + } + if (Encoding != 0L) { + output.WriteRawTag(24); + output.WriteInt64(Encoding); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (NumRows != 0L) { + output.WriteRawTag(16); + output.WriteInt64(NumRows); + } + if (Encoding != 0L) { + output.WriteRawTag(24); + output.WriteInt64(Encoding); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (rows_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Rows); + } + if (NumRows != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(NumRows); + } + if (Encoding != 0L) { + size += 1 + pb::CodedOutputStream.ComputeInt64Size(Encoding); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(NextRequest other) { + if (other == null) { + return; + } + if (other.rows_ != null) { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + Rows.MergeFrom(other.Rows); + } + if (other.NumRows != 0L) { + NumRows = other.NumRows; + } + if (other.Encoding != 0L) { + Encoding = other.Encoding; + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + case 16: { + NumRows = input.ReadInt64(); + break; + } + case 24: { + Encoding = input.ReadInt64(); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + case 16: { + NumRows = input.ReadInt64(); + break; + } + case 24: { + Encoding = input.ReadInt64(); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class RowData : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new RowData()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[12]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RowData() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RowData(RowData other) : this() { + rows_ = other.rows_ != null ? other.rows_.Clone() : null; + metadata_ = other.metadata_ != null ? other.metadata_.Clone() : null; + data_ = other.data_.Clone(); + stats_ = other.stats_ != null ? other.stats_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RowData Clone() { + return new RowData(this); + } + + /// Field number for the "rows" field. + public const int RowsFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Rows rows_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Rows Rows { + get { return rows_; } + set { + rows_ = value; + } + } + + /// Field number for the "metadata" field. + public const int MetadataFieldNumber = 2; + private global::Google.Cloud.Spanner.V1.ResultSetMetadata metadata_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.ResultSetMetadata Metadata { + get { return metadata_; } + set { + metadata_ = value; + } + } + + /// Field number for the "data" field. + public const int DataFieldNumber = 3; + private static readonly pb::FieldCodec _repeated_data_codec + = pb::FieldCodec.ForMessage(26, global::Google.Protobuf.WellKnownTypes.ListValue.Parser); + private readonly pbc::RepeatedField data_ = new pbc::RepeatedField(); + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public pbc::RepeatedField Data { + get { return data_; } + } + + /// Field number for the "stats" field. + public const int StatsFieldNumber = 4; + private global::Google.Cloud.Spanner.V1.ResultSetStats stats_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.ResultSetStats Stats { + get { return stats_; } + set { + stats_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as RowData); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(RowData other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Rows, other.Rows)) return false; + if (!object.Equals(Metadata, other.Metadata)) return false; + if(!data_.Equals(other.data_)) return false; + if (!object.Equals(Stats, other.Stats)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (rows_ != null) hash ^= Rows.GetHashCode(); + if (metadata_ != null) hash ^= Metadata.GetHashCode(); + hash ^= data_.GetHashCode(); + if (stats_ != null) hash ^= Stats.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (metadata_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Metadata); + } + data_.WriteTo(output, _repeated_data_codec); + if (stats_ != null) { + output.WriteRawTag(34); + output.WriteMessage(Stats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (metadata_ != null) { + output.WriteRawTag(18); + output.WriteMessage(Metadata); + } + data_.WriteTo(ref output, _repeated_data_codec); + if (stats_ != null) { + output.WriteRawTag(34); + output.WriteMessage(Stats); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (rows_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Rows); + } + if (metadata_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Metadata); + } + size += data_.CalculateSize(_repeated_data_codec); + if (stats_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Stats); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(RowData other) { + if (other == null) { + return; + } + if (other.rows_ != null) { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + Rows.MergeFrom(other.Rows); + } + if (other.metadata_ != null) { + if (metadata_ == null) { + Metadata = new global::Google.Cloud.Spanner.V1.ResultSetMetadata(); + } + Metadata.MergeFrom(other.Metadata); + } + data_.Add(other.data_); + if (other.stats_ != null) { + if (stats_ == null) { + Stats = new global::Google.Cloud.Spanner.V1.ResultSetStats(); + } + Stats.MergeFrom(other.Stats); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + case 18: { + if (metadata_ == null) { + Metadata = new global::Google.Cloud.Spanner.V1.ResultSetMetadata(); + } + input.ReadMessage(Metadata); + break; + } + case 26: { + data_.AddEntriesFrom(input, _repeated_data_codec); + break; + } + case 34: { + if (stats_ == null) { + Stats = new global::Google.Cloud.Spanner.V1.ResultSetStats(); + } + input.ReadMessage(Stats); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + case 18: { + if (metadata_ == null) { + Metadata = new global::Google.Cloud.Spanner.V1.ResultSetMetadata(); + } + input.ReadMessage(Metadata); + break; + } + case 26: { + data_.AddEntriesFrom(ref input, _repeated_data_codec); + break; + } + case 34: { + if (stats_ == null) { + Stats = new global::Google.Cloud.Spanner.V1.ResultSetStats(); + } + input.ReadMessage(Stats); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class MetadataRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new MetadataRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[13]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MetadataRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MetadataRequest(MetadataRequest other) : this() { + rows_ = other.rows_ != null ? other.rows_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public MetadataRequest Clone() { + return new MetadataRequest(this); + } + + /// Field number for the "rows" field. + public const int RowsFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Rows rows_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Rows Rows { + get { return rows_; } + set { + rows_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as MetadataRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(MetadataRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Rows, other.Rows)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (rows_ != null) hash ^= Rows.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (rows_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Rows); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(MetadataRequest other) { + if (other == null) { + return; + } + if (other.rows_ != null) { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + Rows.MergeFrom(other.Rows); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ResultSetStatsRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ResultSetStatsRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[14]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResultSetStatsRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResultSetStatsRequest(ResultSetStatsRequest other) : this() { + rows_ = other.rows_ != null ? other.rows_.Clone() : null; + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResultSetStatsRequest Clone() { + return new ResultSetStatsRequest(this); + } + + /// Field number for the "rows" field. + public const int RowsFieldNumber = 1; + private global::Google.Cloud.SpannerLib.V1.Rows rows_; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.Rows Rows { + get { return rows_; } + set { + rows_ = value; + } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ResultSetStatsRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ResultSetStatsRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Rows, other.Rows)) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (rows_ != null) hash ^= Rows.GetHashCode(); + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (rows_ != null) { + output.WriteRawTag(10); + output.WriteMessage(Rows); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (rows_ != null) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Rows); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ResultSetStatsRequest other) { + if (other == null) { + return; + } + if (other.rows_ != null) { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + Rows.MergeFrom(other.Rows); + } + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + if (rows_ == null) { + Rows = new global::Google.Cloud.SpannerLib.V1.Rows(); + } + input.ReadMessage(Rows); + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ConnectionStreamRequest : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConnectionStreamRequest()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[15]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConnectionStreamRequest() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConnectionStreamRequest(ConnectionStreamRequest other) : this() { + switch (other.RequestCase) { + case RequestOneofCase.ExecuteRequest: + ExecuteRequest = other.ExecuteRequest.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConnectionStreamRequest Clone() { + return new ConnectionStreamRequest(this); + } + + /// Field number for the "execute_request" field. + public const int ExecuteRequestFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.SpannerLib.V1.ExecuteRequest ExecuteRequest { + get { return requestCase_ == RequestOneofCase.ExecuteRequest ? (global::Google.Cloud.SpannerLib.V1.ExecuteRequest) request_ : null; } + set { + request_ = value; + requestCase_ = value == null ? RequestOneofCase.None : RequestOneofCase.ExecuteRequest; + } + } + + private object request_; + /// Enum of possible cases for the "request" oneof. + public enum RequestOneofCase { + None = 0, + ExecuteRequest = 1, + } + private RequestOneofCase requestCase_ = RequestOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public RequestOneofCase RequestCase { + get { return requestCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearRequest() { + requestCase_ = RequestOneofCase.None; + request_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ConnectionStreamRequest); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ConnectionStreamRequest other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(ExecuteRequest, other.ExecuteRequest)) return false; + if (RequestCase != other.RequestCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (requestCase_ == RequestOneofCase.ExecuteRequest) hash ^= ExecuteRequest.GetHashCode(); + hash ^= (int) requestCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (requestCase_ == RequestOneofCase.ExecuteRequest) { + output.WriteRawTag(10); + output.WriteMessage(ExecuteRequest); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (requestCase_ == RequestOneofCase.ExecuteRequest) { + output.WriteRawTag(10); + output.WriteMessage(ExecuteRequest); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (requestCase_ == RequestOneofCase.ExecuteRequest) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(ExecuteRequest); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ConnectionStreamRequest other) { + if (other == null) { + return; + } + switch (other.RequestCase) { + case RequestOneofCase.ExecuteRequest: + if (ExecuteRequest == null) { + ExecuteRequest = new global::Google.Cloud.SpannerLib.V1.ExecuteRequest(); + } + ExecuteRequest.MergeFrom(other.ExecuteRequest); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Google.Cloud.SpannerLib.V1.ExecuteRequest subBuilder = new global::Google.Cloud.SpannerLib.V1.ExecuteRequest(); + if (requestCase_ == RequestOneofCase.ExecuteRequest) { + subBuilder.MergeFrom(ExecuteRequest); + } + input.ReadMessage(subBuilder); + ExecuteRequest = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Google.Cloud.SpannerLib.V1.ExecuteRequest subBuilder = new global::Google.Cloud.SpannerLib.V1.ExecuteRequest(); + if (requestCase_ == RequestOneofCase.ExecuteRequest) { + subBuilder.MergeFrom(ExecuteRequest); + } + input.ReadMessage(subBuilder); + ExecuteRequest = subBuilder; + break; + } + } + } + } + #endif + + } + + [global::System.Diagnostics.DebuggerDisplayAttribute("{ToString(),nq}")] + public sealed partial class ConnectionStreamResponse : pb::IMessage + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + , pb::IBufferMessage + #endif + { + private static readonly pb::MessageParser _parser = new pb::MessageParser(() => new ConnectionStreamResponse()); + private pb::UnknownFieldSet _unknownFields; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pb::MessageParser Parser { get { return _parser; } } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public static pbr::MessageDescriptor Descriptor { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.MessageTypes[16]; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + pbr::MessageDescriptor pb::IMessage.Descriptor { + get { return Descriptor; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConnectionStreamResponse() { + OnConstruction(); + } + + partial void OnConstruction(); + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConnectionStreamResponse(ConnectionStreamResponse other) : this() { + switch (other.ResponseCase) { + case ResponseOneofCase.Row: + Row = other.Row.Clone(); + break; + } + + _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ConnectionStreamResponse Clone() { + return new ConnectionStreamResponse(this); + } + + /// Field number for the "row" field. + public const int RowFieldNumber = 1; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public global::Google.Cloud.Spanner.V1.PartialResultSet Row { + get { return responseCase_ == ResponseOneofCase.Row ? (global::Google.Cloud.Spanner.V1.PartialResultSet) response_ : null; } + set { + response_ = value; + responseCase_ = value == null ? ResponseOneofCase.None : ResponseOneofCase.Row; + } + } + + private object response_; + /// Enum of possible cases for the "response" oneof. + public enum ResponseOneofCase { + None = 0, + Row = 1, + } + private ResponseOneofCase responseCase_ = ResponseOneofCase.None; + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public ResponseOneofCase ResponseCase { + get { return responseCase_; } + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void ClearResponse() { + responseCase_ = ResponseOneofCase.None; + response_ = null; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override bool Equals(object other) { + return Equals(other as ConnectionStreamResponse); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public bool Equals(ConnectionStreamResponse other) { + if (ReferenceEquals(other, null)) { + return false; + } + if (ReferenceEquals(other, this)) { + return true; + } + if (!object.Equals(Row, other.Row)) return false; + if (ResponseCase != other.ResponseCase) return false; + return Equals(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override int GetHashCode() { + int hash = 1; + if (responseCase_ == ResponseOneofCase.Row) hash ^= Row.GetHashCode(); + hash ^= (int) responseCase_; + if (_unknownFields != null) { + hash ^= _unknownFields.GetHashCode(); + } + return hash; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public override string ToString() { + return pb::JsonFormatter.ToDiagnosticString(this); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void WriteTo(pb::CodedOutputStream output) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + output.WriteRawMessage(this); + #else + if (responseCase_ == ResponseOneofCase.Row) { + output.WriteRawTag(10); + output.WriteMessage(Row); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(output); + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) { + if (responseCase_ == ResponseOneofCase.Row) { + output.WriteRawTag(10); + output.WriteMessage(Row); + } + if (_unknownFields != null) { + _unknownFields.WriteTo(ref output); + } + } + #endif + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public int CalculateSize() { + int size = 0; + if (responseCase_ == ResponseOneofCase.Row) { + size += 1 + pb::CodedOutputStream.ComputeMessageSize(Row); + } + if (_unknownFields != null) { + size += _unknownFields.CalculateSize(); + } + return size; + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(ConnectionStreamResponse other) { + if (other == null) { + return; + } + switch (other.ResponseCase) { + case ResponseOneofCase.Row: + if (Row == null) { + Row = new global::Google.Cloud.Spanner.V1.PartialResultSet(); + } + Row.MergeFrom(other.Row); + break; + } + + _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields); + } + + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + public void MergeFrom(pb::CodedInputStream input) { + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + input.ReadRawMessage(this); + #else + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, input); + break; + case 10: { + global::Google.Cloud.Spanner.V1.PartialResultSet subBuilder = new global::Google.Cloud.Spanner.V1.PartialResultSet(); + if (responseCase_ == ResponseOneofCase.Row) { + subBuilder.MergeFrom(Row); + } + input.ReadMessage(subBuilder); + Row = subBuilder; + break; + } + } + } + #endif + } + + #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE + [global::System.Diagnostics.DebuggerNonUserCodeAttribute] + [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)] + void pb::IBufferMessage.InternalMergeFrom(ref pb::ParseContext input) { + uint tag; + while ((tag = input.ReadTag()) != 0) { + if ((tag & 7) == 4) { + // Abort on any end group tag. + return; + } + switch(tag) { + default: + _unknownFields = pb::UnknownFieldSet.MergeFieldFrom(_unknownFields, ref input); + break; + case 10: { + global::Google.Cloud.Spanner.V1.PartialResultSet subBuilder = new global::Google.Cloud.Spanner.V1.PartialResultSet(); + if (responseCase_ == ResponseOneofCase.Row) { + subBuilder.MergeFrom(Row); + } + input.ReadMessage(subBuilder); + Row = subBuilder; + break; + } + } + } + } + #endif + + } + + #endregion + +} + +#endregion Designer generated code diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/SpannerlibGrpc.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/SpannerlibGrpc.cs new file mode 100644 index 00000000..d5e9db94 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/SpannerlibGrpc.cs @@ -0,0 +1,590 @@ +// +// Generated by the protocol buffer compiler. DO NOT EDIT! +// source: google/spannerlib/v1/spannerlib.proto +// +#pragma warning disable 0414, 1591, 8981, 0612 +#region Designer generated code + +using grpc = global::Grpc.Core; + +namespace Google.Cloud.SpannerLib.V1 { + public static partial class SpannerLib + { + static readonly string __ServiceName = "google.spannerlib.v1.SpannerLib"; + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static void __Helper_SerializeMessage(global::Google.Protobuf.IMessage message, grpc::SerializationContext context) + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (message is global::Google.Protobuf.IBufferMessage) + { + context.SetPayloadLength(message.CalculateSize()); + global::Google.Protobuf.MessageExtensions.WriteTo(message, context.GetBufferWriter()); + context.Complete(); + return; + } + #endif + context.Complete(global::Google.Protobuf.MessageExtensions.ToByteArray(message)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static class __Helper_MessageCache + { + public static readonly bool IsBufferMessage = global::System.Reflection.IntrospectionExtensions.GetTypeInfo(typeof(global::Google.Protobuf.IBufferMessage)).IsAssignableFrom(typeof(T)); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static T __Helper_DeserializeMessage(grpc::DeserializationContext context, global::Google.Protobuf.MessageParser parser) where T : global::Google.Protobuf.IMessage + { + #if !GRPC_DISABLE_PROTOBUF_BUFFER_SERIALIZATION + if (__Helper_MessageCache.IsBufferMessage) + { + return parser.ParseFrom(context.PayloadAsReadOnlySequence()); + } + #endif + return parser.ParseFrom(context.PayloadAsNewBuffer()); + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_InfoRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.InfoRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_InfoResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.InfoResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_CreatePoolRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.CreatePoolRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_Pool = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.Pool.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_protobuf_Empty = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Protobuf.WellKnownTypes.Empty.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_CreateConnectionRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_Connection = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.Connection.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_ExecuteRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.ExecuteRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_Rows = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.Rows.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_RowData = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.RowData.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_ExecuteBatchRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spanner_v1_ExecuteBatchDmlResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.Spanner.V1.ExecuteBatchDmlResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spanner_v1_ResultSetMetadata = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.Spanner.V1.ResultSetMetadata.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_NextRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.NextRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_protobuf_ListValue = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Protobuf.WellKnownTypes.ListValue.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spanner_v1_ResultSetStats = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.Spanner.V1.ResultSetStats.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_BeginTransactionRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spanner_v1_CommitResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.Spanner.V1.CommitResponse.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_WriteMutationsRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_ConnectionStreamRequest = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.ConnectionStreamRequest.Parser)); + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Marshaller __Marshaller_google_spannerlib_v1_ConnectionStreamResponse = grpc::Marshallers.Create(__Helper_SerializeMessage, context => __Helper_DeserializeMessage(context, global::Google.Cloud.SpannerLib.V1.ConnectionStreamResponse.Parser)); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Info = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Info", + __Marshaller_google_spannerlib_v1_InfoRequest, + __Marshaller_google_spannerlib_v1_InfoResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_CreatePool = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "CreatePool", + __Marshaller_google_spannerlib_v1_CreatePoolRequest, + __Marshaller_google_spannerlib_v1_Pool); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ClosePool = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "ClosePool", + __Marshaller_google_spannerlib_v1_Pool, + __Marshaller_google_protobuf_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_CreateConnection = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "CreateConnection", + __Marshaller_google_spannerlib_v1_CreateConnectionRequest, + __Marshaller_google_spannerlib_v1_Connection); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_CloseConnection = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "CloseConnection", + __Marshaller_google_spannerlib_v1_Connection, + __Marshaller_google_protobuf_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Execute = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Execute", + __Marshaller_google_spannerlib_v1_ExecuteRequest, + __Marshaller_google_spannerlib_v1_Rows); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ExecuteStreaming = new grpc::Method( + grpc::MethodType.ServerStreaming, + __ServiceName, + "ExecuteStreaming", + __Marshaller_google_spannerlib_v1_ExecuteRequest, + __Marshaller_google_spannerlib_v1_RowData); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ExecuteBatch = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "ExecuteBatch", + __Marshaller_google_spannerlib_v1_ExecuteBatchRequest, + __Marshaller_google_spanner_v1_ExecuteBatchDmlResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Metadata = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Metadata", + __Marshaller_google_spannerlib_v1_Rows, + __Marshaller_google_spanner_v1_ResultSetMetadata); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Next = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Next", + __Marshaller_google_spannerlib_v1_NextRequest, + __Marshaller_google_protobuf_ListValue); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ResultSetStats = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "ResultSetStats", + __Marshaller_google_spannerlib_v1_Rows, + __Marshaller_google_spanner_v1_ResultSetStats); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_CloseRows = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "CloseRows", + __Marshaller_google_spannerlib_v1_Rows, + __Marshaller_google_protobuf_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_BeginTransaction = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "BeginTransaction", + __Marshaller_google_spannerlib_v1_BeginTransactionRequest, + __Marshaller_google_protobuf_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Commit = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Commit", + __Marshaller_google_spannerlib_v1_Connection, + __Marshaller_google_spanner_v1_CommitResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_Rollback = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "Rollback", + __Marshaller_google_spannerlib_v1_Connection, + __Marshaller_google_protobuf_Empty); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_WriteMutations = new grpc::Method( + grpc::MethodType.Unary, + __ServiceName, + "WriteMutations", + __Marshaller_google_spannerlib_v1_WriteMutationsRequest, + __Marshaller_google_spanner_v1_CommitResponse); + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + static readonly grpc::Method __Method_ConnectionStream = new grpc::Method( + grpc::MethodType.DuplexStreaming, + __ServiceName, + "ConnectionStream", + __Marshaller_google_spannerlib_v1_ConnectionStreamRequest, + __Marshaller_google_spannerlib_v1_ConnectionStreamResponse); + + /// Service descriptor + public static global::Google.Protobuf.Reflection.ServiceDescriptor Descriptor + { + get { return global::Google.Cloud.SpannerLib.V1.SpannerlibReflection.Descriptor.Services[0]; } + } + + /// Client for SpannerLib + public partial class SpannerLibClient : grpc::ClientBase + { + /// Creates a new client for SpannerLib + /// The channel to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public SpannerLibClient(grpc::ChannelBase channel) : base(channel) + { + } + /// Creates a new client for SpannerLib that uses a custom CallInvoker. + /// The callInvoker to use to make remote calls. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public SpannerLibClient(grpc::CallInvoker callInvoker) : base(callInvoker) + { + } + /// Protected parameterless constructor to allow creation of test doubles. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected SpannerLibClient() : base() + { + } + /// Protected constructor to allow creation of configured clients. + /// The client configuration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected SpannerLibClient(ClientBaseConfiguration configuration) : base(configuration) + { + } + + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.InfoResponse Info(global::Google.Cloud.SpannerLib.V1.InfoRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Info(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.InfoResponse Info(global::Google.Cloud.SpannerLib.V1.InfoRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Info, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall InfoAsync(global::Google.Cloud.SpannerLib.V1.InfoRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return InfoAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall InfoAsync(global::Google.Cloud.SpannerLib.V1.InfoRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Info, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.Pool CreatePool(global::Google.Cloud.SpannerLib.V1.CreatePoolRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CreatePool(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.Pool CreatePool(global::Google.Cloud.SpannerLib.V1.CreatePoolRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_CreatePool, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CreatePoolAsync(global::Google.Cloud.SpannerLib.V1.CreatePoolRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CreatePoolAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CreatePoolAsync(global::Google.Cloud.SpannerLib.V1.CreatePoolRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_CreatePool, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty ClosePool(global::Google.Cloud.SpannerLib.V1.Pool request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ClosePool(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty ClosePool(global::Google.Cloud.SpannerLib.V1.Pool request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_ClosePool, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ClosePoolAsync(global::Google.Cloud.SpannerLib.V1.Pool request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ClosePoolAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ClosePoolAsync(global::Google.Cloud.SpannerLib.V1.Pool request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_ClosePool, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.Connection CreateConnection(global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CreateConnection(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.Connection CreateConnection(global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_CreateConnection, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CreateConnectionAsync(global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CreateConnectionAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CreateConnectionAsync(global::Google.Cloud.SpannerLib.V1.CreateConnectionRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_CreateConnection, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty CloseConnection(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CloseConnection(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty CloseConnection(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_CloseConnection, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CloseConnectionAsync(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CloseConnectionAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CloseConnectionAsync(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_CloseConnection, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.Rows Execute(global::Google.Cloud.SpannerLib.V1.ExecuteRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Execute(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.SpannerLib.V1.Rows Execute(global::Google.Cloud.SpannerLib.V1.ExecuteRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Execute, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ExecuteAsync(global::Google.Cloud.SpannerLib.V1.ExecuteRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ExecuteAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ExecuteAsync(global::Google.Cloud.SpannerLib.V1.ExecuteRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Execute, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall ExecuteStreaming(global::Google.Cloud.SpannerLib.V1.ExecuteRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ExecuteStreaming(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncServerStreamingCall ExecuteStreaming(global::Google.Cloud.SpannerLib.V1.ExecuteRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncServerStreamingCall(__Method_ExecuteStreaming, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.ExecuteBatchDmlResponse ExecuteBatch(global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ExecuteBatch(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.ExecuteBatchDmlResponse ExecuteBatch(global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_ExecuteBatch, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ExecuteBatchAsync(global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ExecuteBatchAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ExecuteBatchAsync(global::Google.Cloud.SpannerLib.V1.ExecuteBatchRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_ExecuteBatch, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.ResultSetMetadata Metadata(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Metadata(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.ResultSetMetadata Metadata(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Metadata, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall MetadataAsync(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return MetadataAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall MetadataAsync(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Metadata, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.ListValue Next(global::Google.Cloud.SpannerLib.V1.NextRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Next(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.ListValue Next(global::Google.Cloud.SpannerLib.V1.NextRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Next, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall NextAsync(global::Google.Cloud.SpannerLib.V1.NextRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return NextAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall NextAsync(global::Google.Cloud.SpannerLib.V1.NextRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Next, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.ResultSetStats ResultSetStats(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ResultSetStats(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.ResultSetStats ResultSetStats(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_ResultSetStats, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ResultSetStatsAsync(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ResultSetStatsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall ResultSetStatsAsync(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_ResultSetStats, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty CloseRows(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CloseRows(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty CloseRows(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_CloseRows, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CloseRowsAsync(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CloseRowsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CloseRowsAsync(global::Google.Cloud.SpannerLib.V1.Rows request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_CloseRows, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty BeginTransaction(global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return BeginTransaction(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty BeginTransaction(global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_BeginTransaction, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall BeginTransactionAsync(global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return BeginTransactionAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall BeginTransactionAsync(global::Google.Cloud.SpannerLib.V1.BeginTransactionRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_BeginTransaction, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.CommitResponse Commit(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Commit(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.CommitResponse Commit(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Commit, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CommitAsync(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return CommitAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall CommitAsync(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Commit, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty Rollback(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return Rollback(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Protobuf.WellKnownTypes.Empty Rollback(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_Rollback, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall RollbackAsync(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return RollbackAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall RollbackAsync(global::Google.Cloud.SpannerLib.V1.Connection request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_Rollback, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.CommitResponse WriteMutations(global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return WriteMutations(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual global::Google.Cloud.Spanner.V1.CommitResponse WriteMutations(global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest request, grpc::CallOptions options) + { + return CallInvoker.BlockingUnaryCall(__Method_WriteMutations, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall WriteMutationsAsync(global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest request, grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return WriteMutationsAsync(request, new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncUnaryCall WriteMutationsAsync(global::Google.Cloud.SpannerLib.V1.WriteMutationsRequest request, grpc::CallOptions options) + { + return CallInvoker.AsyncUnaryCall(__Method_WriteMutations, null, options, request); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall ConnectionStream(grpc::Metadata headers = null, global::System.DateTime? deadline = null, global::System.Threading.CancellationToken cancellationToken = default(global::System.Threading.CancellationToken)) + { + return ConnectionStream(new grpc::CallOptions(headers, deadline, cancellationToken)); + } + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + public virtual grpc::AsyncDuplexStreamingCall ConnectionStream(grpc::CallOptions options) + { + return CallInvoker.AsyncDuplexStreamingCall(__Method_ConnectionStream, null, options); + } + /// Creates a new instance of client from given ClientBaseConfiguration. + [global::System.CodeDom.Compiler.GeneratedCode("grpc_csharp_plugin", null)] + protected override SpannerLibClient NewInstance(ClientBaseConfiguration configuration) + { + return new SpannerLibClient(configuration); + } + } + + } +} +#endregion diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/spannerlib-dotnet-grpc-v1.csproj b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/spannerlib-dotnet-grpc-v1.csproj new file mode 100644 index 00000000..3141df11 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-v1/spannerlib-dotnet-grpc-v1.csproj @@ -0,0 +1,15 @@ + + + + netstandard2.1 + Google.Cloud.SpannerLib.V1 + enable + default + + + + + + + + diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/MockSpannerServer.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/MockSpannerServer.cs index 269c77ab..28118fdf 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/MockSpannerServer.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/MockSpannerServer.cs @@ -795,4 +795,10 @@ public override Task DropDatabase(DropDatabaseRequest request, ServerCall _requests.Enqueue(request); return Task.FromResult(new Empty()); } + + public void Reset() + { + _requests.Clear(); + } + } \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/SpannerConverter.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/SpannerConverter.cs index cbb3096c..9b64ffab 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/SpannerConverter.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-mockserver/SpannerConverter.cs @@ -61,10 +61,18 @@ internal static Value ToProtobufValue(Spanner.V1.Type type, object? value) .ToString(InvariantCulture) }; case TypeCode.Float32: + if (value is float float32) + { + return new Value { NumberValue = float32 }; + } return new Value { NumberValue = Convert.ToSingle(value, InvariantCulture) }; case TypeCode.Float64: return new Value { NumberValue = Convert.ToDouble(value, InvariantCulture) }; case TypeCode.Timestamp: + if (value is string value1) + { + return Value.ForString(value1); + } return new Value { StringValue = XmlConvert.ToString(Convert.ToDateTime(value, InvariantCulture), XmlDateTimeSerializationMode.Utc) @@ -100,7 +108,7 @@ internal static Value ToProtobufValue(Spanner.V1.Type type, object? value) } if (value is string str) { - return Value.ForString(SpannerNumeric.Parse(str).ToString()); + return Value.ForString(str); } if (value is float || value is double || value is decimal) { @@ -122,6 +130,8 @@ internal static Value ToProtobufValue(Spanner.V1.Type type, object? value) return Value.ForString(numericValue.ToString()); } throw new ArgumentException("Numeric parameters must be of type SpannerNumeric or string"); + case TypeCode.Uuid: + return Value.ForString(value.ToString()); default: throw new ArgumentOutOfRangeException(nameof(type.Code), type.Code, null); diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-native-impl/SharedLibSpanner.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-native-impl/SharedLibSpanner.cs index 1a94c318..431d1774 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-native-impl/SharedLibSpanner.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-native-impl/SharedLibSpanner.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using System.Threading; using System.Threading.Tasks; using Google.Cloud.Spanner.V1; using Google.Protobuf; @@ -115,9 +116,9 @@ public Rows Execute(Connection connection, ExecuteSqlRequest statement) return new Rows(connection, handler.ObjectId()); } - public Task ExecuteAsync(Connection connection, ExecuteSqlRequest statement) + public Task ExecuteAsync(Connection connection, ExecuteSqlRequest statement, CancellationToken cancellationToken) { - return Task.Run(() => Execute(connection, statement)); + return Task.Run(() => Execute(connection, statement), cancellationToken); } public long[] ExecuteBatch(Connection connection, ExecuteBatchDmlRequest statements) @@ -154,9 +155,9 @@ public long[] ExecuteBatch(Connection connection, ExecuteBatchDmlRequest stateme return result; } - public Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequest statements) + public Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequest statements, CancellationToken cancellationToken = default) { - return Task.Run(() => ExecuteBatch(connection, statements)); + return Task.Run(() => ExecuteBatch(connection, statements), cancellationToken); } public ResultSetMetadata? Metadata(Rows rows) @@ -165,9 +166,9 @@ public Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequ return handler.Length == 0 ? null : ResultSetMetadata.Parser.ParseFrom(handler.Value()); } - public async Task MetadataAsync(Rows rows) + public async Task MetadataAsync(Rows rows, CancellationToken cancellationToken = default) { - return await Task.Run(() => Metadata(rows)); + return await Task.Run(() => Metadata(rows), cancellationToken); } public ResultSetStats? Stats(Rows rows) @@ -182,9 +183,9 @@ public Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequ return handler.Length == 0 ? null : ListValue.Parser.ParseFrom(handler.Value()); } - public async Task NextAsync(Rows rows, int numRows, ISpannerLib.RowEncoding encoding) + public async Task NextAsync(Rows rows, int numRows, ISpannerLib.RowEncoding encoding, CancellationToken cancellationToken = default) { - return await Task.Run(() => Next(rows, numRows, encoding)); + return await Task.Run(() => Next(rows, numRows, encoding), cancellationToken); } public void CloseRows(Rows rows) @@ -192,6 +193,11 @@ public void CloseRows(Rows rows) ExecuteAndReleaseLibraryFunction(() => SpannerLib.CloseRows(rows.SpannerConnection.Pool.Id, rows.SpannerConnection.Id, rows.Id)); } + public Task CloseRowsAsync(Rows rows, CancellationToken cancellationToken = default) + { + return Task.Run(() => CloseRows(rows), cancellationToken); + } + public void BeginTransaction(Connection connection, TransactionOptions transactionOptions) { using var handler = ExecuteLibraryFunction(() => @@ -208,8 +214,18 @@ public void BeginTransaction(Connection connection, TransactionOptions transacti return handler.Length == 0 ? null : CommitResponse.Parser.ParseFrom(handler.Value()); } + public Task CommitAsync(Connection connection, CancellationToken cancellationToken = default) + { + return Task.Run(() => Commit(connection), cancellationToken); + } + public void Rollback(Connection connection) { ExecuteAndReleaseLibraryFunction(() => SpannerLib.Rollback(connection.Pool.Id, connection.Id)); } + + public Task RollbackAsync(Connection connection, CancellationToken cancellationToken = default) + { + return Task.Run(() => Rollback(connection), cancellationToken); + } } diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/AbstractMockServerTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/AbstractMockServerTests.cs new file mode 100644 index 00000000..a98b679b --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/AbstractMockServerTests.cs @@ -0,0 +1,66 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using Google.Cloud.SpannerLib.Grpc; +using Google.Cloud.SpannerLib.MockServer; +using Google.Cloud.SpannerLib.Native.Impl; +using NUnit.Framework.Internal; + +namespace Google.Cloud.SpannerLib.Tests; + +public abstract class AbstractMockServerTests +{ + public enum LibType + { + Shared, + Grpc, + GrpcTcp, + } + + protected readonly Dictionary SpannerLibDictionary = new([ + new KeyValuePair(LibType.Shared, new SharedLibSpanner()), + new KeyValuePair(LibType.Grpc, new GrpcLibSpanner()), + new KeyValuePair(LibType.GrpcTcp, new GrpcLibSpanner(addressType: Server.AddressType.Tcp)), + ]); + + protected SpannerMockServerFixture Fixture; + + protected string ConnectionString => $"{Fixture.Host}:{Fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; + + [OneTimeSetUp] + public void Setup() + { + Fixture = new SpannerMockServerFixture(); + Fixture.SpannerMock.AddOrUpdateStatementResult("SELECT 1", StatementResult.CreateSelect1ResultSet()); + } + + [OneTimeTearDown] + public void Teardown() + { + foreach (var spannerLib in SpannerLibDictionary.Values) + { + spannerLib.Dispose(); + } + Fixture.Dispose(); + } + + [TearDown] + public void Reset() + { + Fixture.SpannerMock.Reset(); + Fixture.DatabaseAdminMock.Reset(); + Fixture.SpannerMock.AddOrUpdateStatementResult("SELECT 1", StatementResult.CreateSelect1ResultSet()); + } + +} \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BasicTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BasicTests.cs index 687746f2..81358026 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BasicTests.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BasicTests.cs @@ -24,46 +24,28 @@ namespace Google.Cloud.SpannerLib.Tests; -public class BasicTests +public class BasicTests : AbstractMockServerTests { - private readonly ISpannerLib _spannerLib = new SharedLibSpanner(); - - private SpannerMockServerFixture _fixture; - - private string ConnectionString => $"{_fixture.Host}:{_fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; - - [SetUp] - public void Setup() - { - _fixture = new SpannerMockServerFixture(); - _fixture.SpannerMock.AddOrUpdateStatementResult("SELECT 1", StatementResult.CreateSelect1ResultSet()); - } - - [TearDown] - public void Teardown() - { - _fixture.Dispose(); - } [Test] - public void TestCreatePool() + public void TestCreatePool([Values] LibType libType) { - var pool = Pool.Create(_spannerLib, ConnectionString); + var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); pool.Close(); } [Test] - public void TestCreateConnection() + public void TestCreateConnection([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); var connection = pool.CreateConnection(); connection.Close(); } [Test] - public void TestExecuteQuery() + public void TestExecuteQuery([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "SELECT 1" }); for (var row = rows.Next(); row != null; row = rows.Next()) @@ -75,12 +57,12 @@ public void TestExecuteQuery() } [Test] - public void TestExecuteQueryError() + public void TestExecuteQueryError([Values] LibType libType) { var sql = "select * from non_existing_table"; - _fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateException(new RpcException(new Status(StatusCode.NotFound, "Table not found")))); + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateException(new RpcException(new Status(StatusCode.NotFound, "Table not found")))); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); SpannerException exception = Assert.Throws(() => connection.Execute(new ExecuteSqlRequest { Sql = sql })); Assert.That(exception.Code, Is.EqualTo(Code.NotFound)); @@ -88,15 +70,15 @@ public void TestExecuteQueryError() } [Test] - public void TestExecuteParameterizedQuery() + public void TestExecuteParameterizedQuery([Values] LibType libType) { var sql = "select col_varchar from all_types where col_bigint=$1::bigint"; - _fixture.SpannerMock.AddOrUpdateStatementResult(sql, + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateSingleColumnResultSet( new Spanner.V1.Type { Code = TypeCode.String }, "col_varchar", "some-value")); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); var parameters = new Struct { @@ -119,15 +101,15 @@ public void TestExecuteParameterizedQuery() } [Test] - public void TestQueryParameterStartingWithUnderscore() + public void TestQueryParameterStartingWithUnderscore([Values] LibType libType) { var sql = "select col_string from all_types where col_int64=@__id"; - _fixture.SpannerMock.AddOrUpdateStatementResult(sql, + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateSingleColumnResultSet( new Spanner.V1.Type { Code = TypeCode.String }, "col_string", "some-value")); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); var parameters = new Struct { @@ -151,9 +133,9 @@ public void TestQueryParameterStartingWithUnderscore() [Test] [Ignore("execute async disabled for now")] - public async Task TestExecuteQueryAsync() + public async Task TestExecuteQueryAsync([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using var rows = await connection.ExecuteAsync(new ExecuteSqlRequest { Sql = "SELECT 1" }); var metadata = rows.Metadata; @@ -167,9 +149,9 @@ public async Task TestExecuteQueryAsync() } [Test] - public void TestReadOnlyTransaction() + public void TestReadOnlyTransaction([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions { ReadOnly = new TransactionOptions.Types.ReadOnly() }); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "SELECT 1" }); @@ -184,11 +166,11 @@ public void TestReadOnlyTransaction() } [Test] - public void TestReadWriteTransaction() + public void TestReadWriteTransaction([Values] LibType libType) { var sql = "update table1 set value='one' where id=1"; - _fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateUpdateCount(1)); - using var pool = Pool.Create(_spannerLib, ConnectionString); + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateUpdateCount(1)); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions { ReadWrite = new TransactionOptions.Types.ReadWrite() }); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = sql }); @@ -202,7 +184,7 @@ public void TestReadWriteTransaction() public void TestBenchmarkNativeSpannerLib() { var totalRowCount = 1000000; - _fixture.SpannerMock.AddOrUpdateStatementResult( + Fixture.SpannerMock.AddOrUpdateStatementResult( "select * from all_types", StatementResult.CreateResultSet( new List> @@ -236,7 +218,7 @@ public void TestBenchmarkNativeSpannerLib() public void TestBenchmarkDotnetGrpcClient() { var totalRowCount = 1000000; - _fixture.SpannerMock.AddOrUpdateStatementResult( + Fixture.SpannerMock.AddOrUpdateStatementResult( "select * from all_types", StatementResult.CreateResultSet( new List> @@ -251,7 +233,7 @@ public void TestBenchmarkDotnetGrpcClient() var totalValueCount = totalRowCount * 5; var builder = new SpannerClientBuilder { - Endpoint = $"http://{_fixture.Endpoint}", + Endpoint = $"http://{Fixture.Endpoint}", ChannelCredentials = ChannelCredentials.Insecure }; SpannerClient client = builder.Build(); diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BatchTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BatchTests.cs index e2c95b01..8428e941 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BatchTests.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BatchTests.cs @@ -15,38 +15,19 @@ using Google.Cloud.Spanner.Admin.Database.V1; using Google.Cloud.Spanner.V1; using Google.Cloud.SpannerLib.MockServer; -using Google.Cloud.SpannerLib.Native.Impl; using Google.Protobuf.WellKnownTypes; namespace Google.Cloud.SpannerLib.Tests; -public class BatchTests +public class BatchTests : AbstractMockServerTests { - private readonly ISpannerLib _spannerLib = new SharedLibSpanner(); - - private SpannerMockServerFixture _fixture; - - private string ConnectionString => $"{_fixture.Host}:{_fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; - - [SetUp] - public void Setup() - { - _fixture = new SpannerMockServerFixture(); - } - - [TearDown] - public void Teardown() - { - _fixture.Dispose(); - } - [Test] - public void TestBatchDml() + public void TestBatchDml([Values] LibType libType) { var insert = "insert into test (id, value) values (@id, @value)"; - _fixture.SpannerMock.AddOrUpdateStatementResult(insert, StatementResult.CreateUpdateCount(1)); + Fixture.SpannerMock.AddOrUpdateStatementResult(insert, StatementResult.CreateUpdateCount(1)); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); var updateCounts = connection.ExecuteBatch([ new ExecuteBatchDmlRequest.Types.Statement {Sql = insert, Params = new Struct @@ -67,15 +48,15 @@ public void TestBatchDml() }}, ]); Assert.That(updateCounts, Is.EqualTo(new long[]{1,1})); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestBatchDdl() + public void TestBatchDdl([Values] LibType libType) { // We don't need to set up any results for DDL statements on the mock server. // It automatically responds with an long-running operation that has finished when it receives a DDL request. - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); // The input argument for ExecuteBatch is always a ExecuteBatchDmlRequest, even for DDL statements. var updateCounts = connection.ExecuteBatch([ @@ -83,7 +64,7 @@ public void TestBatchDdl() new ExecuteBatchDmlRequest.Types.Statement {Sql = "create index my_index on my_table (value)"}, ]); Assert.That(updateCounts, Is.EqualTo(new long[]{-1,-1})); - Assert.That(_fixture.DatabaseAdminMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.DatabaseAdminMock.Requests.OfType().Count(), Is.EqualTo(1)); } } \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BenchmarkTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BenchmarkTests.cs new file mode 100644 index 00000000..74504411 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/BenchmarkTests.cs @@ -0,0 +1,197 @@ +// Copyright 2025 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +using System.Diagnostics; +using Google.Cloud.Spanner.Data; +using Google.Cloud.Spanner.V1; +using Google.Protobuf.WellKnownTypes; + +namespace Google.Cloud.SpannerLib.Tests; + +public class BenchmarkTests : AbstractMockServerTests +{ + readonly struct Stats + { + public TimeSpan Min { get; init; } + public TimeSpan P50 { get; init; } + public TimeSpan P90 { get; init; } + public TimeSpan P95 { get; init; } + public TimeSpan P99 { get; init; } + public TimeSpan Max { get; init; } + public TimeSpan Avg { get; init; } + + public override string ToString() + { + return $"Min: {Min}{Environment.NewLine}" + + $"P50: {P50}{Environment.NewLine}" + + $"P90: {P90}{Environment.NewLine}" + + $"P95: {P95}{Environment.NewLine}" + + $"P99: {P99}{Environment.NewLine}" + + $"Max: {Max}{Environment.NewLine}" + + $"Avg: {Avg}{Environment.NewLine}"; + } + } + + [Test, Sequential] + [Ignore("for local testing")] + public async Task TestBenchmarkRealSpanner([Values] LibType? libType, [Values(false, false, false, true)] bool clientLib) + { + const string connectionString = "projects/appdev-soda-spanner-staging/instances/knut-test-ycsb/databases/knut-test-db"; + const int numTasks = 2000; + object connector; + + if (clientLib) + { + connector = $"Data Source={connectionString}"; + } + else + { + var pool = Pool.Create(SpannerLibDictionary[libType!.Value], connectionString); + connector = pool; + } + + // Warmup + var warmupDuration = await ReadRandomRows(connector, 10); + Console.WriteLine($"Warmup Duration: {warmupDuration}"); + + for (var i = 0; i < 10; i++) + { + var numRows = (i + 1) * 10; + var duration = await ReadRandomRows(connector, numRows); + Console.WriteLine($"Duration ({numRows}): {duration}"); + } + + var stopwatch = Stopwatch.StartNew(); + var tasks = new Task[numTasks]; + for (var i = 0; i < numTasks; i++) + { + tasks[i] = ReadRandomRows(connector, 10); + } + + await Task.WhenAll(tasks); + var durations = new TimeSpan[numTasks]; + for (var i = 0; i < numTasks; i++) + { + durations[i] = tasks[i].Result; + } + var totalDuration = stopwatch.Elapsed; + + var stats = CalculateStats(durations); + Console.WriteLine(); + Console.WriteLine($"Num tasks: {numTasks}"); + Console.WriteLine($"{stats}"); + ThreadPool.GetMaxThreads(out var workerThreads, out _); + Console.WriteLine($"Max threads: {workerThreads}"); + Console.WriteLine($"Total time: {totalDuration}"); + + if (connector is IDisposable disposable) + { + disposable.Dispose(); + } + } + + static Stats CalculateStats(TimeSpan[] durations) + { + var ordered = durations.Order().ToArray(); + var stats = new Stats + { + Min = ordered[0], + P50 = ordered[ordered.Length * 50 / 100], + P90 = ordered[ordered.Length * 90 / 100], + P95 = ordered[ordered.Length * 95 / 100], + P99 = ordered[ordered.Length * 99 / 100], + Max = ordered[^1], + Avg = TimeSpan.FromTicks((long) ordered.Average(duration => duration.Ticks)) + }; + return stats; + } + + static Task ReadRandomRows(object connector, int maxRows) + { + if (connector is Pool pool) + { + return ReadRandomRows(pool, maxRows); + } + if (connector is string connString) + { + return ReadRandomRows(connString, maxRows); + } + throw new NotSupportedException(); + } + + static async Task ReadRandomRows(Pool pool, int maxRows) + { + // Add the randomly selected identifiers to a set to ensure that we know exactly how many rows will be returned, + // as the random selection of identifiers could contain duplicates. + var set = new HashSet(); + var list = Value.ForList(); + list.ListValue.Values.Capacity = maxRows; + for (var c = 0; c < maxRows; c++) + { + var id = Random.Shared.Next(1, 1_000_001); + set.Add(id); + list.ListValue.Values.Add(Value.ForString($"{id}")); + } + await using var connection = pool.CreateConnection(); + + var stopwatch = Stopwatch.StartNew(); + var request = new ExecuteSqlRequest + { + Sql = "select * from all_types where col_bigint = any($1)", + Params = new Struct { Fields = { ["p1"] = list } }, + }; + var count = 0; + await using var rows = await connection.ExecuteAsync(request); + while (await rows.NextAsync() is { } row) + { + Assert.That(row.Values.Count, Is.EqualTo(10)); + count++; + } + Assert.That(count, Is.EqualTo(set.Count)); + + return stopwatch.Elapsed; + } + + static async Task ReadRandomRows(string connectionString, int maxRows) + { + var set = new HashSet(); + var list = new List + { + Capacity = maxRows + }; + for (var c = 0; c < maxRows; c++) + { + var id = Random.Shared.Next(1, 1_000_001); + set.Add(id); + list.Add(id); + } + await using var connection = new SpannerConnection(connectionString); + + var stopwatch = Stopwatch.StartNew(); + await using var cmd = connection.CreateSelectCommand( + "select * from all_types where col_bigint = any($1)", + new SpannerParameterCollection {{"p1", SpannerDbType.ArrayOf(SpannerDbType.Int64), list}} + ); + var count = 0; + await using var rows = await cmd.ExecuteReaderAsync(); + while (await rows.ReadAsync()) + { + Assert.That(rows.FieldCount, Is.EqualTo(10)); + count++; + } + Assert.That(count, Is.EqualTo(set.Count)); + + return stopwatch.Elapsed; + } +} \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/ConnectionTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/ConnectionTests.cs index 1f4e88ea..b6bc88ad 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/ConnectionTests.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/ConnectionTests.cs @@ -13,47 +13,27 @@ // limitations under the License. using Google.Cloud.Spanner.V1; -using Google.Cloud.SpannerLib.MockServer; -using Google.Cloud.SpannerLib.Native.Impl; using Google.Protobuf.WellKnownTypes; using Google.Rpc; namespace Google.Cloud.SpannerLib.Tests; -public class ConnectionTests +public class ConnectionTests : AbstractMockServerTests { - private readonly ISpannerLib _spannerLib = new SharedLibSpanner(); - - private SpannerMockServerFixture _fixture; - - private string ConnectionString => $"{_fixture.Host}:{_fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; - - [SetUp] - public void Setup() - { - _fixture = new SpannerMockServerFixture(); - } - - [TearDown] - public void Teardown() - { - _fixture.Dispose(); - } - [Test] - public void TestCreateConnection() + public void TestCreateConnection([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); Assert.That(connection, Is.Not.Null); Assert.That(connection.Id, Is.GreaterThan(0)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestCreateTwoConnections() + public void TestCreateTwoConnections([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection1 = pool.CreateConnection(); using var connection2 = pool.CreateConnection(); Assert.That(connection1, Is.Not.Null); @@ -61,13 +41,13 @@ public void TestCreateTwoConnections() Assert.That(connection1.Id, Is.GreaterThan(0)); Assert.That(connection2.Id, Is.GreaterThan(0)); Assert.That(connection1.Id, Is.Not.EqualTo(connection2.Id)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestWriteMutations() + public void TestWriteMutations([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); var insertMutation = new Mutation { @@ -99,9 +79,9 @@ public void TestWriteMutations() }); Assert.That(response, Is.Not.Null); Assert.That(response.CommitTimestamp, Is.Not.Null); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - var commit = _fixture.SpannerMock.Requests.OfType().Single(); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + var commit = Fixture.SpannerMock.Requests.OfType().Single(); Assert.That(commit, Is.Not.Null); Assert.That(commit.Mutations.Count, Is.EqualTo(2)); Assert.That(commit.Mutations[0].Insert.Values.Count, Is.EqualTo(2)); @@ -109,9 +89,9 @@ public void TestWriteMutations() } [Test] - public void TestWriteMutationsInTransaction() + public void TestWriteMutationsInTransaction([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions()); @@ -136,18 +116,18 @@ public void TestWriteMutationsInTransaction() response = connection.Commit(); Assert.That(response, Is.Not.Null); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - var commit = _fixture.SpannerMock.Requests.OfType().Single(); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + var commit = Fixture.SpannerMock.Requests.OfType().Single(); Assert.That(commit, Is.Not.Null); Assert.That(commit.Mutations.Count, Is.EqualTo(1)); Assert.That(commit.Mutations[0].Insert.Values.Count, Is.EqualTo(1)); } [Test] - public void TestWriteMutationsInReadOnlyTransaction() + public void TestWriteMutationsInReadOnlyTransaction([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions{ReadOnly = new TransactionOptions.Types.ReadOnly()}); diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/PoolTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/PoolTests.cs index 314770c2..c33ffdbb 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/PoolTests.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/PoolTests.cs @@ -14,48 +14,29 @@ using Google.Cloud.Spanner.V1; using Google.Cloud.SpannerLib.MockServer; -using Google.Cloud.SpannerLib.Native.Impl; using Google.Rpc; using Grpc.Core; namespace Google.Cloud.SpannerLib.Tests; -public class PoolTests +public class PoolTests : AbstractMockServerTests { - private readonly ISpannerLib _spannerLib = new SharedLibSpanner(); - - private SpannerMockServerFixture _fixture; - - private string ConnectionString => $"{_fixture.Host}:{_fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; - - [SetUp] - public void Setup() - { - _fixture = new SpannerMockServerFixture(); - } - - [TearDown] - public void Teardown() - { - _fixture.Dispose(); - } - [Test] - public void TestCreatePool() + public void TestCreatePool([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); Assert.That(pool, Is.Not.Null); Assert.That(pool.Id, Is.GreaterThan(0)); // Creating a pool should create the underlying client and a multiplexed session. - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestCreatePoolFails() + public void TestCreatePoolFails([Values] LibType libType) { - _fixture.SpannerMock.AddOrUpdateExecutionTime(nameof(_fixture.SpannerMock.CreateSession), ExecutionTime.CreateException(StatusCode.PermissionDenied, "Not allowed")); + Fixture.SpannerMock.AddOrUpdateExecutionTime(nameof(Fixture.SpannerMock.CreateSession), ExecutionTime.CreateException(StatusCode.PermissionDenied, "Not allowed")); - SpannerException exception = Assert.Throws(() => Pool.Create(_spannerLib, ConnectionString)); + SpannerException exception = Assert.Throws(() => Pool.Create(SpannerLibDictionary[libType], ConnectionString)); Assert.That(exception.Code, Is.EqualTo(Code.PermissionDenied)); } diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/RowsTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/RowsTests.cs index e45fb226..a4d0d253 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/RowsTests.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/RowsTests.cs @@ -15,35 +15,17 @@ using Google.Cloud.Spanner.Admin.Database.V1; using Google.Cloud.Spanner.V1; using Google.Cloud.SpannerLib.MockServer; -using Google.Cloud.SpannerLib.Native.Impl; +using Google.Rpc; +using TypeCode = Google.Cloud.Spanner.V1.TypeCode; namespace Google.Cloud.SpannerLib.Tests; -public class RowsTests +public class RowsTests : AbstractMockServerTests { - private readonly ISpannerLib _spannerLib = new SharedLibSpanner(); - - private SpannerMockServerFixture _fixture; - - private string ConnectionString => $"{_fixture.Host}:{_fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; - - [SetUp] - public void Setup() - { - _fixture = new SpannerMockServerFixture(); - _fixture.SpannerMock.AddOrUpdateStatementResult("SELECT 1", StatementResult.CreateSelect1ResultSet()); - } - - [TearDown] - public void Teardown() - { - _fixture.Dispose(); - } - [Test] - public void TestExecuteSelect1() + public void TestExecuteSelect1([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "SELECT 1" }); var numRows = 0; @@ -58,14 +40,28 @@ public void TestExecuteSelect1() } [Test] - public void TestRandomResults() + public void TestEmptyResults([Values] LibType libType) + { + var sql = "select * from (select 1) where false"; + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateSingleColumnResultSet(new Spanner.V1.Type{Code = TypeCode.Int64}, "c")); + + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); + using var connection = pool.CreateConnection(); + using var rows = connection.Execute(new ExecuteSqlRequest { Sql = sql }); + Assert.That(rows.Metadata, Is.Not.Null); + Assert.That(rows.Metadata.RowType.Fields.Count, Is.EqualTo(1)); + Assert.That(rows.Next(), Is.Null); + } + + [Test] + public void TestRandomResults([Values] LibType libType) { var numRows = 10; var rowType = RandomResultSetGenerator.GenerateAllTypesRowType(); var results = RandomResultSetGenerator.Generate(rowType, numRows); - _fixture.SpannerMock.AddOrUpdateStatementResult("select * from random", StatementResult.CreateQuery(results)); + Fixture.SpannerMock.AddOrUpdateStatementResult("select * from random", StatementResult.CreateQuery(results)); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "select * from random" }); @@ -77,48 +73,118 @@ public void TestRandomResults() } Assert.That(rowCount, Is.EqualTo(numRows)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - var request = _fixture.SpannerMock.Requests.OfType().First(); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + var request = Fixture.SpannerMock.Requests.OfType().First(); + Assert.That(request.Transaction?.SingleUse?.ReadOnly?.HasStrong ?? false); + } + + [Test] + public void TestStopHalfway([Values] LibType libType) + { + var numRows = 10; + var rowType = RandomResultSetGenerator.GenerateAllTypesRowType(); + var results = RandomResultSetGenerator.Generate(rowType, numRows); + Fixture.SpannerMock.AddOrUpdateStatementResult("select * from random", StatementResult.CreateQuery(results)); + var stopAfterRows = Random.Shared.Next(1, numRows - 1); + + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); + using var connection = pool.CreateConnection(); + using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "select * from random" }); + Assert.That(rows.Metadata, Is.Not.Null); + Assert.That(rows.Metadata.RowType.Fields.Count, Is.EqualTo(rowType.Fields.Count)); + + var rowCount = 0; + while (rows.Next() is { } row) + { + rowCount++; + Assert.That(row.Values.Count, Is.EqualTo(rowType.Fields.Count)); + if (rowCount == stopAfterRows) + { + break; + } + } + + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + var request = Fixture.SpannerMock.Requests.OfType().First(); Assert.That(request.Transaction?.SingleUse?.ReadOnly?.HasStrong ?? false); } [Test] - public void TestExecuteDml() + public void TestCloseConnectionWithOpenRows([Values] LibType libType) + { + var numRows = 5000; + var rowType = RandomResultSetGenerator.GenerateAllTypesRowType(); + var results = RandomResultSetGenerator.Generate(rowType, numRows); + Fixture.SpannerMock.AddOrUpdateStatementResult("select * from random", StatementResult.CreateQuery(results)); + + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); + using var connection = pool.CreateConnection(); + using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "select * from random" }); + + // Verify that we can fetch the first row. + Assert.That(rows.Next(), Is.Not.Null); + // Close the connection while the rows object is still open. + connection.Close(); + // Getting all the rows should not be possible. + // If the underlying Rows object uses a stream, then it could be that it still receives some rows, but it will + // eventually fail. + var exception = Assert.Throws(() => + { + while (rows.Next() is not null) + { + } + }); + // The error is 'Connection not found' or an internal exception from the underlying driver, depending on exactly + // when the driver detects that the connection and all related objects have been closed. + Assert.That(exception.Code is Code.NotFound or Code.Unknown, Is.True); + + if (libType == LibType.Shared) + { + // TODO: Remove this once it has been fixed in the shared library. + // Closing a Rows object that has already been closed because the connection has been closed, should + // be a no-op. + var closeException = Assert.Throws(() => rows.Close()); + Assert.That(closeException.Code, Is.EqualTo(Code.NotFound)); + } + } + + [Test] + public void TestExecuteDml([Values] LibType libType) { var sql = "update my_table set value=1 where id=2"; - _fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateUpdateCount(1L)); + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateUpdateCount(1L)); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = sql }); Assert.That(rows.Next(), Is.Null); Assert.That(rows.UpdateCount, Is.EqualTo(1L)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - var request = _fixture.SpannerMock.Requests.OfType().First(); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + var request = Fixture.SpannerMock.Requests.OfType().First(); Assert.That(request.Transaction?.Begin?.ReadWrite, Is.Not.Null); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestExecuteDdl() + public void TestExecuteDdl([Values] LibType libType) { // The mock DatabaseAdmin server always responds with a finished operation when // UpdateDatabaseDdl is called, so we don't need to set up any results. - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using var rows = connection.Execute(new ExecuteSqlRequest { Sql = "create my_table (id int64 primary key)" }); Assert.That(rows.Next(), Is.Null); Assert.That(rows.UpdateCount, Is.EqualTo(-1L)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); - Assert.That(_fixture.DatabaseAdminMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.DatabaseAdminMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestExecuteClientSideStatement() + public void TestExecuteClientSideStatement([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); using (var rows = connection.Execute(new ExecuteSqlRequest { Sql = "show variable retry_aborts_internally" })) { diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/TransactionTests.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/TransactionTests.cs index 0c55f56c..010fe5bd 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/TransactionTests.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/TransactionTests.cs @@ -14,66 +14,47 @@ using Google.Cloud.Spanner.V1; using Google.Cloud.SpannerLib.MockServer; -using Google.Cloud.SpannerLib.Native.Impl; using Google.Protobuf.WellKnownTypes; using Google.Rpc; namespace Google.Cloud.SpannerLib.Tests; -public class TransactionTests +public class TransactionTests : AbstractMockServerTests { - private readonly ISpannerLib _spannerLib = new SharedLibSpanner(); - - private SpannerMockServerFixture _fixture; - - private string ConnectionString => $"{_fixture.Host}:{_fixture.Port}/projects/p1/instances/i1/databases/d1;UsePlainText=true"; - - [SetUp] - public void Setup() - { - _fixture = new SpannerMockServerFixture(); - } - - [TearDown] - public void Teardown() - { - _fixture.Dispose(); - } - [Test] - public void TestBeginAndCommit() + public void TestBeginAndCommit([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions()); connection.Commit(); // TODO: The library should take a shortcut and just skip committing empty transactions. - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); } [Test] - public void TestBeginAndRollback() + public void TestBeginAndRollback([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions()); connection.Rollback(); // An empty transaction that is rolled back should be a no-op. - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); } [Test] - public void TestReadWriteTransaction() + public void TestReadWriteTransaction([Values] LibType libType) { var updateSql = "update my_table set value=@value where id=@id"; - _fixture.SpannerMock.AddOrUpdateStatementResult(updateSql, StatementResult.CreateUpdateCount(1)); + Fixture.SpannerMock.AddOrUpdateStatementResult(updateSql, StatementResult.CreateUpdateCount(1)); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions()); @@ -98,22 +79,22 @@ public void TestReadWriteTransaction() // There should be no BeginTransaction requests, as the transaction start is inlined with the // first statement. - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - var request = _fixture.SpannerMock.Requests.OfType().Single(); + var request = Fixture.SpannerMock.Requests.OfType().Single(); Assert.That(request.Transaction?.Begin?.ReadWrite, Is.Not.Null); } [Test] - public void TestReadOnlyTransaction() + public void TestReadOnlyTransaction([Values] LibType libType) { var numRows = 5; var sql = "select * from random"; - _fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateQuery(RandomResultSetGenerator.Generate(numRows))); + Fixture.SpannerMock.AddOrUpdateStatementResult(sql, StatementResult.CreateQuery(RandomResultSetGenerator.Generate(numRows))); - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); connection.BeginTransaction(new TransactionOptions { @@ -135,18 +116,18 @@ public void TestReadOnlyTransaction() // There should be no BeginTransaction requests, as the transaction start is inlined with the // first statement. - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); - Assert.That(_fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(1)); + Assert.That(Fixture.SpannerMock.Requests.OfType().Count(), Is.EqualTo(0)); - var request = _fixture.SpannerMock.Requests.OfType().Single(); + var request = Fixture.SpannerMock.Requests.OfType().Single(); Assert.That(request.Transaction?.Begin?.ReadOnly, Is.Not.Null); } [Test] - public void TestBeginTwice() + public void TestBeginTwice([Values] LibType libType) { - using var pool = Pool.Create(_spannerLib, ConnectionString); + using var pool = Pool.Create(SpannerLibDictionary[libType], ConnectionString); using var connection = pool.CreateConnection(); // Try to start two transactions on a connection. connection.BeginTransaction(new TransactionOptions()); diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/spannerlib-dotnet-tests.csproj b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/spannerlib-dotnet-tests.csproj index 7ff1583e..0fb199a0 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/spannerlib-dotnet-tests.csproj +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-tests/spannerlib-dotnet-tests.csproj @@ -11,6 +11,7 @@ + @@ -22,6 +23,7 @@ + diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet.sln b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet.sln index 9c030840..c12c60ca 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet.sln +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet.sln @@ -10,6 +10,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spannerlib-dotnet-tests", " EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spannerlib-dotnet-mockserver", "spannerlib-dotnet-mockserver\spannerlib-dotnet-mockserver.csproj", "{218C7FF7-84C7-4415-ABF8-69C5D7FCB6D9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spannerlib-dotnet-grpc-server", "spannerlib-dotnet-grpc-server\spannerlib-dotnet-grpc-server.csproj", "{331CF599-8892-46E5-81A3-25793A6BABA8}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spannerlib-dotnet-grpc-tests", "spannerlib-dotnet-grpc-tests\spannerlib-dotnet-grpc-tests.csproj", "{4B345CB2-82D5-41BC-80FD-D7EC8E8BF679}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spannerlib-dotnet-grpc-impl", "spannerlib-dotnet-grpc-impl\spannerlib-dotnet-grpc-impl.csproj", "{60403079-D584-4CB9-AAB7-7AC7FF39BEBE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "spannerlib-dotnet-grpc-v1", "spannerlib-dotnet-grpc-v1\spannerlib-dotnet-grpc-v1.csproj", "{C2538D0C-6544-4B44-88A7-02517B786FFD}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -36,5 +44,21 @@ Global {218C7FF7-84C7-4415-ABF8-69C5D7FCB6D9}.Debug|Any CPU.Build.0 = Debug|Any CPU {218C7FF7-84C7-4415-ABF8-69C5D7FCB6D9}.Release|Any CPU.ActiveCfg = Release|Any CPU {218C7FF7-84C7-4415-ABF8-69C5D7FCB6D9}.Release|Any CPU.Build.0 = Release|Any CPU + {331CF599-8892-46E5-81A3-25793A6BABA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {331CF599-8892-46E5-81A3-25793A6BABA8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {331CF599-8892-46E5-81A3-25793A6BABA8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {331CF599-8892-46E5-81A3-25793A6BABA8}.Release|Any CPU.Build.0 = Release|Any CPU + {4B345CB2-82D5-41BC-80FD-D7EC8E8BF679}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {4B345CB2-82D5-41BC-80FD-D7EC8E8BF679}.Debug|Any CPU.Build.0 = Debug|Any CPU + {4B345CB2-82D5-41BC-80FD-D7EC8E8BF679}.Release|Any CPU.ActiveCfg = Release|Any CPU + {4B345CB2-82D5-41BC-80FD-D7EC8E8BF679}.Release|Any CPU.Build.0 = Release|Any CPU + {60403079-D584-4CB9-AAB7-7AC7FF39BEBE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {60403079-D584-4CB9-AAB7-7AC7FF39BEBE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {60403079-D584-4CB9-AAB7-7AC7FF39BEBE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {60403079-D584-4CB9-AAB7-7AC7FF39BEBE}.Release|Any CPU.Build.0 = Release|Any CPU + {C2538D0C-6544-4B44-88A7-02517B786FFD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {C2538D0C-6544-4B44-88A7-02517B786FFD}.Debug|Any CPU.Build.0 = Debug|Any CPU + {C2538D0C-6544-4B44-88A7-02517B786FFD}.Release|Any CPU.ActiveCfg = Release|Any CPU + {C2538D0C-6544-4B44-88A7-02517B786FFD}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection EndGlobal diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/AbstractLibObject.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/AbstractLibObject.cs index a40850ae..7de9a28d 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/AbstractLibObject.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/AbstractLibObject.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using System.Threading.Tasks; namespace Google.Cloud.SpannerLib; @@ -20,7 +21,7 @@ namespace Google.Cloud.SpannerLib; /// This is the base class for all objects that are created by SpannerLib. It implements IDisposable and automatically /// closes the object in SpannerLib when the object is either being closed, disposed, or finalized. /// -public abstract class AbstractLibObject : IDisposable +public abstract class AbstractLibObject : IDisposable, IAsyncDisposable { internal ISpannerLib Spanner { get; } public long Id { get; } @@ -56,7 +57,13 @@ public void Dispose() Dispose(true); GC.SuppressFinalize(this); } - + + public async ValueTask DisposeAsync() + { + await DisposeAsyncCore().ConfigureAwait(false); + GC.SuppressFinalize(this); + } + public void Close() { Dispose(true); @@ -81,10 +88,35 @@ protected virtual void Dispose(bool disposing) _disposed = true; } } + + protected virtual async ValueTask DisposeAsyncCore() + { + if (_disposed) + { + return; + } + try + { + if (Id > 0) + { + await CloseLibObjectAsync(); + } + } + finally + { + _disposed = true; + } + } /// /// CloseLibObject should be implemented by concrete subclasses and call the corresponding Close function in /// SpannerLib. /// protected abstract void CloseLibObject(); + + protected virtual ValueTask CloseLibObjectAsync() + { + CloseLibObject(); + return default; + } } \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Connection.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Connection.cs index e3abaad1..1ef9943a 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Connection.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Connection.cs @@ -13,6 +13,7 @@ // limitations under the License. using System.Collections.Generic; +using System.Threading; using System.Threading.Tasks; using Google.Cloud.Spanner.V1; @@ -54,6 +55,11 @@ public void BeginTransaction(TransactionOptions transactionOptions) return Spanner.Commit(this); } + public Task CommitAsync(CancellationToken cancellationToken = default) + { + return Spanner.CommitAsync(this, cancellationToken); + } + /// /// Rollbacks the current transaction. /// @@ -62,6 +68,11 @@ public void Rollback() Spanner.Rollback(this); } + public Task RollbackAsync(CancellationToken cancellationToken = default) + { + return Spanner.RollbackAsync(this, cancellationToken); + } + /// /// Writes the given list of mutations to Spanner. If the connection has an active read/write transaction, then the /// mutations will be buffered in the current transaction and sent to Spanner when the transaction is committed. @@ -139,4 +150,9 @@ protected override void CloseLibObject() { Spanner.CloseConnection(this); } + + protected override async ValueTask CloseLibObjectAsync() + { + await Spanner.CloseConnectionAsync(this); + } } diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/ISpannerLib.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/ISpannerLib.cs index c91086ae..5dfd8e48 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/ISpannerLib.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/ISpannerLib.cs @@ -12,6 +12,8 @@ // See the License for the specific language governing permissions and // limitations under the License. +using System; +using System.Threading; using System.Threading.Tasks; using Google.Cloud.Spanner.V1; using Google.Protobuf.WellKnownTypes; @@ -24,7 +26,7 @@ namespace Google.Cloud.SpannerLib; /// it as a child process and communicating with it through a gRPC API. The classes in this assembly use this generic /// interface to abstract away the underlying communication method. /// -public interface ISpannerLib +public interface ISpannerLib : IDisposable { /// /// RowEncoding is used to specify the format that SpannerLib should use to return row data. @@ -66,6 +68,14 @@ public enum RowEncoding /// /// The connection to close public void CloseConnection(Connection connection); + + /// + /// Closes the given connection. This also closes any open Rows objects of this connection. Any active transaction + /// on the connection is rolled back. + /// + /// The connection to close + /// The cancellation token + public Task CloseConnectionAsync(Connection connection, CancellationToken cancellationToken = default) => Task.Run(() => CloseConnection(connection), cancellationToken); /// /// Writes an array of mutations to Spanner. The mutations are buffered in the current transaction of the given @@ -97,11 +107,12 @@ public enum RowEncoding /// /// The connection to use to execute the SQL statement /// The statement to execute + /// The cancellation token /// /// A Rows object with the results of the statement. The contents of the Rows object depends on the type of SQL /// statement. /// - public Task ExecuteAsync(Connection connection, ExecuteSqlRequest statement); + public Task ExecuteAsync(Connection connection, ExecuteSqlRequest statement, CancellationToken cancellationToken = default); /// /// Executes a batch of DML or DDL statements on Spanner. The batch may not contain a mix of DML and DDL statements. @@ -116,8 +127,9 @@ public enum RowEncoding /// /// The connection to use to execute the batch /// The DML or DDL statements to execute + /// The cancellation token /// The update count per statement. The update count for a DDL statement is -1. - public Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequest statements); + public Task ExecuteBatchAsync(Connection connection, ExecuteBatchDmlRequest statements, CancellationToken cancellationToken = default); /// /// Returns the ResultSetMetadata of a Rows object. This can be used to inspect the type of data that a Rows object @@ -132,8 +144,9 @@ public enum RowEncoding /// contains. /// /// The Rows object to get the metadata of + /// The cancellation token /// The ResultSetMetadata of the given Rows object - public Task MetadataAsync(Rows rows); + public Task MetadataAsync(Rows rows, CancellationToken cancellationToken = default); /// /// Returns the ResultSetStats of a Rows object. This object contains the update count of a DML statement that was @@ -164,8 +177,9 @@ public enum RowEncoding /// The Rows object to return data rows for /// The maximum number of rows to return /// The encoding that should be used for the data rows + /// The cancellation token /// A ListValue with the actual row data, or null if there are no more rows - public Task NextAsync(Rows rows, int numRows, RowEncoding encoding); + public Task NextAsync(Rows rows, int numRows, RowEncoding encoding, CancellationToken cancellationToken = default); /// /// Closes the given Rows object. This releases all resources associated with this statement result. @@ -173,6 +187,13 @@ public enum RowEncoding /// The Rows object to close public void CloseRows(Rows rows); + /// + /// Closes the given Rows object. This releases all resources associated with this statement result. + /// + /// The Rows object to close + /// The cancellation token + public Task CloseRowsAsync(Rows rows, CancellationToken cancellationToken = default) => Task.Run(() => CloseRows(rows), cancellationToken); + /// /// Starts a new transaction on this connection. A connection can have at most one transaction at any time. All /// transactions, including read-only transactions, must be either committed or rolled back. @@ -190,10 +211,30 @@ public enum RowEncoding /// The connection that has the transaction that should be committed /// The CommitResponse of the transaction, or null if it was a read-only transaction public CommitResponse? Commit(Connection connection); + + /// + /// Commits the current transaction on this connection. + /// + /// The connection that has the transaction that should be committed + /// The CommitResponse of the transaction, or null if it was a read-only transaction + /// The cancellation token + public Task CommitAsync(Connection connection, CancellationToken cancellationToken = default); /// /// Rollbacks the current transaction. /// /// The connection that has the transaction that should be rolled back public void Rollback(Connection connection); + + /// + /// Rollbacks the current transaction. + /// + /// The connection that has the transaction that should be rolled back + /// The cancellation token + public Task RollbackAsync(Connection connection, CancellationToken cancellationToken = default); + + void IDisposable.Dispose() + { + // no-op + } } \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Rows.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Rows.cs index 72178e6d..8e18b2da 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Rows.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/Rows.cs @@ -13,6 +13,7 @@ // limitations under the License. using System; +using System.Threading; using System.Threading.Tasks; using Google.Cloud.Spanner.V1; using Google.Protobuf.WellKnownTypes; @@ -29,14 +30,14 @@ public class Rows : AbstractLibObject private ResultSetMetadata? _metadata; - public ResultSetMetadata? Metadata => _metadata ??= Spanner.Metadata(this); + public virtual ResultSetMetadata? Metadata => _metadata ??= Spanner.Metadata(this); private readonly Lazy _stats; /// /// The ResultSetStats of the SQL statement. This is only available once all data rows have been read. /// - private ResultSetStats? Stats => _stats.Value; + protected virtual ResultSetStats? Stats => _stats.Value; /// /// The update count of the SQL statement. This is only available once all data rows have been read. @@ -76,7 +77,7 @@ public Rows(Connection connection, long id, bool initMetadata = true) : base(con /// Returns the next data row from this Rows object. /// /// The next data row or null if there are no more data - public ListValue? Next() + public virtual ListValue? Next() { var res = Spanner.Next(this, 1, ISpannerLib.RowEncoding.Proto); if (res == null && !_stats.IsValueCreated) @@ -91,9 +92,9 @@ public Rows(Connection connection, long id, bool initMetadata = true) : base(con /// Returns the next data row from this Rows object. /// /// The next data row or null if there are no more data - public async Task NextAsync() + public virtual async Task NextAsync(CancellationToken cancellationToken = default) { - return await Spanner.NextAsync(this, 1, ISpannerLib.RowEncoding.Proto); + return await Spanner.NextAsync(this, 1, ISpannerLib.RowEncoding.Proto, cancellationToken); } /// @@ -103,4 +104,10 @@ protected override void CloseLibObject() { Spanner.CloseRows(this); } + + protected override async ValueTask CloseLibObjectAsync() + { + await Spanner.CloseRowsAsync(this); + } + } diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/SpannerException.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/SpannerException.cs index 3acc98d5..bb87ddb3 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/SpannerException.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet/SpannerException.cs @@ -14,6 +14,8 @@ using System; using Google.Rpc; +using Grpc.Core; +using Status = Google.Rpc.Status; namespace Google.Cloud.SpannerLib; @@ -24,6 +26,11 @@ namespace Google.Cloud.SpannerLib; /// The status that was returned by SpannerLib public class SpannerException(Status status) : Exception(status.Message) { + public static SpannerException ToSpannerException(RpcException exception) + { + return new SpannerException(new Status { Code = (int) exception.Status.StatusCode, Message = exception.Message }); + } + public Status Status { get; } = status; public Code Code => (Code)Status.Code; diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/GrpcSpannerLibraryImpl.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/GrpcSpannerLibraryImpl.java index ca546179..705ccffe 100644 --- a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/GrpcSpannerLibraryImpl.java +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/GrpcSpannerLibraryImpl.java @@ -41,6 +41,9 @@ import io.grpc.ManagedChannel; import io.grpc.StatusException; import io.grpc.stub.BlockingClientCall; +import java.util.List; +import java.util.concurrent.ThreadLocalRandom; +import java.util.stream.Collectors; /** This implementation communicates with SpannerLib through a gRPC interface. */ public class GrpcSpannerLibraryImpl implements SpannerLibrary { @@ -48,10 +51,26 @@ public class GrpcSpannerLibraryImpl implements SpannerLibrary { private final SpannerLibBlockingV2Stub stub; private final boolean useStreamingRows; + private final List channels; + private final List stubs; + public GrpcSpannerLibraryImpl(Channel channel, boolean useStreamingRows) { this.channel = channel; this.stub = SpannerLibGrpc.newBlockingV2Stub(channel); this.useStreamingRows = useStreamingRows; + + this.channels = null; + this.stubs = null; + } + + public GrpcSpannerLibraryImpl(List channels) { + this.channel = channels.get(0); + this.stub = SpannerLibGrpc.newBlockingV2Stub(channels.get(0)); + this.useStreamingRows = true; + + this.channels = channels; + this.stubs = + channels.stream().map(SpannerLibGrpc::newBlockingV2Stub).collect(Collectors.toList()); } static SpannerLibException toSpannerLibException(StatusException exception) { @@ -86,6 +105,13 @@ private static com.google.cloud.spannerlib.v1.Rows toProto(Rows rows) { @Override public void close() { + if (this.channels != null) { + for (Channel channel : channels) { + if (channel instanceof ManagedChannel) { + ((ManagedChannel) channel).shutdown(); + } + } + } if (this.channel instanceof ManagedChannel) { ((ManagedChannel) this.channel).shutdown(); } @@ -207,6 +233,10 @@ public Rows execute(Connection connection, ExecuteSqlRequest request) { } private Rows executeStreaming(Connection connection, ExecuteSqlRequest request) { + SpannerLibBlockingV2Stub stub = this.stub; + if (stubs != null) { + stub = stubs.get(ThreadLocalRandom.current().nextInt(stubs.size())); + } BlockingClientCall stream = stub.executeStreaming( ExecuteRequest.newBuilder() diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequest.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequest.java new file mode 100644 index 00000000..787fa695 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequest.java @@ -0,0 +1,364 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: google/spannerlib/v1/spannerlib.proto +// Protobuf Java Version: 4.32.1 + +package com.google.cloud.spannerlib.v1; + +/** Protobuf type {@code google.spannerlib.v1.InfoRequest} */ +@com.google.protobuf.Generated +public final class InfoRequest extends com.google.protobuf.GeneratedMessage + implements + // @@protoc_insertion_point(message_implements:google.spannerlib.v1.InfoRequest) + InfoRequestOrBuilder { + private static final long serialVersionUID = 0L; + + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 32, + /* patch= */ 1, + /* suffix= */ "", + InfoRequest.class.getName()); + } + + // Use InfoRequest.newBuilder() to construct. + private InfoRequest(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + + private InfoRequest() {} + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.cloud.spannerlib.v1.InfoRequest.class, + com.google.cloud.spannerlib.v1.InfoRequest.Builder.class); + } + + private byte memoizedIsInitialized = -1; + + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.google.cloud.spannerlib.v1.InfoRequest)) { + return super.equals(obj); + } + com.google.cloud.spannerlib.v1.InfoRequest other = + (com.google.cloud.spannerlib.v1.InfoRequest) obj; + + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom(java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseDelimitedFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException( + PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.google.cloud.spannerlib.v1.InfoRequest prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** Protobuf type {@code google.spannerlib.v1.InfoRequest} */ + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder + implements + // @@protoc_insertion_point(builder_implements:google.spannerlib.v1.InfoRequest) + com.google.cloud.spannerlib.v1.InfoRequestOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoRequest_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoRequest_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.cloud.spannerlib.v1.InfoRequest.class, + com.google.cloud.spannerlib.v1.InfoRequest.Builder.class); + } + + // Construct using com.google.cloud.spannerlib.v1.InfoRequest.newBuilder() + private Builder() {} + + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + } + + @java.lang.Override + public Builder clear() { + super.clear(); + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoRequest_descriptor; + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoRequest getDefaultInstanceForType() { + return com.google.cloud.spannerlib.v1.InfoRequest.getDefaultInstance(); + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoRequest build() { + com.google.cloud.spannerlib.v1.InfoRequest result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoRequest buildPartial() { + com.google.cloud.spannerlib.v1.InfoRequest result = + new com.google.cloud.spannerlib.v1.InfoRequest(this); + onBuilt(); + return result; + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.cloud.spannerlib.v1.InfoRequest) { + return mergeFrom((com.google.cloud.spannerlib.v1.InfoRequest) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.cloud.spannerlib.v1.InfoRequest other) { + if (other == com.google.cloud.spannerlib.v1.InfoRequest.getDefaultInstance()) return this; + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: + { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + // @@protoc_insertion_point(builder_scope:google.spannerlib.v1.InfoRequest) + } + + // @@protoc_insertion_point(class_scope:google.spannerlib.v1.InfoRequest) + private static final com.google.cloud.spannerlib.v1.InfoRequest DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new com.google.cloud.spannerlib.v1.InfoRequest(); + } + + public static com.google.cloud.spannerlib.v1.InfoRequest getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public InfoRequest parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoRequest getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } +} diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequestOrBuilder.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequestOrBuilder.java new file mode 100644 index 00000000..40f8f103 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoRequestOrBuilder.java @@ -0,0 +1,12 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: google/spannerlib/v1/spannerlib.proto +// Protobuf Java Version: 4.32.1 + +package com.google.cloud.spannerlib.v1; + +@com.google.protobuf.Generated +public interface InfoRequestOrBuilder + extends + // @@protoc_insertion_point(interface_extends:google.spannerlib.v1.InfoRequest) + com.google.protobuf.MessageOrBuilder {} diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponse.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponse.java new file mode 100644 index 00000000..b7dc7f72 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponse.java @@ -0,0 +1,522 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: google/spannerlib/v1/spannerlib.proto +// Protobuf Java Version: 4.32.1 + +package com.google.cloud.spannerlib.v1; + +/** Protobuf type {@code google.spannerlib.v1.InfoResponse} */ +@com.google.protobuf.Generated +public final class InfoResponse extends com.google.protobuf.GeneratedMessage + implements + // @@protoc_insertion_point(message_implements:google.spannerlib.v1.InfoResponse) + InfoResponseOrBuilder { + private static final long serialVersionUID = 0L; + + static { + com.google.protobuf.RuntimeVersion.validateProtobufGencodeVersion( + com.google.protobuf.RuntimeVersion.RuntimeDomain.PUBLIC, + /* major= */ 4, + /* minor= */ 32, + /* patch= */ 1, + /* suffix= */ "", + InfoResponse.class.getName()); + } + + // Use InfoResponse.newBuilder() to construct. + private InfoResponse(com.google.protobuf.GeneratedMessage.Builder builder) { + super(builder); + } + + private InfoResponse() { + version_ = ""; + } + + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.cloud.spannerlib.v1.InfoResponse.class, + com.google.cloud.spannerlib.v1.InfoResponse.Builder.class); + } + + public static final int VERSION_FIELD_NUMBER = 1; + + @SuppressWarnings("serial") + private volatile java.lang.Object version_ = ""; + + /** + * string version = 1; + * + * @return The version. + */ + @java.lang.Override + public java.lang.String getVersion() { + java.lang.Object ref = version_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + version_ = s; + return s; + } + } + + /** + * string version = 1; + * + * @return The bytes for version. + */ + @java.lang.Override + public com.google.protobuf.ByteString getVersionBytes() { + java.lang.Object ref = version_; + if (ref instanceof java.lang.String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + version_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + private byte memoizedIsInitialized = -1; + + @java.lang.Override + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + memoizedIsInitialized = 1; + return true; + } + + @java.lang.Override + public void writeTo(com.google.protobuf.CodedOutputStream output) throws java.io.IOException { + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) { + com.google.protobuf.GeneratedMessage.writeString(output, 1, version_); + } + getUnknownFields().writeTo(output); + } + + @java.lang.Override + public int getSerializedSize() { + int size = memoizedSize; + if (size != -1) return size; + + size = 0; + if (!com.google.protobuf.GeneratedMessage.isStringEmpty(version_)) { + size += com.google.protobuf.GeneratedMessage.computeStringSize(1, version_); + } + size += getUnknownFields().getSerializedSize(); + memoizedSize = size; + return size; + } + + @java.lang.Override + public boolean equals(final java.lang.Object obj) { + if (obj == this) { + return true; + } + if (!(obj instanceof com.google.cloud.spannerlib.v1.InfoResponse)) { + return super.equals(obj); + } + com.google.cloud.spannerlib.v1.InfoResponse other = + (com.google.cloud.spannerlib.v1.InfoResponse) obj; + + if (!getVersion().equals(other.getVersion())) return false; + if (!getUnknownFields().equals(other.getUnknownFields())) return false; + return true; + } + + @java.lang.Override + public int hashCode() { + if (memoizedHashCode != 0) { + return memoizedHashCode; + } + int hash = 41; + hash = (19 * hash) + getDescriptor().hashCode(); + hash = (37 * hash) + VERSION_FIELD_NUMBER; + hash = (53 * hash) + getVersion().hashCode(); + hash = (29 * hash) + getUnknownFields().hashCode(); + memoizedHashCode = hash; + return hash; + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom(java.nio.ByteBuffer data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + java.nio.ByteBuffer data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + com.google.protobuf.ByteString data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + com.google.protobuf.ByteString data, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom(byte[] data) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + byte[] data, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom(java.io.InputStream input) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseDelimitedFrom( + java.io.InputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException(PARSER, input); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseDelimitedFrom( + java.io.InputStream input, com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseDelimitedWithIOException( + PARSER, input, extensionRegistry); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + com.google.protobuf.CodedInputStream input) throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException(PARSER, input); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse parseFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return com.google.protobuf.GeneratedMessage.parseWithIOException( + PARSER, input, extensionRegistry); + } + + @java.lang.Override + public Builder newBuilderForType() { + return newBuilder(); + } + + public static Builder newBuilder() { + return DEFAULT_INSTANCE.toBuilder(); + } + + public static Builder newBuilder(com.google.cloud.spannerlib.v1.InfoResponse prototype) { + return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype); + } + + @java.lang.Override + public Builder toBuilder() { + return this == DEFAULT_INSTANCE ? new Builder() : new Builder().mergeFrom(this); + } + + @java.lang.Override + protected Builder newBuilderForType(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + Builder builder = new Builder(parent); + return builder; + } + + /** Protobuf type {@code google.spannerlib.v1.InfoResponse} */ + public static final class Builder extends com.google.protobuf.GeneratedMessage.Builder + implements + // @@protoc_insertion_point(builder_implements:google.spannerlib.v1.InfoResponse) + com.google.cloud.spannerlib.v1.InfoResponseOrBuilder { + public static final com.google.protobuf.Descriptors.Descriptor getDescriptor() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoResponse_descriptor; + } + + @java.lang.Override + protected com.google.protobuf.GeneratedMessage.FieldAccessorTable + internalGetFieldAccessorTable() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoResponse_fieldAccessorTable + .ensureFieldAccessorsInitialized( + com.google.cloud.spannerlib.v1.InfoResponse.class, + com.google.cloud.spannerlib.v1.InfoResponse.Builder.class); + } + + // Construct using com.google.cloud.spannerlib.v1.InfoResponse.newBuilder() + private Builder() {} + + private Builder(com.google.protobuf.GeneratedMessage.BuilderParent parent) { + super(parent); + } + + @java.lang.Override + public Builder clear() { + super.clear(); + bitField0_ = 0; + version_ = ""; + return this; + } + + @java.lang.Override + public com.google.protobuf.Descriptors.Descriptor getDescriptorForType() { + return com.google.cloud.spannerlib.v1.SpannerLibProto + .internal_static_google_spannerlib_v1_InfoResponse_descriptor; + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoResponse getDefaultInstanceForType() { + return com.google.cloud.spannerlib.v1.InfoResponse.getDefaultInstance(); + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoResponse build() { + com.google.cloud.spannerlib.v1.InfoResponse result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoResponse buildPartial() { + com.google.cloud.spannerlib.v1.InfoResponse result = + new com.google.cloud.spannerlib.v1.InfoResponse(this); + if (bitField0_ != 0) { + buildPartial0(result); + } + onBuilt(); + return result; + } + + private void buildPartial0(com.google.cloud.spannerlib.v1.InfoResponse result) { + int from_bitField0_ = bitField0_; + if (((from_bitField0_ & 0x00000001) != 0)) { + result.version_ = version_; + } + } + + @java.lang.Override + public Builder mergeFrom(com.google.protobuf.Message other) { + if (other instanceof com.google.cloud.spannerlib.v1.InfoResponse) { + return mergeFrom((com.google.cloud.spannerlib.v1.InfoResponse) other); + } else { + super.mergeFrom(other); + return this; + } + } + + public Builder mergeFrom(com.google.cloud.spannerlib.v1.InfoResponse other) { + if (other == com.google.cloud.spannerlib.v1.InfoResponse.getDefaultInstance()) return this; + if (!other.getVersion().isEmpty()) { + version_ = other.version_; + bitField0_ |= 0x00000001; + onChanged(); + } + this.mergeUnknownFields(other.getUnknownFields()); + onChanged(); + return this; + } + + @java.lang.Override + public final boolean isInitialized() { + return true; + } + + @java.lang.Override + public Builder mergeFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + if (extensionRegistry == null) { + throw new java.lang.NullPointerException(); + } + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + case 10: + { + version_ = input.readStringRequireUtf8(); + bitField0_ |= 0x00000001; + break; + } // case 10 + default: + { + if (!super.parseUnknownField(input, extensionRegistry, tag)) { + done = true; // was an endgroup tag + } + break; + } // default: + } // switch (tag) + } // while (!done) + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.unwrapIOException(); + } finally { + onChanged(); + } // finally + return this; + } + + private int bitField0_; + + private java.lang.Object version_ = ""; + + /** + * string version = 1; + * + * @return The version. + */ + public java.lang.String getVersion() { + java.lang.Object ref = version_; + if (!(ref instanceof java.lang.String)) { + com.google.protobuf.ByteString bs = (com.google.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + version_ = s; + return s; + } else { + return (java.lang.String) ref; + } + } + + /** + * string version = 1; + * + * @return The bytes for version. + */ + public com.google.protobuf.ByteString getVersionBytes() { + java.lang.Object ref = version_; + if (ref instanceof String) { + com.google.protobuf.ByteString b = + com.google.protobuf.ByteString.copyFromUtf8((java.lang.String) ref); + version_ = b; + return b; + } else { + return (com.google.protobuf.ByteString) ref; + } + } + + /** + * string version = 1; + * + * @param value The version to set. + * @return This builder for chaining. + */ + public Builder setVersion(java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + version_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + /** + * string version = 1; + * + * @return This builder for chaining. + */ + public Builder clearVersion() { + version_ = getDefaultInstance().getVersion(); + bitField0_ = (bitField0_ & ~0x00000001); + onChanged(); + return this; + } + + /** + * string version = 1; + * + * @param value The bytes for version to set. + * @return This builder for chaining. + */ + public Builder setVersionBytes(com.google.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + checkByteStringIsUtf8(value); + version_ = value; + bitField0_ |= 0x00000001; + onChanged(); + return this; + } + + // @@protoc_insertion_point(builder_scope:google.spannerlib.v1.InfoResponse) + } + + // @@protoc_insertion_point(class_scope:google.spannerlib.v1.InfoResponse) + private static final com.google.cloud.spannerlib.v1.InfoResponse DEFAULT_INSTANCE; + + static { + DEFAULT_INSTANCE = new com.google.cloud.spannerlib.v1.InfoResponse(); + } + + public static com.google.cloud.spannerlib.v1.InfoResponse getDefaultInstance() { + return DEFAULT_INSTANCE; + } + + private static final com.google.protobuf.Parser PARSER = + new com.google.protobuf.AbstractParser() { + @java.lang.Override + public InfoResponse parsePartialFrom( + com.google.protobuf.CodedInputStream input, + com.google.protobuf.ExtensionRegistryLite extensionRegistry) + throws com.google.protobuf.InvalidProtocolBufferException { + Builder builder = newBuilder(); + try { + builder.mergeFrom(input, extensionRegistry); + } catch (com.google.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(builder.buildPartial()); + } catch (com.google.protobuf.UninitializedMessageException e) { + throw e.asInvalidProtocolBufferException().setUnfinishedMessage(builder.buildPartial()); + } catch (java.io.IOException e) { + throw new com.google.protobuf.InvalidProtocolBufferException(e) + .setUnfinishedMessage(builder.buildPartial()); + } + return builder.buildPartial(); + } + }; + + public static com.google.protobuf.Parser parser() { + return PARSER; + } + + @java.lang.Override + public com.google.protobuf.Parser getParserForType() { + return PARSER; + } + + @java.lang.Override + public com.google.cloud.spannerlib.v1.InfoResponse getDefaultInstanceForType() { + return DEFAULT_INSTANCE; + } +} diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponseOrBuilder.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponseOrBuilder.java new file mode 100644 index 00000000..c9698fbd --- /dev/null +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/InfoResponseOrBuilder.java @@ -0,0 +1,27 @@ +// Generated by the protocol buffer compiler. DO NOT EDIT! +// NO CHECKED-IN PROTOBUF GENCODE +// source: google/spannerlib/v1/spannerlib.proto +// Protobuf Java Version: 4.32.1 + +package com.google.cloud.spannerlib.v1; + +@com.google.protobuf.Generated +public interface InfoResponseOrBuilder + extends + // @@protoc_insertion_point(interface_extends:google.spannerlib.v1.InfoResponse) + com.google.protobuf.MessageOrBuilder { + + /** + * string version = 1; + * + * @return The version. + */ + java.lang.String getVersion(); + + /** + * string version = 1; + * + * @return The bytes for version. + */ + com.google.protobuf.ByteString getVersionBytes(); +} diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibGrpc.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibGrpc.java index 939d2530..643b7cf2 100644 --- a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibGrpc.java +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibGrpc.java @@ -11,6 +11,47 @@ private SpannerLibGrpc() {} public static final java.lang.String SERVICE_NAME = "google.spannerlib.v1.SpannerLib"; // Static method descriptors that strictly reflect the proto. + private static volatile io.grpc.MethodDescriptor< + com.google.cloud.spannerlib.v1.InfoRequest, com.google.cloud.spannerlib.v1.InfoResponse> + getInfoMethod; + + @io.grpc.stub.annotations.RpcMethod( + fullMethodName = SERVICE_NAME + '/' + "Info", + requestType = com.google.cloud.spannerlib.v1.InfoRequest.class, + responseType = com.google.cloud.spannerlib.v1.InfoResponse.class, + methodType = io.grpc.MethodDescriptor.MethodType.UNARY) + public static io.grpc.MethodDescriptor< + com.google.cloud.spannerlib.v1.InfoRequest, com.google.cloud.spannerlib.v1.InfoResponse> + getInfoMethod() { + io.grpc.MethodDescriptor< + com.google.cloud.spannerlib.v1.InfoRequest, com.google.cloud.spannerlib.v1.InfoResponse> + getInfoMethod; + if ((getInfoMethod = SpannerLibGrpc.getInfoMethod) == null) { + synchronized (SpannerLibGrpc.class) { + if ((getInfoMethod = SpannerLibGrpc.getInfoMethod) == null) { + SpannerLibGrpc.getInfoMethod = + getInfoMethod = + io.grpc.MethodDescriptor + . + newBuilder() + .setType(io.grpc.MethodDescriptor.MethodType.UNARY) + .setFullMethodName(generateFullMethodName(SERVICE_NAME, "Info")) + .setSampledToLocalTracing(true) + .setRequestMarshaller( + io.grpc.protobuf.ProtoUtils.marshaller( + com.google.cloud.spannerlib.v1.InfoRequest.getDefaultInstance())) + .setResponseMarshaller( + io.grpc.protobuf.ProtoUtils.marshaller( + com.google.cloud.spannerlib.v1.InfoResponse.getDefaultInstance())) + .setSchemaDescriptor(new SpannerLibMethodDescriptorSupplier("Info")) + .build(); + } + } + } + return getInfoMethod; + } + private static volatile io.grpc.MethodDescriptor< com.google.cloud.spannerlib.v1.CreatePoolRequest, com.google.cloud.spannerlib.v1.Pool> getCreatePoolMethod; @@ -735,6 +776,13 @@ public SpannerLibFutureStub newStub( /** */ public interface AsyncService { + /** */ + default void info( + com.google.cloud.spannerlib.v1.InfoRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ServerCalls.asyncUnimplementedUnaryCall(getInfoMethod(), responseObserver); + } + /** */ default void createPool( com.google.cloud.spannerlib.v1.CreatePoolRequest request, @@ -878,6 +926,14 @@ protected SpannerLibStub build(io.grpc.Channel channel, io.grpc.CallOptions call return new SpannerLibStub(channel, callOptions); } + /** */ + public void info( + com.google.cloud.spannerlib.v1.InfoRequest request, + io.grpc.stub.StreamObserver responseObserver) { + io.grpc.stub.ClientCalls.asyncUnaryCall( + getChannel().newCall(getInfoMethod(), getCallOptions()), request, responseObserver); + } + /** */ public void createPool( com.google.cloud.spannerlib.v1.CreatePoolRequest request, @@ -1036,6 +1092,13 @@ protected SpannerLibBlockingV2Stub build( return new SpannerLibBlockingV2Stub(channel, callOptions); } + /** */ + public com.google.cloud.spannerlib.v1.InfoResponse info( + com.google.cloud.spannerlib.v1.InfoRequest request) throws io.grpc.StatusException { + return io.grpc.stub.ClientCalls.blockingV2UnaryCall( + getChannel(), getInfoMethod(), getCallOptions(), request); + } + /** */ public com.google.cloud.spannerlib.v1.Pool createPool( com.google.cloud.spannerlib.v1.CreatePoolRequest request) throws io.grpc.StatusException { @@ -1169,6 +1232,13 @@ protected SpannerLibBlockingStub build( return new SpannerLibBlockingStub(channel, callOptions); } + /** */ + public com.google.cloud.spannerlib.v1.InfoResponse info( + com.google.cloud.spannerlib.v1.InfoRequest request) { + return io.grpc.stub.ClientCalls.blockingUnaryCall( + getChannel(), getInfoMethod(), getCallOptions(), request); + } + /** */ public com.google.cloud.spannerlib.v1.Pool createPool( com.google.cloud.spannerlib.v1.CreatePoolRequest request) { @@ -1283,6 +1353,14 @@ protected SpannerLibFutureStub build(io.grpc.Channel channel, io.grpc.CallOption return new SpannerLibFutureStub(channel, callOptions); } + /** */ + public com.google.common.util.concurrent.ListenableFuture< + com.google.cloud.spannerlib.v1.InfoResponse> + info(com.google.cloud.spannerlib.v1.InfoRequest request) { + return io.grpc.stub.ClientCalls.futureUnaryCall( + getChannel().newCall(getInfoMethod(), getCallOptions()), request); + } + /** */ public com.google.common.util.concurrent.ListenableFuture createPool(com.google.cloud.spannerlib.v1.CreatePoolRequest request) { @@ -1385,22 +1463,23 @@ public com.google.common.util.concurrent.ListenableFuture implements io.grpc.stub.ServerCalls.UnaryMethod, @@ -1419,6 +1498,12 @@ private static final class MethodHandlers @java.lang.SuppressWarnings("unchecked") public void invoke(Req request, io.grpc.stub.StreamObserver responseObserver) { switch (methodId) { + case METHODID_INFO: + serviceImpl.info( + (com.google.cloud.spannerlib.v1.InfoRequest) request, + (io.grpc.stub.StreamObserver) + responseObserver); + break; case METHODID_CREATE_POOL: serviceImpl.createPool( (com.google.cloud.spannerlib.v1.CreatePoolRequest) request, @@ -1522,6 +1607,12 @@ public io.grpc.stub.StreamObserver invoke( public static final io.grpc.ServerServiceDefinition bindService(AsyncService service) { return io.grpc.ServerServiceDefinition.builder(getServiceDescriptor()) + .addMethod( + getInfoMethod(), + io.grpc.stub.ServerCalls.asyncUnaryCall( + new MethodHandlers< + com.google.cloud.spannerlib.v1.InfoRequest, + com.google.cloud.spannerlib.v1.InfoResponse>(service, METHODID_INFO))) .addMethod( getCreatePoolMethod(), io.grpc.stub.ServerCalls.asyncUnaryCall( @@ -1670,6 +1761,7 @@ public static io.grpc.ServiceDescriptor getServiceDescriptor() { result = io.grpc.ServiceDescriptor.newBuilder(SERVICE_NAME) .setSchemaDescriptor(new SpannerLibFileDescriptorSupplier()) + .addMethod(getInfoMethod()) .addMethod(getCreatePoolMethod()) .addMethod(getClosePoolMethod()) .addMethod(getCreateConnectionMethod()) diff --git a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibProto.java b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibProto.java index a1e78d92..37ae2f12 100644 --- a/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibProto.java +++ b/spannerlib/wrappers/spannerlib-java/src/main/java/com/google/cloud/spannerlib/v1/SpannerLibProto.java @@ -25,6 +25,14 @@ public static void registerAllExtensions(com.google.protobuf.ExtensionRegistry r registerAllExtensions((com.google.protobuf.ExtensionRegistryLite) registry); } + static final com.google.protobuf.Descriptors.Descriptor + internal_static_google_spannerlib_v1_InfoRequest_descriptor; + static final com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_google_spannerlib_v1_InfoRequest_fieldAccessorTable; + static final com.google.protobuf.Descriptors.Descriptor + internal_static_google_spannerlib_v1_InfoResponse_descriptor; + static final com.google.protobuf.GeneratedMessage.FieldAccessorTable + internal_static_google_spannerlib_v1_InfoResponse_fieldAccessorTable; static final com.google.protobuf.Descriptors.Descriptor internal_static_google_spannerlib_v1_CreatePoolRequest_descriptor; static final com.google.protobuf.GeneratedMessage.FieldAccessorTable @@ -100,87 +108,91 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { + "oto\032\034google/protobuf/struct.proto\032\"googl" + "e/spanner/v1/result_set.proto\032\037google/sp" + "anner/v1/spanner.proto\032#google/spanner/v" - + "1/transaction.proto\"3\n\021CreatePoolRequest" - + "\022\036\n\021connection_string\030\001 \001(\tB\003\340A\002\"H\n\027Crea" - + "teConnectionRequest\022-\n\004pool\030\001 \001(\0132\032.goog" - + "le.spannerlib.v1.PoolB\003\340A\002\"\223\001\n\016ExecuteRe" - + "quest\0229\n\nconnection\030\001 \001(\0132 .google.spann" - + "erlib.v1.ConnectionB\003\340A\002\022F\n\023execute_sql_" - + "request\030\002 \001(\0132$.google.spanner.v1.Execut" - + "eSqlRequestB\003\340A\002\"\243\001\n\023ExecuteBatchRequest" - + "\0229\n\nconnection\030\001 \001(\0132 .google.spannerlib" - + ".v1.ConnectionB\003\340A\002\022Q\n\031execute_batch_dml" - + "_request\030\002 \001(\0132).google.spanner.v1.Execu" - + "teBatchDmlRequestB\003\340A\002\"\235\001\n\027BeginTransact" - + "ionRequest\0229\n\nconnection\030\001 \001(\0132 .google." - + "spannerlib.v1.ConnectionB\003\340A\002\022G\n\023transac" - + "tion_options\030\002 \001(\0132%.google.spanner.v1.T" - + "ransactionOptionsB\003\340A\002\"\236\001\n\025WriteMutation" - + "sRequest\0229\n\nconnection\030\001 \001(\0132 .google.sp" - + "annerlib.v1.ConnectionB\003\340A\002\022J\n\tmutations" - + "\030\002 \001(\01322.google.spanner.v1.BatchWriteReq" - + "uest.MutationGroupB\003\340A\002\"\027\n\004Pool\022\017\n\002id\030\001 " - + "\001(\003B\003\340A\002\"L\n\nConnection\022-\n\004pool\030\001 \001(\0132\032.g" - + "oogle.spannerlib.v1.PoolB\003\340A\002\022\017\n\002id\030\002 \001(" - + "\003B\003\340A\002\"R\n\004Rows\0229\n\nconnection\030\001 \001(\0132 .goo" - + "gle.spannerlib.v1.ConnectionB\003\340A\002\022\017\n\002id\030" - + "\002 \001(\003B\003\340A\002\"j\n\013NextRequest\022-\n\004rows\030\001 \001(\0132" - + "\032.google.spannerlib.v1.RowsB\003\340A\002\022\025\n\010num_" - + "rows\030\002 \001(\003B\003\340A\002\022\025\n\010encoding\030\003 \001(\003B\003\340A\002\"\321" - + "\001\n\007RowData\022-\n\004rows\030\001 \001(\0132\032.google.spanne" - + "rlib.v1.RowsB\003\340A\002\0226\n\010metadata\030\002 \001(\0132$.go" - + "ogle.spanner.v1.ResultSetMetadata\022-\n\004dat" - + "a\030\003 \003(\0132\032.google.protobuf.ListValueB\003\340A\002" - + "\0220\n\005stats\030\004 \001(\0132!.google.spanner.v1.Resu" - + "ltSetStats\"@\n\017MetadataRequest\022-\n\004rows\030\001 " - + "\001(\0132\032.google.spannerlib.v1.RowsB\003\340A\002\"F\n\025" - + "ResultSetStatsRequest\022-\n\004rows\030\001 \001(\0132\032.go" - + "ogle.spannerlib.v1.RowsB\003\340A\002\"e\n\027Connecti" - + "onStreamRequest\022?\n\017execute_request\030\001 \001(\013" - + "2$.google.spannerlib.v1.ExecuteRequestH\000" - + "B\t\n\007request\"Z\n\030ConnectionStreamResponse\022" - + "2\n\003row\030\001 \001(\0132#.google.spanner.v1.Partial" - + "ResultSetH\000B\n\n\010response2\361\n\n\nSpannerLib\022S" - + "\n\nCreatePool\022\'.google.spannerlib.v1.Crea" - + "tePoolRequest\032\032.google.spannerlib.v1.Poo" - + "l\"\000\022A\n\tClosePool\022\032.google.spannerlib.v1." - + "Pool\032\026.google.protobuf.Empty\"\000\022e\n\020Create" - + "Connection\022-.google.spannerlib.v1.Create" - + "ConnectionRequest\032 .google.spannerlib.v1" - + ".Connection\"\000\022M\n\017CloseConnection\022 .googl" - + "e.spannerlib.v1.Connection\032\026.google.prot" - + "obuf.Empty\"\000\022M\n\007Execute\022$.google.spanner" - + "lib.v1.ExecuteRequest\032\032.google.spannerli" - + "b.v1.Rows\"\000\022[\n\020ExecuteStreaming\022$.google" - + ".spannerlib.v1.ExecuteRequest\032\035.google.s" - + "pannerlib.v1.RowData\"\0000\001\022g\n\014ExecuteBatch" - + "\022).google.spannerlib.v1.ExecuteBatchRequ" - + "est\032*.google.spanner.v1.ExecuteBatchDmlR" - + "esponse\"\000\022N\n\010Metadata\022\032.google.spannerli" - + "b.v1.Rows\032$.google.spanner.v1.ResultSetM" - + "etadata\"\000\022G\n\004Next\022!.google.spannerlib.v1" - + ".NextRequest\032\032.google.protobuf.ListValue" - + "\"\000\022Q\n\016ResultSetStats\022\032.google.spannerlib" - + ".v1.Rows\032!.google.spanner.v1.ResultSetSt" - + "ats\"\000\022A\n\tCloseRows\022\032.google.spannerlib.v" - + "1.Rows\032\026.google.protobuf.Empty\"\000\022[\n\020Begi" - + "nTransaction\022-.google.spannerlib.v1.Begi" - + "nTransactionRequest\032\026.google.protobuf.Em" - + "pty\"\000\022O\n\006Commit\022 .google.spannerlib.v1.C" - + "onnection\032!.google.spanner.v1.CommitResp" - + "onse\"\000\022F\n\010Rollback\022 .google.spannerlib.v" - + "1.Connection\032\026.google.protobuf.Empty\"\000\022b" - + "\n\016WriteMutations\022+.google.spannerlib.v1." - + "WriteMutationsRequest\032!.google.spanner.v" - + "1.CommitResponse\"\000\022w\n\020ConnectionStream\022-" - + ".google.spannerlib.v1.ConnectionStreamRe" - + "quest\032..google.spannerlib.v1.ConnectionS" - + "treamResponse\"\000(\0010\001B\315\001\n\036com.google.cloud" - + ".spannerlib.v1B\017SpannerLibProtoP\001Z>cloud" - + ".google.com/go/spannerlib/apiv1/spannerl" - + "ibpb;spannerlibpb\252\002\032Google.Cloud.Spanner" - + "Lib.V1\312\002\032Google\\Cloud\\SpannerLib\\V1\352\002\035Go" - + "ogle::Cloud::SpannerLib::V1b\006proto3" + + "1/transaction.proto\"\r\n\013InfoRequest\"\037\n\014In" + + "foResponse\022\017\n\007version\030\001 \001(\t\"3\n\021CreatePoo" + + "lRequest\022\036\n\021connection_string\030\001 \001(\tB\003\340A\002" + + "\"H\n\027CreateConnectionRequest\022-\n\004pool\030\001 \001(" + + "\0132\032.google.spannerlib.v1.PoolB\003\340A\002\"\223\001\n\016E" + + "xecuteRequest\0229\n\nconnection\030\001 \001(\0132 .goog" + + "le.spannerlib.v1.ConnectionB\003\340A\002\022F\n\023exec" + + "ute_sql_request\030\002 \001(\0132$.google.spanner.v" + + "1.ExecuteSqlRequestB\003\340A\002\"\243\001\n\023ExecuteBatc" + + "hRequest\0229\n\nconnection\030\001 \001(\0132 .google.sp" + + "annerlib.v1.ConnectionB\003\340A\002\022Q\n\031execute_b" + + "atch_dml_request\030\002 \001(\0132).google.spanner." + + "v1.ExecuteBatchDmlRequestB\003\340A\002\"\235\001\n\027Begin" + + "TransactionRequest\0229\n\nconnection\030\001 \001(\0132 " + + ".google.spannerlib.v1.ConnectionB\003\340A\002\022G\n" + + "\023transaction_options\030\002 \001(\0132%.google.span" + + "ner.v1.TransactionOptionsB\003\340A\002\"\236\001\n\025Write" + + "MutationsRequest\0229\n\nconnection\030\001 \001(\0132 .g" + + "oogle.spannerlib.v1.ConnectionB\003\340A\002\022J\n\tm" + + "utations\030\002 \001(\01322.google.spanner.v1.Batch" + + "WriteRequest.MutationGroupB\003\340A\002\"\027\n\004Pool\022" + + "\017\n\002id\030\001 \001(\003B\003\340A\002\"L\n\nConnection\022-\n\004pool\030\001" + + " \001(\0132\032.google.spannerlib.v1.PoolB\003\340A\002\022\017\n" + + "\002id\030\002 \001(\003B\003\340A\002\"R\n\004Rows\0229\n\nconnection\030\001 \001" + + "(\0132 .google.spannerlib.v1.ConnectionB\003\340A" + + "\002\022\017\n\002id\030\002 \001(\003B\003\340A\002\"j\n\013NextRequest\022-\n\004row" + + "s\030\001 \001(\0132\032.google.spannerlib.v1.RowsB\003\340A\002" + + "\022\025\n\010num_rows\030\002 \001(\003B\003\340A\002\022\025\n\010encoding\030\003 \001(" + + "\003B\003\340A\002\"\321\001\n\007RowData\022-\n\004rows\030\001 \001(\0132\032.googl" + + "e.spannerlib.v1.RowsB\003\340A\002\0226\n\010metadata\030\002 " + + "\001(\0132$.google.spanner.v1.ResultSetMetadat" + + "a\022-\n\004data\030\003 \003(\0132\032.google.protobuf.ListVa" + + "lueB\003\340A\002\0220\n\005stats\030\004 \001(\0132!.google.spanner" + + ".v1.ResultSetStats\"@\n\017MetadataRequest\022-\n" + + "\004rows\030\001 \001(\0132\032.google.spannerlib.v1.RowsB" + + "\003\340A\002\"F\n\025ResultSetStatsRequest\022-\n\004rows\030\001 " + + "\001(\0132\032.google.spannerlib.v1.RowsB\003\340A\002\"e\n\027" + + "ConnectionStreamRequest\022?\n\017execute_reque" + + "st\030\001 \001(\0132$.google.spannerlib.v1.ExecuteR" + + "equestH\000B\t\n\007request\"Z\n\030ConnectionStreamR" + + "esponse\0222\n\003row\030\001 \001(\0132#.google.spanner.v1" + + ".PartialResultSetH\000B\n\n\010response2\302\013\n\nSpan" + + "nerLib\022O\n\004Info\022!.google.spannerlib.v1.In" + + "foRequest\032\".google.spannerlib.v1.InfoRes" + + "ponse\"\000\022S\n\nCreatePool\022\'.google.spannerli" + + "b.v1.CreatePoolRequest\032\032.google.spannerl" + + "ib.v1.Pool\"\000\022A\n\tClosePool\022\032.google.spann" + + "erlib.v1.Pool\032\026.google.protobuf.Empty\"\000\022" + + "e\n\020CreateConnection\022-.google.spannerlib." + + "v1.CreateConnectionRequest\032 .google.span" + + "nerlib.v1.Connection\"\000\022M\n\017CloseConnectio" + + "n\022 .google.spannerlib.v1.Connection\032\026.go" + + "ogle.protobuf.Empty\"\000\022M\n\007Execute\022$.googl" + + "e.spannerlib.v1.ExecuteRequest\032\032.google." + + "spannerlib.v1.Rows\"\000\022[\n\020ExecuteStreaming" + + "\022$.google.spannerlib.v1.ExecuteRequest\032\035" + + ".google.spannerlib.v1.RowData\"\0000\001\022g\n\014Exe" + + "cuteBatch\022).google.spannerlib.v1.Execute" + + "BatchRequest\032*.google.spanner.v1.Execute" + + "BatchDmlResponse\"\000\022N\n\010Metadata\022\032.google." + + "spannerlib.v1.Rows\032$.google.spanner.v1.R" + + "esultSetMetadata\"\000\022G\n\004Next\022!.google.span" + + "nerlib.v1.NextRequest\032\032.google.protobuf." + + "ListValue\"\000\022Q\n\016ResultSetStats\022\032.google.s" + + "pannerlib.v1.Rows\032!.google.spanner.v1.Re" + + "sultSetStats\"\000\022A\n\tCloseRows\022\032.google.spa" + + "nnerlib.v1.Rows\032\026.google.protobuf.Empty\"" + + "\000\022[\n\020BeginTransaction\022-.google.spannerli" + + "b.v1.BeginTransactionRequest\032\026.google.pr" + + "otobuf.Empty\"\000\022O\n\006Commit\022 .google.spanne" + + "rlib.v1.Connection\032!.google.spanner.v1.C" + + "ommitResponse\"\000\022F\n\010Rollback\022 .google.spa" + + "nnerlib.v1.Connection\032\026.google.protobuf." + + "Empty\"\000\022b\n\016WriteMutations\022+.google.spann" + + "erlib.v1.WriteMutationsRequest\032!.google." + + "spanner.v1.CommitResponse\"\000\022w\n\020Connectio" + + "nStream\022-.google.spannerlib.v1.Connectio" + + "nStreamRequest\032..google.spannerlib.v1.Co" + + "nnectionStreamResponse\"\000(\0010\001B\315\001\n\036com.goo" + + "gle.cloud.spannerlib.v1B\017SpannerLibProto" + + "P\001Z>cloud.google.com/go/spannerlib/apiv1" + + "/spannerlibpb;spannerlibpb\252\002\032Google.Clou" + + "d.SpannerLib.V1\312\002\032Google\\Cloud\\SpannerLi" + + "b\\V1\352\002\035Google::Cloud::SpannerLib::V1b\006pr" + + "oto3" }; descriptor = com.google.protobuf.Descriptors.FileDescriptor.internalBuildGeneratedFileFrom( @@ -193,8 +205,21 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { com.google.spanner.v1.SpannerProto.getDescriptor(), com.google.spanner.v1.TransactionProto.getDescriptor(), }); - internal_static_google_spannerlib_v1_CreatePoolRequest_descriptor = + internal_static_google_spannerlib_v1_InfoRequest_descriptor = getDescriptor().getMessageTypes().get(0); + internal_static_google_spannerlib_v1_InfoRequest_fieldAccessorTable = + new com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_google_spannerlib_v1_InfoRequest_descriptor, new java.lang.String[] {}); + internal_static_google_spannerlib_v1_InfoResponse_descriptor = + getDescriptor().getMessageTypes().get(1); + internal_static_google_spannerlib_v1_InfoResponse_fieldAccessorTable = + new com.google.protobuf.GeneratedMessage.FieldAccessorTable( + internal_static_google_spannerlib_v1_InfoResponse_descriptor, + new java.lang.String[] { + "Version", + }); + internal_static_google_spannerlib_v1_CreatePoolRequest_descriptor = + getDescriptor().getMessageTypes().get(2); internal_static_google_spannerlib_v1_CreatePoolRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_CreatePoolRequest_descriptor, @@ -202,7 +227,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "ConnectionString", }); internal_static_google_spannerlib_v1_CreateConnectionRequest_descriptor = - getDescriptor().getMessageTypes().get(1); + getDescriptor().getMessageTypes().get(3); internal_static_google_spannerlib_v1_CreateConnectionRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_CreateConnectionRequest_descriptor, @@ -210,7 +235,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Pool", }); internal_static_google_spannerlib_v1_ExecuteRequest_descriptor = - getDescriptor().getMessageTypes().get(2); + getDescriptor().getMessageTypes().get(4); internal_static_google_spannerlib_v1_ExecuteRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_ExecuteRequest_descriptor, @@ -218,7 +243,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Connection", "ExecuteSqlRequest", }); internal_static_google_spannerlib_v1_ExecuteBatchRequest_descriptor = - getDescriptor().getMessageTypes().get(3); + getDescriptor().getMessageTypes().get(5); internal_static_google_spannerlib_v1_ExecuteBatchRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_ExecuteBatchRequest_descriptor, @@ -226,7 +251,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Connection", "ExecuteBatchDmlRequest", }); internal_static_google_spannerlib_v1_BeginTransactionRequest_descriptor = - getDescriptor().getMessageTypes().get(4); + getDescriptor().getMessageTypes().get(6); internal_static_google_spannerlib_v1_BeginTransactionRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_BeginTransactionRequest_descriptor, @@ -234,14 +259,14 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Connection", "TransactionOptions", }); internal_static_google_spannerlib_v1_WriteMutationsRequest_descriptor = - getDescriptor().getMessageTypes().get(5); + getDescriptor().getMessageTypes().get(7); internal_static_google_spannerlib_v1_WriteMutationsRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_WriteMutationsRequest_descriptor, new java.lang.String[] { "Connection", "Mutations", }); - internal_static_google_spannerlib_v1_Pool_descriptor = getDescriptor().getMessageTypes().get(6); + internal_static_google_spannerlib_v1_Pool_descriptor = getDescriptor().getMessageTypes().get(8); internal_static_google_spannerlib_v1_Pool_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_Pool_descriptor, @@ -249,14 +274,15 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Id", }); internal_static_google_spannerlib_v1_Connection_descriptor = - getDescriptor().getMessageTypes().get(7); + getDescriptor().getMessageTypes().get(9); internal_static_google_spannerlib_v1_Connection_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_Connection_descriptor, new java.lang.String[] { "Pool", "Id", }); - internal_static_google_spannerlib_v1_Rows_descriptor = getDescriptor().getMessageTypes().get(8); + internal_static_google_spannerlib_v1_Rows_descriptor = + getDescriptor().getMessageTypes().get(10); internal_static_google_spannerlib_v1_Rows_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_Rows_descriptor, @@ -264,7 +290,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Connection", "Id", }); internal_static_google_spannerlib_v1_NextRequest_descriptor = - getDescriptor().getMessageTypes().get(9); + getDescriptor().getMessageTypes().get(11); internal_static_google_spannerlib_v1_NextRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_NextRequest_descriptor, @@ -272,7 +298,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Rows", "NumRows", "Encoding", }); internal_static_google_spannerlib_v1_RowData_descriptor = - getDescriptor().getMessageTypes().get(10); + getDescriptor().getMessageTypes().get(12); internal_static_google_spannerlib_v1_RowData_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_RowData_descriptor, @@ -280,7 +306,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Rows", "Metadata", "Data", "Stats", }); internal_static_google_spannerlib_v1_MetadataRequest_descriptor = - getDescriptor().getMessageTypes().get(11); + getDescriptor().getMessageTypes().get(13); internal_static_google_spannerlib_v1_MetadataRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_MetadataRequest_descriptor, @@ -288,7 +314,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Rows", }); internal_static_google_spannerlib_v1_ResultSetStatsRequest_descriptor = - getDescriptor().getMessageTypes().get(12); + getDescriptor().getMessageTypes().get(14); internal_static_google_spannerlib_v1_ResultSetStatsRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_ResultSetStatsRequest_descriptor, @@ -296,7 +322,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "Rows", }); internal_static_google_spannerlib_v1_ConnectionStreamRequest_descriptor = - getDescriptor().getMessageTypes().get(13); + getDescriptor().getMessageTypes().get(15); internal_static_google_spannerlib_v1_ConnectionStreamRequest_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_ConnectionStreamRequest_descriptor, @@ -304,7 +330,7 @@ public static com.google.protobuf.Descriptors.FileDescriptor getDescriptor() { "ExecuteRequest", "Request", }); internal_static_google_spannerlib_v1_ConnectionStreamResponse_descriptor = - getDescriptor().getMessageTypes().get(14); + getDescriptor().getMessageTypes().get(16); internal_static_google_spannerlib_v1_ConnectionStreamResponse_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_google_spannerlib_v1_ConnectionStreamResponse_descriptor, diff --git a/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/AbstractSpannerLibTest.java b/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/AbstractSpannerLibTest.java index 712bc36d..4ecea7b3 100644 --- a/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/AbstractSpannerLibTest.java +++ b/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/AbstractSpannerLibTest.java @@ -18,9 +18,11 @@ import com.google.cloud.spanner.connection.AbstractMockServerTest; import com.google.common.collect.ImmutableList; -import io.grpc.ManagedChannel; +import io.grpc.Channel; import io.grpc.ManagedChannelBuilder; +import java.util.ArrayList; import java.util.Collection; +import java.util.List; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; @@ -81,9 +83,16 @@ public void maybeCreateLibrary() throws Exception { private SpannerLibrary createLibrary() { if (libraryType == PoolTest.LibraryType.GRPC) { - ManagedChannel channel = - ManagedChannelBuilder.forTarget(grpcServerAddress).usePlaintext().build(); - return new GrpcSpannerLibraryImpl(channel, true); + int numChannels = 20; + List channels = new ArrayList<>(numChannels); + for (int i = 0; i < numChannels; i++) { + channels.add(ManagedChannelBuilder.forTarget(grpcServerAddress).usePlaintext().build()); + } + return new GrpcSpannerLibraryImpl(channels); + + // ManagedChannel channel = + // ManagedChannelBuilder.forTarget(grpcServerAddress).usePlaintext().build(); + // return new GrpcSpannerLibraryImpl(channel, true); } else if (libraryType == PoolTest.LibraryType.SHARED) { return NativeSpannerLibraryImpl.getInstance(); } else { diff --git a/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/BenchmarkTest.java b/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/BenchmarkTest.java new file mode 100644 index 00000000..60d29aeb --- /dev/null +++ b/spannerlib/wrappers/spannerlib-java/src/test/java/com/google/cloud/spannerlib/BenchmarkTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.cloud.spannerlib; + +import static org.junit.Assert.assertEquals; + +import com.google.common.base.Stopwatch; +import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.ListenableFuture; +import com.google.common.util.concurrent.ListeningExecutorService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.protobuf.ListValue; +import com.google.protobuf.Struct; +import com.google.protobuf.Value; +import com.google.spanner.v1.ExecuteSqlRequest; +import java.time.Duration; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadLocalRandom; +import org.junit.Ignore; +import org.junit.Test; + +public class BenchmarkTest extends AbstractSpannerLibTest { + static class Stats { + public final Duration min; + public final Duration p50; + public final Duration p90; + public final Duration p95; + public final Duration p99; + public final Duration max; + public final Duration avg; + + public Stats( + Duration min, + Duration p50, + Duration p90, + Duration p95, + Duration p99, + Duration max, + Duration avg) { + this.min = min; + this.p50 = p50; + this.p90 = p90; + this.p95 = p95; + this.p99 = p99; + this.max = max; + this.avg = avg; + } + + @Override + public String toString() { + return String.format( + "Min: %s\n" + + "P50: %s\n" + + "P90: %s\n" + + "P95: %s\n" + + "P99: %s\n" + + "Max: %s\n" + + "Avg: %s\n", + min, p50, p90, p95, p99, max, avg); + } + } + + @Test + @Ignore("For local testing") + public void testBenchmarkRealSpanner() throws Exception { + try (Pool pool = + Pool.createPool( + library, + "projects/appdev-soda-spanner-staging/instances/knut-test-ycsb/databases/knut-test-db")) { + Duration warmupDuration = readRandomRows(pool, 10); + System.out.printf("Warmup duration: %s%n", warmupDuration); + + for (int i = 0; i < 10; i++) { + int numRows = (i + 1) * 10; + Duration duration = readRandomRows(pool, numRows); + System.out.printf("Duration (%d): %s%n", numRows, duration); + } + + int numThreads = 100; + int numTasks = 200; + ListeningExecutorService executor = + MoreExecutors.listeningDecorator(Executors.newCachedThreadPool()); + List> futures = new ArrayList<>(numTasks); + for (int i = 0; i < numTasks; i++) { + futures.add(executor.submit(() -> readRandomRows(pool, 10))); + } + Futures.allAsList(futures).get(); + Stats stats = calculateStats(new ArrayList<>(Futures.allAsList(futures).get())); + System.out.println(); + System.out.printf("Num tasks: %d\n", numTasks); + System.out.println(stats); + } + } + + private static Stats calculateStats(List durations) { + durations.sort(Duration::compareTo); + return new Stats( + durations.get(0), + durations.get(durations.size() * 50 / 100), + durations.get(durations.size() * 90 / 100), + durations.get(durations.size() * 95 / 100), + durations.get(durations.size() * 99 / 100), + durations.get(durations.size() - 1), + Duration.ofNanos( + (long) durations.stream().mapToLong(Duration::toNanos).average().orElse(0.0d))); + } + + private static Duration readRandomRows(Pool pool, int maxRows) { + HashSet set = new HashSet(); + ListValue.Builder builder = ListValue.newBuilder(); + for (int c = 0; c < maxRows; c++) { + int id = ThreadLocalRandom.current().nextInt(1, 1_000_001); + set.add(id); + builder.addValues(Value.newBuilder().setStringValue(String.valueOf(id)).build()); + } + try (Connection connection = pool.createConnection()) { + Stopwatch stopwatch = Stopwatch.createStarted(); + ExecuteSqlRequest request = + ExecuteSqlRequest.newBuilder() + .setSql("select * from all_types where col_bigint = any($1)") + .setParams( + Struct.newBuilder() + .putFields("p1", Value.newBuilder().setListValue(builder.build()).build()) + .build()) + .build(); + int count = 0; + try (Rows rows = connection.execute(request)) { + ListValue row; + while ((row = rows.next()) != null) { + assertEquals(10, row.getValuesList().size()); + count++; + } + assertEquals(set.size(), count); + } + return stopwatch.elapsed(); + } + } +} From 98f24298fe58ef31ddf8a35923912e998e4d133b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Sun, 5 Oct 2025 06:36:28 +0100 Subject: [PATCH 07/15] fix: update dependency net.java.dev.jna:jna to v5.18.1 (#544) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR contains the following updates: | Package | Change | Age | Confidence | |---|---|---|---| | [net.java.dev.jna:jna](https://redirect.github.com/java-native-access/jna) | `5.18.0` -> `5.18.1` | [![age](https://developer.mend.io/api/mc/badges/age/maven/net.java.dev.jna:jna/5.18.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | [![confidence](https://developer.mend.io/api/mc/badges/confidence/maven/net.java.dev.jna:jna/5.18.0/5.18.1?slim=true)](https://docs.renovatebot.com/merge-confidence/) | --- ### Release Notes
java-native-access/jna (net.java.dev.jna:jna) ### [`v5.18.1`](https://redirect.github.com/java-native-access/jna/blob/HEAD/CHANGES.md#Release-5181) [Compare Source](https://redirect.github.com/java-native-access/jna/compare/5.18.0...5.18.1) \============== ## Bug Fixes - [#​1686](https://redirect.github.com/java-native-access/jna/issues/1686): Fix `sortFields` race condition while getting fields - [@​bendk](https://redirect.github.com/bendk).
--- ### Configuration 📅 **Schedule**: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC), Automerge - At any time (no schedule defined). 🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied. ♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox. 🔕 **Ignore**: Close this PR and you won't be reminded about this update again. --- - [ ] If you want to rebase/retry this PR, check this box --- This PR was generated by [Mend Renovate](https://mend.io/renovate/). View the [repository job log](https://developer.mend.io/github/googleapis/go-sql-spanner). --- spannerlib/wrappers/spannerlib-java/pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spannerlib/wrappers/spannerlib-java/pom.xml b/spannerlib/wrappers/spannerlib-java/pom.xml index 098402d0..eaa50031 100644 --- a/spannerlib/wrappers/spannerlib-java/pom.xml +++ b/spannerlib/wrappers/spannerlib-java/pom.xml @@ -39,7 +39,7 @@ net.java.dev.jna jna - 5.18.0 + 5.18.1 From 002d386b88d031ad4c8e8cb98153678ad5a74cba Mon Sep 17 00:00:00 2001 From: Marco Pracucci Date: Mon, 6 Oct 2025 12:32:56 +0200 Subject: [PATCH 08/15] feat: add authority param support to DSN (#546) Signed-off-by: Marco Pracucci --- connection_properties.go | 11 +++++++++++ driver.go | 8 ++++++++ 2 files changed, 19 insertions(+) diff --git a/connection_properties.go b/connection_properties.go index be6716b7..ad1bdff1 100644 --- a/connection_properties.go +++ b/connection_properties.go @@ -286,6 +286,17 @@ var propertyEndpoint = createConnectionProperty( connectionstate.ContextStartup, connectionstate.ConvertString, ) +var propertyAuthority = createConnectionProperty( + "authority", + "The expected server name in the TLS handshake. By default, the endpoint hostname is used. This option "+ + "is useful when connecting to Spanner via Google Private Connect or other custom endpoints where the "+ + "endpoint hostname does not match the server’s TLS certificate.", + "", + false, + nil, + connectionstate.ContextStartup, + connectionstate.ConvertString, +) var propertyCredentials = createConnectionProperty( "credentials", "The location of the credentials file to use for this connection. If neither this property or encoded "+ diff --git a/driver.go b/driver.go index 735b5e51..59945602 100644 --- a/driver.go +++ b/driver.go @@ -372,6 +372,10 @@ type ConnectorConfig struct { // Leave this empty to use the standard Spanner API endpoint. Host string + // The expected server name in the TLS handshake. + // Leave this empty to use the endpoint hostname. + Authority string + // Project, Instance, and Database identify the database that the connector // should create connections for. Project string @@ -568,6 +572,10 @@ func createConnector(d *Driver, connectorConfig ConnectorConfig) (*connector, er if connectorConfig.Host != "" { opts = append(opts, option.WithEndpoint(connectorConfig.Host)) } + assignPropertyValueIfExists(state, propertyAuthority, &connectorConfig.Authority) + if connectorConfig.Authority != "" { + opts = append(opts, option.WithGRPCDialOption(grpc.WithAuthority(connectorConfig.Authority))) + } if val := propertyCredentials.GetValueOrDefault(state); val != "" { opts = append(opts, option.WithCredentialsFile(val)) } From fba2986be9416ba761285645644d9a5a8eb7180b Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 6 Oct 2025 17:04:01 +0100 Subject: [PATCH 09/15] fix: update all dependencies (#542) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix: update all dependencies * chore: go mod tidy * build: add ByteBuddy for Java wrapper --------- Co-authored-by: Knut Olav Løite --- benchmarks/go.mod | 24 +++++----- benchmarks/go.sum | 48 +++++++++---------- examples/go.mod | 24 +++++----- examples/go.sum | 52 ++++++++++----------- go.mod | 24 +++++----- go.sum | 48 +++++++++---------- snippets/go.mod | 24 +++++----- snippets/go.sum | 52 ++++++++++----------- spannerlib/go.mod | 24 +++++----- spannerlib/go.sum | 48 +++++++++---------- spannerlib/wrappers/spannerlib-java/pom.xml | 19 ++++++-- 11 files changed, 200 insertions(+), 187 deletions(-) diff --git a/benchmarks/go.mod b/benchmarks/go.mod index 5ce60736..78dcf556 100644 --- a/benchmarks/go.mod +++ b/benchmarks/go.mod @@ -8,19 +8,19 @@ replace github.com/googleapis/go-sql-spanner => ../ require ( cloud.google.com/go v0.123.0 - cloud.google.com/go/spanner v1.85.1 + cloud.google.com/go/spanner v1.86.0 github.com/google/uuid v1.6.0 github.com/googleapis/go-sql-spanner v1.18.1 - google.golang.org/api v0.249.0 + google.golang.org/api v0.251.0 google.golang.org/grpc v1.75.1 - google.golang.org/protobuf v1.36.9 + google.golang.org/protobuf v1.36.10 ) require ( cel.dev/expr v0.24.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.8.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/longrunning v0.6.7 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect @@ -52,14 +52,14 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/net v0.44.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/time v0.13.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect ) diff --git a/benchmarks/go.sum b/benchmarks/go.sum index c8f84b25..37cdcdc0 100644 --- a/benchmarks/go.sum +++ b/benchmarks/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= -cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -526,8 +526,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+ cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.85.1 h1:cJx1ZD//C2QIfFQl8hSTn4twL8amAXtnayyflRIjj40= -cloud.google.com/go/spanner v1.85.1/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= +cloud.google.com/go/spanner v1.86.0 h1:jlNWusBol1Jxa9PmYGknUBzLwvD1cebuEenzqebZ9xs= +cloud.google.com/go/spanner v1.86.0/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -955,8 +955,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1071,8 +1071,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1102,8 +1102,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1120,8 +1120,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1199,8 +1199,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1225,16 +1225,16 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1371,8 +1371,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w= -google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ= +google.golang.org/api v0.251.0 h1:6lea5nHRT8RUmpy9kkC2PJYnhnDAB13LqrLSVQlMIE8= +google.golang.org/api v0.251.0/go.mod h1:Rwy0lPf/TD7+T2VhYcffCHhyyInyuxGjICxdfLqT7KI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1579,8 +1579,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/examples/go.mod b/examples/go.mod index b44c738f..c5ed264a 100644 --- a/examples/go.mod +++ b/examples/go.mod @@ -8,19 +8,19 @@ replace github.com/googleapis/go-sql-spanner => ../ require ( cloud.google.com/go v0.123.0 - cloud.google.com/go/spanner v1.85.1 + cloud.google.com/go/spanner v1.86.0 github.com/docker/docker v28.3.3+incompatible github.com/docker/go-connections v0.5.0 github.com/googleapis/go-sql-spanner v1.16.2 github.com/testcontainers/testcontainers-go v0.38.0 - google.golang.org/api v0.249.0 + google.golang.org/api v0.251.0 ) require ( cel.dev/expr v0.24.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.8.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/longrunning v0.6.7 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect @@ -91,17 +91,17 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/net v0.44.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/time v0.13.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/examples/go.sum b/examples/go.sum index f5e3c65d..f6ba2e7b 100644 --- a/examples/go.sum +++ b/examples/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= -cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -526,8 +526,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+ cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.85.1 h1:cJx1ZD//C2QIfFQl8hSTn4twL8amAXtnayyflRIjj40= -cloud.google.com/go/spanner v1.85.1/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= +cloud.google.com/go/spanner v1.86.0 h1:jlNWusBol1Jxa9PmYGknUBzLwvD1cebuEenzqebZ9xs= +cloud.google.com/go/spanner v1.86.0/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -1052,8 +1052,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1168,8 +1168,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1199,8 +1199,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1217,8 +1217,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1300,8 +1300,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1310,8 +1310,8 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1328,16 +1328,16 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1476,8 +1476,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w= -google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ= +google.golang.org/api v0.251.0 h1:6lea5nHRT8RUmpy9kkC2PJYnhnDAB13LqrLSVQlMIE8= +google.golang.org/api v0.251.0/go.mod h1:Rwy0lPf/TD7+T2VhYcffCHhyyInyuxGjICxdfLqT7KI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1621,8 +1621,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1684,8 +1684,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/go.mod b/go.mod index 64d30a41..3311c949 100644 --- a/go.mod +++ b/go.mod @@ -7,23 +7,23 @@ toolchain go1.25.1 require ( cloud.google.com/go v0.123.0 cloud.google.com/go/longrunning v0.6.7 - cloud.google.com/go/spanner v1.85.1 + cloud.google.com/go/spanner v1.86.0 github.com/golang/protobuf v1.5.4 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 github.com/googleapis/gax-go/v2 v2.15.0 github.com/hashicorp/golang-lru/v2 v2.0.7 - google.golang.org/api v0.249.0 - google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 + google.golang.org/api v0.251.0 + google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 google.golang.org/grpc v1.75.1 - google.golang.org/protobuf v1.36.9 + google.golang.org/protobuf v1.36.10 ) require ( cel.dev/expr v0.24.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.8.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 // indirect @@ -52,13 +52,13 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/net v0.44.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/time v0.13.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect ) diff --git a/go.sum b/go.sum index c8f84b25..37cdcdc0 100644 --- a/go.sum +++ b/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= -cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -526,8 +526,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+ cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.85.1 h1:cJx1ZD//C2QIfFQl8hSTn4twL8amAXtnayyflRIjj40= -cloud.google.com/go/spanner v1.85.1/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= +cloud.google.com/go/spanner v1.86.0 h1:jlNWusBol1Jxa9PmYGknUBzLwvD1cebuEenzqebZ9xs= +cloud.google.com/go/spanner v1.86.0/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -955,8 +955,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1071,8 +1071,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1102,8 +1102,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1120,8 +1120,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1199,8 +1199,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1225,16 +1225,16 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1371,8 +1371,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w= -google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ= +google.golang.org/api v0.251.0 h1:6lea5nHRT8RUmpy9kkC2PJYnhnDAB13LqrLSVQlMIE8= +google.golang.org/api v0.251.0/go.mod h1:Rwy0lPf/TD7+T2VhYcffCHhyyInyuxGjICxdfLqT7KI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1579,8 +1579,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/snippets/go.mod b/snippets/go.mod index eb9473c5..2dd835ea 100644 --- a/snippets/go.mod +++ b/snippets/go.mod @@ -7,8 +7,8 @@ toolchain go1.25.1 replace github.com/googleapis/go-sql-spanner => ../ require ( - cloud.google.com/go/spanner v1.85.1 - github.com/docker/docker v28.4.0+incompatible + cloud.google.com/go/spanner v1.86.0 + github.com/docker/docker v28.5.0+incompatible github.com/googleapis/go-sql-spanner v1.18.1 github.com/testcontainers/testcontainers-go v0.39.0 ) @@ -18,7 +18,7 @@ require ( cloud.google.com/go v0.123.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.8.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/longrunning v0.6.7 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect @@ -90,18 +90,18 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/net v0.44.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.17.0 // indirect golang.org/x/sys v0.36.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 // indirect - google.golang.org/api v0.249.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/time v0.13.0 // indirect + google.golang.org/api v0.251.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect google.golang.org/grpc v1.75.1 // indirect - google.golang.org/protobuf v1.36.9 // indirect + google.golang.org/protobuf v1.36.10 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/snippets/go.sum b/snippets/go.sum index a3288fd3..064c23d0 100644 --- a/snippets/go.sum +++ b/snippets/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= -cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -526,8 +526,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+ cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.85.1 h1:cJx1ZD//C2QIfFQl8hSTn4twL8amAXtnayyflRIjj40= -cloud.google.com/go/spanner v1.85.1/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= +cloud.google.com/go/spanner v1.86.0 h1:jlNWusBol1Jxa9PmYGknUBzLwvD1cebuEenzqebZ9xs= +cloud.google.com/go/spanner v1.86.0/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -688,8 +688,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1 github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/docker v28.4.0+incompatible h1:KVC7bz5zJY/4AZe/78BIvCnPsLaC9T/zh72xnlrTTOk= -github.com/docker/docker v28.4.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/docker v28.5.0+incompatible h1:ZdSQoRUE9XxhFI/B8YLvhnEFMmYN9Pp8Egd2qcaFk1E= +github.com/docker/docker v28.5.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.6.0 h1:LlMG9azAe1TqfR7sO+NJttz1gy6KO7VJBh+pMmjSD94= github.com/docker/go-connections v0.6.0/go.mod h1:AahvXYshr6JgfUJGdDCs2b5EZG/vmaMAntpSFH5BFKE= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= @@ -1047,8 +1047,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1163,8 +1163,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1194,8 +1194,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1212,8 +1212,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1306,8 +1306,8 @@ golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1324,16 +1324,16 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1470,8 +1470,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w= -google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ= +google.golang.org/api v0.251.0 h1:6lea5nHRT8RUmpy9kkC2PJYnhnDAB13LqrLSVQlMIE8= +google.golang.org/api v0.251.0/go.mod h1:Rwy0lPf/TD7+T2VhYcffCHhyyInyuxGjICxdfLqT7KI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1615,8 +1615,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1678,8 +1678,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= diff --git a/spannerlib/go.mod b/spannerlib/go.mod index 1c9f5b9f..668edc15 100644 --- a/spannerlib/go.mod +++ b/spannerlib/go.mod @@ -8,11 +8,11 @@ replace github.com/googleapis/go-sql-spanner => .. require ( cloud.google.com/go/longrunning v0.6.7 - cloud.google.com/go/spanner v1.85.1 + cloud.google.com/go/spanner v1.86.0 github.com/google/go-cmp v0.7.0 github.com/googleapis/go-sql-spanner v1.18.1 google.golang.org/grpc v1.75.1 - google.golang.org/protobuf v1.36.9 + google.golang.org/protobuf v1.36.10 ) require ( @@ -20,7 +20,7 @@ require ( cloud.google.com/go v0.123.0 // indirect cloud.google.com/go/auth v0.16.5 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect - cloud.google.com/go/compute/metadata v0.8.0 // indirect + cloud.google.com/go/compute/metadata v0.9.0 // indirect cloud.google.com/go/iam v1.5.2 // indirect cloud.google.com/go/monitoring v1.24.2 // indirect github.com/GoogleCloudPlatform/grpc-gcp-go/grpcgcp v1.5.3 // indirect @@ -53,15 +53,15 @@ require ( go.opentelemetry.io/otel/sdk v1.37.0 // indirect go.opentelemetry.io/otel/sdk/metric v1.37.0 // indirect go.opentelemetry.io/otel/trace v1.37.0 // indirect - golang.org/x/crypto v0.41.0 // indirect - golang.org/x/net v0.43.0 // indirect - golang.org/x/oauth2 v0.30.0 // indirect - golang.org/x/sync v0.16.0 // indirect - golang.org/x/sys v0.35.0 // indirect - golang.org/x/text v0.28.0 // indirect - golang.org/x/time v0.12.0 // indirect - google.golang.org/api v0.249.0 // indirect + golang.org/x/crypto v0.42.0 // indirect + golang.org/x/net v0.44.0 // indirect + golang.org/x/oauth2 v0.31.0 // indirect + golang.org/x/sync v0.17.0 // indirect + golang.org/x/sys v0.36.0 // indirect + golang.org/x/text v0.29.0 // indirect + golang.org/x/time v0.13.0 // indirect + google.golang.org/api v0.251.0 // indirect google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect ) diff --git a/spannerlib/go.sum b/spannerlib/go.sum index c8f84b25..37cdcdc0 100644 --- a/spannerlib/go.sum +++ b/spannerlib/go.sum @@ -184,8 +184,8 @@ cloud.google.com/go/compute/metadata v0.1.0/go.mod h1:Z1VN+bulIf6bt4P/C37K4DyZYZ cloud.google.com/go/compute/metadata v0.2.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k= cloud.google.com/go/compute/metadata v0.2.1/go.mod h1:jgHgmJd2RKBGzXqF5LR2EZMGxBkeanZ9wwa75XHJgOM= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= -cloud.google.com/go/compute/metadata v0.8.0 h1:HxMRIbao8w17ZX6wBnjhcDkW6lTFpgcaobyVfZWqRLA= -cloud.google.com/go/compute/metadata v0.8.0/go.mod h1:sYOGTp851OV9bOFJ9CH7elVvyzopvWQFNNghtDQ/Biw= +cloud.google.com/go/compute/metadata v0.9.0 h1:pDUj4QMoPejqq20dK0Pg2N4yG9zIkYGdBtwLoEkH9Zs= +cloud.google.com/go/compute/metadata v0.9.0/go.mod h1:E0bWwX5wTnLPedCKqk3pJmVgCBSM6qQI1yTBdEb3C10= cloud.google.com/go/contactcenterinsights v1.3.0/go.mod h1:Eu2oemoePuEFc/xKFPjbTuPSj0fYJcPls9TFlPNnHHY= cloud.google.com/go/contactcenterinsights v1.4.0/go.mod h1:L2YzkGbPsv+vMQMCADxJoT9YiTTnSEd6fEvCeHTYVck= cloud.google.com/go/contactcenterinsights v1.6.0/go.mod h1:IIDlT6CLcDoyv79kDv8iWxMSTZhLxSCofVV5W6YFM/w= @@ -526,8 +526,8 @@ cloud.google.com/go/shell v1.6.0/go.mod h1:oHO8QACS90luWgxP3N9iZVuEiSF84zNyLytb+ cloud.google.com/go/spanner v1.41.0/go.mod h1:MLYDBJR/dY4Wt7ZaMIQ7rXOTLjYrmxLE/5ve9vFfWos= cloud.google.com/go/spanner v1.44.0/go.mod h1:G8XIgYdOK+Fbcpbs7p2fiprDw4CaZX63whnSMLVBxjk= cloud.google.com/go/spanner v1.45.0/go.mod h1:FIws5LowYz8YAE1J8fOS7DJup8ff7xJeetWEo5REA2M= -cloud.google.com/go/spanner v1.85.1 h1:cJx1ZD//C2QIfFQl8hSTn4twL8amAXtnayyflRIjj40= -cloud.google.com/go/spanner v1.85.1/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= +cloud.google.com/go/spanner v1.86.0 h1:jlNWusBol1Jxa9PmYGknUBzLwvD1cebuEenzqebZ9xs= +cloud.google.com/go/spanner v1.86.0/go.mod h1:bbwCXbM+zljwSPLZ44wZOdzcdmy89hbUGmM/r9sD0ws= cloud.google.com/go/speech v1.6.0/go.mod h1:79tcr4FHCimOp56lwC01xnt/WPJZc4v3gzyT7FoBkCM= cloud.google.com/go/speech v1.7.0/go.mod h1:KptqL+BAQIhMsj1kOP2la5DSEEerPDuOP/2mmkhHhZQ= cloud.google.com/go/speech v1.8.0/go.mod h1:9bYIl1/tjsAnMgKGHKmBZzXKEkGgtU+MpdDPTE9f7y0= @@ -955,8 +955,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20180807140117-3d87b88a115f/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -1071,8 +1071,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -1102,8 +1102,8 @@ golang.org/x/oauth2 v0.4.0/go.mod h1:RznEsdpjGAINPTOF0UH/t+xJ75L18YO3Ho6Pyn+uRec golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= -golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= -golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= +golang.org/x/oauth2 v0.31.0 h1:8Fq0yVZLh4j4YA47vHKFTa9Ew5XIrCP8LC6UeNZnLxo= +golang.org/x/oauth2 v0.31.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1120,8 +1120,8 @@ golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220929204114-8fcdb60fdcc0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1199,8 +1199,8 @@ golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -1225,16 +1225,16 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.1.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1371,8 +1371,8 @@ google.golang.org/api v0.108.0/go.mod h1:2Ts0XTHNVWxypznxWOYUeI4g3WdP9Pk2Qk58+a/ google.golang.org/api v0.110.0/go.mod h1:7FC4Vvx1Mooxh8C5HWjzZHcavuS2f6pmJpZx60ca7iI= google.golang.org/api v0.111.0/go.mod h1:qtFHvU9mhgTJegR31csQ+rwxyUTHOKFqCKWp1J0fdw0= google.golang.org/api v0.114.0/go.mod h1:ifYI2ZsFK6/uGddGfAD5BMxlnkBqCmqHSDUVi45N5Yg= -google.golang.org/api v0.249.0 h1:0VrsWAKzIZi058aeq+I86uIXbNhm9GxSHpbmZ92a38w= -google.golang.org/api v0.249.0/go.mod h1:dGk9qyI0UYPwO/cjt2q06LG/EhUpwZGdAbYF14wHHrQ= +google.golang.org/api v0.251.0 h1:6lea5nHRT8RUmpy9kkC2PJYnhnDAB13LqrLSVQlMIE8= +google.golang.org/api v0.251.0/go.mod h1:Rwy0lPf/TD7+T2VhYcffCHhyyInyuxGjICxdfLqT7KI= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1516,8 +1516,8 @@ google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b h1:eZTgydvqZO44zyT google.golang.org/genproto v0.0.0-20250804133106-a7a43d27e69b/go.mod h1:suyz2QBHQKlGIF92HEEsCfO1SwxXdk7PFLz+Zd9Uah4= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c h1:AtEkQdl5b6zsybXcbz00j1LwNodDuH6hVifIaNqk7NQ= google.golang.org/genproto/googleapis/api v0.0.0-20250818200422-3122310a409c/go.mod h1:ea2MjsO70ssTfCjiwHgI0ZFqcw45Ksuk2ckf9G468GA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9 h1:V1jCN2HBa8sySkR5vLcCSqJSTMv093Rw9EJefhQGP7M= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250922171735-9219d122eba9/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1579,8 +1579,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.29.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.36.9 h1:w2gp2mA27hUeUzj9Ex9FBjsBm40zfaDtEWow293U7Iw= -google.golang.org/protobuf v1.36.9/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/spannerlib/wrappers/spannerlib-java/pom.xml b/spannerlib/wrappers/spannerlib-java/pom.xml index eaa50031..088b2784 100644 --- a/spannerlib/wrappers/spannerlib-java/pom.xml +++ b/spannerlib/wrappers/spannerlib-java/pom.xml @@ -16,14 +16,14 @@ com.google.cloud sdk-platform-java-config - 3.52.2 + 3.52.3 com.google.cloud google-cloud-spanner-bom - 6.100.0 + 6.101.1 pom import @@ -54,12 +54,25 @@ test-jar test + + + net.bytebuddy + byte-buddy + 1.17.7 + test + + + net.bytebuddy + byte-buddy-agent + 1.17.7 + test + com.google.api gax-grpc testlib test - 2.70.2 + 2.70.3 junit From bb87d9605f38cb875ec83a61a216d8697e60f490 Mon Sep 17 00:00:00 2001 From: aakashanandg Date: Tue, 7 Oct 2025 11:09:26 +0530 Subject: [PATCH 10/15] feat(ruby): Add Ruby FFI wrapper for spannerlib (#545) * feat(ruby): add Ruby FFI wrapper for spannerlib --- .../integration-tests-on-emulator.yml | 36 ++- spannerlib/.gitignore | 7 + .../wrappers/spannerlib-ruby/.gitignore | 16 ++ spannerlib/wrappers/spannerlib-ruby/.rspec | 3 + .../wrappers/spannerlib-ruby/.rubocop.yml | 32 +++ spannerlib/wrappers/spannerlib-ruby/Gemfile | 14 + spannerlib/wrappers/spannerlib-ruby/Rakefile | 45 ++++ .../wrappers/spannerlib-ruby/bin/console | 11 + spannerlib/wrappers/spannerlib-ruby/bin/setup | 8 + .../lib/spannerlib/connection.rb | 106 ++++++++ .../lib/spannerlib/exceptions.rb | 24 ++ .../spannerlib-ruby/lib/spannerlib/ffi.rb | 249 ++++++++++++++++++ .../spannerlib-ruby/lib/spannerlib/pool.rb | 63 +++++ .../spannerlib-ruby/lib/spannerlib/ruby.rb | 24 ++ .../lib/spannerlib/ruby/version.rb | 7 + .../spannerlib-ruby/sig/spannerlib/ruby.rbs | 6 + .../spannerlib-ruby/spannerlib-ruby.gemspec | 27 ++ .../integration/connection_emulator_spec.rb | 165 ++++++++++++ .../spec/integration/pool_emulator_spec.rb | 42 +++ .../spec/spannerlib/connection_spec.rb | 53 ++++ .../spec/spannerlib/pool_spec.rb | 53 ++++ .../spannerlib-ruby/spec/spec_helper.rb | 32 +++ 22 files changed, 1020 insertions(+), 3 deletions(-) create mode 100644 spannerlib/wrappers/spannerlib-ruby/.gitignore create mode 100644 spannerlib/wrappers/spannerlib-ruby/.rspec create mode 100644 spannerlib/wrappers/spannerlib-ruby/.rubocop.yml create mode 100644 spannerlib/wrappers/spannerlib-ruby/Gemfile create mode 100644 spannerlib/wrappers/spannerlib-ruby/Rakefile create mode 100755 spannerlib/wrappers/spannerlib-ruby/bin/console create mode 100755 spannerlib/wrappers/spannerlib-ruby/bin/setup create mode 100644 spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/connection.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/exceptions.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ffi.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/pool.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby/version.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/sig/spannerlib/ruby.rbs create mode 100644 spannerlib/wrappers/spannerlib-ruby/spannerlib-ruby.gemspec create mode 100644 spannerlib/wrappers/spannerlib-ruby/spec/integration/connection_emulator_spec.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/spec/integration/pool_emulator_spec.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/connection_spec.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/pool_spec.rb create mode 100644 spannerlib/wrappers/spannerlib-ruby/spec/spec_helper.rb diff --git a/.github/workflows/integration-tests-on-emulator.yml b/.github/workflows/integration-tests-on-emulator.yml index 38a57e1c..acecd5fa 100644 --- a/.github/workflows/integration-tests-on-emulator.yml +++ b/.github/workflows/integration-tests-on-emulator.yml @@ -2,9 +2,13 @@ on: push: branches: [ main ] pull_request: + name: Integration tests on emulator + jobs: - test: + # This is the original job, renamed for clarity + test-go: + name: Go Integration Tests runs-on: ubuntu-latest services: emulator: @@ -18,11 +22,37 @@ jobs: with: go-version: 1.25.x - name: Checkout code - uses: actions/checkout@v5 - - name: Run integration tests on emulator + uses: actions/checkout@v4 + - name: Run Go integration tests on emulator run: go test -race env: JOB_TYPE: test SPANNER_EMULATOR_HOST: localhost:9010 SPANNER_TEST_PROJECT: emulator-test-project SPANNER_TEST_INSTANCE: test-instance + + test-ruby: + name: Ruby Integration Tests + runs-on: ubuntu-latest + services: + emulator: + image: gcr.io/cloud-spanner-emulator/emulator:latest + ports: + - 9010:9010 + - 9020:9020 + steps: + - name: Checkout code + uses: actions/checkout@v5 + - name: Set up Ruby + uses: ruby/setup-ruby@v1 + with: + ruby-version: '3.3.1' + working-directory: spannerlib/wrappers/spannerlib-ruby + bundler-cache: true + - name: Compile and Run Ruby Integration Tests + working-directory: spannerlib/wrappers/spannerlib-ruby + env: + SPANNER_EMULATOR_HOST: localhost:9010 + run: | + bundle exec rake compile + bundle exec rspec spec/integration/ diff --git a/spannerlib/.gitignore b/spannerlib/.gitignore index f6dbcd3d..e3130ba8 100644 --- a/spannerlib/.gitignore +++ b/spannerlib/.gitignore @@ -1,3 +1,10 @@ spannerlib.h spannerlib.so grpc_server +vendor/bundle +shared/ +*.gem +.DS_Store +*.swp +ext/ +Gemfile.lock diff --git a/spannerlib/wrappers/spannerlib-ruby/.gitignore b/spannerlib/wrappers/spannerlib-ruby/.gitignore new file mode 100644 index 00000000..c458d7fd --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/.gitignore @@ -0,0 +1,16 @@ +/.bundle/ +/.yardoc +/_yardoc/ +/coverage/ +/doc/ +/pkg/ +/spec/reports/ +/tmp/ + +.rspec_status +/vendor/bundle +/shared/ +*.gem + +.DS_Store +*.swp \ No newline at end of file diff --git a/spannerlib/wrappers/spannerlib-ruby/.rspec b/spannerlib/wrappers/spannerlib-ruby/.rspec new file mode 100644 index 00000000..34c5164d --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/.rspec @@ -0,0 +1,3 @@ +--format documentation +--color +--require spec_helper diff --git a/spannerlib/wrappers/spannerlib-ruby/.rubocop.yml b/spannerlib/wrappers/spannerlib-ruby/.rubocop.yml new file mode 100644 index 00000000..40dda27b --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/.rubocop.yml @@ -0,0 +1,32 @@ +AllCops: + NewCops: enable + SuggestExtensions: false + Exclude: + - 'lib/spanner_pb.rb' + - 'vendor/**/*' + +plugins: + - rubocop-rspec + +Layout/LineLength: + Max: 150 + +Style/Documentation: + Enabled: false + +RSpec/ExampleLength: + Enabled: false +RSpec/MultipleExpectations: + Enabled: false + +# Add this block to disable the 'let' rule +RSpec/InstanceVariable: + Enabled: false +RSpec/BeforeAfterAll: + Enabled: false +RSpec/DescribeClass: + Exclude: + - 'spec/integration/**/*' + +Style/StringLiterals: + EnforcedStyle: double_quotes diff --git a/spannerlib/wrappers/spannerlib-ruby/Gemfile b/spannerlib/wrappers/spannerlib-ruby/Gemfile new file mode 100644 index 00000000..a40cfd66 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/Gemfile @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +gemspec + +gem "rake", "~> 13.0" + +group :development, :test do + gem "rake-compiler", "~> 1.0" + gem "rspec", "~> 3.0" + gem "rubocop", require: false + gem "rubocop-rspec", require: false +end diff --git a/spannerlib/wrappers/spannerlib-ruby/Rakefile b/spannerlib/wrappers/spannerlib-ruby/Rakefile new file mode 100644 index 00000000..c6babf0a --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/Rakefile @@ -0,0 +1,45 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require "bundler/gem_tasks" +require "rspec/core/rake_task" +require "rubocop/rake_task" +require "rbconfig" + +RSpec::Core::RakeTask.new(:spec) + +RuboCop::RakeTask.new + +task :compile do + go_source_dir = File.expand_path("../../shared", __dir__) + target_dir = File.expand_path("lib/spannerlib/#{RbConfig::CONFIG['arch']}", __dir__) + output_file = File.join(target_dir, "spannerlib.#{RbConfig::CONFIG['SOEXT']}") + + mkdir_p target_dir + + command = [ + "go", "build", + "-buildmode=c-shared", + "-o", output_file, + go_source_dir + ].join(" ") + + puts command + sh command +end + +task default: %i[compile spec rubocop] + diff --git a/spannerlib/wrappers/spannerlib-ruby/bin/console b/spannerlib/wrappers/spannerlib-ruby/bin/console new file mode 100755 index 00000000..951cbd1b --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/bin/console @@ -0,0 +1,11 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +require "bundler/setup" +require "spannerlib/ruby" + +# You can add fixtures and/or initialization code here to make experimenting +# with your gem easier. You can also use a different console, if you like. + +require "irb" +IRB.start(__FILE__) diff --git a/spannerlib/wrappers/spannerlib-ruby/bin/setup b/spannerlib/wrappers/spannerlib-ruby/bin/setup new file mode 100755 index 00000000..dce67d86 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/bin/setup @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +set -euo pipefail +IFS=$'\n\t' +set -vx + +bundle install + +# Do any other automated setup that you need to do here diff --git a/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/connection.rb b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/connection.rb new file mode 100644 index 00000000..ea824a7c --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/connection.rb @@ -0,0 +1,106 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require_relative "ffi" + +class Connection + attr_reader :pool_id, :conn_id + + def initialize(pool_id, conn_id) + @pool_id = pool_id + @conn_id = conn_id + end + + # Accepts either an object that responds to `to_proto` or a raw string/bytes + # containing the serialized mutation proto. We avoid requiring the protobuf + # definitions at load time so specs that don't need them can run. + def write_mutations(mutation_group) + req_bytes = if mutation_group.respond_to?(:to_proto) + mutation_group.to_proto + elsif mutation_group.is_a?(String) + mutation_group + else + mutation_group.to_s + end + + SpannerLib.write_mutations(@pool_id, @conn_id, req_bytes) + end + + # Begin a read/write transaction on this connection. Accepts TransactionOptions proto or bytes. + # Returns message bytes (or nil) — higher-level parsing not implemented here. + def begin_transaction(transaction_options = nil) + bytes = if transaction_options.respond_to?(:to_proto) + transaction_options.to_proto + else + transaction_options.is_a?(String) ? transaction_options : transaction_options&.to_s + end + SpannerLib.begin_transaction(@pool_id, @conn_id, bytes) + end + + # Commit the current transaction. Returns CommitResponse bytes or nil. + def commit + SpannerLib.commit(@pool_id, @conn_id) + end + + # Rollback the current transaction. + def rollback + SpannerLib.rollback(@pool_id, @conn_id) + nil + end + + # Execute SQL request (expects a request object with to_proto or raw bytes). Returns message bytes (or nil). + def execute(request) + bytes = if request.respond_to?(:to_proto) + request.to_proto + else + request.is_a?(String) ? request : request.to_s + end + SpannerLib.execute(@pool_id, @conn_id, bytes) + end + + # Execute batch DML/DDL request. Returns ExecuteBatchDmlResponse bytes (or nil). + def execute_batch(request) + bytes = if request.respond_to?(:to_proto) + request.to_proto + else + request.is_a?(String) ? request : request.to_s + end + SpannerLib.execute_batch(@pool_id, @conn_id, bytes) + end + + # Rows helpers — return raw message bytes (caller should parse them). + def metadata(rows_id) + SpannerLib.metadata(@pool_id, @conn_id, rows_id) + end + + def next_rows(rows_id, num_rows, encoding = 0) + SpannerLib.next(@pool_id, @conn_id, rows_id, num_rows, encoding) + end + + def result_set_stats(rows_id) + SpannerLib.result_set_stats(@pool_id, @conn_id, rows_id) + end + + def close_rows(rows_id) + SpannerLib.close_rows(@pool_id, @conn_id, rows_id) + end + + # Closes this connection. Any active transaction on the connection is rolled back. + def close + SpannerLib.close_connection(@pool_id, @conn_id) + nil + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/exceptions.rb b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/exceptions.rb new file mode 100644 index 00000000..6331652d --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/exceptions.rb @@ -0,0 +1,24 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +class SpannerLibException < StandardError + attr_reader :status + + def initialize(msg = nil, status = nil) + super(msg) + @status = status + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ffi.rb b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ffi.rb new file mode 100644 index 00000000..f01059c8 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ffi.rb @@ -0,0 +1,249 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +# rubocop:disable Metrics/ModuleLength + +require "rubygems" +require "bundler/setup" + +require "google/protobuf" +require "google/rpc/status_pb" + +require "ffi" + +module SpannerLib + extend FFI::Library + + def self.library_path + lib_dir = File.expand_path(__dir__) + Dir.glob(File.join(lib_dir, "*/spannerlib.#{FFI::Platform::LIBSUFFIX}")).first + end + + ffi_lib library_path + + class GoString < FFI::Struct + layout :p, :pointer, + :len, :long + end + + # GoBytes is the Ruby representation of a Go byte slice + class GoBytes < FFI::Struct + layout :p, :pointer, + :len, :long, + :cap, :long + end + + # Message is the common return type for all native functions. + class Message < FFI::Struct + layout :pinner, :long_long, + :code, :int, + :objectId, :long_long, + :length, :int, + :pointer, :pointer + end + + # --- Native Function Signatures --- + attach_function :CreatePool, [GoString.by_value], Message.by_value + attach_function :ClosePool, [:int64], Message.by_value + attach_function :CreateConnection, [:int64], Message.by_value + attach_function :CloseConnection, %i[int64 int64], Message.by_value + attach_function :WriteMutations, [:int64, :int64, GoBytes.by_value], Message.by_value + attach_function :BeginTransaction, [:int64, :int64, GoBytes.by_value], Message.by_value + attach_function :Commit, %i[int64 int64], Message.by_value + attach_function :Rollback, %i[int64 int64], Message.by_value + attach_function :Execute, [:int64, :int64, GoBytes.by_value], Message.by_value + attach_function :ExecuteBatch, [:int64, :int64, GoBytes.by_value], Message.by_value + attach_function :Metadata, %i[int64 int64 int64], Message.by_value + attach_function :Next, %i[int64 int64 int64 int32 int32], Message.by_value + attach_function :ResultSetStats, %i[int64 int64 int64], Message.by_value + attach_function :CloseRows, %i[int64 int64 int64], Message.by_value + attach_function :Release, [:int64], :void + + # --- Ruby-friendly Wrappers --- + + def self.create_pool(dsn) + dsn_str = dsn.to_s.dup + dsn_ptr = FFI::MemoryPointer.from_string(dsn_str) + + go_dsn = GoString.new + go_dsn[:p] = dsn_ptr + go_dsn[:len] = dsn_str.bytesize + + message = CreatePool(go_dsn) + handle_object_id_response(message, "CreatePool") + end + + def self.close_pool(pool_id) + message = ClosePool(pool_id) + handle_status_response(message, "ClosePool") + end + + def self.create_connection(pool_id) + message = CreateConnection(pool_id) + handle_object_id_response(message, "CreateConnection") + end + + def self.close_connection(pool_id, conn_id) + message = CloseConnection(pool_id, conn_id) + handle_status_response(message, "CloseConnection") + end + + def self.release(pinner) + Release(pinner) + end + + def self.with_gobytes(bytes) + bytes ||= "" + len = bytes.bytesize + ptr = FFI::MemoryPointer.new(len) + ptr.write_bytes(bytes, 0, len) if len.positive? + + go_bytes = GoBytes.new + go_bytes[:p] = ptr + go_bytes[:len] = len + go_bytes[:cap] = len + + yield(go_bytes) + end + + def self.ensure_release(message) + pinner = message[:pinner] + begin + yield + ensure + release(pinner) if pinner != 0 + end + end + + def self.handle_object_id_response(message, func_name) + ensure_release(message) do + if message[:code] != 0 + error_msg = read_error_message(message) + raise "#{func_name} failed with code #{message[:code]}: #{error_msg}" + end + message[:objectId] + end + end + + def self.handle_status_response(message, func_name) + ensure_release(message) do + if message[:code] != 0 + error_msg = read_error_message(message) + raise "#{func_name} failed with code #{message[:code]}: #{error_msg}" + end + end + nil + end + + # rubocop:disable Metrics/MethodLength + def self.handle_data_response(message, func_name) + ensure_release(message) do + if message[:code] != 0 + error_msg = read_error_message(message) + raise "#{func_name} failed with code #{message[:code]}: #{error_msg}" + end + + len = message[:length] + ptr = message[:pointer] + + if len.positive? && !ptr.null? + ptr.read_bytes(len) + else + "" + end + end + end + # rubocop:enable Metrics/MethodLength + + # rubocop:disable Metrics/MethodLength + def self.read_error_message(message) + len = message[:length] + ptr = message[:pointer] + if len.positive? && !ptr.null? + raw_bytes = ptr.read_bytes(len) + begin + status_proto = ::Google::Rpc::Status.decode(raw_bytes) + "Status Proto { code: #{status_proto.code}, message: '#{status_proto.message}' }" + rescue StandardError => e + clean_string = raw_bytes.encode("UTF-8", invalid: :replace, undef: :replace, replace: "?").strip + "Failed to decode Status proto (code #{message[:code]}): #{e.class}: #{e.message} | Raw: #{clean_string}" + end + else + "No error message provided" + end + end + # rubocop:enable Metrics/MethodLength + + def self.write_mutations(pool_id, conn_id, proto_bytes) + with_gobytes(proto_bytes) do |gobytes| + message = WriteMutations(pool_id, conn_id, gobytes) + handle_data_response(message, "WriteMutations") + end + end + + def self.begin_transaction(pool_id, conn_id, proto_bytes) + with_gobytes(proto_bytes) do |gobytes| + message = BeginTransaction(pool_id, conn_id, gobytes) + handle_data_response(message, "BeginTransaction") + end + end + + def self.commit(pool_id, conn_id) + message = Commit(pool_id, conn_id) + handle_data_response(message, "Commit") + end + + def self.rollback(pool_id, conn_id) + message = Rollback(pool_id, conn_id) + handle_status_response(message, "Rollback") + end + + def self.execute(pool_id, conn_id, proto_bytes) + with_gobytes(proto_bytes) do |gobytes| + message = Execute(pool_id, conn_id, gobytes) + handle_object_id_response(message, "Execute") + end + end + + def self.execute_batch(pool_id, conn_id, proto_bytes) + with_gobytes(proto_bytes) do |gobytes| + message = ExecuteBatch(pool_id, conn_id, gobytes) + handle_data_response(message, "ExecuteBatch") + end + end + + def self.metadata(pool_id, conn_id, rows_id) + message = Metadata(pool_id, conn_id, rows_id) + handle_data_response(message, "Metadata") + end + + def self.next(pool_id, conn_id, rows_id, max_rows, fetch_size) + message = Next(pool_id, conn_id, rows_id, max_rows, fetch_size) + handle_data_response(message, "Next") + end + + def self.result_set_stats(pool_id, conn_id, rows_id) + message = ResultSetStats(pool_id, conn_id, rows_id) + handle_data_response(message, "ResultSetStats") + end + + def self.close_rows(pool_id, conn_id, rows_id) + message = CloseRows(pool_id, conn_id, rows_id) + handle_status_response(message, "CloseRows") + end +end + +# rubocop:enable Metrics/ModuleLength diff --git a/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/pool.rb b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/pool.rb new file mode 100644 index 00000000..33f7065a --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/pool.rb @@ -0,0 +1,63 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require_relative "ffi" +require_relative "connection" + +class Pool + attr_reader :id + + def initialize(id) + @id = id + @closed = false + end + + # Create a new Pool given a DSN string. Raises SpannerLibException on failure. + def self.create_pool(dsn) + begin + pool_id = SpannerLib.create_pool(dsn) + rescue StandardError => e + raise SpannerLibException, e.message + end + + raise SpannerLibException, "failed to create pool" if pool_id.nil? || pool_id <= 0 + + Pool.new(pool_id) + end + + # Close this pool and free native resources. + def close + return if @closed + + SpannerLib.close_pool(@id) + @closed = true + end + + # Create a new Connection associated with this Pool. + def create_connection + raise SpannerLibException, "pool closed" if @closed + + begin + conn_id = SpannerLib.create_connection(@id) + rescue StandardError => e + raise SpannerLibException, e.message + end + + raise SpannerLibException, "failed to create connection" if conn_id.nil? || conn_id <= 0 + + Connection.new(@id, conn_id) + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby.rb b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby.rb new file mode 100644 index 00000000..d206682b --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby.rb @@ -0,0 +1,24 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require_relative "ruby/version" + +module Spannerlib + module Ruby + class Error < StandardError; end + # Your code goes here... + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby/version.rb b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby/version.rb new file mode 100644 index 00000000..100ee429 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/lib/spannerlib/ruby/version.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module Spannerlib + module Ruby + VERSION = "0.1.0" + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/sig/spannerlib/ruby.rbs b/spannerlib/wrappers/spannerlib-ruby/sig/spannerlib/ruby.rbs new file mode 100644 index 00000000..e76e73dd --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/sig/spannerlib/ruby.rbs @@ -0,0 +1,6 @@ +module Spannerlib + module Ruby + VERSION: String + # See the writing guide of rbs: https://github.com/ruby/rbs#guides + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/spannerlib-ruby.gemspec b/spannerlib/wrappers/spannerlib-ruby/spannerlib-ruby.gemspec new file mode 100644 index 00000000..4f746b3d --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/spannerlib-ruby.gemspec @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +require_relative "lib/spannerlib/ruby/version" + +Gem::Specification.new do |spec| + spec.name = "spannerlib-ruby" + spec.version = Spannerlib::Ruby::VERSION + spec.authors = ["Google LLC"] + spec.email = ["cloud-spanner-developers@googlegroups.com"] + + spec.summary = "Ruby wrapper for the Spanner native library" + spec.description = "Lightweight Ruby FFI bindings for the Spanner native library produced from the Go implementation." + spec.homepage = "https://github.com/googleapis/go-sql-spanner/tree/main/spannerlib/wrappers/spannerlib-ruby" + spec.license = "Apache 2.0 License" + spec.required_ruby_version = ">= 3.1.0" + + spec.metadata["rubygems_mfa_required"] = "true" + + spec.bindir = "exe" + spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) } + spec.require_paths = ["lib"] + + spec.add_dependency "ffi" + spec.add_dependency "google-cloud-spanner-v1", "~> 1.7" + spec.add_dependency "google-protobuf", "~> 3.19" + spec.add_dependency "grpc", "~> 1.60" +end diff --git a/spannerlib/wrappers/spannerlib-ruby/spec/integration/connection_emulator_spec.rb b/spannerlib/wrappers/spannerlib-ruby/spec/integration/connection_emulator_spec.rb new file mode 100644 index 00000000..1149b6a3 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/spec/integration/connection_emulator_spec.rb @@ -0,0 +1,165 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require "spec_helper" +require "google/cloud/spanner/v1" + +RSpec.describe "Connection APIs against Spanner emulator", :integration do + before(:all) do + @emulator_host = ENV.fetch("SPANNER_EMULATOR_HOST", nil) + skip "SPANNER_EMULATOR_HOST not set" unless @emulator_host && !@emulator_host.empty? + + require "spannerlib/pool" + @dsn = "projects/your-project-id/instances/test-instance/databases/test-database?autoConfigEmulator=true" + + pool = Pool.create_pool(@dsn) + conn = pool.create_connection + ddl_batch_req = Google::Cloud::Spanner::V1::ExecuteBatchDmlRequest.new( + statements: [ + Google::Cloud::Spanner::V1::ExecuteBatchDmlRequest::Statement.new(sql: "DROP TABLE IF EXISTS test_table"), + Google::Cloud::Spanner::V1::ExecuteBatchDmlRequest::Statement.new( + sql: "CREATE TABLE test_table (id INT64 NOT NULL, name STRING(100)) PRIMARY KEY(id)" + ) + ] + ) + conn.execute_batch(ddl_batch_req) + conn.close + pool.close + end + + before do + @pool = Pool.create_pool(@dsn) + @conn = @pool.create_connection + delete_req = Google::Cloud::Spanner::V1::BatchWriteRequest::MutationGroup.new( + mutations: [ + Google::Cloud::Spanner::V1::Mutation.new( + delete: Google::Cloud::Spanner::V1::Mutation::Delete.new( + table: "test_table", + key_set: Google::Cloud::Spanner::V1::KeySet.new(all: true) + ) + ) + ] + ) + @conn.write_mutations(delete_req) + end + + after do + @conn.close + @pool.close + end + + it "creates a connection pool" do + expect(@pool.id).to be > 0 + expect(@conn.conn_id).to be > 0 + end + + it "creates two connections from the same pool" do + conn2 = @pool.create_connection + expect(@conn.conn_id).not_to eq(conn2.conn_id) + expect(conn2.conn_id).to be > 0 + conn2.close + end + + it "writes and reads data in a read-write transaction" do + @conn.begin_transaction + insert_data_req = Google::Cloud::Spanner::V1::BatchWriteRequest::MutationGroup.new( + mutations: [ + Google::Cloud::Spanner::V1::Mutation.new( + insert: Google::Cloud::Spanner::V1::Mutation::Write.new( + table: "test_table", + columns: %w[id name], + values: [ + Google::Protobuf::ListValue.new(values: [Google::Protobuf::Value.new(string_value: "1"), + Google::Protobuf::Value.new(string_value: "Alice")]), + Google::Protobuf::ListValue.new(values: [Google::Protobuf::Value.new(string_value: "2"), + Google::Protobuf::Value.new(string_value: "Bob")]) + ] + ) + ) + ] + ) + @conn.write_mutations(insert_data_req) + @conn.commit + + select_req = Google::Cloud::Spanner::V1::ExecuteSqlRequest.new(sql: "SELECT id, name FROM test_table ORDER BY id") + rows_id = @conn.execute(select_req) + + all_rows = [] + loop do + row_bytes = @conn.next_rows(rows_id, 1) + break if row_bytes.nil? || row_bytes.empty? + + all_rows << Google::Protobuf::ListValue.decode(row_bytes) + end + @conn.close_rows(rows_id) + + expect(all_rows.length).to eq(2) + expect(all_rows[0].values[1].string_value).to eq("Alice") + end + + it "writes and reads data without an explicit transaction (autocommit)" do + insert_data_req = Google::Cloud::Spanner::V1::BatchWriteRequest::MutationGroup.new( + mutations: [ + Google::Cloud::Spanner::V1::Mutation.new( + insert: Google::Cloud::Spanner::V1::Mutation::Write.new( + table: "test_table", + columns: %w[id name], + values: [ + Google::Protobuf::ListValue.new(values: [Google::Protobuf::Value.new(string_value: "3"), + Google::Protobuf::Value.new(string_value: "Charlie")]), + Google::Protobuf::ListValue.new(values: [Google::Protobuf::Value.new(string_value: "4"), + Google::Protobuf::Value.new(string_value: "David")]) + ] + ) + ) + ] + ) + @conn.write_mutations(insert_data_req) + + select_req = Google::Cloud::Spanner::V1::ExecuteSqlRequest.new(sql: "SELECT id, name FROM test_table ORDER BY id") + rows_id = @conn.execute(select_req) + + all_rows = [] + loop do + row_bytes = @conn.next_rows(rows_id, 1) + break if row_bytes.nil? || row_bytes.empty? + + all_rows << Google::Protobuf::ListValue.decode(row_bytes) + end + @conn.close_rows(rows_id) + + expect(all_rows.length).to eq(2) + expect(all_rows[0].values[1].string_value).to eq("Charlie") + end + + it "raises an error when writing in a read-only transaction" do + transaction_options = Google::Cloud::Spanner::V1::TransactionOptions.new( + read_only: Google::Cloud::Spanner::V1::TransactionOptions::ReadOnly.new(strong: true) + ) + @conn.begin_transaction(transaction_options) + + insert_data_req = Google::Cloud::Spanner::V1::BatchWriteRequest::MutationGroup.new( + mutations: [ + Google::Cloud::Spanner::V1::Mutation.new( + insert: Google::Cloud::Spanner::V1::Mutation::Write.new(table: "test_table") + ) + ] + ) + expect { @conn.write_mutations(insert_data_req) }.to raise_error(RuntimeError, /read-only transactions cannot write/) + + @conn.rollback + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/spec/integration/pool_emulator_spec.rb b/spannerlib/wrappers/spannerlib-ruby/spec/integration/pool_emulator_spec.rb new file mode 100644 index 00000000..4f7c0911 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/spec/integration/pool_emulator_spec.rb @@ -0,0 +1,42 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe "Connection APIs against Spanner emulator", :integration do + before(:all) do + @emulator_host = ENV.fetch("SPANNER_EMULATOR_HOST", nil) + skip "SPANNER_EMULATOR_HOST not set; skipping emulator integration tests" unless @emulator_host && !@emulator_host.empty? + + begin + require "spannerlib/pool" + rescue LoadError, StandardError => e + skip "Could not load native spanner library; skipping emulator integration tests: #{e.class}: #{e.message}" + end + @dsn = "projects/your-project-id/instances/test-instance/databases/test-database?autoConfigEmulator=true" + end + + it "creates a pool and a connection against the emulator" do + pool = Pool.create_pool(@dsn) + expect(pool.id).to be > 0 + + conn = pool.create_connection + expect(conn).to respond_to(:pool_id) + expect(conn).to respond_to(:conn_id) + + expect { pool.close }.not_to raise_error + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/connection_spec.rb b/spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/connection_spec.rb new file mode 100644 index 00000000..a9d92cbb --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/connection_spec.rb @@ -0,0 +1,53 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language gove + +# frozen_string_literal: true + +require "spec_helper" +require "spannerlib/pool" +require "spannerlib/ffi" +require "spannerlib/exceptions" + +RSpec.describe Connection do + let(:dsn) { "localhost:1234/projects/p/instances/i/databases/d?usePlainText=true" } + let(:pool) { Pool.create_pool(dsn) } + + before do + allow(SpannerLib).to receive(:create_pool).and_return(1) + end + + describe "creation" do + it "is created by a Pool" do + allow(SpannerLib).to receive(:create_connection).with(1).and_return(2) + + # The object under test is the one returned by `pool.create_connection` + conn = pool.create_connection + + expect(conn).to be_a(Connection) + expect(conn.conn_id).to eq(2) + expect(conn.pool_id).to eq(1) + end + + it "raises a SpannerLibException when the FFI call fails" do + allow(SpannerLib).to receive(:create_connection).with(1).and_raise(StandardError.new("boom")) + + expect { pool.create_connection }.to raise_error(SpannerLibException) + end + + it "raises when the FFI call returns a non-positive id" do + allow(SpannerLib).to receive(:create_connection).with(1).and_return(0) + + expect { pool.create_connection }.to raise_error(SpannerLibException) + end + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/pool_spec.rb b/spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/pool_spec.rb new file mode 100644 index 00000000..f6d6a373 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/spec/spannerlib/pool_spec.rb @@ -0,0 +1,53 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require "spec_helper" +require "spannerlib/pool" +require "spannerlib/ffi" +require "spannerlib/exceptions" + +RSpec.describe Pool do + let(:dsn) { "localhost:1234/projects/p/instances/i/databases/d?usePlainText=true" } + + describe ".create_pool" do + it "creates a pool and returns an object with id > 0" do + allow(SpannerLib).to receive(:create_pool).with(dsn).and_return(42) + + pool = described_class.create_pool(dsn) + + expect(pool).to be_a(described_class) + expect(pool.id).to be > 0 + end + + it "raises a SpannerLibException when create_session/create_pool fails" do + allow(SpannerLib).to receive(:create_pool).with(dsn).and_raise(StandardError.new("Not allowed")) + + expect { described_class.create_pool(dsn) }.to raise_error(SpannerLibException) + end + + it "raises when create_pool returns nil" do + allow(SpannerLib).to receive(:create_pool).with(dsn).and_return(nil) + + expect { described_class.create_pool(dsn) }.to raise_error(SpannerLibException) + end + + it "raises when create_pool returns a non-positive id" do + allow(SpannerLib).to receive(:create_pool).with(dsn).and_return(0) + + expect { described_class.create_pool(dsn) }.to raise_error(SpannerLibException) + end + end +end diff --git a/spannerlib/wrappers/spannerlib-ruby/spec/spec_helper.rb b/spannerlib/wrappers/spannerlib-ruby/spec/spec_helper.rb new file mode 100644 index 00000000..514ba076 --- /dev/null +++ b/spannerlib/wrappers/spannerlib-ruby/spec/spec_helper.rb @@ -0,0 +1,32 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# frozen_string_literal: true + +require "rubygems" +require "bundler/setup" + +require "spannerlib/ruby" + +RSpec.configure do |config| + # Enable flags like --only-failures and --next-failure + config.example_status_persistence_file_path = ".rspec_status" + + # Disable RSpec exposing methods globally on `Module` and `main` + config.disable_monkey_patching! + + config.expect_with :rspec do |c| + c.syntax = :expect + end +end From ced9a88f91e2b54a892c1b170a216d3e2fd16efb Mon Sep 17 00:00:00 2001 From: "release-please[bot]" <55107282+release-please[bot]@users.noreply.github.com> Date: Tue, 7 Oct 2025 18:59:33 +0200 Subject: [PATCH 11/15] chore(main): release 1.19.0 (#541) Co-authored-by: release-please[bot] <55107282+release-please[bot]@users.noreply.github.com> --- .release-please-manifest.json | 2 +- CHANGES.md | 15 +++++++++++++++ driver.go | 2 +- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index aa06f863..de44c40d 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "1.18.1" + ".": "1.19.0" } \ No newline at end of file diff --git a/CHANGES.md b/CHANGES.md index 58343eb9..abd0a1eb 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,20 @@ # Changelog +## [1.19.0](https://github.com/googleapis/go-sql-spanner/compare/v1.18.1...v1.19.0) (2025-10-07) + + +### Features + +* Add authority param support to DSN ([#546](https://github.com/googleapis/go-sql-spanner/issues/546)) ([002d386](https://github.com/googleapis/go-sql-spanner/commit/002d386b88d031ad4c8e8cb98153678ad5a74cba)) +* **ruby:** Add Ruby FFI wrapper for spannerlib ([#545](https://github.com/googleapis/go-sql-spanner/issues/545)) ([bb87d96](https://github.com/googleapis/go-sql-spanner/commit/bb87d9605f38cb875ec83a61a216d8697e60f490)) + + +### Bug Fixes + +* Update all dependencies ([#542](https://github.com/googleapis/go-sql-spanner/issues/542)) ([fba2986](https://github.com/googleapis/go-sql-spanner/commit/fba2986be9416ba761285645644d9a5a8eb7180b)) +* Update dependency net.java.dev.jna:jna to v5.18.1 ([#544](https://github.com/googleapis/go-sql-spanner/issues/544)) ([98f2429](https://github.com/googleapis/go-sql-spanner/commit/98f24298fe58ef31ddf8a35923912e998e4d133b)) +* Update module github.com/googleapis/go-sql-spanner to v1.18.1 ([#540](https://github.com/googleapis/go-sql-spanner/issues/540)) ([1eca441](https://github.com/googleapis/go-sql-spanner/commit/1eca4414dfddef2c5e9e3642712317c3929738be)) + ## [1.18.1](https://github.com/googleapis/go-sql-spanner/compare/v1.18.0...v1.18.1) (2025-09-23) diff --git a/driver.go b/driver.go index 59945602..2ccaafb6 100644 --- a/driver.go +++ b/driver.go @@ -51,7 +51,7 @@ import ( "google.golang.org/protobuf/proto" ) -const userAgent = "go-sql-spanner/1.18.1" // x-release-please-version +const userAgent = "go-sql-spanner/1.19.0" // x-release-please-version const gormModule = "github.com/googleapis/go-gorm-spanner" const gormUserAgent = "go-gorm-spanner" From 8893903b0a4365424b96e862579fe28f689c3e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 7 Oct 2025 18:59:49 +0200 Subject: [PATCH 12/15] chore: store temp TransactionOptions in connection state (#548) Store temporary TransactionOptions in the connection state as local options. Local options only apply to the current transaction. This simplifies the internal state handling of the driver, as all transaction state should only be read from the connection state, and not also from a temporary variable. This also enables the use of a combination of temporary transaction options and using SQL statements to set further options. The shared library always includes temporary transaction options, as the BeginTransaction function accepts TransactionOptions as an input argument. This meant that using SQL statements to set further transaction options was not supported through the shared library. --- conn.go | 143 ++++++++++++++++--------- connection_properties.go | 21 ++++ driver.go | 24 +++-- driver_with_mockserver_test.go | 2 +- spannerlib/api/transaction_test.go | 164 +++++++++++++++++++++++++++++ transaction.go | 13 +++ 6 files changed, 311 insertions(+), 56 deletions(-) diff --git a/conn.go b/conn.go index 31dc2c41..7b7e5102 100644 --- a/conn.go +++ b/conn.go @@ -275,14 +275,9 @@ type conn struct { // tempExecOptions can be set by passing it in as an argument to ExecContext or QueryContext // and are applied only to that statement. tempExecOptions *ExecOptions - // tempTransactionOptions are temporarily set right before a read/write transaction is started. - tempTransactionOptions *ReadWriteTransactionOptions - // tempReadOnlyTransactionOptions are temporarily set right before a read-only - // transaction is started on a Spanner connection. - tempReadOnlyTransactionOptions *ReadOnlyTransactionOptions - // tempBatchReadOnlyTransactionOptions are temporarily set right before a - // batch read-only transaction is started on a Spanner connection. - tempBatchReadOnlyTransactionOptions *BatchReadOnlyTransactionOptions + // tempTransactionCloseFunc is set right before a transaction is started, and is set as the + // close function for that transaction. + tempTransactionCloseFunc func() } func (c *conn) UnderlyingClient() (*spanner.Client, error) { @@ -1011,8 +1006,10 @@ func (c *conn) options(reset bool) *ExecOptions { TransactionTag: c.TransactionTag(), IsolationLevel: toProtoIsolationLevelOrDefault(c.IsolationLevel()), ReadLockMode: c.ReadLockMode(), + CommitPriority: propertyCommitPriority.GetValueOrDefault(c.state), CommitOptions: spanner.CommitOptions{ - MaxCommitDelay: c.maxCommitDelayPointer(), + MaxCommitDelay: c.maxCommitDelayPointer(), + ReturnCommitStats: propertyReturnCommitStats.GetValueOrDefault(c.state), }, }, PartitionedQueryOptions: PartitionedQueryOptions{}, @@ -1045,16 +1042,43 @@ func (c *conn) resetTransactionForRetry(ctx context.Context, errDuringCommit boo } func (c *conn) withTempTransactionOptions(options *ReadWriteTransactionOptions) { - c.tempTransactionOptions = options + if options == nil { + return + } + c.tempTransactionCloseFunc = options.close + // Start a transaction for the connection state, so we can set the transaction options + // as local options in the current transaction. + _ = c.state.Begin() + if options.DisableInternalRetries { + _ = propertyRetryAbortsInternally.SetLocalValue(c.state, !options.DisableInternalRetries) + } + if options.TransactionOptions.BeginTransactionOption != spanner.DefaultBeginTransaction { + _ = propertyBeginTransactionOption.SetLocalValue(c.state, options.TransactionOptions.BeginTransactionOption) + } + if options.TransactionOptions.CommitOptions.MaxCommitDelay != nil { + _ = propertyMaxCommitDelay.SetLocalValue(c.state, *options.TransactionOptions.CommitOptions.MaxCommitDelay) + } + if options.TransactionOptions.CommitOptions.ReturnCommitStats { + _ = propertyReturnCommitStats.SetLocalValue(c.state, options.TransactionOptions.CommitOptions.ReturnCommitStats) + } + if options.TransactionOptions.TransactionTag != "" { + _ = propertyTransactionTag.SetLocalValue(c.state, options.TransactionOptions.TransactionTag) + } + if options.TransactionOptions.ReadLockMode != spannerpb.TransactionOptions_ReadWrite_READ_LOCK_MODE_UNSPECIFIED { + _ = propertyReadLockMode.SetLocalValue(c.state, options.TransactionOptions.ReadLockMode) + } + if options.TransactionOptions.IsolationLevel != spannerpb.TransactionOptions_ISOLATION_LEVEL_UNSPECIFIED { + _ = propertyIsolationLevel.SetLocalValue(c.state, toSqlIsolationLevelOrDefault(options.TransactionOptions.IsolationLevel)) + } + if options.TransactionOptions.ExcludeTxnFromChangeStreams { + _ = propertyExcludeTxnFromChangeStreams.SetLocalValue(c.state, options.TransactionOptions.ExcludeTxnFromChangeStreams) + } + if options.TransactionOptions.CommitPriority != spannerpb.RequestOptions_PRIORITY_UNSPECIFIED { + _ = propertyCommitPriority.SetLocalValue(c.state, options.TransactionOptions.CommitPriority) + } } func (c *conn) getTransactionOptions(execOptions *ExecOptions) ReadWriteTransactionOptions { - if c.tempTransactionOptions != nil { - defer func() { c.tempTransactionOptions = nil }() - opts := *c.tempTransactionOptions - opts.TransactionOptions.BeginTransactionOption = c.convertDefaultBeginTransactionOption(opts.TransactionOptions.BeginTransactionOption) - return opts - } txOpts := ReadWriteTransactionOptions{ TransactionOptions: execOptions.TransactionOptions, DisableInternalRetries: !c.RetryAbortsInternally(), @@ -1075,28 +1099,39 @@ func (c *conn) getTransactionOptions(execOptions *ExecOptions) ReadWriteTransact } func (c *conn) withTempReadOnlyTransactionOptions(options *ReadOnlyTransactionOptions) { - c.tempReadOnlyTransactionOptions = options + if options == nil { + return + } + c.tempTransactionCloseFunc = options.close + // Start a transaction for the connection state, so we can set the transaction options + // as local options in the current transaction. + _ = c.state.Begin() + if options.BeginTransactionOption != spanner.DefaultBeginTransaction { + _ = propertyBeginTransactionOption.SetLocalValue(c.state, options.BeginTransactionOption) + } + if options.TimestampBound.String() != "(strong)" { + _ = propertyReadOnlyStaleness.SetLocalValue(c.state, options.TimestampBound) + } } func (c *conn) getReadOnlyTransactionOptions() ReadOnlyTransactionOptions { - if c.tempReadOnlyTransactionOptions != nil { - defer func() { c.tempReadOnlyTransactionOptions = nil }() - opts := *c.tempReadOnlyTransactionOptions - opts.BeginTransactionOption = c.convertDefaultBeginTransactionOption(opts.BeginTransactionOption) - return opts - } return ReadOnlyTransactionOptions{TimestampBound: c.ReadOnlyStaleness(), BeginTransactionOption: c.convertDefaultBeginTransactionOption(propertyBeginTransactionOption.GetValueOrDefault(c.state))} } func (c *conn) withTempBatchReadOnlyTransactionOptions(options *BatchReadOnlyTransactionOptions) { - c.tempBatchReadOnlyTransactionOptions = options + if options == nil { + return + } + c.tempTransactionCloseFunc = options.close + // Start a transaction for the connection state, so we can set the transaction options + // as local options in the current transaction. + _ = c.state.Begin() + if options.TimestampBound.String() != "(strong)" { + _ = propertyReadOnlyStaleness.SetLocalValue(c.state, options.TimestampBound) + } } func (c *conn) getBatchReadOnlyTransactionOptions() BatchReadOnlyTransactionOptions { - if c.tempBatchReadOnlyTransactionOptions != nil { - defer func() { c.tempBatchReadOnlyTransactionOptions = nil }() - return *c.tempBatchReadOnlyTransactionOptions - } return BatchReadOnlyTransactionOptions{TimestampBound: c.ReadOnlyStaleness()} } @@ -1108,7 +1143,6 @@ func (c *conn) BeginReadOnlyTransaction(ctx context.Context, options *ReadOnlyTr c.withTempReadOnlyTransactionOptions(options) tx, err := c.BeginTx(ctx, driver.TxOptions{ReadOnly: true}) if err != nil { - c.withTempReadOnlyTransactionOptions(nil) return nil, err } return tx, nil @@ -1122,7 +1156,6 @@ func (c *conn) BeginReadWriteTransaction(ctx context.Context, options *ReadWrite c.withTempTransactionOptions(options) tx, err := c.BeginTx(ctx, driver.TxOptions{}) if err != nil { - c.withTempTransactionOptions(nil) return nil, err } return tx, nil @@ -1133,6 +1166,13 @@ func (c *conn) Begin() (driver.Tx, error) { } func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver.Tx, error) { + defer func() { + c.tempTransactionCloseFunc = nil + }() + return c.beginTx(ctx, driverOpts, c.tempTransactionCloseFunc) +} + +func (c *conn) beginTx(ctx context.Context, driverOpts driver.TxOptions, closeFunc func()) (driver.Tx, error) { if c.resetForRetry { c.resetForRetry = false return c.tx, nil @@ -1141,6 +1181,10 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver defer func() { if c.tx != nil { _ = c.state.Begin() + } else { + // Rollback in case the connection state transaction was started before this function + // was called, for example if the caller set temporary transaction options. + _ = c.state.Rollback() } }() @@ -1180,6 +1224,9 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver if batchReadOnly && !driverOpts.ReadOnly { return nil, status.Error(codes.InvalidArgument, "levelBatchReadOnly can only be used for read-only transactions") } + if closeFunc == nil { + closeFunc = func() {} + } if driverOpts.ReadOnly { var logger *slog.Logger @@ -1188,6 +1235,8 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver if batchReadOnly { logger = c.logger.With("tx", "batchro") var err error + // BatchReadOnly transactions (currently) do not support inline-begin. + // This means that the transaction options must be supplied here, and not through a callback. bo, err = c.client.BatchReadOnlyTransaction(ctx, batchReadOnlyTxOpts.TimestampBound) if err != nil { return nil, err @@ -1195,19 +1244,14 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver ro = &bo.ReadOnlyTransaction } else { logger = c.logger.With("tx", "ro") - ro = c.client.ReadOnlyTransaction().WithBeginTransactionOption(readOnlyTxOpts.BeginTransactionOption).WithTimestampBound(readOnlyTxOpts.TimestampBound) + ro = c.client.ReadOnlyTransaction().WithBeginTransactionOption(readOnlyTxOpts.BeginTransactionOption) } c.tx = &readOnlyTransaction{ roTx: ro, boTx: bo, logger: logger, close: func(result txResult) { - if batchReadOnlyTxOpts.close != nil { - batchReadOnlyTxOpts.close() - } - if readOnlyTxOpts.close != nil { - readOnlyTxOpts.close() - } + closeFunc() if result == txResultCommit { _ = c.state.Commit() } else { @@ -1215,22 +1259,23 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver } c.tx = nil }, + timestampBoundCallback: func() spanner.TimestampBound { + return propertyReadOnlyStaleness.GetValueOrDefault(c.state) + }, } return c.tx, nil } + // These options are only used to determine how to start the transaction. + // All other options are fetched in a callback that is called when the transaction is actually started. + // That callback reads all transaction options from the connection state at that moment. This allows + // applications to execute a series of statement like this: + // BEGIN TRANSACTION; + // SET LOCAL transaction_tag='my_tag'; + // SET LOCAL commit_priority=LOW; + // INSERT INTO my_table ... -- This starts the transaction with the options above included. opts := spanner.TransactionOptions{} - if c.tempTransactionOptions != nil { - opts = c.tempTransactionOptions.TransactionOptions - } - opts.BeginTransactionOption = c.convertDefaultBeginTransactionOption(opts.BeginTransactionOption) - tempCloseFunc := func() {} - if c.tempTransactionOptions != nil && c.tempTransactionOptions.close != nil { - tempCloseFunc = c.tempTransactionOptions.close - } - if !disableRetryAborts && c.tempTransactionOptions != nil { - disableRetryAborts = c.tempTransactionOptions.DisableInternalRetries - } + opts.BeginTransactionOption = c.convertDefaultBeginTransactionOption(propertyBeginTransactionOption.GetValueOrDefault(c.state)) tx, err := spanner.NewReadWriteStmtBasedTransactionWithCallbackForOptions(ctx, c.client, opts, func() spanner.TransactionOptions { defer func() { @@ -1249,7 +1294,7 @@ func (c *conn) BeginTx(ctx context.Context, driverOpts driver.TxOptions) (driver logger: logger, rwTx: tx, close: func(result txResult, commitResponse *spanner.CommitResponse, commitErr error) { - tempCloseFunc() + closeFunc() c.prevTx = c.tx c.tx = nil if commitErr == nil { diff --git a/connection_properties.go b/connection_properties.go index ad1bdff1..73465dc7 100644 --- a/connection_properties.go +++ b/connection_properties.go @@ -257,6 +257,27 @@ var propertyMaxCommitDelay = createConnectionProperty( connectionstate.ContextUser, connectionstate.ConvertDuration, ) +var propertyCommitPriority = createConnectionProperty( + "commit_priority", + "Sets the priority for commit RPC invocations from this connection (HIGH/MEDIUM/LOW/UNSPECIFIED). "+ + "The default is UNSPECIFIED.", + spannerpb.RequestOptions_PRIORITY_UNSPECIFIED, + false, + nil, + connectionstate.ContextUser, + func(value string) (spannerpb.RequestOptions_Priority, error) { + return parseRpcPriority(value) + }, +) +var propertyReturnCommitStats = createConnectionProperty( + "return_commit_stats", + "return_commit_stats determines whether transactions should request Spanner to return commit statistics.", + false, + false, + nil, + connectionstate.ContextUser, + connectionstate.ConvertBool, +) // ------------------------------------------------------------------------------------------------ // Statement connection properties. diff --git a/driver.go b/driver.go index 2ccaafb6..7ac7400f 100644 --- a/driver.go +++ b/driver.go @@ -1156,7 +1156,6 @@ func BeginReadWriteTransaction(ctx context.Context, db *sql.DB, options ReadWrit } tx, err := conn.BeginTx(ctx, &sql.TxOptions{}) if err != nil { - clearTempReadWriteTransactionOptions(conn) return nil, err } return tx, nil @@ -1174,11 +1173,6 @@ func withTempReadWriteTransactionOptions(conn *sql.Conn, options *ReadWriteTrans }) } -func clearTempReadWriteTransactionOptions(conn *sql.Conn) { - _ = withTempReadWriteTransactionOptions(conn, nil) - _ = conn.Close() -} - // ReadOnlyTransactionOptions can be used to create a read-only transaction // on a Spanner connection. type ReadOnlyTransactionOptions struct { @@ -1537,6 +1531,24 @@ func toProtoIsolationLevelOrDefault(level sql.IsolationLevel) spannerpb.Transact return res } +func toSqlIsolationLevel(level spannerpb.TransactionOptions_IsolationLevel) (sql.IsolationLevel, error) { + switch level { + case spannerpb.TransactionOptions_ISOLATION_LEVEL_UNSPECIFIED: + return sql.LevelDefault, nil + case spannerpb.TransactionOptions_SERIALIZABLE: + return sql.LevelSerializable, nil + case spannerpb.TransactionOptions_REPEATABLE_READ: + return sql.LevelRepeatableRead, nil + default: + } + return sql.LevelDefault, spanner.ToSpannerError(status.Errorf(codes.InvalidArgument, "invalid or unsupported isolation level: %v", level)) +} + +func toSqlIsolationLevelOrDefault(level spannerpb.TransactionOptions_IsolationLevel) sql.IsolationLevel { + res, _ := toSqlIsolationLevel(level) + return res +} + type spannerIsolationLevel sql.IsolationLevel const ( diff --git a/driver_with_mockserver_test.go b/driver_with_mockserver_test.go index ac9cbf79..209c1fa1 100644 --- a/driver_with_mockserver_test.go +++ b/driver_with_mockserver_test.go @@ -5076,7 +5076,7 @@ func TestBeginReadWriteTransaction(t *testing.T) { t.Fatalf("missing transaction for ExecuteSqlRequest") } if req.Transaction.GetId() == nil { - t.Fatalf("missing begin selector for ExecuteSqlRequest") + t.Fatalf("missing ID selector for ExecuteSqlRequest") } if g, w := req.RequestOptions.TransactionTag, tag; g != w { t.Fatalf("transaction tag mismatch\n Got: %v\nWant: %v", g, w) diff --git a/spannerlib/api/transaction_test.go b/spannerlib/api/transaction_test.go index 1f0ec81d..efb6c993 100644 --- a/spannerlib/api/transaction_test.go +++ b/spannerlib/api/transaction_test.go @@ -24,6 +24,7 @@ import ( "cloud.google.com/go/spanner/apiv1/spannerpb" "github.com/googleapis/go-sql-spanner/testutil" "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) func TestBeginAndCommit(t *testing.T) { @@ -409,3 +410,166 @@ func TestDdlInTransaction(t *testing.T) { t.Fatalf("ClosePool returned unexpected error: %v", err) } } + +func TestTransactionOptionsAsSqlStatements(t *testing.T) { + t.Parallel() + + ctx := context.Background() + server, teardown := setupMockServer(t) + defer teardown() + dsn := fmt.Sprintf("%s/projects/p/instances/i/databases/d?useplaintext=true", server.Address) + + poolId, err := CreatePool(ctx, dsn) + if err != nil { + t.Fatalf("CreatePool returned unexpected error: %v", err) + } + connId, err := CreateConnection(ctx, poolId) + if err != nil { + t.Fatalf("CreateConnection returned unexpected error: %v", err) + } + if err := BeginTransaction(ctx, poolId, connId, &spannerpb.TransactionOptions{}); err != nil { + t.Fatalf("BeginTransaction returned unexpected error: %v", err) + } + + // Set some local transaction options. + if rowsId, err := Execute(ctx, poolId, connId, &spannerpb.ExecuteSqlRequest{Sql: "set local transaction_tag = 'my_tag'"}); err != nil { + t.Fatalf("setting transaction_tag returned unexpected error: %v", err) + } else { + _ = CloseRows(ctx, poolId, connId, rowsId) + } + if rowsId, err := Execute(ctx, poolId, connId, &spannerpb.ExecuteSqlRequest{Sql: "set local retry_aborts_internally = false"}); err != nil { + t.Fatalf("setting retry_aborts_internally returned unexpected error: %v", err) + } else { + _ = CloseRows(ctx, poolId, connId, rowsId) + } + + // Execute a statement in the transaction. + if rowsId, err := Execute(ctx, poolId, connId, &spannerpb.ExecuteSqlRequest{Sql: testutil.UpdateBarSetFoo}); err != nil { + t.Fatalf("Execute returned unexpected error: %v", err) + } else { + _ = CloseRows(ctx, poolId, connId, rowsId) + } + + // Abort the transaction to verify that the retry_aborts_internally setting was respected. + server.TestSpanner.PutExecutionTime(testutil.MethodCommitTransaction, testutil.SimulatedExecutionTime{ + Errors: []error{status.Error(codes.Aborted, "Aborted")}, + }) + + // Commit the transaction. This should fail with an Aborted error. + if _, err := Commit(ctx, poolId, connId); err == nil { + t.Fatal("missing expected error") + } else { + if g, w := spanner.ErrCode(err), codes.Aborted; g != w { + t.Fatalf("error code mismatch\n Got: %v\nWant: %v", g, w) + } + } + + // Verify that the transaction_tag setting was respected. + requests := server.TestSpanner.DrainRequestsFromServer() + executeRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.ExecuteSqlRequest{})) + if g, w := len(executeRequests), 1; g != w { + t.Fatalf("Execute request count mismatch\n Got: %v\nWant: %v", g, w) + } + executeRequest := executeRequests[0].(*spannerpb.ExecuteSqlRequest) + if executeRequest.RequestOptions == nil { + t.Fatalf("Execute request options not set") + } + if g, w := executeRequest.RequestOptions.TransactionTag, "my_tag"; g != w { + t.Fatalf("TransactionTag mismatch\n Got: %v\nWant: %v", g, w) + } + commitRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.CommitRequest{})) + if g, w := len(commitRequests), 1; g != w { + t.Fatalf("Commit request count mismatch\n Got: %v\nWant: %v", g, w) + } + commitRequest := commitRequests[0].(*spannerpb.CommitRequest) + if commitRequest.RequestOptions == nil { + t.Fatalf("Commit request options not set") + } + if g, w := commitRequest.RequestOptions.TransactionTag, "my_tag"; g != w { + t.Fatalf("TransactionTag mismatch\n Got: %v\nWant: %v", g, w) + } + + if err := CloseConnection(ctx, poolId, connId); err != nil { + t.Fatalf("CloseConnection returned unexpected error: %v", err) + } + if err := ClosePool(ctx, poolId); err != nil { + t.Fatalf("ClosePool returned unexpected error: %v", err) + } +} + +func TestReadOnlyTransactionOptionsAsSqlStatements(t *testing.T) { + t.Parallel() + + ctx := context.Background() + server, teardown := setupMockServer(t) + defer teardown() + dsn := fmt.Sprintf("%s/projects/p/instances/i/databases/d?useplaintext=true", server.Address) + + poolId, err := CreatePool(ctx, dsn) + if err != nil { + t.Fatalf("CreatePool returned unexpected error: %v", err) + } + connId, err := CreateConnection(ctx, poolId) + if err != nil { + t.Fatalf("CreateConnection returned unexpected error: %v", err) + } + // Start a read-only transaction without any further options. + if err := BeginTransaction(ctx, poolId, connId, &spannerpb.TransactionOptions{ + Mode: &spannerpb.TransactionOptions_ReadOnly_{ + ReadOnly: &spannerpb.TransactionOptions_ReadOnly{}, + }, + }); err != nil { + t.Fatalf("BeginTransaction returned unexpected error: %v", err) + } + + // Set a local read-only transaction options. + if rowsId, err := Execute(ctx, poolId, connId, &spannerpb.ExecuteSqlRequest{Sql: "set local read_only_staleness = 'exact_staleness 10s'"}); err != nil { + t.Fatalf("setting read_only_staleness returned unexpected error: %v", err) + } else { + _ = CloseRows(ctx, poolId, connId, rowsId) + } + + // Execute a statement in the transaction. + if rowsId, err := Execute(ctx, poolId, connId, &spannerpb.ExecuteSqlRequest{Sql: testutil.SelectFooFromBar}); err != nil { + t.Fatalf("Execute returned unexpected error: %v", err) + } else { + _ = CloseRows(ctx, poolId, connId, rowsId) + } + + // Commit the transaction to end it. + if _, err := Commit(ctx, poolId, connId); err != nil { + t.Fatalf("commit returned unexpected error: %v", err) + } + + // Verify that the read-only staleness setting was used. + requests := server.TestSpanner.DrainRequestsFromServer() + executeRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.ExecuteSqlRequest{})) + if g, w := len(executeRequests), 1; g != w { + t.Fatalf("Execute request count mismatch\n Got: %v\nWant: %v", g, w) + } + executeRequest := executeRequests[0].(*spannerpb.ExecuteSqlRequest) + if executeRequest.GetTransaction() == nil || executeRequest.GetTransaction().GetBegin() == nil || executeRequest.GetTransaction().GetBegin().GetReadOnly() == nil { + t.Fatal("ExecuteRequest does not contain a BeginTransaction option") + } + + readOnly := executeRequest.GetTransaction().GetBegin().GetReadOnly() + if readOnly.GetExactStaleness() == nil { + t.Fatal("BeginTransaction does not contain a ExactStaleness option") + } + if g, w := readOnly.GetExactStaleness().GetSeconds(), int64(10); g != w { + t.Fatalf("read staleness mismatch\n Got: %v\nWant: %v", g, w) + } + + // There should be no commit requests, as committing a read-only transaction is a no-op on Spanner. + commitRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.CommitRequest{})) + if g, w := len(commitRequests), 0; g != w { + t.Fatalf("Commit request count mismatch\n Got: %v\nWant: %v", g, w) + } + + if err := CloseConnection(ctx, poolId, connId); err != nil { + t.Fatalf("CloseConnection returned unexpected error: %v", err) + } + if err := ClosePool(ctx, poolId); err != nil { + t.Fatalf("ClosePool returned unexpected error: %v", err) + } +} diff --git a/transaction.go b/transaction.go index a2db9634..297c6b60 100644 --- a/transaction.go +++ b/transaction.go @@ -22,6 +22,7 @@ import ( "fmt" "log/slog" "math/rand" + "sync" "time" "cloud.google.com/go/spanner" @@ -112,6 +113,10 @@ type readOnlyTransaction struct { boTx *spanner.BatchReadOnlyTransaction logger *slog.Logger close func(result txResult) + + timestampBoundMu sync.Mutex + timestampBoundSet bool + timestampBoundCallback func() spanner.TimestampBound } func (tx *readOnlyTransaction) Commit() error { @@ -160,6 +165,14 @@ func (tx *readOnlyTransaction) Query(ctx context.Context, stmt spanner.Statement } return mi, nil } + if tx.timestampBoundCallback != nil { + tx.timestampBoundMu.Lock() + if !tx.timestampBoundSet { + tx.roTx.WithTimestampBound(tx.timestampBoundCallback()) + tx.timestampBoundSet = true + } + tx.timestampBoundMu.Unlock() + } return &readOnlyRowIterator{tx.roTx.QueryWithOptions(ctx, stmt, execOptions.QueryOptions), stmtType}, nil } From 6a396d35be5b7ccbc5bb0e1cae5ad503ed705e5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 7 Oct 2025 19:00:43 +0200 Subject: [PATCH 13/15] feat: parse SET TRANSACTION statements (#549) * feat: parse SET TRANSACTION statements Parse SET TRANSACTION statements and translate these to SET LOCAL statements. SET TRANSACTION may only be executed in a transaction block, and can only be used for a specific, limited set of connection properties. The syntax is specified by the SQL standard and PostgreSQL. See also https://www.postgresql.org/docs/current/sql-set-transaction.html This change only adds partial support. The following features will be added in future changes: 1. SET TRANSACTION READ {WRITE | ONLY} is not picked up by the driver, as the type of transaction is set directly when BeginTx is called. A refactor of this transaction handling is needed to be able to pick up SET TRANSACTION READ ONLY / SET TRANSACTION READ WRITE statements that are executed after BeginTx has been called. 2. PostgreSQL allows multiple transaction modes to be set in a single SET TRANSACTION statement. E.g. the following is allowed: SET TRANSACTION READ WRITE, ISOLATION LEVEL SERIALIZABLE The current implementation only supports one transaction mode per SET statement. * feat: support multiple transaction options in one statement --- conn.go | 11 +- connection_properties.go | 18 ++ connectionstate/connection_state.go | 5 +- parser/simple_parser.go | 14 +- parser/statement_parser_test.go | 34 ++++ parser/statements.go | 121 +++++++++++++- parser/statements_test.go | 251 +++++++++++++++++++++++----- statements.go | 20 ++- transaction_test.go | 107 ++++++++++++ 9 files changed, 522 insertions(+), 59 deletions(-) create mode 100644 transaction_test.go diff --git a/conn.go b/conn.go index 7b7e5102..d35b238d 100644 --- a/conn.go +++ b/conn.go @@ -327,13 +327,18 @@ func (c *conn) showConnectionVariable(identifier parser.Identifier) (any, bool, return c.state.GetValue(extension, name) } -func (c *conn) setConnectionVariable(identifier parser.Identifier, value string, local bool) error { +func (c *conn) setConnectionVariable(identifier parser.Identifier, value string, local bool, transaction bool) error { + if transaction && !local { + // When transaction == true, then local must also be true. + // We should never hit this condition, as this is an indication of a bug in the driver code. + return status.Errorf(codes.FailedPrecondition, "transaction properties must be set as a local value") + } extension, name, err := toExtensionAndName(identifier) if err != nil { return err } if local { - return c.state.SetLocalValue(extension, name, value) + return c.state.SetLocalValue(extension, name, value, transaction) } return c.state.SetValue(extension, name, value, connectionstate.ContextUser) } @@ -1188,6 +1193,8 @@ func (c *conn) beginTx(ctx context.Context, driverOpts driver.TxOptions, closeFu } }() + // TODO: Delay the actual determination of the transaction type until the first query. + // This is required in order to support SET TRANSACTION READ {ONLY | WRITE} readOnlyTxOpts := c.getReadOnlyTransactionOptions() batchReadOnlyTxOpts := c.getBatchReadOnlyTransactionOptions() if c.inTransaction() { diff --git a/connection_properties.go b/connection_properties.go index 73465dc7..6d65e02e 100644 --- a/connection_properties.go +++ b/connection_properties.go @@ -228,6 +228,24 @@ var propertyDecodeToNativeArrays = createConnectionProperty( // Transaction connection properties. // ------------------------------------------------------------------------------------------------ +var propertyTransactionReadOnly = createConnectionProperty( + "transaction_read_only", + "transaction_read_only is the default read-only mode for transactions on this connection.", + false, + false, + nil, + connectionstate.ContextUser, + connectionstate.ConvertBool, +) +var propertyTransactionDeferrable = createConnectionProperty( + "transaction_deferrable", + "transaction_deferrable is a no-op on Spanner. It is defined in this driver for compatibility with PostgreSQL.", + false, + false, + nil, + connectionstate.ContextUser, + connectionstate.ConvertBool, +) var propertyExcludeTxnFromChangeStreams = createConnectionProperty( "exclude_txn_from_change_streams", "exclude_txn_from_change_streams determines whether transactions on this connection should be excluded from "+ diff --git a/connectionstate/connection_state.go b/connectionstate/connection_state.go index 6fd7131d..77417eea 100644 --- a/connectionstate/connection_state.go +++ b/connectionstate/connection_state.go @@ -131,7 +131,10 @@ func (cs *ConnectionState) SetValue(extension, name, value string, context Conte return cs.setValue(extension, name, value, context, false) } -func (cs *ConnectionState) SetLocalValue(extension, name, value string) error { +func (cs *ConnectionState) SetLocalValue(extension, name, value string, isSetTransaction bool) error { + if isSetTransaction && !cs.inTransaction { + return status.Error(codes.FailedPrecondition, "SET TRANSACTION can only be used in transaction blocks") + } return cs.setValue(extension, name, value, ContextUser, true) } diff --git a/parser/simple_parser.go b/parser/simple_parser.go index 9a2da379..e8fef032 100644 --- a/parser/simple_parser.go +++ b/parser/simple_parser.go @@ -290,6 +290,16 @@ func (p *simpleParser) eatKeywords(keywords []string) bool { return true } +// peekKeyword checks if the next keyword is the given keyword. +// The position of the parser is not updated. +func (p *simpleParser) peekKeyword(keyword string) bool { + pos := p.pos + defer func() { + p.pos = pos + }() + return p.eatKeyword(keyword) +} + // eatKeyword eats the given keyword at the current position of the parser if it exists // and returns true if the keyword was found. Otherwise, it returns false. func (p *simpleParser) eatKeyword(keyword string) bool { @@ -323,8 +333,8 @@ func (p *simpleParser) readKeyword() string { if isSpace(p.sql[p.pos]) { break } - // Only upper/lower-case letters are allowed in keywords. - if !((p.sql[p.pos] >= 'A' && p.sql[p.pos] <= 'Z') || (p.sql[p.pos] >= 'a' && p.sql[p.pos] <= 'z')) { + // Only upper/lower-case letters and underscores are allowed in keywords. + if !((p.sql[p.pos] >= 'A' && p.sql[p.pos] <= 'Z') || (p.sql[p.pos] >= 'a' && p.sql[p.pos] <= 'z')) && p.sql[p.pos] != '_' { break } } diff --git a/parser/statement_parser_test.go b/parser/statement_parser_test.go index ed50be2b..2ab64399 100644 --- a/parser/statement_parser_test.go +++ b/parser/statement_parser_test.go @@ -2135,6 +2135,10 @@ func TestReadKeyword(t *testing.T) { input: "Select from my_table", want: "Select", }, + { + input: "statement_tag", + want: "statement_tag", + }, } statementParser, err := NewStatementParser(databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL, 1000) if err != nil { @@ -2404,6 +2408,36 @@ func TestCachedParamsAreImmutable(t *testing.T) { } } +func TestPeekKeyword(t *testing.T) { + t.Parallel() + + parser, err := NewStatementParser(databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL, 1000) + if err != nil { + t.Fatal(err) + } + sp := &simpleParser{sql: []byte("select * from foo"), statementParser: parser} + if !sp.peekKeyword("select") { + t.Fatal("peekKeyword should have returned true") + } + if g, w := sp.pos, 0; g != w { + t.Fatalf("position mismatch\n Got: %v\nWant: %v", g, w) + } + + if !sp.eatKeyword("select") { + t.Fatal("eatKeyword should have returned true") + } + if !sp.eatToken('*') { + t.Fatal("eatToken should have returned true") + } + pos := sp.pos + if !sp.peekKeyword("from") { + t.Fatal("peekKeyword should have returned true") + } + if g, w := sp.pos, pos; g != w { + t.Fatalf("position mismatch\n Got: %v\nWant: %v", g, w) + } +} + func TestEatKeyword(t *testing.T) { t.Parallel() diff --git a/parser/statements.go b/parser/statements.go index 2dc1ce93..56307399 100644 --- a/parser/statements.go +++ b/parser/statements.go @@ -15,6 +15,8 @@ package parser import ( + "fmt" + "cloud.google.com/go/spanner/admin/database/apiv1/databasepb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -142,11 +144,27 @@ func (s *ParsedShowStatement) parse(parser *StatementParser, query string) error // ParsedSetStatement is a statement of the form // SET [SESSION | LOCAL] [my_extension.]my_property {=|to} +// +// It also covers statements of the form SET TRANSACTION. This is a +// synonym for SET LOCAL, but is only supported for a specific set of +// properties, and may only be executed before a transaction has been +// activated. Examples include: +// SET TRANSACTION READ ONLY +// SET TRANSACTION ISOLATION LEVEL [SERIALIZABLE | REPEATABLE READ] +// +// One SET statement can set more than one property. type ParsedSetStatement struct { - query string - Identifier Identifier - Literal Literal - IsLocal bool + query string + // Identifiers contains the properties that are being set. The number of elements in this slice + // must be equal to the number of Literals. + Identifiers []Identifier + // Literals contains the values that should be set for the properties. + Literals []Literal + // IsLocal indicates whether this is a SET LOCAL statement or not. + IsLocal bool + // IsTransaction indicates whether this is a SET TRANSACTION statement or not. + // IsTransaction automatically also implies IsLocal. + IsTransaction bool } func (s *ParsedSetStatement) Name() string { @@ -165,10 +183,17 @@ func (s *ParsedSetStatement) parse(parser *StatementParser, query string) error return status.Errorf(codes.InvalidArgument, "syntax error: expected SET") } isLocal := sp.eatKeyword("LOCAL") - if !isLocal && parser.Dialect == databasepb.DatabaseDialect_POSTGRESQL { + isTransaction := false + if !isLocal { + isTransaction = sp.eatKeyword("TRANSACTION") + } + if !isLocal && !isTransaction && parser.Dialect == databasepb.DatabaseDialect_POSTGRESQL { // Just eat and ignore the SESSION keyword if it exists, as SESSION is the default. _ = sp.eatKeyword("SESSION") } + if isTransaction { + return s.parseSetTransaction(sp, query) + } identifier, err := sp.eatIdentifier() if err != nil { return err @@ -191,12 +216,93 @@ func (s *ParsedSetStatement) parse(parser *StatementParser, query string) error return status.Errorf(codes.InvalidArgument, "unexpected tokens at position %d in %q", sp.pos, sp.sql) } s.query = query - s.Identifier = identifier - s.Literal = literalValue + s.Identifiers = []Identifier{identifier} + s.Literals = []Literal{literalValue} s.IsLocal = isLocal return nil } +func (s *ParsedSetStatement) parseSetTransaction(sp *simpleParser, query string) error { + if !sp.hasMoreTokens() { + return status.Errorf(codes.InvalidArgument, "syntax error: missing TRANSACTION OPTION, expected one of ISOLATION LEVEL, READ WRITE, or READ ONLY") + } + s.query = query + s.IsLocal = true + s.IsTransaction = true + + for { + if sp.peekKeyword("ISOLATION") { + if err := s.parseSetTransactionIsolationLevel(sp, query); err != nil { + return err + } + } else if sp.peekKeyword("READ") { + if err := s.parseSetTransactionMode(sp, query); err != nil { + return err + } + } else if sp.statementParser.Dialect == databasepb.DatabaseDialect_POSTGRESQL && (sp.peekKeyword("DEFERRABLE") || sp.peekKeyword("NOT")) { + // https://www.postgresql.org/docs/current/sql-set-transaction.html + if err := s.parseSetTransactionDeferrable(sp, query); err != nil { + return err + } + } else { + return status.Error(codes.InvalidArgument, "invalid TRANSACTION option, expected one of ISOLATION LEVEL, READ WRITE, or READ ONLY") + } + if !sp.hasMoreTokens() { + return nil + } + // Eat and ignore any commas separating the various options. + sp.eatToken(',') + } +} + +func (s *ParsedSetStatement) parseSetTransactionIsolationLevel(sp *simpleParser, query string) error { + if !sp.eatKeywords([]string{"ISOLATION", "LEVEL"}) { + return status.Errorf(codes.InvalidArgument, "syntax error: expected ISOLATION LEVEL") + } + var value Literal + if sp.eatKeyword("SERIALIZABLE") { + value = Literal{Value: "serializable"} + } else if sp.eatKeywords([]string{"REPEATABLE", "READ"}) { + value = Literal{Value: "repeatable_read"} + } else { + return status.Errorf(codes.InvalidArgument, "syntax error: expected SERIALIZABLE OR REPETABLE READ") + } + + s.Identifiers = append(s.Identifiers, Identifier{Parts: []string{"isolation_level"}}) + s.Literals = append(s.Literals, value) + return nil +} + +func (s *ParsedSetStatement) parseSetTransactionMode(sp *simpleParser, query string) error { + readOnly := false + if sp.eatKeywords([]string{"READ", "ONLY"}) { + readOnly = true + } else if sp.eatKeywords([]string{"READ", "WRITE"}) { + readOnly = false + } else { + return status.Errorf(codes.InvalidArgument, "syntax error: expected READ ONLY or READ WRITE") + } + + s.Identifiers = append(s.Identifiers, Identifier{Parts: []string{"transaction_read_only"}}) + s.Literals = append(s.Literals, Literal{Value: fmt.Sprintf("%v", readOnly)}) + return nil +} + +func (s *ParsedSetStatement) parseSetTransactionDeferrable(sp *simpleParser, query string) error { + deferrable := false + if sp.eatKeywords([]string{"NOT", "DEFERRABLE"}) { + deferrable = false + } else if sp.eatKeyword("DEFERRABLE") { + deferrable = true + } else { + return status.Errorf(codes.InvalidArgument, "syntax error: expected [NOT] DEFERRABLE") + } + + s.Identifiers = append(s.Identifiers, Identifier{Parts: []string{"transaction_deferrable"}}) + s.Literals = append(s.Literals, Literal{Value: fmt.Sprintf("%v", deferrable)}) + return nil +} + // ParsedResetStatement is a statement of the form // RESET [my_extension.]my_property type ParsedResetStatement struct { @@ -404,6 +510,7 @@ func (s *ParsedBeginStatement) parse(parser *StatementParser, query string) erro // Parse a statement of the form // GoogleSQL: BEGIN [TRANSACTION] // PostgreSQL: {START | BEGIN} [{TRANSACTION | WORK}] (https://www.postgresql.org/docs/current/sql-begin.html) + // TODO: Support transaction modes in the BEGIN / START statement. sp := &simpleParser{sql: []byte(query), statementParser: parser} if sp.statementParser.Dialect == databasepb.DatabaseDialect_POSTGRESQL { if !sp.eatKeyword("START") && !sp.eatKeyword("BEGIN") { diff --git a/parser/statements_test.go b/parser/statements_test.go index a7bb1d1c..91fada7e 100644 --- a/parser/statements_test.go +++ b/parser/statements_test.go @@ -15,6 +15,7 @@ package parser import ( + "fmt" "reflect" "strings" "testing" @@ -128,56 +129,218 @@ func TestParseSetStatement(t *testing.T) { type test struct { input string want ParsedSetStatement + onlyPg bool wantErr bool } tests := []test{ { input: "set my_property = 'foo'", want: ParsedSetStatement{ - query: "set my_property = 'foo'", - Identifier: Identifier{Parts: []string{"my_property"}}, - Literal: Literal{Value: "foo"}, + query: "set my_property = 'foo'", + Identifiers: []Identifier{{Parts: []string{"my_property"}}}, + Literals: []Literal{{Value: "foo"}}, }, }, { input: "set local my_property = 'foo'", want: ParsedSetStatement{ - query: "set local my_property = 'foo'", - Identifier: Identifier{Parts: []string{"my_property"}}, - Literal: Literal{Value: "foo"}, - IsLocal: true, + query: "set local my_property = 'foo'", + Identifiers: []Identifier{{Parts: []string{"my_property"}}}, + Literals: []Literal{{Value: "foo"}}, + IsLocal: true, }, }, { input: "set my_property = 1", want: ParsedSetStatement{ - query: "set my_property = 1", - Identifier: Identifier{Parts: []string{"my_property"}}, - Literal: Literal{Value: "1"}, + query: "set my_property = 1", + Identifiers: []Identifier{{Parts: []string{"my_property"}}}, + Literals: []Literal{{Value: "1"}}, }, }, { input: "set my_property = true", want: ParsedSetStatement{ - query: "set my_property = true", - Identifier: Identifier{Parts: []string{"my_property"}}, - Literal: Literal{Value: "true"}, + query: "set my_property = true", + Identifiers: []Identifier{{Parts: []string{"my_property"}}}, + Literals: []Literal{{Value: "true"}}, }, }, { input: "set \n -- comment \n my_property /* yet more comments */ = \ntrue/*comment*/ ", want: ParsedSetStatement{ - query: "set \n -- comment \n my_property /* yet more comments */ = \ntrue/*comment*/ ", - Identifier: Identifier{Parts: []string{"my_property"}}, - Literal: Literal{Value: "true"}, + query: "set \n -- comment \n my_property /* yet more comments */ = \ntrue/*comment*/ ", + Identifiers: []Identifier{{Parts: []string{"my_property"}}}, + Literals: []Literal{{Value: "true"}}, }, }, { input: "set \n -- comment \n a.b /* yet more comments */ =\n/*comment*/'value'/*comment*/ ", want: ParsedSetStatement{ - query: "set \n -- comment \n a.b /* yet more comments */ =\n/*comment*/'value'/*comment*/ ", - Identifier: Identifier{Parts: []string{"a", "b"}}, - Literal: Literal{Value: "value"}, + query: "set \n -- comment \n a.b /* yet more comments */ =\n/*comment*/'value'/*comment*/ ", + Identifiers: []Identifier{{Parts: []string{"a", "b"}}}, + Literals: []Literal{{Value: "value"}}, + }, + }, + { + input: "set transaction isolation level serializable", + want: ParsedSetStatement{ + query: "set transaction isolation level serializable", + Identifiers: []Identifier{{Parts: []string{"isolation_level"}}}, + Literals: []Literal{{Value: "serializable"}}, + IsLocal: true, + IsTransaction: true, + }, + }, + { + input: "set transaction isolation serializable", + wantErr: true, + }, + { + input: "set transaction isolation level serializable foo", + wantErr: true, + }, + { + input: "set isolation level serializable", + wantErr: true, + }, + { + input: "set transaction isolation level serialisable", + wantErr: true, + }, + { + input: "set transaction isolation level repeatable read", + want: ParsedSetStatement{ + query: "set transaction isolation level repeatable read", + Identifiers: []Identifier{{Parts: []string{"isolation_level"}}}, + Literals: []Literal{{Value: "repeatable_read"}}, + IsLocal: true, + IsTransaction: true, + }, + }, + { + input: "set transaction isolation level repeatable", + wantErr: true, + }, + { + input: "set transaction isolation level read", + wantErr: true, + }, + { + input: "set transaction isolation level repeatable read serializable", + wantErr: true, + }, + { + input: "set transaction isolation level serializable repeatable read", + wantErr: true, + }, + { + input: "set transaction read write", + want: ParsedSetStatement{ + query: "set transaction read write", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "false"}}, + IsLocal: true, + IsTransaction: true, + }, + }, + { + input: "set transaction read write isolation level serializable", + want: ParsedSetStatement{ + query: "set transaction read write isolation level serializable", + Identifiers: []Identifier{ + {Parts: []string{"transaction_read_only"}}, + {Parts: []string{"isolation_level"}}, + }, + Literals: []Literal{ + {Value: "false"}, + {Value: "serializable"}, + }, + IsLocal: true, + IsTransaction: true, + }, + }, + { + input: "set transaction read only, isolation level repeatable read", + want: ParsedSetStatement{ + query: "set transaction read only, isolation level repeatable read", + Identifiers: []Identifier{ + {Parts: []string{"transaction_read_only"}}, + {Parts: []string{"isolation_level"}}, + }, + Literals: []Literal{ + {Value: "true"}, + {Value: "repeatable_read"}, + }, + IsLocal: true, + IsTransaction: true, + }, + }, + { + onlyPg: true, + input: "set transaction read only, isolation level repeatable read not deferrable", + want: ParsedSetStatement{ + query: "set transaction read only, isolation level repeatable read not deferrable", + Identifiers: []Identifier{ + {Parts: []string{"transaction_read_only"}}, + {Parts: []string{"isolation_level"}}, + {Parts: []string{"transaction_deferrable"}}, + }, + Literals: []Literal{ + {Value: "true"}, + {Value: "repeatable_read"}, + {Value: "false"}, + }, + IsLocal: true, + IsTransaction: true, + }, + }, + { + input: "set transaction read only", + want: ParsedSetStatement{ + query: "set transaction read only", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "true"}}, + IsLocal: true, + IsTransaction: true, + }, + }, + { + input: "set transaction read", + wantErr: true, + }, + { + input: "set transaction write", + wantErr: true, + }, + { + input: "set transaction read only write", + wantErr: true, + }, + { + input: "set transaction write only", + wantErr: true, + }, + { + onlyPg: true, + input: "set transaction deferrable", + want: ParsedSetStatement{ + query: "set transaction deferrable", + Identifiers: []Identifier{{Parts: []string{"transaction_deferrable"}}}, + Literals: []Literal{{Value: "true"}}, + IsLocal: true, + IsTransaction: true, + }, + }, + { + onlyPg: true, + input: "set transaction not deferrable", + want: ParsedSetStatement{ + query: "set transaction not deferrable", + Identifiers: []Identifier{{Parts: []string{"transaction_deferrable"}}}, + Literals: []Literal{{Value: "false"}}, + IsLocal: true, + IsTransaction: true, }, }, { @@ -205,31 +368,33 @@ func TestParseSetStatement(t *testing.T) { wantErr: true, }, } - parser, err := NewStatementParser(databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL, 1000) - if err != nil { - t.Fatal(err) - } - keyword := "SET" - for _, test := range tests { - t.Run(test.input, func(t *testing.T) { - stmt, err := parseStatement(parser, keyword, test.input) - if test.wantErr { - if err == nil { - t.Fatalf("parseStatement(%q) should have failed", test.input) - } - } else { - if err != nil { - t.Fatal(err) - } - showStmt, ok := stmt.(*ParsedSetStatement) - if !ok { - t.Fatalf("parseStatement(%q) should have returned a *parsedSetStatement", test.input) - } - if !reflect.DeepEqual(*showStmt, test.want) { - t.Errorf("parseStatement(%q) = %v, want %v", test.input, *showStmt, test.want) + for _, dialect := range []databasepb.DatabaseDialect{databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL, databasepb.DatabaseDialect_POSTGRESQL} { + parser, err := NewStatementParser(dialect, 1000) + if err != nil { + t.Fatal(err) + } + keyword := "SET" + for _, test := range tests { + t.Run(fmt.Sprintf("%s %s", dialect, test.input), func(t *testing.T) { + stmt, err := parseStatement(parser, keyword, test.input) + if test.wantErr || (test.onlyPg && dialect == databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL) { + if err == nil { + t.Fatalf("parseStatement(%q) should have failed", test.input) + } + } else { + if err != nil { + t.Fatal(err) + } + showStmt, ok := stmt.(*ParsedSetStatement) + if !ok { + t.Fatalf("parseStatement(%q) should have returned a *parsedSetStatement", test.input) + } + if !reflect.DeepEqual(*showStmt, test.want) { + t.Errorf("parseStatement(%q) = %v, want %v", test.input, *showStmt, test.want) + } } - } - }) + }) + } } } diff --git a/statements.go b/statements.go index f7232a7b..2c7c7a7a 100644 --- a/statements.go +++ b/statements.go @@ -112,33 +112,45 @@ type executableSetStatement struct { } func (s *executableSetStatement) execContext(ctx context.Context, c *conn, opts *ExecOptions) (driver.Result, error) { - if err := c.setConnectionVariable(s.stmt.Identifier, s.stmt.Literal.Value, s.stmt.IsLocal); err != nil { + if err := s.execute(c); err != nil { return nil, err } return driver.ResultNoRows, nil } func (s *executableSetStatement) queryContext(ctx context.Context, c *conn, opts *ExecOptions) (driver.Rows, error) { - if err := c.setConnectionVariable(s.stmt.Identifier, s.stmt.Literal.Value, s.stmt.IsLocal); err != nil { + if err := s.execute(c); err != nil { return nil, err } return createEmptyRows(opts), nil } +func (s *executableSetStatement) execute(c *conn) error { + if len(s.stmt.Identifiers) != len(s.stmt.Literals) { + return status.Errorf(codes.InvalidArgument, "statement contains %d identifiers, but %d values given", len(s.stmt.Identifiers), len(s.stmt.Literals)) + } + for index := range s.stmt.Identifiers { + if err := c.setConnectionVariable(s.stmt.Identifiers[index], s.stmt.Literals[index].Value, s.stmt.IsLocal, s.stmt.IsTransaction); err != nil { + return err + } + } + return nil +} + // RESET [my_extension.]my_property type executableResetStatement struct { stmt *parser.ParsedResetStatement } func (s *executableResetStatement) execContext(ctx context.Context, c *conn, opts *ExecOptions) (driver.Result, error) { - if err := c.setConnectionVariable(s.stmt.Identifier, "default", false); err != nil { + if err := c.setConnectionVariable(s.stmt.Identifier, "default", false, false); err != nil { return nil, err } return driver.ResultNoRows, nil } func (s *executableResetStatement) queryContext(ctx context.Context, c *conn, opts *ExecOptions) (driver.Rows, error) { - if err := c.setConnectionVariable(s.stmt.Identifier, "default", false); err != nil { + if err := c.setConnectionVariable(s.stmt.Identifier, "default", false, false); err != nil { return nil, err } return createEmptyRows(opts), nil diff --git a/transaction_test.go b/transaction_test.go new file mode 100644 index 00000000..d7c49ad2 --- /dev/null +++ b/transaction_test.go @@ -0,0 +1,107 @@ +package spannerdriver + +import ( + "context" + "database/sql" + "reflect" + "testing" + + "cloud.google.com/go/spanner/admin/database/apiv1/databasepb" + "cloud.google.com/go/spanner/apiv1/spannerpb" + "github.com/googleapis/go-sql-spanner/testutil" +) + +func TestSetTransactionIsolationLevel(t *testing.T) { + t.Parallel() + + db, server, teardown := setupTestDBConnection(t) + defer teardown() + ctx := context.Background() + + tx, _ := db.BeginTx(ctx, &sql.TxOptions{}) + if _, err := tx.ExecContext(ctx, "set transaction isolation level repeatable read"); err != nil { + t.Fatal(err) + } + _, _ = tx.ExecContext(ctx, testutil.UpdateBarSetFoo) + _ = tx.Commit() + + requests := server.TestSpanner.DrainRequestsFromServer() + executeRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.ExecuteSqlRequest{})) + if g, w := len(executeRequests), 1; g != w { + t.Fatalf("execute requests count mismatch\n Got: %v\nWant: %v", g, w) + } + request := executeRequests[0].(*spannerpb.ExecuteSqlRequest) + if request.GetTransaction() == nil || request.GetTransaction().GetBegin() == nil { + t.Fatal("missing begin transaction on ExecuteSqlRequest") + } + if g, w := request.GetTransaction().GetBegin().GetIsolationLevel(), spannerpb.TransactionOptions_REPEATABLE_READ; g != w { + t.Fatalf("begin isolation level mismatch\n Got: %v\nWant: %v", g, w) + } +} + +func TestSetTransactionReadOnly(t *testing.T) { + t.Parallel() + + db, server, teardown := setupTestDBConnection(t) + defer teardown() + ctx := context.Background() + + tx, _ := db.BeginTx(ctx, &sql.TxOptions{}) + if _, err := tx.ExecContext(ctx, "set transaction read only"); err != nil { + t.Fatal(err) + } + row := tx.QueryRowContext(ctx, testutil.SelectFooFromBar, ExecOptions{DirectExecuteQuery: true}) + if err := row.Err(); err != nil { + t.Fatal(err) + } + _ = tx.Commit() + + requests := server.TestSpanner.DrainRequestsFromServer() + executeRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.ExecuteSqlRequest{})) + if g, w := len(executeRequests), 1; g != w { + t.Fatalf("execute requests count mismatch\n Got: %v\nWant: %v", g, w) + } + request := executeRequests[0].(*spannerpb.ExecuteSqlRequest) + if request.GetTransaction() == nil || request.GetTransaction().GetBegin() == nil { + t.Fatal("missing begin transaction on ExecuteSqlRequest") + } + // TODO: Enable once transaction_read_only is picked up by the driver. + //readOnly := request.GetTransaction().GetBegin().GetReadOnly() + //if readOnly == nil { + // t.Fatal("missing readOnly on ExecuteSqlRequest") + //} +} + +func TestSetTransactionDeferrable(t *testing.T) { + t.Parallel() + + // SET TRANSACTION [NOT] DEFERRABLE is only supported for PostgreSQL-dialect databases. + db, _, teardown := setupTestDBConnectionWithParamsAndDialect(t, "", databasepb.DatabaseDialect_POSTGRESQL) + defer teardown() + ctx := context.Background() + + tx, _ := db.BeginTx(ctx, &sql.TxOptions{}) + if _, err := tx.ExecContext(ctx, "set transaction deferrable"); err != nil { + t.Fatal(err) + } + row := tx.QueryRowContext(ctx, testutil.SelectFooFromBar, ExecOptions{DirectExecuteQuery: true}) + if err := row.Err(); err != nil { + t.Fatal(err) + } + + // transaction_deferrable is a no-op on Spanner, but the SQL statement is supported for + // PostgreSQL-dialect databases for compatibility reasons. + row = tx.QueryRowContext(ctx, "show transaction_deferrable") + if err := row.Err(); err != nil { + t.Fatal(err) + } + var deferrable bool + if err := row.Scan(&deferrable); err != nil { + t.Fatal(err) + } + _ = tx.Commit() + + if g, w := deferrable, true; g != w { + t.Fatalf("deferrable mismatch\n Got: %v\nWant: %v", g, w) + } +} From 49e945e9a22be07f88168e80cdc842b23daa5a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Tue, 7 Oct 2025 19:33:23 +0200 Subject: [PATCH 14/15] feat: support transaction options in BEGIN statements (#550) * feat: parse SET TRANSACTION statements Parse SET TRANSACTION statements and translate these to SET LOCAL statements. SET TRANSACTION may only be executed in a transaction block, and can only be used for a specific, limited set of connection properties. The syntax is specified by the SQL standard and PostgreSQL. See also https://www.postgresql.org/docs/current/sql-set-transaction.html This change only adds partial support. The following features will be added in future changes: 1. SET TRANSACTION READ {WRITE | ONLY} is not picked up by the driver, as the type of transaction is set directly when BeginTx is called. A refactor of this transaction handling is needed to be able to pick up SET TRANSACTION READ ONLY / SET TRANSACTION READ WRITE statements that are executed after BeginTx has been called. 2. PostgreSQL allows multiple transaction modes to be set in a single SET TRANSACTION statement. E.g. the following is allowed: SET TRANSACTION READ WRITE, ISOLATION LEVEL SERIALIZABLE The current implementation only supports one transaction mode per SET statement. * feat: support multiple transaction options in one statement * feat: support transaction options in BEGIN statements Adds support for including transaction options in BEGIN statements, like: ```sql BEGIN READ ONLY; BEGIN READ WRITE; BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ; BEGIN READ WRITE, ISOLATION LEVEL SERIALIZABLE; ``` * chore: re-trigger checks --- parser/statements.go | 78 ++++++++++++++++--------- parser/statements_test.go | 86 ++++++++++++++++++++++++++- statements.go | 9 +++ transaction_test.go | 119 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 264 insertions(+), 28 deletions(-) diff --git a/parser/statements.go b/parser/statements.go index 56307399..d45b01e3 100644 --- a/parser/statements.go +++ b/parser/statements.go @@ -230,34 +230,49 @@ func (s *ParsedSetStatement) parseSetTransaction(sp *simpleParser, query string) s.IsLocal = true s.IsTransaction = true + var err error + s.Identifiers, s.Literals, err = parseTransactionOptions(sp) + if err != nil { + return err + } + return nil +} + +func parseTransactionOptions(sp *simpleParser) ([]Identifier, []Literal, error) { + identifiers := make([]Identifier, 0, 2) + literals := make([]Literal, 0, 2) + var err error for { if sp.peekKeyword("ISOLATION") { - if err := s.parseSetTransactionIsolationLevel(sp, query); err != nil { - return err + identifiers, literals, err = parseTransactionIsolationLevel(sp, identifiers, literals) + if err != nil { + return nil, nil, err } } else if sp.peekKeyword("READ") { - if err := s.parseSetTransactionMode(sp, query); err != nil { - return err + identifiers, literals, err = parseTransactionMode(sp, identifiers, literals) + if err != nil { + return nil, nil, err } } else if sp.statementParser.Dialect == databasepb.DatabaseDialect_POSTGRESQL && (sp.peekKeyword("DEFERRABLE") || sp.peekKeyword("NOT")) { // https://www.postgresql.org/docs/current/sql-set-transaction.html - if err := s.parseSetTransactionDeferrable(sp, query); err != nil { - return err + identifiers, literals, err = parseTransactionDeferrable(sp, identifiers, literals) + if err != nil { + return nil, nil, err } } else { - return status.Error(codes.InvalidArgument, "invalid TRANSACTION option, expected one of ISOLATION LEVEL, READ WRITE, or READ ONLY") + return nil, nil, status.Error(codes.InvalidArgument, "invalid TRANSACTION option, expected one of ISOLATION LEVEL, READ WRITE, or READ ONLY") } if !sp.hasMoreTokens() { - return nil + return identifiers, literals, nil } // Eat and ignore any commas separating the various options. sp.eatToken(',') } } -func (s *ParsedSetStatement) parseSetTransactionIsolationLevel(sp *simpleParser, query string) error { +func parseTransactionIsolationLevel(sp *simpleParser, identifiers []Identifier, literals []Literal) ([]Identifier, []Literal, error) { if !sp.eatKeywords([]string{"ISOLATION", "LEVEL"}) { - return status.Errorf(codes.InvalidArgument, "syntax error: expected ISOLATION LEVEL") + return nil, nil, status.Errorf(codes.InvalidArgument, "syntax error: expected ISOLATION LEVEL") } var value Literal if sp.eatKeyword("SERIALIZABLE") { @@ -265,42 +280,42 @@ func (s *ParsedSetStatement) parseSetTransactionIsolationLevel(sp *simpleParser, } else if sp.eatKeywords([]string{"REPEATABLE", "READ"}) { value = Literal{Value: "repeatable_read"} } else { - return status.Errorf(codes.InvalidArgument, "syntax error: expected SERIALIZABLE OR REPETABLE READ") + return nil, nil, status.Errorf(codes.InvalidArgument, "syntax error: expected SERIALIZABLE OR REPETABLE READ") } - s.Identifiers = append(s.Identifiers, Identifier{Parts: []string{"isolation_level"}}) - s.Literals = append(s.Literals, value) - return nil + identifiers = append(identifiers, Identifier{Parts: []string{"isolation_level"}}) + literals = append(literals, value) + return identifiers, literals, nil } -func (s *ParsedSetStatement) parseSetTransactionMode(sp *simpleParser, query string) error { +func parseTransactionMode(sp *simpleParser, identifiers []Identifier, literals []Literal) ([]Identifier, []Literal, error) { readOnly := false if sp.eatKeywords([]string{"READ", "ONLY"}) { readOnly = true } else if sp.eatKeywords([]string{"READ", "WRITE"}) { readOnly = false } else { - return status.Errorf(codes.InvalidArgument, "syntax error: expected READ ONLY or READ WRITE") + return nil, nil, status.Errorf(codes.InvalidArgument, "syntax error: expected READ ONLY or READ WRITE") } - s.Identifiers = append(s.Identifiers, Identifier{Parts: []string{"transaction_read_only"}}) - s.Literals = append(s.Literals, Literal{Value: fmt.Sprintf("%v", readOnly)}) - return nil + identifiers = append(identifiers, Identifier{Parts: []string{"transaction_read_only"}}) + literals = append(literals, Literal{Value: fmt.Sprintf("%v", readOnly)}) + return identifiers, literals, nil } -func (s *ParsedSetStatement) parseSetTransactionDeferrable(sp *simpleParser, query string) error { +func parseTransactionDeferrable(sp *simpleParser, identifiers []Identifier, literals []Literal) ([]Identifier, []Literal, error) { deferrable := false if sp.eatKeywords([]string{"NOT", "DEFERRABLE"}) { deferrable = false } else if sp.eatKeyword("DEFERRABLE") { deferrable = true } else { - return status.Errorf(codes.InvalidArgument, "syntax error: expected [NOT] DEFERRABLE") + return nil, nil, status.Errorf(codes.InvalidArgument, "syntax error: expected [NOT] DEFERRABLE") } - s.Identifiers = append(s.Identifiers, Identifier{Parts: []string{"transaction_deferrable"}}) - s.Literals = append(s.Literals, Literal{Value: fmt.Sprintf("%v", deferrable)}) - return nil + identifiers = append(identifiers, Identifier{Parts: []string{"transaction_deferrable"}}) + literals = append(literals, Literal{Value: fmt.Sprintf("%v", deferrable)}) + return identifiers, literals, nil } // ParsedResetStatement is a statement of the form @@ -496,6 +511,12 @@ func (s *ParsedAbortBatchStatement) parse(parser *StatementParser, query string) type ParsedBeginStatement struct { query string + // Identifiers contains the transaction properties that were included in the BEGIN statement. E.g. the statement + // BEGIN TRANSACTION READ ONLY contains the transaction property 'transaction_read_only'. + Identifiers []Identifier + // Literals contains the transaction property values that were included in the BEGIN statement. E.g. the statement + // BEGIN TRANSACTION READ ONLY contains the value 'true' for the property 'transaction_read_only'. + Literals []Literal } func (s *ParsedBeginStatement) Name() string { @@ -508,7 +529,7 @@ func (s *ParsedBeginStatement) Query() string { func (s *ParsedBeginStatement) parse(parser *StatementParser, query string) error { // Parse a statement of the form - // GoogleSQL: BEGIN [TRANSACTION] + // GoogleSQL: BEGIN [TRANSACTION] [READ WRITE | READ ONLY | ISOLATION LEVEL {SERIALIZABLE | READ COMMITTED}] // PostgreSQL: {START | BEGIN} [{TRANSACTION | WORK}] (https://www.postgresql.org/docs/current/sql-begin.html) // TODO: Support transaction modes in the BEGIN / START statement. sp := &simpleParser{sql: []byte(query), statementParser: parser} @@ -531,8 +552,13 @@ func (s *ParsedBeginStatement) parse(parser *StatementParser, query string) erro } if sp.hasMoreTokens() { - return status.Errorf(codes.InvalidArgument, "unexpected tokens at position %d in %q", sp.pos, sp.sql) + var err error + s.Identifiers, s.Literals, err = parseTransactionOptions(sp) + if err != nil { + return err + } } + s.query = query return nil } diff --git a/parser/statements_test.go b/parser/statements_test.go index 91fada7e..45361c74 100644 --- a/parser/statements_test.go +++ b/parser/statements_test.go @@ -431,6 +431,38 @@ func TestParseBeginStatementGoogleSQL(t *testing.T) { input: "begin transaction foo", wantErr: true, }, + { + input: "begin read only", + want: ParsedBeginStatement{ + query: "begin read only", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "true"}}, + }, + }, + { + input: "begin read write", + want: ParsedBeginStatement{ + query: "begin read write", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "false"}}, + }, + }, + { + input: "begin transaction isolation level serializable", + want: ParsedBeginStatement{ + query: "begin transaction isolation level serializable", + Identifiers: []Identifier{{Parts: []string{"isolation_level"}}}, + Literals: []Literal{{Value: "serializable"}}, + }, + }, + { + input: "begin transaction isolation level repeatable read, read write", + want: ParsedBeginStatement{ + query: "begin transaction isolation level repeatable read, read write", + Identifiers: []Identifier{{Parts: []string{"isolation_level"}}, {Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "repeatable_read"}, {Value: "false"}}, + }, + }, } parser, err := NewStatementParser(databasepb.DatabaseDialect_GOOGLE_STANDARD_SQL, 1000) if err != nil { @@ -454,7 +486,7 @@ func TestParseBeginStatementGoogleSQL(t *testing.T) { t.Fatalf("parseStatement(%q) should have returned a *parsedBeginStatement", test.input) } if !reflect.DeepEqual(*showStmt, test.want) { - t.Errorf("parseStatement(%q) = %v, want %v", test.input, *showStmt, test.want) + t.Errorf("parseStatement(%q) mismatch\n Got: %v\nWant: %v", test.input, *showStmt, test.want) } } }) @@ -506,6 +538,56 @@ func TestParseBeginStatementPostgreSQL(t *testing.T) { query: "start work", }, }, + { + input: "start work read only", + want: ParsedBeginStatement{ + query: "start work read only", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "true"}}, + }, + }, + { + input: "begin read write", + want: ParsedBeginStatement{ + query: "begin read write", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}}, + Literals: []Literal{{Value: "false"}}, + }, + }, + { + input: "begin read write, isolation level repeatable read", + want: ParsedBeginStatement{ + query: "begin read write, isolation level repeatable read", + Identifiers: []Identifier{{Parts: []string{"transaction_read_only"}}, {Parts: []string{"isolation_level"}}}, + Literals: []Literal{{Value: "false"}, {Value: "repeatable_read"}}, + }, + }, + { + // Note that it is possible to set multiple conflicting transaction options in one statement. + // This statement for example sets the transaction to both read/write and read-only. + // The last option will take precedence, as these options are essentially the same as executing the + // following statements sequentially after the BEGIN TRANSACTION statement: + // SET TRANSACTION READ WRITE + // SET TRANSACTION ISOLATION LEVEL REPEATABLE READ + // SET TRANSACTION READ ONLY + // SET TRANSACTION DEFERRABLE + input: "begin transaction \nread write,\nisolation level repeatable read\nread only\ndeferrable", + want: ParsedBeginStatement{ + query: "begin transaction \nread write,\nisolation level repeatable read\nread only\ndeferrable", + Identifiers: []Identifier{ + {Parts: []string{"transaction_read_only"}}, + {Parts: []string{"isolation_level"}}, + {Parts: []string{"transaction_read_only"}}, + {Parts: []string{"transaction_deferrable"}}, + }, + Literals: []Literal{ + {Value: "false"}, + {Value: "repeatable_read"}, + {Value: "true"}, + {Value: "true"}, + }, + }, + }, { input: "start foo", wantErr: true, @@ -541,7 +623,7 @@ func TestParseBeginStatementPostgreSQL(t *testing.T) { t.Fatalf("parseStatement(%q) should have returned a *parsedBeginStatement", test.input) } if !reflect.DeepEqual(*showStmt, test.want) { - t.Errorf("parseStatement(%q) = %v, want %v", test.input, *showStmt, test.want) + t.Errorf("parseStatement(%q) mismatch\n Got: %v\nWant: %v", test.input, *showStmt, test.want) } } }) diff --git a/statements.go b/statements.go index 2c7c7a7a..147146b5 100644 --- a/statements.go +++ b/statements.go @@ -279,10 +279,19 @@ type executableBeginStatement struct { } func (s *executableBeginStatement) execContext(ctx context.Context, c *conn, opts *ExecOptions) (driver.Result, error) { + if len(s.stmt.Identifiers) != len(s.stmt.Literals) { + return nil, status.Errorf(codes.InvalidArgument, "statement contains %d identifiers, but %d values given", len(s.stmt.Identifiers), len(s.stmt.Literals)) + } _, err := c.BeginTx(ctx, driver.TxOptions{}) if err != nil { return nil, err } + for index := range s.stmt.Identifiers { + if err := c.setConnectionVariable(s.stmt.Identifiers[index], s.stmt.Literals[index].Value /*IsLocal=*/, true /*IsTransaction=*/, true); err != nil { + return nil, err + } + } + return driver.ResultNoRows, nil } diff --git a/transaction_test.go b/transaction_test.go index d7c49ad2..0842279b 100644 --- a/transaction_test.go +++ b/transaction_test.go @@ -105,3 +105,122 @@ func TestSetTransactionDeferrable(t *testing.T) { t.Fatalf("deferrable mismatch\n Got: %v\nWant: %v", g, w) } } + +func TestBeginTransactionIsolationLevel(t *testing.T) { + t.Parallel() + + db, server, teardown := setupTestDBConnection(t) + defer teardown() + ctx := context.Background() + + conn, err := db.Conn(ctx) + if err != nil { + t.Fatal(err) + } + defer silentClose(conn) + + if _, err := conn.ExecContext(ctx, "begin transaction isolation level repeatable read"); err != nil { + t.Fatal(err) + } + if _, err := conn.ExecContext(ctx, testutil.UpdateBarSetFoo); err != nil { + t.Fatal(err) + } + if _, err := conn.ExecContext(ctx, "commit"); err != nil { + t.Fatal(err) + } + + requests := server.TestSpanner.DrainRequestsFromServer() + executeRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.ExecuteSqlRequest{})) + if g, w := len(executeRequests), 1; g != w { + t.Fatalf("execute requests count mismatch\n Got: %v\nWant: %v", g, w) + } + request := executeRequests[0].(*spannerpb.ExecuteSqlRequest) + if request.GetTransaction() == nil || request.GetTransaction().GetBegin() == nil { + t.Fatal("missing begin transaction on ExecuteSqlRequest") + } + if g, w := request.GetTransaction().GetBegin().GetIsolationLevel(), spannerpb.TransactionOptions_REPEATABLE_READ; g != w { + t.Fatalf("begin isolation level mismatch\n Got: %v\nWant: %v", g, w) + } +} + +func TestBeginTransactionReadOnly(t *testing.T) { + t.Parallel() + + db, server, teardown := setupTestDBConnection(t) + defer teardown() + ctx := context.Background() + + conn, err := db.Conn(ctx) + if err != nil { + t.Fatal(err) + } + defer silentClose(conn) + + if _, err := conn.ExecContext(ctx, "begin transaction read write"); err != nil { + t.Fatal(err) + } + row := conn.QueryRowContext(ctx, testutil.SelectFooFromBar, ExecOptions{DirectExecuteQuery: true}) + var c int64 + // If we don't call row.Scan(..), then the underlying Rows object is not closed. That again means that the + // connection cannot be released. + if err := row.Scan(&c); err != nil { + t.Fatal(err) + } + if _, err := conn.ExecContext(ctx, "commit"); err != nil { + t.Fatal(err) + } + + requests := server.TestSpanner.DrainRequestsFromServer() + executeRequests := testutil.RequestsOfType(requests, reflect.TypeOf(&spannerpb.ExecuteSqlRequest{})) + if g, w := len(executeRequests), 1; g != w { + t.Fatalf("execute requests count mismatch\n Got: %v\nWant: %v", g, w) + } + request := executeRequests[0].(*spannerpb.ExecuteSqlRequest) + if request.GetTransaction() == nil || request.GetTransaction().GetBegin() == nil { + t.Fatal("missing begin transaction on ExecuteSqlRequest") + } + // TODO: Enable once transaction_read_only is picked up by the driver. + //readOnly := request.GetTransaction().GetBegin().GetReadOnly() + //if readOnly == nil { + // t.Fatal("missing readOnly on ExecuteSqlRequest") + //} +} + +func TestBeginTransactionDeferrable(t *testing.T) { + t.Parallel() + + // BEGIN TRANSACTION [NOT] DEFERRABLE is only supported for PostgreSQL-dialect databases. + db, _, teardown := setupTestDBConnectionWithParamsAndDialect(t, "", databasepb.DatabaseDialect_POSTGRESQL) + defer teardown() + ctx := context.Background() + + conn, err := db.Conn(ctx) + if err != nil { + t.Fatal(err) + } + defer silentClose(conn) + + if _, err := conn.ExecContext(ctx, "begin transaction deferrable"); err != nil { + t.Fatal(err) + } + row := conn.QueryRowContext(ctx, testutil.SelectFooFromBar, ExecOptions{DirectExecuteQuery: true}) + var c int64 + if err := row.Scan(&c); err != nil { + t.Fatal(err) + } + + // transaction_deferrable is a no-op on Spanner, but the SQL statement is supported for + // PostgreSQL-dialect databases for compatibility reasons. + row = conn.QueryRowContext(ctx, "show transaction_deferrable") + var deferrable bool + if err := row.Scan(&deferrable); err != nil { + t.Fatal(err) + } + if _, err := conn.ExecContext(ctx, "commit"); err != nil { + t.Fatal(err) + } + + if g, w := deferrable, true; g != w { + t.Fatalf("deferrable mismatch\n Got: %v\nWant: %v", g, w) + } +} From ab5873b1801d9051194d4a4ebf11b94fe4ce2e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Olav=20L=C3=B8ite?= Date: Thu, 16 Oct 2025 12:34:19 +0200 Subject: [PATCH 15/15] chore: add timeout for server startup --- .../spannerlib-dotnet-grpc-server/Server.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs index 436869da..1235d086 100644 --- a/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs +++ b/spannerlib/wrappers/spannerlib-dotnet/spannerlib-dotnet-grpc-server/Server.cs @@ -48,11 +48,11 @@ public string Start(AddressType addressType = AddressType.UnixDomainSocket) { throw new InvalidOperationException("The server is already started."); } - (_host, _process) = StartGrpcServer(addressType); + (_host, _process) = StartGrpcServer(addressType, TimeSpan.FromSeconds(5)); return _host; } - private static Tuple StartGrpcServer(AddressType addressType) + private static Tuple StartGrpcServer(AddressType addressType, TimeSpan timeout) { string arguments; if (addressType == AddressType.UnixDomainSocket) @@ -87,8 +87,13 @@ private static Tuple StartGrpcServer(AddressType addressType) } if (addressType == AddressType.UnixDomainSocket) { + var watch = new Stopwatch(); while (!File.Exists(arguments)) { + if (watch.Elapsed > timeout) + { + throw new TimeoutException($"Attempt to start gRPC server timed out after {timeout}"); + } Thread.Sleep(1); } }