Skip to content

Commit e2b15ee

Browse files
committed
Add sql and expanded_sql methods to the statement object
These methods allow you to retrieve the SQL statement that was used to create the statement object. The `sql` method just returns the sql statement, where the `expanded_sql` method returns the statement but with bind parameters substituted. This should aid with debugging and other tasks. Fixes #293
1 parent 9b8dfb4 commit e2b15ee

File tree

2 files changed

+48
-0
lines changed

2 files changed

+48
-0
lines changed

ext/sqlite3/statement.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -598,6 +598,35 @@ database_name(VALUE self, VALUE index)
598598

599599
#endif
600600

601+
/* call-seq: stmt.sql
602+
*
603+
* Returns the SQL statement used to create this prepared statement
604+
*/
605+
static VALUE
606+
get_sql(VALUE self)
607+
{
608+
sqlite3StmtRubyPtr ctx;
609+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
610+
REQUIRE_OPEN_STMT(ctx);
611+
612+
return rb_obj_freeze(SQLITE3_UTF8_STR_NEW2(sqlite3_sql(ctx->st)));
613+
}
614+
615+
/* call-seq: stmt.expanded_sql
616+
*
617+
* Returns the SQL statement used to create this prepared statement, but
618+
* with bind parameters substituted in to the statement.
619+
*/
620+
static VALUE
621+
get_expanded_sql(VALUE self)
622+
{
623+
sqlite3StmtRubyPtr ctx;
624+
TypedData_Get_Struct(self, sqlite3StmtRuby, &statement_type, ctx);
625+
REQUIRE_OPEN_STMT(ctx);
626+
627+
return rb_obj_freeze(SQLITE3_UTF8_STR_NEW2(sqlite3_expanded_sql(ctx->st)));
628+
}
629+
601630
void
602631
init_sqlite3_statement(void)
603632
{
@@ -615,6 +644,8 @@ init_sqlite3_statement(void)
615644
rb_define_method(cSqlite3Statement, "column_name", column_name, 1);
616645
rb_define_method(cSqlite3Statement, "column_decltype", column_decltype, 1);
617646
rb_define_method(cSqlite3Statement, "bind_parameter_count", bind_parameter_count, 0);
647+
rb_define_method(cSqlite3Statement, "sql", get_sql, 0);
648+
rb_define_method(cSqlite3Statement, "expanded_sql", get_expanded_sql, 0);
618649
#ifdef HAVE_SQLITE3_COLUMN_DATABASE_NAME
619650
rb_define_method(cSqlite3Statement, "database_name", database_name, 1);
620651
#endif

test/test_statement.rb

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,23 @@ def test_column_names_are_deduped
6565
stmt&.close
6666
end
6767

68+
def test_sql_method
69+
sql = "SELECT 1234"
70+
stmt = @db.prepare sql
71+
assert_equal sql, stmt.sql
72+
ensure
73+
stmt.close
74+
end
75+
76+
def test_expanded_sql_method
77+
sql = "SELECT ?"
78+
stmt = @db.prepare sql
79+
stmt.bind_params 1234
80+
assert_equal "SELECT 1234", stmt.expanded_sql
81+
ensure
82+
stmt.close
83+
end
84+
6885
def test_insert_duplicate_records
6986
@db.execute 'CREATE TABLE "things" ("name" varchar(20) CONSTRAINT "index_things_on_name" UNIQUE)'
7087
stmt = @db.prepare("INSERT INTO things(name) VALUES(?)")

0 commit comments

Comments
 (0)