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
8 changes: 8 additions & 0 deletions acceptance/cases/tasks/database_tasks_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ def expected_schema_sql_on_emulator
col_date DATE,
col_timestamp TIMESTAMP,
col_json JSON,
col_uuid UUID,
col_array_string ARRAY<STRING(MAX)>,
col_array_int64 ARRAY<INT64>,
col_array_float64 ARRAY<FLOAT64>,
Expand All @@ -138,6 +139,7 @@ def expected_schema_sql_on_emulator
col_array_date ARRAY<DATE>,
col_array_timestamp ARRAY<TIMESTAMP>,
col_array_json ARRAY<JSON>,
col_array_uuid ARRAY<UUID>,
) PRIMARY KEY(id);
CREATE TABLE firms (
id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
Expand Down Expand Up @@ -287,6 +289,7 @@ def expected_schema_sql_on_emulator_7_1
col_date DATE,
col_timestamp TIMESTAMP,
col_json JSON,
col_uuid UUID,
col_array_string ARRAY<STRING(MAX)>,
col_array_int64 ARRAY<INT64>,
col_array_float64 ARRAY<FLOAT64>,
Expand All @@ -296,6 +299,7 @@ def expected_schema_sql_on_emulator_7_1
col_array_date ARRAY<DATE>,
col_array_timestamp ARRAY<TIMESTAMP>,
col_array_json ARRAY<JSON>,
col_array_uuid ARRAY<UUID>,
) PRIMARY KEY(id);
CREATE TABLE firms (
id INT64 NOT NULL GENERATED BY DEFAULT AS IDENTITY (BIT_REVERSED_POSITIVE),
Expand Down Expand Up @@ -463,6 +467,7 @@ def expected_schema_sql_on_production
col_date DATE,
col_timestamp TIMESTAMP,
col_json JSON,
col_uuid UUID,
col_array_string ARRAY<STRING(MAX)>,
col_array_int64 ARRAY<INT64>,
col_array_float64 ARRAY<FLOAT64>,
Expand All @@ -472,6 +477,7 @@ def expected_schema_sql_on_production
col_array_date ARRAY<DATE>,
col_array_timestamp ARRAY<TIMESTAMP>,
col_array_json ARRAY<JSON>,
col_array_uuid ARRAY<UUID>,
) PRIMARY KEY(id);
CREATE TABLE ar_internal_metadata (
key STRING(MAX) NOT NULL,
Expand Down Expand Up @@ -624,6 +630,7 @@ def expected_schema_sql_on_production_7_1
col_date DATE,
col_timestamp TIMESTAMP,
col_json JSON,
col_uuid UUID,
col_array_string ARRAY<STRING(MAX)>,
col_array_int64 ARRAY<INT64>,
col_array_float64 ARRAY<FLOAT64>,
Expand All @@ -633,6 +640,7 @@ def expected_schema_sql_on_production_7_1
col_array_date ARRAY<DATE>,
col_array_timestamp ARRAY<TIMESTAMP>,
col_array_json ARRAY<JSON>,
col_array_uuid ARRAY<UUID>,
) PRIMARY KEY(id);
CREATE TABLE ar_internal_metadata (
key STRING(MAX) NOT NULL,
Expand Down
19 changes: 15 additions & 4 deletions acceptance/cases/type/all_types_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ def create_test_record
AllTypes.create col_string: "string", col_int64: 100, col_float64: 3.14, col_numeric: 6.626, col_bool: true,
col_bytes: StringIO.new("bytes"), col_date: ::Date.new(2021, 6, 23),
col_timestamp: ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"),
col_json: { kind: "user_renamed", change: %w[jack john]},
col_json: { kind: "user_renamed", change: %w[jack john] },
col_uuid: "3840ba25-55df-4cb7-a210-1fe37278954f",
col_array_string: ["string1", nil, "string2"],
col_array_int64: [100, nil, 200, "300"],
col_array_float64: [3.14, nil, 2.0/3.0, "3.14"],
Expand All @@ -42,7 +43,8 @@ def create_test_record
::Time.new(2021, 6, 24, 17, 8, 21, "+02:00"), "2021-06-25 17:08:21 +02:00"],
col_array_json: [{ kind: "user_renamed", change: %w[jack john]}, nil, \
{ kind: "user_renamed", change: %w[alice meredith]},
"{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"]
"{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"],
col_array_uuid: ["e986c19c-9bf3-44f8-851d-710ad3d0067b", nil, "a02f50b6-2860-48dc-acd6-49b42abc3094"]
end

