extralite 2.5 → 2.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/CHANGELOG.md +34 -13
  4. data/Gemfile +4 -0
  5. data/Gemfile-bundle +1 -1
  6. data/LICENSE +1 -1
  7. data/README.md +1059 -247
  8. data/Rakefile +18 -0
  9. data/TODO.md +0 -7
  10. data/examples/kv_store.rb +49 -0
  11. data/examples/multi_fiber.rb +16 -0
  12. data/examples/on_progress.rb +9 -0
  13. data/examples/pubsub_store_polyphony.rb +194 -0
  14. data/examples/pubsub_store_threads.rb +204 -0
  15. data/ext/extralite/changeset.c +463 -0
  16. data/ext/extralite/common.c +177 -91
  17. data/ext/extralite/database.c +745 -276
  18. data/ext/extralite/extconf-bundle.rb +10 -4
  19. data/ext/extralite/extconf.rb +34 -34
  20. data/ext/extralite/extralite.h +104 -47
  21. data/ext/extralite/extralite_ext.c +6 -0
  22. data/ext/extralite/iterator.c +14 -86
  23. data/ext/extralite/query.c +171 -264
  24. data/extralite-bundle.gemspec +1 -1
  25. data/extralite.gemspec +1 -1
  26. data/gemspec.rb +10 -11
  27. data/lib/extralite/version.rb +1 -1
  28. data/lib/extralite.rb +69 -10
  29. data/lib/sequel/adapters/extralite.rb +1 -1
  30. data/test/helper.rb +9 -1
  31. data/test/perf_argv_transform.rb +74 -0
  32. data/test/perf_ary.rb +14 -12
  33. data/test/perf_hash.rb +17 -15
  34. data/test/perf_hash_prepared.rb +58 -0
  35. data/test/perf_hash_transform.rb +66 -0
  36. data/test/perf_polyphony.rb +74 -0
  37. data/test/test_changeset.rb +161 -0
  38. data/test/test_database.rb +720 -104
  39. data/test/test_extralite.rb +2 -2
  40. data/test/test_iterator.rb +28 -13
  41. data/test/test_query.rb +352 -110
  42. data/test/test_sequel.rb +4 -4
  43. metadata +24 -16
  44. data/Gemfile.lock +0 -37
  45. data/test/perf_prepared.rb +0 -64
@@ -162,6 +162,12 @@ static inline VALUE row_to_ary(sqlite3_stmt *stmt, int column_count) {
162
162
  return row;
163
163
  }
164
164
 
