Class: ActiveRecord::ConnectionAdapters::ClickHouseAdapter

Inherits:
AbstractAdapter
  • Object
show all
Includes:
ActiveRecord::ConnectionAdapters::ClickHouse::DatabaseStatements, ActiveRecord::ConnectionAdapters::ClickHouse::ErrorTranslation, ActiveRecord::ConnectionAdapters::ClickHouse::Quoting, ActiveRecord::ConnectionAdapters::ClickHouse::SchemaStatements
Defined in:
lib/active_record/connection_adapters/clickhouse_adapter.rb

Constant Summary collapse

ADAPTER_NAME =
"ClickHouse"
CONNECTION_PARAMETER_KEYS =
%i[
  host port hosts username password database ssl ssl_verify select_format
  connect_timeout read_timeout write_timeout read_only failover_cooldown
  mutations_sync compression join_use_nulls async_insert wait_for_async_insert
].freeze
NATIVE_DATABASE_TYPES =
{
  # No autoincrement exists; ids are generated client-side (decision #19),
  # so a Rails-style pk is just a plain Int64 column.
  primary_key: { name: "Int64" },
  string: { name: "String" },
  text: { name: "String" },
  integer: { name: "Int32", limit: 4 },
  bigint: { name: "Int64", limit: 8 },
  float: { name: "Float64" },
  decimal: { name: "Decimal" },
  datetime: { name: "DateTime64" },
  date: { name: "Date32" },
  boolean: { name: "Bool" },
  uuid: { name: "UUID" },
  json: { name: "JSON" }
}.freeze

Constants included from ActiveRecord::ConnectionAdapters::ClickHouse::ErrorTranslation

ActiveRecord::ConnectionAdapters::ClickHouse::ErrorTranslation::EXCEPTION_CLASS_BY_CODE, ActiveRecord::ConnectionAdapters::ClickHouse::ErrorTranslation::NULL_INSERT_MESSAGE, ActiveRecord::ConnectionAdapters::ClickHouse::ErrorTranslation::READONLY_CODE

Constants included from ActiveRecord::ConnectionAdapters::ClickHouse::SchemaStatements

ActiveRecord::ConnectionAdapters::ClickHouse::SchemaStatements::NON_TABLE_ENGINES

Constants included from ActiveRecord::ConnectionAdapters::ClickHouse::Quoting

ActiveRecord::ConnectionAdapters::ClickHouse::Quoting::COLUMN_NAME_MATCHER, ActiveRecord::ConnectionAdapters::ClickHouse::Quoting::COLUMN_NAME_WITH_ORDER_MATCHER, ActiveRecord::ConnectionAdapters::ClickHouse::Quoting::QUOTED_STRING_ESCAPES

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ActiveRecord::ConnectionAdapters::ClickHouse::SchemaStatements

#add_index, #add_projection, #attach_partition, #build_change_column_default_definition, #build_change_column_definition, #change_column, #change_column_comment, #change_column_default, #change_column_null, #change_table_comment, #create_dictionary, #create_join_table, #create_materialized_view, #create_table, #data_source_exists?, #data_sources, #detach_partition, #dictionaries, #drop_dictionary, #drop_materialized_view, #drop_partition, #drop_projection, #drop_table, #freeze_partition, #indexes, #internal_string_options_for_primary_key, #materialize_projection, #optimize_table, #partitions, #primary_keys, #reload_dictionary, #remove_column, #remove_index, #rename_column, #rename_index, #rename_table, #table_comment, #table_exists?, #table_options, #tables, #type_to_sql, #valid_column_definition_options, #valid_table_definition_options, #view_exists?, #views, #with_suppressed_primary_key_reporting

Methods included from ActiveRecord::ConnectionAdapters::ClickHouse::DatabaseStatements

#build_explain_clause, #create_savepoint, #default_sequence_name, #delete, #empty_insert_statement_value, #exec_rollback_to_savepoint, #explain, #high_precision_current_timestamp, #insert, #insert_fixtures_set, #insert_stream, #next_sequence_value, #prefetch_primary_key?, #release_savepoint, #return_value_after_insert?, #update, #with_request_settings, #write_query?

Methods included from ActiveRecord::ConnectionAdapters::ClickHouse::Quoting