def test_create_record
Expand All @@ -67,6 +69,7 @@ def test_create_record
assert_equal ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00").utc, record.col_timestamp.utc
assert_equal ({"kind" => "user_renamed", "change" => %w[jack john]}),
record.col_json
assert_equal "3840ba25-55df-4cb7-a210-1fe37278954f", record.col_uuid

assert_equal ["string1", nil, "string2"], record.col_array_string
assert_equal [100, nil, 200, 300], record.col_array_int64
Expand All @@ -85,6 +88,7 @@ def test_create_record
{"kind" => "user_renamed", "change" => %w[alice meredith]}, \
"{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"],
record.col_array_json
assert_equal ["e986c19c-9bf3-44f8-851d-710ad3d0067b", nil, "a02f50b6-2860-48dc-acd6-49b42abc3094"], record.col_array_uuid
end
end

Expand All @@ -100,6 +104,7 @@ def test_update_record
col_date: ::Date.new(2021, 6, 28),
col_timestamp: ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00"),
col_json: { kind: "user_created", change: %w[jack alice]},
col_uuid: "b493579f-f4f6-41f6-a520-8373ecf1cde4",
col_array_string: ["new string 1", "new string 2"],
col_array_int64: [300, 200, 100],
col_array_float64: [1.1, 2.2, 3.3],
Expand All @@ -108,7 +113,8 @@ def test_update_record
col_array_bytes: [StringIO.new("new bytes 1"), StringIO.new("new bytes 2")],
col_array_date: [::Date.new(2021, 6, 28)],
col_array_timestamp: [::Time.utc(2020, 12, 31, 0, 0, 0)],
col_array_json: [{ kind: "user_created", change: %w[jack alice]}]
col_array_json: [{ kind: "user_created", change: %w[jack alice]}],
col_array_uuid: ["a664b1eb-4dc7-4795-9ed8-28fab6644cea", nil, "1c794d81-bc6d-4771-9c92-a920d28a7aaa"]
end

# Verify that the record was updated.
Expand All @@ -123,6 +129,7 @@ def test_update_record
assert_equal ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00").utc, record.col_timestamp.utc
assert_equal ({"kind" => "user_created", "change" => %w[jack alice]}),
record.col_json
assert_equal "b493579f-f4f6-41f6-a520-8373ecf1cde4", record.col_uuid

assert_equal ["new string 1", "new string 2"], record.col_array_string
assert_equal [300, 200, 100], record.col_array_int64
Expand All @@ -135,6 +142,8 @@ def test_update_record
assert_equal [::Time.utc(2020, 12, 31, 0, 0, 0)], record.col_array_timestamp.map(&:utc)
assert_equal [{"kind" => "user_created", "change" => %w[jack alice]}],
record.col_array_json
assert_equal ["a664b1eb-4dc7-4795-9ed8-28fab6644cea", nil, "1c794d81-bc6d-4771-9c92-a920d28a7aaa"],
record.col_array_uuid
end
end

Expand All @@ -151,7 +160,8 @@ def test_create_empty_arrays
col_array_bytes: [],
col_array_date: [],
col_array_timestamp: [],
col_array_json: []
col_array_json: [],
col_array_uuid: []
end

record = AllTypes.find record.id
Expand All @@ -164,6 +174,7 @@ def test_create_empty_arrays
assert_equal [], record.col_array_date
assert_equal [], record.col_array_timestamp
assert_equal [], record.col_array_json
assert_equal [], record.col_array_uuid
end
end
end
Expand Down
2 changes: 2 additions & 0 deletions acceptance/schema/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def create_tables_in_test_schema
t.column :col_date, :date
t.column :col_timestamp, :datetime
t.column :col_json, :json
t.column :col_uuid, :uuid

t.column :col_array_string, :string, array: true
t.column :col_array_int64, :bigint, array: true
Expand All @@ -34,6 +35,7 @@ def create_tables_in_test_schema
t.column :col_array_date, :date, array: true
t.column :col_array_timestamp, :datetime, array: true
t.column :col_array_json, :json, array: true
t.column :col_array_uuid, :uuid, array: true
end

