chdb-ruby 0.1.0 → 0.2.0.rc.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4b53978c961a9a237f689559adad514d7b95ad435ddfa83284bd78dbf985a339
4
- data.tar.gz: 4d5d284e83f4f52800739f39ed2185b629182a39e10f359f3c884e4fc27c9de5
3
+ metadata.gz: d3dffafce42be0cf41b18bdc22e47ae17a4dfea85169a641b2068a9d0e54b306
4
+ data.tar.gz: e0cde6afb8872dd2a72f5dc8b90392ec0163707daa430907aa126e63a57bbf77
5
5
  SHA512:
6
- metadata.gz: 05d288d130263d52120d1741351e081d05c072c992b9f7f05cc91be3454b2f423971295dfb670acee179cd1905017b24ead943fc9cc67b4747f155edc6541c41
7
- data.tar.gz: 4607787c66d0f16b3a74377d1e6e43a6cf3ab7a5aac60b27b30fccfaa2fc6a5eff09f780d611e690a9805278a5a104a99eab5f458b97718949f45446b4b5ccb3
6
+ metadata.gz: d198f71a5348388d2b49eb5819014490d0300a20fb1d48c8342da35162d41b650d3c872f1d65b15777d2a73a47b9ca5438f551a066c05b59faab2f2b6148bd02
7
+ data.tar.gz: f73e40324a300d87849350637257a593f484ba2b8a8f7e40c671969ed9dbc2c1737437641dbe96a7a119d22b33bff753a514bd66f612453c0f9305ffea620a4a
data/README.md CHANGED
@@ -114,6 +114,17 @@ ChDB::Database.open(':memory:') do |db|
114
114
  json_data = db.query_with_format('SELECT 1 as a, 2 as b', 'JSON')
115
115
  p json_data
116
116
  end
