google-cloud-bigquery 1.23.0 → 1.28.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -981,8 +981,7 @@ module Google
981
981
  # @param [String] description A user-friendly description of the
982
982
  # dataset.
983
983
  # @param [Integer] expiration The default lifetime of all tables in the
984
- # dataset, in milliseconds. The minimum value is 3600000 milliseconds
985
- # (one hour).
984
+ # dataset, in milliseconds. The minimum value is `3_600_000` (one hour).
986
985
  # @param [String] location The geographic location where the dataset
987
986
  # should reside. Possible values include `EU` and `US`. The default
988
987
  # value is `US`.
@@ -94,8 +94,7 @@ module Google
94
94
  # otherwise.
95
95
  #
96
96
  def batch?
97
- val = @gapi.configuration.query.priority
98
- val == "BATCH"
97
+ @gapi.configuration.query.priority == "BATCH"
99
98
  end
100
99
 
101
100
  ##
@@ -528,8 +527,9 @@ module Google
528
527
  # The period for which the destination table will be partitioned, if
529
528
  # any. See [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
530
529
  #
531
- # @return [String, nil] The partition type. Currently the only supported
532
- # value is "DAY", or `nil` if not present.
530
+ # @return [String, nil] The partition type. The supported types are `DAY`,
531
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
532
+ # hour, month, and year, respectively; or `nil` if not present.
533
533
  #
534
534
  # @!group Attributes
535
535
  #
@@ -1302,13 +1302,16 @@ module Google
1302
1302
  ##
1303
1303
  # Sets the partitioning for the destination table. See [Partitioned
1304
1304
  # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
1305
+ # The supported types are `DAY`, `HOUR`, `MONTH`, and `YEAR`, which will
1306
+ # generate one partition per day, hour, month, and year, respectively.
1305
1307
  #
1306
1308
  # You can only set the partitioning field while creating a table.
1307
1309
  # BigQuery does not allow you to change partitioning on an existing
1308
1310
  # table.
1309
1311
  #
1310
- # @param [String] type The partition type. Currently the only
1311
- # supported value is "DAY".
1312
+ # @param [String] type The partition type. The supported types are `DAY`,
1313
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
1314
+ # hour, month, and year, respectively.
1312
1315
  #
1313
1316
  # @example
1314
1317
  # require "google/cloud/bigquery"
@@ -603,6 +603,93 @@ module Google
603
603
  update_gapi!
604
604
  end
605
605
 
