Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
14 changes: 14 additions & 0 deletions google-cloud-bigquery/acceptance/bigquery/dataset_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@
dataset.default_expiration = nil
end

it "sets and gets the default_collation" do
new_default_collation = "und:ci"

dataset.default_collation = new_default_collation

fresh = bigquery.dataset dataset.dataset_id
_(fresh).wont_be :nil?
_(fresh).must_be_kind_of Google::Cloud::Bigquery::Dataset
_(fresh.dataset_id).must_equal dataset.dataset_id
_(fresh.default_collation).must_equal new_default_collation
ensure
dataset.default_collation = nil
end

it "should fail to set metadata with stale etag" do
fresh = bigquery.dataset dataset.dataset_id
_(fresh.etag).wont_be :nil?
Expand Down
25 changes: 25 additions & 0 deletions google-cloud-bigquery/acceptance/bigquery/table_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,18 @@
_(table.labels).must_equal new_labels
end

it "sets and gets the default_collation" do
new_default_collation = "und:ci"

table.default_collation = new_default_collation

fresh = dataset.table table.table_id
_(fresh).wont_be :nil?
_(fresh).must_be_kind_of Google::Cloud::Bigquery::Table
_(fresh.table_id).must_equal table.table_id
_(fresh.default_collation).must_equal new_default_collation
end

it "loads and reloads table with partial projection of table metadata" do
_(table.table_id).must_equal table_id # ensure table is created
%w[unspecified basic storage full].each do |view|
Expand Down Expand Up @@ -1186,6 +1198,19 @@
_(table.schema.fields.map(&:default_value_expression)).must_be :==, schema_fields_default.map(&:default_value_expression)
end

it "creates a table with a field with collation" do
t = nil
begin
t = dataset.create_table "#{prefix}_table_collation_test" do |schema|
schema.string "name", mode: :required, collation: "und:ci"
end
t.reload!
_(t.schema.field("name").collation).must_equal "und:ci"
ensure
t.delete if t
end
end

it "restores snapshot into a table" do
begin
result = table.clone target_clone_table
Expand Down
31 changes: 31 additions & 0 deletions google-cloud-bigquery/lib/google/cloud/bigquery/dataset.rb
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,37 @@ def description= new_description
patch_gapi! :description
end

##
# The default collation of the dataset.
#
# @return [String, nil] The default collation, or `nil` if not present or the object is a
# reference (see {#reference?}).
#
# @!group Attributes
#
def default_collation
return nil if reference?
ensure_full_data!
@gapi.default_collation
end

##
# Updates the default collation of the dataset.
#
# If the dataset is not a full resource representation (see
# {#resource_full?}), the full representation will be retrieved before
# the update to comply with ETag-based optimistic concurrency control.
#
# @param [String] new_default_collation The new default collation for the dataset.
#
# @!group Attributes
#
def default_collation= new_default_collation
reload! unless resource_full?
@gapi.update! default_collation: new_default_collation
patch_gapi! :default_collation
end

##
# The default lifetime of all tables in the dataset, in milliseconds.
#
Expand Down
9 changes: 6 additions & 3 deletions google-cloud-bigquery/lib/google/cloud/bigquery/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -318,13 +318,14 @@ def dump destination
# "[CURRENT_DATE(), DATE '2020-01-01'"]
#
def string name, description: nil, mode: :nullable, policy_tags: nil,
max_length: nil, default_value_expression: nil
max_length: nil, default_value_expression: nil, collation: nil
add_field name, :string,
description: description,
mode: mode,
policy_tags: policy_tags,
max_length: max_length,
default_value_expression: default_value_expression
default_value_expression: default_value_expression,
collation: collation
end

##
Expand Down Expand Up @@ -981,7 +982,8 @@ def add_field name,
max_length: nil,
precision: nil,
scale: nil,
default_value_expression: nil
default_value_expression: nil,
collation: nil
frozen_check!