117
+
118
+ # Execute streaming query
119
+ ChDB::Database.open(':memory:') do |db|
120
+ total_rows = 0
121
+ collected = []
122
+ db.send_query('SELECT * FROM numbers(200000)') do |chunk|
123
+ collected << chunk.buf
124
+ total_rows += chunk.rows_read
125
+ end
126
+ p total_rows # => 200000
127
+ end
117
128
  ```
118
129
 
119
130
  ## Thread Safety
data/dependencies.yml CHANGED
@@ -1,2 +1,2 @@
1
1
  chdb:
2
- version: "3.1.2"
2
+ version: "3.2.0"
data/ext/chdb/chdb.c CHANGED
@@ -6,6 +6,7 @@
6
6
  #include "connection.h"
7
7
  #include "exception.h"
8
8
  #include "local_result.h"
9
+ #include "streaming_result.h"
9
10
 
10
11
  void Init_chdb_native()
11
12
  {
@@ -15,6 +16,7 @@ void Init_chdb_native()
15
16
  init_chdb_handle();
16
17
  init_chdb_constants();
17
18
  init_local_result();
19
+ init_streaming_result();
18
20
  init_connection();
19
21
 
20
22
  DEBUG_PRINT("chdb extension initialized successfully");
@@ -10,6 +10,11 @@ connect_chdb_func connect_chdb_ptr = NULL;
10
10
  close_conn_func close_conn_ptr = NULL;
11
11
  query_conn_func query_conn_ptr = NULL;
12
12
  free_result_v2_func free_result_v2_ptr = NULL;
13
+ query_conn_streaming_func query_conn_streaming_ptr = NULL;
14
+ chdb_streaming_result_error_func chdb_streaming_result_error_ptr = NULL;
15
+ chdb_streaming_fetch_result_func chdb_streaming_fetch_result_ptr = NULL;
16
+ chdb_streaming_cancel_query_func chdb_streaming_cancel_query_ptr = NULL;
17
+ chdb_destroy_result_func chdb_destroy_result_ptr = NULL;
13
18
 
14
19
  VALUE get_chdb_rb_path()
15
20
  {
@@ -39,6 +44,11 @@ void init_chdb_handle()
39
44
  close_conn_ptr = NULL;
40
45
  query_conn_ptr = NULL;
41
46
  free_result_v2_ptr = NULL;
47
+ query_conn_streaming_ptr = NULL;
48
+ chdb_streaming_result_error_ptr = NULL;
49
+ chdb_streaming_fetch_result_ptr = NULL;
50
+ chdb_streaming_cancel_query_ptr = NULL;
51
+ chdb_destroy_result_ptr = NULL;
42
52
 
43
53
  chdb_handle = dlopen(RSTRING_PTR(lib_path), RTLD_LAZY | RTLD_GLOBAL);
44
54
  if (!chdb_handle)
@@ -51,18 +61,30 @@ void init_chdb_handle()
51
61
  close_conn_ptr = (close_conn_func)dlsym(chdb_handle, "close_conn");
52
62
  query_conn_ptr = (query_conn_func)dlsym(chdb_handle, "query_conn");
53
63
  free_result_v2_ptr = (free_result_v2_func)dlsym(chdb_handle, "free_result_v2");
64
+ query_conn_streaming_ptr = (query_conn_streaming_func)dlsym(chdb_handle, "query_conn_streaming");
65
+ chdb_streaming_result_error_ptr = (chdb_streaming_result_error_func)dlsym(chdb_handle, "chdb_streaming_result_error");
66
+ chdb_streaming_fetch_result_ptr = (chdb_streaming_fetch_result_func)dlsym(chdb_handle, "chdb_streaming_fetch_result");
67
+ chdb_streaming_cancel_query_ptr = (chdb_streaming_cancel_query_func)dlsym(chdb_handle, "chdb_streaming_cancel_query");
68
+ chdb_destroy_result_ptr = (chdb_destroy_result_func)dlsym(chdb_handle, "chdb_destroy_result");
54
69
 
55
- if (!connect_chdb_ptr || !close_conn_ptr || !query_conn_ptr || !free_result_v2_ptr)
70
+ if (!connect_chdb_ptr || !close_conn_ptr || !query_conn_ptr || !free_result_v2_ptr ||
71
+ !query_conn_streaming_ptr || !chdb_streaming_result_error_ptr || !chdb_streaming_fetch_result_ptr ||
72
+ !chdb_streaming_cancel_query_ptr || !chdb_destroy_result_ptr)
56
73
  {
57
74
  close_chdb_handle();
58
75
 
59
76
  rb_raise(cChDBError,
60
- "Symbol loading failed: %s\nMissing functions: connect_chdb(%p) close_conn(%p) query_conn(%p), free_result_v2(%p)",
77
+ "Symbol loading failed: %s\nMissing functions: connect_chdb(%p), close_conn(%p), query_conn(%p), free_result_v2(%p), query_conn_streaming(%p), chdb_streaming_result_error(%p), chdb_streaming_fetch_result(%p), chdb_streaming_cancel_query(%p), chdb_destroy_result(%p)",
61
78
  dlerror(),
62
79
  (void*)connect_chdb_ptr,
63
80
  (void*)close_conn_ptr,
64
81
  (void*)query_conn_ptr,
65
- (void*)free_result_v2_ptr);
82
+ (void*)free_result_v2_ptr,
83
+ (void*)query_conn_streaming_ptr,
84
+ (void*)chdb_streaming_result_error_ptr,
85
+ (void*)chdb_streaming_fetch_result_ptr,
86
+ (void*)chdb_streaming_cancel_query_ptr,
87
+ (void*)chdb_destroy_result_ptr);
66
88
  }
67
89
 
68
90
  rb_set_end_proc(close_chdb_handle, 0);
@@ -1,15 +1,27 @@
1
1
  #ifndef CHDB_HANDLE_H
2
2
  #define CHDB_HANDLE_H
3
3
 
4
+ #include "include/chdb.h"
5
+
4
6
  typedef struct chdb_conn **(*connect_chdb_func)(int, char**);
5
7
  typedef void (*close_conn_func)(struct chdb_conn**);
6
8
  typedef struct local_result_v2 *(*query_conn_func)(struct chdb_conn*, const char*, const char*);
7
9
  typedef void (*free_result_v2_func)(struct local_result_v2*);
10
+ typedef chdb_streaming_result *(*query_conn_streaming_func)(struct chdb_conn*, const char*, const char*);
11
+ typedef const char *(*chdb_streaming_result_error_func)(chdb_streaming_result*);
12
+ typedef struct local_result_v2 *(*chdb_streaming_fetch_result_func)(struct chdb_conn*, chdb_streaming_result*);
13
+ typedef void (*chdb_streaming_cancel_query_func)(struct chdb_conn*, chdb_streaming_result*);
14
+ typedef void (*chdb_destroy_result_func)(chdb_streaming_result*);
8
15
 
9
16
  extern connect_chdb_func connect_chdb_ptr;
10
17
  extern close_conn_func close_conn_ptr;
11
18
  extern query_conn_func query_conn_ptr;
12
19
  extern free_result_v2_func free_result_v2_ptr;
20
+ extern query_conn_streaming_func query_conn_streaming_ptr;
21
+ extern chdb_streaming_result_error_func chdb_streaming_result_error_ptr;
22
+ extern chdb_streaming_fetch_result_func chdb_streaming_fetch_result_ptr;
23
+ extern chdb_streaming_cancel_query_func chdb_streaming_cancel_query_ptr;
24
+ extern chdb_destroy_result_func chdb_destroy_result_ptr;
13
25
 
14
26
  extern void *chdb_handle;
15
27
 
@@ -5,6 +5,7 @@
5
5
  #include "exception.h"
6
6
  #include "include/chdb.h"
7
7
  #include "local_result.h"
8
+ #include "streaming_result.h"
8
9
 
9
10
  void connection_free(void *ptr)
10
11
  {
@@ -32,6 +33,9 @@ void init_connection()
32
33
  rb_define_alloc_func(cConnection, connection_alloc);
33
34
  rb_define_method(cConnection, "initialize", connection_initialize, 2);
34
35
  rb_define_method(cConnection, "query", connection_query, 2);
36
+ rb_define_method(cConnection, "send_query", connection_streaming_query, 2);
37
+ rb_define_method(cConnection, "fetch_streaming_result", connection_streaming_fecth_result, 1);
38
+ rb_define_method(cConnection, "cancel_streaming_query", connection_streaming_cancel_query, 1);
35
39
  rb_define_method(cConnection, "close", connection_close, 0);
36
40
  }
37
41
 
@@ -105,6 +109,83 @@ VALUE connection_query(VALUE self, VALUE query, VALUE format)
105
109
  return result_obj;
106
110
  }
107
111
 
112
+ VALUE connection_streaming_query(VALUE self, VALUE query, VALUE format)
113
+ {
114
+ Connection *conn;
115
+ TypedData_Get_Struct(self, Connection, &ConnectionType, conn);
116
+
117
+ Check_Type(query, T_STRING);
118
+ Check_Type(format, T_STRING);
119
+
120
+ chdb_streaming_result *c_result = query_conn_streaming_ptr(
121
+ *conn->c_conn,
122
+ StringValueCStr(query),
123
+ StringValueCStr(format)
124
+ );
125
+
126
+ if (!c_result)
127
+ {
128
+ rb_raise(cChDBError, "Query failed with nil streaming result");
129
+ }
130
+
131
+ const char *error = chdb_streaming_result_error_ptr(c_result);
132
+ if (error)
133
+ {
134
+ VALUE error_message = rb_str_new_cstr(error);
135
+ chdb_destroy_result_ptr(c_result);
136
+ rb_raise(cChDBError, "CHDB error: %s", StringValueCStr(error_message));
137
+ }
138
+
139
+ VALUE result_obj = rb_class_new_instance(0, NULL, cStreamingResult);
140
+ StreamingResult *result;
141
+ TypedData_Get_Struct(result_obj, StreamingResult, &StreamingResultType, result);
142
+ result->c_result = c_result;
143
+
144
+ return result_obj;
145
+ }
146
+
147
+ VALUE connection_streaming_fecth_result(VALUE self, VALUE streaming_result)
148
+ {
149
+ Connection *conn;
150
+ TypedData_Get_Struct(self, Connection, &ConnectionType, conn);
151
+
152
+ StreamingResult *result;
153
+ TypedData_Get_Struct(streaming_result, StreamingResult, &StreamingResultType, result);
154
+
155
+ struct local_result_v2 *c_result = chdb_streaming_fetch_result_ptr(*conn->c_conn, result->c_result);
156
+
157
+ if (!c_result)
158
+ {
159
+ rb_raise(cChDBError, "Failed to fetch streaming result");
160
+ }
161
+
162
+ if (c_result->error_message)
163
+ {
164
+ VALUE error_message = rb_str_new_cstr(c_result->error_message);
165
+ free_result_v2_ptr(c_result);
166
+ rb_raise(cChDBError, "CHDB error: %s", StringValueCStr(error_message));
167
+ }
168
+
169
+ VALUE result_obj = rb_class_new_instance(0, NULL, cLocalResult);
170
+ LocalResult *local_result;
171
+ TypedData_Get_Struct(result_obj, LocalResult, &LocalResultType, local_result);
172
+ local_result->c_result = c_result;
173
+
174
+ return result_obj;
175
+ }
176
+
177
+ VALUE connection_streaming_cancel_query(VALUE self, VALUE streaming_result)
178
+ {
179
+ Connection *conn;
180
+ TypedData_Get_Struct(self, Connection, &ConnectionType, conn);
181
+
182
+ StreamingResult *result;
183
+ TypedData_Get_Struct(streaming_result, StreamingResult, &StreamingResultType, result);
184
+
185
+ chdb_streaming_cancel_query_ptr(*conn->c_conn, result->c_result);
186
+ return Qnil;
187
+ }
188
+
108
189
  VALUE connection_close(VALUE self)
109
190
  {
110
191
  Connection *conn;
@@ -18,6 +18,12 @@ VALUE connection_initialize(VALUE self, VALUE argc, VALUE argv);
18
18
 
19
19
  VALUE connection_query(VALUE self, VALUE query, VALUE format);
20
20
 
21
+ VALUE connection_streaming_query(VALUE self, VALUE query, VALUE format);
22
+
23
+ VALUE connection_streaming_fecth_result(VALUE self, VALUE streaming_result);
24
+
25
+ VALUE connection_streaming_cancel_query(VALUE self, VALUE streaming_result);
26
+
21
27
  VALUE connection_close(VALUE self);
22
28
 
23
29
  #endif
@@ -1,7 +1,6 @@
1
1
  #include "local_result.h"
2
2
 
3
3
  #include "constants.h"
4
- #include "include/chdb.h"
5
4
  #include "chdb_handle.h"
6
5
 
7
6
  VALUE cLocalResult;
@@ -3,6 +3,8 @@
3
3
 
4
4
  #include <ruby.h>
5
5
 
6
+ #include "include/chdb.h"
7
+
6
8
  typedef struct
7
9
  {
8
10
  struct local_result_v2 *c_result;
@@ -0,0 +1,39 @@
1
+ #include "streaming_result.h"
2
+
3
+ #include "constants.h"
4
+ #include "chdb_handle.h"
5
+
6
+ VALUE cStreamingResult;
7
+
8
+ void streaming_result_free(void *ptr)
9
+ {
10
+ StreamingResult *result = (StreamingResult *)ptr;
11
+ DEBUG_PRINT("Freeing StreamingResult: %p", (void*)result);
12
+ if (result->c_result)
13
+ {
14
+ DEBUG_PRINT("Freeing chdb_streaming_result: %p", (void*)result->c_result);
15
+ chdb_destroy_result_ptr(result->c_result);
16
+ }
17
+ free(result);
18
+ }
19
+
20
+ const rb_data_type_t StreamingResultType =
21
+ {
22
+ "StreamingResult",
23
+ {NULL, streaming_result_free, NULL},
24
+ };
25
+
26
+ void init_streaming_result()
27
+ {
28
+ VALUE mChDB = rb_define_module("ChDB");
29
+ cStreamingResult = rb_define_class_under(mChDB, "StreamingResult", rb_cObject);
30
+ rb_define_alloc_func(cStreamingResult, streaming_result_alloc);
31
+ }
32
+
33
+ VALUE streaming_result_alloc(VALUE klass)
34
+ {
35
+ StreamingResult *result = ALLOC(StreamingResult);
36
+ DEBUG_PRINT("Allocating StreamingResult: %p", (void*)result);
37
+ result->c_result = NULL;
38
+ return rb_data_typed_object_wrap(klass, result, &StreamingResultType);
39
+ }
@@ -0,0 +1,20 @@
1
+ #ifndef CHDB_STREAMING_RESULT_H
2
+ #define CHDB_STREAMING_RESULT_H
3
+
4
+ #include <ruby.h>
5
+
6
+ #include "include/chdb.h"
7
+
8
+ typedef struct
9
+ {
10
+ chdb_streaming_result *c_result;
11
+ } StreamingResult;
12
+
13
+ extern VALUE cStreamingResult;
14
+ extern const rb_data_type_t StreamingResultType;
15
+
16
+ void init_streaming_result();
17
+
18
+ VALUE streaming_result_alloc(VALUE klass);
19
+
20
+ #endif
data/lib/chdb/database.rb CHANGED
@@ -94,14 +94,14 @@ module ChDB
94
94
  end
95
95
  end
96
96
 
97
- def execute2(sql, *bind_vars, &) # rubocop:disable Metrics/MethodLength
97
+ def execute2(sql, *bind_vars, &block) # rubocop:disable Metrics/MethodLength
98
98
  prepare(sql) do |stmt|
99
99
  result = stmt.execute(*bind_vars)
100
100
  stmt.parse
101
101
 
102
- if block_given?
102
+ if block
103
103
  yield stmt.columns
104
- result.each(&)
104
+ result.each(&block)
105
105
  else
106
106
  return result.each_with_object([stmt.columns]) do |row, arr|
107
107
  arr << row
@@ -128,6 +128,18 @@ module ChDB
128
128
  end
129
129
  end
130
130
 
131
+ def send_query(sql, format = 'CSV', bind_vars = [], &block)
132
+ prepare(sql) do |stmt|
133
+ result = stmt.send_query(bind_vars, format)
134
+
135
+ if block
136
+ result.each(&block)
137
+ else
138
+ result
139
+ end
140
+ end
141
+ end
142
+
131
143
  def get_first_row(sql, *bind_vars)
132
144
  execute(sql, *bind_vars).first
133
145
  end
@@ -54,4 +54,44 @@ module ChDB
54
54
  class HashResultSet < ResultSet # :nodoc:
55
55
  alias next next_hash
56
56
  end
57
+
58
+ class StreamingResultSet
59
+ include Enumerable
60
+
61
+ def initialize(db, streaming_result)
62
+ @db = db
63
+ @streaming_result = streaming_result
64
+ @done = false
65
+ end
66
+
67
+ def eof?
68
+ @done
69
+ end
70
+
71
+ def next
72
+ return nil if @done
73
+
74
+ result = @db.conn.fetch_streaming_result(@streaming_result)
75
+
76
+ if result.nil? || result.rows_read.zero?
77
+ @done = true
78
+ nil
79
+ else
80
+ result
81
+ end
82
+ end
83
+
84
+ def each
85
+ while (node = self.next)
86
+ yield node
87
+ end
88
+ end
89
+
90
+ def cancel
91
+ return nil if @done
92
+
93
+ @db.conn.cancel_streaming_query(@streaming_result)
94
+ @done = true
95
+ end
96
+ end
57
97
  end
@@ -8,6 +8,7 @@ rescue LoadError
8
8
  require 'chdb/chdb_native'
9
9
  end
10
10
  require 'chdb/local_result'
11
+ require 'chdb/streaming_result'
11
12
  require 'chdb/result_set'
12
13
  require 'chdb/result_handler'
13
14
  require 'chdb/parameter_binding'
@@ -71,6 +72,21 @@ module ChDB
71
72
  @result.buf
72
73
  end
73
74
 
75
+ def send_query(*bind_vars, format)
76
+ reset! if @executed
77
+
78
+ bind_params(*bind_vars) unless bind_vars.empty?
79
+
80
+ my_processed_sql = process_sql
81
+ streaming_result = @connection.conn.send_query(my_processed_sql, format)
82
+ streaming_result.output_format = format
83
+
84
+ results = StreamingResultSet.new(@connection, streaming_result)
85
+
86
+ yield results if block_given?
87
+ results
88
+ end
89
+
74
90
  def reset!
75
91
  @executed = false
76
92
  @parsed = false
@@ -78,7 +94,7 @@ module ChDB
78
94
  @bind_vars.clear
79
95
  @parsed_data.clear
80
96
  @columns.clear
81
- @results = nil
97
+ @result = nil
82
98
  end
83
99
 
84
100
  def step
@@ -101,7 +117,7 @@ module ChDB
101
117
  end
102
118
 
103
119
  @parsed = true
104
- @results = nil
120
+ @result = nil
105
121
  end
106
122
 
107
123
  private
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChDB
4
+ # Represents the local result of a ChDB operation.
5
+ class StreamingResult
6
+ attr_accessor :output_format
7
+ end
8
+ end
data/lib/chdb/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
 
3
3
  module ChDB
4
4
  # (String) the version of the chdb gem, e.g. "0.1.0"
5
- VERSION = '0.1.0'
5
+ VERSION = '0.2.0.rc.1'
6
6
  end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chdb-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0.rc.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Xiaozhe Yu
8
8
  - Auxten Wang
9
+ autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2025-04-02 00:00:00.000000000 Z
12
+ date: 2025-05-07 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: csv
@@ -27,6 +28,7 @@ dependencies:
27
28
  description: |
28
29
  Ruby library to interface with the chDB database engine (https://clickhouse.com/docs/chdb). Precompiled
29
30
  binaries are available for common platforms for recent versions of Ruby.
31
+ email:
30
32
  executables: []
31
33
  extensions:
32
34
  - ext/chdb/extconf.rb
@@ -48,6 +50,8 @@ files:
48
50
  - ext/chdb/extconf.rb
49
51
  - ext/chdb/local_result.c
50
52
  - ext/chdb/local_result.h
53
+ - ext/chdb/streaming_result.c
54
+ - ext/chdb/streaming_result.h
51
55
  - lib/chdb.rb
52
56
  - lib/chdb/constants.rb
53
57
  - lib/chdb/data_path.rb
@@ -59,6 +63,7 @@ files:
59
63
  - lib/chdb/result_set.rb
60
64
  - lib/chdb/sql_processor.rb
61
65
  - lib/chdb/statement.rb
66
+ - lib/chdb/streaming_result.rb
62
67
  - lib/chdb/version.rb
63
68
  - lib/chdb/version_info.rb
64
69
  homepage: https://github.com/chdb-io/chdb-ruby
@@ -70,6 +75,7 @@ metadata:
70
75
  changelog_uri: https://github.com/chdb-io/chdb-ruby/blob/main/CHANGELOG.md
71
76
  source_code_uri: https://github.com/chdb-io/chdb-ruby
72
77
  rubygems_mfa_required: 'true'
78
+ post_install_message:
73
79
  rdoc_options:
74
80
  - "--main"
75
81
  - README.md
@@ -82,11 +88,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
82
88
  version: '3.1'
83
89
  required_rubygems_version: !ruby/object:Gem::Requirement
84
90
  requirements:
85
- - - ">="
91
+ - - ">"
86
92
  - !ruby/object:Gem::Version
87
- version: '0'
93
+ version: 1.3.1
88
94
  requirements: []
89
- rubygems_version: 3.6.2
95
+ rubygems_version: 3.3.27
96
+ signing_key:
90
97
  specification_version: 4
91
98
  summary: Ruby library to interface with the chDB database engine (https://clickhouse.com/docs/chdb).
92
99
  test_files: []