google-cloud-bigquery 1.12.0 → 1.38.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/AUTHENTICATION.md +9 -28
  3. data/CHANGELOG.md +372 -1
  4. data/CONTRIBUTING.md +328 -116
  5. data/LOGGING.md +2 -2
  6. data/OVERVIEW.md +21 -20
  7. data/TROUBLESHOOTING.md +2 -8
  8. data/lib/google/cloud/bigquery/argument.rb +197 -0
  9. data/lib/google/cloud/bigquery/convert.rb +154 -170
  10. data/lib/google/cloud/bigquery/copy_job.rb +40 -23
  11. data/lib/google/cloud/bigquery/credentials.rb +5 -12
  12. data/lib/google/cloud/bigquery/data.rb +109 -18
  13. data/lib/google/cloud/bigquery/dataset/access.rb +322 -51
  14. data/lib/google/cloud/bigquery/dataset/list.rb +7 -13
  15. data/lib/google/cloud/bigquery/dataset.rb +960 -279
  16. data/lib/google/cloud/bigquery/external/avro_source.rb +107 -0
  17. data/lib/google/cloud/bigquery/external/bigtable_source/column.rb +404 -0
  18. data/lib/google/cloud/bigquery/external/bigtable_source/column_family.rb +945 -0
  19. data/lib/google/cloud/bigquery/external/bigtable_source.rb +230 -0
  20. data/lib/google/cloud/bigquery/external/csv_source.rb +481 -0
  21. data/lib/google/cloud/bigquery/external/data_source.rb +771 -0
  22. data/lib/google/cloud/bigquery/external/json_source.rb +170 -0
  23. data/lib/google/cloud/bigquery/external/parquet_source.rb +148 -0
  24. data/lib/google/cloud/bigquery/external/sheets_source.rb +166 -0
  25. data/lib/google/cloud/bigquery/external.rb +50 -2256
  26. data/lib/google/cloud/bigquery/extract_job.rb +217 -58
  27. data/lib/google/cloud/bigquery/insert_response.rb +1 -3
  28. data/lib/google/cloud/bigquery/job/list.rb +13 -20
  29. data/lib/google/cloud/bigquery/job.rb +286 -11
  30. data/lib/google/cloud/bigquery/load_job.rb +801 -133
  31. data/lib/google/cloud/bigquery/model/list.rb +5 -9
  32. data/lib/google/cloud/bigquery/model.rb +247 -16
  33. data/lib/google/cloud/bigquery/policy.rb +432 -0
  34. data/lib/google/cloud/bigquery/project/list.rb +6 -11
  35. data/lib/google/cloud/bigquery/project.rb +526 -243
  36. data/lib/google/cloud/bigquery/query_job.rb +584 -125
  37. data/lib/google/cloud/bigquery/routine/list.rb +165 -0
  38. data/lib/google/cloud/bigquery/routine.rb +1227 -0
  39. data/lib/google/cloud/bigquery/schema/field.rb +413 -63
  40. data/lib/google/cloud/bigquery/schema.rb +221 -48
  41. data/lib/google/cloud/bigquery/service.rb +186 -109
  42. data/lib/google/cloud/bigquery/standard_sql.rb +269 -53
  43. data/lib/google/cloud/bigquery/table/async_inserter.rb +86 -42
  44. data/lib/google/cloud/bigquery/table/list.rb +6 -11
  45. data/lib/google/cloud/bigquery/table.rb +1188 -326
  46. data/lib/google/cloud/bigquery/time.rb +6 -0
  47. data/lib/google/cloud/bigquery/version.rb +1 -1
  48. data/lib/google/cloud/bigquery.rb +18 -8
  49. data/lib/google-cloud-bigquery.rb +15 -13
  50. metadata +67 -40
