1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-11-14 00:22:38 +03:00

Add a new sqlite3_is_interrupted() interface that can be used by long-running

app-defined functions and similar to see if they need to exit early due to
an sqlite3_interrupt() call.

FossilOrigin-Name: d030f341369b7f32789cbcf3d0ad9a2ac5cad99a56dac7dfe68b7f06dc339b17
This commit is contained in:
drh
2023-01-11 00:27:06 +00:00
parent 706631de32
commit 3b7a19b033
8 changed files with 81 additions and 17 deletions

View File

@@ -510,7 +510,9 @@ static const sqlite3_api_routines sqlite3Apis = {
#endif
sqlite3_db_name,
/* Version 3.40.0 and later */
sqlite3_value_encoding
sqlite3_value_encoding,
/* Version 3.41.0 and later */
sqlite3_is_interrupted
};
/* True if x is the directory separator character

View File

@@ -1796,7 +1796,9 @@ int sqlite3_busy_timeout(sqlite3 *db, int ms){
*/
void sqlite3_interrupt(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) ){
if( !sqlite3SafetyCheckOk(db)
&& (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE)
){
(void)SQLITE_MISUSE_BKPT;
return;
}
@@ -1804,6 +1806,21 @@ void sqlite3_interrupt(sqlite3 *db){
AtomicStore(&db->u1.isInterrupted, 1);
}
/*
** Return true or false depending on whether or not an interrupt is
** pending on connection db.
*/
int sqlite3_is_interrupted(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db)
&& (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE)
){
(void)SQLITE_MISUSE_BKPT;
return 0;
}
#endif
return AtomicLoad(&db->u1.isInterrupted)!=0;
}
/*
** This function is exactly the same as sqlite3_create_function(), except

View File

@@ -2679,8 +2679,12 @@ sqlite3_int64 sqlite3_total_changes64(sqlite3*);
** ^A call to sqlite3_interrupt(D) that occurs when there are no running
** SQL statements is a no-op and has no effect on SQL statements
** that are started after the sqlite3_interrupt() call returns.
**
** ^The [sqlite3_is_interrupted(D)] interface can be used to determine whether
** or not an interrupt is currently in effect for [database connection] D.
*/
void sqlite3_interrupt(sqlite3*);
int sqlite3_is_interrupted(sqlite3*);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete

View File

@@ -359,6 +359,8 @@ struct sqlite3_api_routines {
const char *(*db_name)(sqlite3*,int);
/* Version 3.40.0 and later */
int (*value_encoding)(sqlite3_value*);
/* Version 3.41.0 and later */
int (*is_interrupted)(sqlite3*);
};
/*
@@ -685,6 +687,8 @@ typedef int (*sqlite3_loadext_entry)(
#define sqlite3_db_name sqlite3_api->db_name
/* Version 3.40.0 and later */
#define sqlite3_value_encoding sqlite3_api->value_encoding
/* Version 3.41.0 and later */
#define sqlite3_is_interrupted sqlite3_api->is_interrupted
#endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */
#if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION)

View File

@@ -5537,7 +5537,6 @@ static int SQLITE_TCLAPI test_stmt_int(
return TCL_OK;
}
/*
** Usage: sqlite3_interrupt DB
**
@@ -5559,6 +5558,29 @@ static int SQLITE_TCLAPI test_interrupt(
return TCL_OK;
}
/*
** Usage: sqlite3_is_interrupted DB
**
** return true if an interrupt is current in effect on DB
*/
static int SQLITE_TCLAPI test_is_interrupted(
void * clientData,
Tcl_Interp *interp,
int argc,
char **argv
){
sqlite3 *db;
int rc;
if( argc!=2 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB", 0);
return TCL_ERROR;
}
if( getDbPointer(interp, argv[1], &db) ) return TCL_ERROR;
rc = sqlite3_is_interrupted(db);
Tcl_AppendResult(interp, rc ? "1" : "0", (void*)0);
return TCL_OK;
}
/*
** Usage: sqlite_delete_function DB function-name
**
@@ -8631,6 +8653,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
{ "sqlite3_key", (Tcl_CmdProc*)test_key },
{ "sqlite3_rekey", (Tcl_CmdProc*)test_rekey },
{ "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt },
{ "sqlite3_is_interrupted", (Tcl_CmdProc*)test_is_interrupted },
{ "sqlite_delete_function", (Tcl_CmdProc*)delete_function },
{ "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation },
{ "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit },