google-cloud-bigquery 1.18.1 → 1.21.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 5906552349d5601779e5fc80cbc4dbcb054ecbc810885fa6db0ec617e2253a2a
4
- data.tar.gz: 3e077eaf5f351d697058b97a89cc2fccc0c8a9f2af6f8d8263f2ea5ae7f738da
3
+ metadata.gz: f38543236358fc319ecfcc2058ffa499e24034027aa56644924d2cf496815550
4
+ data.tar.gz: 37196fa1c3db03e48df4cb0ae5ae5b9b1ee07b9d112063467ebc57d25b34551a
5
5
  SHA512:
6
- metadata.gz: 3c031b1150418cb31a835b9996c6ce31322ffc5b3cbefd05520283ffb11695967c920ec051ab53f726e8968f9c343fd1839b355bc23483145556f5c401ab1c4e
7
- data.tar.gz: da68f76f39a126cc17069a7e071721771321faeade8ee916b3cf33a580c5fccb775a463ea2e8046be803b4ca984a84833b3c21589082dc0f6aacf101e85a5fb5
6
+ metadata.gz: a234359fb8a04b42f22725f5540cf0378b7e51b3d847ddd4f24ba41f2a54b4de85068bb9aee10089995c29794c0a64694223ac6bf88202eda6a646ce02c85275
7
+ data.tar.gz: 99c6c915df70afde18de06907802c60d18df253238e6f3ab752827ea3cfc0aee0ab9bef8dc0816f5980db26334dd2b15ce0a2ecf7db3b026e2f0caa101dcafc8
@@ -1,5 +1,51 @@
1
1
  # Release History
2
2
 
3
+ ### 1.21.2 / 2020-07-21
4
+
5
+ #### Documentation
6
+
7
+ * Update Data#each samples
8
+
9
+ ### 1.21.1 / 2020-05-28
10
+
11
+ #### Documentation
12
+
13
+ * Fix a few broken links
14
+
15
+ ### 1.21.0 / 2020-03-31
16
+
17
+ #### Features
18
+
19
+ * Add Job#parent_job_id and Job#script_statistics
20
+ * Add parent_job to Project#jobs
21
+ * Add Job#num_child_jobs
22
+ * Add Job#parent_job_id
23
+ * Add Job#script_statistics
24
+
25
+ ### 1.20.0 / 2020-03-11
26
+
27
+ #### Features
28
+
29
+ * Add Range Partitioning
30
+ * Add range partitioning methods to Table and Table::Updater
31
+ * Add range partitioning methods to LoadJob
32
+ * Add range partitioning methods to QueryJob
33
+
34
+ ### 1.19.0 / 2020-02-11
35
+
36
+ #### Features
37
+
38
+ * Add Routine
39
+ * Add Dataset#create_routine
40
+ * Add Argument
41
+ * Update StandardSql classes to expose public initializer
42
+ * Add Data#ddl_target_routine and QueryJob#ddl_target_routine
43
+ * Allow row inserts to skip insert_id generation
44
+ * Streaming inserts using an insert_id are not able to be inserted as fast as inserts without an insert_id
45
+ * Add the ability for users to skip insert_id generation in order to speed up the inserts
46
+ * The default behavior continues to generate insert_id values for each row inserted
47
+ * Add yield documentation for Dataset#insert
48
+
3
49
  ### 1.18.1 / 2019-12-18
4
50
 
5
51
  #### Bug Fixes
@@ -24,14 +24,8 @@ improved, *please* create a new issue on GitHub so we can talk about it.
24
24
 
25
25
  - [New issue][gh-ruby]
26
26
 
27
- Or, you can ask questions on the [Google Cloud Platform Slack][slack-ruby]. You
28
- can use the "ruby" channel for general Ruby questions, or use the
29
- "google-cloud-ruby" channel if you have questions about this gem in particular.
30
-
31
27
  [so-ruby]: http://stackoverflow.com/questions/tagged/google-cloud-platform+ruby+bigquery
32
28
 
33
- [gh-search-ruby]: https://github.com/googlecloudplatform/google-cloud-ruby/issues?q=label%3A%22api%3A+bigquery%22
34
-
35
- [gh-ruby]: https://github.com/googlecloudplatform/google-cloud-ruby/issues/new
29
+ [gh-search-ruby]: https://github.com/googleapis/google-cloud-ruby/issues?q=label%3A%22api%3A+bigquery%22
36
30
 
37
- [slack-ruby]: https://gcp-slack.appspot.com/
31
+ [gh-ruby]: https://github.com/googleapis/google-cloud-ruby/issues/new
@@ -53,9 +53,15 @@ module Google
53
53
  # bigquery = gcloud.bigquery
54
54
  # dataset = bigquery.dataset "my_dataset"
55
55
  # table = dataset.table "my_table"
56
- # table.data.each do |row|
57
- # puts row
56
+ #
57
+ # data = table.data
58
+ #
59
+ # # Iterate over the first page of results
60
+ # data.each do |row|
61
+ # puts row[:name]
58
62
  # end
63
+ # # Retrieve the next page of results
64
+ # data = data.next if data.next?
59
65
  #
60
66
  # @example The default scope can be overridden with the `scope` option:
61
67
  # require "google/cloud"
