google-cloud-bigquery 1.14.0 → 1.42.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.
- checksums.yaml +4 -4
- data/AUTHENTICATION.md +17 -54
- data/CHANGELOG.md +377 -0
- data/CONTRIBUTING.md +328 -116
- data/LOGGING.md +1 -1
- data/OVERVIEW.md +21 -20
- data/TROUBLESHOOTING.md +2 -8
- data/lib/google/cloud/bigquery/argument.rb +197 -0
- data/lib/google/cloud/bigquery/convert.rb +155 -173
- data/lib/google/cloud/bigquery/copy_job.rb +74 -26
- data/lib/google/cloud/bigquery/credentials.rb +5 -12
- data/lib/google/cloud/bigquery/data.rb +109 -18
- data/lib/google/cloud/bigquery/dataset/access.rb +474 -52
- data/lib/google/cloud/bigquery/dataset/list.rb +7 -13
- data/lib/google/cloud/bigquery/dataset/tag.rb +67 -0
- data/lib/google/cloud/bigquery/dataset.rb +1044 -287
- data/lib/google/cloud/bigquery/external/avro_source.rb +107 -0
- data/lib/google/cloud/bigquery/external/bigtable_source/column.rb +404 -0
- data/lib/google/cloud/bigquery/external/bigtable_source/column_family.rb +945 -0
- data/lib/google/cloud/bigquery/external/bigtable_source.rb +230 -0
- data/lib/google/cloud/bigquery/external/csv_source.rb +481 -0
- data/lib/google/cloud/bigquery/external/data_source.rb +771 -0
- data/lib/google/cloud/bigquery/external/json_source.rb +170 -0
- data/lib/google/cloud/bigquery/external/parquet_source.rb +148 -0
- data/lib/google/cloud/bigquery/external/sheets_source.rb +166 -0
- data/lib/google/cloud/bigquery/external.rb +50 -2256
- data/lib/google/cloud/bigquery/extract_job.rb +226 -61
- data/lib/google/cloud/bigquery/insert_response.rb +1 -3
- data/lib/google/cloud/bigquery/job/list.rb +10 -14
- data/lib/google/cloud/bigquery/job.rb +289 -14
- data/lib/google/cloud/bigquery/load_job.rb +810 -136
- data/lib/google/cloud/bigquery/model/list.rb +5 -9
- data/lib/google/cloud/bigquery/model.rb +247 -16
- data/lib/google/cloud/bigquery/policy.rb +432 -0
- data/lib/google/cloud/bigquery/project/list.rb +6 -11
- data/lib/google/cloud/bigquery/project.rb +509 -250
- data/lib/google/cloud/bigquery/query_job.rb +594 -128
- data/lib/google/cloud/bigquery/routine/list.rb +165 -0
- data/lib/google/cloud/bigquery/routine.rb +1227 -0
- data/lib/google/cloud/bigquery/schema/field.rb +413 -63
- data/lib/google/cloud/bigquery/schema.rb +221 -48
- data/lib/google/cloud/bigquery/service.rb +204 -112
- data/lib/google/cloud/bigquery/standard_sql.rb +269 -53
- data/lib/google/cloud/bigquery/table/async_inserter.rb +86 -43
- data/lib/google/cloud/bigquery/table/list.rb +6 -11
- data/lib/google/cloud/bigquery/table.rb +1470 -377
- data/lib/google/cloud/bigquery/time.rb +6 -0
- data/lib/google/cloud/bigquery/version.rb +1 -1
- data/lib/google/cloud/bigquery.rb +4 -6
- data/lib/google-cloud-bigquery.rb +14 -13
- metadata +66 -38
@@ -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
|
@@ -23,30 +23,29 @@ require "date"
|
|
23
23
|
module Google
|
24
24
|
module Cloud
|
25
25
|
module Bigquery
|
26
|
-
# rubocop:disable Metrics/ModuleLength
|
27
|
-
|
28
26
|
##
|
29
27
|
# @private
|
30
28
|
#
|
31
|
-
# Internal conversion of raw data values to/from
|
29
|
+
# Internal conversion of raw data values to/from BigQuery values
|
30
|
+
#
|
31
|
+
# | BigQuery | Ruby | Notes |
|
32
|
+
# |--------------|--------------------------------------|----------------------------------------------------|
|
33
|
+
# | `BOOL` | `true`/`false` | |
|
34
|
+
# | `INT64` | `Integer` | |
|
35
|
+
# | `FLOAT64` | `Float` | |
|
36
|
+
# | `NUMERIC` | `BigDecimal` | `BigDecimal` values will be rounded to scale 9. |
|
37
|
+
# | `BIGNUMERIC` | converted to `BigDecimal` | Pass data as `String`; map query params in `types`.|
|
38
|
+
# | `STRING` | `String` | |
|
39
|
+
# | `DATETIME` | `DateTime` | `DATETIME` does not support time zone. |
|
40
|
+
# | `DATE` | `Date` | |
|
41
|
+
# | `GEOGRAPHY` | `String` | |
|
42
|
+
# | `TIMESTAMP` | `Time` | |
|
43
|
+
# | `TIME` | `Google::Cloud::BigQuery::Time` | |
|
44
|
+
# | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
|
45
|
+
# | `ARRAY` | `Array` | Nested arrays, `nil` values are not supported. |
|
46
|
+
# | `STRUCT` | `Hash` | Hash keys may be strings or symbols. |
|
32
47
|
#
|
33
|
-
# | BigQuery | Ruby | Notes |
|
34
|
-
# |-------------|----------------|---|
|
35
|
-
# | `BOOL` | `true`/`false` | |
|
36
|
-
# | `INT64` | `Integer` | |
|
37
|
-
# | `FLOAT64` | `Float` | |
|
38
|
-
# | `NUMERIC` | `BigDecimal` | Will be rounded to 9 decimal places |
|
39
|
-
# | `STRING` | `String` | |
|
40
|
-
# | `DATETIME` | `DateTime` | `DATETIME` does not support time zone. |
|
41
|
-
# | `DATE` | `Date` | |
|
42
|
-
# | `TIMESTAMP` | `Time` | |
|
43
|
-
# | `TIME` | `Google::Cloud::BigQuery::Time` | |
|
44
|
-
# | `BYTES` | `File`, `IO`, `StringIO`, or similar | |
|
45
|
-
# | `ARRAY` | `Array` | Nested arrays, `nil` values are not supported. |
|
46
|
-
# | `STRUCT` | `Hash` | Hash keys may be strings or symbols. |
|
47
48
|
module Convert
|
48
|
-
##
|
49
|
-
# @private
|
50
49
|
def self.format_rows rows, fields
|
51
50
|
Array(rows).map do |row|
|
52
51
|
# convert TableRow to hash to handle nested TableCell values
|
@@ -54,13 +53,10 @@ module Google
|
|
54
53
|
end
|
55
54
|
end
|
56
55
|
|
57
|
-
##
|
58
|
-
# @private
|
59
56
|
def self.format_row row, fields
|
60
|
-
|
57
|
+
fields.zip(row[:f]).to_h do |f, v|
|
61
58
|
[f.name.to_sym, format_value(v, f)]
|
62
59
|
end
|
63
|
-
Hash[row_pairs]
|
64
60
|
end
|
65
61
|
|
66
62
|
# rubocop:disable all
|
@@ -75,11 +71,7 @@ module Google
|
|
75
71
|
elsif Array === value[:v]
|
76
72
|
value[:v].map { |v| format_value v, field }
|
77
73
|
elsif Hash === value[:v]
|
78
|
-
|
79
|
-
nil
|
80
|
-
else
|
81
|
-
format_row value[:v], field.fields
|
82
|
-
end
|
74
|
+
format_row value[:v], field.fields
|
83
75
|
elsif field.type == "STRING"
|
84
76
|
String value[:v]
|
85
77
|
elsif field.type == "INTEGER"
|
@@ -96,6 +88,8 @@ module Google
|
|
96
88
|
end
|
97
89
|
elsif field.type == "NUMERIC"
|
98
90
|
BigDecimal value[:v]
|
91
|
+
elsif field.type == "BIGNUMERIC"
|
92
|
+
BigDecimal value[:v]
|
99
93
|
elsif field.type == "BOOLEAN"
|
100
94
|
(value[:v] == "true" ? true : (value[:v] == "false" ? false : nil))
|
101
95
|
elsif field.type == "BYTES"
|
@@ -108,135 +102,118 @@ module Google
|
|
108
102
|
::Time.parse("#{value[:v]} UTC").to_datetime
|
109
103
|
elsif field.type == "DATE"
|
110
104
|
Date.parse value[:v]
|
105
|
+
elsif field.type == "GEOGRAPHY"
|
106
|
+
String value[:v]
|
111
107
|
else
|
112
108
|
value[:v]
|
113
109
|
end
|
114
110
|
end
|
115
111
|
|
116
|
-
|
117
|
-
|
118
|
-
def self.
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
value: false)
|
132
|
-
)
|
133
|
-
elsif Integer === value
|
134
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
135
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
136
|
-
type: "INT64"),
|
137
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
138
|
-
value: value)
|
139
|
-
)
|
140
|
-
elsif Float === value
|
141
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
142
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
143
|
-
type: "FLOAT64"),
|
144
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
145
|
-
value: value)
|
146
|
-
)
|
147
|
-
elsif BigDecimal === value
|
148
|
-
# Round to precision of 9
|
149
|
-
value_str = value.finite? ? value.round(9).to_s("F") : value.to_s
|
150
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
151
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
152
|
-
type: "NUMERIC"),
|
153
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
154
|
-
value: value_str)
|
155
|
-
)
|
156
|
-
elsif String === value
|
157
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
158
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
159
|
-
type: "STRING"),
|
160
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
161
|
-
value: value)
|
162
|
-
)
|
163
|
-
elsif DateTime === value
|
164
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
165
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
166
|
-
type: "DATETIME"),
|
167
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
168
|
-
value: value.strftime("%Y-%m-%d %H:%M:%S.%6N"))
|
169
|
-
)
|
170
|
-
elsif Date === value
|
171
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
172
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
173
|
-
type: "DATE"),
|
174
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
175
|
-
value: value.to_s)
|
176
|
-
)
|
177
|
-
elsif ::Time === value
|
178
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
179
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
180
|
-
type: "TIMESTAMP"),
|
181
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
182
|
-
value: value.strftime("%Y-%m-%d %H:%M:%S.%6N%:z"))
|
183
|
-
)
|
184
|
-
elsif Bigquery::Time === value
|
185
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
186
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
187
|
-
type: "TIME"),
|
188
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
189
|
-
value: value.value)
|
190
|
-
)
|
191
|
-
elsif value.respond_to?(:read) && value.respond_to?(:rewind)
|
192
|
-
value.rewind
|
193
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
194
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
195
|
-
type: "BYTES"),
|
196
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
197
|
-
value: Base64.strict_encode64(
|
198
|
-
value.read.force_encoding("ASCII-8BIT")))
|
199
|
-
)
|
200
|
-
elsif Array === value
|
201
|
-
array_params = value.map { |param| Convert.to_query_param param }
|
202
|
-
return Google::Apis::BigqueryV2::QueryParameter.new(
|
203
|
-
parameter_type: Google::Apis::BigqueryV2::QueryParameterType.new(
|
204
|
-
type: "ARRAY",
|
205
|
-
array_type: array_params.first.parameter_type
|
206
|
-
),
|
207
|
-
parameter_value: Google::Apis::BigqueryV2::QueryParameterValue.new(
|
208
|
-
array_values: array_params.map(&:parameter_value)
|
209
|
-
)
|
210
|
-
)
|
211
|
-
elsif Hash === value
|
212
|
-
struct_pairs = value.map do |name, param|
|
213
|
-
struct_param = Convert.to_query_param param
|
214
|
-
[Google::Apis::BigqueryV2::QueryParameterType::StructType.new(
|
215
|
-
name: String(name),
|
216
|
-
type: struct_param.parameter_type
|
217
|
-
), struct_param.parameter_value]
|
112
|
+
# rubocop:enable all
|
113
|
+
|
114
|
+
def self.to_query_param_value value, type = nil
|
115
|
+
return Google::Apis::BigqueryV2::QueryParameterValue.new value: nil if value.nil?
|
116
|
+
|
117
|
+
json_value = to_json_value value, type
|
118
|
+
|
119
|
+
case json_value
|
120
|
+
when Array
|
121
|
+
type = extract_array_type type
|
122
|
+
array_values = json_value.map { |v| to_query_param_value v, type }
|
123
|
+
Google::Apis::BigqueryV2::QueryParameterValue.new array_values: array_values
|
124
|
+
when Hash
|
125
|
+
struct_values = json_value.to_h do |k, v|
|
126
|
+
[String(k), to_query_param_value(v, type)]
|
218
127
|
end
|
219
|
-
|
220
|
-
|
221
|
-
|
128
|
+
Google::Apis::BigqueryV2::QueryParameterValue.new struct_values: struct_values
|
129
|
+
else
|
130
|
+
# Everything else is converted to a string, per the API expectations.
|
131
|
+
Google::Apis::BigqueryV2::QueryParameterValue.new value: json_value.to_s
|
132
|
+
end
|
133
|
+
end
|
222
134
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
135
|
+
def self.to_query_param_type type
|
136
|
+
case type
|
137
|
+
when Array
|
138
|
+
Google::Apis::BigqueryV2::QueryParameterType.new(
|
139
|
+
type: "ARRAY".freeze,
|
140
|
+
array_type: to_query_param_type(type.first)
|
141
|
+
)
|
142
|
+
when Hash
|
143
|
+
Google::Apis::BigqueryV2::QueryParameterType.new(
|
144
|
+
type: "STRUCT".freeze,
|
145
|
+
struct_types: type.map do |key, val|
|
146
|
+
Google::Apis::BigqueryV2::QueryParameterType::StructType.new(
|
147
|
+
name: String(key),
|
148
|
+
type: to_query_param_type(val)
|
149
|
+
)
|
150
|
+
end
|
231
151
|
)
|
232
152
|
else
|
233
|
-
|
153
|
+
Google::Apis::BigqueryV2::QueryParameterType.new type: type.to_s.freeze
|
234
154
|
end
|
235
155
|
end
|
236
156
|
|
237
|
-
|
238
|
-
#
|
239
|
-
|
157
|
+
# rubocop:disable Lint/DuplicateBranch
|
158
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
159
|
+
# rubocop:disable Style/GuardClause
|
160
|
+
|
161
|
+
def self.default_query_param_type_for param
|
162
|
+
raise ArgumentError, "nil params are not supported, must assign optional type" if param.nil?
|
163
|
+
|
164
|
+
case param
|
165
|
+
when String
|
166
|
+
:STRING
|
167
|
+
when Symbol
|
168
|
+
:STRING
|
169
|
+
when TrueClass
|
170
|
+
:BOOL
|
171
|
+
when FalseClass
|
172
|
+
:BOOL
|
173
|
+
when Integer
|
174
|
+
:INT64
|
175
|
+
when BigDecimal
|
176
|
+
:NUMERIC
|
177
|
+
when Numeric
|
178
|
+
:FLOAT64
|
179
|
+
when ::Time
|
180
|
+
:TIMESTAMP
|
181
|
+
when Bigquery::Time
|
182
|
+
:TIME
|
183
|
+
when DateTime
|
184
|
+
:DATETIME
|
185
|
+
when Date
|
186
|
+
:DATE
|
187
|
+
when Array
|
188
|
+
if param.empty?
|
189
|
+
raise ArgumentError, "Cannot determine type for empty array values"
|
190
|
+
end
|
191
|
+
non_nil_values = param.compact.map { |p| default_query_param_type_for p }.compact
|
192
|
+
if non_nil_values.empty?
|
193
|
+
raise ArgumentError, "Cannot determine type for array of nil values"
|
194
|
+
end
|
195
|
+
if non_nil_values.uniq.count > 1
|
196
|
+
raise ArgumentError, "Cannot determine type for array of different types of values"
|
197
|
+
end
|
198
|
+
[non_nil_values.first]
|
199
|
+
when Hash
|
200
|
+
param.transform_values do |value|
|
201
|
+
default_query_param_type_for value
|
202
|
+
end
|
203
|
+
else
|
204
|
+
if param.respond_to?(:read) && param.respond_to?(:rewind)
|
205
|
+
:BYTES
|
206
|
+
else
|
207
|
+
raise "A query parameter of type #{param.class} is not supported"
|
208
|
+
end
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
# rubocop:enable Lint/DuplicateBranch
|
213
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
214
|
+
# rubocop:enable Style/GuardClause
|
215
|
+
|
216
|
+
def self.to_json_value value, type = nil
|
240
217
|
if DateTime === value
|
241
218
|
value.strftime "%Y-%m-%d %H:%M:%S.%6N"
|
242
219
|
elsif Date === value
|
@@ -245,30 +222,49 @@ module Google
|
|
245
222
|
value.strftime "%Y-%m-%d %H:%M:%S.%6N%:z"
|
246
223
|
elsif Bigquery::Time === value
|
247
224
|
value.value
|
225
|
+
elsif BigDecimal === value
|
226
|
+
if value.finite?
|
227
|
+
# Round to precision of 9 unless explicit `BIGNUMERIC`
|
228
|
+
bigdecimal = type == :BIGNUMERIC ? value : value.round(9)
|
229
|
+
bigdecimal.to_s "F"
|
230
|
+
else
|
231
|
+
value.to_s
|
232
|
+
end
|
248
233
|
elsif value.respond_to?(:read) && value.respond_to?(:rewind)
|
249
234
|
value.rewind
|
250
|
-
Base64.strict_encode64
|
235
|
+
Base64.strict_encode64 value.read.force_encoding("ASCII-8BIT")
|
251
236
|
elsif Array === value
|
252
|
-
|
237
|
+
type = extract_array_type type
|
238
|
+
value.map { |x| to_json_value x, type }
|
253
239
|
elsif Hash === value
|
254
|
-
|
240
|
+
value.to_h { |k, v| [k.to_s, to_json_value(v, type)] }
|
255
241
|
else
|
256
242
|
value
|
257
243
|
end
|
258
244
|
end
|
259
245
|
|
260
|
-
|
246
|
+
def self.to_query_param param, type = nil
|
247
|
+
type ||= default_query_param_type_for param
|
261
248
|
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
249
|
+
Google::Apis::BigqueryV2::QueryParameter.new(
|
250
|
+
parameter_type: to_query_param_type(type),
|
251
|
+
parameter_value: to_query_param_value(param, type)
|
252
|
+
)
|
266
253
|
end
|
267
254
|
|
268
255
|
##
|
269
|
-
#
|
256
|
+
# Lists are specified by providing the type code in an array. For example, an array of integers are specified as
|
257
|
+
# `[:INT64]`. Extracts the symbol/hash.
|
258
|
+
def self.extract_array_type type
|
259
|
+
return nil if type.nil?
|
260
|
+
unless type.is_a?(Array) && type.count == 1 && (type.first.is_a?(Symbol) || type.first.is_a?(Hash))
|
261
|
+
raise ArgumentError, "types Array #{type.inspect} should include only a single symbol or hash element."
|
262
|
+
end
|
263
|
+
type.first
|
264
|
+
end
|
265
|
+
|
270
266
|
def self.to_json_row row
|
271
|
-
|
267
|
+
row.to_h { |k, v| [k.to_s, to_json_value(v)] }
|
272
268
|
end
|
273
269
|
|
274
270
|
def self.resolve_legacy_sql standard_sql, legacy_sql
|
@@ -278,8 +274,6 @@ module Google
|
|
278
274
|
end
|
279
275
|
|
280
276
|
##
|
281
|
-
# @private
|
282
|
-
#
|
283
277
|
# Converts create disposition strings to API values.
|
284
278
|
#
|
285
279
|
# @return [String] API representation of create disposition.
|
@@ -298,8 +292,6 @@ module Google
|
|
298
292
|
end
|
299
293
|
|
300
294
|
##
|
301
|
-
# @private
|
302
|
-
#
|
303
295
|
# Converts write disposition strings to API values.
|
304
296
|
#
|
305
297
|
# @return [String] API representation of write disposition.
|
@@ -320,8 +312,6 @@ module Google
|
|
320
312
|
end
|
321
313
|
|
322
314
|
##
|
323
|
-
# @private
|
324
|
-
#
|
325
315
|
# Converts source format strings to API values.
|
326
316
|
#
|
327
317
|
# @return [String] API representation of source format.
|
@@ -335,15 +325,15 @@ module Google
|
|
335
325
|
"parquet" => "PARQUET",
|
336
326
|
"datastore" => "DATASTORE_BACKUP",
|
337
327
|
"backup" => "DATASTORE_BACKUP",
|
338
|
-
"datastore_backup" => "DATASTORE_BACKUP"
|
328
|
+
"datastore_backup" => "DATASTORE_BACKUP",
|
329
|
+
"ml_tf_saved_model" => "ML_TF_SAVED_MODEL",
|
330
|
+
"ml_xgboost_booster" => "ML_XGBOOST_BOOSTER"
|
339
331
|
}[format.to_s.downcase]
|
340
332
|
return val unless val.nil?
|
341
333
|
format
|
342
334
|
end
|
343
335
|
|
344
336
|
##
|
345
|
-
# @private
|
346
|
-
#
|
347
337
|
# Converts file paths into source format by extension.
|
348
338
|
#
|
349
339
|
# @return [String] API representation of source format.
|
@@ -354,8 +344,6 @@ module Google
|
|
354
344
|
end
|
355
345
|
|
356
346
|
##
|
357
|
-
# @private
|
358
|
-
#
|
359
347
|
# Converts file path into source format by extension.
|
360
348
|
#
|
361
349
|
# @return [String] API representation of source format.
|
@@ -370,8 +358,6 @@ module Google
|
|
370
358
|
end
|
371
359
|
|
372
360
|
##
|
373
|
-
# @private
|
374
|
-
#
|
375
361
|
# Converts a primitive time value in milliseconds to a Ruby Time object.
|
376
362
|
#
|
377
363
|
# @return [Time, nil] The Ruby Time object, or nil if the given argument
|
@@ -382,19 +368,15 @@ module Google
|
|
382
368
|
end
|
383
369
|
|
384
370
|
##
|
385
|
-
# @private
|
386
|
-
#
|
387
371
|
# Converts a Ruby Time object to a primitive time value in milliseconds.
|
388
372
|
#
|
389
373
|
# @return [Integer, nil] The primitive time value in milliseconds, or
|
390
374
|
# nil if the given argument is nil.
|
391
375
|
def self.time_to_millis time_obj
|
392
376
|
return nil unless time_obj
|
393
|
-
(time_obj.to_i * 1000) + (time_obj.nsec /
|
377
|
+
(time_obj.to_i * 1000) + (time_obj.nsec / 1_000_000)
|
394
378
|
end
|
395
379
|
end
|
396
|
-
|
397
|
-
# rubocop:enable Metrics/ModuleLength
|
398
380
|
end
|
399
381
|
end
|
400
382
|
end
|