new_gapi = Google::Apis::BigqueryV2::TableFieldSchema.new(
Expand All @@ -999,6 +1001,7 @@ def add_field name,
new_gapi.precision = precision if precision
new_gapi.scale = scale if scale
new_gapi.default_value_expression = default_value_expression if default_value_expression
new_gapi.collation = collation if collation
# Remove any existing field of this name
@gapi.fields ||= []
@gapi.fields.reject! { |f| f.name == new_gapi.name }
Expand Down
34 changes: 31 additions & 3 deletions google-cloud-bigquery/lib/google/cloud/bigquery/schema/field.rb
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,31 @@ def scale
@gapi.scale
end

##
# The collation of the field.
#
# Collation can be set only when the type of field is `STRING`.
# The following values are supported:
#
# * `und:ci`: undetermined locale, case insensitive.
# * (empty string): Default to case-sensitive behavior.
#
# @return [String, nil] The collation for the field, or `nil`.
#
def collation
@gapi.collation
end

##
# Updates the collation of the field.
#
# @param [String] new_collation The new collation. See {#collation}
# for supported values.
#
def collation= new_collation
@gapi.update! collation: new_collation
end

##
# Checks if the type of the field is `STRING`.
#
Expand Down Expand Up @@ -568,15 +593,16 @@ def field name
# @param [Integer] max_length The maximum UTF-8 length of strings
# allowed in the field.
#
def string name, description: nil, mode: :nullable, policy_tags: nil, max_length: nil
def string name, description: nil, mode: :nullable, policy_tags: nil, max_length: nil, collation: nil
record_check!

add_field name,
:string,
description: description,
mode: mode,
policy_tags: policy_tags,
max_length: max_length
max_length: max_length,
collation: collation
end

##
Expand Down Expand Up @@ -1029,7 +1055,8 @@ def add_field name,
policy_tags: nil,
max_length: nil,
precision: nil,
scale: nil
scale: nil,
collation: nil
frozen_check!

new_gapi = Google::Apis::BigqueryV2::TableFieldSchema.new(
Expand All @@ -1046,6 +1073,7 @@ def add_field name,
new_gapi.max_length = max_length if max_length
new_gapi.precision = precision if precision
new_gapi.scale = scale if scale
new_gapi.collation = collation if collation
# Remove any existing field of this name
@gapi.fields ||= []
@gapi.fields.reject! { |f| f.name == new_gapi.name }
Expand Down
42 changes: 39 additions & 3 deletions google-cloud-bigquery/lib/google/cloud/bigquery/table.rb
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,37 @@ def description= new_description
patch_gapi! :description
end

##
# The default collation of the table.
#
# @return [String, nil] The default collation, or `nil` if not present or the object is a
# reference (see {#reference?}).
#
# @!group Attributes
#
def default_collation
return nil if reference?
ensure_full_data!
@gapi.default_collation
end

##
# Updates the default collation of the table.
#
# If the table is not a full resource representation (see
# {#resource_full?}), the full representation will be retrieved before
# the update to comply with ETag-based optimistic concurrency control.
#
# @param [String] new_default_collation The new default collation for the table.
#
# @!group Attributes
#
def default_collation= new_default_collation
reload! unless resource_full?
@gapi.update! default_collation: new_default_collation
patch_gapi! :default_collation
end

##
# The number of bytes in the table.
#
Expand Down Expand Up @@ -3706,7 +3737,7 @@ def schema replace: false
# At most 1 policy tag is currently allowed.
# @param [Integer] max_length The maximum UTF-8 length of strings
# allowed in the field.
# @param default_value_expression [String] The default value of a field
# @param [String] default_value_expression The default value of a field
# using a SQL expression. It can only be set for top level fields (columns).
# Use a struct or array expression to specify default value for the entire struct or
# array. The valid SQL expressions are:
Expand All @@ -3722,6 +3753,11 @@ def schema replace: false
# `ST_GEOPOINT`
# - Struct or array composed with the above allowed functions, for example:
# "[CURRENT_DATE(), DATE '2020-01-01'"]
# @param [String] collation The collation of the field.
# Collation can be set only when the type of field is `STRING`.
# The following values are supported:
# - `und:ci`: undetermined locale, case insensitive.
# - (empty string): Default to case-sensitive behavior.
#
# @example
# require "google/cloud/bigquery"
Expand All @@ -3743,9 +3779,9 @@ def schema replace: false
#
# @!group Schema
def string name, description: nil, mode: :nullable, policy_tags: nil, max_length: nil,
default_value_expression: nil
default_value_expression: nil, collation: nil
schema.string name, description: description, mode: mode, policy_tags: policy_tags, max_length: max_length,
default_value_expression: default_value_expression
default_value_expression: default_value_expression, collation: collation
end

##
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,16 @@ def self.attr_test attr, val
attr_test :default_expiration, 999
attr_test :etag, "etag123456789"
attr_test :api_url, "http://googleapi/bigquery/v2/projects/test-project/datasets/my_dataset"

it "gets full data for default_collation" do
mock = Minitest::Mock.new
bigquery.service.mocked_service = mock
mock.expect :get_dataset, dataset_full_gapi, [project, dataset_id], access_policy_version: nil

_(dataset.default_collation).must_equal "und:ci"

# A second call to attribute does not make a second HTTP API call
_(dataset.default_collation).must_equal "und:ci"
mock.verify
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -134,4 +134,17 @@ def self.attr_test attr, val
attr_test :buffer_bytes, 2000
attr_test :buffer_rows, 200

it "gets full data for default_collation" do
mock = Minitest::Mock.new
mock.expect :get_table, table_full_gapi,
[table.project_id, table.dataset_id, table.table_id], **patch_table_args
table.service.mocked_service = mock

_(table.default_collation).must_equal "und:ci"

mock.verify

# A second call to attribute does not make a second HTTP API call
table.default_collation
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -421,4 +421,32 @@

_(table.schema.fields.map(&:default_value_expression)).must_be :==, [field_string_required_gapi_default.default_value_expression]
end

it "sets the collation on a string field" do
mock = Minitest::Mock.new
field_string_collation_gapi = Google::Apis::BigqueryV2::TableFieldSchema.new(
name: "first_name",
type: "STRING",
mode: "REQUIRED",
collation: "und:ci",
description: nil,
fields: []
)
new_schema_gapi = Google::Apis::BigqueryV2::TableSchema.new(
fields: [field_string_collation_gapi])
returned_table_gapi = table_gapi.dup
returned_table_gapi.schema = new_schema_gapi
patch_table_gapi = Google::Apis::BigqueryV2::Table.new schema: new_schema_gapi, etag: etag
mock.expect :patch_table, returned_table_gapi,
[table.project_id, table.dataset_id, table.table_id, patch_table_gapi], options: {header: {"If-Match" => etag}}
table.service.mocked_service = mock

table.schema replace: true do |schema|
schema.string "first_name", mode: :required, collation: "und:ci"
end

mock.verify

_(table.schema.field("first_name").collation).must_equal "und:ci"
end
end
2 changes: 2 additions & 0 deletions google-cloud-bigquery/test/helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ def random_dataset_hash id = nil, name = nil, description = nil, default_expirat
"friendlyName" => name,
"description" => description,
"defaultTableExpirationMs" => default_expiration,
"defaultCollation" => "und:ci",
"access" => [],
"creationTime" => time_millis,
"lastModifiedTime" => time_millis,
Expand Down Expand Up @@ -275,6 +276,7 @@ def random_table_hash dataset, id = nil, name = nil, description = nil, project_
"lastModifiedTime" => time_millis,
"location" => "US",
"labels" => { "foo" => "bar" },
"defaultCollation" => "und:ci",
"streamingBuffer" => {
"estimatedBytes" => "2000", # String per google/google-api-ruby-client
"estimatedRows" => "200", # String per google/google-api-ruby-client
Expand Down
Loading