google-cloud-bigquery 1.23.0 → 1.28.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
  #