Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a5e3de5
wip
blowmage Dec 6, 2019
31cdc69
wip2
blowmage Jan 7, 2020
785f066
Add Routine acceptance test
quartzmo Jan 10, 2020
f1f355e
Add create_routine
quartzmo Jan 11, 2020
7b4fb51
Add Routine::List and #update_routine
quartzmo Jan 21, 2020
f3ff1f9
Add Routine unit tests
quartzmo Jan 23, 2020
69e20cd
Add Routine resource methods
quartzmo Jan 28, 2020
4e100f1
Update Routine and tests
quartzmo Jan 29, 2020
0bed1f9
Completed Routine unit tests and doctest
quartzmo Jan 30, 2020
20654f8
Make Argument immutable
quartzmo Jan 30, 2020
292c610
Make StandardSql types immutable
quartzmo Feb 2, 2020
ee509b8
Finish update of StandardSql types
quartzmo Feb 4, 2020
6c6d86e
Add Routine#update
quartzmo Feb 4, 2020
61e19dd
Update docs
quartzmo Feb 4, 2020
6b58ddb
Rename Routine#type to Routine#routine_type
quartzmo Feb 4, 2020
ea0b4d4
Update Routine docs
quartzmo Feb 5, 2020
f96325d
Complete docs for Argument and StandardSql
quartzmo Feb 6, 2020
3278898
Add filter to Dataset#routines
quartzmo Feb 7, 2020
5f3618f
Add Data#ddl_target_routine and QueryJob#ddl_target_routine
quartzmo Feb 7, 2020
d20597e
Update all test fixtures to squiggly heredoc
quartzmo Feb 11, 2020
24bff50
Update force param default in all #exists? methods to false
quartzmo Feb 11, 2020
3b8a9a5
Update Routine docs return types for reference state
quartzmo Feb 11, 2020
5fe33e7
Update options = {} to keyword arguments or **kwargs
quartzmo Feb 11, 2020
ab68c7f
Override lifecycle methods in Updater subclasses to return not implem…
quartzmo Feb 11, 2020
887cb3a
Restore CopyJob.from_options and ExtractJob.from_options from **kwarg…
quartzmo Feb 11, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions google-cloud-bigquery/acceptance/bigquery/bigquery_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@
# job.statement_type.must_equal "SELECT"
job.ddl_operation_performed.must_be :nil?
job.ddl_target_table.must_be :nil?
job.ddl_target_routine.must_be :nil?
end

it "should run a query job with dryrun flag" do
Expand Down
2 changes: 1 addition & 1 deletion google-cloud-bigquery/acceptance/bigquery/model_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
end
let(:model_id) { "model_#{SecureRandom.hex(4)}" }
let :model_sql do
model_sql = <<-MODEL_SQL
model_sql = <<~MODEL_SQL
CREATE MODEL #{dataset.dataset_id}.#{model_id}
OPTIONS (
model_type='linear_reg',
Expand Down
230 changes: 230 additions & 0 deletions google-cloud-bigquery/acceptance/bigquery/routine_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
# Copyright 2020 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

require "bigquery_helper"

describe Google::Cloud::Bigquery, :bigquery do
let(:dataset_id) { "#{prefix}_dataset" }
let(:dataset) do
d = bigquery.dataset dataset_id
if d.nil?
d = bigquery.create_dataset dataset_id
end
d
end
let(:routine_id) { "routine_#{SecureRandom.hex(4)}" }
let :routine_sql do
routine_sql = <<~SQL
CREATE FUNCTION `#{routine_id}`(
arr ARRAY<STRUCT<name STRING, val INT64>>
) AS (
(SELECT SUM(IF(elem.name = "foo",elem.val,null)) FROM UNNEST(arr) AS elem)
)
SQL
end

it "can create from SQL, list, read, update, and delete a routine" do
# create from sql
job = dataset.query_job routine_sql
job.wait_until_done!
job.wont_be :failed?
job.ddl_operation_performed.must_equal "CREATE"
routine = job.ddl_target_routine
routine.must_be_kind_of Google::Cloud::Bigquery::Routine
routine.reference?.must_equal true
routine.project_id.must_equal bigquery.project
routine.dataset_id.must_equal dataset.dataset_id
routine.routine_id.must_equal routine_id

# list
dataset.routines.all.map(&:routine_id).must_include routine_id

# list with filter
dataset.routines(filter: "routineType:SCALAR_FUNCTION").all.map(&:routine_id).must_include routine_id

# list with filter
dataset.routines(filter: "routineType:PROCEDURE").all.map(&:routine_id).wont_include routine_id

# get
routine = dataset.routine routine_id
routine.must_be_kind_of Google::Cloud::Bigquery::Routine
routine.project_id.must_equal bigquery.project
routine.dataset_id.must_equal dataset.dataset_id
routine.routine_id.must_equal routine_id

routine.description.must_be :nil?
routine.routine_type.must_equal "SCALAR_FUNCTION"
routine.language.must_equal "SQL"
routine.body.must_equal "(SELECT SUM(IF(elem.name = \"foo\",elem.val,null)) FROM UNNEST(arr) AS elem)"

arguments = routine.arguments
arguments.must_be_kind_of Array
arguments.size.must_equal 1

argument = arguments.first
argument.must_be_kind_of Google::Cloud::Bigquery::Argument
argument.argument_kind.must_be :nil?
argument.fixed_type?.must_equal true
argument.any_type?.must_equal false
argument.mode.must_be :nil?
argument.in?.must_equal false
argument.out?.must_equal false
argument.inout?.must_equal false
argument.name.must_equal "arr"

data_type = argument.data_type
data_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
data_type.type_kind.must_equal "ARRAY"
data_type.struct_type.must_be :nil?
data_type.array_element_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
data_type.array_element_type.type_kind.must_equal "STRUCT"
data_type.array_element_type.struct_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::StructType

struct_fields = data_type.array_element_type.struct_type.fields
struct_fields.must_be_kind_of Array
struct_fields.size.must_equal 2
struct_fields[0].must_be_kind_of Google::Cloud::Bigquery::StandardSql::Field
struct_fields[0].name.must_equal "name"
struct_fields[0].type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
struct_fields[0].type.type_kind.must_equal "STRING"
struct_fields[1].must_be_kind_of Google::Cloud::Bigquery::StandardSql::Field
struct_fields[1].name.must_equal "val"
struct_fields[1].type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
struct_fields[1].type.type_kind.must_equal "INT64"

# update
new_description = "Routine was updated #{Time.now}"
routine.description = new_description
routine.refresh!
routine.description.must_equal new_description

# delete
routine.delete.must_equal true

dataset.routine(routine_id).must_be_nil
end

it "can create, update and delete a routine" do
# create
routine = dataset.create_routine routine_id do |r|
r.routine_type = "SCALAR_FUNCTION"
r.language = :SQL
r.arguments = [
Google::Cloud::Bigquery::Argument.new(name: "x", data_type: "INT64")
]
r.body = "x * 3"
r.description = "my description"
end

routine.must_be_kind_of Google::Cloud::Bigquery::Routine
routine.project_id.must_equal bigquery.project
routine.dataset_id.must_equal dataset.dataset_id
routine.routine_id.must_equal routine_id

routine.description.must_equal "my description"
routine.routine_type.must_equal "SCALAR_FUNCTION"
routine.language.must_equal "SQL"
routine.body.must_equal "x * 3"

arguments = routine.arguments
arguments.must_be_kind_of Array
arguments.size.must_equal 1

argument = arguments.first
argument.must_be_kind_of Google::Cloud::Bigquery::Argument
argument.argument_kind.must_be :nil?
argument.mode.must_be :nil?
argument.name.must_equal "x"

data_type = argument.data_type
data_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
data_type.type_kind.must_equal "INT64"
data_type.array_element_type.must_be :nil?
data_type.struct_type.must_be :nil?

# update
new_body = "(SELECT SUM(IF(elem.name = \"foo\",elem.val,null)) FROM UNNEST(arr) AS elem)"
new_arguments = [
Google::Cloud::Bigquery::Argument.new(
name: "arr",
argument_kind: "FIXED_TYPE",
data_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
type_kind: "ARRAY",
array_element_type: Google::Cloud::Bigquery::StandardSql::DataType.new(
type_kind: "STRUCT",
struct_type: Google::Cloud::Bigquery::StandardSql::StructType.new(
fields: [
Google::Cloud::Bigquery::StandardSql::Field.new(
name: "name",
type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "STRING")
),
Google::Cloud::Bigquery::StandardSql::Field.new(
name: "val",
type: Google::Cloud::Bigquery::StandardSql::DataType.new(type_kind: "INT64")
)
]
)
)
)
)
]

routine.update do |r|
r.body = new_body
r.arguments = new_arguments
end

routine.body.must_equal new_body

arguments = routine.arguments
arguments.must_be_kind_of Array
arguments.size.must_equal 1

argument = arguments.first
argument.must_be_kind_of Google::Cloud::Bigquery::Argument
argument.argument_kind.must_equal "FIXED_TYPE"
argument.mode.must_be :nil?
argument.name.must_equal "arr"

data_type = argument.data_type
data_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
data_type.type_kind.must_equal "ARRAY"
data_type.struct_type.must_be :nil?
data_type.array_element_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
data_type.array_element_type.type_kind.must_equal "STRUCT"
data_type.array_element_type.struct_type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::StructType

struct_fields = data_type.array_element_type.struct_type.fields
struct_fields.must_be_kind_of Array
struct_fields.size.must_equal 2
struct_fields[0].must_be_kind_of Google::Cloud::Bigquery::StandardSql::Field
struct_fields[0].name.must_equal "name"
struct_fields[0].type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
struct_fields[0].type.type_kind.must_equal "STRING"
struct_fields[1].must_be_kind_of Google::Cloud::Bigquery::StandardSql::Field
struct_fields[1].name.must_equal "val"
struct_fields[1].type.must_be_kind_of Google::Cloud::Bigquery::StandardSql::DataType
struct_fields[1].type.type_kind.must_equal "INT64"

# get
routine.reload!
routine.body.must_equal new_body
routine.arguments.first.data_type.array_element_type.struct_type.fields.last.type.type_kind.must_equal "INT64"

# delete
routine.delete.must_equal true

dataset.routine(routine_id).must_be_nil
end
end
16 changes: 16 additions & 0 deletions google-cloud-bigquery/acceptance/bigquery/standard_query_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,20 @@
rows.count.must_equal 1
rows.first[:value].must_equal ["foo", "bar", "baz"]
end

it "queries a struct with no names" do
rows = bigquery.query "SELECT STRUCT(1, 'abc', 3.14) AS value", standard_sql: true

rows.class.must_equal Google::Cloud::Bigquery::Data
rows.count.must_equal 1
rows.first[:value].must_equal({ _field_1: 1, _field_2: "abc", _field_3: 3.14 })
end

it "queries a struct with duplicate names" do
rows = bigquery.query "SELECT STRUCT(1 AS x, 'abc' AS x, 3.14 AS x) AS value", standard_sql: true

rows.class.must_equal Google::Cloud::Bigquery::Data
rows.count.must_equal 1
rows.first[:value].must_equal({ x: 1, _field_2: "abc", _field_3: 3.14 })
end
end
Loading