diff --git a/.docker/clickhouse/users.xml b/.docker/clickhouse/users.xml index 61188536..365da099 100644 --- a/.docker/clickhouse/users.xml +++ b/.docker/clickhouse/users.xml @@ -4,6 +4,7 @@ random + 1 diff --git a/README.md b/README.md index 176e6eba..793f536c 100644 --- a/README.md +++ b/README.md @@ -199,6 +199,9 @@ false`. The default integer is `UInt32` | UInt64 | 0 to 18446744073709551615 | 5,6,7,8 | | UInt256 | 0 to ... | 8+ | | Array | ... | ... | +| Json* | ... | ... | + +* **Note**: using the JSON type requires that `allow_experimental_object_type = 1` is [set in ClickHouse settings](https://clickhouse.com/docs/en/sql-reference/data-types/json). Example: diff --git a/lib/active_record/connection_adapters/clickhouse_adapter.rb b/lib/active_record/connection_adapters/clickhouse_adapter.rb index 9d6ee4d8..91925a65 100644 --- a/lib/active_record/connection_adapters/clickhouse_adapter.rb +++ b/lib/active_record/connection_adapters/clickhouse_adapter.rb @@ -100,6 +100,8 @@ class ClickhouseAdapter < AbstractAdapter boolean: { name: 'Bool' }, uuid: { name: 'UUID' }, + json: { name: 'Object(\'json\')' }, + enum8: { name: 'Enum8' }, enum16: { name: 'Enum16' }, @@ -207,6 +209,7 @@ def initialize_type_map(m) # :nodoc: m.register_type %r(bool)i, ActiveModel::Type::Boolean.new m.register_type %r{uuid}i, Clickhouse::OID::Uuid.new + m.register_type %r{Object\('json'\)}i, Type::Json.new # register_class_with_limit m, %r(Array), Clickhouse::OID::Array m.register_type(%r(Array)) do |sql_type| Clickhouse::OID::Array.new(sql_type) diff --git a/spec/fixtures/migrations/add_sample_data/1_create_sample_table.rb b/spec/fixtures/migrations/add_sample_data/1_create_sample_table.rb index 0ae71253..73ed898b 100644 --- a/spec/fixtures/migrations/add_sample_data/1_create_sample_table.rb +++ b/spec/fixtures/migrations/add_sample_data/1_create_sample_table.rb @@ -12,6 +12,7 @@ def up t.string :byte_array, null: true t.uuid :relation_uuid t.decimal :decimal_value, precision: 38, scale: 16, null: true + t.json :json_value, null: false, default: {} end end end diff --git a/spec/single/model_spec.rb b/spec/single/model_spec.rb index e9e46b54..c07d04c0 100644 --- a/spec/single/model_spec.rb +++ b/spec/single/model_spec.rb @@ -154,6 +154,28 @@ class ModelPk < ActiveRecord::Base end end + describe 'JSON column type' do + let(:json) { { 'key' => 'value' } } + let!(:record1) { Model.create!(event_name: 'some event', json_value: json) } + + it 'is mapped to :json' do + type = Model.columns_hash['json_value'].type + expect(type).to eq(:json) + end + + it 'keeps JSON value' do + expect(Model.first.json_value).to eq(json) + end + + context 'when the JSON column is complex' do + let(:json) { { 'key' => { 'nested_key' => 'value', 'another_key' => ['something'] } } } + + it 'keeps JSON value' do + expect(Model.first.json_value).to eq(json) + end + end + end + describe 'UUID column type' do let(:random_uuid) { SecureRandom.uuid } let!(:record1) do