165
+ static inline void row_to_argv_values(sqlite3_stmt *stmt, int column_count, VALUE *values) {
166
+ for (int i = 0; i < column_count; i++) {
167
+ values[i] = get_column_value(stmt, i, sqlite3_column_type(stmt, i));
168
+ }
169
+ }
170
+
165
171
  typedef struct {
166
172
  sqlite3 *db;
167
173
  sqlite3_stmt **stmt;
@@ -205,9 +211,9 @@ statements. It will release the GVL while the statements are being prepared and
205
211
  executed. All statements excluding the last one are executed. The last statement
206
212
  is not executed, but instead handed back to the caller for looping over results.
207
213
  */
208
- void prepare_multi_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
214
+ void prepare_multi_stmt(enum gvl_mode mode, sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
209
215
  prepare_stmt_ctx ctx = {db, stmt, RSTRING_PTR(sql), RSTRING_LEN(sql), 0};
210
- gvl_call(GVL_RELEASE, prepare_multi_stmt_impl, (void *)&ctx);
216
+ gvl_call(mode, prepare_multi_stmt_impl, (void *)&ctx);
211
217
  RB_GC_GUARD(sql);
212
218
 
213
219
  switch (ctx.rc) {
@@ -247,9 +253,9 @@ end:
247
253
  return NULL;
248
254
  }
249
255
 
250
- void prepare_single_stmt(sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
256
+ void prepare_single_stmt(enum gvl_mode mode, sqlite3 *db, sqlite3_stmt **stmt, VALUE sql) {
251
257
  prepare_stmt_ctx ctx = {db, stmt, RSTRING_PTR(sql), RSTRING_LEN(sql), 0};
252
- gvl_call(GVL_RELEASE, prepare_single_stmt_impl, (void *)&ctx);
258
+ gvl_call(mode, prepare_single_stmt_impl, (void *)&ctx);
253
259
  RB_GC_GUARD(sql);
254
260
 
255
261
  switch (ctx.rc) {
@@ -315,65 +321,130 @@ VALUE cleanup_stmt(query_ctx *ctx) {
315
321
  return Qnil;
316
322
  }
317
323
 
324
+ VALUE safe_query_argv(query_ctx *ctx);
325
+
318
326
  VALUE safe_query_hash(query_ctx *ctx) {
319
- VALUE array = MULTI_ROW_P(ctx->mode) ? rb_ary_new() : Qnil;
327
+ VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
320
328
  VALUE row = Qnil;
321
329
  int column_count = sqlite3_column_count(ctx->stmt);
322
330
  VALUE column_names = get_column_names(ctx->stmt, column_count);
323
331
  int row_count = 0;
332
+ int do_transform = !NIL_P(ctx->transform_proc);
324
333
 
325
334
  while (stmt_iterate(ctx)) {
326
335
  row = row_to_hash(ctx->stmt, column_count, column_names);
336
+ if (do_transform)
337
+ row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
327
338
  row_count++;
328
- switch (ctx->mode) {
329
- case QUERY_YIELD:
339
+ switch (ctx->row_mode) {
340
+ case ROW_YIELD:
330
341
  rb_yield(row);
331
342
  break;
332
- case QUERY_MULTI_ROW:
343
+ case ROW_MULTI:
333
344
  rb_ary_push(array, row);
334
345
  break;
335
- case QUERY_SINGLE_ROW:
346
+ case ROW_SINGLE:
336
347
  return row;
337
348
  }
338
349
  if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
339
- return MULTI_ROW_P(ctx->mode) ? array : ctx->self;
350
+ return ROW_MULTI_P(ctx->row_mode) ? array : ctx->self;
340
351
  }
341
352
 
342
353
  RB_GC_GUARD(column_names);
343
354
  RB_GC_GUARD(row);
344
355
  RB_GC_GUARD(array);
345
- return MULTI_ROW_P(ctx->mode) ? array : Qnil;
356
+ return ROW_MULTI_P(ctx->row_mode) ? array : Qnil;
357
+ }
358
+
359
+ #define MAX_ARGV_COLUMNS 8
360
+ #define NIL_ARGV_VALUES {Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil, Qnil}
361
+ #define ARGV_GC_GUARD(values) \
362
+ RB_GC_GUARD(values[0]); \
363
+ RB_GC_GUARD(values[1]); \
364
+ RB_GC_GUARD(values[2]); \
365
+ RB_GC_GUARD(values[3]); \
366
+ RB_GC_GUARD(values[4]); \
367
+ RB_GC_GUARD(values[5]); \
368
+ RB_GC_GUARD(values[6]); \
369
+ RB_GC_GUARD(values[7])
370
+
371
+ #define ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, return_rows) \
372
+ row_to_argv_values(ctx->stmt, column_count, argv_values); \
373
+ if (do_transform) \
374
+ row = rb_funcall2(ctx->transform_proc, ID_call, column_count, argv_values); \
375
+ else if (return_rows) \
376
+ row = column_count == 1 ? argv_values[0] : rb_ary_new_from_values(column_count, argv_values);
377
+
378
+ VALUE safe_query_argv(query_ctx *ctx) {
379
+ VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
380
+ VALUE argv_values[MAX_ARGV_COLUMNS] = NIL_ARGV_VALUES;
381
+ VALUE row = Qnil;
382
+ int column_count = sqlite3_column_count(ctx->stmt);
383
+ if (column_count > MAX_ARGV_COLUMNS)
384
+ rb_raise(cError, "Conversion is supported only up to %d columns", MAX_ARGV_COLUMNS);
385
+
386
+ int do_transform = !NIL_P(ctx->transform_proc);
387
+ int return_rows = (ctx->row_mode != ROW_YIELD);
388
+
389
+ int row_count = 0;
390
+ while (stmt_iterate(ctx)) {
391
+ row_count++;
392
+ ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, return_rows);
393
+ switch (ctx->row_mode) {
394
+ case ROW_YIELD:
395
+ if (do_transform)
396
+ rb_yield(row);
397
+ else
398
+ rb_yield_values2(column_count, argv_values);
399
+ break;
400
+ case ROW_MULTI:
401
+ rb_ary_push(array, row);
402
+ break;
403
+ case ROW_SINGLE:
404
+ return row;
405
+ }
406
+ if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
407
+ return ROW_MULTI_P(ctx->row_mode) ? array : ctx->self;
408
+ }
409
+
410
+ ARGV_GC_GUARD(argv_values);
411
+ RB_GC_GUARD(row);
412
+ RB_GC_GUARD(array);
413
+ return ROW_MULTI_P(ctx->row_mode) ? array : Qnil;
346
414
  }
347
415
 
348
416
  VALUE safe_query_ary(query_ctx *ctx) {
349
- VALUE array = MULTI_ROW_P(ctx->mode) ? rb_ary_new() : Qnil;
417
+ VALUE array = ROW_MULTI_P(ctx->row_mode) ? rb_ary_new() : Qnil;
350
418
  VALUE row = Qnil;
351
419
  int column_count = sqlite3_column_count(ctx->stmt);
352
420
  int row_count = 0;
421
+ int do_transform = !NIL_P(ctx->transform_proc);
353
422
 
354
423
  while (stmt_iterate(ctx)) {
355
424
  row = row_to_ary(ctx->stmt, column_count);
425
+ if (do_transform)
426
+ row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
356
427
  row_count++;
357
- switch (ctx->mode) {
358
- case QUERY_YIELD:
428
+ switch (ctx->row_mode) {
429
+ case ROW_YIELD:
359
430
  rb_yield(row);
360
431
  break;
361
- case QUERY_MULTI_ROW:
432
+ case ROW_MULTI:
362
433
  rb_ary_push(array, row);
363
434
  break;
364
- case QUERY_SINGLE_ROW:
435
+ case ROW_SINGLE:
365
436
  return row;
366
437
  }
367
438
  if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
368
- return MULTI_ROW_P(ctx->mode) ? array : ctx->self;
439
+ return ROW_MULTI_P(ctx->row_mode) ? array : ctx->self;
369
440
  }
370
441
 
371
442
  RB_GC_GUARD(row);
372
443
  RB_GC_GUARD(array);
373
- return MULTI_ROW_P(ctx->mode) ? array : Qnil;
444
+ return ROW_MULTI_P(ctx->row_mode) ? array : Qnil;
374
445
  }
375
446
 
376
- VALUE safe_query_single_row(query_ctx *ctx) {
447
+ VALUE safe_query_single_row_hash(query_ctx *ctx) {
377
448
  int column_count;
378
449
  VALUE row = Qnil;
379
450
  VALUE column_names;
@@ -381,64 +452,54 @@ VALUE safe_query_single_row(query_ctx *ctx) {
381
452
  column_count = sqlite3_column_count(ctx->stmt);
382
453
  column_names = get_column_names(ctx->stmt, column_count);
383
454
 
384
- if (stmt_iterate(ctx))
455
+ if (stmt_iterate(ctx)) {
385
456
  row = row_to_hash(ctx->stmt, column_count, column_names);
457
+ if (!NIL_P(ctx->transform_proc))
458
+ row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
459
+ }
386
460
 
387
461
  RB_GC_GUARD(row);
388
462
  RB_GC_GUARD(column_names);
389
463
  return row;
390
464
  }
391
465
 
392
- VALUE safe_query_single_column(query_ctx *ctx) {
393
- VALUE array = MULTI_ROW_P(ctx->mode) ? rb_ary_new() : Qnil;
394
- VALUE value = Qnil;
466
+ VALUE safe_query_single_row_argv(query_ctx *ctx) {
467
+ VALUE argv_values[MAX_ARGV_COLUMNS] = NIL_ARGV_VALUES;
468
+ VALUE row = Qnil;
395
469
  int column_count = sqlite3_column_count(ctx->stmt);
396
- int row_count = 0;
397
-
398
- if (column_count != 1) rb_raise(cError, "Expected query result to have 1 column");
470
+ if (column_count > MAX_ARGV_COLUMNS)
471
+ rb_raise(cError, "Conversion is supported only up to %d columns", MAX_ARGV_COLUMNS);
472
+ int do_transform = !NIL_P(ctx->transform_proc);
399
473
 
400
- while (stmt_iterate(ctx)) {
401
- value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
402
- row_count++;
403
- switch (ctx->mode) {
404
- case QUERY_YIELD:
405
- rb_yield(value);
406
- break;
407
- case QUERY_MULTI_ROW:
408
- rb_ary_push(array, value);
409
- break;
410
- case QUERY_SINGLE_ROW:
411
- return value;
412
- }
413
- if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
414
- return MULTI_ROW_P(ctx->mode) ? array : ctx->self;
474
+ if (stmt_iterate(ctx)) {
475
+ ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, 1);
415
476
  }
416
477
 
417
- RB_GC_GUARD(value);
418
- RB_GC_GUARD(array);
419
- return MULTI_ROW_P(ctx->mode) ? array : Qnil;
478
+ ARGV_GC_GUARD(argv_values);
479
+ RB_GC_GUARD(row);
480
+ return row;
420
481
  }
421
482
 
422
- VALUE safe_query_single_value(query_ctx *ctx) {
423
- int column_count;
424
- VALUE value = Qnil;
425
-
426
- column_count = sqlite3_column_count(ctx->stmt);
427
- if (column_count != 1)
428
- rb_raise(cError, "Expected query result to have 1 column");
483
+ VALUE safe_query_single_row_ary(query_ctx *ctx) {
484
+ int column_count = sqlite3_column_count(ctx->stmt);
485
+ VALUE row = Qnil;
486
+ int do_transform = !NIL_P(ctx->transform_proc);
429
487
 
430
- if (stmt_iterate(ctx))
431
- value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
488
+ if (stmt_iterate(ctx)) {
489
+ row = row_to_ary(ctx->stmt, column_count);
490
+ if (do_transform)
491
+ row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
492
+ }
432
493
 
433
- RB_GC_GUARD(value);
434
- return value;
494
+ RB_GC_GUARD(row);
495
+ return row;
435
496
  }
436
497
 
437
498
  enum batch_mode {
438
499
  BATCH_EXECUTE,
439
- BATCH_QUERY_ARY,
440
500
  BATCH_QUERY_HASH,
441
- BATCH_QUERY_SINGLE_COLUMN
501
+ BATCH_QUERY_ARGV,
502
+ BATCH_QUERY_ARY,
442
503
  };
443
504
 
444
505
  static inline VALUE batch_iterate_hash(query_ctx *ctx) {
@@ -446,13 +507,17 @@ static inline VALUE batch_iterate_hash(query_ctx *ctx) {
446
507
  VALUE row = Qnil;
447
508
  int column_count = sqlite3_column_count(ctx->stmt);
448
509
  VALUE column_names = get_column_names(ctx->stmt, column_count);
510
+ const int do_transform = !NIL_P(ctx->transform_proc);
449
511
 
450
512
  while (stmt_iterate(ctx)) {
451
513
  row = row_to_hash(ctx->stmt, column_count, column_names);
514
+ if (do_transform)
515
+ row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
452
516
  rb_ary_push(rows, row);
453
517
  }
454
518
 
455
519
  RB_GC_GUARD(column_names);
520
+ RB_GC_GUARD(row);
456
521
  RB_GC_GUARD(rows);
457
522
  return rows;
458
523
  }
@@ -461,27 +526,36 @@ static inline VALUE batch_iterate_ary(query_ctx *ctx) {
461
526
  VALUE rows = rb_ary_new();
462
527
  VALUE row = Qnil;
463
528
  int column_count = sqlite3_column_count(ctx->stmt);
529
+ int do_transform = !NIL_P(ctx->transform_proc);
464
530
 
465
531
  while (stmt_iterate(ctx)) {
466
532
  row = row_to_ary(ctx->stmt, column_count);
533
+ if (do_transform)
534
+ row = rb_funcall(ctx->transform_proc, ID_call, 1, row);
467
535
  rb_ary_push(rows, row);
468
536
  }
469
537
 
538
+ RB_GC_GUARD(row);
470
539
  RB_GC_GUARD(rows);
471
540
  return rows;
472
541
  }
473
542
 
474
- static inline VALUE batch_iterate_single_column(query_ctx *ctx) {
543
+ static inline VALUE batch_iterate_argv(query_ctx *ctx) {
475
544
  VALUE rows = rb_ary_new();
476
- VALUE value = Qnil;
545
+ VALUE argv_values[MAX_ARGV_COLUMNS] = NIL_ARGV_VALUES;
546
+ VALUE row = Qnil;
477
547
  int column_count = sqlite3_column_count(ctx->stmt);
478
- if (column_count != 1) rb_raise(cError, "Expected query result to have 1 column");
548
+ if (column_count > MAX_ARGV_COLUMNS)
549
+ rb_raise(cError, "Conversion is supported only up to %d columns", MAX_ARGV_COLUMNS);
550
+ int do_transform = !NIL_P(ctx->transform_proc);
479
551
 
480
552
  while (stmt_iterate(ctx)) {
481
- value = get_column_value(ctx->stmt, 0, sqlite3_column_type(ctx->stmt, 0));
482
- rb_ary_push(rows, value);
553
+ ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, 1);
554
+ rb_ary_push(rows, row);
483
555
  }
484
556
 
557
+ ARGV_GC_GUARD(argv_values);
558
+ RB_GC_GUARD(row);
485
559
  RB_GC_GUARD(rows);
486
560
  return rows;
487
561
  }
@@ -491,34 +565,35 @@ static inline void batch_iterate(query_ctx *ctx, enum batch_mode mode, VALUE *ro
491
565
  case BATCH_EXECUTE:
492
566
  while (stmt_iterate(ctx));
493
567
  break;
494
- case BATCH_QUERY_ARY:
495
- *rows = batch_iterate_ary(ctx);
496
- break;
497
568
  case BATCH_QUERY_HASH:
498
569
  *rows = batch_iterate_hash(ctx);
499
570
  break;
500
- case BATCH_QUERY_SINGLE_COLUMN:
501
- *rows = batch_iterate_single_column(ctx);
571
+ case BATCH_QUERY_ARGV:
572
+ *rows = batch_iterate_argv(ctx);
573
+ break;
574
+ case BATCH_QUERY_ARY:
575
+ *rows = batch_iterate_ary(ctx);
502
576
  break;
503
577
  }
504
578
  }
505
579
 
506
- static inline VALUE batch_run_array(query_ctx *ctx, enum batch_mode mode) {
580
+ static inline VALUE batch_run_array(query_ctx *ctx, enum batch_mode batch_mode) {
507
581
  int count = RARRAY_LEN(ctx->params);
508
582
  int block_given = rb_block_given_p();
509
- VALUE results = (mode != BATCH_EXECUTE) && !block_given ? rb_ary_new() : Qnil;
583
+ VALUE results = (batch_mode != BATCH_EXECUTE) && !block_given ? rb_ary_new() : Qnil;
510
584
  VALUE rows = Qnil;
511
585
  int changes = 0;
512
586
 
513
587
  for (int i = 0; i < count; i++) {
514
588
  sqlite3_reset(ctx->stmt);
515
589
  sqlite3_clear_bindings(ctx->stmt);
590
+ Database_issue_query(ctx->db, ctx->sql);
516
591
  bind_all_parameters_from_object(ctx->stmt, RARRAY_AREF(ctx->params, i));
517
592
 
518
- batch_iterate(ctx, mode, &rows);
593
+ batch_iterate(ctx, batch_mode, &rows);
519
594
  changes += sqlite3_changes(ctx->sqlite3_db);
520
595
 
521
- if (mode != BATCH_EXECUTE) {
596
+ if (batch_mode != BATCH_EXECUTE) {
522
597
  if (block_given)
523
598
  rb_yield(rows);
524
599
  else
@@ -529,7 +604,7 @@ static inline VALUE batch_run_array(query_ctx *ctx, enum batch_mode mode) {
529
604
  RB_GC_GUARD(rows);
530
605
  RB_GC_GUARD(results);
531
606
 
532
- if (mode == BATCH_EXECUTE || block_given)
607
+ if (batch_mode == BATCH_EXECUTE || block_given)
533
608
  return INT2FIX(changes);
534
609
  else
535
610
  return results;
@@ -537,7 +612,7 @@ static inline VALUE batch_run_array(query_ctx *ctx, enum batch_mode mode) {
537
612
 
538
613
  struct batch_execute_each_ctx {
539
614
  query_ctx *ctx;
540
- enum batch_mode mode;
615
+ enum batch_mode batch_mode;
541
616
  int block_given;
542
617
  VALUE results;
543
618
  int changes;
@@ -549,12 +624,13 @@ static VALUE batch_run_each_iter(RB_BLOCK_CALL_FUNC_ARGLIST(yield_value, vctx))
549
624
 
550
625
  sqlite3_reset(each_ctx->ctx->stmt);
551
626
  sqlite3_clear_bindings(each_ctx->ctx->stmt);
627
+ Database_issue_query(each_ctx->ctx->db, each_ctx->ctx->sql);
552
628
  bind_all_parameters_from_object(each_ctx->ctx->stmt, yield_value);
553
629
 
554
- batch_iterate(each_ctx->ctx, each_ctx->mode, &rows);
630
+ batch_iterate(each_ctx->ctx, each_ctx->batch_mode, &rows);
555
631
  each_ctx->changes += sqlite3_changes(each_ctx->ctx->sqlite3_db);
556
632
 
557
- if (each_ctx->mode != BATCH_EXECUTE) {
633
+ if (each_ctx->batch_mode != BATCH_EXECUTE) {
558
634
  if (each_ctx->block_given)
559
635
  rb_yield(rows);
560
636
  else
@@ -565,26 +641,26 @@ static VALUE batch_run_each_iter(RB_BLOCK_CALL_FUNC_ARGLIST(yield_value, vctx))
565
641
  return Qnil;
566
642
  }
567
643
 
568
- static inline VALUE batch_run_each(query_ctx *ctx, enum batch_mode mode) {
644
+ static inline VALUE batch_run_each(query_ctx *ctx, enum batch_mode batch_mode) {
569
645
  struct batch_execute_each_ctx each_ctx = {
570
646
  .ctx = ctx,
571
- .mode = mode,
647
+ .batch_mode = batch_mode,
572
648
  .block_given = rb_block_given_p(),
573
- .results = ((mode != BATCH_EXECUTE) && !rb_block_given_p() ? rb_ary_new() : Qnil),
649
+ .results = ((batch_mode != BATCH_EXECUTE) && !rb_block_given_p() ? rb_ary_new() : Qnil),
574
650
  .changes = 0
575
651
  };
576
652
  rb_block_call(ctx->params, ID_each, 0, 0, batch_run_each_iter, (VALUE)&each_ctx);
577
653
 
578
- if (mode == BATCH_EXECUTE || each_ctx.block_given)
654
+ if (batch_mode == BATCH_EXECUTE || each_ctx.block_given)
579
655
  return INT2FIX(each_ctx.changes);
580
656
  else
581
657
  return each_ctx.results;
582
658
  }
583
659
 
584
- static inline VALUE batch_run_proc(query_ctx *ctx, enum batch_mode mode) {
660
+ static inline VALUE batch_run_proc(query_ctx *ctx, enum batch_mode batch_mode) {
585
661
  VALUE params = Qnil;
586
662
  int block_given = rb_block_given_p();
587
- VALUE results = (mode != BATCH_EXECUTE) && !block_given ? rb_ary_new() : Qnil;
663
+ VALUE results = (batch_mode != BATCH_EXECUTE) && !block_given ? rb_ary_new() : Qnil;
588
664
  VALUE rows = Qnil;
589
665
  int changes = 0;
590
666
 
@@ -594,12 +670,13 @@ static inline VALUE batch_run_proc(query_ctx *ctx, enum batch_mode mode) {
594
670
 
595
671
  sqlite3_reset(ctx->stmt);
596
672
  sqlite3_clear_bindings(ctx->stmt);
673
+ Database_issue_query(ctx->db, ctx->sql);
597
674
  bind_all_parameters_from_object(ctx->stmt, params);
598
675
 
599
- batch_iterate(ctx, mode, &rows);
676
+ batch_iterate(ctx, batch_mode, &rows);
600
677
  changes += sqlite3_changes(ctx->sqlite3_db);
601
678
 
602
- if (mode != BATCH_EXECUTE) {
679
+ if (batch_mode != BATCH_EXECUTE) {
603
680
  if (block_given)
604
681
  rb_yield(rows);
605
682
  else
@@ -611,21 +688,21 @@ static inline VALUE batch_run_proc(query_ctx *ctx, enum batch_mode mode) {
611
688
  RB_GC_GUARD(results);
612
689
  RB_GC_GUARD(params);
613
690
 
614
- if (mode == BATCH_EXECUTE || block_given)
691
+ if (batch_mode == BATCH_EXECUTE || block_given)
615
692
  return INT2FIX(changes);
616
693
  else
617
694
  return results;
618
695
  }
619
696
 
620
- static inline VALUE batch_run(query_ctx *ctx, enum batch_mode mode) {
697
+ static inline VALUE batch_run(query_ctx *ctx, enum batch_mode batch_mode) {
621
698
  if (TYPE(ctx->params) == T_ARRAY)
622
- return batch_run_array(ctx, mode);
699
+ return batch_run_array(ctx, batch_mode);
623
700
 
624
701
  if (rb_respond_to(ctx->params, ID_each))
625
- return batch_run_each(ctx, mode);
702
+ return batch_run_each(ctx, batch_mode);
626
703
 
627
704
  if (rb_respond_to(ctx->params, ID_call))
628
- return batch_run_proc(ctx, mode);
705
+ return batch_run_proc(ctx, batch_mode);
629
706
 
630
707
  rb_raise(cParameterError, "Invalid parameter source supplied to #batch_execute");
631
708
  }
@@ -635,15 +712,24 @@ VALUE safe_batch_execute(query_ctx *ctx) {
635
712
  }
636
713
 
637
714
  VALUE safe_batch_query(query_ctx *ctx) {
638
- return batch_run(ctx, BATCH_QUERY_HASH);
715
+ switch (ctx->query_mode) {
716
+ case QUERY_HASH:
717
+ return batch_run(ctx, BATCH_QUERY_HASH);
718
+ case QUERY_ARGV:
719
+ return batch_run(ctx, BATCH_QUERY_ARGV);
720
+ case QUERY_ARY:
721
+ return batch_run(ctx, BATCH_QUERY_ARY);
722
+ default:
723
+ rb_raise(cError, "Invalid query mode (safe_batch_query)");
724
+ }
639
725
  }
640
726
 
641
727
  VALUE safe_batch_query_ary(query_ctx *ctx) {
642
728
  return batch_run(ctx, BATCH_QUERY_ARY);
643
729
  }
644
730
 
645
- VALUE safe_batch_query_single_column(query_ctx *ctx) {
646
- return batch_run(ctx, BATCH_QUERY_SINGLE_COLUMN);
731
+ VALUE safe_batch_query_argv(query_ctx *ctx) {
732
+ return batch_run(ctx, BATCH_QUERY_ARGV);
647
733
  }
648
734
 
649
735
  VALUE safe_query_columns(query_ctx *ctx) {