606
+ ###
607
+ # The JavaScript UDF determinism level. Optional.
608
+ #
609
+ # * `DETERMINISTIC` - Deterministic indicates that two calls with the same input to a UDF yield the same output.
610
+ # If all JavaScript UDFs are `DETERMINISTIC`, the query result is potentially cachable.
611
+ # * `NOT_DETERMINISTIC` - Not deterministic indicates that the output of the UDF is not guaranteed to yield the
612
+ # same output each time for a given set of inputs. If any JavaScript UDF is `NOT_DETERMINISTIC`, the query
613
+ # result is not cacheable.
614
+ #
615
+ # Even if a JavaScript UDF is deterministic, many other factors can prevent usage of cached query results.
616
+ # Example factors include but not limited to: DDL/DML, non-deterministic SQL function calls, update of
617
+ # referenced tables/views/UDFs or imported JavaScript libraries. SQL UDFs cannot have determinism specified.
618
+ # Their determinism is automatically determined.
619
+ #
620
+ # @return [String, nil] The routine determinism level in upper case, or `nil` if not set or the object is a
621
+ # reference (see {#reference?}).
622
+ #
623
+ # @example
624
+ # require "google/cloud/bigquery"
625
+ #
626
+ # bigquery = Google::Cloud::Bigquery.new
627
+ # dataset = bigquery.dataset "my_dataset"
628
+ # routine = dataset.routine "my_routine"
629
+ #
630
+ # routine.determinism_level #=> "NOT_DETERMINISTIC"
631
+ #
632
+ # @!group Attributes
633
+ #
634
+ def determinism_level
635
+ return nil if reference?
636
+ ensure_full_data!
637
+ @gapi.determinism_level
638
+ end
639
+
640
+ ##
641
+ # Updates the JavaScript UDF determinism level. Optional.
642
+ #
643
+ # * `DETERMINISTIC` - Deterministic indicates that two calls with the same input to a UDF yield the same output.
644
+ # If all JavaScript UDFs are `DETERMINISTIC`, the query result is potentially cachable.
645
+ # * `NOT_DETERMINISTIC` - Not deterministic indicates that the output of the UDF is not guaranteed to yield the
646
+ # same output each time for a given set of inputs. If any JavaScript UDF is `NOT_DETERMINISTIC`, the query
647
+ # result is not cacheable.
648
+ #
649
+ # @param [String, nil] new_determinism_level The new routine determinism level in upper case.
650
+ #
651
+ # @example
652
+ # require "google/cloud/bigquery"
653
+ #
654
+ # bigquery = Google::Cloud::Bigquery.new
655
+ # dataset = bigquery.dataset "my_dataset"
656
+ # routine = dataset.routine "my_routine"
657
+ #
658
+ # routine.determinism_level #=> "NOT_DETERMINISTIC"
659
+ # routine.determinism_level = "DETERMINISTIC"
660
+ #
661
+ # @!group Attributes
662
+ #
663
+ def determinism_level= new_determinism_level
664
+ ensure_full_data!
665
+ @gapi.determinism_level = new_determinism_level
666
+ update_gapi!
667
+ end
668
+
669
+ ##
670
+ # Checks if the value of {#determinism_level} is `DETERMINISTIC`. The default is `false`.
671
+ #
672
+ # @return [Boolean] `true` when `DETERMINISTIC` and the object is not a reference (see {#reference?}), `false`
673
+ # otherwise.
674
+ #
675
+ # @!group Attributes
676
+ #
677
+ def determinism_level_deterministic?
678
+ @gapi.determinism_level == "DETERMINISTIC"
679
+ end
680
+
681
+ ##
682
+ # Checks if the value of {#determinism_level} is `NOT_DETERMINISTIC`. The default is `false`.
683
+ #
684
+ # @return [Boolean] `true` when `NOT_DETERMINISTIC` and the object is not a reference (see {#reference?}),
685
+ # `false` otherwise.
686
+ #
687
+ # @!group Attributes
688
+ #
689
+ def determinism_level_not_deterministic?
690
+ @gapi.determinism_level == "NOT_DETERMINISTIC"
691
+ end
692
+
606
693
  ##
607
694
  # Updates the routine with changes made in the given block in a single update request. The following attributes
608
695
  # may be set: {Updater#routine_type=}, {Updater#language=}, {Updater#arguments=}, {Updater#return_type=},
@@ -999,7 +1086,9 @@ module Google
999
1086
  # routine = dataset.routine "my_routine"
1000
1087
  #
1001
1088
  # routine.return_type.type_kind #=> "INT64"
1002
- # routine.return_type = "STRING"
1089
+ # routine.update do |r|
1090
+ # r.return_type = "STRING"
1091
+ # end
1003
1092
  #
1004
1093
  def return_type= new_return_type
1005
1094
  @gapi.return_type = StandardSql::DataType.gapi_from_string_or_data_type new_return_type
@@ -1019,9 +1108,11 @@ module Google
1019
1108
  # dataset = bigquery.dataset "my_dataset"
1020
1109
  # routine = dataset.routine "my_routine"
1021
1110
  #
1022
- # routine.imported_libraries = [
1023
- # "gs://cloud-samples-data/bigquery/udfs/max-value.js"
1024
- # ]
1111
+ # routine.update do |r|
1112
+ # r.imported_libraries = [
1113
+ # "gs://cloud-samples-data/bigquery/udfs/max-value.js"
1114
+ # ]
1115
+ # end
1025
1116
  #
1026
1117
  def imported_libraries= new_imported_libraries
1027
1118
  @gapi.imported_libraries = new_imported_libraries
@@ -1069,12 +1160,43 @@ module Google
1069
1160
  # routine = dataset.routine "my_routine"
1070
1161
  #
1071
1162
  # routine.description #=> "My routine description"
1072
- # routine.description = "My updated routine description"
1163
+ # routine.update do |r|
1164
+ # r.description = "My updated routine description"
1165
+ # end
1073
1166
  #
1074
1167
  def description= new_description
1075
1168
  @gapi.description = new_description
1076
1169
  end
1077
1170
 