create_table :firms do |t|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@
date: { name: "DATE" },
binary: { name: "BYTES", limit: "MAX" },
boolean: { name: "BOOL" },
json: { name: "JSON" }
json: { name: "JSON" },
uuid: { name: "UUID" }
}.freeze
3 changes: 3 additions & 0 deletions lib/active_record/connection_adapters/spanner_adapter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
require "active_record/type/spanner/bytes"
require "active_record/type/spanner/spanner_active_record_converter"
require "active_record/type/spanner/time"
require "active_record/type/spanner/uuid"
require "arel/visitors/spanner"
require "activerecord_spanner_adapter/base"
require "activerecord_spanner_adapter/connection"
Expand Down Expand Up @@ -250,6 +251,7 @@ def initialize_type_map m = type_map
register_class_with_limit m, %r{^STRING}i, Type::String
m.register_type "TIMESTAMP", ActiveRecord::Type::Spanner::Time.new
m.register_type "JSON", ActiveRecord::Type::Json.new
m.register_type "UUID", ActiveRecord::Type::Spanner::Uuid.new

register_array_types m
end
Expand All @@ -265,6 +267,7 @@ def register_array_types m
m.register_type %r{^ARRAY<STRING\((MAX|d+)\)>}i, Type::Spanner::Array.new(Type::String.new)
m.register_type %r{^ARRAY<TIMESTAMP>}i, Type::Spanner::Array.new(ActiveRecord::Type::Spanner::Time.new)
m.register_type %r{^ARRAY<JSON>}i, Type::Spanner::Array.new(ActiveRecord::Type::Json.new)
m.register_type %r{^ARRAY<UUID>}i, Type::Spanner::Array.new(ActiveRecord::Type::Spanner::Uuid.new)
end

def extract_limit sql_type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ def self.convert_active_model_type_to_spanner type # rubocop:disable Metrics/Cyc
when ActiveModel::Type::DateTime, ActiveModel::Type::Time, ActiveRecord::Type::Spanner::Time then :TIMESTAMP
when ActiveModel::Type::Date then :DATE
when ActiveRecord::Type::Json then :JSON
when ActiveRecord::Type::Spanner::Uuid then :UUID
when ActiveRecord::Type::Spanner::Array then [convert_active_model_type_to_spanner(type.element_type)]
end
end
Expand Down
19 changes: 19 additions & 0 deletions lib/active_record/type/spanner/uuid.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
# Copyright 2026 Google LLC
#
# Use of this source code is governed by an MIT-style
# license that can be found in the LICENSE file or at
# https://opensource.org/licenses/MIT.

# frozen_string_literal: true

module ActiveRecord
module Type
module Spanner
class Uuid < ActiveModel::Type::Value
def type
:uuid
end
end
end
end
end
40 changes: 31 additions & 9 deletions test/activerecord_spanner_mock_server/model_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -537,6 +537,17 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "NO"),
)
result_set.rows.push row
row = ListValue.new
row.values.push(
Value.new(string_value: "col_uuid"),
Value.new(string_value: "UUID"),
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "11"),
Value.new(string_value: "NO"),
)
result_set.rows.push row

row = ListValue.new
row.values.push(
Expand All @@ -545,7 +556,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "11"),
Value.new(string_value: "12"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -556,7 +567,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "12"),
Value.new(string_value: "13"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -567,7 +578,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "13"),
Value.new(string_value: "14"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -578,7 +589,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "14"),
Value.new(string_value: "15"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -589,7 +600,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "15"),
Value.new(string_value: "16"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -600,7 +611,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "16"),
Value.new(string_value: "17"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -611,7 +622,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "17"),
Value.new(string_value: "18"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -622,7 +633,7 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "18"),
Value.new(string_value: "19"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
Expand All @@ -633,10 +644,21 @@ def self.register_all_types_columns_result spanner_mock_server
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "19"),
Value.new(string_value: "20"),
Value.new(string_value: "NO"),
)
result_set.rows.push row
row = ListValue.new
row.values.push(
Value.new(string_value: "col_array_uuid"),
Value.new(string_value: "ARRAY<UUID>"),
Value.new(string_value: "YES"),
Value.new(null_value: "NULL_VALUE"),
Value.new(null_value: "NULL_VALUE"),
Value.new(string_value: "21"),
Value.new(string_value: "NO"),
)
result_set.rows.push row

spanner_mock_server.put_statement_result sql, StatementResult.new(result_set)
end
Expand Down
Loading
Loading