11#include <sqlite3_ruby.h>
22
33#define REQUIRE_OPEN_STMT (_ctxt ) \
4- if(!_ctxt->st) \
4+ if (!_ctxt->st) \
55 rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a closed statement");
66
7- static void
8- require_open_db (VALUE stmt_rb )
9- {
10- VALUE closed_p = rb_funcall (
11- rb_iv_get (stmt_rb , "@connection" ),
12- rb_intern ("closed?" ), 0 );
13-
14- if (RTEST (closed_p )) {
15- rb_raise (rb_path2class ("SQLite3::Exception" ),
16- "cannot use a statement associated with a closed database" );
17- }
18- }
19-
7+ #define REQUIRE_LIVE_DB (_ctxt ) \
8+ if (_ctxt->db->flags & SQLITE_DATABASE_DISCARDED) \
9+ rb_raise(rb_path2class("SQLite3::Exception"), "cannot use a statement associated with a discarded database");
2010
2111VALUE cSqlite3Statement ;
2212
@@ -71,6 +61,11 @@ prepare(VALUE self, VALUE db, VALUE sql)
7161
7262 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
7363
64+ /* Dereferencing a pointer to the database struct will be faster than accessing it through the
65+ * instance variable @connection. The struct pointer is guaranteed to be live because instance
66+ * variable will keep it from being GCed. */
67+ ctx -> db = db_ctx ;
68+
7469#ifdef HAVE_SQLITE3_PREPARE_V2
7570 status = sqlite3_prepare_v2 (
7671#else
@@ -135,7 +130,7 @@ step(VALUE self)
135130
136131 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
137132
138- require_open_db ( self );
133+ REQUIRE_LIVE_DB ( ctx );
139134 REQUIRE_OPEN_STMT (ctx );
140135
141136 if (ctx -> done_p ) { return Qnil ; }
@@ -232,7 +227,7 @@ bind_param(VALUE self, VALUE key, VALUE value)
232227
233228 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
234229
235- require_open_db ( self );
230+ REQUIRE_LIVE_DB ( ctx );
236231 REQUIRE_OPEN_STMT (ctx );
237232
238233 switch (TYPE (key )) {
@@ -326,7 +321,7 @@ reset_bang(VALUE self)
326321
327322 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
328323
329- require_open_db ( self );
324+ REQUIRE_LIVE_DB ( ctx );
330325 REQUIRE_OPEN_STMT (ctx );
331326
332327 sqlite3_reset (ctx -> st );
@@ -348,7 +343,7 @@ clear_bindings_bang(VALUE self)
348343
349344 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
350345
351- require_open_db ( self );
346+ REQUIRE_LIVE_DB ( ctx );
352347 REQUIRE_OPEN_STMT (ctx );
353348
354349 sqlite3_clear_bindings (ctx -> st );
@@ -382,7 +377,7 @@ column_count(VALUE self)
382377 sqlite3StmtRubyPtr ctx ;
383378 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
384379
385- require_open_db ( self );
380+ REQUIRE_LIVE_DB ( ctx );
386381 REQUIRE_OPEN_STMT (ctx );
387382
388383 return INT2NUM (sqlite3_column_count (ctx -> st ));
@@ -415,7 +410,7 @@ column_name(VALUE self, VALUE index)
415410
416411 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
417412
418- require_open_db ( self );
413+ REQUIRE_LIVE_DB ( ctx );
419414 REQUIRE_OPEN_STMT (ctx );
420415
421416 name = sqlite3_column_name (ctx -> st , (int )NUM2INT (index ));
@@ -440,7 +435,7 @@ column_decltype(VALUE self, VALUE index)
440435
441436 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
442437
443- require_open_db ( self );
438+ REQUIRE_LIVE_DB ( ctx );
444439 REQUIRE_OPEN_STMT (ctx );
445440
446441 name = sqlite3_column_decltype (ctx -> st , (int )NUM2INT (index ));
@@ -459,7 +454,7 @@ bind_parameter_count(VALUE self)
459454 sqlite3StmtRubyPtr ctx ;
460455 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
461456
462- require_open_db ( self );
457+ REQUIRE_LIVE_DB ( ctx );
463458 REQUIRE_OPEN_STMT (ctx );
464459
465460 return INT2NUM (sqlite3_bind_parameter_count (ctx -> st ));
@@ -568,7 +563,7 @@ stats_as_hash(VALUE self)
568563 sqlite3StmtRubyPtr ctx ;
569564 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
570565
571- require_open_db ( self );
566+ REQUIRE_LIVE_DB ( ctx );
572567 REQUIRE_OPEN_STMT (ctx );
573568
574569 VALUE arg = rb_hash_new ();
@@ -587,7 +582,7 @@ stat_for(VALUE self, VALUE key)
587582 sqlite3StmtRubyPtr ctx ;
588583 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
589584
590- require_open_db ( self );
585+ REQUIRE_LIVE_DB ( ctx );
591586 REQUIRE_OPEN_STMT (ctx );
592587
593588 if (SYMBOL_P (key )) {
@@ -609,7 +604,7 @@ memused(VALUE self)
609604 sqlite3StmtRubyPtr ctx ;
610605 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
611606
612- require_open_db ( self );
607+ REQUIRE_LIVE_DB ( ctx );
613608 REQUIRE_OPEN_STMT (ctx );
614609
615610 return INT2NUM (sqlite3_stmt_status (ctx -> st , SQLITE_STMTSTATUS_MEMUSED , 0 ));
@@ -628,7 +623,7 @@ database_name(VALUE self, VALUE index)
628623 sqlite3StmtRubyPtr ctx ;
629624 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
630625
631- require_open_db ( self );
626+ REQUIRE_LIVE_DB ( ctx );
632627 REQUIRE_OPEN_STMT (ctx );
633628
634629 return SQLITE3_UTF8_STR_NEW2 (
@@ -647,7 +642,7 @@ get_sql(VALUE self)
647642 sqlite3StmtRubyPtr ctx ;
648643 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
649644
650- require_open_db ( self );
645+ REQUIRE_LIVE_DB ( ctx );
651646 REQUIRE_OPEN_STMT (ctx );
652647
653648 return rb_obj_freeze (SQLITE3_UTF8_STR_NEW2 (sqlite3_sql (ctx -> st )));
@@ -667,7 +662,7 @@ get_expanded_sql(VALUE self)
667662
668663 TypedData_Get_Struct (self , sqlite3StmtRuby , & statement_type , ctx );
669664
670- require_open_db ( self );
665+ REQUIRE_LIVE_DB ( ctx );
671666 REQUIRE_OPEN_STMT (ctx );
672667
673668 expanded_sql = sqlite3_expanded_sql (ctx -> st );
0 commit comments