1171
+ ##
1172
+ # Updates the JavaScript UDF determinism level. Optional.
1173
+ #
1174
+ # * `DETERMINISTIC` - Deterministic indicates that two calls with the same input to a UDF yield the same
1175
+ # output. If all JavaScript UDFs are `DETERMINISTIC`, the query result is potentially cachable.
1176
+ # * `NOT_DETERMINISTIC` - Not deterministic indicates that the output of the UDF is not guaranteed to yield
1177
+ # the same output each time for a given set of inputs. If any JavaScript UDF is `NOT_DETERMINISTIC`, the
1178
+ # query result is not cacheable.
1179
+ #
1180
+ # @param [String, nil] new_determinism_level The new routine determinism level in upper case.
1181
+ #
1182
+ # @example
1183
+ # require "google/cloud/bigquery"
1184
+ #
1185
+ # bigquery = Google::Cloud::Bigquery.new
1186
+ # dataset = bigquery.dataset "my_dataset"
1187
+ # routine = dataset.routine "my_routine"
1188
+ #
1189
+ # routine.determinism_level #=> "NOT_DETERMINISTIC"
1190
+ # routine.update do |r|
1191
+ # r.determinism_level = "DETERMINISTIC"
1192
+ # end
1193
+ #
1194
+ # @!group Attributes
1195
+ #
1196
+ def determinism_level= new_determinism_level
1197
+ @gapi.determinism_level = new_determinism_level
1198
+ end
1199
+
1078
1200
  def update
1079
1201
  raise "not implemented in #{self.class}"
1080
1202
  end
@@ -65,6 +65,8 @@ module Google
65
65
  service.request_options.header ||= {}
66
66
  service.request_options.header["x-goog-api-client"] = \
67
67
  "gl-ruby/#{RUBY_VERSION} gccl/#{Google::Cloud::Bigquery::VERSION}"
68
+ service.request_options.query ||= {}
69
+ service.request_options.query["prettyPrint"] = false
68
70
  service.request_options.quota_project = @quota_project if @quota_project
69
71
  service.authorization = @credentials.client
70
72
  service.root_url = host if host
@@ -180,6 +182,34 @@ module Google
180
182
  end
181
183
  end
182
184
 
185
+ ##
186
+ # Returns Google::Apis::BigqueryV2::Policy
187
+ def get_table_policy dataset_id, table_id
188
+ policy_options = API::GetPolicyOptions.new requested_policy_version: 1
189
+ execute do
190
+ service.get_table_iam_policy table_path(dataset_id, table_id),
191
+ API::GetIamPolicyRequest.new(options: policy_options)
192
+ end
193
+ end
194
+
195
+ ##
196
+ # @param [Google::Apis::BigqueryV2::Policy] new_policy
197
+ def set_table_policy dataset_id, table_id, new_policy
198
+ execute do
199
+ service.set_table_iam_policy table_path(dataset_id, table_id),
200
+ API::SetIamPolicyRequest.new(policy: new_policy)
201
+ end
202
+ end
203
+
204
+ ##
205
+ # Returns Google::Apis::BigqueryV2::TestIamPermissionsResponse
206
+ def test_table_permissions dataset_id, table_id, permissions
207
+ execute do
208
+ service.test_table_iam_permissions table_path(dataset_id, table_id),
209
+ API::TestIamPermissionsRequest.new(permissions: permissions)
210
+ end
211
+ end
212
+
183
213
  ##
184
214
  # Deletes the table specified by tableId from the dataset.
185
215
  # If the table contains data, all the data will be deleted.
@@ -506,6 +536,11 @@ module Google
506
536
 
507
537
  protected
508
538
 
539
+ # Creates a formatted table path.
540
+ def table_path dataset_id, table_id
541
+ "projects/#{@project}/datasets/#{dataset_id}/tables/#{table_id}"
542
+ end
543
+
509
544
  # Generate a random string similar to the BigQuery service job IDs.
510
545
  def generate_id
511
546
  SecureRandom.urlsafe_base64 21
@@ -23,6 +23,7 @@ require "google/cloud/bigquery/external"
23
23
  require "google/cloud/bigquery/insert_response"
24
24
  require "google/cloud/bigquery/table/async_inserter"
25
25
  require "google/cloud/bigquery/convert"
