Class: ClickhouseRuby::Result

Inherits:
Object
  • Object
show all
Includes:
Enumerable
Defined in:
lib/clickhouse_ruby/result.rb

Overview

Query result container that provides access to columns, types, and rows

Result implements Enumerable for easy iteration over rows. Each row is returned as a Hash with column names as keys and properly deserialized values.

Examples:

Iterating over results

result = client.execute('SELECT id, name FROM users')
result.columns  # => ['id', 'name']
result.types    # => ['UInt64', 'String']

result.each do |row|
  puts "#{row['id']}: #{row['name']}"
end

Array-like access

result.rows[0]       # => { 'id' => 1, 'name' => 'Alice' }
result.first         # => { 'id' => 1, 'name' => 'Alice' }
result.to_a          # => [{ 'id' => 1, 'name' => 'Alice' }, ...]

Metadata access

result.count         # => 100
result.empty?        # => false
result.elapsed_time  # => 0.023 (seconds)

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(columns:, types:, data:, statistics: {}, deserialize: true) ⇒ Result

Creates a new Result from parsed response data

Parameters:

  • columns (Array<String>)

    column names

  • types (Array<String>)

    ClickHouse type strings

  • data (Array<Array>)

    raw row data (values in column order)

  • statistics (Hash) (defaults to: {})

    optional query statistics from ClickHouse

  • deserialize (Boolean) (defaults to: true)

    whether to deserialize values using type system



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/clickhouse_ruby/result.rb', line 57

def initialize(columns:, types:, data:, statistics: {}, deserialize: true)
  @columns = columns.freeze
  @types = types.freeze
  @elapsed_time = statistics['elapsed']
  @rows_read = statistics['rows_read']
  @bytes_read = statistics['bytes_read']

  # Build type instances for deserialization
  @type_instances = if deserialize
                      types.map { |t| Types.lookup(t) }
                    else
                      nil
                    end

  # Convert raw data to row hashes
  @rows = build_rows(data).freeze
end

Instance Attribute Details

#bytes_readInteger? (readonly)

Returns bytes read by ClickHouse.

Returns:

  • (Integer, nil)

    bytes read by ClickHouse



48
49
50
# File 'lib/clickhouse_ruby/result.rb', line 48

def bytes_read
  @bytes_read
end

#columnsArray<String> (readonly)

Returns column names in order.

Returns:

  • (Array<String>)

    column names in order



33
34
35
# File 'lib/clickhouse_ruby/result.rb', line 33

def columns
  @columns
end

#elapsed_timeFloat? (readonly)

Returns query execution time in seconds (from ClickHouse).

Returns:

  • (Float, nil)

    query execution time in seconds (from ClickHouse)



42
43
44
# File 'lib/clickhouse_ruby/result.rb', line 42

def elapsed_time
  @elapsed_time
end

#rowsArray<Hash> (readonly)

Returns rows as hashes with column names as keys.

Returns:

  • (Array<Hash>)

    rows as hashes with column names as keys



39
40
41
# File 'lib/clickhouse_ruby/result.rb', line 39

def rows
  @rows
end

#rows_readInteger? (readonly)

Returns number of rows read by ClickHouse.

Returns:

  • (Integer, nil)

    number of rows read by ClickHouse



45
46
47
# File 'lib/clickhouse_ruby/result.rb', line 45

def rows_read
  @rows_read
end

#typesArray<String> (readonly)

Returns ClickHouse type strings for each column.

Returns:

  • (Array<String>)

    ClickHouse type strings for each column



36
37
38
# File 'lib/clickhouse_ruby/result.rb', line 36

def types
  @types
end

Class Method Details

.emptyResult

Creates an empty result (for commands that don’t return data)

Returns:

  • (Result)

    an empty result



143
144
145
# File 'lib/clickhouse_ruby/result.rb', line 143

def self.empty
  new(columns: [], types: [], data: [])
end

.from_json_compact(response_data) ⇒ Result

Creates a result from JSONCompact format response

Parameters:

  • response_data (Hash)

    parsed JSON response

Returns:



151
152
153
154
155
156
157
158
159
# File 'lib/clickhouse_ruby/result.rb', line 151

def self.from_json_compact(response_data)
  meta = response_data['meta'] || []
  columns = meta.map { |m| m['name'] }
  types = meta.map { |m| m['type'] }
  data = response_data['data'] || []
  statistics = response_data['statistics'] || {}

  new(columns: columns, types: types, data: data, statistics: statistics)
end

Instance Method Details

#[](index) ⇒ Hash?

Access a row by index

Parameters:

  • index (Integer)

    row index

Returns:

  • (Hash, nil)

    the row or nil



117
118
119
# File 'lib/clickhouse_ruby/result.rb', line 117

def [](index)
  @rows[index]
end

#column_typesHash<String, String>

Returns column names mapped to their types

Returns:

  • (Hash<String, String>)

    column name => type mapping



136
137
138
# File 'lib/clickhouse_ruby/result.rb', line 136

def column_types
  @columns.zip(@types).to_h
end

#column_values(column_name) ⇒ Array

Returns a specific column’s values across all rows

Parameters:

  • column_name (String)

    the column name

Returns:

  • (Array)

    values for that column

Raises:

  • (ArgumentError)

    if column doesn’t exist



126
127
128
129
130
131
# File 'lib/clickhouse_ruby/result.rb', line 126

def column_values(column_name)
  index = @columns.index(column_name)
  raise ArgumentError, "Unknown column: #{column_name}" if index.nil?

  @rows.map { |row| row[column_name] }
end

#countInteger Also known as: size, length

Returns the number of rows

Returns:

  • (Integer)

    row count



86
87
88
# File 'lib/clickhouse_ruby/result.rb', line 86

def count
  @rows.length
end

#each {|Hash| ... } ⇒ Enumerator

Iterates over each row

Yields:

  • (Hash)

    each row as a hash

Returns:

  • (Enumerator)

    if no block given



79
80
81
# File 'lib/clickhouse_ruby/result.rb', line 79

def each(&block)
  @rows.each(&block)
end

#empty?Boolean

Returns whether there are no rows

Returns:

  • (Boolean)

    true if no rows



95
96
97
# File 'lib/clickhouse_ruby/result.rb', line 95

def empty?
  @rows.empty?
end

#firstHash?

Returns the first row

Returns:

  • (Hash, nil)

    the first row or nil



102
103
104
# File 'lib/clickhouse_ruby/result.rb', line 102

def first
  @rows.first
end

#inspectString

Returns a human-readable string representation

Returns:

  • (String)

    string representation



164
165
166
# File 'lib/clickhouse_ruby/result.rb', line 164

def inspect
  "#<#{self.class.name} columns=#{@columns.inspect} rows=#{count}>"
end

#lastHash?

Returns the last row

Returns:

  • (Hash, nil)

    the last row or nil



109
110
111
# File 'lib/clickhouse_ruby/result.rb', line 109

def last
  @rows.last
end