@@ -460,6 +460,36 @@ bind_parameter_count(VALUE self)
460
460
return INT2NUM (sqlite3_bind_parameter_count (ctx -> st ));
461
461
}
462
462
463
+ /** call-seq: stmt.named_params
464
+ *
465
+ * Return the list of named parameters in the statement.
466
+ */
467
+ static VALUE
468
+ named_params (VALUE self )
469
+ {
470
+ sqlite3StmtRubyPtr ctx ;
471
+ TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
472
+
473
+ REQUIRE_LIVE_DB (ctx );
474
+ REQUIRE_OPEN_STMT (ctx );
475
+
476
+ int param_count = sqlite3_bind_parameter_count (ctx -> st );
477
+ VALUE params = rb_ary_new2 (param_count );
478
+
479
+ // The first host parameter has an index of 1, not 0.
480
+ for (int i = 1 ; i <= param_count ; i ++ ) {
481
+ const char * name = sqlite3_bind_parameter_name (ctx -> st , i );
482
+ // If parameters of the ?NNN form are used, there may be gaps in the list.
483
+ if (name ) {
484
+ VALUE rb_name = interned_utf8_cstr (name );
485
+ // The initial ":" or "$" or "@" or "?" is included as part of the name.
486
+ rb_name = rb_str_substr (rb_name , 1 , RSTRING_LEN (rb_name ) - 1 );
487
+ rb_ary_push (params , rb_name );
488
+ }
489
+ }
490
+ return rb_obj_freeze (params );
491
+ }
492
+
463
493
enum stmt_stat_sym {
464
494
stmt_stat_sym_fullscan_steps ,
465
495
stmt_stat_sym_sorts ,
@@ -689,6 +719,7 @@ init_sqlite3_statement(void)
689
719
rb_define_method (cSqlite3Statement , "column_name" , column_name , 1 );
690
720
rb_define_method (cSqlite3Statement , "column_decltype" , column_decltype , 1 );
691
721
rb_define_method (cSqlite3Statement , "bind_parameter_count" , bind_parameter_count , 0 );
722
+ rb_define_method (cSqlite3Statement , "named_params" , named_params , 0 );
692
723
rb_define_method (cSqlite3Statement , "sql" , get_sql , 0 );
693
724
rb_define_method (cSqlite3Statement , "expanded_sql" , get_expanded_sql , 0 );
694
725
#ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
0 commit comments