26
+ require "google/cloud/bigquery/policy"
26
27
  require "google/apis/bigquery_v2"
27
28
 
28
29
  module Google
@@ -36,16 +37,16 @@ module Google
36
37
  # repeated fields.
37
38
  #
38
39
  # The Table class can also represent a
39
- # [view](https://cloud.google.com/bigquery/docs/views), which is a virtual
40
- # table defined by a SQL query. BigQuery's views are logical views, not
41
- # materialized views, which means that the query that defines the view is
42
- # re-executed every time the view is queried. Queries are billed according
43
- # to the total amount of data in all table fields referenced directly or
44
- # indirectly by the top-level query. (See {#view?}, {#query}, {#query=},
45
- # and {Dataset#create_view}.)
40
+ # [logical view](https://cloud.google.com/bigquery/docs/views), which is a virtual
41
+ # table defined by a SQL query (see {#view?} and {Dataset#create_view}); or a
42
+ # [materialized view](https://cloud.google.com/bigquery/docs/materialized-views-intro),
43
+ # which is a precomputed view that periodically caches results of a query for increased
44
+ # performance and efficiency (see {#materialized_view?} and {Dataset#create_materialized_view}).
46
45
  #
47
46
  # @see https://cloud.google.com/bigquery/docs/loading-data#loading_denormalized_nested_and_repeated_data
48
47
  # Loading denormalized, nested, and repeated data
48
+ # @see https://cloud.google.com/bigquery/docs/views Creating views
49
+ # @see https://cloud.google.com/bigquery/docs/materialized-views-intro Introduction to materialized views
49
50
  #
50
51
  # @example
51
52
  # require "google/cloud/bigquery"
@@ -76,7 +77,7 @@ module Google
76
77
  # }
77
78
  # table.insert row
78
79
  #
79
- # @example Creating a BigQuery view:
80
+ # @example Creating a logical view:
80
81
  # require "google/cloud/bigquery"
81
82
  #
82
83
  # bigquery = Google::Cloud::Bigquery.new
@@ -85,6 +86,15 @@ module Google
85
86
  # "SELECT name, age FROM `my_project.my_dataset.my_table`"
86
87
  # view.view? # true
87
88
  #
89
+ # @example Creating a materialized view:
90
+ # require "google/cloud/bigquery"
91
+ #
92
+ # bigquery = Google::Cloud::Bigquery.new
93
+ # dataset = bigquery.dataset "my_dataset"
94
+ # view = dataset.create_materialized_view "my_materialized_view",
95
+ # "SELECT name, age FROM `my_project.my_dataset.my_table`"
96
+ # view.materialized_view? # true
97
+ #
88
98
  class Table
89
99
  ##
90
100
  # @private The Service object.
@@ -250,9 +260,10 @@ module Google
250
260
  # The period for which the table is time partitioned, if any. See
251
261
  # [Partitioned Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
252
262
  #
253
- # @return [String, nil] The time partition type. Currently the only supported
254
- # value is "DAY", or `nil` if the object is a reference (see
255
- # {#reference?}).
263
+ # @return [String, nil] The time partition type. The supported types are `DAY`,
264
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
265
+ # hour, month, and year, respectively; or `nil` if not set or the object is a
266
+ # reference (see {#reference?}).
256
267
  #
257
268
  # @!group Attributes
258
269
  #
@@ -265,13 +276,16 @@ module Google
265
276
  ##
266
277
  # Sets the time partitioning type for the table. See [Partitioned
267
278
  # Tables](https://cloud.google.com/bigquery/docs/partitioned-tables).
279
+ # The supported types are `DAY`, `HOUR`, `MONTH`, and `YEAR`, which will
280
+ # generate one partition per day, hour, month, and year, respectively.
268
281
  #
269
282
  # You can only set time partitioning when creating a table as in
270
283
  # the example below. BigQuery does not allow you to change time partitioning
271
284
  # on an existing table.
272
285
  #
273
- # @param [String] type The time partition type. Currently the only
274
- # supported value is "DAY".
286
+ # @param [String] type The time partition type. The supported types are `DAY`,
287
+ # `HOUR`, `MONTH`, and `YEAR`, which will generate one partition per day,
288
+ # hour, month, and year, respectively.
275
289
  #
276
290
  # @example
277
291
  # require "google/cloud/bigquery"
