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