extralite-bundle 2.3 → 2.4

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.
@@ -1,11 +1,14 @@
1
1
  #include <stdio.h>
2
+ #include <stdlib.h>
2
3
  #include "extralite.h"
3
4
 
4
5
  VALUE cDatabase;
6
+ VALUE cBlob;
5
7
  VALUE cError;
6
8
  VALUE cSQLError;
7
9
  VALUE cBusyError;
8
10
  VALUE cInterruptError;
11
+ VALUE cParameterError;
9
12
  VALUE eArgumentError;
10
13
 
11
14
  ID ID_bind;
@@ -13,7 +16,6 @@ ID ID_call;
13
16
  ID ID_keys;
14
17
  ID ID_new;
15
18
  ID ID_strip;
16
- ID ID_to_s;
17
19
 
18
20
  VALUE SYM_read_only;
19
21
 
@@ -21,6 +23,11 @@ static size_t Database_size(const void *ptr) {
21
23
  return sizeof(Database_t);
22
24
  }
23
25
 
26
+ static void Database_mark(void *ptr) {
27
+ Database_t *db = ptr;
28
+ rb_gc_mark(db->trace_block);
29
+ }
30
+
24
31
  static void Database_free(void *ptr) {
25
32
  Database_t *db = ptr;
26
33
  if (db->sqlite3_db) sqlite3_close_v2(db->sqlite3_db);
@@ -29,8 +36,8 @@ static void Database_free(void *ptr) {
29
36
 
30
37
  static const rb_data_type_t Database_type = {
31
38
  "Database",
32
- {0, Database_free, Database_size,},
33
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
39
+ {Database_mark, Database_free, Database_size,},
40
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
34
41
  };
35
42
 
36
43
  static VALUE Database_allocate(VALUE klass) {
@@ -48,7 +55,7 @@ inline Database_t *self_to_database(VALUE self) {
48
55
  inline Database_t *self_to_open_database(VALUE self) {
49
56
  Database_t *db = self_to_database(self);
50
57
  if (!(db)->sqlite3_db) rb_raise(cError, "Database is closed");
51
-
58
+
52
59
  return db;
53
60
  }
54
61
 
@@ -118,6 +125,7 @@ VALUE Database_initialize(int argc, VALUE *argv, VALUE self) {
118
125
  #endif
119
126
 
120
127
  db->trace_block = Qnil;
128
+ db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD;
121
129
 
122
130
  return Qnil;
123
131
  }
@@ -178,8 +186,8 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA
178
186
  RB_GC_GUARD(sql);
179
187
 
180
188
  bind_all_parameters(stmt, argc - 1, argv + 1);
181
- query_ctx ctx = { self, db->sqlite3_db, stmt, Qnil, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
182
-
189
+ query_ctx ctx = QUERY_CTX(self, db, stmt, Qnil, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS);
190
+
183
191
  return rb_ensure(SAFE(call), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
184
192
  }
185
193
 
@@ -190,18 +198,18 @@ static inline VALUE Database_perform_query(int argc, VALUE *argv, VALUE self, VA
190
198
  * Runs a query returning rows as hashes (with symbol keys). If a block is
191
199
  * given, it will be called for each row. Otherwise, an array containing all
192
200
  * rows is returned.
193
- *
201
+ *
194
202
  * Query parameters to be bound to placeholders in the query can be specified as
195
203
  * a list of values or as a hash mapping parameter names to values. When
196
204
  * parameters are given as an array, the query should specify parameters using
197
205
  * `?`:
198
- *
206
+ *
199
207
  * db.query('select * from foo where x = ?', 42)
200
208
  *
201
209
  * Named placeholders are specified using `:`. The placeholder values are
202
210
  * specified using a hash, where keys are either strings are symbols. String
203
211
  * keys can include or omit the `:` prefix. The following are equivalent:
204
- *
212
+ *
205
213
  * db.query('select * from foo where x = :bar', bar: 42)
206
214
  * db.query('select * from foo where x = :bar', 'bar' => 42)
207
215
  * db.query('select * from foo where x = :bar', ':bar' => 42)
@@ -355,7 +363,7 @@ VALUE Database_execute_multi(VALUE self, VALUE sql, VALUE params_array) {
355
363
 
356
364
  // prepare query ctx
357
365
  prepare_single_stmt(db->sqlite3_db, &stmt, sql);
358
- query_ctx ctx = { self, db->sqlite3_db, stmt, params_array, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
366
+ query_ctx ctx = QUERY_CTX(self, db, stmt, params_array, QUERY_MULTI_ROW, ALL_ROWS);
359
367
 
360
368
  return rb_ensure(SAFE(safe_execute_multi), (VALUE)&ctx, SAFE(cleanup_stmt), (VALUE)&ctx);
361
369
  }
@@ -391,10 +399,10 @@ VALUE Database_changes(VALUE self) {
391
399
  return INT2FIX(sqlite3_changes(db->sqlite3_db));
392
400
  }
393
401
 
394
- /* call-seq:
395
- * db.filename -> string
402
+ /* call-seq: db.filename -> string db.filename(db_name) -> string
396
403
  *
397
- * Returns the database filename.
404
+ * Returns the database filename. If db_name is given, returns the filename for
405
+ * the respective attached database.
398
406
  */
399
407
  VALUE Database_filename(int argc, VALUE *argv, VALUE self) {
400
408
  const char *db_name;
@@ -480,13 +488,13 @@ typedef struct {
480
488
  #define BACKUP_STEP_MAX_PAGES 16
481
489
  #define BACKUP_SLEEP_MS 100
482
490
 
483
- void *backup_step_without_gvl(void *ptr) {
491
+ void *backup_step_impl(void *ptr) {
484
492
  backup_ctx *ctx = (backup_ctx *)ptr;
485
493
  ctx->rc = sqlite3_backup_step(ctx->backup, BACKUP_STEP_MAX_PAGES);
486
494
  return NULL;
487
495
  }
488
496
 
489
- void *backup_sleep_without_gvl(void *unused) {
497
+ void *backup_sleep_impl(void *unused) {
490
498
  sqlite3_sleep(BACKUP_SLEEP_MS);
491
499
  return NULL;
492
500
  }
@@ -496,7 +504,7 @@ VALUE backup_safe_iterate(VALUE ptr) {
496
504
  int done = 0;
497
505
 
498
506
  while (!done) {
499
- rb_thread_call_without_gvl(backup_step_without_gvl, (void *)ctx, RUBY_UBF_IO, 0);
507
+ gvl_call(GVL_RELEASE, backup_step_impl, (void *)ctx);
500
508
  switch(ctx->rc) {
501
509
  case SQLITE_DONE:
502
510
  if (ctx->block_given) {
@@ -514,7 +522,7 @@ VALUE backup_safe_iterate(VALUE ptr) {
514
522
  continue;
515
523
  case SQLITE_BUSY:
516
524
  case SQLITE_LOCKED:
517
- rb_thread_call_without_gvl(backup_sleep_without_gvl, NULL, RUBY_UBF_IO, 0);
525
+ gvl_call(GVL_RELEASE, backup_sleep_impl, NULL);
518
526
  continue;
519
527
  default:
520
528
  rb_raise(cError, "%s", sqlite3_errstr(ctx->rc));
@@ -689,7 +697,7 @@ VALUE Database_total_changes(VALUE self) {
689
697
  VALUE Database_trace(VALUE self) {
690
698
  Database_t *db = self_to_open_database(self);
691
699
 
692
- db->trace_block = rb_block_given_p() ? rb_block_proc() : Qnil;
700
+ RB_OBJ_WRITE(self, &db->trace_block, rb_block_given_p() ? rb_block_proc() : Qnil);
693
701
  return self;
694
702
  }
695
703
 
@@ -734,11 +742,51 @@ VALUE Database_error_offset(VALUE self) {
734
742
  * @return [String] string representation
735
743
  */
736
744
  VALUE Database_inspect(VALUE self) {
745
+ Database_t *db = self_to_database(self);
737
746
  VALUE cname = rb_class_name(CLASS_OF(self));
738
- VALUE filename = Database_filename(0, NULL, self);
739
- if (RSTRING_LEN(filename) == 0) filename = rb_str_new_literal(":memory:");
740
747
 
741
- return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, filename);
748
+ if (!(db)->sqlite3_db)
749
+ return rb_sprintf("#<%"PRIsVALUE":%p (closed)>", cname, (void*)self);
750
+ else {
751
+ VALUE filename = Database_filename(0, NULL, self);
752
+ if (RSTRING_LEN(filename) == 0) filename = rb_str_new_literal(":memory:");
753
+ return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, filename);
754
+ }
755
+ }
756
+
757
+ /* Returns the database's GVL release threshold.
758
+ *
759
+ * @return [Integer] GVL release threshold
760
+ */
761
+ VALUE Database_gvl_release_threshold_get(VALUE self) {
762
+ Database_t *db = self_to_open_database(self);
763
+ return INT2NUM(db->gvl_release_threshold);
764
+ }
765
+
766
+ /* Sets the database's GVL release threshold. To always hold the GVL while
767
+ * running a query, set the threshold to 0. To release the GVL on each record,
768
+ * set the threshold to 1. Larger values mean the GVL will be released less
769
+ * often, e.g. a value of 10 means the GVL will be released every 10 records
770
+ * iterated. A value of nil sets the threshold to the default value, which is
771
+ * currently 1000.
772
+ *
773
+ * @return [Integer, nil] New GVL release threshold
774
+ */
775
+ VALUE Database_gvl_release_threshold_set(VALUE self, VALUE value) {
776
+ Database_t *db = self_to_open_database(self);
777
+
778
+ switch (TYPE(value)) {
779
+ case T_FIXNUM:
780
+ db->gvl_release_threshold = NUM2INT(value);
781
+ break;
782
+ case T_NIL:
783
+ db->gvl_release_threshold = DEFAULT_GVL_RELEASE_THRESHOLD;
784
+ break;
785
+ default:
786
+ rb_raise(eArgumentError, "Invalid GVL release threshold value (expect integer or nil)");
787
+ }
788
+
789
+ return INT2NUM(db->gvl_release_threshold);
742
790
  }
743
791
 
744
792
  void Init_ExtraliteDatabase(void) {
@@ -765,6 +813,8 @@ void Init_ExtraliteDatabase(void) {
765
813
  rb_define_method(cDatabase, "execute", Database_execute, -1);
766
814
  rb_define_method(cDatabase, "execute_multi", Database_execute_multi, 2);
767
815
  rb_define_method(cDatabase, "filename", Database_filename, -1);
816
+ rb_define_method(cDatabase, "gvl_release_threshold", Database_gvl_release_threshold_get, 0);
817
+ rb_define_method(cDatabase, "gvl_release_threshold=", Database_gvl_release_threshold_set, 1);
768
818
  rb_define_method(cDatabase, "initialize", Database_initialize, -1);
769
819
  rb_define_method(cDatabase, "inspect", Database_inspect, 0);
770
820
  rb_define_method(cDatabase, "interrupt", Database_interrupt, 0);
@@ -787,14 +837,13 @@ void Init_ExtraliteDatabase(void) {
787
837
  rb_define_method(cDatabase, "load_extension", Database_load_extension, 1);
788
838
  #endif
789
839
 
840
+ cBlob = rb_define_class_under(mExtralite, "Blob", rb_cString);
841
+
790
842
  cError = rb_define_class_under(mExtralite, "Error", rb_eStandardError);
791
843
  cSQLError = rb_define_class_under(mExtralite, "SQLError", cError);
792
844
  cBusyError = rb_define_class_under(mExtralite, "BusyError", cError);
793
845
  cInterruptError = rb_define_class_under(mExtralite, "InterruptError", cError);
794
- rb_gc_register_mark_object(cError);
795
- rb_gc_register_mark_object(cSQLError);
796
- rb_gc_register_mark_object(cBusyError);
797
- rb_gc_register_mark_object(cInterruptError);
846
+ cParameterError = rb_define_class_under(mExtralite, "ParameterError", cError);
798
847
 
799
848
  eArgumentError = rb_const_get(rb_cObject, rb_intern("ArgumentError"));
800
849
 
@@ -803,7 +852,6 @@ void Init_ExtraliteDatabase(void) {
803
852
  ID_keys = rb_intern("keys");
804
853
  ID_new = rb_intern("new");
805
854
  ID_strip = rb_intern("strip");
806
- ID_to_s = rb_intern("to_s");
807
855
 
808
856
  SYM_read_only = ID2SYM(rb_intern("read_only"));
809
857
  rb_gc_register_mark_object(SYM_read_only);
@@ -23,17 +23,18 @@
23
23
  extern VALUE cDatabase;
24
24
  extern VALUE cQuery;
25
25
  extern VALUE cIterator;
26
+ extern VALUE cBlob;
26
27
 
27
28
  extern VALUE cError;
28
29
  extern VALUE cSQLError;
29
30
  extern VALUE cBusyError;
30
31
  extern VALUE cInterruptError;
32
+ extern VALUE cParameterError;
31
33
 
32
34
  extern ID ID_call;
33
35
  extern ID ID_keys;
34
36
  extern ID ID_new;
35
37
  extern ID ID_strip;
36
- extern ID ID_to_s;
37
38
 
38
39
  extern VALUE SYM_hash;
39
40
  extern VALUE SYM_ary;
@@ -42,6 +43,7 @@ extern VALUE SYM_single_column;
42
43
  typedef struct {
43
44
  sqlite3 *sqlite3_db;
44
45
  VALUE trace_block;
46
+ int gvl_release_threshold;
45
47
  } Database_t;
46
48
 
47
49
  typedef struct {
@@ -79,19 +81,22 @@ typedef struct {
79
81
  enum query_mode mode;
80
82
  int max_rows;
81
83
  int eof;
84
+ int gvl_release_threshold;
85
+ int step_count;
82
86
  } query_ctx;
83
87
 
84
- typedef struct {
85
- VALUE dst;
86
- VALUE src;
87
- sqlite3_backup *p;
88
- } backup_t;
88
+ enum gvl_mode {
89
+ GVL_RELEASE,
90
+ GVL_HOLD
91
+ };
89
92
 
90
- #define TUPLE_MAX_EMBEDDED_VALUES 20
91
93
  #define ALL_ROWS -1
92
94
  #define SINGLE_ROW -2
93
95
  #define QUERY_MODE(default) (rb_block_given_p() ? QUERY_YIELD : default)
94
96
  #define MULTI_ROW_P(mode) (mode == QUERY_MULTI_ROW)
97
+ #define QUERY_CTX(self, db, stmt, params, mode, max_rows) \
98
+ { self, db->sqlite3_db, stmt, params, mode, max_rows, 0, db->gvl_release_threshold, 0 }
99
+ #define DEFAULT_GVL_RELEASE_THRESHOLD 1000
95
100
 
96
101
  extern rb_encoding *UTF8_ENCODING;
97
102
 
@@ -126,4 +131,6 @@ VALUE cleanup_stmt(query_ctx *ctx);
126
131
  sqlite3 *Database_sqlite3_db(VALUE self);
127
132
  Database_t *self_to_database(VALUE self);
128
133
 
129
- #endif /* EXTRALITE_H */
134
+ void *gvl_call(enum gvl_mode mode, void *(*fn)(void *), void *data);
135
+
136
+ #endif /* EXTRALITE_H */
@@ -52,7 +52,7 @@ static inline enum iterator_mode symbol_to_mode(VALUE sym) {
52
52
  * iteration mode is one of: `:hash`, `:ary`, or `:single_column`. An iterator
53
53
  * is normally returned from one of the methods `Query#each`/`Query#each_hash`,
54
54
  * `Query#each_ary` or `Query#each_single_column` when called without a block:
55
- *
55
+ *
56
56
  * iterator = query.each
57
57
  * ...
58
58
  *
@@ -115,12 +115,12 @@ inline next_method mode_to_next_method(enum iterator_mode mode) {
115
115
 
116
116
  /* Returns the next 1 or more rows from the associated query's result set
117
117
  * according to the iteration mode, i.e. as a hash, an array or a single value.
118
- *
118
+ *
119
119
  * If no row count is given, a single row is returned. If a row count is given,
120
120
  * an array containing up to the `row_count` rows is returned. If `row_count` is
121
121
  * -1, all rows are returned. If the end of the result set has been reached,
122
122
  * `nil` is returned.
123
- *
123
+ *
124
124
  * If a block is given, rows are passed to the block and self is returned.
125
125
  *
126
126
  * @overload next()
@@ -152,7 +152,7 @@ inline to_a_method mode_to_to_a_method(enum iterator_mode mode) {
152
152
 
153
153
  /* Returns all rows from the associated query's result set according to the
154
154
  * iteration mode, i.e. as a hash, an array or a single value.
155
- *
155
+ *
156
156
  * @return [Array] array of query result set rows
157
157
  */
158
158
  VALUE Iterator_to_a(VALUE self) {
@@ -180,7 +180,7 @@ inline VALUE mode_to_symbol(Iterator_t *iterator) {
180
180
  VALUE Iterator_inspect(VALUE self) {
181
181
  VALUE cname = rb_class_name(CLASS_OF(self));
182
182
  VALUE sym = mode_to_symbol(self_to_iterator(self));
183
-
183
+
184
184
  return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, sym);
185
185
  }
186
186
 
@@ -33,7 +33,7 @@ static void Query_free(void *ptr) {
33
33
  static const rb_data_type_t Query_type = {
34
34
  "Query",
35
35
  {Query_mark, Query_free, Query_size,},
36
- 0, 0, RUBY_TYPED_FREE_IMMEDIATELY
36
+ 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED
37
37
  };
38
38
 
39
39
  static VALUE Query_allocate(VALUE klass) {
@@ -67,10 +67,12 @@ VALUE Query_initialize(VALUE self, VALUE db, VALUE sql) {
67
67
  if (!RSTRING_LEN(sql))
68
68
  rb_raise(cError, "Cannot prepare an empty SQL query");
69
69
 
70
+ RB_OBJ_WRITE(self, &query->db, db);
71
+ RB_OBJ_WRITE(self, &query->sql, sql);
72
+
70
73
  query->db = db;
71
74
  query->db_struct = self_to_database(db);
72
75
  query->sqlite3_db = Database_sqlite3_db(db);
73
- query->sql = sql;
74
76
  query->stmt = NULL;
75
77
  query->closed = 0;
76
78
  query->eof = 0;
@@ -134,14 +136,14 @@ VALUE Query_reset(VALUE self) {
134
136
  * Bound parameters can be specified as a list of values or as a hash mapping
135
137
  * parameter names to values. When parameters are given as a splatted array, the
136
138
  * query should specify parameters using `?`:
137
- *
139
+ *
138
140
  * query = db.prepare('select * from foo where x = ?')
139
141
  * query.bind(42)
140
142
  *
141
143
  * Named placeholders are specified using `:`. The placeholder values are
142
144
  * specified using a hash, where keys are either strings are symbols. String
143
145
  * keys can include or omit the `:` prefix. The following are equivalent:
144
- *
146
+ *
145
147
  * query = db.prepare('select * from foo where x = :bar')
146
148
  * query.bind(bar: 42)
147
149
  *
@@ -171,19 +173,18 @@ VALUE Query_eof_p(VALUE self) {
171
173
  static inline VALUE Query_perform_next(VALUE self, int max_rows, VALUE (*call)(query_ctx *)) {
172
174
  Query_t *query = self_to_query(self);
173
175
  if (query->closed) rb_raise(cError, "Query is closed");
174
-
176
+
175
177
  if (!query->stmt) query_reset(query);
176
178
  if (query->eof) return rb_block_given_p() ? self : Qnil;
177
179
 
178
- query_ctx ctx = {
180
+ query_ctx ctx = QUERY_CTX(
179
181
  self,
180
- query->sqlite3_db,
182
+ query->db_struct,
181
183
  query->stmt,
182
184
  Qnil,
183
185
  QUERY_MODE(max_rows == SINGLE_ROW ? QUERY_SINGLE_ROW : QUERY_MULTI_ROW),
184
- MAX_ROWS(max_rows),
185
- 0
186
- };
186
+ MAX_ROWS(max_rows)
187
+ );
187
188
  VALUE result = call(&ctx);
188
189
  query->eof = ctx.eof;
189
190
  return (ctx.mode == QUERY_YIELD) ? self : result;
@@ -193,12 +194,12 @@ static inline VALUE Query_perform_next(VALUE self, int max_rows, VALUE (*call)(q
193
194
 
194
195
  /* Returns the next 1 or more rows from the associated query's result set as a
195
196
  * hash.
196
- *
197
+ *
197
198
  * If no row count is given, a single row is returned. If a row count is given,
198
199
  * an array containing up to the `row_count` rows is returned. If `row_count` is
199
200
  * -1, all rows are returned. If the end of the result set has been reached,
200
201
  * `nil` is returned.
201
- *
202
+ *
202
203
  * If a block is given, rows are passed to the block and self is returned.
203
204
  *
204
205
  * @overload next()
@@ -219,12 +220,12 @@ VALUE Query_next_hash(int argc, VALUE *argv, VALUE self) {
219
220
 
220
221
  /* Returns the next 1 or more rows from the associated query's result set as an
221
222
  * array.
222
- *
223
+ *
223
224
  * If no row count is given, a single row is returned. If a row count is given,
224
225
  * an array containing up to the `row_count` rows is returned. If `row_count` is
225
226
  * -1, all rows are returned. If the end of the result set has been reached,
226
227
  * `nil` is returned.
227
- *
228
+ *
228
229
  * If a block is given, rows are passed to the block and self is returned.
229
230
  *
230
231
  * @overload next_ary()
@@ -241,12 +242,12 @@ VALUE Query_next_ary(int argc, VALUE *argv, VALUE self) {
241
242
  /* Returns the next 1 or more rows from the associated query's result set as an
242
243
  * single values. If the result set contains more than one column an error is
243
244
  * raised.
244
- *
245
+ *
245
246
  * If no row count is given, a single row is returned. If a row count is given,
246
247
  * an array containing up to the `row_count` rows is returned. If `row_count` is
247
248
  * -1, all rows are returned. If the end of the result set has been reached,
248
249
  * `nil` is returned.
249
- *
250
+ *
250
251
  * If a block is given, rows are passed to the block and self is returned.
251
252
  *
252
253
  * @overload next_ary()
@@ -261,7 +262,7 @@ VALUE Query_next_single_column(int argc, VALUE *argv, VALUE self) {
261
262
  }
262
263
 
263
264
  /* Returns all rows in the associated query's result set as hashes.
264
- *
265
+ *
265
266
  * @overload to_a()
266
267
  * @return [Array<Hash>] all rows
267
268
  * @overload to_a_hash
@@ -274,7 +275,7 @@ VALUE Query_to_a_hash(VALUE self) {
274
275
  }
275
276
 
276
277
  /* Returns all rows in the associated query's result set as arrays.
277
- *
278
+ *
278
279
  * @return [Array<Array>] all rows
279
280
  */
280
281
  VALUE Query_to_a_ary(VALUE self) {
@@ -285,7 +286,7 @@ VALUE Query_to_a_ary(VALUE self) {
285
286
 
286
287
  /* Returns all rows in the associated query's result set as single values. If
287
288
  * the result set contains more than one column an error is raised.
288
- *
289
+ *
289
290
  * @return [Array<Object>] all rows
290
291
  */
291
292
  VALUE Query_to_a_single_column(VALUE self) {
@@ -297,7 +298,7 @@ VALUE Query_to_a_single_column(VALUE self) {
297
298
  /* Iterates through the result set, passing each row to the given block as a
298
299
  * hash. If no block is given, returns a `Extralite::Iterator` instance in hash
299
300
  * mode.
300
- *
301
+ *
301
302
  * @return [Extralite::Query, Extralite::Iterator] self or an iterator if no block is given
302
303
  */
303
304
  VALUE Query_each_hash(VALUE self) {
@@ -311,7 +312,7 @@ VALUE Query_each_hash(VALUE self) {
311
312
  /* Iterates through the result set, passing each row to the given block as an
312
313
  * array. If no block is given, returns a `Extralite::Iterator` instance in
313
314
  * array mode.
314
- *
315
+ *
315
316
  * @return [Extralite::Query, Extralite::Iterator] self or an iterator if no block is given
316
317
  */
317
318
  VALUE Query_each_ary(VALUE self) {
@@ -326,7 +327,7 @@ VALUE Query_each_ary(VALUE self) {
326
327
  * single value. If the result set contains more than one column an error is
327
328
  * raised. If no block is given, returns a `Extralite::Iterator` instance in
328
329
  * single column mode.
329
- *
330
+ *
330
331
  * @return [Extralite::Query, Extralite::Iterator] self or an iterator if no block is given
331
332
  */
332
333
  VALUE Query_each_single_column(VALUE self) {
@@ -388,7 +389,14 @@ VALUE Query_execute_multi(VALUE self, VALUE parameters) {
388
389
  if (!query->stmt)
389
390
  prepare_single_stmt(query->sqlite3_db, &query->stmt, query->sql);
390
391
 
391
- query_ctx ctx = { self, query->sqlite3_db, query->stmt, parameters, QUERY_MODE(QUERY_MULTI_ROW), ALL_ROWS };
392
+ query_ctx ctx = QUERY_CTX(
393
+ self,
394
+ query->db_struct,
395
+ query->stmt,
396
+ parameters,
397
+ QUERY_MODE(QUERY_MULTI_ROW),
398
+ ALL_ROWS
399
+ );
392
400
  return safe_execute_multi(&ctx);
393
401
  }
394
402
 
@@ -405,7 +413,7 @@ VALUE Query_database(VALUE self) {
405
413
  }
406
414
 
407
415
  /* Returns the SQL string for the query.
408
- *
416
+ *
409
417
  * @return [String] SQL string
410
418
  */
411
419
  VALUE Query_sql(VALUE self) {
@@ -414,7 +422,7 @@ VALUE Query_sql(VALUE self) {
414
422
  }
415
423
 
416
424
  /* Returns the column names for the query without running it.
417
- *
425
+ *
418
426
  * @return [Array<Symbol>] column names
419
427
  */
420
428
  VALUE Query_columns(VALUE self) {
@@ -424,7 +432,7 @@ VALUE Query_columns(VALUE self) {
424
432
  }
425
433
 
426
434
  /* Closes the query. Attempting to run a closed query will raise an error.
427
- *
435
+ *
428
436
  * @return [Extralite::Query] self
429
437
  */
430
438
  VALUE Query_close(VALUE self) {
@@ -438,7 +446,7 @@ VALUE Query_close(VALUE self) {
438
446
  }
439
447
 
440
448
  /* Returns true if the query is closed.
441
- *
449
+ *
442
450
  * @return [boolean] true if query is closed
443
451
  */
444
452
  VALUE Query_closed_p(VALUE self) {
@@ -449,7 +457,7 @@ VALUE Query_closed_p(VALUE self) {
449
457
  /* Returns the current [status
450
458
  * value](https://sqlite.org/c3ref/c_stmtstatus_counter.html) for the given op.
451
459
  * To reset the value, pass true as reset.
452
- *
460
+ *
453
461
  * @overload status(op)
454
462
  * @param op [Integer] status op
455
463
  * @return [Integer] current status value for the given op
@@ -486,7 +494,7 @@ VALUE Query_inspect(VALUE self) {
486
494
  rb_str_cat2(sql, "...");
487
495
  }
488
496
  sql = rb_funcall(sql, ID_inspect, 0);
489
-
497
+
490
498
  RB_GC_GUARD(sql);
491
499
  return rb_sprintf("#<%"PRIsVALUE":%p %"PRIsVALUE">", cname, (void*)self, sql);
492
500
  }