@@ -721,7 +735,7 @@ module Google
721
735
  end
722
736
 
723
737
  ##
724
- # Checks if the table's type is "TABLE".
738
+ # Checks if the table's type is `TABLE`.
725
739
  #
726
740
  # @return [Boolean, nil] `true` when the type is `TABLE`, `false`
727
741
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -735,8 +749,10 @@ module Google
735
749
  end
736
750
 
737
751
  ##
738
- # Checks if the table's type is "VIEW", indicating that the table
739
- # represents a BigQuery view. See {Dataset#create_view}.
752
+ # Checks if the table's type is `VIEW`, indicating that the table
753
+ # represents a BigQuery logical view. See {Dataset#create_view}.
754
+ #
755
+ # @see https://cloud.google.com/bigquery/docs/views Creating views
740
756
  #
741
757
  # @return [Boolean, nil] `true` when the type is `VIEW`, `false`
742
758
  # otherwise, if the object is a resource (see {#resource?}); `nil` if
@@ -750,7 +766,25 @@ module Google
750
766
  end
751
767
 
752
768
  ##
753
- # Checks if the table's type is "EXTERNAL", indicating that the table
769
+ # Checks if the table's type is `MATERIALIZED_VIEW`, indicating that
770
+ # the table represents a BigQuery materialized view.
771
+ # See {Dataset#create_materialized_view}.
772
+ #
773
+ # @see https://cloud.google.com/bigquery/docs/materialized-views-intro Introduction to materialized views
774
+ #
775
+ # @return [Boolean, nil] `true` when the type is `MATERIALIZED_VIEW`,
776
+ # `false` otherwise, if the object is a resource (see {#resource?});
777
+ # `nil` if the object is a reference (see {#reference?}).
778
+ #
779
+ # @!group Attributes
780
+ #
781
+ def materialized_view?
782
+ return nil if reference?
783
+ @gapi.type == "MATERIALIZED_VIEW"
784
+ end
785
+
786
+ ##
787
+ # Checks if the table's type is `EXTERNAL`, indicating that the table
754
788
  # represents an External Data Source. See {#external?} and
755
789
  # {External::DataSource}.
756
790
  #
@@ -1133,21 +1167,24 @@ module Google
1133
1167
  end
1134
1168
 
1135
1169
  ##
1136
- # The query that executes each time the view is loaded.
1170
+ # The query that defines the view or materialized view. See {#view?} and
1171
+ # {#materialized_view?}.
1137
1172
  #
1138
- # @return [String] The query that defines the view.
1173
+ # @return [String, nil] The query that defines the view or materialized_view;
1174
+ # or `nil` if not a view or materialized view.
1139
1175
  #
1140
1176
  # @!group Attributes
1141
1177
  #
1142
1178
  def query
1143
- @gapi.view&.query
1179
+ view? ? @gapi.view&.query : @gapi.materialized_view&.query
1144
1180
  end
1145
1181
 
1146
1182
  ##
1147
- # Updates the query that executes each time the view is loaded.
1183
+ # Updates the query that defines the view. (See {#view?}.) Not supported
1184
+ # for materialized views.
1148
1185
  #
1149
- # This sets the query using standard SQL. To specify legacy SQL or to
1150
- # use user-defined function resources use (#set_query) instead.
1186
+ # This method sets the query using standard SQL. To specify legacy SQL or
1187
+ # to use user-defined function resources for a view, use (#set_query) instead.
1151
1188
  #
1152
1189
  # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1153
1190
  # Reference
@@ -1162,7 +1199,7 @@ module Google
1162
1199
  # view = dataset.table "my_view"
1163
1200
  #
1164
1201
  # view.query = "SELECT first_name FROM " \
1165
- # "`my_project.my_dataset.my_table`"
1202
+ # "`my_project.my_dataset.my_table`"
1166
1203
  #
1167
1204
  # @!group Lifecycle
1168
1205
  #
@@ -1171,12 +1208,12 @@ module Google
1171
1208
  end
1172
1209
 
1173
1210
  ##
1174
- # Updates the query that executes each time the view is loaded. Allows
1175
- # setting of standard vs. legacy SQL and user-defined function
1176
- # resources.
1211
+ # Updates the query that defines the view. (See {#view?}.) Not supported for
1212
+ # materialized views.
1177
1213
  #