#quote, #quote_string, #quoted_date, #quoted_false, #quoted_true, #unquoted_false, #unquoted_true

Constructor Details

#initializeClickHouseAdapter

Returns a new instance of ClickHouseAdapter.



39
40
41
42
43
44
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 39

def initialize(...)
  super

  @connection_parameters =
    { host: "localhost", port: 8123 }.merge(@config.slice(*CONNECTION_PARAMETER_KEYS)).compact
end

Class Method Details

.native_database_typesObject

Rails' class-level valid_type? reads this off the class.



105
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 105

def self.native_database_types = NATIVE_DATABASE_TYPES

.new_client(config) ⇒ Object



28
29
30
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 28

def new_client(config)
  ClickHouse::HTTPConnection.new(config)
end

Instance Method Details

#active?Boolean

Returns:

  • (Boolean)


46
47
48
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 46

def active?
  @lock.synchronize { @raw_connection&.ping } || false
end

#build_insert_sql(insert) ⇒ Object

:nodoc:



83
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 83

def build_insert_sql(insert) = "INSERT #{insert.into} #{insert.values_list}" # :nodoc:

#clusterObject

With cluster: configured, schema DDL is stamped ON CLUSTER so every replica runs it through the distributed DDL queue.



52
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 52

def cluster = @config[:cluster]

#create_schema_dumper(options) ⇒ Object

:nodoc:



121
122
123
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 121

def create_schema_dumper(options) # :nodoc:
  ClickHouse::SchemaDumper.create(self, options)
end

#disconnect!Object

Closing inside @lock keeps a queued query (which holds the lock for its whole HTTP round-trip) from starting on a socket that dies mid-read — the postgresql adapter's own disconnect! pattern.



61
62
63
64
65
66
67
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 61

def disconnect!
  @lock.synchronize do
    super
    @raw_connection&.close
    @raw_connection = nil
  end
end

#get_database_versionObject

:nodoc:



125
126
127
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 125

def get_database_version # :nodoc:
  Version.new(query_value("SELECT version()", "SCHEMA"))
end

#lookup_cast_type(sql_type) ⇒ Object

The abstract TYPE_MAP pattern-matches generic SQL names: ClickHouse-only shapes (Nullable(...), UUID, Bool, Map, ...) degrade to unfrozen Type::Value there, and Tuple(String, Int64) even false-matches Integer. Frozen so lookups stay Ractor-shareable like Rails' own type maps.



115
116
117
118
119
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 115

def lookup_cast_type(sql_type) # :nodoc:
  ClickHouse::Types.active_record_cast_type(sql_type).freeze
rescue ClickHouse::TypeParser::Error
  super
end

#native_database_typesObject



102
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 102

def native_database_types = NATIVE_DATABASE_TYPES

#on_cluster_clauseObject



54
55
56
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 54

def on_cluster_clause
  cluster ? " ON CLUSTER #{quote_table_name(cluster)}" : ""
end

#supports_datetime_with_precision?Boolean

DateTime64(P) is native precision; claiming it makes the DSL apply Rails' default microsecond precision (6) to datetime columns, like other adapters.

Returns:

  • (Boolean)


73
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 73

def supports_datetime_with_precision? = true

#supports_explain?Boolean

Returns:

  • (Boolean)


69
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 69

def supports_explain? = true

#supports_indexes_in_create?Boolean

Data-skipping indexes are INDEX clauses inside CREATE TABLE, not statements.

Returns:

  • (Boolean)


76
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 76

def supports_indexes_in_create? = true

#supports_insert_on_duplicate_skip?Boolean

insert_all implies skip-duplicates; without unique constraints nothing can conflict, so the semantics hold vacuously and the INSERT goes through plain. Upsert still raises upstream (supports_insert_on_duplicate_update? is false).

Returns:

  • (Boolean)


81
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 81

def supports_insert_on_duplicate_skip? = true

#valid_type?(_type) ⇒ Boolean

Column types the dumper can't map to AR symbols (Array, Map, Tuple, ...) are dumped verbatim, so every introspected type is valid by construction.

Returns:

  • (Boolean)


109
# File 'lib/active_record/connection_adapters/clickhouse_adapter.rb', line 109

def valid_type?(_type) = true