ruby-kuzu 0.0.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 +7 -0
- checksums.yaml.gz.sig +0 -0
- data/History.md +6 -0
- data/LICENSE.txt +20 -0
- data/README.md +95 -0
- data/ext/kuzu_ext/config.c +318 -0
- data/ext/kuzu_ext/connection.c +310 -0
- data/ext/kuzu_ext/database.c +196 -0
- data/ext/kuzu_ext/extconf.rb +20 -0
- data/ext/kuzu_ext/kuzu_ext.c +158 -0
- data/ext/kuzu_ext/kuzu_ext.h +130 -0
- data/ext/kuzu_ext/node.c +24 -0
- data/ext/kuzu_ext/prepared_statement.c +392 -0
- data/ext/kuzu_ext/query_summary.c +140 -0
- data/ext/kuzu_ext/recursive_rel.c +24 -0
- data/ext/kuzu_ext/rel.c +24 -0
- data/ext/kuzu_ext/result.c +514 -0
- data/ext/kuzu_ext/types.c +612 -0
- data/lib/kuzu/config.rb +70 -0
- data/lib/kuzu/connection.rb +51 -0
- data/lib/kuzu/database.rb +53 -0
- data/lib/kuzu/node.rb +46 -0
- data/lib/kuzu/prepared_statement.rb +42 -0
- data/lib/kuzu/query_summary.rb +28 -0
- data/lib/kuzu/recursive_rel.rb +37 -0
- data/lib/kuzu/rel.rb +51 -0
- data/lib/kuzu/result.rb +139 -0
- data/lib/kuzu.rb +79 -0
- data/spec/kuzu/config_spec.rb +98 -0
- data/spec/kuzu/database_spec.rb +51 -0
- data/spec/kuzu/prepared_statement_spec.rb +93 -0
- data/spec/kuzu/query_summary_spec.rb +30 -0
- data/spec/kuzu/result_spec.rb +190 -0
- data/spec/kuzu/types_spec.rb +254 -0
- data/spec/kuzu_spec.rb +55 -0
- data/spec/spec_helper.rb +101 -0
- data.tar.gz.sig +0 -0
- metadata +163 -0
- metadata.gz.sig +0 -0
@@ -0,0 +1,310 @@
|
|
1
|
+
/*
|
2
|
+
* connection.c - Kuzu::Connection class
|
3
|
+
*
|
4
|
+
*/
|
5
|
+
|
6
|
+
#include "kuzu.h"
|
7
|
+
#include "kuzu_ext.h"
|
8
|
+
#include "ruby/thread.h"
|
9
|
+
|
10
|
+
#define CHECK_CONNECTION(self) ((rkuzu_connection *)rb_check_typeddata((self), &rkuzu_connection_type))
|
11
|
+
// #define DEBUG_GC(msg, ptr) fprintf( stderr, msg, ptr )
|
12
|
+
#define DEBUG_GC(msg, ptr)
|
13
|
+
|
14
|
+
|
15
|
+
VALUE rkuzu_cKuzuConnection;
|
16
|
+
|
17
|
+
static void rkuzu_connection_free( void * );
|
18
|
+
static void rkuzu_connection_mark( void * );
|
19
|
+
|
20
|
+
static const rb_data_type_t rkuzu_connection_type = {
|
21
|
+
.wrap_struct_name = "Kuzu::Connection",
|
22
|
+
.function = {
|
23
|
+
.dfree = rkuzu_connection_free,
|
24
|
+
.dmark = rkuzu_connection_mark,
|
25
|
+
},
|
26
|
+
.data = NULL,
|
27
|
+
};
|
28
|
+
|
29
|
+
|
30
|
+
rkuzu_connection *
|
31
|
+
rkuzu_get_connection( VALUE conn_obj )
|
32
|
+
{
|
33
|
+
return CHECK_CONNECTION( conn_obj );
|
34
|
+
}
|
35
|
+
|
36
|
+
|
37
|
+
static rkuzu_connection *
|
38
|
+
rkuzu_connection_alloc( void )
|
39
|
+
{
|
40
|
+
rkuzu_connection *ptr = ALLOC( rkuzu_connection );
|
41
|
+
|
42
|
+
ptr->database = Qnil;
|
43
|
+
ptr->queries = rb_ary_new();
|
44
|
+
ptr->statements = rb_ary_new();
|
45
|
+
|
46
|
+
return ptr;
|
47
|
+
}
|
48
|
+
|
49
|
+
|
50
|
+
static void
|
51
|
+
rkuzu_connection_free( void *ptr )
|
52
|
+
{
|
53
|
+
rkuzu_connection *conn_s = (rkuzu_connection *)ptr;
|
54
|
+
|
55
|
+
if ( ptr ) {
|
56
|
+
DEBUG_GC( ">>> freeing connection %p\n", ptr );
|
57
|
+
|
58
|
+
kuzu_connection_destroy( &conn_s->conn );
|
59
|
+
|
60
|
+
xfree( ptr );
|
61
|
+
ptr = NULL;
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
static void
|
67
|
+
rkuzu_connection_mark( void *ptr )
|
68
|
+
{
|
69
|
+
rkuzu_connection *conn_s = (rkuzu_connection *)ptr;
|
70
|
+
|
71
|
+
if ( ptr ) {
|
72
|
+
DEBUG_GC( ">>> marking connection %p\n", ptr );
|
73
|
+
rb_gc_mark( conn_s->database );
|
74
|
+
rb_gc_mark( conn_s->statements );
|
75
|
+
rb_gc_mark( conn_s->queries );
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
|
80
|
+
/*
|
81
|
+
* ::allocate function
|
82
|
+
*/
|
83
|
+
static VALUE
|
84
|
+
rkuzu_connection_s_allocate( VALUE klass )
|
85
|
+
{
|
86
|
+
return TypedData_Wrap_Struct( klass, &rkuzu_connection_type, NULL );
|
87
|
+
}
|
88
|
+
|
89
|
+
|
90
|
+
|
91
|
+
/*
|
92
|
+
* call-seq:
|
93
|
+
* new( database ) -> connection
|
94
|
+
*
|
95
|
+
* Create a Kuzu::Connection to the specified +database+.
|
96
|
+
*
|
97
|
+
*/
|
98
|
+
static VALUE
|
99
|
+
rkuzu_connection_initialize( VALUE self, VALUE database )
|
100
|
+
{
|
101
|
+
rkuzu_connection *ptr = CHECK_CONNECTION( self );
|
102
|
+
|
103
|
+
if ( !ptr ) {
|
104
|
+
rkuzu_database *dbobject = rkuzu_get_database( database );
|
105
|
+
ptr = rkuzu_connection_alloc();
|
106
|
+
|
107
|
+
if ( kuzu_connection_init(&dbobject->db, &ptr->conn) != KuzuSuccess ) {
|
108
|
+
xfree( ptr );
|
109
|
+
ptr = NULL;
|
110
|
+
rb_raise( rkuzu_eConnectionError, "Failed to connect!" );
|
111
|
+
}
|
112
|
+
|
113
|
+
DEBUG_GC( ">>> allocated connection %p\n", ptr );
|
114
|
+
RTYPEDDATA_DATA( self ) = ptr;
|
115
|
+
|
116
|
+
ptr->database = database;
|
117
|
+
|
118
|
+
} else {
|
119
|
+
rb_raise( rb_eRuntimeError, "cannot reinit connection" );
|
120
|
+
}
|
121
|
+
|
122
|
+
rb_call_super( 0, 0 );
|
123
|
+
|
124
|
+
return Qtrue;
|
125
|
+
}
|
126
|
+
|
127
|
+
|
128
|
+
struct query_call {
|
129
|
+
kuzu_connection *conn;
|
130
|
+
const char *query_s;
|
131
|
+
kuzu_query_result *result;
|
132
|
+
};
|
133
|
+
|
134
|
+
|
135
|
+
static void *
|
136
|
+
rkuzu_connection_do_query_without_gvl( void *ptr )
|
137
|
+
{
|
138
|
+
struct query_call *qcall = (struct query_call *)ptr;
|
139
|
+
kuzu_state state;
|
140
|
+
|
141
|
+
state = kuzu_connection_query( qcall->conn, qcall->query_s, qcall->result );
|
142
|
+
|
143
|
+
return (void *)state;
|
144
|
+
}
|
145
|
+
|
146
|
+
|
147
|
+
static void
|
148
|
+
rkuzu_connection_cancel_query( void *ptr )
|
149
|
+
{
|
150
|
+
kuzu_connection *conn = (kuzu_connection *)ptr;
|
151
|
+
kuzu_connection_interrupt( conn );
|
152
|
+
}
|
153
|
+
|
154
|
+
|
155
|
+
static kuzu_query_result
|
156
|
+
rkuzu_connection_do_query( VALUE self, VALUE query )
|
157
|
+
{
|
158
|
+
rkuzu_connection *conn = CHECK_CONNECTION( self );
|
159
|
+
const char *query_s = StringValueCStr( query );
|
160
|
+
kuzu_query_result result;
|
161
|
+
kuzu_state query_state;
|
162
|
+
struct query_call qcall;
|
163
|
+
void *result_ptr;
|
164
|
+
|
165
|
+
qcall.conn = &conn->conn;
|
166
|
+
qcall.query_s = query_s;
|
167
|
+
qcall.result = &result;
|
168
|
+
|
169
|
+
result_ptr = rb_thread_call_without_gvl(
|
170
|
+
rkuzu_connection_do_query_without_gvl, (void *)&qcall,
|
171
|
+
rkuzu_connection_cancel_query, (void *)&conn->conn );
|
172
|
+
|
173
|
+
query_state = (kuzu_state)result_ptr;
|
174
|
+
|
175
|
+
if ( query_state != KuzuSuccess ) {
|
176
|
+
char *err_detail = kuzu_query_result_get_error_message( &result );
|
177
|
+
char errmsg[ 4096 ] = "\0";
|
178
|
+
|
179
|
+
snprintf( errmsg, 4096, "Could not execute query `%s': %s.", query_s, err_detail );
|
180
|
+
|
181
|
+
kuzu_destroy_string( err_detail );
|
182
|
+
kuzu_query_result_destroy( &result );
|
183
|
+
|
184
|
+
rb_raise( rkuzu_eQueryError, "%s", errmsg );
|
185
|
+
}
|
186
|
+
|
187
|
+
return *qcall.result;
|
188
|
+
}
|
189
|
+
|
190
|
+
|
191
|
+
|
192
|
+
static VALUE
|
193
|
+
rkuzu_connection__query( VALUE self, VALUE query )
|
194
|
+
{
|
195
|
+
kuzu_query_result result = rkuzu_connection_do_query( self, query );
|
196
|
+
return rkuzu_result_from_query( rkuzu_cKuzuResult, self, query, result );
|
197
|
+
}
|
198
|
+
|
199
|
+
|
200
|
+
/*
|
201
|
+
* call-seq:
|
202
|
+
* connection.query!( query_string )
|
203
|
+
*
|
204
|
+
* Execute the given +query_string+ and return `true` if the query was
|
205
|
+
* successful.
|
206
|
+
*
|
207
|
+
*/
|
208
|
+
static VALUE
|
209
|
+
rkuzu_connection_query_bang( VALUE self, VALUE query )
|
210
|
+
{
|
211
|
+
kuzu_query_result result = rkuzu_connection_do_query( self, query );
|
212
|
+
return kuzu_query_result_is_success( &result ) ? Qtrue : Qfalse;
|
213
|
+
}
|
214
|
+
|
215
|
+
|
216
|
+
/*
|
217
|
+
* call-seq:
|
218
|
+
* connection.max_num_threads_for_exec -> integer
|
219
|
+
*
|
220
|
+
* Returns the maximum number of threads of the connection to use for
|
221
|
+
* executing queries.
|
222
|
+
*
|
223
|
+
*/
|
224
|
+
static VALUE
|
225
|
+
rkuzu_connection_max_num_threads_for_exec( VALUE self )
|
226
|
+
{
|
227
|
+
rkuzu_connection *ptr = CHECK_CONNECTION( self );
|
228
|
+
uint64_t count;
|
229
|
+
|
230
|
+
if ( kuzu_connection_get_max_num_thread_for_exec( &ptr->conn, &count ) != KuzuSuccess ) {
|
231
|
+
rb_raise( rkuzu_eError, "kuzu_connection_get_max_num_thread_for_exec failed" );
|
232
|
+
}
|
233
|
+
|
234
|
+
return ULONG2NUM( count );
|
235
|
+
}
|
236
|
+
|
237
|
+
|
238
|
+
/*
|
239
|
+
* call-seq:
|
240
|
+
* connection.max_num_threads_for_exec = integer
|
241
|
+
*
|
242
|
+
* Sets the maximum number of threads of the connection to use for
|
243
|
+
* executing queries.
|
244
|
+
*
|
245
|
+
*/
|
246
|
+
static VALUE
|
247
|
+
rkuzu_connection_max_num_threads_for_exec_eq( VALUE self, VALUE count )
|
248
|
+
{
|
249
|
+
rkuzu_connection *ptr = CHECK_CONNECTION( self );
|
250
|
+
uint64_t thread_count = NUM2ULONG( count );
|
251
|
+
|
252
|
+
if ( kuzu_connection_set_max_num_thread_for_exec( &ptr->conn, thread_count ) != KuzuSuccess ) {
|
253
|
+
rb_raise( rkuzu_eError, "kuzu_connection_set_max_num_thread_for_exec failed" );
|
254
|
+
}
|
255
|
+
|
256
|
+
return Qtrue;
|
257
|
+
}
|
258
|
+
|
259
|
+
|
260
|
+
/*
|
261
|
+
* call-seq:
|
262
|
+
* connection.query_timeout = integer
|
263
|
+
*
|
264
|
+
* Sets query timeout value in milliseconds for the connection.
|
265
|
+
*
|
266
|
+
*/
|
267
|
+
static VALUE
|
268
|
+
rkuzu_connection_query_timeout_eq( VALUE self, VALUE timeout )
|
269
|
+
{
|
270
|
+
rkuzu_connection *ptr = CHECK_CONNECTION( self );
|
271
|
+
uint64_t timeout_in_ms = NUM2ULONG( timeout );
|
272
|
+
|
273
|
+
if ( kuzu_connection_set_query_timeout( &ptr->conn, timeout_in_ms ) != KuzuSuccess ) {
|
274
|
+
rb_raise( rkuzu_eError, "kuzu_connection_set_query_timeout failed" );
|
275
|
+
}
|
276
|
+
|
277
|
+
return Qtrue;
|
278
|
+
}
|
279
|
+
|
280
|
+
|
281
|
+
|
282
|
+
/*
|
283
|
+
* Document-class: Kuzu::Connection
|
284
|
+
*/
|
285
|
+
void
|
286
|
+
rkuzu_init_connection( void )
|
287
|
+
{
|
288
|
+
#ifdef FOR_RDOC
|
289
|
+
rkuzu_mKuzu = rb_define_module( "Kuzu" );
|
290
|
+
#endif
|
291
|
+
|
292
|
+
rkuzu_cKuzuConnection = rb_define_class_under( rkuzu_mKuzu, "Connection", rb_cObject );
|
293
|
+
|
294
|
+
rb_define_alloc_func( rkuzu_cKuzuConnection, rkuzu_connection_s_allocate );
|
295
|
+
|
296
|
+
rb_define_protected_method( rkuzu_cKuzuConnection, "initialize", rkuzu_connection_initialize, 1 );
|
297
|
+
|
298
|
+
rb_define_protected_method( rkuzu_cKuzuConnection, "_query", rkuzu_connection__query, 1 );
|
299
|
+
rb_define_method( rkuzu_cKuzuConnection, "query!", rkuzu_connection_query_bang, 1 );
|
300
|
+
rb_define_alias( rkuzu_cKuzuConnection, "run", "query!" );
|
301
|
+
|
302
|
+
rb_define_method( rkuzu_cKuzuConnection, "max_num_threads_for_exec",
|
303
|
+
rkuzu_connection_max_num_threads_for_exec, 0 );
|
304
|
+
rb_define_method( rkuzu_cKuzuConnection, "max_num_threads_for_exec=",
|
305
|
+
rkuzu_connection_max_num_threads_for_exec_eq, 1 );
|
306
|
+
|
307
|
+
rb_define_method( rkuzu_cKuzuConnection, "query_timeout=", rkuzu_connection_query_timeout_eq, 1 );
|
308
|
+
|
309
|
+
rb_require( "kuzu/connection" );
|
310
|
+
}
|
@@ -0,0 +1,196 @@
|
|
1
|
+
/*
|
2
|
+
* database.c - Kuzu::Database class
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "kuzu_ext.h"
|
6
|
+
|
7
|
+
#define CHECK_DATABASE(self) ((rkuzu_database*)rb_check_typeddata((self), &rkuzu_database_type))
|
8
|
+
// #define DEBUG_GC(msg, ptr) fprintf( stderr, msg, ptr )
|
9
|
+
#define DEBUG_GC(msg, ptr)
|
10
|
+
|
11
|
+
|
12
|
+
VALUE rkuzu_cKuzuDatabase;
|
13
|
+
|
14
|
+
static void rkuzu_database_free( void * );
|
15
|
+
static void rkuzu_database_mark( void * );
|
16
|
+
|
17
|
+
static const rb_data_type_t rkuzu_database_type = {
|
18
|
+
.wrap_struct_name = "Kuzu::Database",
|
19
|
+
.function = {
|
20
|
+
.dmark = rkuzu_database_mark,
|
21
|
+
.dfree = rkuzu_database_free,
|
22
|
+
},
|
23
|
+
.data = NULL,
|
24
|
+
};
|
25
|
+
|
26
|
+
|
27
|
+
rkuzu_database *
|
28
|
+
rkuzu_get_database( VALUE obj )
|
29
|
+
{
|
30
|
+
return CHECK_DATABASE( obj );
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
/*
|
35
|
+
* Struct allocation/init function.
|
36
|
+
*/
|
37
|
+
static rkuzu_database *
|
38
|
+
rkuzu_database_alloc( void )
|
39
|
+
{
|
40
|
+
rkuzu_database *ptr = ALLOC( rkuzu_database );
|
41
|
+
|
42
|
+
ptr->path = Qnil;
|
43
|
+
ptr->config = Qnil;
|
44
|
+
|
45
|
+
return ptr;
|
46
|
+
}
|
47
|
+
|
48
|
+
|
49
|
+
/*
|
50
|
+
* Free function
|
51
|
+
*/
|
52
|
+
static void
|
53
|
+
rkuzu_database_free( void *ptr )
|
54
|
+
{
|
55
|
+
if ( ptr ) {
|
56
|
+
DEBUG_GC( ">>> freeing database %p\n", ptr );
|
57
|
+
rkuzu_database *database_s = (rkuzu_database *)ptr;
|
58
|
+
|
59
|
+
kuzu_database_destroy( &database_s->db );
|
60
|
+
|
61
|
+
database_s->path = Qnil;
|
62
|
+
database_s->config = Qnil;
|
63
|
+
|
64
|
+
xfree( ptr );
|
65
|
+
ptr = NULL;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
|
69
|
+
|
70
|
+
/*
|
71
|
+
* Mark function
|
72
|
+
*/
|
73
|
+
static void
|
74
|
+
rkuzu_database_mark( void *ptr )
|
75
|
+
{
|
76
|
+
rkuzu_database *database_s = (rkuzu_database *)ptr;
|
77
|
+
|
78
|
+
DEBUG_GC( ">>> marking database %p\n", ptr );
|
79
|
+
|
80
|
+
rb_gc_mark( database_s->path );
|
81
|
+
rb_gc_mark( database_s->config );
|
82
|
+
}
|
83
|
+
|
84
|
+
|
85
|
+
|
86
|
+
/*
|
87
|
+
* ::allocate function
|
88
|
+
*/
|
89
|
+
static VALUE
|
90
|
+
rkuzu_database_s_allocate( VALUE klass )
|
91
|
+
{
|
92
|
+
return TypedData_Wrap_Struct( klass, &rkuzu_database_type, NULL );
|
93
|
+
}
|
94
|
+
|
95
|
+
|
96
|
+
/*
|
97
|
+
* call-seq:
|
98
|
+
* database.new( path, **options ) -> database
|
99
|
+
*
|
100
|
+
* Create a new Datbase using the given +path+ and +options+.
|
101
|
+
*
|
102
|
+
*/
|
103
|
+
static VALUE
|
104
|
+
rkuzu_database_initialize( int argc, VALUE *argv, VALUE self )
|
105
|
+
{
|
106
|
+
rkuzu_database *ptr = CHECK_DATABASE( self );
|
107
|
+
|
108
|
+
if ( !ptr ) {
|
109
|
+
VALUE path, options, config;
|
110
|
+
VALUE config_argv[1];
|
111
|
+
kuzu_system_config *sysconfig;
|
112
|
+
char *database_path;
|
113
|
+
|
114
|
+
rb_scan_args( argc, argv, "1:", &path, &options );
|
115
|
+
config_argv[0] = options;
|
116
|
+
config = rb_funcallv_public_kw( rkuzu_cKuzuConfig, rb_intern("from_options"), 1,
|
117
|
+
config_argv, RB_PASS_KEYWORDS );
|
118
|
+
|
119
|
+
sysconfig = rkuzu_get_config( config );
|
120
|
+
database_path = StringValueCStr( path );
|
121
|
+
|
122
|
+
ptr = rkuzu_database_alloc();
|
123
|
+
if ( kuzu_database_init(database_path, *sysconfig, &ptr->db) != KuzuSuccess ) {
|
124
|
+
xfree( ptr );
|
125
|
+
ptr = NULL;
|
126
|
+
|
127
|
+
rb_raise( rkuzu_eDatabaseError, "Couldn't create database!" );
|
128
|
+
}
|
129
|
+
|
130
|
+
DEBUG_GC( ">>> allocated database %p\n", ptr );
|
131
|
+
RTYPEDDATA_DATA( self ) = ptr;
|
132
|
+
|
133
|
+
ptr->path = rb_obj_freeze( rb_obj_dup(path) );
|
134
|
+
ptr->config = rb_obj_freeze( config );
|
135
|
+
} else {
|
136
|
+
rb_raise( rb_eRuntimeError, "cannot reinit database" );
|
137
|
+
}
|
138
|
+
|
139
|
+
rb_call_super( 0, 0 );
|
140
|
+
|
141
|
+
return Qtrue;
|
142
|
+
}
|
143
|
+
|
144
|
+
|
145
|
+
/*
|
146
|
+
* call-seq:
|
147
|
+
* database.config() -> config
|
148
|
+
*
|
149
|
+
* Return the Kuzu::Config that reflects the config options the database
|
150
|
+
* was created with.
|
151
|
+
*
|
152
|
+
*/
|
153
|
+
static VALUE
|
154
|
+
rkuzu_database_config( VALUE self )
|
155
|
+
{
|
156
|
+
rkuzu_database *ptr = CHECK_DATABASE( self );
|
157
|
+
return ptr->config;
|
158
|
+
}
|
159
|
+
|
160
|
+
|
161
|
+
|
162
|
+
/*
|
163
|
+
* call-seq:
|
164
|
+
* database.path() -> string or nil
|
165
|
+
*
|
166
|
+
* Return the path the database was created with, or +nil+ if it was
|
167
|
+
* created in memory.
|
168
|
+
*
|
169
|
+
*/
|
170
|
+
static VALUE
|
171
|
+
rkuzu_database_path( VALUE self )
|
172
|
+
{
|
173
|
+
rkuzu_database *ptr = CHECK_DATABASE( self );
|
174
|
+
|
175
|
+
if ( RSTRING_LEN(ptr->path) == 0 ) {
|
176
|
+
return Qnil;
|
177
|
+
} else {
|
178
|
+
return ptr->path;
|
179
|
+
}
|
180
|
+
}
|
181
|
+
|
182
|
+
|
183
|
+
void
|
184
|
+
rkuzu_init_database( void )
|
185
|
+
{
|
186
|
+
rkuzu_cKuzuDatabase = rb_define_class_under( rkuzu_mKuzu, "Database", rb_cObject );
|
187
|
+
|
188
|
+
rb_define_alloc_func( rkuzu_cKuzuDatabase, rkuzu_database_s_allocate );
|
189
|
+
|
190
|
+
rb_define_method( rkuzu_cKuzuDatabase, "initialize", rkuzu_database_initialize, -1 );
|
191
|
+
|
192
|
+
rb_define_method( rkuzu_cKuzuDatabase, "config", rkuzu_database_config, 0 );
|
193
|
+
rb_define_method( rkuzu_cKuzuDatabase, "path", rkuzu_database_path, 0 );
|
194
|
+
|
195
|
+
rb_require( "kuzu/database" );
|
196
|
+
}
|
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rbconfig'
|
4
|
+
require 'mkmf'
|
5
|
+
|
6
|
+
dir_config( 'libkuzu' )
|
7
|
+
|
8
|
+
have_library( 'kuzu' ) or
|
9
|
+
abort "No kuzu library!"
|
10
|
+
|
11
|
+
have_header( 'kuzu.h' ) or
|
12
|
+
abort "No kuzu.h header!"
|
13
|
+
have_header( 'ruby/thread.h' ) or
|
14
|
+
abort "Your Ruby is too old!"
|
15
|
+
|
16
|
+
have_func( 'kuzu_database_init', 'kuzu.h' )
|
17
|
+
|
18
|
+
create_header()
|
19
|
+
create_makefile( 'kuzu_ext' )
|
20
|
+
|
@@ -0,0 +1,158 @@
|
|
1
|
+
/*
|
2
|
+
* kuzu_ext.c - Ruby binding for Kùzu
|
3
|
+
*
|
4
|
+
* Authors:
|
5
|
+
* * Michael Granger <ged@FaerieMUD.org>
|
6
|
+
*
|
7
|
+
* Refs:
|
8
|
+
* - https://docs.kuzudb.com/
|
9
|
+
*
|
10
|
+
*/
|
11
|
+
|
12
|
+
#include "kuzu_ext.h"
|
13
|
+
|
14
|
+
VALUE rkuzu_mKuzu;
|
15
|
+
|
16
|
+
VALUE rkuzu_eError;
|
17
|
+
VALUE rkuzu_eDatabaseError;
|
18
|
+
VALUE rkuzu_eConnectionError;
|
19
|
+
VALUE rkuzu_eQueryError;
|
20
|
+
VALUE rkuzu_eFinishedError;
|
21
|
+
|
22
|
+
VALUE rkuzu_rb_cDate;
|
23
|
+
VALUE rkuzu_rb_cOstruct;
|
24
|
+
|
25
|
+
|
26
|
+
/* --------------------------------------------------------------
|
27
|
+
* Logging Functions
|
28
|
+
* -------------------------------------------------------------- */
|
29
|
+
|
30
|
+
/*
|
31
|
+
* Log a message to the given +context+ object's logger.
|
32
|
+
*/
|
33
|
+
void
|
34
|
+
#if HAVE_STDARG_PROTOTYPES
|
35
|
+
rkuzu_log_obj( VALUE context, const char *level, const char *fmt, ... )
|
36
|
+
#else
|
37
|
+
rkuzu_log_obj( VALUE context, const char *level, const char *fmt, va_dcl )
|
38
|
+
#endif
|
39
|
+
{
|
40
|
+
char buf[BUFSIZ];
|
41
|
+
va_list args;
|
42
|
+
VALUE logger = Qnil;
|
43
|
+
VALUE message = Qnil;
|
44
|
+
|
45
|
+
va_init_list( args, fmt );
|
46
|
+
vsnprintf( buf, BUFSIZ, fmt, args );
|
47
|
+
message = rb_str_new2( buf );
|
48
|
+
|
49
|
+
logger = rb_funcall( context, rb_intern("log"), 0 );
|
50
|
+
rb_funcall( logger, rb_intern(level), 1, message );
|
51
|
+
|
52
|
+
va_end( args );
|
53
|
+
}
|
54
|
+
|
55
|
+
|
56
|
+
/*
|
57
|
+
* Log a message to the global logger.
|
58
|
+
*/
|
59
|
+
void
|
60
|
+
#if HAVE_STDARG_PROTOTYPES
|
61
|
+
rkuzu_log( const char *level, const char *fmt, ... )
|
62
|
+
#else
|
63
|
+
rkuzu_log( const char *level, const char *fmt, va_dcl )
|
64
|
+
#endif
|
65
|
+
{
|
66
|
+
char buf[BUFSIZ];
|
67
|
+
va_list args;
|
68
|
+
VALUE logger = Qnil;
|
69
|
+
VALUE message = Qnil;
|
70
|
+
|
71
|
+
va_init_list( args, fmt );
|
72
|
+
vsnprintf( buf, BUFSIZ, fmt, args );
|
73
|
+
message = rb_str_new2( buf );
|
74
|
+
|
75
|
+
logger = rb_funcall( rkuzu_mKuzu, rb_intern("logger"), 0 );
|
76
|
+
rb_funcall( logger, rb_intern(level), 1, message );
|
77
|
+
|
78
|
+
va_end( args );
|
79
|
+
}
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
/* --------------------------------------------------------------
|
84
|
+
* Module methods
|
85
|
+
* -------------------------------------------------------------- */
|
86
|
+
|
87
|
+
/*
|
88
|
+
* call-seq:
|
89
|
+
* Kuzu.kuzu_version -> string
|
90
|
+
*
|
91
|
+
* Return the version of the underlying Kuzu library.
|
92
|
+
*
|
93
|
+
*/
|
94
|
+
static VALUE
|
95
|
+
rkuzu_s_kuzu_version( VALUE _ )
|
96
|
+
{
|
97
|
+
const char *version = kuzu_get_version();
|
98
|
+
|
99
|
+
return rb_str_new2( version );
|
100
|
+
}
|
101
|
+
|
102
|
+
|
103
|
+
/*
|
104
|
+
* call-seq:
|
105
|
+
* Kuzu.storage_version -> integer
|
106
|
+
*
|
107
|
+
* Return the storage version used by the underlying library.
|
108
|
+
*
|
109
|
+
*/
|
110
|
+
static VALUE
|
111
|
+
rkuzu_s_storage_version( VALUE _ )
|
112
|
+
{
|
113
|
+
const unsigned long long version = kuzu_get_storage_version();
|
114
|
+
|
115
|
+
return ULONG2NUM( version );
|
116
|
+
}
|
117
|
+
|
118
|
+
|
119
|
+
/*
|
120
|
+
* Kuzu extension init function
|
121
|
+
*/
|
122
|
+
void
|
123
|
+
Init_kuzu_ext( void )
|
124
|
+
{
|
125
|
+
rb_require( "date" );
|
126
|
+
rkuzu_rb_cDate = rb_const_get( rb_cObject, rb_intern("Date") );
|
127
|
+
|
128
|
+
rb_require( "ostruct" );
|
129
|
+
rkuzu_rb_cOstruct = rb_const_get( rb_cObject, rb_intern("OpenStruct") );
|
130
|
+
|
131
|
+
/*
|
132
|
+
* Document-module: Kuzu
|
133
|
+
*
|
134
|
+
* The top level namespace for Kuzu classes.
|
135
|
+
*/
|
136
|
+
rkuzu_mKuzu = rb_define_module( "Kuzu" );
|
137
|
+
|
138
|
+
rb_define_singleton_method( rkuzu_mKuzu, "kuzu_version", rkuzu_s_kuzu_version, 0 );
|
139
|
+
rb_define_singleton_method( rkuzu_mKuzu, "storage_version", rkuzu_s_storage_version, 0 );
|
140
|
+
|
141
|
+
rkuzu_eError = rb_define_class_under( rkuzu_mKuzu, "Error", rb_eRuntimeError );
|
142
|
+
rkuzu_eDatabaseError = rb_define_class_under( rkuzu_mKuzu, "DatabaseError", rkuzu_eError );
|
143
|
+
rkuzu_eConnectionError = rb_define_class_under( rkuzu_mKuzu, "ConnectionError", rkuzu_eError );
|
144
|
+
rkuzu_eQueryError = rb_define_class_under( rkuzu_mKuzu, "QueryError", rkuzu_eError );
|
145
|
+
rkuzu_eFinishedError = rb_define_class_under( rkuzu_mKuzu, "FinishedError", rkuzu_eError );
|
146
|
+
|
147
|
+
rb_require( "kuzu" );
|
148
|
+
|
149
|
+
rkuzu_init_database();
|
150
|
+
rkuzu_init_config();
|
151
|
+
rkuzu_init_connection();
|
152
|
+
rkuzu_init_prepared_statement();
|
153
|
+
rkuzu_init_result();
|
154
|
+
rkuzu_init_query_summary();
|
155
|
+
rkuzu_init_node();
|
156
|
+
rkuzu_init_rel();
|
157
|
+
rkuzu_init_recursive_rel();
|
158
|
+
}
|