@@ -411,125 +411,129 @@ bind_parameter_count(VALUE self)
411
411
return INT2NUM (sqlite3_bind_parameter_count (ctx -> st ));
412
412
}
413
413
414
- /* call-seq: stmt.fullscan_steps
415
- *
416
- * Return the number of times that SQLite has stepped forward in a table as part of a full table scan
417
- */
418
- static VALUE
419
- fullscan_steps (VALUE self )
420
- {
421
- sqlite3StmtRubyPtr ctx ;
422
- TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
423
- REQUIRE_OPEN_STMT (ctx );
414
+ enum stmt_stat_sym {
415
+ stmt_stat_sym_fullscan_steps ,
416
+ stmt_stat_sym_sorts ,
417
+ stmt_stat_sym_autoindexes ,
418
+ stmt_stat_sym_vm_steps ,
419
+ #ifdef SQLITE_STMTSTATUS_REPREPARE
420
+ stmt_stat_sym_reprepares ,
421
+ #endif
422
+ #ifdef SQLITE_STMTSTATUS_RUN
423
+ stmt_stat_sym_runs ,
424
+ #endif
425
+ #ifdef SQLITE_STMTSTATUS_FILTER_MISS
426
+ stmt_stat_sym_filter_misses ,
427
+ #endif
428
+ #ifdef SQLITE_STMTSTATUS_FILTER_HIT
429
+ stmt_stat_sym_filter_hits ,
430
+ #endif
431
+ stmt_stat_sym_last
432
+ };
424
433
425
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_FULLSCAN_STEP , 0 ));
426
- }
434
+ static VALUE stmt_stat_symbols [stmt_stat_sym_last ];
427
435
428
- /* call-seq: stmt.sorts
429
- *
430
- * Return the number of sort operations that have occurred
431
- */
432
- static VALUE
433
- sorts (VALUE self )
436
+ static void
437
+ setup_stmt_stat_symbols (void )
434
438
{
435
- sqlite3StmtRubyPtr ctx ;
436
- TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
437
- REQUIRE_OPEN_STMT (ctx );
438
-
439
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_SORT , 0 ));
439
+ if (stmt_stat_symbols [0 ] == 0 ) {
440
+ #define S (s ) stmt_stat_symbols[stmt_stat_sym_##s] = ID2SYM(rb_intern_const(#s))
441
+ S (fullscan_steps );
442
+ S (sorts );
443
+ S (autoindexes );
444
+ S (vm_steps );
445
+ #ifdef SQLITE_STMTSTATUS_REPREPARE
446
+ S (reprepares );
447
+ #endif
448
+ #ifdef SQLITE_STMTSTATUS_RUN
449
+ S (runs );
450
+ #endif
451
+ #ifdef SQLITE_STMTSTATUS_FILTER_MISS
452
+ S (filter_misses );
453
+ #endif
454
+ #ifdef SQLITE_STMTSTATUS_FILTER_HIT
455
+ S (filter_hits );
456
+ #endif
457
+ #undef S
458
+ }
440
459
}
441
460
442
- /* call-seq: stmt.autoindexes
443
- *
444
- * Return the number of rows inserted into transient indices that were created automatically in order to help joins run faster
445
- */
446
- static VALUE
447
- autoindexes (VALUE self )
461
+ static size_t
462
+ stmt_stat_internal (VALUE hash_or_sym , sqlite3_stmt * stmt )
448
463
{
449
- sqlite3StmtRubyPtr ctx ;
450
- TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
451
- REQUIRE_OPEN_STMT (ctx );
464
+ VALUE hash = Qnil , key = Qnil ;
452
465
453
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_AUTOINDEX , 0 ));
454
- }
466
+ setup_stmt_stat_symbols ();
455
467
456
- /* call-seq: stmt.vm_steps
457
- *
458
- * Return the number of virtual machine operations executed by the prepared statement
459
- */
460
- static VALUE
461
- vm_steps (VALUE self )
462
- {
463
- sqlite3StmtRubyPtr ctx ;
464
- TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
465
- REQUIRE_OPEN_STMT (ctx );
468
+ if (RB_TYPE_P (hash_or_sym , T_HASH )) {
469
+ hash = hash_or_sym ;
470
+ }
471
+ else if (SYMBOL_P (hash_or_sym )) {
472
+ key = hash_or_sym ;
473
+ }
474
+ else {
475
+ rb_raise (rb_eTypeError , "non-hash or symbol argument" );
476
+ }
466
477
467
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_VM_STEP , 0 ));
468
- }
478
+ #define SET (name , stat_type ) \
479
+ if (key == stmt_stat_symbols[stmt_stat_sym_##name]) \
480
+ return sqlite3_stmt_status(stmt, stat_type, 0); \
481
+ else if (hash != Qnil) \
482
+ rb_hash_aset(hash, stmt_stat_symbols[stmt_stat_sym_##name], SIZET2NUM(sqlite3_stmt_status(stmt, stat_type, 0)));
469
483
484
+ SET (fullscan_steps , SQLITE_STMTSTATUS_FULLSCAN_STEP );
485
+ SET (sorts , SQLITE_STMTSTATUS_SORT );
486
+ SET (autoindexes , SQLITE_STMTSTATUS_AUTOINDEX );
487
+ SET (vm_steps , SQLITE_STMTSTATUS_VM_STEP );
470
488
#ifdef SQLITE_STMTSTATUS_REPREPARE
471
- /* call-seq: stmt.reprepares
472
- *
473
- * Return the number of times that the prepare statement has been automatically regenerated due to schema changes or changes to bound parameters that might affect the query plan.
474
- */
475
- static VALUE
476
- reprepares (VALUE self )
477
- {
478
- sqlite3StmtRubyPtr ctx ;
479
- TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
480
- REQUIRE_OPEN_STMT (ctx );
481
-
482
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_REPREPARE , 0 ));
483
- }
489
+ SET (reprepares , SQLITE_STMTSTATUS_REPREPARE );
484
490
#endif
485
-
486
491
#ifdef SQLITE_STMTSTATUS_RUN
487
- /* call-seq: stmt.runs
488
- *
489
- * Return the number of times that the prepared statement has been run
490
- */
491
- static VALUE
492
- runs (VALUE self )
493
- {
494
- sqlite3StmtRubyPtr ctx ;
495
- TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
496
- REQUIRE_OPEN_STMT (ctx );
497
-
498
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_RUN , 0 ));
499
- }
492
+ SET (runs , SQLITE_STMTSTATUS_RUN );
500
493
#endif
501
-
502
494
#ifdef SQLITE_STMTSTATUS_FILTER_MISS
503
- /* call-seq: stmt. filter_misses
504
- *
505
- * Return the number of times that the Bloom filter returned a find, and thus the join step had to be processed as normal.
506
- */
507
- static VALUE
508
- filter_misses ( VALUE self )
509
- {
510
- sqlite3StmtRubyPtr ctx ;
511
- TypedData_Get_Struct ( self , sqlite3StmtRuby , & statement_type , ctx );
512
- REQUIRE_OPEN_STMT ( ctx );
495
+ SET ( filter_misses , SQLITE_STMTSTATUS_FILTER_MISS );
496
+ #endif
497
+ #ifdef SQLITE_STMTSTATUS_FILTER_HIT
498
+ SET ( filter_hits , SQLITE_STMTSTATUS_FILTER_HIT );
499
+ #endif
500
+ #undef SET
501
+
502
+ if (! NIL_P ( key )) { /* matched key should return above */
503
+ rb_raise ( rb_eArgError , "unknown key: %" PRIsVALUE , rb_sym2str ( key ) );
504
+ }
513
505
514
- return INT2NUM ( sqlite3_stmt_status ( ctx -> st , SQLITE_STMTSTATUS_FILTER_MISS , 0 )) ;
506
+ return 0 ;
515
507
}
516
- #endif
517
508
518
- #ifdef SQLITE_STMTSTATUS_FILTER_HIT
519
- /* call-seq: stmt.filter_hits
509
+ /* call-seq: stmt.stmt_stat(hash_or_key)
520
510
*
521
- * Return the number of times that a join step was bypassed because a Bloom filter returned not-found
511
+ * Returns a Hash containing information about the statement.
522
512
*/
523
513
static VALUE
524
- filter_hits (VALUE self )
514
+ stmt_stat (VALUE self , VALUE arg ) // arg is (nil || hash || symbol )
525
515
{
526
516
sqlite3StmtRubyPtr ctx ;
527
517
TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
528
518
REQUIRE_OPEN_STMT (ctx );
529
519
530
- return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_FILTER_HIT , 0 ));
520
+ if (NIL_P (arg )) {
521
+ arg = rb_hash_new ();
522
+ }
523
+ else if (SYMBOL_P (arg )) {
524
+ size_t value = stmt_stat_internal (arg , ctx -> st );
525
+ return SIZET2NUM (value );
526
+ }
527
+ else if (RB_TYPE_P (arg , T_HASH )) {
528
+ // ok
529
+ }
530
+ else {
531
+ rb_raise (rb_eTypeError , "non-hash or symbol given" );
532
+ }
533
+
534
+ stmt_stat_internal (arg , ctx -> st );
535
+ return arg ;
531
536
}
532
- #endif
533
537
534
538
#ifdef SQLITE_STMTSTATUS_MEMUSED
535
539
/* call-seq: stmt.memory_used
@@ -583,33 +587,10 @@ init_sqlite3_statement(void)
583
587
rb_define_method (cSqlite3Statement , "column_name" , column_name , 1 );
584
588
rb_define_method (cSqlite3Statement , "column_decltype" , column_decltype , 1 );
585
589
rb_define_method (cSqlite3Statement , "bind_parameter_count" , bind_parameter_count , 0 );
586
- rb_define_method (cSqlite3Statement , "fullscan_steps" , fullscan_steps , 0 );
587
- rb_define_method (cSqlite3Statement , "sorts" , sorts , 0 );
588
- rb_define_method (cSqlite3Statement , "autoindexes" , autoindexes , 0 );
589
- rb_define_method (cSqlite3Statement , "vm_steps" , vm_steps , 0 );
590
- rb_define_private_method (cSqlite3Statement , "prepare" , prepare , 2 );
591
-
592
- #ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
593
- rb_define_method (cSqlite3Statement , "database_name" , database_name , 1 );
594
- #endif
595
-
596
- #ifdef SQLITE_STMTSTATUS_REPREPARE
597
- rb_define_method (cSqlite3Statement , "reprepares" , reprepares , 0 );
598
- #endif
599
-
600
- #ifdef SQLITE_STMTSTATUS_RUN
601
- rb_define_method (cSqlite3Statement , "runs" , runs , 0 );
602
- #endif
603
-
604
- #ifdef SQLITE_STMTSTATUS_FILTER_MISS
605
- rb_define_method (cSqlite3Statement , "filter_misses" , filter_misses , 0 );
606
- #endif
607
-
608
- #ifdef SQLITE_STMTSTATUS_FILTER_HIT
609
- rb_define_method (cSqlite3Statement , "filter_hits" , filter_hits , 0 );
610
- #endif
611
-
590
+ rb_define_method (cSqlite3Statement , "stmt_stat" , stmt_stat , 1 );
612
591
#ifdef SQLITE_STMTSTATUS_MEMUSED
613
592
rb_define_method (cSqlite3Statement , "memused" , memused , 0 );
614
593
#endif
594
+
595
+ rb_define_private_method (cSqlite3Statement , "prepare" , prepare , 2 );
615
596
}
0 commit comments