1178
- # @see https://cloud.google.com/bigquery/query-reference BigQuery Query
1179
- # Reference
1214
+ # Allows setting of standard vs. legacy SQL and user-defined function resources.
1215
+ #
1216
+ # @see https://cloud.google.com/bigquery/query-reference BigQuery Query Reference
1180
1217
  #
1181
1218
  # @param [String] query The query that defines the view.
1182
1219
  # @param [Boolean] standard_sql Specifies whether to use BigQuery's
@@ -1188,11 +1225,12 @@ module Google
1188
1225
  # SQL](https://cloud.google.com/bigquery/docs/reference/legacy-sql)
1189
1226
  # dialect. Optional. The default value is false.
1190
1227
  # @param [Array<String>, String] udfs User-defined function resources
1191
- # used in a legacy SQL query. May be either a code resource to load from
1192
- # a Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
1193
- # that contains code for a user-defined function (UDF). Providing an
1194
- # inline code resource is equivalent to providing a URI for a file
1195
- # containing the same code.
1228
+ # used in a legacy SQL query. Optional.
1229
+ #
1230
+ # May be either a code resource to load from a Google Cloud Storage URI
1231
+ # (`gs://bucket/path`), or an inline resource that contains code for a
1232
+ # user-defined function (UDF). Providing an inline code resource is equivalent
1233
+ # to providing a URI for a file containing the same code.
1196
1234
  #
1197
1235
  # This parameter is used for defining User Defined Function (UDF)
1198
1236
  # resources only when using legacy SQL. Users of standard SQL should
@@ -1203,7 +1241,7 @@ module Google
1203
1241
  # standard SQL - Differences in user-defined JavaScript
1204
1242
  # functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#differences_in_user-defined_javascript_functions)
1205
1243
  #
1206
- # @example
1244
+ # @example Update a view:
1207
1245
  # require "google/cloud/bigquery"
1208
1246
  #
1209
1247
  # bigquery = Google::Cloud::Bigquery.new
@@ -1211,12 +1249,13 @@ module Google
1211
1249
  # view = dataset.table "my_view"
1212
1250
  #
1213
1251
  # view.set_query "SELECT first_name FROM " \
1214
- # "`my_project.my_dataset.my_table`",
1252
+ # "`my_project.my_dataset.my_table`",
1215
1253
  # standard_sql: true
1216
1254
  #
1217
1255
  # @!group Lifecycle
1218
1256
  #
1219
1257
  def set_query query, standard_sql: nil, legacy_sql: nil, udfs: nil
1258
+ raise "Updating the query is not supported for Table type: #{@gapi.type}" unless view?
1220
1259
  use_legacy_sql = Convert.resolve_legacy_sql standard_sql, legacy_sql