@@ -0,0 +1,197 @@
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/bigquery/standard_sql"
17
+
18
+ module Google
19
+ module Cloud
20
+ module Bigquery
21
+ ##
22
+ # # Argument
23
+ #
24
+ # Input/output argument of a function or a stored procedure. See {Routine}.
25
+ #
26
+ # @example
27
+ # require "google/cloud/bigquery"
28
+ #
29
+ # bigquery = Google::Cloud::Bigquery.new
30
+ # dataset = bigquery.dataset "my_dataset"
31
+ # routine = dataset.create_routine "my_routine" do |r|
32
+ # r.routine_type = "SCALAR_FUNCTION"
33
+ # r.language = :SQL
34
+ # r.body = "(SELECT SUM(IF(elem.name = \"foo\",elem.val,null)) FROM UNNEST(arr) AS elem)"
35
+ # r.arguments = [
36
+ # Google::Cloud::Bigquery::Argument.new(
37
+ # name: "arr",
38
+ # argument_kind: "FIXED_TYPE",
39
+ # data_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
40
+ # type_kind: "ARRAY",
41
+ # array_element_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
42
+ # type_kind: "STRUCT",
43
+ # struct_type: Google::Cloud::Bigquery::StandardSql::StructType.new(
44
+ # fields: [
45
+ # Google::Cloud::Bigquery::StandardSql::Field.new(
46
+ # name: "name",
47
+ # type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "STRING")
48
+ # ),
49
+ # Google::Cloud::Bigquery::StandardSql::Field.new(
50
+ # name: "val",
51
+ # type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "INT64")
52
+ # )
53
+ # ]
54
+ # )
55
+ # )
56
+ # )
57
+ # )
58
+ # ]
59
+ # end
60
+ #
61
+ class Argument
62
+ ##
63
+ # Creates a new, immutable Argument object.
64
+ #
65
+ # @overload initialize(data_type, kind, mode, name)
66
+ # @param [StandardSql::DataType, String] data_type The data type of the argument. Required unless
67
+ # {#argument_kind} is `ANY_TYPE`.
68
+ # @param [String] argument_kind The kind of argument. Optional. Defaults to `FIXED_TYPE`.
69
+ #
70
+ # * `FIXED_TYPE` - The argument is a variable with fully specified type, which can be a struct or an array,
71
+ # but not a table.
72
+ # * `ANY_TYPE` - The argument is any type, including struct or array, but not a table.
73
+ #
74
+ # To be added: `FIXED_TABLE`, `ANY_TABLE`.
75
+ # @param [String] mode Specifies whether the argument is input or output. Optional. Can be set for procedures
76
+ # only.
77
+ #
78
+ # * IN - The argument is input-only.
79
+ # * OUT - The argument is output-only.
80
+ # * INOUT - The argument is both an input and an output.
81
+ # @param [String] name The name of the argument. Optional. Can be absent for a function return argument.
82
+ #
83
+ def initialize **kwargs
84
+ kwargs[:data_type] = StandardSql::DataType.gapi_from_string_or_data_type kwargs[:data_type]
85
+ @gapi = Google::Apis::BigqueryV2::Argument.new(**kwargs)
86
+ end
87
+
88
+ ##
89
+ # The data type of the argument. Required unless {#argument_kind} is `ANY_TYPE`.
90
+ #
91
+ # @return [StandardSql::DataType] The data type.
92
+ #
93
+ def data_type
94
+ StandardSql::DataType.from_gapi @gapi.data_type
95
+ end
96
+
97
+ ##
98
+ # The kind of argument. Optional. Defaults to `FIXED_TYPE`.
99
+ #
100
+ # * `FIXED_TYPE` - The argument is a variable with fully specified type, which can be a struct or an array, but
101
+ # not a table.
102
+ # * `ANY_TYPE` - The argument is any type, including struct or array, but not a table.
103
+ #
104
+ # To be added: `FIXED_TABLE`, `ANY_TABLE`.
105
+ #
106
+ # @return [String] The upper case kind of argument.
107
+ #
108
+ def argument_kind
109
+ @gapi.argument_kind
110
+ end
111
+
112
+ ##
113
+ # Checks if the value of {#argument_kind} is `FIXED_TYPE`. The default is `true`.
114
+ #
115
+ # @return [Boolean] `true` when `FIXED_TYPE`, `false` otherwise.
116
+ #
117
+ def fixed_type?
118
+ return true if @gapi.argument_kind.nil?
119
+ @gapi.argument_kind == "FIXED_TYPE"
120
+ end
121
+
122
+ ##
123
+ # Checks if the value of {#argument_kind} is `ANY_TYPE`. The default is `false`.
124
+ #
125
+ # @return [Boolean] `true` when `ANY_TYPE`, `false` otherwise.
126
+ #
127
+ def any_type?
128
+ @gapi.argument_kind == "ANY_TYPE"
129
+ end
130
+
131
+ ##
132
+ # Specifies whether the argument is input or output. Optional. Can be set for procedures only.
133
+ #
134
+ # * IN - The argument is input-only.
135
+ # * OUT - The argument is output-only.
136
+ # * INOUT - The argument is both an input and an output.
137
+ #
138
+ # @return [String] The upper case input/output mode of the argument.
139
+ #
140
+ def mode
141
+ @gapi.mode
142
+ end
143
+
144
+ ##
145
+ # Checks if the value of {#mode} is `IN`. Can be set for procedures only. The default is `false`.
146
+ #
147
+ # @return [Boolean] `true` when `IN`, `false` otherwise.
148
+ #
149
+ def in?
150
+ @gapi.mode == "IN"
151
+ end
152
+
153
+ ##
154
+ # Checks if the value of {#mode} is `OUT`. Can be set for procedures only. The default is `false`.
155
+ #
156
+ # @return [Boolean] `true` when `OUT`, `false` otherwise.
157
+ #
158
+ def out?
159
+ @gapi.mode == "OUT"
160
+ end
161
+
162
+ ##
163
+ # Checks if the value of {#mode} is `INOUT`. Can be set for procedures only. The default is `false`.
164
+ #
165
+ # @return [Boolean] `true` when `INOUT`, `false` otherwise.
166
+ #
167
+ def inout?
168
+ @gapi.mode == "INOUT"
169
+ end
170
+
171
+ ##
172
+ #
173
+ # The name of the argument. Optional. Can be absent for a function return argument.
174
+ #
175
+ # @return [String] The name of the argument.
176
+ #
177
+ def name
178
+ @gapi.name
179
+ end
180
+
181
+ ##
182
+ # @private
183
+ def to_gapi
184
+ @gapi
185
+ end
186
+
187
+ ##
188
+ # @private New Argument from a Google API Client object.
189
+ def self.from_gapi gapi
190
+ new.tap do |a|
191
+ a.instance_variable_set :@gapi, gapi
192
+ end
193
+ end
194
+ end
195
+ end
196
+ end
197
+ end
@@ -152,7 +152,7 @@ module Google
152
152
  #
