diff --git a/bigquery/bigquery.go b/bigquery/bigquery.go index 94720a912784..c597679bc70b 100644 --- a/bigquery/bigquery.go +++ b/bigquery/bigquery.go @@ -21,6 +21,7 @@ import ( "io" "net/http" "net/url" + "os" "strings" "time" @@ -59,6 +60,9 @@ type Client struct { projectID string bqs *bq.Service rc *readClient + + // governs use of preview query features. + enableQueryPreview bool } // DetectProjectID is a sentinel value that instructs NewClient to detect the @@ -75,6 +79,12 @@ const DetectProjectID = "*detect-project-id*" // // If the project ID is set to DetectProjectID, NewClient will attempt to detect // the project ID from credentials. +// +// This client supports enabling query-related preview features via environmental +// variables. By setting the environment variable QUERY_PREVIEW_ENABLED to the string +// "TRUE", the client will enable preview features, though behavior may still be +// controlled via the bigquery service as well. Currently, the feature(s) in scope +// include: stateless queries (query execution without corresponding job metadata). func NewClient(ctx context.Context, projectID string, opts ...option.ClientOption) (*Client, error) { o := []option.ClientOption{ option.WithScopes(Scope), @@ -92,9 +102,17 @@ func NewClient(ctx context.Context, projectID string, opts ...option.ClientOptio return nil, err } + var preview bool + if v, ok := os.LookupEnv("QUERY_PREVIEW_ENABLED"); ok { + if strings.ToUpper(v) == "TRUE" { + preview = true + } + } + c := &Client{ - projectID: projectID, - bqs: bqs, + projectID: projectID, + bqs: bqs, + enableQueryPreview: preview, } return c, nil } diff --git a/bigquery/go.mod b/bigquery/go.mod index 06cbdf1e7141..f00fd4307ffd 100644 --- a/bigquery/go.mod +++ b/bigquery/go.mod @@ -3,23 +3,23 @@ module cloud.google.com/go/bigquery go 1.19 require ( - cloud.google.com/go v0.110.6 + cloud.google.com/go v0.110.7 cloud.google.com/go/datacatalog v1.16.0 cloud.google.com/go/iam v1.1.1 cloud.google.com/go/longrunning v0.5.1 cloud.google.com/go/storage v1.30.1 github.com/apache/arrow/go/v12 v12.0.0 github.com/google/go-cmp v0.5.9 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.3.1 github.com/googleapis/gax-go/v2 v2.12.0 go.opencensus.io v0.24.0 golang.org/x/sync v0.3.0 golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 - google.golang.org/api v0.139.0 - google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 - google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d - google.golang.org/grpc v1.57.0 + google.golang.org/api v0.145.0 + google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb + google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb + google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 + google.golang.org/grpc v1.58.2 google.golang.org/protobuf v1.31.0 ) @@ -35,7 +35,7 @@ require ( github.com/google/flatbuffers v2.0.8+incompatible // indirect github.com/google/martian/v3 v3.3.2 // indirect github.com/google/s2a-go v0.1.7 // indirect - github.com/googleapis/enterprise-certificate-proxy v0.2.5 // indirect + github.com/googleapis/enterprise-certificate-proxy v0.3.1 // indirect github.com/klauspost/asmfmt v1.3.2 // indirect github.com/klauspost/compress v1.15.9 // indirect github.com/klauspost/cpuid/v2 v2.0.9 // indirect @@ -47,7 +47,7 @@ require ( golang.org/x/crypto v0.14.0 // indirect golang.org/x/mod v0.10.0 // indirect golang.org/x/net v0.17.0 // indirect - golang.org/x/oauth2 v0.11.0 // indirect + golang.org/x/oauth2 v0.12.0 // indirect golang.org/x/sys v0.13.0 // indirect golang.org/x/text v0.13.0 // indirect golang.org/x/tools v0.9.1 // indirect diff --git a/bigquery/go.sum b/bigquery/go.sum index 2ccda0976c9e..a6cef97b448c 100644 --- a/bigquery/go.sum +++ b/bigquery/go.sum @@ -1,6 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.110.6 h1:8uYAkj3YHTP/1iwReuHPxLSbdcyc+dSBbzFMrVwDR6Q= -cloud.google.com/go v0.110.6/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= +cloud.google.com/go v0.110.7 h1:rJyC7nWRg2jWGZ4wSJ5nY65GTdYJkg0cd/uXb+ACI6o= +cloud.google.com/go v0.110.7/go.mod h1:+EYjdK8e5RME/VY/qLCAtuyALQ9q67dvuum8i+H5xsI= cloud.google.com/go/compute v1.23.0 h1:tP41Zoavr8ptEqaW6j+LQOnyBBhO7OkOMAGrgLopTwY= cloud.google.com/go/compute v1.23.0/go.mod h1:4tCnrn48xsqlwSAiLf1HXMQk8CONslYbdiEZc9FEIbM= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= @@ -75,10 +75,10 @@ github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.2.5 h1:UR4rDjcgpgEnqpIEvkiqTYKBCKLNmlge2eVjoZfySzM= -github.com/googleapis/enterprise-certificate-proxy v0.2.5/go.mod h1:RxW0N9901Cko1VOCW3SXCpWP+mlIEkk2tP7jnHy9a3w= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/googleapis/enterprise-certificate-proxy v0.3.1 h1:SBWmZhjUDRorQxrN0nwzf+AHBxnbFjViHQS4P0yVpmQ= +github.com/googleapis/enterprise-certificate-proxy v0.3.1/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= github.com/klauspost/asmfmt v1.3.2 h1:4Ri7ox3EwapiOjCki+hw14RyKk201CN4rzyCJRFLpK4= @@ -135,8 +135,8 @@ golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwY golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= -golang.org/x/oauth2 v0.11.0 h1:vPL4xzxBM4niKCW6g9whtaWVXTJf1U5e4aZxxFx/gbU= -golang.org/x/oauth2 v0.11.0/go.mod h1:LdF7O/8bLR/qWK9DrpXmbHLTouvRHK0SgJl0GmDBchk= +golang.org/x/oauth2 v0.12.0 h1:smVPGxink+n1ZI5pkQa8y6fZT0RW0MgCO5bFpepy4B4= +golang.org/x/oauth2 v0.12.0/go.mod h1:A74bZ3aGXgCY0qaIC9Ahg6Lglin4AMAco8cIv9baba4= 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-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -167,8 +167,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8= gonum.org/v1/gonum v0.11.0 h1:f1IJhK4Km5tBJmaiJXtk/PkL4cdVX6J+tGiM187uT5E= -google.golang.org/api v0.139.0 h1:A1TrCPgMmOiYu0AiNkvQIpIx+D8blHTDcJ5EogkP7LI= -google.golang.org/api v0.139.0/go.mod h1:CVagp6Eekz9CjGZ718Z+sloknzkDJE7Vc1Ckj9+viBk= +google.golang.org/api v0.145.0 h1:kBjvf1A3/m30kUvnUX9jZJxTu3lJrpGFt5V/1YZrjwg= +google.golang.org/api v0.145.0/go.mod h1:OARJqIfoYjXJj4C1AiBSXYZt03qsoz8FQYU6fBEfrHM= 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.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c= @@ -176,20 +176,20 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5 h1:L6iMMGrtzgHsWofoFcihmDEMYeDR9KN/ThbPWGrh++g= -google.golang.org/genproto v0.0.0-20230803162519-f966b187b2e5/go.mod h1:oH/ZOT02u4kWEp7oYBGYFFkCdKS/uYR9Z7+0/xuuFp8= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5 h1:nIgk/EEq3/YlnmVVXVnm14rC2oxgs1o0ong4sD/rd44= -google.golang.org/genproto/googleapis/api v0.0.0-20230803162519-f966b187b2e5/go.mod h1:5DZzOUPCLYL3mNkQ0ms0F3EuUNZ7py1Bqeq6sxzI7/Q= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb h1:XFBgcDwm7irdHTbz4Zk2h7Mh+eis4nfJEFQFYzJzuIA= +google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb h1:lK0oleSc7IQsUxO3U5TjL9DWlsxpEBemh+zpB7IqhWI= +google.golang.org/genproto/googleapis/api v0.0.0-20230913181813-007df8e322eb/go.mod h1:KjSP20unUpOx5kyQUFa7k4OJg0qeJ7DEZflGDu2p6Bk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13 h1:N3bU/SQDCDyD6R528GJ/PwW9KjYcJA3dgyH+MovAkIM= +google.golang.org/genproto/googleapis/rpc v0.0.0-20230920204549-e6e6cdab5c13/go.mod h1:KSqppvjFjtoCI+KGd4PELB0qLNxdJHRGqRI09mB6pQA= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +google.golang.org/grpc v1.58.2 h1:SXUpjxeVF3FKrTYQI4f4KvbGD5u2xccdYdurwowix5I= +google.golang.org/grpc v1.58.2/go.mod h1:tgX3ZQDlNJGU96V6yHh1T/JeoBQ2TXdr43YbYSsCJk0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= diff --git a/bigquery/integration_test.go b/bigquery/integration_test.go index 64ea202a5923..232333383da9 100644 --- a/bigquery/integration_test.go +++ b/bigquery/integration_test.go @@ -775,6 +775,11 @@ func TestIntegration_SimpleRowResults(t *testing.T) { if client == nil { t.Skip("Integration tests skipped") } + beforePreview := client.enableQueryPreview + // ensure we restore the preview setting on test exit + defer func() { + client.enableQueryPreview = beforePreview + }() ctx := context.Background() testCases := []struct { @@ -797,7 +802,7 @@ func TestIntegration_SimpleRowResults(t *testing.T) { // in the job config, but switching to relying on jobs.getQueryResults allows the // service to decide the behavior. description: "ctas ddl", - query: fmt.Sprintf("CREATE TABLE %s.%s AS SELECT 17 as foo", dataset.DatasetID, tableIDs.New()), + query: fmt.Sprintf("CREATE OR REPLACE TABLE %s.%s AS SELECT 17 as foo", dataset.DatasetID, tableIDs.New()), want: nil, }, { @@ -806,19 +811,45 @@ func TestIntegration_SimpleRowResults(t *testing.T) { query: "select count(*) from unnest(generate_array(1,1000000)), unnest(generate_array(1, 1000)) as foo", want: [][]Value{{int64(1000000000)}}, }, + { + // Query doesn't yield a result. + description: "DML", + query: fmt.Sprintf("CREATE OR REPLACE TABLE %s.%s (foo STRING, bar INT64)", dataset.DatasetID, tableIDs.New()), + want: [][]Value{}, + }, } - for _, tc := range testCases { - curCase := tc - t.Run(curCase.description, func(t *testing.T) { - t.Parallel() - q := client.Query(curCase.query) - it, err := q.Read(ctx) - if err != nil { - t.Fatalf("%s read error: %v", curCase.description, err) - } - checkReadAndTotalRows(t, curCase.description, it, curCase.want) - }) - } + + t.Run("nopreview_group", func(t *testing.T) { + client.enableQueryPreview = false + for _, tc := range testCases { + curCase := tc + t.Run(curCase.description, func(t *testing.T) { + t.Parallel() + q := client.Query(curCase.query) + it, err := q.Read(ctx) + if err != nil { + t.Fatalf("%s read error: %v", curCase.description, err) + } + checkReadAndTotalRows(t, curCase.description, it, curCase.want) + }) + } + }) + t.Run("preview_group", func(t *testing.T) { + client.enableQueryPreview = true + for _, tc := range testCases { + curCase := tc + t.Run(curCase.description, func(t *testing.T) { + t.Parallel() + q := client.Query(curCase.query) + it, err := q.Read(ctx) + if err != nil { + t.Fatalf("%s read error: %v", curCase.description, err) + } + checkReadAndTotalRows(t, curCase.description, it, curCase.want) + }) + } + }) + } func TestIntegration_QueryIterationPager(t *testing.T) { @@ -3284,21 +3315,28 @@ func checkReadAndTotalRows(t *testing.T, msg string, it *RowIterator, want [][]V func compareRead(it *RowIterator, want [][]Value, compareTotalRows bool) (msg string, ok bool) { got, _, totalRows, err := readAll(it) + jobStr := "" + if it.SourceJob() != nil { + jobStr = it.SourceJob().jobID + } + if jobStr != "" { + jobStr = fmt.Sprintf("(Job: %s)", jobStr) + } if err != nil { return err.Error(), false } if len(got) != len(want) { - return fmt.Sprintf("got %d rows, want %d", len(got), len(want)), false + return fmt.Sprintf("%s got %d rows, want %d", jobStr, len(got), len(want)), false } if compareTotalRows && len(got) != int(totalRows) { - return fmt.Sprintf("got %d rows, but totalRows = %d", len(got), totalRows), false + return fmt.Sprintf("%s got %d rows, but totalRows = %d", jobStr, len(got), totalRows), false } sort.Sort(byCol0(got)) for i, r := range got { gotRow := []Value(r) wantRow := want[i] if !testutil.Equal(gotRow, wantRow) { - return fmt.Sprintf("#%d: got %#v, want %#v", i, gotRow, wantRow), false + return fmt.Sprintf("%s #%d: got %#v, want %#v", jobStr, i, gotRow, wantRow), false } } return "", true diff --git a/bigquery/iterator.go b/bigquery/iterator.go index 37b12dea84d4..6339bd52b541 100644 --- a/bigquery/iterator.go +++ b/bigquery/iterator.go @@ -240,7 +240,11 @@ func fetchPage(ctx context.Context, src *rowSource, schema Schema, startIndex ui if src.j != nil { return fetchJobResultPage(ctx, src, schema, startIndex, pageSize, pageToken) } - return fetchTableResultPage(ctx, src, schema, startIndex, pageSize, pageToken) + if src.t != nil { + return fetchTableResultPage(ctx, src, schema, startIndex, pageSize, pageToken) + } + // No rows, but no table or job reference. Return an empty result set. + return &fetchPageResult{}, nil } return result, nil } diff --git a/bigquery/query.go b/bigquery/query.go index 7030cfd50c4f..a44e93227d72 100644 --- a/bigquery/query.go +++ b/bigquery/query.go @@ -393,11 +393,14 @@ func (q *Query) Read(ctx context.Context) (it *RowIterator, err error) { } // construct a minimal job for backing the row iterator. - minimalJob := &Job{ - c: q.client, - jobID: resp.JobReference.JobId, - location: resp.JobReference.Location, - projectID: resp.JobReference.ProjectId, + var minimalJob *Job + if resp.JobReference != nil { + minimalJob = &Job{ + c: q.client, + jobID: resp.JobReference.JobId, + location: resp.JobReference.Location, + projectID: resp.JobReference.ProjectId, + } } if resp.JobComplete { @@ -484,6 +487,9 @@ func (q *Query) probeFastPath() (*bq.QueryRequest, error) { DatasetId: q.QueryConfig.DefaultDatasetID, } } + if q.client.enableQueryPreview { + qRequest.JobCreationMode = "JOB_CREATION_OPTIONAL" + } return qRequest, nil } diff --git a/go.work.sum b/go.work.sum index 389a68974736..e53ed9473d2f 100644 --- a/go.work.sum +++ b/go.work.sum @@ -31,9 +31,9 @@ golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4= +golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= golang.org/x/tools v0.10.0 h1:tvDr/iQoUqNdohiYm0LmmKcBk+q86lb9EprIUFhHHGg= golang.org/x/tools v0.10.0/go.mod h1:UJwyiVBsOA2uwvK/e5OY3GTpDUJriEd+/YlqAwLPmyM= -google.golang.org/api v0.123.0/go.mod h1:gcitW0lvnyWjSp9nKxAbdHKIZ6vF4aajGueeslZOyms= google.golang.org/genproto v0.0.0-20230526203410-71b5a4ffd15e/go.mod h1:zqTuNwFlFRsw5zIts5VnzLQxSRqh+CGOTVMlYbY0Eyk= google.golang.org/genproto v0.0.0-20230711160842-782d3b101e98/go.mod h1:S7mY02OqCJTD0E1OiQy1F72PWFB4bZJ87cAtLPYgDR0= google.golang.org/genproto v0.0.0-20230913181813-007df8e322eb/go.mod h1:yZTlhN0tQnXo3h00fuXNCxJdLdIdnVFVBaRJ5LWBbw4=