@@ -259,6 +259,44 @@ busy_handler(int argc, VALUE *argv, VALUE self)
259
259
return self ;
260
260
}
261
261
262
+ static int
263
+ rb_sqlite3_statement_timeout (void * context )
264
+ {
265
+ sqlite3RubyPtr ctx = (sqlite3RubyPtr )context ;
266
+ struct timespec currentTime ;
267
+ clock_gettime (CLOCK_MONOTONIC , & currentTime );
268
+
269
+ if (!timespecisset (& ctx -> stmt_deadline )) {
270
+ // Set stmt_deadline if not already set
271
+ ctx -> stmt_deadline = currentTime ;
272
+ } else if (timespecafter (& currentTime , & ctx -> stmt_deadline )) {
273
+ return 1 ;
274
+ }
275
+
276
+ return 0 ;
277
+ }
278
+
279
+ /* call-seq: db.statement_timeout = ms
280
+ *
281
+ * Indicates that if a query lasts longer than the indicated number of
282
+ * milliseconds, SQLite should interrupt that query and return an error.
283
+ * By default, SQLite does not interrupt queries. To restore the default
284
+ * behavior, send 0 as the +ms+ parameter.
285
+ */
286
+ static VALUE
287
+ set_statement_timeout (VALUE self , VALUE milliseconds )
288
+ {
289
+ sqlite3RubyPtr ctx ;
290
+ TypedData_Get_Struct (self , sqlite3Ruby , & database_type , ctx );
291
+
292
+ ctx -> stmt_timeout = NUM2INT (milliseconds );
293
+ int n = NUM2INT (milliseconds ) == 0 ? -1 : 1000 ;
294
+
295
+ sqlite3_progress_handler (ctx -> db , n , rb_sqlite3_statement_timeout , (void * )ctx );
296
+
297
+ return self ;
298
+ }
299
+
262
300
/* call-seq: last_insert_row_id
263
301
*
264
302
* Obtains the unique row ID of the last row to be inserted by this Database
@@ -869,6 +907,9 @@ init_sqlite3_database(void)
869
907
rb_define_method (cSqlite3Database , "authorizer=" , set_authorizer , 1 );
870
908
rb_define_method (cSqlite3Database , "busy_handler" , busy_handler , -1 );
871
909
rb_define_method (cSqlite3Database , "busy_timeout=" , set_busy_timeout , 1 );
910
+ #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
911
+ rb_define_method (cSqlite3Database , "statement_timeout=" , set_statement_timeout , 1 );
912
+ #endif
872
913
rb_define_method (cSqlite3Database , "extended_result_codes=" , set_extended_result_codes , 1 );
873
914
rb_define_method (cSqlite3Database , "transaction_active?" , transaction_active_p , 0 );
874
915
rb_define_private_method (cSqlite3Database , "exec_batch" , exec_batch , 2 );
0 commit comments