Class: ClickhouseRuby::Client
- Inherits:
-
Object
- Object
- ClickhouseRuby::Client
- Defined in:
- lib/clickhouse_ruby/client.rb
Overview
Main HTTP client for ClickHouse communication
The Client provides a high-level interface for executing queries and inserting data into ClickHouse. It handles:
-
Connection pooling for performance
-
Automatic format handling (JSONCompact for queries)
-
Proper error handling with rich context
-
Bulk inserts with JSONEachRow format
CRITICAL: This client ALWAYS checks HTTP status codes before parsing response bodies. This prevents the silent error bug found in clickhouse-activerecord (issue #230).
Constant Summary collapse
- DEFAULT_FORMAT =
Default response format for queries
'JSONCompact'- INSERT_FORMAT =
Format for bulk inserts (5x faster than VALUES)
'JSONEachRow'
Instance Attribute Summary collapse
-
#config ⇒ Configuration
readonly
The client configuration.
-
#pool ⇒ ConnectionPool
readonly
The connection pool.
Instance Method Summary collapse
-
#close ⇒ void
(also: #disconnect)
Closes all connections in the pool.
-
#command(sql, settings: {}) ⇒ Boolean
Executes a command (INSERT, CREATE, DROP, etc.) that doesn’t return data.
-
#execute(sql, settings: {}, format: DEFAULT_FORMAT) ⇒ Result
Executes a SQL query and returns results.
-
#initialize(config) ⇒ Client
constructor
Creates a new Client.
-
#insert(table, rows, columns: nil, settings: {}, format: :json_each_row) ⇒ Boolean
Inserts multiple rows using bulk insert (JSONEachRow format).
-
#ping ⇒ Boolean
Checks if the ClickHouse server is reachable.
-
#pool_stats ⇒ Hash
Returns pool statistics.
-
#server_version ⇒ String
Returns the ClickHouse server version.
Constructor Details
#initialize(config) ⇒ Client
Creates a new Client
58 59 60 61 62 63 64 |
# File 'lib/clickhouse_ruby/client.rb', line 58 def initialize(config) @config = config @config.validate! @pool = ConnectionPool.new(config) @logger = config.logger @default_settings = config.default_settings || {} end |
Instance Attribute Details
#config ⇒ Configuration (readonly)
Returns the client configuration.
49 50 51 |
# File 'lib/clickhouse_ruby/client.rb', line 49 def config @config end |
#pool ⇒ ConnectionPool (readonly)
Returns the connection pool.
52 53 54 |
# File 'lib/clickhouse_ruby/client.rb', line 52 def pool @pool end |
Instance Method Details
#close ⇒ void Also known as: disconnect
This method returns an undefined value.
Closes all connections in the pool
Call this when shutting down to clean up resources.
200 201 202 |
# File 'lib/clickhouse_ruby/client.rb', line 200 def close @pool.shutdown end |
#command(sql, settings: {}) ⇒ Boolean
Executes a command (INSERT, CREATE, DROP, etc.) that doesn’t return data
108 109 110 111 112 |
# File 'lib/clickhouse_ruby/client.rb', line 108 def command(sql, settings: {}) params = build_query_params(settings) execute_request(sql, params) true end |
#execute(sql, settings: {}, format: DEFAULT_FORMAT) ⇒ Result
Executes a SQL query and returns results
84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/clickhouse_ruby/client.rb', line 84 def execute(sql, settings: {}, format: DEFAULT_FORMAT) # Build the query with format query_with_format = "#{sql.strip} FORMAT #{format}" # Build query parameters params = build_query_params(settings) # Execute via connection pool response = execute_request(query_with_format, params) # Parse response based on format parse_response(response, sql, format) end |
#insert(table, rows, columns: nil, settings: {}, format: :json_each_row) ⇒ Boolean
Inserts multiple rows using bulk insert (JSONEachRow format)
This is significantly faster than INSERT … VALUES for large datasets. The data is sent in JSONEachRow format which ClickHouse can parse efficiently.
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/clickhouse_ruby/client.rb', line 139 def insert(table, rows, columns: nil, settings: {}, format: :json_each_row) raise ArgumentError, 'rows cannot be empty' if rows.nil? || rows.empty? # Determine columns from first row if not specified columns ||= rows.first.keys.map(&:to_s) # Build INSERT statement columns_str = columns.map { |c| quote_identifier(c) }.join(', ') sql = "INSERT INTO #{quote_identifier(table)} (#{columns_str}) FORMAT #{INSERT_FORMAT}" # Build JSON body body = rows.map do |row| row_data = {} columns.each do |col| key = col.to_s value = row[col] || row[col.to_sym] row_data[key] = serialize_value(value) end JSON.generate(row_data) end.join("\n") # Build params and execute params = build_query_params(settings) path = build_path(params) @pool.with_connection do |conn| log_query(sql) if @logger response = conn.post("#{path}&query=#{URI.encode_www_form_component(sql)}", body, { 'Content-Type' => 'application/json' }) handle_response(response, sql) end true end |
#ping ⇒ Boolean
Checks if the ClickHouse server is reachable
180 181 182 183 184 |
# File 'lib/clickhouse_ruby/client.rb', line 180 def ping @pool.with_connection(&:ping) rescue StandardError false end |
#pool_stats ⇒ Hash
Returns pool statistics
208 209 210 |
# File 'lib/clickhouse_ruby/client.rb', line 208 def pool_stats @pool.stats end |
#server_version ⇒ String
Returns the ClickHouse server version
190 191 192 193 |
# File 'lib/clickhouse_ruby/client.rb', line 190 def server_version result = execute('SELECT version() AS version') result.first['version'] end |