Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
d030f341369b7f32789cbcf3d0ad9a2a |
User & Date: | drh 2023-01-11 00:27:06 |
Context
2023-01-11
| ||
16:17 | Improved progress-handler and interrupt detection during PRAGMA integrity_check. (check-in: 6db42780 user: drh tags: trunk) | |
00:27 | 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. (check-in: d030f341 user: drh tags: trunk) | |
2023-01-10
| ||
19:57 | When computing the datatypes for columns in a view, use the same datatype name as the underlying table if such is available and is consistent with the computed affinity of the column. Forum thread 7fb1fe9dcf310ef5. (check-in: 497a9836 user: drh tags: trunk) | |
Changes
Changes to src/loadext.c.
︙ | ︙ | |||
506 507 508 509 510 511 512 | sqlite3_serialize, #else 0, 0, #endif sqlite3_db_name, /* Version 3.40.0 and later */ | | > > | 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 | sqlite3_serialize, #else 0, 0, #endif sqlite3_db_name, /* Version 3.40.0 and later */ sqlite3_value_encoding, /* Version 3.41.0 and later */ sqlite3_is_interrupted }; /* True if x is the directory separator character */ #if SQLITE_OS_WIN # define DirSep(X) ((X)=='/'||(X)=='\\') #else |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
1792 1793 1794 1795 1796 1797 1798 | } /* ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR | | > > > > > > > > > > > > > > > > > | 1792 1793 1794 1795 1796 1797 1798 1799 1800 1801 1802 1803 1804 1805 1806 1807 1808 1809 1810 1811 1812 1813 1814 1815 1816 1817 1818 1819 1820 1821 1822 1823 1824 1825 1826 1827 1828 1829 1830 | } /* ** Cause any pending operation to stop at its earliest opportunity. */ void sqlite3_interrupt(sqlite3 *db){ #ifdef SQLITE_ENABLE_API_ARMOR if( !sqlite3SafetyCheckOk(db) && (db==0 || db->eOpenState!=SQLITE_STATE_ZOMBIE) ){ (void)SQLITE_MISUSE_BKPT; return; } #endif 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 ** that it is designed to be called by internal code. The difference is ** that if a malloc() fails in sqlite3_create_function(), an error code ** is returned and the mallocFailed flag cleared. */ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 | ** running statement count reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^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. */ void sqlite3_interrupt(sqlite3*); /* ** CAPI3REF: Determine If An SQL Statement Is Complete ** ** These routines are useful during command-line input to determine if the ** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into | > > > > | 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 | ** running statement count reaches zero are interrupted as if they had been ** running prior to the sqlite3_interrupt() call. ^New SQL statements ** that are started after the running statement count reaches zero are ** not effected by the sqlite3_interrupt(). ** ^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 ** ** These routines are useful during command-line input to determine if the ** currently entered text seems to form a complete SQL statement or ** if additional input is needed before sending the text into |
︙ | ︙ |
Changes to src/sqlite3ext.h.
︙ | ︙ | |||
355 356 357 358 359 360 361 362 363 364 365 366 367 368 | int (*deserialize)(sqlite3*,const char*,unsigned char*, sqlite3_int64,sqlite3_int64,unsigned); unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*, unsigned int); const char *(*db_name)(sqlite3*,int); /* Version 3.40.0 and later */ int (*value_encoding)(sqlite3_value*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( | > > | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 | int (*deserialize)(sqlite3*,const char*,unsigned char*, sqlite3_int64,sqlite3_int64,unsigned); unsigned char *(*serialize)(sqlite3*,const char *,sqlite3_int64*, unsigned int); 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*); }; /* ** This is the function signature used for all extension entry points. It ** is also defined in the file "loadext.c". */ typedef int (*sqlite3_loadext_entry)( |
︙ | ︙ | |||
681 682 683 684 685 686 687 688 689 690 691 692 693 694 | #ifndef SQLITE_OMIT_DESERIALIZE #define sqlite3_deserialize sqlite3_api->deserialize #define sqlite3_serialize sqlite3_api->serialize #endif #define sqlite3_db_name sqlite3_api->db_name /* Version 3.40.0 and later */ #define sqlite3_value_encoding sqlite3_api->value_encoding #endif /* !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) */ #if !defined(SQLITE_CORE) && !defined(SQLITE_OMIT_LOAD_EXTENSION) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; | > > | 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 | #ifndef SQLITE_OMIT_DESERIALIZE #define sqlite3_deserialize sqlite3_api->deserialize #define sqlite3_serialize sqlite3_api->serialize #endif #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) /* This case when the file really is being compiled as a loadable ** extension */ # define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api=0; # define SQLITE_EXTENSION_INIT2(v) sqlite3_api=v; |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
5533 5534 5535 5536 5537 5538 5539 | if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); return TCL_OK; } | < > > > > > > > > > > > > > > > > > > > > > > > | 5533 5534 5535 5536 5537 5538 5539 5540 5541 5542 5543 5544 5545 5546 5547 5548 5549 5550 5551 5552 5553 5554 5555 5556 5557 5558 5559 5560 5561 5562 5563 5564 5565 5566 5567 5568 5569 5570 5571 5572 5573 5574 5575 5576 5577 5578 5579 5580 5581 5582 5583 5584 5585 5586 5587 5588 5589 | if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR; if( Tcl_GetIntFromObj(interp, objv[2], &col) ) return TCL_ERROR; Tcl_SetObjResult(interp, Tcl_NewIntObj(xFunc(pStmt, col))); return TCL_OK; } /* ** Usage: sqlite3_interrupt DB ** ** Trigger an interrupt on DB */ static int SQLITE_TCLAPI test_interrupt( void * clientData, Tcl_Interp *interp, int argc, char **argv ){ sqlite3 *db; 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; sqlite3_interrupt(db); 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 ** ** Delete the user function 'function-name' from database handle DB. It ** is assumed that the user function was created as UTF8, any number of ** arguments (the way the TCL interface does it). |
︙ | ︙ | |||
8627 8628 8629 8630 8631 8632 8633 8634 8635 8636 8637 8638 8639 8640 | { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, { "sqlite_bind", (Tcl_CmdProc*)test_bind }, { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, { "sqlite3_key", (Tcl_CmdProc*)test_key }, { "sqlite3_rekey", (Tcl_CmdProc*)test_rekey }, { "sqlite3_interrupt", (Tcl_CmdProc*)test_interrupt }, { "sqlite_delete_function", (Tcl_CmdProc*)delete_function }, { "sqlite_delete_collation", (Tcl_CmdProc*)delete_collation }, { "sqlite3_get_autocommit", (Tcl_CmdProc*)get_autocommit }, { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, { "printf", (Tcl_CmdProc*)test_printf }, { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address }, | > | 8649 8650 8651 8652 8653 8654 8655 8656 8657 8658 8659 8660 8661 8662 8663 | { "sqlite_register_test_function", (Tcl_CmdProc*)test_register_func }, { "sqlite_abort", (Tcl_CmdProc*)sqlite_abort }, { "sqlite_bind", (Tcl_CmdProc*)test_bind }, { "breakpoint", (Tcl_CmdProc*)test_breakpoint }, { "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 }, { "sqlite3_busy_timeout", (Tcl_CmdProc*)test_busy_timeout }, { "printf", (Tcl_CmdProc*)test_printf }, { "sqlite3IoTrace", (Tcl_CmdProc*)test_io_trace }, { "clang_sanitize_address", (Tcl_CmdProc*)clang_sanitize_address }, |
︙ | ︙ |
Changes to test/interrupt.test.
︙ | ︙ | |||
90 91 92 93 94 95 96 | } $cksum ifcapable {vacuum && !default_autovacuum} { do_test interrupt-2.4 { expr {$::origsize>[file size test.db]} } 1 } ifcapable {explain} { | | > > > > > | > > > > > > > > > | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 | } $cksum ifcapable {vacuum && !default_autovacuum} { do_test interrupt-2.4 { expr {$::origsize>[file size test.db]} } 1 } ifcapable {explain} { do_test interrupt-2.5.1 { sqlite3_is_interrupted $DB } {0} do_test interrupt-2.5.2 { unset -nocomplain ::interrupt_count set ::interrupt_count 0 set sql {EXPLAIN SELECT max(a,b), a, b FROM t1} execsql $sql set rc [catch {db eval $sql { sqlite3_interrupt $DB; incr ::interrupt_count [sqlite3_is_interrupted $DB]; }} msg] lappend rc $msg } {1 interrupted} do_test interrupt-2.5.3 { set ::interrupt_count } {1} } integrity_check interrupt-2.6 do_test interrupt-2.7 { sqlite3_is_interrupted $DB } {0} # Ticket #594. If an interrupt occurs in the middle of a transaction # and that transaction is later rolled back, the internal schema tables do # not reset. # # UPDATE: Interrupting a DML statement in the middle of a transaction now # causes the transaction to roll back. Leaving the transaction open after |
︙ | ︙ |