clickhouse-ruby 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +80 -0
- data/LICENSE +21 -0
- data/README.md +251 -0
- data/lib/clickhouse_ruby/active_record/arel_visitor.rb +468 -0
- data/lib/clickhouse_ruby/active_record/connection_adapter.rb +723 -0
- data/lib/clickhouse_ruby/active_record/railtie.rb +192 -0
- data/lib/clickhouse_ruby/active_record/schema_statements.rb +693 -0
- data/lib/clickhouse_ruby/active_record.rb +121 -0
- data/lib/clickhouse_ruby/client.rb +471 -0
- data/lib/clickhouse_ruby/configuration.rb +145 -0
- data/lib/clickhouse_ruby/connection.rb +328 -0
- data/lib/clickhouse_ruby/connection_pool.rb +301 -0
- data/lib/clickhouse_ruby/errors.rb +144 -0
- data/lib/clickhouse_ruby/result.rb +189 -0
- data/lib/clickhouse_ruby/types/array.rb +183 -0
- data/lib/clickhouse_ruby/types/base.rb +77 -0
- data/lib/clickhouse_ruby/types/boolean.rb +68 -0
- data/lib/clickhouse_ruby/types/date_time.rb +163 -0
- data/lib/clickhouse_ruby/types/float.rb +115 -0
- data/lib/clickhouse_ruby/types/integer.rb +157 -0
- data/lib/clickhouse_ruby/types/low_cardinality.rb +58 -0
- data/lib/clickhouse_ruby/types/map.rb +249 -0
- data/lib/clickhouse_ruby/types/nullable.rb +73 -0
- data/lib/clickhouse_ruby/types/parser.rb +244 -0
- data/lib/clickhouse_ruby/types/registry.rb +148 -0
- data/lib/clickhouse_ruby/types/string.rb +83 -0
- data/lib/clickhouse_ruby/types/tuple.rb +206 -0
- data/lib/clickhouse_ruby/types/uuid.rb +84 -0
- data/lib/clickhouse_ruby/types.rb +69 -0
- data/lib/clickhouse_ruby/version.rb +5 -0
- data/lib/clickhouse_ruby.rb +101 -0
- metadata +150 -0
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails/railtie'
|
|
4
|
+
|
|
5
|
+
module ClickhouseRuby
|
|
6
|
+
module ActiveRecord
|
|
7
|
+
# Rails integration for ClickhouseRuby ClickHouse adapter
|
|
8
|
+
#
|
|
9
|
+
# This Railtie hooks into Rails to:
|
|
10
|
+
# - Register the ClickHouse adapter with ActiveRecord
|
|
11
|
+
# - Configure default settings for Rails environments
|
|
12
|
+
# - Set up logging integration
|
|
13
|
+
#
|
|
14
|
+
# @example database.yml
|
|
15
|
+
# development:
|
|
16
|
+
# adapter: clickhouse
|
|
17
|
+
# host: localhost
|
|
18
|
+
# port: 8123
|
|
19
|
+
# database: myapp_development
|
|
20
|
+
#
|
|
21
|
+
# production:
|
|
22
|
+
# adapter: clickhouse
|
|
23
|
+
# host: <%= ENV['CLICKHOUSE_HOST'] %>
|
|
24
|
+
# port: 8443
|
|
25
|
+
# database: myapp_production
|
|
26
|
+
# ssl: true
|
|
27
|
+
# ssl_verify: true
|
|
28
|
+
#
|
|
29
|
+
class Railtie < ::Rails::Railtie
|
|
30
|
+
# Initialize the adapter when ActiveRecord loads
|
|
31
|
+
initializer 'chruby.initialize_active_record' do
|
|
32
|
+
# Register the adapter
|
|
33
|
+
::ActiveSupport.on_load(:active_record) do
|
|
34
|
+
require_relative 'connection_adapter'
|
|
35
|
+
|
|
36
|
+
# Log that the adapter is being registered
|
|
37
|
+
if defined?(Rails.logger) && Rails.logger
|
|
38
|
+
Rails.logger.info '[ClickhouseRuby] ClickHouse adapter registered with ActiveRecord'
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# Configure database tasks (db:create, db:drop, etc.)
|
|
44
|
+
initializer 'chruby.configure_database_tasks' do
|
|
45
|
+
::ActiveSupport.on_load(:active_record) do
|
|
46
|
+
# Register ClickHouse-specific database tasks
|
|
47
|
+
if defined?(::ActiveRecord::Tasks::DatabaseTasks)
|
|
48
|
+
::ActiveRecord::Tasks::DatabaseTasks.register_task(/clickhouse/, 'ClickhouseRuby::ActiveRecord::DatabaseTasks')
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Configure the connection pool for Rails
|
|
54
|
+
config.after_initialize do
|
|
55
|
+
# Set up connection pool based on Rails configuration
|
|
56
|
+
if defined?(ActiveRecord::Base)
|
|
57
|
+
# Ensure connections are properly managed
|
|
58
|
+
ActiveRecord::Base.connection_pool.disconnect! rescue nil
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# Add generators namespace for Rails generators
|
|
63
|
+
generators do
|
|
64
|
+
require_relative 'generators/migration_generator' if defined?(::Rails::Generators)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Log deprecation warnings for known issues
|
|
68
|
+
initializer 'chruby.log_deprecation_warnings' do
|
|
69
|
+
::ActiveSupport.on_load(:active_record) do
|
|
70
|
+
# Warn about features that don't work with ClickHouse
|
|
71
|
+
if defined?(Rails.logger) && Rails.logger
|
|
72
|
+
Rails.logger.debug '[ClickhouseRuby] Note: ClickHouse does not support transactions, savepoints, or foreign keys'
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Database tasks for Rails (db:create, db:drop, etc.)
|
|
79
|
+
class DatabaseTasks
|
|
80
|
+
delegate :configuration_hash, :root, to: ::ActiveRecord::Tasks::DatabaseTasks
|
|
81
|
+
|
|
82
|
+
def self.using_database_configurations?
|
|
83
|
+
true
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Create a ClickHouse database
|
|
87
|
+
#
|
|
88
|
+
# @param master_configuration_hash [Hash] database configuration
|
|
89
|
+
def create(master_configuration_hash = configuration_hash)
|
|
90
|
+
config = master_configuration_hash.symbolize_keys
|
|
91
|
+
database = config[:database]
|
|
92
|
+
|
|
93
|
+
return if database.nil? || database.empty?
|
|
94
|
+
|
|
95
|
+
# Connect without database to create it
|
|
96
|
+
temp_config = config.dup
|
|
97
|
+
temp_config[:database] = 'default'
|
|
98
|
+
|
|
99
|
+
adapter = ConnectionAdapter.new(nil, nil, nil, temp_config)
|
|
100
|
+
adapter.connect
|
|
101
|
+
adapter.create_database(database, if_not_exists: true)
|
|
102
|
+
adapter.disconnect!
|
|
103
|
+
|
|
104
|
+
puts "Created database '#{database}'"
|
|
105
|
+
rescue ClickhouseRuby::Error => e
|
|
106
|
+
raise "Failed to create database '#{database}': #{e.message}"
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
# Drop a ClickHouse database
|
|
110
|
+
#
|
|
111
|
+
# @param master_configuration_hash [Hash] database configuration
|
|
112
|
+
def drop(master_configuration_hash = configuration_hash)
|
|
113
|
+
config = master_configuration_hash.symbolize_keys
|
|
114
|
+
database = config[:database]
|
|
115
|
+
|
|
116
|
+
return if database.nil? || database.empty?
|
|
117
|
+
|
|
118
|
+
# Connect without database to drop it
|
|
119
|
+
temp_config = config.dup
|
|
120
|
+
temp_config[:database] = 'default'
|
|
121
|
+
|
|
122
|
+
adapter = ConnectionAdapter.new(nil, nil, nil, temp_config)
|
|
123
|
+
adapter.connect
|
|
124
|
+
adapter.drop_database(database, if_exists: true)
|
|
125
|
+
adapter.disconnect!
|
|
126
|
+
|
|
127
|
+
puts "Dropped database '#{database}'"
|
|
128
|
+
rescue ClickhouseRuby::Error => e
|
|
129
|
+
raise "Failed to drop database '#{database}': #{e.message}"
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
# Purge (drop and recreate) a ClickHouse database
|
|
133
|
+
def purge(master_configuration_hash = configuration_hash)
|
|
134
|
+
drop(master_configuration_hash)
|
|
135
|
+
create(master_configuration_hash)
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Return structure dump (schema)
|
|
139
|
+
#
|
|
140
|
+
# @param master_configuration_hash [Hash] database configuration
|
|
141
|
+
# @param filename [String] path to dump file
|
|
142
|
+
def structure_dump(master_configuration_hash, filename)
|
|
143
|
+
config = master_configuration_hash.symbolize_keys
|
|
144
|
+
|
|
145
|
+
adapter = ConnectionAdapter.new(nil, nil, nil, config)
|
|
146
|
+
adapter.connect
|
|
147
|
+
|
|
148
|
+
File.open(filename, 'w') do |file|
|
|
149
|
+
# Dump each table's CREATE statement
|
|
150
|
+
adapter.tables.each do |table_name|
|
|
151
|
+
result = adapter.execute("SHOW CREATE TABLE #{adapter.quote_table_name(table_name)}")
|
|
152
|
+
create_statement = result.first['statement'] || result.first['Create Table']
|
|
153
|
+
file.puts "#{create_statement};\n\n"
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
adapter.disconnect!
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
# Load structure from dump file
|
|
161
|
+
#
|
|
162
|
+
# @param master_configuration_hash [Hash] database configuration
|
|
163
|
+
# @param filename [String] path to dump file
|
|
164
|
+
def structure_load(master_configuration_hash, filename)
|
|
165
|
+
config = master_configuration_hash.symbolize_keys
|
|
166
|
+
|
|
167
|
+
adapter = ConnectionAdapter.new(nil, nil, nil, config)
|
|
168
|
+
adapter.connect
|
|
169
|
+
|
|
170
|
+
# Read and execute each statement
|
|
171
|
+
sql = File.read(filename)
|
|
172
|
+
statements = sql.split(/;\s*\n/).reject(&:empty?)
|
|
173
|
+
|
|
174
|
+
statements.each do |statement|
|
|
175
|
+
adapter.execute(statement.strip) unless statement.strip.empty?
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
adapter.disconnect!
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Charset (not applicable to ClickHouse)
|
|
182
|
+
def charset(_master_configuration_hash = configuration_hash)
|
|
183
|
+
'UTF-8'
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# Collation (not applicable to ClickHouse)
|
|
187
|
+
def collation(_master_configuration_hash = configuration_hash)
|
|
188
|
+
nil
|
|
189
|
+
end
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
end
|