@@ -0,0 +1,1227 @@
1
+ # Copyright 2020 Google LLC
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # https://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+
15
+
16
+ # require "google/cloud/errors"
17
+ require "google/cloud/bigquery/convert"
18
+ require "google/cloud/bigquery/service"
19
+ require "google/cloud/bigquery/routine/list"
20
+ require "google/cloud/bigquery/argument"
21
+
22
+ module Google
23
+ module Cloud
24
+ module Bigquery
25
+ ##
26
+ # # Routine
27
+ #
28
+ # A user-defined function or a stored procedure.
29
+ #
30
+ # @example Creating a new routine:
31
+ # require "google/cloud/bigquery"
32
+ #
33
+ # bigquery = Google::Cloud::Bigquery.new
34
+ # dataset = bigquery.dataset "my_dataset"
35
+ #
36
+ # routine = dataset.create_routine "my_routine" do |r|
37
+ # r.routine_type = "SCALAR_FUNCTION"
38
+ # r.language = "SQL"
39
+ # r.arguments = [
40
+ # Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
41
+ # ]
42
+ # r.body = "x * 3"
43
+ # r.description = "My routine description"
44
+ # end
45
+ #
46
+ # puts routine.routine_id
47
+ #
48
+ # @example Extended example:
49
+ # require "google/cloud/bigquery"
50
+ #
51
+ # bigquery = Google::Cloud::Bigquery.new
52
+ # dataset = bigquery.dataset "my_dataset"
53
+ # routine = dataset.create_routine "my_routine" do |r|
54
+ # r.routine_type = "SCALAR_FUNCTION"
55
+ # r.language = :SQL
56
+ # r.body = "(SELECT SUM(IF(elem.name = \"foo\",elem.val,null)) FROM UNNEST(arr) AS elem)"
57
+ # r.arguments = [
58
+ # Google::Cloud::Bigquery::Argument.new(
59
+ # name: "arr",
60
+ # argument_kind: "FIXED_TYPE",
61
+ # data_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
62
+ # type_kind: "ARRAY",
63
+ # array_element_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
64
+ # type_kind: "STRUCT",
65
+ # struct_type: Google::Cloud::Bigquery::StandardSql::StructType.new(
66
+ # fields: [
67
+ # Google::Cloud::Bigquery::StandardSql::Field.new(
68
+ # name: "name",
69
+ # type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "STRING")
70
+ # ),
71
+ # Google::Cloud::Bigquery::StandardSql::Field.new(
72
+ # name: "val",
73
+ # type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "INT64")
74
+ # )
75
+ # ]
76
+ # )
77
+ # )
78
+ # )
79
+ # )
80
+ # ]
81
+ # end
82
+ #
83
+ # @example Retrieving and updating an existing routine:
84
+ # require "google/cloud/bigquery"
85
+ #
86
+ # bigquery = Google::Cloud::Bigquery.new
87
+ # dataset = bigquery.dataset "my_dataset"
88
+ # routine = dataset.routine "my_routine"
89
+ #
90
+ # routine.update do |r|
91
+ # r.body = "x * 4"
92
+ # r.description = "My new routine description"
93
+ # end
94
+ #
95
+ class Routine
96
+ ##
97
+ # @private The Service object.
98
+ attr_accessor :service
99
+
100
+ ##
101
+ # @private The Google API Client object.
102
+ attr_accessor :gapi
103
+
104
+ ##
105
+ # @private A Google API Client Dataset Reference object.
106
+ attr_reader :reference
107
+
108
+ ##
109
+ # @private Creates an empty Routine object.
110
+ def initialize
111
+ @service = nil
112
+ @gapi = nil
113
+ @reference = nil
114
+ end
115
+
116
+ ##
117
+ # A unique ID for this routine, without the project name.
118
+ #
119
+ # @return [String] The ID must contain only letters (`[A-Za-z]`), numbers (`[0-9]`), or underscores (`_`). The
120
+ # maximum length is 256 characters.
121
+ #
122
+ # @!group Attributes
123
+ #
124
+ def routine_id
125
+ return reference.routine_id if reference?
126
+ @gapi.routine_reference.routine_id
127
+ end
128
+
129
+ ##
130
+ # The ID of the dataset containing this routine.
131
+ #
132
+ # @return [String] The dataset ID.
133
+ #
134
+ # @!group Attributes
135
+ #
136
+ def dataset_id
137
+ return reference.dataset_id if reference?
138
+ @gapi.routine_reference.dataset_id
139
+ end
140
+
141
+ ##
142
+ # The ID of the project containing this routine.
143
+ #
144
+ # @return [String] The project ID.
145
+ #
146
+ # @!group Attributes
147
+ #
148
+ def project_id
149
+ return reference.project_id if reference?
150
+ @gapi.routine_reference.project_id
151
+ end
152
+
153
+ ##
154
+ # @private The gapi fragment containing the Project ID, Dataset ID, and Routine ID.
155
+ #
156
+ # @return [Google::Apis::BigqueryV2::RoutineReference]
157
+ #
158
+ def routine_ref
159
+ reference? ? reference : @gapi.routine_reference
160
+ end
161
+
162
+ ##
163
+ # The ETag hash of the routine.
164
+ #
165
+ # @return [String, nil] The ETag hash, or `nil` if the object is a reference (see {#reference?}).
166
+ #
167
+ # @example
168
+ # require "google/cloud/bigquery"
169
+ #
170
+ # bigquery = Google::Cloud::Bigquery.new
171
+ # dataset = bigquery.dataset "my_dataset"
172
+ # routine = dataset.routine "my_routine"
173
+ #
174
+ # routine.etag # "etag123456789"
175
+ #
176
+ # @!group Attributes
177
+ #
178
+ def etag
179
+ return nil if reference?
180
+ @gapi.etag
181
+ end
182
+
183
+ ##
184
+ # The type of routine. Required.
185
+ #
186
+ # * `SCALAR_FUNCTION` - Non-builtin permanent scalar function.
187
+ # * `PROCEDURE` - Stored procedure.
188
+ #
189
+ # @return [String, nil] The type of routine in upper case, or `nil` if the object is a reference (see
190
+ # {#reference?}).
191
+ #
192
+ # @!group Attributes
193
+ #
194
+ def routine_type
195
+ return nil if reference?
196
+ @gapi.routine_type
197
+ end
198
+
199
+ ##
200
+ # Updates the type of routine. Required.
201
+ #
202
+ # * `SCALAR_FUNCTION` - Non-builtin permanent scalar function.
203
+ # * `PROCEDURE` - Stored procedure.
204
+ #
205
+ # @param [String] new_routine_type The new type of the routine in upper case.
206
+ #
207
+ # @!group Attributes
208
+ #
209
+ def routine_type= new_routine_type
210
+ ensure_full_data!
211
+ @gapi.routine_type = new_routine_type
212
+ update_gapi!
213
+ end
214
+
215
+ ##
216
+ # Checks if the value of {#routine_type} is `PROCEDURE`. The default is `false`.
217
+ #
218
+ # @return [Boolean] `true` when `PROCEDURE` and the object is not a reference (see {#reference?}), `false`
219
+ # otherwise.
220
+ #
221
+ # @!group Attributes
222
+ #
223
+ def procedure?
224
+ @gapi.routine_type == "PROCEDURE"
225
+ end
226
+
227
+ ##
228
+ # Checks if the value of {#routine_type} is `SCALAR_FUNCTION`. The default is `true`.
229
+ #
230
+ # @return [Boolean] `true` when `SCALAR_FUNCTION` and the object is not a reference (see {#reference?}), `false`
231
+ # otherwise.
232
+ #
233
+ # @!group Attributes
234
+ #
235
+ def scalar_function?
236
+ @gapi.routine_type == "SCALAR_FUNCTION"
237
+ end
238
+
239
+ ##
240
+ # The time when this routine was created.
241
+ #
242
+ # @return [Time, nil] The creation time, or `nil` if the object is a reference (see {#reference?}).
243
+ #
244
+ # @!group Attributes
245
+ #
246
+ def created_at
247
+ return nil if reference?
248
+ Convert.millis_to_time @gapi.creation_time
249
+ end
250
+
251
+ ##
252
+ # The time when this routine was last modified.
253
+ #
254
+ # @return [Time, nil] The last modified time, or `nil` if the object is a reference (see {#reference?}).
255
+ #
256
+ # @!group Attributes
257
+ #
258
+ def modified_at
259
+ return nil if reference?
260
+ Convert.millis_to_time @gapi.last_modified_time
261
+ end
262
+
263
+ ##
264
+ # The programming language of routine. Optional. Defaults to "SQL".
265
+ #
266
+ # * `SQL` - SQL language.
267
+ # * `JAVASCRIPT` - JavaScript language.
268
+ #
269
+ # @return [String, nil] The language in upper case, or `nil` if the object is a reference (see {#reference?}).
270
+ #
271
+ # @!group Attributes
272
+ #
273
+ def language
274
+ return nil if reference?
275
+ @gapi.language
276
+ end
277
+
278
+ ##
279
+ # Updates the programming language of routine. Optional. Defaults to "SQL".
280
+ #
281
+ # * `SQL` - SQL language.
282
+ # * `JAVASCRIPT` - JavaScript language.
283
+ #
284
+ # @param [String] new_language The new language in upper case.
285
+ #
286
+ # @!group Attributes
287
+ #
288
+ def language= new_language
289
+ ensure_full_data!
290
+ @gapi.language = new_language
291
+ update_gapi!
292
+ end
293
+
294
+ ##
295
+ # Checks if the value of {#language} is `JAVASCRIPT`. The default is `false`.
296
+ #
297
+ # @return [Boolean] `true` when `JAVASCRIPT` and the object is not a reference (see {#reference?}), `false`
298
+ # otherwise.
299
+ #
300
+ # @!group Attributes
301
+ #
302
+ def javascript?
303
+ @gapi.language == "JAVASCRIPT"
304
+ end
305
+
306
+ ##
307
+ # Checks if the value of {#language} is `SQL`. The default is `true`.
308
+ #
309
+ # @return [Boolean] `true` when `SQL` and the object is not a reference (see {#reference?}), `false`
310
+ # otherwise.
311
+ #
312
+ # @!group Attributes
313
+ #
314
+ def sql?
315
+ return true if @gapi.language.nil?
316
+ @gapi.language == "SQL"
317
+ end
318
+
319
+ ##
320
+ # The input/output arguments of the routine. Optional.
321
+ #
322
+ # @return [Array<Argument>, nil] An array of argument objects, or `nil` if the object is a reference (see
323
+ # {#reference?}).
324
+ #
325
+ # @example
326
+ # require "google/cloud/bigquery"
327
+ #
328
+ # bigquery = Google::Cloud::Bigquery.new
329
+ # dataset = bigquery.dataset "my_dataset"
330
+ # routine = dataset.routine "my_routine"
331
+ #
332
+ # puts "#{routine.routine_id} arguments:"
333
+ # routine.arguments.each do |arguments|
334
+ # puts "* #{arguments.name}"
335
+ # end
336
+ #
337
+ # @!group Attributes
338
+ #
339
+ def arguments
340
+ return nil if reference?
341
+ ensure_full_data!
342
+ # always return frozen arguments
343
+ Array(@gapi.arguments).map { |a| Argument.from_gapi a }.freeze
344
+ end
345
+
346
+ ##
347
+ # Updates the input/output arguments of the routine. Optional.
348
+ #
349
+ # @param [Array<Argument>] new_arguments The new arguments.
350
+ #
351
+ # @example
352
+ # require "google/cloud/bigquery"
353
+ #
354
+ # bigquery = Google::Cloud::Bigquery.new
355
+ # dataset = bigquery.dataset "my_dataset"
356
+ # routine = dataset.routine "my_routine"
357
+ #
358
+ # routine.arguments = [
359
+ # Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
360
+ # ]
361
+ #
362
+ # @!group Attributes
363
+ #
364
+ def arguments= new_arguments
365
+ ensure_full_data!
366
+ @gapi.update! arguments: new_arguments.map(&:to_gapi)
367
+ update_gapi!
368
+ end
369
+
370
+ ##
371
+ # The return type of the routine. Optional if the routine is a SQL function ({#sql?}); required otherwise.
372
+ #
373
+ # If absent, the return type is inferred from {#body} at query time in each query that references this routine.
374
+ # If present, then the evaluated result will be cast to the specified returned type at query time.
375
+ #
376
+ # For example, for the functions created with the following statements:
377
+ #
378
+ # * `CREATE FUNCTION Add(x FLOAT64, y FLOAT64) RETURNS FLOAT64 AS (x + y);`
379
+ # * `CREATE FUNCTION Increment(x FLOAT64) AS (Add(x, 1));`
380
+ # * `CREATE FUNCTION Decrement(x FLOAT64) RETURNS FLOAT64 AS (Add(x, -1));`
381
+ #
382
+ # The returnType is `{typeKind: "FLOAT64"}` for Add and Decrement, and is absent for Increment (inferred as
383
+ # `FLOAT64` at query time).
384
+ #
385
+ # Suppose the function Add is replaced by `CREATE OR REPLACE FUNCTION Add(x INT64, y INT64) AS (x + y);`
386
+ #
387
+ # Then the inferred return type of Increment is automatically changed to `INT64` at query time, while the return
388
+ # type of Decrement remains `FLOAT64`.
389
+ #
390
+ # @return [Google::Cloud::Bigquery::StandardSql::DataType, nil] The return type in upper case, or `nil` if the
391
+ # object is a reference (see {#reference?}).
392
+ #
393
+ # @example
394
+ # require "google/cloud/bigquery"
395
+ #
396
+ # bigquery = Google::Cloud::Bigquery.new
397
+ # dataset = bigquery.dataset "my_dataset"
398
+ # routine = dataset.routine "my_routine"
399
+ #
400
+ # routine.return_type.type_kind #=> "INT64"
401
+ #
402
+ # @!group Attributes
403
+ #
404
+ def return_type
405
+ return nil if reference?
406
+ ensure_full_data!
407
+ return nil unless @gapi.return_type
408
+ StandardSql::DataType.from_gapi @gapi.return_type
409
+ end
410
+
411
+ ##
412
+ # Updates the return type of the routine. Optional if the routine is a SQL function ({#sql?}); required
413
+ # otherwise.
414
+ #
415
+ # If absent, the return type is inferred from {#body} at query time in each query that references this routine.
416
+ # If present, then the evaluated result will be cast to the specified returned type at query time.
417
+ #
418
+ # For example, for the functions created with the following statements:
419
+ #
420
+ # * `CREATE FUNCTION Add(x FLOAT64, y FLOAT64) RETURNS FLOAT64 AS (x + y);`
421
+ # * `CREATE FUNCTION Increment(x FLOAT64) AS (Add(x, 1));`
422
+ # * `CREATE FUNCTION Decrement(x FLOAT64) RETURNS FLOAT64 AS (Add(x, -1));`
423
+ #
424
+ # The returnType is `{typeKind: "FLOAT64"}` for Add and Decrement, and is absent for Increment (inferred as
425
+ # `FLOAT64` at query time).
426
+ #
427
+ # Suppose the function Add is replaced by `CREATE OR REPLACE FUNCTION Add(x INT64, y INT64) AS (x + y);`
428
+ #
429
+ # Then the inferred return type of Increment is automatically changed to `INT64` at query time, while the return
430
+ # type of Decrement remains `FLOAT64`.
431
+ #
432
+ # @param [Google::Cloud::Bigquery::StandardSql::DataType, String] new_return_type The new return type for the
433
+ # routine.
434
+ #
435
+ # @example
436
+ # require "google/cloud/bigquery"
437
+ #
438
+ # bigquery = Google::Cloud::Bigquery.new
439
+ # dataset = bigquery.dataset "my_dataset"
440
+ # routine = dataset.routine "my_routine"
441
+ #
442
+ # routine.return_type.type_kind #=> "INT64"
443
+ # routine.return_type = "STRING"
444
+ #
445
+ # @!group Attributes
446
+ #
447
+ def return_type= new_return_type
448
+ ensure_full_data!
449
+ @gapi.return_type = StandardSql::DataType.gapi_from_string_or_data_type new_return_type
450
+ update_gapi!
451
+ end
452
+
453
+ ##
454
+ # The list of the Google Cloud Storage URIs of imported JavaScript libraries. Optional. Only used if
455
+ # {#language} is `JAVASCRIPT` ({#javascript?}).
456
+ #
457
+ # @return [Array<String>, nil] A frozen array of Google Cloud Storage URIs, e.g.
458
+ # `["gs://cloud-samples-data/bigquery/udfs/max-value.js"]`, or `nil` if the object is a reference (see
459
+ # {#reference?}).
460
+ #
461
+ # @!group Attributes
462
+ #
463
+ def imported_libraries
464
+ return nil if reference?
465
+ ensure_full_data!
466
+ @gapi.imported_libraries.freeze
467
+ end
468
+
469
+ ##
470
+ # Updates the list of the Google Cloud Storage URIs of imported JavaScript libraries. Optional. Only used if
471
+ # {#language} is `JAVASCRIPT` ({#javascript?}).
472
+ #
473
+ # @param [Array<String>, nil] new_imported_libraries An array of Google Cloud Storage URIs, e.g.
474
+ # `["gs://cloud-samples-data/bigquery/udfs/max-value.js"]`.
475
+ #
476
+ # @example
477
+ # require "google/cloud/bigquery"
478
+ #
479
+ # bigquery = Google::Cloud::Bigquery.new
480
+ # dataset = bigquery.dataset "my_dataset"
481
+ # routine = dataset.routine "my_routine"
482
+ #
483
+ # routine.imported_libraries = [
484
+ # "gs://cloud-samples-data/bigquery/udfs/max-value.js"
485
+ # ]
486
+ #
487
+ # @!group Attributes
488
+ #
489
+ def imported_libraries= new_imported_libraries
490
+ ensure_full_data!
491
+ @gapi.imported_libraries = new_imported_libraries
492
+ update_gapi!
493
+ end
494
+
495
+ ##
496
+ # The body of the routine. Required.
497
+ #
498
+ # For functions ({#scalar_function?}), this is the expression in the `AS` clause.
499
+ #
500
+ # When the routine is a SQL function ({#sql?}), it is the substring inside (but excluding) the parentheses. For
501
+ # example, for the function created with the following statement:
502
+ # ```
503
+ # CREATE FUNCTION JoinLines(x string, y string) as (concat(x, "\n", y))
504
+ # ```
505
+ # The definition_body is `concat(x, "\n", y)` (`\n` is not replaced with linebreak).
506
+ #
507
+ # When the routine is a JavaScript function ({#javascript?}), it is the evaluated string in the `AS` clause. For
508
+ # example, for the function created with the following statement:
509
+ # ```
510
+ # CREATE FUNCTION f() RETURNS STRING LANGUAGE js AS 'return "\n";\n'
511
+ # ```
512
+ # The definition_body is
513
+ # ```
514
+ # "return \"\n\";\n"`
515
+ # ```
516
+ # Note that both `\n` are replaced with linebreaks.
517
+ #
518
+ # @return [String, nil] The body of the routine, or `nil` if the object is a reference (see {#reference?}).
519
+ #
520
+ # @!group Attributes
521
+ #
522
+ def body
523
+ return nil if reference?
524
+ ensure_full_data!
525
+ @gapi.definition_body
526
+ end
527
+
528
+ ##
529
+ # Updates the body of the routine. Required.
530
+ #
531
+ # For functions ({#scalar_function?}), this is the expression in the `AS` clause.
532
+ #
533
+ # When the routine is a SQL function ({#sql?}), it is the substring inside (but excluding) the parentheses. For
534
+ # example, for the function created with the following statement:
535
+ # ```
536
+ # CREATE FUNCTION JoinLines(x string, y string) as (concat(x, "\n", y))
537
+ # ```
538
+ # The definition_body is `concat(x, "\n", y)` (`\n` is not replaced with linebreak).
539
+ #
540
+ # When the routine is a JavaScript function ({#javascript?}), it is the evaluated string in the `AS` clause. For
541
+ # example, for the function created with the following statement:
542
+ # ```
543
+ # CREATE FUNCTION f() RETURNS STRING LANGUAGE js AS 'return "\n";\n'
544
+ # ```
545
+ # The definition_body is
546
+ # ```
547
+ # "return \"\n\";\n"`
548
+ # ```
549
+ # Note that both `\n` are replaced with linebreaks.
550
+ #
551
+ # @param [String] new_body The new body of the routine.
552
+ #
553
+ # @!group Attributes
554
+ #
555
+ def body= new_body
556
+ ensure_full_data!
557
+ @gapi.definition_body = new_body
558
+ update_gapi!
559
+ end
560
+
561
+ ###
562
+ # The description of the routine if defined. Optional. [Experimental]
563
+ #
564
+ # @return [String, nil] The routine description, or `nil` if the object is a reference (see {#reference?}).
565
+ #
566
+ # @example
567
+ # require "google/cloud/bigquery"
568
+ #
569
+ # bigquery = Google::Cloud::Bigquery.new
570
+ # dataset = bigquery.dataset "my_dataset"
571
+ # routine = dataset.routine "my_routine"
572
+ #
573
+ # routine.description #=> "My routine description"
574
+ #
575
+ # @!group Attributes
576
+ #
577
+ def description
578
+ return nil if reference?
579
+ ensure_full_data!
580
+ @gapi.description
581
+ end
582
+
583
+ ##
584
+ # Updates the description of the routine. Optional. [Experimental]
585
+ #
586
+ # @param [String] new_description The new routine description.
587
+ #
588
+ # @example
589
+ # require "google/cloud/bigquery"
590
+ #
591
+ # bigquery = Google::Cloud::Bigquery.new
592
+ # dataset = bigquery.dataset "my_dataset"
593
+ # routine = dataset.routine "my_routine"
594
+ #
595
+ # routine.description #=> "My routine description"
596
+ # routine.description = "My updated routine description"
597
+ #
598
+ # @!group Attributes
599
+ #
600
+ def description= new_description
601
+ ensure_full_data!
602
+ @gapi.description = new_description
603
+ update_gapi!
604
+ end
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
+
693
+ ##
694
+ # Updates the routine with changes made in the given block in a single update request. The following attributes
695
+ # may be set: {Updater#routine_type=}, {Updater#language=}, {Updater#arguments=}, {Updater#return_type=},
696
+ # {Updater#imported_libraries=}, {Updater#body=}, and {Updater#description=}.
697
+ #
698
+ # @yield [routine] A block for setting properties on the routine.
699
+ # @yieldparam [Google::Cloud::Bigquery::Routine::Updater] routine An updater to set additional properties on the
700
+ # routine.
701
+ #
702
+ # @example
703
+ # require "google/cloud/bigquery"
704
+ #
705
+ # bigquery = Google::Cloud::Bigquery.new
706
+ # dataset = bigquery.dataset "my_dataset"
707
+ # routine = dataset.routine "my_routine"
708
+ #
709
+ # routine.update do |r|
710
+ # r.routine_type = "SCALAR_FUNCTION"
711
+ # r.language = "SQL"
712
+ # r.arguments = [
713
+ # Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
714
+ # ]
715
+ # r.body = "x * 3"
716
+ # r.description = "My new routine description"
717
+ # end
718
+ #
719
+ # @!group Lifecycle
720
+ #
721
+ def update
722
+ ensure_full_data!
723
+ updater = Updater.new @gapi
724
+ yield updater
725
+ update_gapi! updater.to_gapi if updater.updates?
726
+ end
727
+
728
+ ##
729
+ # Permanently deletes the routine.
730
+ #
731
+ # @return [Boolean] Returns `true` if the routine was deleted.
732
+ #
733
+ # @example
734
+ # require "google/cloud/bigquery"
735
+ #
736
+ # bigquery = Google::Cloud::Bigquery.new
737
+ # dataset = bigquery.dataset "my_dataset"
738
+ # routine = dataset.routine "my_routine"
739
+ #
740
+ # routine.delete
741
+ #
742
+ # @!group Lifecycle
743
+ #
744
+ def delete
745
+ ensure_service!
746
+ service.delete_routine dataset_id, routine_id
747
+ # Set flag for #exists?
748
+ @exists = false
749
+ true
750
+ end
751
+
752
+ ##
753
+ # Reloads the routine with current data from the BigQuery service.
754
+ #
755
+ # @return [Google::Cloud::Bigquery::Routine] Returns the reloaded
756
+ # routine.
757
+ #
758
+ # @example Skip retrieving the routine from the service, then load it:
759
+ # require "google/cloud/bigquery"
760
+ #
761
+ # bigquery = Google::Cloud::Bigquery.new
762
+ #
763
+ # dataset = bigquery.dataset "my_dataset"
764
+ # routine = dataset.routine "my_routine", skip_lookup: true
765
+ #
766
+ # routine.reload!
767
+ #
768
+ # @!group Lifecycle
769
+ #
770
+ def reload!
771
+ ensure_service!
772
+ @gapi = service.get_routine dataset_id, routine_id
773
+ @reference = nil
774
+ @exists = nil
775
+ self
776
+ end
777
+ alias refresh! reload!
778
+
779
+ ##
780
+ # Determines whether the routine exists in the BigQuery service. The
781
+ # result is cached locally. To refresh state, set `force` to `true`.
782
+ #
783
+ # @param [Boolean] force Force the latest resource representation to be
784
+ # retrieved from the BigQuery service when `true`. Otherwise the
785
+ # return value of this method will be memoized to reduce the number of
786
+ # API calls made to the BigQuery service. The default is `false`.
787
+ #
788
+ # @return [Boolean] `true` when the routine exists in the BigQuery
789
+ # service, `false` otherwise.
790
+ #
791
+ # @example
792
+ # require "google/cloud/bigquery"
793
+ #
794
+ # bigquery = Google::Cloud::Bigquery.new
795
+ #
796
+ # dataset = bigquery.dataset "my_dataset"
797
+ # routine = dataset.routine "my_routine", skip_lookup: true
798
+ # routine.exists? #=> true
799
+ #
800
+ def exists? force: false
801
+ return resource_exists? if force
802
+ # If we have a value, return it
803
+ return @exists unless @exists.nil?
804
+ # Always true if we have a gapi object
805
+ return true if resource?
806
+ resource_exists?
807
+ end
808
+
809
+ ##
810
+ # Whether the routine was created without retrieving the resource
811
+ # representation from the BigQuery service.
812
+ #
813
+ # @return [Boolean] `true` when the routine is just a local reference
814
+ # object, `false` otherwise.
815
+ #
816
+ # @example
817
+ # require "google/cloud/bigquery"
818
+ #
819
+ # bigquery = Google::Cloud::Bigquery.new
820
+ #
821
+ # dataset = bigquery.dataset "my_dataset"
822
+ # routine = dataset.routine "my_routine", skip_lookup: true
823
+ #
824
+ # routine.reference? #=> true
825
+ # routine.reload!
826
+ # routine.reference? #=> false
827
+ #
828
+ def reference?
829
+ @gapi.nil?
830
+ end
831
+
832
+ ##
833
+ # Whether the routine was created with a resource representation from
834
+ # the BigQuery service.
835
+ #
836
+ # @return [Boolean] `true` when the routine was created with a resource
837
+ # representation, `false` otherwise.
838
+ #
839
+ # @example
840
+ # require "google/cloud/bigquery"
841
+ #
842
+ # bigquery = Google::Cloud::Bigquery.new
843
+ #
844
+ # dataset = bigquery.dataset "my_dataset"
845
+ # routine = dataset.routine "my_routine", skip_lookup: true
846
+ #
847
+ # routine.resource? #=> false
848
+ # routine.reload!
849
+ # routine.resource? #=> true
850
+ #
851
+ def resource?
852
+ !@gapi.nil?
853
+ end
854
+
855
+ ##
856
+ # Whether the routine was created with a partial resource representation
857
+ # from the BigQuery service by retrieval through {Dataset#routines}.
858
+ # See [Models: list
859
+ # response](https://cloud.google.com/bigquery/docs/reference/rest/v2/routines/list#response)
860
+ # for the contents of the partial representation. Accessing any
861
+ # attribute outside of the partial representation will result in loading
862
+ # the full representation.
863
+ #
864
+ # @return [Boolean] `true` when the routine was created with a partial
865
+ # resource representation, `false` otherwise.
866
+ #
867
+ # @example
868
+ # require "google/cloud/bigquery"
869
+ #
870
+ # bigquery = Google::Cloud::Bigquery.new
871
+ #
872
+ # dataset = bigquery.dataset "my_dataset"
873
+ # routine = dataset.routines.first
874
+ #
875
+ # routine.resource_partial? #=> true
876
+ # routine.description # Loads the full resource.
877
+ # routine.resource_partial? #=> false
878
+ #
879
+ def resource_partial?
880
+ resource? && !resource_full?
881
+ end
882
+
883
+ ##
884
+ # Whether the routine was created with a full resource representation
885
+ # from the BigQuery service.
886
+ #
887
+ # @return [Boolean] `true` when the routine was created with a full
888
+ # resource representation, `false` otherwise.
889
+ #
890
+ # @example
891
+ # require "google/cloud/bigquery"
892
+ #
893
+ # bigquery = Google::Cloud::Bigquery.new
894
+ #
895
+ # dataset = bigquery.dataset "my_dataset"
896
+ # routine = dataset.routine "my_routine"
897
+ #
898
+ # routine.resource_full? #=> true
899
+ #
900
+ def resource_full?
901
+ resource? && !@gapi.definition_body.nil?
902
+ end
903
+
904
+ ##
905
+ # @private New Routine from a Google API Client object.
906
+ def self.from_gapi gapi, service
907
+ new.tap do |r|
908
+ r.instance_variable_set :@gapi, gapi
909
+ r.instance_variable_set :@service, service
910
+ end
911
+ end
912
+
913
+ ##
914
+ # @private New lazy Routine object without making an HTTP request, for use with the skip_lookup option.
915
+ def self.new_reference project_id, dataset_id, routine_id, service
916
+ raise ArgumentError, "project_id is required" unless project_id
917
+ raise ArgumentError, "dataset_id is required" unless dataset_id
918
+ raise ArgumentError, "routine_id is required" unless routine_id
919
+ raise ArgumentError, "service is required" unless service
920
+
921
+ gapi = Google::Apis::BigqueryV2::RoutineReference.new(
922
+ project_id: project_id,
923
+ dataset_id: dataset_id,
924
+ routine_id: routine_id
925
+ )
926
+ new.tap do |r|
927
+ r.service = service
928
+ r.instance_variable_set :@reference, gapi
929
+ end
930
+ end
931
+
932
+ ##
933
+ # @private New lazy Routine object from a Google API Client object.
934
+ def self.new_reference_from_gapi gapi, service
935
+ new.tap do |b|
936
+ b.service = service
937
+ b.instance_variable_set :@reference, gapi
938
+ end
939
+ end
940
+
941
+ protected
942
+
943
+ ##
944
+ # Raise an error unless an active service is available.
945
+ def ensure_service!
946
+ raise "Must have active connection" unless service
947
+ end
948
+
949
+ ##
950
+ # Fetch gapi and memoize whether resource exists.
951
+ def resource_exists?
952
+ reload!
953
+ @exists = true
954
+ rescue Google::Cloud::NotFoundError
955
+ @exists = false
956
+ end
957
+
958
+ ##
959
+ # Load the complete representation of the routine if it has been
960
+ # only partially loaded by a request to the API list method.
961
+ def ensure_full_data!
962
+ reload! unless resource_full?
963
+ end
964
+
965
+ def update_gapi! update_gapi = nil
966
+ update_gapi ||= @gapi
967
+ ensure_service!
968
+ @gapi = service.update_routine dataset_id, routine_id, update_gapi
969
+ self
970
+ end
971
+
972
+ ##
973
+ # Yielded to a block to accumulate changes. See {Dataset#create_routine} and {Routine#update}.
974
+ #
975
+ # @example Creating a new routine:
976
+ # require "google/cloud/bigquery"
977
+ #
978
+ # bigquery = Google::Cloud::Bigquery.new
979
+ # dataset = bigquery.dataset "my_dataset"
980
+ #
981
+ # routine = dataset.create_routine "my_routine" do |r|
982
+ # r.routine_type = "SCALAR_FUNCTION"
983
+ # r.language = "SQL"
984
+ # r.arguments = [
985
+ # Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
986
+ # ]
987
+ # r.body = "x * 3"
988
+ # r.description = "My routine description"
989
+ # end
990
+ #
991
+ # puts routine.routine_id
992
+ #
993
+ # @example Updating an existing routine:
994
+ # require "google/cloud/bigquery"
995
+ #
996
+ # bigquery = Google::Cloud::Bigquery.new
997
+ # dataset = bigquery.dataset "my_dataset"
998
+ # routine = dataset.routine "my_routine"
999
+ #
1000
+ # routine.update do |r|
1001
+ # r.body = "x * 4"
1002
+ # r.description = "My new routine description"
1003
+ # end
1004
+ #
1005
+ class Updater < Routine
1006
+ ##
1007
+ # @private Create an Updater object.
1008
+ def initialize gapi
1009
+ super()
1010
+ @original_gapi = gapi
1011
+ @gapi = gapi.dup
1012
+ end
1013
+
1014
+ ##
1015
+ # Updates the type of routine. Required.
1016
+ #
1017
+ # * `SCALAR_FUNCTION` - Non-builtin permanent scalar function.
1018
+ # * `PROCEDURE` - Stored procedure.
1019
+ #
1020
+ # @param [String] new_routine_type The new type of the routine.
1021
+ #
1022
+ def routine_type= new_routine_type
1023
+ @gapi.routine_type = new_routine_type
1024
+ end
1025
+
1026
+ ##
1027
+ # Updates the programming language of routine. Optional. Defaults to "SQL".
1028
+ #
1029
+ # * `SQL` - SQL language.
1030
+ # * `JAVASCRIPT` - JavaScript language.
1031
+ #
1032
+ # @param [String] new_language The new language in upper case.
1033
+ #
1034
+ def language= new_language
1035
+ @gapi.language = new_language
1036
+ end
1037
+
1038
+ ##
1039
+ # Updates the input/output arguments of the routine. Optional.
1040
+ #
1041
+ # @param [Array<Argument>] new_arguments The new arguments.
1042
+ #
1043
+ # @example
1044
+ # require "google/cloud/bigquery"
1045
+ #
1046
+ # bigquery = Google::Cloud::Bigquery.new
1047
+ # dataset = bigquery.dataset "my_dataset"
1048
+ # routine = dataset.routine "my_routine"
1049
+ #
1050
+ # routine.arguments = [
1051
+ # Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
1052
+ # ]
1053
+ #
1054
+ def arguments= new_arguments
1055
+ @gapi.arguments = new_arguments.map(&:to_gapi)
1056
+ end
1057
+
1058
+ ##
1059
+ # Updates the return type of the routine. Optional if the routine is a SQL function ({#sql?}); required
1060
+ # otherwise.
1061
+ #
1062
+ # If absent, the return type is inferred from {#body} at query time in each query that references this
1063
+ # routine. If present, then the evaluated result will be cast to the specified returned type at query time.
1064
+ #
1065
+ # For example, for the functions created with the following statements:
1066
+ #
1067
+ # * `CREATE FUNCTION Add(x FLOAT64, y FLOAT64) RETURNS FLOAT64 AS (x + y);`
1068
+ # * `CREATE FUNCTION Increment(x FLOAT64) AS (Add(x, 1));`
1069
+ # * `CREATE FUNCTION Decrement(x FLOAT64) RETURNS FLOAT64 AS (Add(x, -1));`
1070
+ #
1071
+ # The returnType is `{typeKind: "FLOAT64"}` for Add and Decrement, and is absent for Increment (inferred as
1072
+ # `FLOAT64` at query time).
1073
+ #
1074
+ # Suppose the function Add is replaced by `CREATE OR REPLACE FUNCTION Add(x INT64, y INT64) AS (x + y);`
1075
+ #
1076
+ # Then the inferred return type of Increment is automatically changed to `INT64` at query time, while the
1077
+ # return type of Decrement remains `FLOAT64`.
1078
+ #
1079
+ # @param [Google::Cloud::Bigquery::StandardSql::DataType, String] new_return_type The new return type for the
1080
+ # routine.
1081
+ #
1082
+ # @example
1083
+ # require "google/cloud/bigquery"
1084
+ #
1085
+ # bigquery = Google::Cloud::Bigquery.new
1086
+ # dataset = bigquery.dataset "my_dataset"
1087
+ # routine = dataset.routine "my_routine"
1088
+ #
1089
+ # routine.return_type.type_kind #=> "INT64"
1090
+ # routine.update do |r|
1091
+ # r.return_type = "STRING"
1092
+ # end
1093
+ #
1094
+ def return_type= new_return_type
1095
+ @gapi.return_type = StandardSql::DataType.gapi_from_string_or_data_type new_return_type
1096
+ end
1097
+
1098
+ ##
1099
+ # Updates the list of the Google Cloud Storage URIs of imported JavaScript libraries. Optional. Only used if
1100
+ # {#language} is `JAVASCRIPT` ({#javascript?}).
1101
+ #
1102
+ # @param [Array<String>, nil] new_imported_libraries An array of Google Cloud Storage URIs, e.g.
1103
+ # `["gs://cloud-samples-data/bigquery/udfs/max-value.js"]`.
1104
+ #
1105
+ # @example
1106
+ # require "google/cloud/bigquery"
1107
+ #
1108
+ # bigquery = Google::Cloud::Bigquery.new
1109
+ # dataset = bigquery.dataset "my_dataset"
1110
+ # routine = dataset.routine "my_routine"
1111
+ #
1112
+ # routine.update do |r|
1113
+ # r.imported_libraries = [
1114
+ # "gs://cloud-samples-data/bigquery/udfs/max-value.js"
1115
+ # ]
1116
+ # end
1117
+ #
1118
+ def imported_libraries= new_imported_libraries
1119
+ @gapi.imported_libraries = new_imported_libraries
1120
+ end
1121
+
1122
+ ##
1123
+ # Updates the body of the routine. Required.
1124
+ #
1125
+ # For functions ({#scalar_function?}), this is the expression in the `AS` clause.
1126
+ #
1127
+ # When the routine is a SQL function ({#sql?}), it is the substring inside (but excluding) the parentheses.
1128
+ # For example, for the function created with the following statement:
1129
+ # ```
1130
+ # CREATE FUNCTION JoinLines(x string, y string) as (concat(x, "\n", y))
1131
+ # ```
1132
+ # The definition_body is `concat(x, "\n", y)` (`\n` is not replaced with linebreak).
1133
+ #
1134
+ # When the routine is a JavaScript function ({#javascript?}), it is the evaluated string in the `AS` clause.
1135
+ # For example, for the function created with the following statement:
1136
+ # ```
1137
+ # CREATE FUNCTION f() RETURNS STRING LANGUAGE js AS 'return "\n";\n'
1138
+ # ```
1139
+ # The definition_body is
1140
+ # ```
1141
+ # "return \"\n\";\n"`
1142
+ # ```
1143
+ # Note that both `\n` are replaced with linebreaks.
1144
+ #
1145
+ # @param [String] new_body The new body of the routine.
1146
+ #
1147
+ def body= new_body
1148
+ @gapi.definition_body = new_body
1149
+ end
1150
+
1151
+ ##
1152
+ # Updates the description of the routine. Optional. [Experimental]
1153
+ #
1154
+ # @param [String] new_description The new routine description.
1155
+ #
1156
+ # @example
1157
+ # require "google/cloud/bigquery"
1158
+ #
1159
+ # bigquery = Google::Cloud::Bigquery.new
1160
+ # dataset = bigquery.dataset "my_dataset"
1161
+ # routine = dataset.routine "my_routine"
1162
+ #
1163
+ # routine.description #=> "My routine description"
1164
+ # routine.update do |r|
1165
+ # r.description = "My updated routine description"
1166
+ # end
1167
+ #
1168
+ def description= new_description
1169
+ @gapi.description = new_description
1170
+ end
1171
+
1172
+ ##
1173
+ # Updates the JavaScript UDF determinism level. Optional.
1174
+ #
1175
+ # * `DETERMINISTIC` - Deterministic indicates that two calls with the same input to a UDF yield the same
1176
+ # output. If all JavaScript UDFs are `DETERMINISTIC`, the query result is potentially cachable.
1177
+ # * `NOT_DETERMINISTIC` - Not deterministic indicates that the output of the UDF is not guaranteed to yield
1178
+ # the same output each time for a given set of inputs. If any JavaScript UDF is `NOT_DETERMINISTIC`, the
1179
+ # query result is not cacheable.
1180
+ #
1181
+ # @param [String, nil] new_determinism_level The new routine determinism level in upper case.
1182
+ #
1183
+ # @example
1184
+ # require "google/cloud/bigquery"
1185
+ #
1186
+ # bigquery = Google::Cloud::Bigquery.new
1187
+ # dataset = bigquery.dataset "my_dataset"
1188
+ # routine = dataset.routine "my_routine"
1189
+ #
1190
+ # routine.determinism_level #=> "NOT_DETERMINISTIC"
1191
+ # routine.update do |r|
1192
+ # r.determinism_level = "DETERMINISTIC"
1193
+ # end
1194
+ #
1195
+ # @!group Attributes
1196
+ #
1197
+ def determinism_level= new_determinism_level
1198
+ @gapi.determinism_level = new_determinism_level
1199
+ end
1200
+
1201
+ def update
1202
+ raise "not implemented in #{self.class}"
1203
+ end
1204
+
1205
+ def delete
1206
+ raise "not implemented in #{self.class}"
1207
+ end
1208
+
1209
+ def reload!
1210
+ raise "not implemented in #{self.class}"
1211
+ end
1212
+ alias refresh! reload!
1213
+
1214
+ # @private
1215
+ def updates?
1216
+ !(@gapi === @original_gapi)
1217
+ end
1218
+
1219
+ # @private
1220
+ def to_gapi
1221
+ @gapi
1222
+ end
1223
+ end
1224
+ end
1225
+ end
1226
+ end
1227
+ end