Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch sqlite3_stmt_retryable Excluding Merge-Ins
This is equivalent to a diff from 87ccdf9cbb to ebada0723a
2017-09-13
| ||
20:20 | Test case update due to PRAGMA integrity_check enhancements in [8525c30c]. No changes to code. (check-in: 43c6023bbf user: drh tags: trunk) | |
18:38 | Experimental sqlite3_stmt_retryable() interface. (Leaf check-in: ebada0723a user: drh tags: sqlite3_stmt_retryable) | |
12:55 | Disable FTS3 matchinfo() tests that assume a littleEndian platform when running on bigEndian. (check-in: 87ccdf9cbb user: drh tags: trunk) | |
00:33 | Improvements to PRAGMA integrity_check for better detection of malformed records. Integrity_check now avoids returning SQLITE_CORRUPT on a corrupt record. Also includes microoptimizations that I stumbled over while working on integrity_check. (check-in: 8525c30c1d user: drh tags: trunk) | |
Changes to src/main.c.
︙ | ︙ | |||
1502 1503 1504 1505 1506 1507 1508 | ** ** This routine is called when an operation failed with a lock. ** If this routine returns non-zero, the lock is retried. If it ** returns 0, the operation aborts with an SQLITE_BUSY error. */ int sqlite3InvokeBusyHandler(BusyHandler *p){ int rc; | | > > > > | 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 | ** ** This routine is called when an operation failed with a lock. ** If this routine returns non-zero, the lock is retried. If it ** returns 0, the operation aborts with an SQLITE_BUSY error. */ int sqlite3InvokeBusyHandler(BusyHandler *p){ int rc; if( p->xFunc==0 || p->nBusy<0 ){ p->nTimeout++; return 0; } rc = p->xFunc(p->pArg, p->nBusy); if( rc==0 ){ p->nTimeout++; p->nBusy = -1; }else{ p->nBusy++; } return rc; } |
︙ | ︙ |
Changes to src/shell.c.
︙ | ︙ | |||
3613 3614 3615 3616 3617 3618 3619 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ /* (not the same as sqlite3_exec) */ ShellState *pArg, /* Pointer to ShellState */ char **pzErrMsg /* Error msg written here */ ){ sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ int rc = SQLITE_OK; /* Return Code */ | | | 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ /* (not the same as sqlite3_exec) */ ShellState *pArg, /* Pointer to ShellState */ char **pzErrMsg /* Error msg written here */ ){ sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ int rc = SQLITE_OK; /* Return Code */ int rc2, rc3; const char *zLeftover; /* Tail of unprocessed SQL */ if( pzErrMsg ){ *pzErrMsg = NULL; } while( zSql[0] && (SQLITE_OK == rc) ){ |
︙ | ︙ | |||
3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 | if( pArg && pArg->scanstatsOn ){ display_scanstats(db, pArg); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ zSql = zLeftover; while( IsSpace(zSql[0]) ) zSql++; | > > > > > > > > > | | > | 3714 3715 3716 3717 3718 3719 3720 3721 3722 3723 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 3740 3741 3742 3743 3744 | if( pArg && pArg->scanstatsOn ){ display_scanstats(db, pArg); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc3 = sqlite3_stmt_retryable(pStmt); rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ zSql = zLeftover; while( IsSpace(zSql[0]) ) zSql++; }else{ if( rc==SQLITE_BUSY ){ if( rc3 ){ raw_printf(pArg->out, "Busy: might succeed on retry\n"); }else{ raw_printf(pArg->out, "Busy: cannot succeed - rollback required\n"); } } if( pzErrMsg ){ *pzErrMsg = save_err_msg(db); } } /* clear saved stmt handle */ if( pArg ){ pArg->pStmt = NULL; } } |
︙ | ︙ |
Changes to src/shell.c.in.
︙ | ︙ | |||
2253 2254 2255 2256 2257 2258 2259 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ /* (not the same as sqlite3_exec) */ ShellState *pArg, /* Pointer to ShellState */ char **pzErrMsg /* Error msg written here */ ){ sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ int rc = SQLITE_OK; /* Return Code */ | | | 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 | int (*xCallback)(void*,int,char**,char**,int*), /* Callback function */ /* (not the same as sqlite3_exec) */ ShellState *pArg, /* Pointer to ShellState */ char **pzErrMsg /* Error msg written here */ ){ sqlite3_stmt *pStmt = NULL; /* Statement to execute. */ int rc = SQLITE_OK; /* Return Code */ int rc2, rc3; const char *zLeftover; /* Tail of unprocessed SQL */ if( pzErrMsg ){ *pzErrMsg = NULL; } while( zSql[0] && (SQLITE_OK == rc) ){ |
︙ | ︙ | |||
2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 | if( pArg && pArg->scanstatsOn ){ display_scanstats(db, pArg); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ zSql = zLeftover; while( IsSpace(zSql[0]) ) zSql++; | > > > > > > > > > | | > | 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371 2372 2373 2374 2375 2376 2377 2378 2379 2380 2381 2382 2383 2384 | if( pArg && pArg->scanstatsOn ){ display_scanstats(db, pArg); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc3 = sqlite3_stmt_retryable(pStmt); rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ zSql = zLeftover; while( IsSpace(zSql[0]) ) zSql++; }else{ if( rc==SQLITE_BUSY ){ if( rc3 ){ raw_printf(pArg->out, "Busy: might succeed on retry\n"); }else{ raw_printf(pArg->out, "Busy: cannot succeed - rollback required\n"); } } if( pzErrMsg ){ *pzErrMsg = save_err_msg(db); } } /* clear saved stmt handle */ if( pArg ){ pArg->pStmt = NULL; } } |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 | ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the ** [prepared statement] S has been stepped at least once using ** [sqlite3_step(S)] but has neither run to completion (returned | > > > > > > > > > > > > | 3760 3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 | ** ^The sqlite3_stmt_readonly() interface returns true for [BEGIN] since ** [BEGIN] merely sets internal flags, but the [BEGIN|BEGIN IMMEDIATE] and ** [BEGIN|BEGIN EXCLUSIVE] commands do touch the database and so ** sqlite3_stmt_readonly() returns false for those commands. */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If An SQL Statement Can Be Retried After SQLITE_BUSY ** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_retryable(X) interface returns true (non-zero) if ** the previous run of [prepared statement] X failed with an ** [SQLITE_BUSY] error but might succeed if run again. If X has not been ** previously run or if the previous run of X did not return SQLITE_BUSY, ** then the result of this function is a meaningless boolean. */ int sqlite3_stmt_retryable(sqlite3_stmt *pStmt); /* ** CAPI3REF: Determine If A Prepared Statement Has Been Reset ** METHOD: sqlite3_stmt ** ** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the ** [prepared statement] S has been stepped at least once using ** [sqlite3_step(S)] but has neither run to completion (returned |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
945 946 947 948 949 950 951 952 953 954 955 956 957 958 | ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { int (*xFunc)(void *,int); /* The busy callback */ void *pArg; /* First arg to busy callback */ int nBusy; /* Incremented with each busy call */ }; /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ | > | 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 | ** callback is currently invoked only from within pager.c. */ typedef struct BusyHandler BusyHandler; struct BusyHandler { int (*xFunc)(void *,int); /* The busy callback */ void *pArg; /* First arg to busy callback */ int nBusy; /* Incremented with each busy call */ u32 nTimeout; /* Number of timeouts */ }; /* ** Name of the master database table. The master database table ** is a special table that holds the names and attributes of all ** user tables and indices. */ |
︙ | ︙ |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
389 390 391 392 393 394 395 396 397 398 399 400 401 402 | bft doingRerun:1; /* True if rerunning after an auto-reprepare */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ | > | 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 | bft doingRerun:1; /* True if rerunning after an auto-reprepare */ bft explain:2; /* True if EXPLAIN present on SQL command */ bft changeCntOn:1; /* True to update the change-counter */ bft runOnlyOnce:1; /* Automatically expire on reset */ bft usesStmtJournal:1; /* True if uses a statement journal */ bft readOnly:1; /* True for statements that do not write */ bft bIsReader:1; /* True for statements that read */ bft retryable:1; /* True if the statement might succeed next time */ yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ yDbMask lockMask; /* Subset of btreeMask that requires a lock */ u32 aCounter[7]; /* Counters used by sqlite3_stmt_status() */ char *zSql; /* Text of the SQL statement that generated this */ void *pFree; /* Free this when deleting the vdbe */ VdbeFrame *pFrame; /* Parent frame */ VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 | /* ** Return true if the prepared statement is guaranteed to not modify the ** database. */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } /* ** Return true if the prepared statement is in need of being reset. */ int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; | > > > > > > > > | 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 | /* ** Return true if the prepared statement is guaranteed to not modify the ** database. */ int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->readOnly : 1; } /* ** Return true if the prepared statement failed with SQLITE_BUSY on its ** previous run but might succeed if tried again. */ int sqlite3_stmt_retryable(sqlite3_stmt *pStmt){ return pStmt ? ((Vdbe*)pStmt)->retryable : 0; } /* ** Return true if the prepared statement is in need of being reset. */ int sqlite3_stmt_busy(sqlite3_stmt *pStmt){ Vdbe *v = (Vdbe*)pStmt; return v!=0 && v->magic==VDBE_MAGIC_RUN && v->pc>=0; |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 | } rc = SQLITE_CONSTRAINT_FOREIGNKEY; }else{ /* The auto-commit flag is true, the vdbe program was successful ** or hit an 'OR FAIL' constraint and there are no deferred foreign ** key constraints to hold up the transaction. This means a commit ** is required. */ rc = vdbeCommit(db, p); } if( rc==SQLITE_BUSY && p->readOnly ){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); | > > | 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 | } rc = SQLITE_CONSTRAINT_FOREIGNKEY; }else{ /* The auto-commit flag is true, the vdbe program was successful ** or hit an 'OR FAIL' constraint and there are no deferred foreign ** key constraints to hold up the transaction. This means a commit ** is required. */ db->busyHandler.nTimeout = 0; rc = vdbeCommit(db, p); p->retryable = db->busyHandler.nTimeout>0; } if( rc==SQLITE_BUSY && p->readOnly ){ sqlite3VdbeLeave(p); return SQLITE_BUSY; }else if( rc!=SQLITE_OK ){ p->rc = rc; sqlite3RollbackAll(db, SQLITE_OK); |
︙ | ︙ |