chdb-ruby 0.1.0.rc.2

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.
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChDB
4
+ # The ResultSet object encapsulates the enumerability of a query's output.
5
+ # It is a simple cursor over the data that the query returns. It will
6
+ # very rarely (if ever) be instantiated directly. Instead, clients should
7
+ # obtain a ResultSet instance via Statement#execute.
8
+ class ResultSet
9
+ include Enumerable
10
+
11
+ # Create a new ResultSet attached to the given database, using the
12
+ # given sql text.
13
+ def initialize(db, stmt)
14
+ @db = db
15
+ @stmt = stmt
16
+ end
17
+
18
+ def eof?
19
+ @stmt.done?
20
+ end
21
+
22
+ def next
23
+ @stmt.step
24
+ end
25
+
26
+ def each
27
+ while (node = self.next)
28
+ yield node
29
+ end
30
+ end
31
+
32
+ # Provides an internal iterator over the rows of the result set where
33
+ # each row is yielded as a hash.
34
+ def each_hash
35
+ while (node = next_hash)
36
+ yield node
37
+ end
38
+ end
39
+
40
+ # Returns the names of the columns returned by this result set.
41
+ def columns
42
+ @stmt.columns
43
+ end
44
+
45
+ # Return the next row as a hash
46
+ def next_hash
47
+ row = @stmt.step
48
+ return nil unless row
49
+
50
+ @stmt.columns.zip(row).to_h
51
+ end
52
+ end
53
+
54
+ class HashResultSet < ResultSet # :nodoc:
55
+ alias next next_hash
56
+ end
57
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChDB
4
+ # This module provides functionality for processing SQL queries,
5
+ # including binding variables and escaping values.
6
+ module SQLProcessor
7
+ def process_sql
8
+ escaped_values = @bind_vars.map { |v| escape(v) }
9
+ sql = @sql.dup
10
+ sql.gsub(/(?<!\\)\?/) { escaped_values.shift or '?' }
11
+ end
12
+
13
+ def escape(value)
14
+ case value
15
+ when String then "'#{value.gsub("'", "''")}'"
16
+ when NilClass then 'NULL'
17
+ when TrueClass then '1'
18
+ when FalseClass then '0'
19
+ else value.to_s
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,137 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'csv'
4
+ begin
5
+ RUBY_VERSION =~ /(\d+\.\d+)/
6
+ require "chdb/#{Regexp.last_match(1)}/chdb_native"
7
+ rescue LoadError
8
+ require 'chdb/chdb_native'
9
+ end
10
+ require 'chdb/local_result'
11
+ require 'chdb/result_set'
12
+ require 'chdb/result_handler'
13
+ require 'chdb/parameter_binding'
14
+ require 'chdb/sql_processor'
15
+
16
+ module ChDB
17
+ # Represents a prepared SQL statement in the ChDB database.
18
+ # This class provides methods for executing SQL statements, binding parameters,
19
+ # and iterating over the result set.
20
+ class Statement
21
+ include Enumerable
22
+ include ParameterBinding
23
+ include SQLProcessor
24
+ include ResultHandler
25
+
26
+ attr_reader :result, :columns, :parsed_data
27
+
28
+ def initialize(db, sql_str)
29
+ validate_inputs(db, sql_str)
30
+ @sql = encode_sql(sql_str)
31
+ @connection = db
32
+ @executed = false
33
+ @parsed = false
34
+ @row_idx = 0
35
+ @bind_vars = []
36
+ @parsed_data = []
37
+ @columns = []
38
+ end
39
+
40
+ def execute(*bind_vars)
41
+ reset! if @executed
42
+ @executed = true
43
+
44
+ bind_params(*bind_vars) unless bind_vars.empty?
45
+
46
+ @processed_sql = process_sql
47
+
48
+ results = @connection.build_result_set self
49
+ @result = @connection.conn.query(@processed_sql, 'CSVWithNames')
50
+ @result.output_format = 'CSVWithNames'
51
+
52
+ yield results if block_given?
53
+ results
54
+ end
55
+
56
+ def execute!(*bind_vars, &block)
57
+ execute(*bind_vars)
58
+ block ? each(&block) : to_a
59
+ end
60
+
61
+ def execute_with_format(*bind_vars, format)
62
+ reset! if @executed
63
+ @executed = true
64
+
65
+ bind_params(*bind_vars) unless bind_vars.empty?
66
+
67
+ @processed_sql = process_sql
68
+ @result = @connection.conn.query(@processed_sql, format)
69
+
70
+ yield @result.buf if block_given?
71
+ @result.buf
72
+ end
73
+
74
+ def reset!
75
+ @executed = false
76
+ @parsed = false
77
+ @row_idx = 0
78
+ @bind_vars.clear
79
+ @parsed_data.clear
80
+ @columns.clear
81
+ @results = nil
82
+ end
83
+
84
+ def step
85
+ parse
86
+ return nil if @row_idx >= @parsed_data.size
87
+
88
+ current_row = @parsed_data[@row_idx]
89
+ @row_idx += 1
90
+ current_row
91
+ end
92
+
93
+ def parse
94
+ return if @parsed
95
+
96
+ if @result&.buf.to_s.empty?
97
+ @columns = []
98
+ @parsed_data = []
99
+ else
100
+ @columns, @parsed_data = ResultHandler.parse_output(@result.buf)
101
+ end
102
+
103
+ @parsed = true
104
+ @results = nil
105
+ end
106
+
107
+ private
108
+
109
+ def validate_inputs(db, sql_str)
110
+ raise ArgumentError, 'SQL statement cannot be nil' if sql_str.nil?
111
+ raise ArgumentError, 'prepare called on a closed database' if db.nil? || db.closed?
112
+ end
113
+
114
+ def encode_sql(sql_str)
115
+ if sql_str.encoding == Encoding::UTF_8
116
+ sql_str.dup
117
+ else
118
+ sql_str.encode(Encoding::UTF_8)
119
+ end
120
+ end
121
+
122
+ # Returns true if the statement is currently active, meaning it has an
123
+ # open result set.
124
+ def active?
125
+ @executed && !done?
126
+ end
127
+
128
+ def each
129
+ loop do
130
+ val = step
131
+ break if val.nil?
132
+
133
+ yield val
134
+ end
135
+ end
136
+ end
137
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChDB
4
+ # (String) the version of the chdb gem, e.g. "0.1.0"
5
+ VERSION = '0.1.0.rc.2'
6
+ end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChDB
4
+ # a hash of descriptive metadata about the current version of the chdb gem
5
+ VERSION_INFO = {
6
+ ruby: RUBY_DESCRIPTION,
7
+ gem: {
8
+ version: ChDB::VERSION
9
+ }
10
+ }.freeze
11
+ end
data/lib/chdb.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ChDB
4
+ def self.lib_file_path
5
+ @lib_file_path ||= File.expand_path(__FILE__)
6
+ end
7
+ end
8
+
9
+ begin
10
+ RUBY_VERSION =~ /(\d+\.\d+)/
11
+ require "chdb/#{Regexp.last_match(1)}/chdb_native"
12
+ rescue LoadError
13
+ require 'chdb/chdb_native'
14
+ end
15
+
16
+ require 'chdb/database'
17
+ require 'chdb/version'
18
+ require 'chdb/version_info'
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: chdb-ruby
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0.rc.2
5
+ platform: ruby
6
+ authors:
7
+ - Xiaozhe Yu
8
+ - Auxten Wang
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2025-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: csv
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.1'
27
+ description: |
28
+ Ruby library to interface with the chDB database engine (https://clickhouse.com/docs/chdb). Precompiled
29
+ binaries are available for common platforms for recent versions of Ruby.
30
+ executables: []
31
+ extensions:
32
+ - ext/chdb/extconf.rb
33
+ extra_rdoc_files: []
34
+ files:
35
+ - INSTALLATION.md
36
+ - LICENSE
37
+ - README.md
38
+ - dependencies.yml
39
+ - ext/chdb/chdb.c
40
+ - ext/chdb/chdb_handle.c
41
+ - ext/chdb/chdb_handle.h
42
+ - ext/chdb/connection.c
43
+ - ext/chdb/connection.h
44
+ - ext/chdb/constants.h
45
+ - ext/chdb/exception.c
46
+ - ext/chdb/exception.h
47
+ - ext/chdb/extconf.rb
48
+ - ext/chdb/local_result.c
49
+ - ext/chdb/local_result.h
50
+ - lib/chdb.rb
51
+ - lib/chdb/constants.rb
52
+ - lib/chdb/data_path.rb
53
+ - lib/chdb/database.rb
54
+ - lib/chdb/errors.rb
55
+ - lib/chdb/local_result.rb
56
+ - lib/chdb/parameter_binding.rb
57
+ - lib/chdb/result_handler.rb
58
+ - lib/chdb/result_set.rb
59
+ - lib/chdb/sql_processor.rb
60
+ - lib/chdb/statement.rb
61
+ - lib/chdb/version.rb
62
+ - lib/chdb/version_info.rb
63
+ homepage: https://github.com/chdb-io/chdb-ruby
64
+ licenses:
65
+ - Apache-2.0
66
+ metadata:
67
+ homepage_uri: https://github.com/chdb-io/chdb-ruby
68
+ bug_tracker_uri: https://github.com/chdb-io/chdb-ruby/issues
69
+ changelog_uri: https://github.com/chdb-io/chdb-ruby/blob/main/CHANGELOG.md
70
+ source_code_uri: https://github.com/chdb-io/chdb-ruby
71
+ rubygems_mfa_required: 'true'
72
+ rdoc_options:
73
+ - "--main"
74
+ - README.md
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '3.1'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.6.2
89
+ specification_version: 4
90
+ summary: Ruby library to interface with the chDB database engine (https://clickhouse.com/docs/chdb).
91
+ test_files: []