Skip to content

Commit b6d0089

Browse files
captn3m0flavorjones
authored andcommitted
Implements stmt.named_params
- Closes #627
1 parent f88c20d commit b6d0089

File tree

2 files changed

+39
-0
lines changed

2 files changed

+39
-0
lines changed

ext/sqlite3/statement.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,36 @@ bind_parameter_count(VALUE self)
460460
return INT2NUM(sqlite3_bind_parameter_count(ctx->st));
461461
}
462462

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+
463493
enum stmt_stat_sym {
464494
stmt_stat_sym_fullscan_steps,
465495
stmt_stat_sym_sorts,
@@ -689,6 +719,7 @@ init_sqlite3_statement(void)
689719
rb_define_method(cSqlite3Statement, "column_name", column_name, 1);
690720
rb_define_method(cSqlite3Statement, "column_decltype", column_decltype, 1);
691721
rb_define_method(cSqlite3Statement, "bind_parameter_count", bind_parameter_count, 0);
722+
rb_define_method(cSqlite3Statement, "named_params", named_params, 0);
692723
rb_define_method(cSqlite3Statement, "sql", get_sql, 0);
693724
rb_define_method(cSqlite3Statement, "expanded_sql", get_expanded_sql, 0);
694725
#ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME

test/test_statement.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,14 @@ def test_named_bind_not_found
256256
stmt.close
257257
end
258258

259+
def test_named_params
260+
assert_equal [], @stmt.named_params
261+
262+
stmt = SQLite3::Statement.new(@db, "select :foo, $bar, @zed")
263+
assert_equal ["foo", "bar", "zed"], stmt.named_params
264+
stmt.close
265+
end
266+
259267
def test_each
260268
r = nil
261269
@stmt.each do |row|

0 commit comments

Comments
 (0)