@@ -48,6 +48,7 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self)
4848 rb_raise (rb_eRuntimeError , "%s" , sqlite3_errmsg (ctx -> db ));
4949
5050 rb_iv_set (self , "@tracefunc" , Qnil );
51+ rb_iv_set (self , "@authorizer" , Qnil );
5152
5253 if (rb_block_given_p ()) {
5354 rb_yield (self );
@@ -382,6 +383,53 @@ static VALUE changes(VALUE self)
382383 return INT2NUM (sqlite3_changes (ctx -> db ));
383384}
384385
386+ static int rb_sqlite3_auth (
387+ void * ctx ,
388+ int _action ,
389+ const char * _a ,
390+ const char * _b ,
391+ const char * _c ,
392+ const char * _d )
393+ {
394+ VALUE self = (VALUE )ctx ;
395+ VALUE action = INT2NUM (_action );
396+ VALUE a = _a ? rb_str_new2 (_a ) : Qnil ;
397+ VALUE b = _b ? rb_str_new2 (_b ) : Qnil ;
398+ VALUE c = _c ? rb_str_new2 (_c ) : Qnil ;
399+ VALUE d = _d ? rb_str_new2 (_d ) : Qnil ;
400+ VALUE callback = rb_iv_get (self , "@authorizer" );
401+ VALUE result = rb_funcall (callback , rb_intern ("call" ), 5 , action , a , b , c , d );
402+
403+ if (T_FIXNUM == TYPE (result )) return (int )NUM2INT (result );
404+ if (Qtrue == result ) return SQLITE_OK ;
405+ if (Qfalse == result ) return SQLITE_DENY ;
406+
407+ return SQLITE_IGNORE ;
408+ }
409+
410+ /* call-seq: set_authorizer = auth
411+ *
412+ * Set the authorizer for this database. +auth+ must respond to +call+, and
413+ * +call+ must take 5 arguments.
414+ */
415+ static VALUE set_authorizer (VALUE self , VALUE authorizer )
416+ {
417+ sqlite3RubyPtr ctx ;
418+ Data_Get_Struct (self , sqlite3Ruby , ctx );
419+ REQUIRE_OPEN_DB (ctx );
420+
421+ int status = sqlite3_set_authorizer (
422+ ctx -> db , NIL_P (authorizer ) ? NULL : rb_sqlite3_auth , (void * )self
423+ );
424+
425+ if (SQLITE_OK != status )
426+ rb_raise (rb_eRuntimeError , "%s" , sqlite3_errmsg (ctx -> db ));
427+
428+ rb_iv_set (self , "@authorizer" , authorizer );
429+
430+ return self ;
431+ }
432+
385433void init_sqlite3_database ()
386434{
387435 cSqlite3Database = rb_define_class_under (mSqlite3 , "Database" , rb_cObject );
@@ -400,4 +448,5 @@ void init_sqlite3_database()
400448 rb_define_method (cSqlite3Database , "errcode" , errcode , 0 );
401449 rb_define_method (cSqlite3Database , "complete?" , complete_p , 1 );
402450 rb_define_method (cSqlite3Database , "changes" , changes , 0 );
451+ rb_define_method (cSqlite3Database , "authorizer=" , set_authorizer , 1 );
403452}
0 commit comments