1221
1260
  @gapi.view = Google::Apis::BigqueryV2::ViewDefinition.new(
1222
1261
  query: query,
@@ -1227,26 +1266,28 @@ module Google
1227
1266
  end
1228
1267
 
1229
1268
  ##
1230
- # Checks if the view's query is using legacy sql.
1269
+ # Checks if the view's query is using legacy sql. See {#view?}.
1231
1270
  #
1232
- # @return [Boolean] `true` when legacy sql is used, `false` otherwise.
1271
+ # @return [Boolean] `true` when legacy sql is used, `false` otherwise; or `nil` if not a logical view.
1233
1272
  #
1234
1273
  # @!group Attributes
1235
1274
  #
1236
1275
  def query_legacy_sql?
1276
+ return nil unless @gapi.view
1237
1277
  val = @gapi.view.use_legacy_sql
1238
1278
  return true if val.nil?
1239
1279
  val
1240
1280
  end
1241
1281
 
1242
1282
  ##
1243
- # Checks if the view's query is using standard sql.
1283
+ # Checks if the view's query is using standard sql. See {#view?}.
1244
1284
  #
1245
1285
  # @return [Boolean] `true` when standard sql is used, `false` otherwise.
1246
1286
  #
1247
1287
  # @!group Attributes
1248
1288
  #
1249
1289
  def query_standard_sql?
1290
+ return nil unless @gapi.view
1250
1291
  !query_legacy_sql?
1251
1292
  end
1252
1293
 
@@ -1258,18 +1299,193 @@ module Google
1258
1299
  # equivalent to providing a URI for a file containing the same code. See
1259
1300
  # [User-Defined
1260
1301
  # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
1302
+ # See {#view?}.
1261
1303
  #
1262
- # @return [Array<String>] An array containing Google Cloud Storage URIs
1263
- # and/or inline source code.
1304
+ # @return [Array<String>, nil] An array containing Google Cloud Storage URIs
1305
+ # and/or inline source code, or `nil` if not a logical view.
1264
1306
  #
1265
1307
  # @!group Attributes
1266
1308
  #
1267
1309
  def query_udfs
1310
+ return nil unless @gapi.view
1268
1311
  udfs_gapi = @gapi.view.user_defined_function_resources
1269
1312
  return [] if udfs_gapi.nil?
1270
1313
  Array(udfs_gapi).map { |udf| udf.inline_code || udf.resource_uri }
1271
1314
  end
1272
1315
 
1316
+ ##
1317
+ # Whether automatic refresh of the materialized view is enabled. When true,
1318
+ # the materialized view is updated when the base table is updated. The default
1319
+ # value is true. See {#materialized_view?}.
1320
+ #
1321
+ # @return [Boolean, nil] `true` when automatic refresh is enabled, `false` otherwise;
1322
+ # or `nil` if not a materialized view.
1323
+ #
1324
+ # @!group Attributes
1325
+ #
1326
+ def enable_refresh?
1327
+ return nil unless @gapi.materialized_view
1328
+ val = @gapi.materialized_view.enable_refresh
1329
+ return true if val.nil?
1330
+ val
1331
+ end
1332
+
1333
+ ##
1334
+ # Sets whether automatic refresh of the materialized view is enabled. When true,
1335
+ # the materialized view is updated when the base table is updated. See {#materialized_view?}.
1336
+ #
1337
+ # @param [Boolean] new_enable_refresh `true` when automatic refresh is enabled, `false` otherwise.
1338
+ #
1339
+ # @!group Attributes
1340
+ #
1341
+ def enable_refresh= new_enable_refresh
1342
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1343
+ enable_refresh: new_enable_refresh
1344
+ )
1345
+ patch_gapi! :materialized_view
1346
+ end
1347
+
1348
+ ##
1349
+ # The time when the materialized view was last modified.
1350
+ # See {#materialized_view?}.
1351
+ #
1352
+ # @return [Time, nil] The time, or `nil` if not present or not a materialized view.
1353
+ #
1354
+ # @!group Attributes
1355
+ #
1356
+ def last_refresh_time
1357
+ Convert.millis_to_time @gapi.materialized_view&.last_refresh_time
1358
+ end
1359
+
1360
+ ##
1361
+ # The maximum frequency in milliseconds at which the materialized view will be refreshed.
1362
+ # See {#materialized_view?}.
1363
+ #
1364
+ # @return [Integer, nil] The maximum frequency in milliseconds;
1365
+ # or `nil` if not a materialized view.
1366
+ #
1367
+ # @!group Attributes
1368
+ #
1369
+ def refresh_interval_ms
1370
+ @gapi.materialized_view&.refresh_interval_ms
1371
+ end
1372
+
1373
+ ##
1374
+ # Sets the maximum frequency at which the materialized view will be refreshed.
1375
+ # See {#materialized_view?}.
1376
+ #
1377
+ # @param [Integer] new_refresh_interval_ms The maximum frequency in milliseconds.
1378
+ #
1379
+ # @!group Attributes
1380
+ #
1381
+ def refresh_interval_ms= new_refresh_interval_ms
1382
+ @gapi.materialized_view = Google::Apis::BigqueryV2::MaterializedViewDefinition.new(
1383
+ refresh_interval_ms: new_refresh_interval_ms
1384
+ )
1385
+ patch_gapi! :materialized_view
1386
+ end
1387
+
1388
+ ##
1389
+ # Gets the Cloud IAM access control policy for the table. The latest policy will be read from the service. See
1390
+ # also {#update_policy}.
1391
+ #
1392
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
1393
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
1394
+ #
1395
+ # @return [Policy] The frozen policy for the table.
1396
+ #
1397
+ # @example
1398
+ # require "google/cloud/bigquery"
1399
+ #
1400
+ # bigquery = Google::Cloud::Bigquery.new
1401
+ # dataset = bigquery.dataset "my_dataset"
1402
+ # table = dataset.table "my_table"
1403
+ #
1404
+ # policy = table.policy
1405
+ #
1406
+ # policy.frozen? #=> true
1407
+ # binding_owner = policy.bindings.find { |b| b.role == "roles/owner" }
1408
+ # binding_owner.role #=> "roles/owner"
1409
+ # binding_owner.members #=> ["user:owner@example.com"]
1410
+ # binding_owner.frozen? #=> true
1411
+ # binding_owner.members.frozen? #=> true
1412
+ #
1413
+ def policy
1414
+ raise ArgumentError, "Block argument not supported: Use #update_policy instead." if block_given?
1415
+ ensure_service!
1416
+ gapi = service.get_table_policy dataset_id, table_id
1417
+ Policy.from_gapi(gapi).freeze
1418
+ end
1419
+
1420
+ ##
1421
+ # Updates the Cloud IAM access control policy for the table. The latest policy will be read from the service.
1422
+ # See also {#policy}.
1423
+ #
1424
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
1425
+ # @see https://cloud.google.com/bigquery/docs/table-access-controls-intro Controlling access to tables
1426
+ #
1427
+ # @yield [policy] A block for updating the policy. The latest policy will be read from the service and passed to
1428
+ # the block. After the block completes, the modified policy will be written to the service.
1429
+ # @yieldparam [Policy] policy The mutable Policy for the table.
1430
+ #
1431
+ # @return [Policy] The updated and frozen policy for the table.
1432
+ #
1433
+ # @example Update the policy by passing a block.
1434
+ # require "google/cloud/bigquery"
1435
+ #
1436
+ # bigquery = Google::Cloud::Bigquery.new
1437
+ # dataset = bigquery.dataset "my_dataset"
1438
+ # table = dataset.table "my_table"
1439
+ #
1440
+ # table.update_policy do |p|
1441
+ # p.grant role: "roles/viewer", members: "user:viewer@example.com"
1442
+ # p.revoke role: "roles/editor", members: "user:editor@example.com"
1443
+ # p.revoke role: "roles/owner"
1444
+ # end # 2 API calls
1445
+ #
1446
+ def update_policy
1447
+ raise ArgumentError, "A block updating the policy must be provided" unless block_given?
1448
+ ensure_service!
1449
+ gapi = service.get_table_policy dataset_id, table_id
1450
+ policy = Policy.from_gapi gapi
1451
+ yield policy
1452
+ # TODO: Check for changes before calling RPC
1453
+ gapi = service.set_table_policy dataset_id, table_id, policy.to_gapi
1454
+ Policy.from_gapi(gapi).freeze
1455
+ end
1456
+
1457
+ ##
1458
+ # Tests the specified permissions against the [Cloud
1459
+ # IAM](https://cloud.google.com/iam/) access control policy.
1460
+ #
1461
+ # @see https://cloud.google.com/iam/docs/managing-policies Managing Policies
1462
+ #
1463
+ # @param [String, Array<String>] permissions The set of permissions
1464
+ # against which to check access. Permissions must be of the format
1465
+ # `bigquery.resource.capability`.
1466
+ # See https://cloud.google.com/bigquery/docs/access-control#bigquery.
1467
+ #
1468
+ # @return [Array<String>] The frozen array of permissions held by the caller.
1469
+ #
1470
+ # @example
1471
+ # require "google/cloud/bigquery"
1472
+ #
1473
+ # bigquery = Google::Cloud::Bigquery.new
1474
+ # dataset = bigquery.dataset "my_dataset"
1475
+ # table = dataset.table "my_table"
1476
+ #
1477
+ # permissions = table.test_iam_permissions "bigquery.tables.get",
1478
+ # "bigquery.tables.delete"
1479
+ # permissions.include? "bigquery.tables.get" #=> true
1480
+ # permissions.include? "bigquery.tables.delete" #=> false
1481
+ #
1482
+ def test_iam_permissions *permissions
1483
+ permissions = Array(permissions).flatten
1484
+ ensure_service!
1485
+ gapi = service.test_table_permissions dataset_id, table_id, permissions
1486
+ gapi.permissions.freeze
1487
+ end
1488
+
1273
1489
  ##
1274
1490
  # Retrieves data from the table.
1275
1491
  #