diff options
author | drh <drh@noemail.net> | 2017-06-09 15:14:41 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2017-06-09 15:14:41 +0000 |
commit | e9acf4b48eb1723721bd7693f6f04ec4d19bb3db (patch) | |
tree | 38a93412969f4356d7e9e63764321405d629a6d5 /src | |
parent | 0282c03abc9f84183cbca8112f81234ba142c464 (diff) | |
parent | c097b309aa9d6d51bc5edfb7e62c14f3af1be72c (diff) | |
download | sqlite-e9acf4b48eb1723721bd7693f6f04ec4d19bb3db.tar.gz sqlite-e9acf4b48eb1723721bd7693f6f04ec4d19bb3db.zip |
Merge enhancements and fixes from trunk.
FossilOrigin-Name: 3fd050c343256c0748256ef183b46df04d9e0da0f81b841dbd336034402b36ab
Diffstat (limited to 'src')
-rw-r--r-- | src/btree.c | 101 | ||||
-rw-r--r-- | src/main.c | 6 | ||||
-rw-r--r-- | src/shell.c | 123 | ||||
-rw-r--r-- | src/sqlite.h.in | 4 | ||||
-rw-r--r-- | src/sqliteInt.h | 3 | ||||
-rw-r--r-- | src/trigger.c | 1 |
6 files changed, 130 insertions, 108 deletions
diff --git a/src/btree.c b/src/btree.c index eeb076c4d..c54433c8e 100644 --- a/src/btree.c +++ b/src/btree.c @@ -771,7 +771,7 @@ static int btreeMoveto( if( pIdxKey==0 ) return SQLITE_NOMEM_BKPT; sqlite3VdbeRecordUnpack(pCur->pKeyInfo, (int)nKey, pKey, pIdxKey); if( pIdxKey->nField==0 ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno); goto moveto_done; } }else{ @@ -1000,7 +1000,7 @@ static int ptrmapGet(BtShared *pBt, Pgno key, u8 *pEType, Pgno *pPgno){ if( pPgno ) *pPgno = get4byte(&pPtrmap[offset+1]); sqlite3PagerUnref(pDbPage); - if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_BKPT; + if( *pEType<1 || *pEType>5 ) return SQLITE_CORRUPT_PGNO(iPtrmap); return SQLITE_OK; } @@ -1385,7 +1385,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ int sz = get2byte(&data[iFree+2]); int top = get2byte(&data[hdr+5]); if( iFree2 ){ - if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_BKPT; + if( iFree+sz>iFree2 ) return SQLITE_CORRUPT_PGNO(pPage->pgno); sz2 = get2byte(&data[iFree2+2]); assert( iFree+sz+sz2+iFree2-(iFree+sz) <= usableSize ); memmove(&data[iFree+sz+sz2], &data[iFree+sz], iFree2-(iFree+sz)); @@ -1416,13 +1416,13 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ ** if PRAGMA cell_size_check=ON. */ if( pc<iCellFirst || pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( pc>=iCellFirst && pc<=iCellLast ); size = pPage->xCellSize(pPage, &src[pc]); cbrk -= size; if( cbrk<iCellFirst || pc+size>usableSize ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( cbrk+size<=usableSize && cbrk>=iCellFirst ); testcase( cbrk+size==usableSize ); @@ -1442,7 +1442,7 @@ static int defragmentPage(MemPage *pPage, int nMaxFrag){ defragment_out: if( data[hdr+7]+cbrk-iCellFirst!=pPage->nFree ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } assert( cbrk>=iCellFirst ); put2byte(&data[hdr+5], cbrk); @@ -1481,7 +1481,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ /* EVIDENCE-OF: R-06866-39125 Freeblocks are always connected in order of ** increasing offset. */ if( pc>usableSize-4 || pc<iAddr+4 ){ - *pRc = SQLITE_CORRUPT_BKPT; + *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); return 0; } /* EVIDENCE-OF: R-22710-53328 The third and fourth bytes of each @@ -1492,7 +1492,7 @@ static u8 *pageFindSlot(MemPage *pPg, int nByte, int *pRc){ testcase( x==4 ); testcase( x==3 ); if( pc < pPg->cellOffset+2*pPg->nCell || size+pc > usableSize ){ - *pRc = SQLITE_CORRUPT_BKPT; + *pRc = SQLITE_CORRUPT_PGNO(pPg->pgno); return 0; }else if( x<4 ){ /* EVIDENCE-OF: R-11498-58022 In a well-formed b-tree page, the total @@ -1559,7 +1559,7 @@ static int allocateSpace(MemPage *pPage, int nByte, int *pIdx){ if( top==0 && pPage->pBt->usableSize==65536 ){ top = 65536; }else{ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } } @@ -1655,11 +1655,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ while( (iFreeBlk = get2byte(&data[iPtr]))<iStart ){ if( iFreeBlk<iPtr+4 ){ if( iFreeBlk==0 ) break; - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } iPtr = iFreeBlk; } - if( iFreeBlk>iLast ) return SQLITE_CORRUPT_BKPT; + if( iFreeBlk>iLast ) return SQLITE_CORRUPT_PGNO(pPage->pgno); assert( iFreeBlk>iPtr || iFreeBlk==0 ); /* At this point: @@ -1670,9 +1670,11 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ */ if( iFreeBlk && iEnd+3>=iFreeBlk ){ nFrag = iFreeBlk - iEnd; - if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_BKPT; + if( iEnd>iFreeBlk ) return SQLITE_CORRUPT_PGNO(pPage->pgno); iEnd = iFreeBlk + get2byte(&data[iFreeBlk+2]); - if( iEnd > pPage->pBt->usableSize ) return SQLITE_CORRUPT_BKPT; + if( iEnd > pPage->pBt->usableSize ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } iSize = iEnd - iStart; iFreeBlk = get2byte(&data[iFreeBlk]); } @@ -1684,20 +1686,20 @@ static int freeSpace(MemPage *pPage, u16 iStart, u16 iSize){ if( iPtr>hdr+1 ){ int iPtrEnd = iPtr + get2byte(&data[iPtr+2]); if( iPtrEnd+3>=iStart ){ - if( iPtrEnd>iStart ) return SQLITE_CORRUPT_BKPT; + if( iPtrEnd>iStart ) return SQLITE_CORRUPT_PGNO(pPage->pgno); nFrag += iStart - iPtrEnd; iSize = iEnd - iPtr; iStart = iPtr; } } - if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_BKPT; + if( nFrag>data[hdr+7] ) return SQLITE_CORRUPT_PGNO(pPage->pgno); data[hdr+7] -= nFrag; } if( iStart==get2byte(&data[hdr+5]) ){ /* The new freeblock is at the beginning of the cell content area, ** so just extend the cell content area rather than create another ** freelist entry */ - if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_BKPT; + if( iPtr!=hdr+1 ) return SQLITE_CORRUPT_PGNO(pPage->pgno); put2byte(&data[hdr+1], iFreeBlk); put2byte(&data[hdr+5], iEnd); }else{ @@ -1765,7 +1767,7 @@ static int decodeFlags(MemPage *pPage, int flagByte){ }else{ /* EVIDENCE-OF: R-47608-56469 Any other value for the b-tree page type is ** an error. */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } pPage->max1bytePayload = pBt->max1bytePayload; return SQLITE_OK; @@ -1805,7 +1807,9 @@ static int btreeInitPage(MemPage *pPage){ data = pPage->aData; /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating ** the b-tree page type. */ - if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT; + if( decodeFlags(pPage, data[hdr]) ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } assert( pBt->pageSize>=512 && pBt->pageSize<=65536 ); pPage->maskPage = (u16)(pBt->pageSize - 1); pPage->nOverflow = 0; @@ -1823,7 +1827,7 @@ static int btreeInitPage(MemPage *pPage){ pPage->nCell = get2byte(&data[hdr+3]); if( pPage->nCell>MX_CELL(pBt) ){ /* To many cells for a single page. The page must be corrupt */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } testcase( pPage->nCell==MX_CELL(pBt) ); /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only @@ -1851,12 +1855,12 @@ static int btreeInitPage(MemPage *pPage){ testcase( pc==iCellFirst ); testcase( pc==iCellLast ); if( pc<iCellFirst || pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } sz = pPage->xCellSize(pPage, &data[pc]); testcase( pc+sz==usableSize ); if( pc+sz>usableSize ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } } if( !pPage->leaf ) iCellLast++; @@ -1874,11 +1878,12 @@ static int btreeInitPage(MemPage *pPage){ /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will ** always be at least one cell before the first freeblock. */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } while( 1 ){ if( pc>iCellLast ){ - return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */ + /* Freeblock off the end of the page */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } next = get2byte(&data[pc]); size = get2byte(&data[pc+2]); @@ -1887,10 +1892,12 @@ static int btreeInitPage(MemPage *pPage){ pc = next; } if( next>0 ){ - return SQLITE_CORRUPT_BKPT; /* Freeblock not in ascending order */ + /* Freeblock not in ascending order */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } if( pc+size>(unsigned int)usableSize ){ - return SQLITE_CORRUPT_BKPT; /* Last freeblock extends past page end */ + /* Last freeblock extends past page end */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } } @@ -1902,7 +1909,7 @@ static int btreeInitPage(MemPage *pPage){ ** area, according to the page header, lies within the page. */ if( nFree>usableSize ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } pPage->nFree = (u16)(nFree - iCellFirst); pPage->isInit = 1; @@ -2069,7 +2076,7 @@ static int getAndInitPage( /* If obtaining a child page for a cursor, we must verify that the page is ** compatible with the root page. */ if( pCur && ((*ppPage)->nCell<1 || (*ppPage)->intKey!=pCur->curIntKey) ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pgno); releasePage(*ppPage); goto getAndInitPage_error; } @@ -3400,7 +3407,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( eType==PTRMAP_OVERFLOW2 ){ /* The pointer is always the first 4 bytes of the page in this case. */ if( get4byte(pPage->aData)!=iFrom ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } put4byte(pPage->aData, iTo); }else{ @@ -3419,7 +3426,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ pPage->xParseCell(pPage, pCell, &info); if( info.nLocal<info.nPayload ){ if( pCell+info.nSize > pPage->aData+pPage->pBt->usableSize ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } if( iFrom==get4byte(pCell+info.nSize-4) ){ put4byte(pCell+info.nSize-4, iTo); @@ -3437,7 +3444,7 @@ static int modifyPagePointer(MemPage *pPage, Pgno iFrom, Pgno iTo, u8 eType){ if( i==nCell ){ if( eType!=PTRMAP_BTREE || get4byte(&pPage->aData[pPage->hdrOffset+8])!=iFrom ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } put4byte(&pPage->aData[pPage->hdrOffset+8], iTo); } @@ -4545,7 +4552,7 @@ static int accessPayload( ** &aPayload[pCur->info.nLocal] > &pPage->aData[pBt->usableSize] ** but is recast into its current form to avoid integer overflow problems */ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pPage->pgno); } /* Check if data must be read/written to/from the btree page itself. */ @@ -4692,7 +4699,8 @@ static int accessPayload( } if( rc==SQLITE_OK && amt>0 ){ - return SQLITE_CORRUPT_BKPT; /* Overflow chain ends prematurely */ + /* Overflow chain ends prematurely */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } return rc; } @@ -4958,7 +4966,7 @@ static int moveToRoot(BtCursor *pCur){ ** (or the freelist). */ assert( pRoot->intKey==1 || pRoot->intKey==0 ); if( pRoot->isInit==0 || (pCur->pKeyInfo==0)!=pRoot->intKey ){ - return SQLITE_CORRUPT_BKPT; + return SQLITE_CORRUPT_PGNO(pCur->apPage[pCur->iPage]->pgno); } skip_init: @@ -5231,7 +5239,9 @@ int sqlite3BtreeMovetoUnpacked( pCell = findCellPastPtr(pPage, idx); if( pPage->intKeyLeaf ){ while( 0x80 <= *(pCell++) ){ - if( pCell>=pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; + if( pCell>=pPage->aDataEnd ){ + return SQLITE_CORRUPT_PGNO(pPage->pgno); + } } } getVarint(pCell, (u64*)&nCellKey); @@ -5304,7 +5314,7 @@ int sqlite3BtreeMovetoUnpacked( testcase( nCell==1 ); /* Invalid key size: 0x80 0x80 0x01 */ testcase( nCell==2 ); /* Minimum legal index key size */ if( nCell<2 ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pPage->pgno); goto moveto_finish; } pCellKey = sqlite3Malloc( nCell+18 ); @@ -5706,7 +5716,7 @@ static int allocateBtreePage( } testcase( iTrunk==mxPage ); if( iTrunk>mxPage || nSearch++ > n ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(pPrevTrunk->pgno); }else{ rc = btreeGetUnusedPage(pBt, iTrunk, &pTrunk, 0); } @@ -5735,7 +5745,7 @@ static int allocateBtreePage( TRACE(("ALLOCATE: %d trunk - %d free pages left\n", *pPgno, n-1)); }else if( k>(u32)(pBt->usableSize/4 - 2) ){ /* Value of k is out of range. Database corruption */ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; #ifndef SQLITE_OMIT_AUTOVACUUM }else if( searchList @@ -5769,7 +5779,7 @@ static int allocateBtreePage( MemPage *pNewTrunk; Pgno iNewTrunk = get4byte(&pTrunk->aData[8]); if( iNewTrunk>mxPage ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iNewTrunk==mxPage ); @@ -5834,7 +5844,7 @@ static int allocateBtreePage( iPage = get4byte(&aData[8+closest*4]); testcase( iPage==mxPage ); if( iPage>mxPage ){ - rc = SQLITE_CORRUPT_BKPT; + rc = SQLITE_CORRUPT_PGNO(iTrunk); goto end_allocate_page; } testcase( iPage==mxPage ); @@ -6104,7 +6114,8 @@ static int clearCell( return SQLITE_OK; /* No overflow pages. Return without doing anything */ } if( pCell+pInfo->nSize-1 > pPage->aData+pPage->maskPage ){ - return SQLITE_CORRUPT_BKPT; /* Cell extends past end of page */ + /* Cell extends past end of page */ + return SQLITE_CORRUPT_PGNO(pPage->pgno); } ovflPgno = get4byte(pCell + pInfo->nSize - 4); assert( pBt->usableSize > 4 ); @@ -8162,12 +8173,18 @@ int sqlite3BtreeInsert( memcpy(newCell, oldCell, 4); } rc = clearCell(pPage, oldCell, &info); - if( info.nSize==szNew && info.nLocal==info.nPayload ){ + if( info.nSize==szNew && info.nLocal==info.nPayload + && (!ISAUTOVACUUM || szNew<pPage->minLocal) + ){ /* Overwrite the old cell with the new if they are the same size. ** We could also try to do this if the old cell is smaller, then add ** the leftover space to the free list. But experiments show that ** doing that is no faster then skipping this optimization and just - ** calling dropCell() and insertCell(). */ + ** calling dropCell() and insertCell(). + ** + ** This optimization cannot be used on an autovacuum database if the + ** new entry uses overflow pages, as the insertCell() call below is + ** necessary to add the PTRMAP_OVERFLOW1 pointer-map entry. */ assert( rc==SQLITE_OK ); /* clearCell never fails when nLocal==nPayload */ if( oldCell+szNew > pPage->aDataEnd ) return SQLITE_CORRUPT_BKPT; memcpy(oldCell, newCell, szNew); diff --git a/src/main.c b/src/main.c index 36e10383a..44b7d5df8 100644 --- a/src/main.c +++ b/src/main.c @@ -3338,6 +3338,12 @@ int sqlite3CantopenError(int lineno){ return reportError(SQLITE_CANTOPEN, lineno, "cannot open file"); } #ifdef SQLITE_DEBUG +int sqlite3CorruptPgnoError(int lineno, Pgno pgno){ + char zMsg[100]; + sqlite3_snprintf(sizeof(zMsg), zMsg, "database corruption page %d", pgno); + testcase( sqlite3GlobalConfig.xLog!=0 ); + return reportError(SQLITE_CORRUPT, lineno, zMsg); +} int sqlite3NomemError(int lineno){ testcase( sqlite3GlobalConfig.xLog!=0 ); return reportError(SQLITE_NOMEM, lineno, "OOM"); diff --git a/src/shell.c b/src/shell.c index 6a436da48..36f6970d1 100644 --- a/src/shell.c +++ b/src/shell.c @@ -6000,19 +6000,11 @@ static int do_meta_command(char *zLine, ShellState *p){ int bIsInit = 0; /* True to initialize the SELFTEST table */ int bVerbose = 0; /* Verbose output */ int bSelftestExists; /* True if SELFTEST already exists */ - char **azTest = 0; /* Content of the SELFTEST table */ - int nRow = 0; /* Number of rows in the SELFTEST table */ - int nCol = 4; /* Number of columns in the SELFTEST table */ - int i; /* Loop counter */ + int i, k; /* Loop counters */ int nTest = 0; /* Number of tests runs */ int nErr = 0; /* Number of errors seen */ ShellText str; /* Answer for a query */ - static char *azDefaultTest[] = { - 0, 0, 0, 0, - "0", "memo", "Missing SELFTEST table - default checks only", "", - "1", "run", "PRAGMA integrity_check", "ok" - }; - static const int nDefaultRow = 2; + sqlite3_stmt *pStmt = 0; /* Query against the SELFTEST table */ open_db(p,0); for(i=1; i<nArg; i++){ @@ -6042,70 +6034,71 @@ static int do_meta_command(char *zLine, ShellState *p){ createSelftestTable(p); bSelftestExists = 1; } - if( bSelftestExists ){ - rc = sqlite3_get_table(p->db, - "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", - &azTest, &nRow, &nCol, 0); + initText(&str); + appendText(&str, "x", 0); + for(k=bSelftestExists; k>=0; k--){ + if( k==1 ){ + rc = sqlite3_prepare_v2(p->db, + "SELECT tno,op,cmd,ans FROM selftest ORDER BY tno", + -1, &pStmt, 0); + }else{ + rc = sqlite3_prepare_v2(p->db, + "VALUES(0,'memo','Missing SELFTEST table - default checks only','')," + " (1,'run','PRAGMA integrity_check','ok')", + -1, &pStmt, 0); + } if( rc ){ raw_printf(stderr, "Error querying the selftest table\n"); rc = 1; - sqlite3_free_table(azTest); + sqlite3_finalize(pStmt); goto meta_command_exit; - }else if( nRow==0 ){ - sqlite3_free_table(azTest); - azTest = azDefaultTest; - nRow = nDefaultRow; } - }else{ - azTest = azDefaultTest; - nRow = nDefaultRow; - } - initText(&str); - appendText(&str, "x", 0); - for(i=1; i<=nRow; i++){ - int tno = atoi(azTest[i*nCol]); - const char *zOp = azTest[i*nCol+1]; - const char *zSql = azTest[i*nCol+2]; - const char *zAns = azTest[i*nCol+3]; - - if( bVerbose>0 ){ - char *zQuote = sqlite3_mprintf("%q", zSql); - printf("%d: %s %s\n", tno, zOp, zSql); - sqlite3_free(zQuote); - } - if( strcmp(zOp,"memo")==0 ){ - utf8_printf(p->out, "%s\n", zSql); - }else - if( strcmp(zOp,"run")==0 ){ - char *zErrMsg = 0; - str.n = 0; - str.z[0] = 0; - rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); - nTest++; - if( bVerbose ){ - utf8_printf(p->out, "Result: %s\n", str.z); + for(i=1; sqlite3_step(pStmt)==SQLITE_ROW; i++){ + int tno = sqlite3_column_int(pStmt, 0); + const char *zOp = (const char*)sqlite3_column_text(pStmt, 1); + const char *zSql = (const char*)sqlite3_column_text(pStmt, 2); + const char *zAns = (const char*)sqlite3_column_text(pStmt, 3); + + k = 0; + if( bVerbose>0 ){ + char *zQuote = sqlite3_mprintf("%q", zSql); + printf("%d: %s %s\n", tno, zOp, zSql); + sqlite3_free(zQuote); } - if( rc || zErrMsg ){ - nErr++; - rc = 1; - utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); - sqlite3_free(zErrMsg); - }else if( strcmp(zAns,str.z)!=0 ){ - nErr++; + if( strcmp(zOp,"memo")==0 ){ + utf8_printf(p->out, "%s\n", zSql); + }else + if( strcmp(zOp,"run")==0 ){ + char *zErrMsg = 0; + str.n = 0; + str.z[0] = 0; + rc = sqlite3_exec(p->db, zSql, captureOutputCallback, &str, &zErrMsg); + nTest++; + if( bVerbose ){ + utf8_printf(p->out, "Result: %s\n", str.z); + } + if( rc || zErrMsg ){ + nErr++; + rc = 1; + utf8_printf(p->out, "%d: error-code-%d: %s\n", tno, rc, zErrMsg); + sqlite3_free(zErrMsg); + }else if( strcmp(zAns,str.z)!=0 ){ + nErr++; + rc = 1; + utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); + utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); + } + }else + { + utf8_printf(stderr, + "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); rc = 1; - utf8_printf(p->out, "%d: Expected: [%s]\n", tno, zAns); - utf8_printf(p->out, "%d: Got: [%s]\n", tno, str.z); + break; } - }else - { - utf8_printf(stderr, - "Unknown operation \"%s\" on selftest line %d\n", zOp, tno); - rc = 1; - break; - } - } + } /* End loop over rows of content from SELFTEST */ + sqlite3_finalize(pStmt); + } /* End loop over k */ freeText(&str); - if( azTest!=azDefaultTest ) sqlite3_free_table(azTest); utf8_printf(p->out, "%d errors out of %d tests\n", nErr, nTest); }else diff --git a/src/sqlite.h.in b/src/sqlite.h.in index b1fd43800..73d13a999 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -5668,7 +5668,9 @@ SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N); ** ^If the column-name parameter to sqlite3_table_column_metadata() is a ** NULL pointer, then this routine simply checks for the existence of the ** table and returns SQLITE_OK if the table exists and SQLITE_ERROR if it -** does not. +** does not. If the table name parameter T in a call to +** sqlite3_table_column_metadata(X,D,T,C,...) is NULL then the result is +** undefined behavior. ** ** ^The column is identified by the second, third and fourth parameters to ** this function. ^(The second parameter is either the name of the database diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 8c52e02c8..9252c352b 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -3402,11 +3402,14 @@ int sqlite3CantopenError(int); #ifdef SQLITE_DEBUG int sqlite3NomemError(int); int sqlite3IoerrnomemError(int); + int sqlite3CorruptPgnoError(int,Pgno); # define SQLITE_NOMEM_BKPT sqlite3NomemError(__LINE__) # define SQLITE_IOERR_NOMEM_BKPT sqlite3IoerrnomemError(__LINE__) +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptPgnoError(__LINE__,(P)) #else # define SQLITE_NOMEM_BKPT SQLITE_NOMEM # define SQLITE_IOERR_NOMEM_BKPT SQLITE_IOERR_NOMEM +# define SQLITE_CORRUPT_PGNO(P) sqlite3CorruptError(__LINE__) #endif /* diff --git a/src/trigger.c b/src/trigger.c index bdf964084..dfa094141 100644 --- a/src/trigger.c +++ b/src/trigger.c @@ -306,6 +306,7 @@ void sqlite3FinishTrigger( if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, iDb); z = sqlite3DbStrNDup(db, (char*)pAll->z, pAll->n); + testcase( z==0 ); sqlite3NestedParse(pParse, "INSERT INTO %Q.%s VALUES('trigger',%Q,%Q,0,'CREATE TRIGGER %q')", db->aDb[iDb].zDbSName, MASTER_NAME, zName, |