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.
Files changed (33) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +80 -0
  3. data/LICENSE +21 -0
  4. data/README.md +251 -0
  5. data/lib/clickhouse_ruby/active_record/arel_visitor.rb +468 -0
  6. data/lib/clickhouse_ruby/active_record/connection_adapter.rb +723 -0
  7. data/lib/clickhouse_ruby/active_record/railtie.rb +192 -0
  8. data/lib/clickhouse_ruby/active_record/schema_statements.rb +693 -0
  9. data/lib/clickhouse_ruby/active_record.rb +121 -0
  10. data/lib/clickhouse_ruby/client.rb +471 -0
  11. data/lib/clickhouse_ruby/configuration.rb +145 -0
  12. data/lib/clickhouse_ruby/connection.rb +328 -0
  13. data/lib/clickhouse_ruby/connection_pool.rb +301 -0
  14. data/lib/clickhouse_ruby/errors.rb +144 -0
  15. data/lib/clickhouse_ruby/result.rb +189 -0
  16. data/lib/clickhouse_ruby/types/array.rb +183 -0
  17. data/lib/clickhouse_ruby/types/base.rb +77 -0
  18. data/lib/clickhouse_ruby/types/boolean.rb +68 -0
  19. data/lib/clickhouse_ruby/types/date_time.rb +163 -0
  20. data/lib/clickhouse_ruby/types/float.rb +115 -0
  21. data/lib/clickhouse_ruby/types/integer.rb +157 -0
  22. data/lib/clickhouse_ruby/types/low_cardinality.rb +58 -0
  23. data/lib/clickhouse_ruby/types/map.rb +249 -0
  24. data/lib/clickhouse_ruby/types/nullable.rb +73 -0
  25. data/lib/clickhouse_ruby/types/parser.rb +244 -0
  26. data/lib/clickhouse_ruby/types/registry.rb +148 -0
  27. data/lib/clickhouse_ruby/types/string.rb +83 -0
  28. data/lib/clickhouse_ruby/types/tuple.rb +206 -0
  29. data/lib/clickhouse_ruby/types/uuid.rb +84 -0
  30. data/lib/clickhouse_ruby/types.rb +69 -0
  31. data/lib/clickhouse_ruby/version.rb +5 -0
  32. data/lib/clickhouse_ruby.rb +101 -0
  33. 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