153
153
  # @return [Google::Cloud::Bigquery::CopyJob::Updater] A job
154
154
  # configuration object for setting copy options.
155
- def self.from_options service, source, target, options = {}
155
+ def self.from_options service, source, target, options
156
156
  job_ref = service.job_ref_from options[:job_id], options[:prefix]
157
157
  copy_cfg = Google::Apis::BigqueryV2::JobConfigurationTableCopy.new(
158
158
  source_table: source,
@@ -284,6 +284,23 @@ module Google
284
284
  @gapi.configuration.update! labels: value
285
285
  end
286
286
 
287
+ def cancel
288
+ raise "not implemented in #{self.class}"
289
+ end
290
+
291
+ def rerun!
292
+ raise "not implemented in #{self.class}"
293
+ end
294
+
295
+ def reload!
296
+ raise "not implemented in #{self.class}"
297
+ end
298
+ alias refresh! reload!
299
+
300
+ def wait_until_done!
301
+ raise "not implemented in #{self.class}"
302
+ end
303
+
287
304
  ##
288
305
  # @private Returns the Google API client library version of this job.
289
306
  #
@@ -41,9 +41,12 @@ module Google
41
41
  #
42
42
  # data.count # 100000
43
43
  # data.total # 164656
44
+ #
45
+ # # Iterate over the first page of results
44
46
  # data.each do |row|
45
47
  # puts row[:word]
46
48
  # end
49
+ # # Retrieve the next page of results
47
50
  # data = data.next if data.next?
48
51
  #
49
52
  class Data < DelegateClass(::Array)
@@ -117,9 +120,12 @@ module Google
117
120
  #
118
121
  # data.count # 100000
119
122
  # data.total # 164656
123
+ #
124
+ # # Iterate over the first page of results
120
125
  # data.each do |row|
121
126
  # puts row[:word]
122
127
  # end
128
+ # # Retrieve the next page of results
123
129
  # data = data.next if data.next?
124
130
  #
125
131
  def total
@@ -316,6 +322,21 @@ module Google
316
322
  job_gapi&.statistics&.query&.ddl_operation_performed
317
323
  end
318
324
 
325
+ ##
326
+ # The DDL target routine, in reference state. (See {Routine#reference?}.)
327
+ # Present only for `CREATE/DROP FUNCTION/PROCEDURE` queries. (See
328
+ # {#statement_type}.)
329
+ #
330
+ # @return [Google::Cloud::Bigquery::Routine, nil] The DDL target routine, in
331
+ # reference state.
332
+ #
333
+ def ddl_target_routine
334
+ ensure_service!
335
+ routine = job_gapi&.statistics&.query&.ddl_target_routine
336
+ return nil if routine.nil?
337
+ Google::Cloud::Bigquery::Routine.new_reference_from_gapi routine, service
338
+ end
339
+
319
340
  ##
320
341
  # The DDL target table, in reference state. (See {Table#reference?}.)
321
342
  # Present only for `CREATE/DROP TABLE/VIEW` queries. (See
@@ -360,9 +381,12 @@ module Google
360
381
  #
361
382
  # data.count # 100000
362
383
  # data.total # 164656
384
+ #
385
+ # # Iterate over the first page of results
363
386
  # data.each do |row|
364
387
  # puts row[:word]
365
388
  # end
389
+ # # Retrieve the next page of results
366
390
  # data = data.next if data.next?
367
391
  #
368
392
  def next?
@@ -387,9 +411,12 @@ module Google
387
411
  #
388
412
  # data.count # 100000
389
413
  # data.total # 164656
414
+ #
415
+ # # Iterate over the first page of results
390
416
  # data.each do |row|
391
417
  # puts row[:word]
392
418
  # end
419
+ # # Retrieve the next page of results
393
420
  # data = data.next if data.next?
394
421
  #
395
422
  def next
@@ -18,6 +18,7 @@ require "google/cloud/errors"
18
18
  require "google/cloud/bigquery/service"
19
19
  require "google/cloud/bigquery/table"
20
20
  require "google/cloud/bigquery/model"
21
+ require "google/cloud/bigquery/routine"
21
22
  require "google/cloud/bigquery/external"
22
23
  require "google/cloud/bigquery/dataset/list"
23
24
  require "google/cloud/bigquery/dataset/access"
@@ -554,6 +555,40 @@ module Google
554
555
  # end
555
556
  # end
556
557
  #
558
+ # @example With time partitioning and clustering.
559
+ # require "google/cloud/bigquery"
560
+ #
561
+ # bigquery = Google::Cloud::Bigquery.new
562
+ # dataset = bigquery.dataset "my_dataset"
563
+ #
564
+ # table = dataset.create_table "my_table" do |t|
565
+ # t.schema do |schema|
566
+ # schema.timestamp "dob", mode: :required
567
+ # schema.string "first_name", mode: :required
568
+ # schema.string "last_name", mode: :required
569
+ # end
570
+ # t.time_partitioning_type = "DAY"
571
+ # t.time_partitioning_field = "dob"
572
+ # t.clustering_fields = ["last_name", "first_name"]
573
+ # end
574
+ #
575
+ # @example With range partitioning.
576
+ # require "google/cloud/bigquery"
577
+ #
578
+ # bigquery = Google::Cloud::Bigquery.new
579
+ # dataset = bigquery.dataset "my_dataset"
580
+ #
581
+ # table = dataset.create_table "my_table" do |t|
582
+ # t.schema do |schema|
583
+ # schema.integer "my_table_id", mode: :required
584
+ # schema.string "my_table_data", mode: :required
585
+ # end
586
+ # t.range_partitioning_field = "my_table_id"
587
+ # t.range_partitioning_start = 0
588
+ # t.range_partitioning_interval = 10
589
+ # t.range_partitioning_end = 100
590
+ # end
591
+ #
557
592
  # @!group Table
558
593
  #
559
594
  def create_table table_id, name: nil, description: nil
@@ -601,12 +636,20 @@ module Google
601
636
  # SQL](https://cloud.google.com/bigquery/docs/reference/legacy-sql)
602
637
  # dialect. Optional. The default value is false.
603
638
  # @param [Array<String>, String] udfs User-defined function resources
604
- # used in the query. May be either a code resource to load from a
605
- # Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
639
+ # used in a legacy SQL query. May be either a code resource to load from
640
+ # a Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
606
641
  # that contains code for a user-defined function (UDF). Providing an
607
642
  # inline code resource is equivalent to providing a URI for a file
608
- # containing the same code. See [User-Defined
609
- # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
643
+ # containing the same code.
644
+ #
645
+ # This parameter is used for defining User Defined Function (UDF)
646
+ # resources only when using legacy SQL. Users of standard SQL should
647
+ # leverage either DDL (e.g. `CREATE [TEMPORARY] FUNCTION ...`) or the
648
+ # Routines API to define UDF resources.
649
+ #
650
+ # For additional information on migrating, see: [Migrating to
651
+ # standard SQL - Differences in user-defined JavaScript
652
+ # functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#differences_in_user-defined_javascript_functions)
610
653
  #
611
654
  # @return [Google::Cloud::Bigquery::Table] A new table object.
612
655
  #
@@ -731,8 +774,7 @@ module Google
731
774
  #
732
775
  def tables token: nil, max: nil
733
776
  ensure_service!
734
- options = { token: token, max: max }
735
- gapi = service.list_tables dataset_id, options
777
+ gapi = service.list_tables dataset_id, token: token, max: max
736
778
  Table::List.from_gapi gapi, service, dataset_id, max
737
779
  end
738
780
 
@@ -817,6 +859,174 @@ module Google
817
859
  Model::List.from_gapi gapi, service, dataset_id, max
818
860
  end
819
861
 
862
+ ##
863
+ # Creates a new routine. The following attributes may be set in the yielded block:
864
+ # {Routine::Updater#routine_type=}, {Routine::Updater#language=}, {Routine::Updater#arguments=},
865
+ # {Routine::Updater#return_type=}, {Routine::Updater#imported_libraries=}, {Routine::Updater#body=}, and
866
+ # {Routine::Updater#description=}.
867
+ #
868
+ # @param [String] routine_id The ID of the routine. The ID must contain only
869
+ # letters (a-z, A-Z), numbers (0-9), or underscores (_). The maximum length
870
+ # is 256 characters.
871
+ # @yield [routine] A block for setting properties on the routine.
872
+ # @yieldparam [Google::Cloud::Bigquery::Routine::Updater] routine An updater to set additional properties on the
873
+ # routine.
874
+ #
875
+ # @return [Google::Cloud::Bigquery::Routine] A new routine object.
876
+ #
877
+ # @example
878
+ # require "google/cloud/bigquery"
879
+ #
880
+ # bigquery = Google::Cloud::Bigquery.new
881
+ # dataset = bigquery.dataset "my_dataset"
882
+ #
883
+ # routine = dataset.create_routine "my_routine" do |r|
884
+ # r.routine_type = "SCALAR_FUNCTION"
885
+ # r.language = "SQL"
886
+ # r.arguments = [
887
+ # Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
888
+ # ]
889
+ # r.body = "x * 3"
890
+ # r.description = "My routine description"
891
+ # end
892
+ #
893
+ # puts routine.routine_id
894
+ #
895
+ # @example Extended example:
896
+ # require "google/cloud/bigquery"
897
+ #
898
+ # bigquery = Google::Cloud::Bigquery.new
899
+ # dataset = bigquery.dataset "my_dataset"
900
+ # routine = dataset.create_routine "my_routine" do |r|
901
+ # r.routine_type = "SCALAR_FUNCTION"
902
+ # r.language = :SQL
903
+ # r.body = "(SELECT SUM(IF(elem.name = \"foo\",elem.val,null)) FROM UNNEST(arr) AS elem)"
904
+ # r.arguments = [
905
+ # Google::Cloud::Bigquery::Argument.new(
906
+ # name: "arr",
907
+ # argument_kind: "FIXED_TYPE",
908
+ # data_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
909
+ # type_kind: "ARRAY",
910
+ # array_element_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
911
+ # type_kind: "STRUCT",
912
+ # struct_type: Google::Cloud::Bigquery::StandardSql::StructType.new(
913
+ # fields: [
914
+ # Google::Cloud::Bigquery::StandardSql::Field.new(
915
+ # name: "name",
916
+ # type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "STRING")
917
+ # ),
918
+ # Google::Cloud::Bigquery::StandardSql::Field.new(
919
+ # name: "val",
920
+ # type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "INT64")
921
+ # )
922
+ # ]
923
+ # )
924
+ # )
925
+ # )
926
+ # )
927
+ # ]
928
+ # end
929
+ #
930
+ # @!group Routine
931
+ #
932
+ def create_routine routine_id
933
+ ensure_service!
934
+ new_tb = Google::Apis::BigqueryV2::Routine.new(
935
+ routine_reference: Google::Apis::BigqueryV2::RoutineReference.new(
936
+ project_id: project_id, dataset_id: dataset_id, routine_id: routine_id
937
+ )
938
+ )
939
+ updater = Routine::Updater.new new_tb
940
+
941
+ yield updater if block_given?
942
+
943
+ gapi = service.insert_routine dataset_id, updater.to_gapi
944
+ Routine.from_gapi gapi, service
945
+ end
946
+
947
+ ##
948
+ # Retrieves an existing routine by ID.
949
+ #
950
+ # @param [String] routine_id The ID of a routine.
951
+ # @param [Boolean] skip_lookup Optionally create just a local reference
952
+ # object without verifying that the resource exists on the BigQuery
953
+ # service. Calls made on this object will raise errors if the resource
954
+ # does not exist. Default is `false`. Optional.
955
+ #
956
+ # @return [Google::Cloud::Bigquery::Routine, nil] Returns `nil` if the
957
+ # routine does not exist.
958
+ #
959
+ # @example
960
+ # require "google/cloud/bigquery"
961
+ #
962
+ # bigquery = Google::Cloud::Bigquery.new
963
+ # dataset = bigquery.dataset "my_dataset"
964
+ #
965
+ # routine = dataset.routine "my_routine"
966
+ # puts routine.routine_id
967
+ #
968
+ # @example Avoid retrieving the routine resource with `skip_lookup`:
969
+ # require "google/cloud/bigquery"
970
+ #
971
+ # bigquery = Google::Cloud::Bigquery.new
972
+ #
973
+ # dataset = bigquery.dataset "my_dataset"
974
+ #
975
+ # routine = dataset.routine "my_routine", skip_lookup: true
976
+ #
977
+ # @!group Routine
978
+ #
979
+ def routine routine_id, skip_lookup: nil
980
+ ensure_service!
981
+ return Routine.new_reference project_id, dataset_id, routine_id, service if skip_lookup
982
+ gapi = service.get_routine dataset_id, routine_id
983
+ Routine.from_gapi gapi, service
984
+ rescue Google::Cloud::NotFoundError
985
+ nil
986
+ end
987
+
988
+ ##
989
+ # Retrieves the list of routines belonging to the dataset.
990
+ #
991
+ # @param [String] token A previously-returned page token representing
992
+ # part of the larger set of results to view.
993
+ # @param [Integer] max Maximum number of routines to return.
994
+ # @param [String] filter If set, then only the routines matching this filter are returned. The current supported
995
+ # form is `routineType:`, with a {Routine#routine_type} enum value. Example: `routineType:SCALAR_FUNCTION`.
996
+ #
997
+ # @return [Array<Google::Cloud::Bigquery::Routine>] An array of routines
998
+ # (See {Google::Cloud::Bigquery::Routine::List})
999
+ #
1000
+ # @example
1001
+ # require "google/cloud/bigquery"
1002
+ #
1003
+ # bigquery = Google::Cloud::Bigquery.new
1004
+ # dataset = bigquery.dataset "my_dataset"
1005
+ #
1006
+ # routines = dataset.routines
1007
+ # routines.each do |routine|
1008
+ # puts routine.routine_id
1009
+ # end
1010
+ #
1011
+ # @example Retrieve all routines: (See {Routine::List#all})
1012
+ # require "google/cloud/bigquery"
1013
+ #
1014
+ # bigquery = Google::Cloud::Bigquery.new
1015
+ # dataset = bigquery.dataset "my_dataset"
1016
+ #
1017
+ # routines = dataset.routines
1018
+ # routines.all do |routine|
1019
+ # puts routine.routine_id
1020
+ # end
1021
+ #
1022
+ # @!group Routine
1023
+ #
1024
+ def routines token: nil, max: nil, filter: nil
1025
+ ensure_service!
1026
+ gapi = service.list_routines dataset_id, token: token, max: max, filter: filter
1027
+ Routine::List.from_gapi gapi, service, dataset_id, max, filter: filter
1028
+ end
1029
+
820
1030
  ##
821
1031
  # Queries data by creating a [query
822
1032
  # job](https://cloud.google.com/bigquery/docs/query-overview#query_jobs).
@@ -969,12 +1179,20 @@ module Google
969
1179
  # list must have a different key. See [Requirements for
970
1180
  # labels](https://cloud.google.com/bigquery/docs/creating-managing-labels#requirements).
971
1181
  # @param [Array<String>, String] udfs User-defined function resources
972
- # used in the query. May be either a code resource to load from a
973
- # Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
1182
+ # used in a legacy SQL query. May be either a code resource to load from
1183
+ # a Google Cloud Storage URI (`gs://bucket/path`), or an inline resource
974
1184
  # that contains code for a user-defined function (UDF). Providing an
975
1185
  # inline code resource is equivalent to providing a URI for a file
976
- # containing the same code. See [User-Defined
977
- # Functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/user-defined-functions).
1186
+ # containing the same code.
1187
+ #
1188
+ # This parameter is used for defining User Defined Function (UDF)
1189
+ # resources only when using legacy SQL. Users of standard SQL should
1190
+ # leverage either DDL (e.g. `CREATE [TEMPORARY] FUNCTION ...`) or the
1191
+ # Routines API to define UDF resources.
1192
+ #
1193
+ # For additional information on migrating, see: [Migrating to
1194
+ # standard SQL - Differences in user-defined JavaScript
1195
+ # functions](https://cloud.google.com/bigquery/docs/reference/standard-sql/migrating-from-legacy-sql#differences_in_user-defined_javascript_functions)
978
1196
  # @param [Integer] maximum_billing_tier Deprecated: Change the billing
979
1197
  # tier to allow high-compute queries.
980
1198
  # @yield [job] a job configuration object
@@ -1073,7 +1291,7 @@ module Google
1073
1291
  #
1074
1292
  # job.wait_until_done!
1075
1293
  # if !job.failed?
1076
- # table_ref = job.ddl_target_table
1294
+ # table_ref = job.ddl_target_table # Or ddl_target_routine for CREATE/DROP FUNCTION/PROCEDURE
1077
1295
  # end
1078
1296
  #
1079
1297
  # @example Execute a DML statement:
@@ -1256,9 +1474,12 @@ module Google
1256
1474
  #
1257
1475
  # data = dataset.query "SELECT name FROM my_table"
1258
1476
  #
1477
+ # # Iterate over the first page of results
1259
1478
  # data.each do |row|
1260
1479
  # puts row[:name]
1261
1480
  # end
1481
+ # # Retrieve the next page of results
1482
+ # data = data.next if data.next?
1262
1483
  #
1263
1484
  # @example Query using legacy SQL:
1264
1485
  # require "google/cloud/bigquery"
@@ -1269,9 +1490,12 @@ module Google
1269
1490
  # data = dataset.query "SELECT name FROM my_table",
1270
1491
  # legacy_sql: true
1271
1492
  #
1493
+ # # Iterate over the first page of results
1272
1494
  # data.each do |row|
1273
1495
  # puts row[:name]
1274
1496
  # end
1497
+ # # Retrieve the next page of results
1498
+ # data = data.next if data.next?
1275
1499
  #
1276
1500
  # @example Query using positional query parameters:
1277
1501
  # require "google/cloud/bigquery"
@@ -1282,9 +1506,12 @@ module Google
1282
1506
  # data = dataset.query "SELECT name FROM my_table WHERE id = ?",
1283
1507
  # params: [1]
1284
1508
  #
1509
+ # # Iterate over the first page of results
1285
1510
  # data.each do |row|
1286
1511
  # puts row[:name]
1287
1512
  # end
1513
+ # # Retrieve the next page of results
1514
+ # data = data.next if data.next?
1288
1515
  #
1289
1516
  # @example Query using named query parameters:
1290
1517
  # require "google/cloud/bigquery"
@@ -1295,9 +1522,12 @@ module Google
1295
1522
  # data = dataset.query "SELECT name FROM my_table WHERE id = @id",
1296
1523
  # params: { id: 1 }
1297
1524
  #
1525
+ # # Iterate over the first page of results
1298
1526
  # data.each do |row|
1299
1527
  # puts row[:name]
1300
1528
  # end
1529
+ # # Retrieve the next page of results
1530
+ # data = data.next if data.next?
1301
1531
  #
1302
1532
  # @example Query using named query parameters with types:
1303
1533
  # require "google/cloud/bigquery"
@@ -1310,9 +1540,12 @@ module Google
1310
1540
  # params: { ids: [] },
1311
1541
  # types: { ids: [:INT64] }
1312
1542
  #
1543
+ # # Iterate over the first page of results
1313
1544
  # data.each do |row|
1314
1545
  # puts row[:name]
1315
1546
  # end
1547
+ # # Retrieve the next page of results
1548
+ # data = data.next if data.next?
1316
1549
  #
1317
1550
  # @example Execute a DDL statement:
1318
1551
  # require "google/cloud/bigquery"
@@ -1321,7 +1554,7 @@ module Google
1321
1554
  #
1322
1555
  # data = bigquery.query "CREATE TABLE my_table (x INT64)"
1323
1556
  #
1324
- # table_ref = data.ddl_target_table
1557
+ # table_ref = data.ddl_target_table # Or ddl_target_routine for CREATE/DROP FUNCTION/PROCEDURE
1325
1558
  #
1326
1559
  # @example Execute a DML statement:
1327
1560
  # require "google/cloud/bigquery"
@@ -1351,9 +1584,12 @@ module Google
1351
1584
  # query.table = dataset.table "my_table", skip_lookup: true
1352
1585
  # end
1353
1586
  #
1587
+ # # Iterate over the first page of results
1354
1588
  # data.each do |row|
1355
1589
  # puts row[:name]
1356
1590
  # end
1591
+ # # Retrieve the next page of results
1592
+ # data = data.next if data.next?
1357
1593
  #
1358
1594
  # @!group Data
1359
1595
  #
@@ -1942,7 +2178,7 @@ module Google
1942
2178
  # dataset = bigquery.dataset "my_dataset", skip_lookup: true
1943
2179
  # dataset.exists? # true
1944
2180
  #
1945
- def exists? force: nil
2181
+ def exists? force: false
1946
2182
  return gapi_exists? if force
1947
2183
  # If we have a memoized value, return it
1948
2184
  return @exists unless @exists.nil?
@@ -2052,7 +2288,7 @@ module Google
2052
2288
  end
2053
2289
 
2054
2290
  ##
2055
- # @private New lazy Dataset object without making an HTTP request.
2291
+ # @private New lazy Dataset object without making an HTTP request, for use with the skip_lookup option.
2056
2292
  def self.new_reference project_id, dataset_id, service
2057
2293
  raise ArgumentError, "dataset_id is required" unless dataset_id
2058
2294
  new.tap do |b|
@@ -2083,12 +2319,13 @@ module Google
2083
2319
  # @param [String] table_id The ID of the destination table.
2084
2320
  # @param [Hash, Array<Hash>] rows A hash object or array of hash objects
2085
2321
  # containing the data. Required.
2086
- # @param [Array<String>] insert_ids A unique ID for each row. BigQuery
2087
- # uses this property to detect duplicate insertion requests on a
2088
- # best-effort basis. For more information, see [data
2089
- # consistency](https://cloud.google.com/bigquery/streaming-data-into-bigquery#dataconsistency).
2090
- # Optional. If not provided, the client library will assign a UUID to
2091
- # each row before the request is sent.
2322
+ # @param [Array<String|Symbol>, Symbol] insert_ids A unique ID for each row. BigQuery uses this property to
2323
+ # detect duplicate insertion requests on a best-effort basis. For more information, see [data
2324
+ # consistency](https://cloud.google.com/bigquery/streaming-data-into-bigquery#dataconsistency). Optional. If
2325
+ # not provided, the client library will assign a UUID to each row before the request is sent.
2326
+ #
2327
+ # The value `:skip` can be provided to skip the generation of IDs for all rows, or to skip the generation of an
2328
+ # ID for a specific row in the array.
2092
2329
  # @param [Boolean] skip_invalid Insert all valid rows of a request, even
2093
2330
  # if invalid rows exist. The default value is `false`, which causes
2094
2331
  # the entire request to fail if any invalid rows exist.
@@ -2099,6 +2336,12 @@ module Google
2099
2336
  # a new table with the given `table_id`, if no table is found for
2100
2337
  # `table_id`. The default value is false.
2101
2338
  #
2339
+ # @yield [table] a block for setting the table
2340
+ # @yieldparam [Google::Cloud::Bigquery::Table::Updater] table An updater
2341
+ # to set additional properties on the table in the API request to
2342
+ # create it. Only used when `autocreate` is set and the table does not
2343
+ # already exist.
2344
+ #
2102
2345
  # @return [Google::Cloud::Bigquery::InsertResponse] An insert response
2103
2346
  # object.
2104
2347
  #
@@ -2144,32 +2387,19 @@ module Google
2144
2387
  #
2145
2388
  # @!group Data
2146
2389
  #
2147
- def insert table_id, rows, insert_ids: nil, skip_invalid: nil, ignore_unknown: nil, autocreate: nil
2390
+ def insert table_id, rows, insert_ids: nil, skip_invalid: nil, ignore_unknown: nil, autocreate: nil, &block
2148
2391
  rows = [rows] if rows.is_a? Hash
2392
+ raise ArgumentError, "No rows provided" if rows.empty?
2393
+
2394
+ insert_ids = Array.new(rows.count) { :skip } if insert_ids == :skip
2149
2395
  insert_ids = Array insert_ids
2150
2396
  if insert_ids.count.positive? && insert_ids.count != rows.count
2151
2397
  raise ArgumentError, "insert_ids must be the same size as rows"
2152
2398
  end
2153
2399
 
2154
2400
  if autocreate
2155
- begin
2156
- insert_data table_id, rows,
2157
- skip_invalid: skip_invalid, ignore_unknown: ignore_unknown, insert_ids: insert_ids
2158
- rescue Google::Cloud::NotFoundError
2159
- sleep rand(1..60)
2160
- begin
2161
- create_table table_id do |tbl_updater|
2162
- yield tbl_updater if block_given?
2163
- end
2164
- # rubocop:disable Lint/HandleExceptions
2165
- rescue Google::Cloud::AlreadyExistsError
2166
- end
2167
- # rubocop:enable Lint/HandleExceptions
2168
-
2169
- sleep 60
2170
- insert table_id, rows, skip_invalid: skip_invalid, ignore_unknown: ignore_unknown, autocreate: true,
2171
- insert_ids: insert_ids
2172
- end
2401
+ insert_data_with_autocreate table_id, rows, skip_invalid: skip_invalid, ignore_unknown: ignore_unknown,
2402
+ insert_ids: insert_ids, &block
2173
2403
  else
2174
2404
  insert_data table_id, rows, skip_invalid: skip_invalid, ignore_unknown: ignore_unknown,
2175
2405
  insert_ids: insert_ids
@@ -2239,15 +2469,30 @@ module Google
2239
2469
 
2240
2470
  protected
2241
2471
 
2242
- def insert_data table_id, rows, skip_invalid: nil, ignore_unknown: nil,
2243
- insert_ids: nil
2472
+ def insert_data_with_autocreate table_id, rows, skip_invalid: nil, ignore_unknown: nil, insert_ids: nil
2473
+ insert_data table_id, rows, skip_invalid: skip_invalid, ignore_unknown: ignore_unknown, insert_ids: insert_ids
2474
+ rescue Google::Cloud::NotFoundError
2475
+ sleep rand(1..60)
2476
+ begin
2477
+ create_table table_id do |tbl_updater|
2478
+ yield tbl_updater if block_given?
2479
+ end
2480
+ # rubocop:disable Lint/HandleExceptions
2481
+ rescue Google::Cloud::AlreadyExistsError
2482
+ end
2483
+ # rubocop:enable Lint/HandleExceptions
2484
+
2485
+ sleep 60
2486
+ retry
2487
+ end
2488
+
2489
+ def insert_data table_id, rows, skip_invalid: nil, ignore_unknown: nil, insert_ids: nil
2244
2490
  rows = [rows] if rows.is_a? Hash
2245
2491
  raise ArgumentError, "No rows provided" if rows.empty?
2246
2492
  ensure_service!
2247
- options = { skip_invalid: skip_invalid,
2248
- ignore_unknown: ignore_unknown,
2249
- insert_ids: insert_ids }
2250
- gapi = service.insert_tabledata dataset_id, table_id, rows, options
2493
+ gapi = service.insert_tabledata dataset_id, table_id, rows, skip_invalid: skip_invalid,
2494
+ ignore_unknown: ignore_unknown,
2495
+ insert_ids: insert_ids
2251
2496
  InsertResponse.from_gapi rows, gapi
2252
2497
  end
2253
2498
 
@@ -2444,14 +2689,14 @@ module Google
2444
2689
  end
2445
2690
 
2446
2691
  ##
2447
- # Yielded to a block to accumulate changes for a patch request.
2692
+ # Yielded to a block to accumulate changes for a create request. See {Project#create_dataset}.
2448
2693
  class Updater < Dataset
2449
2694
  ##
2450
- # A list of attributes that were updated.
2695
+ # @private A list of attributes that were updated.
2451
2696
  attr_reader :updates
2452
2697
 
2453
2698
  ##
2454
- # Create an Updater object.
2699
+ # @private Create an Updater object.
2455
2700
  def initialize gapi
2456
2701
  @updates = []
2457
2702
  @gapi = gapi
@@ -2468,8 +2713,109 @@ module Google
2468
2713
  @access
2469
2714
  end
2470
2715
 
2716
+ # rubocop:disable Style/MethodDefParentheses
2717
+
2718
+ ##
2719
+ # @raise [RuntimeError] not implemented
2720
+ def delete(*)
2721
+ raise "not implemented in #{self.class}"
2722
+ end
2723
+
2471
2724
  ##
2472
- # Make sure any access changes are saved
2725
+ # @raise [RuntimeError] not implemented
2726
+ def create_table(*)
2727
+ raise "not implemented in #{self.class}"
2728
+ end
2729
+
2730
+ ##
2731
+ # @raise [RuntimeError] not implemented
2732
+ def create_view(*)
2733
+ raise "not implemented in #{self.class}"
2734
+ end
2735
+
2736
+ ##
2737
+ # @raise [RuntimeError] not implemented
2738
+ def table(*)
2739
+ raise "not implemented in #{self.class}"
2740
+ end
2741
+
2742
+ ##
2743
+ # @raise [RuntimeError] not implemented
2744
+ def tables(*)
2745
+ raise "not implemented in #{self.class}"
2746
+ end
2747
+
2748
+ ##
2749
+ # @raise [RuntimeError] not implemented
2750
+ def model(*)
2751
+ raise "not implemented in #{self.class}"
2752
+ end
2753
+
2754
+ ##
2755
+ # @raise [RuntimeError] not implemented
2756
+ def models(*)
2757
+ raise "not implemented in #{self.class}"
2758
+ end
2759
+
2760
+ ##
2761
+ # @raise [RuntimeError] not implemented
2762
+ def create_routine(*)
2763
+ raise "not implemented in #{self.class}"
2764
+ end
2765
+
2766
+ ##
2767
+ # @raise [RuntimeError] not implemented
2768
+ def routine(*)
2769
+ raise "not implemented in #{self.class}"
2770
+ end
2771
+
2772
+ ##
2773
+ # @raise [RuntimeError] not implemented
2774
+ def routines(*)
2775
+ raise "not implemented in #{self.class}"
2776
+ end
2777
+
2778
+ ##
2779
+ # @raise [RuntimeError] not implemented
2780
+ def query_job(*)
2781
+ raise "not implemented in #{self.class}"
2782
+ end
2783
+
2784
+ ##
2785
+ # @raise [RuntimeError] not implemented
2786
+ def query(*)
2787
+ raise "not implemented in #{self.class}"
2788
+ end
2789
+
2790
+ ##
2791
+ # @raise [RuntimeError] not implemented
2792
+ def external(*)
2793
+ raise "not implemented in #{self.class}"
2794
+ end
2795
+
2796
+ ##
2797
+ # @raise [RuntimeError] not implemented
2798
+ def load_job(*)
2799
+ raise "not implemented in #{self.class}"
2800
+ end
2801
+
2802
+ ##
2803
+ # @raise [RuntimeError] not implemented
2804
+ def load(*)
2805
+ raise "not implemented in #{self.class}"
2806
+ end
2807
+
2808
+ ##
2809
+ # @raise [RuntimeError] not implemented
2810
+ def reload!
2811
+ raise "not implemented in #{self.class}"
2812
+ end
2813
+ alias refresh! reload!
2814
+
2815
+ # rubocop:enable Style/MethodDefParentheses
2816
+
2817
+ ##
2818
+ # @private Make sure any access changes are saved
2473
2819
  def check_for_mutated_access!
2474
2820
  return if @access.nil?
2475
2821
  return unless @access.changed?
@@ -2477,6 +2823,8 @@ module Google
2477
2823
  patch_gapi! :access
2478
2824
  end
2479
2825
 
2826
+ ##
2827
+ # @private
2480
2828
  def to_gapi
2481
2829
  check_for_mutated_access!
2482
2830
  @gapi