@@ -190,12 +190,28 @@ func (d *Dataset) Identifier(f IdentifierFormat) (string, error) {
190
190
}
191
191
}
192
192
193
- // Create creates a dataset in the BigQuery service. An error will be returned if the
194
- // dataset already exists. Pass in a DatasetMetadata value to configure the dataset.
193
+ // Create creates a dataset in the BigQuery service.
194
+ //
195
+ // An error will be returned if the dataset already exists.
196
+ // Pass in a DatasetMetadata value to configure the dataset.
195
197
func (d * Dataset ) Create (ctx context.Context , md * DatasetMetadata ) (err error ) {
198
+ return d .CreateWithOptions (ctx , md )
199
+ }
200
+
201
+ // CreateWithOptions creates a dataset in the BigQuery service, and
202
+ // provides additional options to control the behavior of the call.
203
+ //
204
+ // An error will be returned if the dataset already exists.
205
+ // Pass in a DatasetMetadata value to configure the dataset.
206
+ func (d * Dataset ) CreateWithOptions (ctx context.Context , md * DatasetMetadata , opts ... DatasetOption ) (err error ) {
196
207
ctx = trace .StartSpan (ctx , "cloud.google.com/go/bigquery.Dataset.Create" )
197
208
defer func () { trace .EndSpan (ctx , err ) }()
198
209
210
+ cOpt := & dsCallOption {}
211
+ for _ , o := range opts {
212
+ o (cOpt )
213
+ }
214
+
199
215
ds , err := md .toBQ ()
200
216
if err != nil {
201
217
return err
@@ -207,6 +223,9 @@ func (d *Dataset) Create(ctx context.Context, md *DatasetMetadata) (err error) {
207
223
}
208
224
call := d .c .bqs .Datasets .Insert (d .ProjectID , ds ).Context (ctx )
209
225
setClientHeader (call .Header ())
226
+ if cOpt .accessPolicyVersion != nil {
227
+ call .AccessPolicyVersion (int64 (optional .ToInt (cOpt .accessPolicyVersion )))
228
+ }
210
229
_ , err = call .Do ()
211
230
return err
212
231
}
@@ -289,11 +308,25 @@ func (d *Dataset) deleteInternal(ctx context.Context, deleteContents bool) (err
289
308
290
309
// Metadata fetches the metadata for the dataset.
291
310
func (d * Dataset ) Metadata (ctx context.Context ) (md * DatasetMetadata , err error ) {
311
+ return d .MetadataWithOptions (ctx )
312
+ }
313
+
314
+ // MetadataWithOptions fetches metadata for the dataset, and provides additional options for
315
+ // controlling the request.
316
+ func (d * Dataset ) MetadataWithOptions (ctx context.Context , opts ... DatasetOption ) (md * DatasetMetadata , err error ) {
292
317
ctx = trace .StartSpan (ctx , "cloud.google.com/go/bigquery.Dataset.Metadata" )
293
318
defer func () { trace .EndSpan (ctx , err ) }()
294
319
320
+ cOpt := & dsCallOption {}
321
+ for _ , o := range opts {
322
+ o (cOpt )
323
+ }
324
+
295
325
call := d .c .bqs .Datasets .Get (d .ProjectID , d .DatasetID ).Context (ctx )
296
326
setClientHeader (call .Header ())
327
+ if cOpt .accessPolicyVersion != nil {
328
+ call .AccessPolicyVersion (int64 (optional .ToInt (cOpt .accessPolicyVersion )))
329
+ }
297
330
var ds * bq.Dataset
298
331
if err := runWithRetry (ctx , func () (err error ) {
299
332
sCtx := trace .StartSpan (ctx , "bigquery.datasets.get" )
@@ -306,6 +339,36 @@ func (d *Dataset) Metadata(ctx context.Context) (md *DatasetMetadata, err error)
306
339
return bqToDatasetMetadata (ds , d .c )
307
340
}
308
341
342
+ // dsCallOption provides a general option holder for dataset RPCs
343
+ type dsCallOption struct {
344
+ accessPolicyVersion optional.Int
345
+ }
346
+
347
+ // DatasetOption provides an option type for customizing requests against the Dataset
348
+ // service.
349
+ type DatasetOption func (* dsCallOption )
350
+
351
+ // WithAccessPolicyVersion is an option that enabled setting of the Access Policy Version for a request
352
+ // where appropriate. Valid values are 0, 1, and 3.
353
+ //
354
+ // Requests specifying an invalid value will be rejected.
355
+ // Requests for conditional access policy binding in datasets must specify version 3.
356
+ //
357
+ // Dataset with no conditional role bindings in access policy may specify any valid value
358
+ // or leave the field unset.
359
+ //
360
+ // This field will be mapped to [IAM Policy version] (https://cloud.google.com/iam/docs/policies#versions)
361
+ // and will be used to fetch policy from IAM. If unset or if 0 or 1 value is used for
362
+ // dataset with conditional bindings, access entry with condition will have role string
363
+ // appended by 'withcond' string followed by a hash value.
364
+ //
365
+ // Please refer https://cloud.google.com/iam/docs/troubleshooting-withcond for more details.
366
+ func WithAccessPolicyVersion (apv int ) DatasetOption {
367
+ return func (o * dsCallOption ) {
368
+ o .accessPolicyVersion = apv
369
+ }
370
+ }
371
+
309
372
func bqToDatasetMetadata (d * bq.Dataset , c * Client ) (* DatasetMetadata , error ) {
310
373
dm := & DatasetMetadata {
311
374
CreationTime : unixMillisToTime (d .CreationTime ),
@@ -345,18 +408,36 @@ func bqToDatasetMetadata(d *bq.Dataset, c *Client) (*DatasetMetadata, error) {
345
408
// set the etag argument to the DatasetMetadata.ETag field from the read.
346
409
// Pass the empty string for etag for a "blind write" that will always succeed.
347
410
func (d * Dataset ) Update (ctx context.Context , dm DatasetMetadataToUpdate , etag string ) (md * DatasetMetadata , err error ) {
411
+ return d .UpdateWithOptions (ctx , dm , etag )
412
+ }
413
+
414
+ // UpdateWithOptions modifies specific Dataset metadata fields and
415
+ // provides an interface for specifying additional options to the request.
416
+ //
417
+ // To perform a read-modify-write that protects against intervening reads,
418
+ // set the etag argument to the DatasetMetadata.ETag field from the read.
419
+ // Pass the empty string for etag for a "blind write" that will always succeed.
420
+ func (d * Dataset ) UpdateWithOptions (ctx context.Context , dm DatasetMetadataToUpdate , etag string , opts ... DatasetOption ) (md * DatasetMetadata , err error ) {
348
421
ctx = trace .StartSpan (ctx , "cloud.google.com/go/bigquery.Dataset.Update" )
349
422
defer func () { trace .EndSpan (ctx , err ) }()
350
423
424
+ cOpt := & dsCallOption {}
425
+ for _ , o := range opts {
426
+ o (cOpt )
427
+ }
351
428
ds , err := dm .toBQ ()
352
429
if err != nil {
353
430
return nil , err
354
431
}
432
+
355
433
call := d .c .bqs .Datasets .Patch (d .ProjectID , d .DatasetID , ds ).Context (ctx )
356
434
setClientHeader (call .Header ())
357
435
if etag != "" {
358
436
call .Header ().Set ("If-Match" , etag )
359
437
}
438
+ if cOpt .accessPolicyVersion != nil {
439
+ call .AccessPolicyVersion (int64 (optional .ToInt (cOpt .accessPolicyVersion )))
440
+ }
360
441
var ds2 * bq.Dataset
361
442
if err := runWithRetry (ctx , func () (err error ) {
362
443
sCtx := trace .StartSpan (ctx , "bigquery.datasets.patch" )
@@ -811,6 +892,50 @@ type AccessEntry struct {
811
892
View * Table // The view granted access (EntityType must be ViewEntity)
812
893
Routine * Routine // The routine granted access (only UDF currently supported)
813
894
Dataset * DatasetAccessEntry // The resources within a dataset granted access.
895
+ Condition * Expr // Condition for the access binding.
896
+ }
897
+
898
+ // Expr represents the conditional information related to dataset access policies.
899
+ type Expr struct {
900
+ // Textual representation of an expression in Common Expression Language syntax.
901
+ Expression string
902
+
903
+ // Optional. Title for the expression, i.e. a short string describing
904
+ // its purpose. This can be used e.g. in UIs which allow to enter the
905
+ // expression.
906
+ Title string
907
+
908
+ // Optional. Description of the expression. This is a longer text which
909
+ // describes the expression, e.g. when hovered over it in a UI.
910
+ Description string
911
+
912
+ // Optional. String indicating the location of the expression for error
913
+ // reporting, e.g. a file name and a position in the file.
914
+ Location string
915
+ }
916
+
917
+ func (ex * Expr ) toBQ () * bq.Expr {
918
+ if ex == nil {
919
+ return nil
920
+ }
921
+ return & bq.Expr {
922
+ Expression : ex .Expression ,
923
+ Title : ex .Title ,
924
+ Description : ex .Description ,
925
+ Location : ex .Location ,
926
+ }
927
+ }
928
+
929
+ func bqToExpr (bq * bq.Expr ) * Expr {
930
+ if bq == nil {
931
+ return nil
932
+ }
933
+ return & Expr {
934
+ Expression : bq .Expression ,
935
+ Title : bq .Title ,
936
+ Description : bq .Description ,
937
+ Location : bq .Location ,
938
+ }
814
939
}
815
940
816
941
// AccessRole is the level of access to grant to a dataset.
@@ -857,7 +982,10 @@ const (
857
982
)
858
983
859
984
func (e * AccessEntry ) toBQ () (* bq.DatasetAccess , error ) {
860
- q := & bq.DatasetAccess {Role : string (e .Role )}
985
+ q := & bq.DatasetAccess {
986
+ Role : string (e .Role ),
987
+ Condition : e .Condition .toBQ (),
988
+ }
861
989
switch e .EntityType {
862
990
case DomainEntity :
863
991
q .Domain = e .Entity
@@ -911,6 +1039,9 @@ func bqToAccessEntry(q *bq.DatasetAccess, c *Client) (*AccessEntry, error) {
911
1039
default :
912
1040
return nil , errors .New ("bigquery: invalid access value" )
913
1041
}
1042
+ if q .Condition != nil {
1043
+ e .Condition = bqToExpr (q .Condition )
1044
+ }
914
1045
return e , nil
915
1046
}
916
1047
0 commit comments