extralite 2.15 → 3.0.0

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.
@@ -151,7 +151,7 @@ static inline void column_names_setup(struct column_names *names, int count) {
151
151
  }
152
152
 
153
153
  static inline void column_names_set(struct column_names *names, int idx, VALUE value) {
154
- if (names->count <= MAX_EMBEDDED_COLUMN_NAMES)
154
+ if (names->count <= MAX_EMBEDDED_COLUMN_NAMES)
155
155
  names->names[idx] = value;
156
156
  else
157
157
  rb_ary_push(names->array, value);
@@ -331,7 +331,7 @@ void *stmt_iterate_step(void *ptr) {
331
331
  inline enum gvl_mode stepwise_gvl_mode(query_ctx *ctx) {
332
332
  // a negative or zero threshold means the GVL is always held during iteration.
333
333
  if (ctx->gvl_release_threshold <= 0) return GVL_HOLD;
334
-
334
+
335
335
  if (!sqlite3_stmt_busy(ctx->stmt)) return GVL_RELEASE;
336
336
 
337
337
  // if positive, the GVL is normally held, and release every <threshold> steps.
@@ -366,6 +366,218 @@ VALUE cleanup_stmt(query_ctx *ctx) {
366
366
  return Qnil;
367
367
  }
368
368
 
369
+ static inline void add_transform_container_obj(VALUE row, struct transform_node *col, VALUE obj) {
370
+ if (col->flags & TRANSFORM_F_ARRAY) {
371
+ VALUE array = rb_hash_aref(row, col->name);
372
+ if (NIL_P(array)) {
373
+ array = rb_ary_new();
374
+ rb_hash_aset(row, col->name, array);
375
+ RB_GC_GUARD(array);
376
+ }
377
+ rb_ary_push(array, obj);
378
+ }
379
+ else
380
+ rb_hash_aset(row, col->name, obj);
381
+ }
382
+
383
+ static VALUE run_transform(VALUE identity_storage, struct transform_node *node, sqlite3_stmt *stmt);
384
+
385
+ static inline VALUE json_parse(VALUE json) {
386
+ if (NIL_P(mJSON)) {
387
+ rb_require("json");
388
+ mJSON = rb_const_get(rb_cObject, rb_intern_const("JSON"));
389
+ }
390
+ return rb_funcall(mJSON, ID_parse, 1, json);
391
+ }
392
+
393
+ static inline VALUE get_transform_column_value(struct transform_node *col, sqlite3_stmt *stmt) {
394
+ int native_type = sqlite3_column_type(stmt, col->idx);
395
+ switch (col->type) {
396
+ case TRANSFORM_T_AUTO:
397
+ if (native_type == SQLITE_NULL) return Qnil;
398
+ return get_column_value(stmt, col->idx, native_type);
399
+ case TRANSFORM_T_INTEGER:
400
+ if (native_type == SQLITE_NULL) return Qnil;
401
+ return get_column_value(stmt, col->idx, SQLITE_INTEGER);
402
+ case TRANSFORM_T_FLOAT:
403
+ if (native_type == SQLITE_NULL) return Qnil;
404
+ return get_column_value(stmt, col->idx, SQLITE_FLOAT);
405
+ case TRANSFORM_T_TEXT:
406
+ if (native_type == SQLITE_NULL) return Qnil;
407
+ return get_column_value(stmt, col->idx, SQLITE_TEXT);
408
+ case TRANSFORM_T_BOOL:
409
+ if (native_type == SQLITE_NULL) return Qnil;
410
+ int64_t v = sqlite3_column_int64(stmt, col->idx);
411
+ return v ? Qtrue : Qfalse;
412
+ case TRANSFORM_T_JSON:
413
+ if (native_type == SQLITE_NULL) return Qnil;
414
+ VALUE json = get_column_value(stmt, col->idx, SQLITE_TEXT);
415
+ return json_parse(json);
416
+ RB_GC_GUARD(json);
417
+ case TRANSFORM_T_PROC:
418
+ VALUE val = get_column_value(stmt, col->idx, native_type);
419
+ return rb_funcall(col->conversion_proc, ID_call, 1, val);
420
+ RB_GC_GUARD(val);
421
+ default:
422
+ rb_raise(cError, "Invalid column value");
423
+ }
424
+ }
425
+
426
+ VALUE run_transform_with_identity(
427
+ VALUE identity_storage, struct transform_node *node, sqlite3_stmt *stmt
428
+ ) {
429
+ VALUE row = Qnil;
430
+ VALUE identity_map = Qnil;
431
+
432
+ VALUE identity_value = get_transform_column_value(node->identity_node, stmt);
433
+ // get_column_value(
434
+ // stmt, node->identity_idx, sqlite3_column_type(stmt, node->identity_idx)
435
+ // );
436
+ VALUE identity_map_key = ULONG2NUM((uint64_t)node);
437
+ identity_map = rb_hash_aref(identity_storage, identity_map_key);
438
+
439
+ if (NIL_P(identity_map)) {
440
+ identity_map = rb_hash_new();
441
+ rb_hash_aset(identity_storage, identity_map_key, identity_map);
442
+ }
443
+ row = rb_hash_aref(identity_map, identity_value);
444
+ if (!NIL_P(row)) {
445
+ struct transform_node *col = node->subnodes_head;
446
+ while (col) {
447
+ if (col->type == TRANSFORM_T_RELATION) {
448
+ VALUE obj = run_transform(identity_storage, col, stmt);
449
+ if (!NIL_P(obj)) add_transform_container_obj(row, col, obj);
450
+ }
451
+ col = col->next;
452
+ }
453
+ return (node->flags & TRANSFORM_F_NAME) ? row : Qnil;
454
+ }
455
+ else {
456
+ // not found in identity map
457
+ row = rb_hash_new();
458
+ struct transform_node *col = node->subnodes_head;
459
+ while (col) {
460
+ if (col == node->identity_node) {
461
+ rb_hash_aset(row, col->name, identity_value);
462
+ rb_hash_aset(identity_map, identity_value, row);
463
+ }
464
+ else if (col->type == TRANSFORM_T_RELATION) {
465
+ VALUE obj = run_transform(identity_storage, col, stmt);
466
+ if (!NIL_P(obj)) add_transform_container_obj(row, col, obj);
467
+ }
468
+ else {
469
+ VALUE value = get_transform_column_value(col, stmt);
470
+ rb_hash_aset(row, col->name, value);
471
+ RB_GC_GUARD(value);
472
+ }
473
+ col = col->next;
474
+ }
475
+ return row;
476
+ }
477
+
478
+ RB_GC_GUARD(identity_map);
479
+ RB_GC_GUARD(row);
480
+ }
481
+
482
+ VALUE run_transform_no_identity(
483
+ VALUE identity_storage, struct transform_node *node, sqlite3_stmt *stmt
484
+ ) {
485
+ VALUE row = rb_hash_new();
486
+ struct transform_node *col = node->subnodes_head;
487
+ while (col) {
488
+ if (col->type == TRANSFORM_T_RELATION) {
489
+ VALUE obj = run_transform(identity_storage, col, stmt);
490
+ if (!NIL_P(obj)) add_transform_container_obj(row, col, obj);
491
+ }
492
+ else {
493
+ VALUE value = get_transform_column_value(col, stmt);
494
+ rb_hash_aset(row, col->name, value);
495
+ RB_GC_GUARD(value);
496
+ }
497
+ col = col->next;
498
+ }
499
+ return row;
500
+ RB_GC_GUARD(row);
501
+ }
502
+
503
+ static inline VALUE run_transform(
504
+ VALUE identity_storage, struct transform_node *node, sqlite3_stmt *stmt
505
+ ) {
506
+ // fprintf(stdout, "transform_container: %p flags: %02x identity_idx: %d\n", node, node->flags, node->identity_idx);
507
+ // if (node->flags & TRANSFORM_F_NAME) INSPECT(" name", node->name);
508
+ if (node->identity_node) {
509
+ return run_transform_with_identity(identity_storage, node, stmt);
510
+ }
511
+ else {
512
+ return run_transform_no_identity(identity_storage, node, stmt);
513
+ }
514
+ }
515
+
516
+ VALUE safe_query_transform(query_ctx *ctx) {
517
+ VALUE array = rb_ary_new();
518
+ VALUE identity_storage = rb_hash_new();
519
+ VALUE row = Qnil;
520
+ // int column_count = sqlite3_column_count(ctx->stmt);
521
+ struct transform_node *transform_root = get_transform_root(ctx->transform);
522
+
523
+ int row_count = 0;
524
+ while (stmt_iterate(ctx)) {
525
+ row_count++;
526
+ row = run_transform(identity_storage, transform_root, ctx->stmt);
527
+ if (!NIL_P(row)) {
528
+ rb_ary_push(array, row);
529
+ if (ctx->max_rows != ALL_ROWS && row_count >= ctx->max_rows)
530
+ goto done;
531
+ }
532
+ }
533
+
534
+ done:
535
+ switch (ctx->row_mode) {
536
+ case ROW_YIELD:
537
+ rb_ary_each(array);
538
+ return ctx->self;
539
+ case ROW_MULTI:
540
+ return array;
541
+ case ROW_SINGLE:
542
+ return rb_ary_entry(array, 0);
543
+ }
544
+
545
+ return Qnil;
546
+ RB_GC_GUARD(identity_storage);
547
+ RB_GC_GUARD(row);
548
+ RB_GC_GUARD(array);
549
+ }
550
+
551
+ VALUE safe_query_single_row_transform(query_ctx *ctx) {
552
+ VALUE array = rb_ary_new();
553
+ VALUE identity_storage = rb_hash_new();
554
+ VALUE row = Qnil;
555
+ // int column_count = sqlite3_column_count(ctx->stmt);
556
+ struct transform_node *transform_root = get_transform_root(ctx->transform);
557
+
558
+ int row_count = 0;
559
+ while (stmt_iterate(ctx)) {
560
+ row_count++;
561
+ row = run_transform(identity_storage, transform_root, ctx->stmt);
562
+ if (!NIL_P(row)) { rb_ary_push(array, row); }
563
+ }
564
+
565
+ row = rb_ary_entry(array, 0);
566
+ switch (ctx->row_mode) {
567
+ case ROW_YIELD:
568
+ rb_yield(row);
569
+ return ctx->self;
570
+ case ROW_MULTI:
571
+ case ROW_SINGLE:
572
+ return row;
573
+ }
574
+
575
+ return Qnil;
576
+ RB_GC_GUARD(identity_storage);
577
+ RB_GC_GUARD(row);
578
+ RB_GC_GUARD(array);
579
+ }
580
+
369
581
  VALUE safe_query_splat(query_ctx *ctx);
370
582
 
371
583
  VALUE safe_query_hash(query_ctx *ctx) {
@@ -374,12 +586,12 @@ VALUE safe_query_hash(query_ctx *ctx) {
374
586
  int column_count = sqlite3_column_count(ctx->stmt);
375
587
  struct column_names names = get_column_names(ctx->stmt, column_count);
376
588
  int row_count = 0;
377
- int do_transform = !NIL_P(ctx->transform_proc);
589
+ int do_transform = !NIL_P(ctx->transform);
378
590
 
379
591
  while (stmt_iterate(ctx)) {
380
592
  row = row_to_hash(ctx->stmt, column_count, &names);
381
593
  if (do_transform)
382
- row = INVOKE_PROC(ctx->transform_proc, 1, &row);
594
+ row = INVOKE_PROC(ctx->transform, 1, &row);
383
595
  row_count++;
384
596
  switch (ctx->row_mode) {
385
597
  case ROW_YIELD:
@@ -416,7 +628,7 @@ VALUE safe_query_hash(query_ctx *ctx) {
416
628
  #define ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, return_rows) \
417
629
  row_to_splat_values(ctx->stmt, column_count, argv_values); \
418
630
  if (do_transform) \
419
- row = INVOKE_PROC(ctx->transform_proc, column_count, argv_values); \
631
+ row = INVOKE_PROC(ctx->transform, column_count, argv_values); \
420
632
  else if (return_rows) \
421
633
  row = column_count == 1 ? argv_values[0] : rb_ary_new_from_values(column_count, argv_values);
422
634
 
@@ -428,7 +640,7 @@ VALUE safe_query_splat(query_ctx *ctx) {
428
640
  if (column_count > MAX_ARGV_COLUMNS)
429
641
  rb_raise(cError, "Conversion is supported only up to %d columns", MAX_ARGV_COLUMNS);
430
642
 
431
- int do_transform = !NIL_P(ctx->transform_proc);
643
+ int do_transform = !NIL_P(ctx->transform);
432
644
  int return_rows = (ctx->row_mode != ROW_YIELD);
433
645
 
434
646
  int row_count = 0;
@@ -463,12 +675,12 @@ VALUE safe_query_array(query_ctx *ctx) {
463
675
  VALUE row = Qnil;
464
676
  int column_count = sqlite3_column_count(ctx->stmt);
465
677
  int row_count = 0;
466
- int do_transform = !NIL_P(ctx->transform_proc);
678
+ int do_transform = !NIL_P(ctx->transform);
467
679
 
468
680
  while (stmt_iterate(ctx)) {
469
681
  row = row_to_array(ctx->stmt, column_count);
470
682
  if (do_transform)
471
- row = INVOKE_PROC(ctx->transform_proc, 1, &row);
683
+ row = INVOKE_PROC(ctx->transform, 1, &row);
472
684
  row_count++;
473
685
  switch (ctx->row_mode) {
474
686
  case ROW_YIELD:
@@ -496,8 +708,8 @@ VALUE safe_query_single_row_hash(query_ctx *ctx) {
496
708
 
497
709
  if (stmt_iterate(ctx)) {
498
710
  row = row_to_hash(ctx->stmt, column_count, &names);
499
- if (!NIL_P(ctx->transform_proc))
500
- row = INVOKE_PROC(ctx->transform_proc, 1, &row);
711
+ if (!NIL_P(ctx->transform))
712
+ row = INVOKE_PROC(ctx->transform, 1, &row);
501
713
  }
502
714
 
503
715
  RB_GC_GUARD(row);
@@ -511,7 +723,7 @@ VALUE safe_query_single_row_splat(query_ctx *ctx) {
511
723
  int column_count = sqlite3_column_count(ctx->stmt);
512
724
  if (column_count > MAX_ARGV_COLUMNS)
513
725
  rb_raise(cError, "Conversion is supported only up to %d columns", MAX_ARGV_COLUMNS);
514
- int do_transform = !NIL_P(ctx->transform_proc);
726
+ int do_transform = !NIL_P(ctx->transform);
515
727
 
516
728
  if (stmt_iterate(ctx)) {
517
729
  ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, 1);
@@ -525,12 +737,12 @@ VALUE safe_query_single_row_splat(query_ctx *ctx) {
525
737
  VALUE safe_query_single_row_array(query_ctx *ctx) {
526
738
  int column_count = sqlite3_column_count(ctx->stmt);
527
739
  VALUE row = Qnil;
528
- int do_transform = !NIL_P(ctx->transform_proc);
740
+ int do_transform = !NIL_P(ctx->transform);
529
741
 
530
742
  if (stmt_iterate(ctx)) {
531
743
  row = row_to_array(ctx->stmt, column_count);
532
744
  if (do_transform)
533
- row = INVOKE_PROC(ctx->transform_proc, 1, &row);
745
+ row = INVOKE_PROC(ctx->transform, 1, &row);
534
746
  }
535
747
 
536
748
  RB_GC_GUARD(row);
@@ -549,12 +761,12 @@ static inline VALUE batch_iterate_hash(query_ctx *ctx) {
549
761
  VALUE row = Qnil;
550
762
  int column_count = sqlite3_column_count(ctx->stmt);
551
763
  struct column_names names = get_column_names(ctx->stmt, column_count);
552
- const int do_transform = !NIL_P(ctx->transform_proc);
764
+ const int do_transform = !NIL_P(ctx->transform);
553
765
 
554
766
  while (stmt_iterate(ctx)) {
555
767
  row = row_to_hash(ctx->stmt, column_count, &names);
556
768
  if (do_transform)
557
- row = INVOKE_PROC(ctx->transform_proc, 1, &row);
769
+ row = INVOKE_PROC(ctx->transform, 1, &row);
558
770
  rb_ary_push(rows, row);
559
771
  }
560
772
 
@@ -568,12 +780,12 @@ static inline VALUE batch_iterate_array(query_ctx *ctx) {
568
780
  VALUE rows = rb_ary_new();
569
781
  VALUE row = Qnil;
570
782
  int column_count = sqlite3_column_count(ctx->stmt);
571
- int do_transform = !NIL_P(ctx->transform_proc);
783
+ int do_transform = !NIL_P(ctx->transform);
572
784
 
573
785
  while (stmt_iterate(ctx)) {
574
786
  row = row_to_array(ctx->stmt, column_count);
575
787
  if (do_transform)
576
- row = INVOKE_PROC(ctx->transform_proc, 1, &row);
788
+ row = INVOKE_PROC(ctx->transform, 1, &row);
577
789
  rb_ary_push(rows, row);
578
790
  }
579
791
 
@@ -589,7 +801,7 @@ static inline VALUE batch_iterate_splat(query_ctx *ctx) {
589
801
  int column_count = sqlite3_column_count(ctx->stmt);
590
802
  if (column_count > MAX_ARGV_COLUMNS)
591
803
  rb_raise(cError, "Conversion is supported only up to %d columns", MAX_ARGV_COLUMNS);
592
- int do_transform = !NIL_P(ctx->transform_proc);
804
+ int do_transform = !NIL_P(ctx->transform);
593
805
 
594
806
  while (stmt_iterate(ctx)) {
595
807
  ARGV_GET_ROW(ctx, column_count, argv_values, row, do_transform, 1);
@@ -753,13 +965,13 @@ static inline VALUE batch_run_proc(query_ctx *ctx, enum batch_mode batch_mode) {
753
965
  static inline VALUE batch_run(query_ctx *ctx, enum batch_mode batch_mode) {
754
966
  if (TYPE(ctx->params) == T_ARRAY)
755
967
  return batch_run_array(ctx, batch_mode);
756
-
968
+
757
969
  if (rb_respond_to(ctx->params, ID_each))
758
970
  return batch_run_each(ctx, batch_mode);
759
-
971
+
760
972
  if (rb_respond_to(ctx->params, ID_call))
761
973
  return batch_run_proc(ctx, batch_mode);
762
-
974
+
763
975
  rb_raise(cParameterError, "Invalid parameter source supplied to #batch_execute");
764
976
  }
765
977
 
@@ -777,7 +989,7 @@ VALUE safe_batch_query(query_ctx *ctx) {
777
989
  return batch_run(ctx, BATCH_QUERY_ARRAY);
778
990
  default:
779
991
  rb_raise(cError, "Invalid query mode (safe_batch_query)");
780
- }
992
+ }
781
993
  }
782
994
 
783
995
  VALUE safe_batch_query_array(query_ctx *ctx) {