diff options
author | drh <drh@noemail.net> | 2014-03-06 13:48:31 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2014-03-06 13:48:31 +0000 |
commit | f2eded23f593efc061694c04a8f987f0831700aa (patch) | |
tree | 06e75392380dc4145da906559f2c7a7da425a516 /src | |
parent | 3bde1354ff995a17adbdd09bc55bc2bf67220966 (diff) | |
parent | fe70510aa757c4579e9943052f828a3cad5d6d74 (diff) | |
download | sqlite-f2eded23f593efc061694c04a8f987f0831700aa.tar.gz sqlite-f2eded23f593efc061694c04a8f987f0831700aa.zip |
Merge the latest 3.8.4 tweaks from trunk.
FossilOrigin-Name: 1ed463d91866182fbc884fb88770717ee5bf33ce
Diffstat (limited to 'src')
-rw-r--r-- | src/analyze.c | 7 | ||||
-rw-r--r-- | src/btree.c | 2 | ||||
-rw-r--r-- | src/insert.c | 9 | ||||
-rw-r--r-- | src/os_win.c | 17 | ||||
-rw-r--r-- | src/shell.c | 9 | ||||
-rw-r--r-- | src/sqliteInt.h | 35 | ||||
-rw-r--r-- | src/vdbe.c | 11 | ||||
-rw-r--r-- | src/vdbeaux.c | 37 | ||||
-rw-r--r-- | src/where.c | 2 |
9 files changed, 110 insertions, 19 deletions
diff --git a/src/analyze.c b/src/analyze.c index 235a2abaf..2a03e292c 100644 --- a/src/analyze.c +++ b/src/analyze.c @@ -1178,7 +1178,10 @@ static void analyzeOneTable( callStatGet(v, regStat4, STAT_GET_NLT, regLt); callStatGet(v, regStat4, STAT_GET_NDLT, regDLt); sqlite3VdbeAddOp4Int(v, seekOp, iTabCur, addrNext, regSampleRowid, 0); - VdbeCoverage(v); + /* We know that the regSampleRowid row exists because it was read by + ** the previous loop. Thus the not-found jump of seekOp will never + ** be taken */ + VdbeCoverageNeverTaken(v); #ifdef SQLITE_ENABLE_STAT3 sqlite3ExprCodeGetColumnOfTable(v, pTab, iTabCur, pIdx->aiColumn[0], regSample); @@ -1192,7 +1195,7 @@ static void analyzeOneTable( sqlite3VdbeAddOp3(v, OP_MakeRecord, regTabname, 6, regTemp); sqlite3VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); sqlite3VdbeAddOp3(v, OP_Insert, iStatCur+1, regTemp, regNewRowid); - sqlite3VdbeAddOp2(v, OP_Goto, 0, addrNext); + sqlite3VdbeAddOp2(v, OP_Goto, 1, addrNext); /* P1==1 for end-of-loop */ sqlite3VdbeJumpHere(v, addrIsNull); } #endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */ diff --git a/src/btree.c b/src/btree.c index eebf6f1e8..29ead1c67 100644 --- a/src/btree.c +++ b/src/btree.c @@ -4576,7 +4576,7 @@ int sqlite3BtreeMovetoUnpacked( || pIdxKey->default_rc==-1 ); }else{ - xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */ + xRecordCompare = 0; /* All keys are integers */ } rc = moveToRoot(pCur); diff --git a/src/insert.c b/src/insert.c index e6a589575..a0cf527c9 100644 --- a/src/insert.c +++ b/src/insert.c @@ -101,13 +101,13 @@ const char *sqlite3IndexAffinityStr(Vdbe *v, Index *pIdx){ ** Compute the affinity string for table pTab, if it has not already been ** computed. As an optimization, omit trailing SQLITE_AFF_NONE affinities. ** -** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values and +** If the affinity exists (if it is no entirely SQLITE_AFF_NONE values) and ** if iReg>0 then code an OP_Affinity opcode that will set the affinities ** for register iReg and following. Or if affinities exists and iReg==0, ** then just set the P4 operand of the previous opcode (which should be ** an OP_MakeRecord) to the affinity string. ** -** A column affinity string has one character column: +** A column affinity string has one character per column: ** ** Character Column affinity ** ------------------------------ @@ -148,10 +148,9 @@ void sqlite3TableAffinity(Vdbe *v, Table *pTab, int iReg){ /* ** Return non-zero if the table pTab in database iDb or any of its indices -** have been opened at any point in the VDBE program beginning at location -** iStartAddr throught the end of the program. This is used to see if +** have been opened at any point in the VDBE program. This is used to see if ** a statement of the form "INSERT INTO <iDb, pTab> SELECT ..." can -** run without using temporary table for the results of the SELECT. +** run without using a temporary table for the results of the SELECT. */ static int readsTable(Parse *p, int iDb, Table *pTab){ Vdbe *v = sqlite3GetVdbe(p); diff --git a/src/os_win.c b/src/os_win.c index 55ade5c7e..287dad3b5 100644 --- a/src/os_win.c +++ b/src/os_win.c @@ -5137,8 +5137,25 @@ static int winFullPathname( */ static void *winDlOpen(sqlite3_vfs *pVfs, const char *zFilename){ HANDLE h; +#if defined(__CYGWIN__) + int nFull = pVfs->mxPathname+1; + char *zFull = sqlite3MallocZero( nFull ); + void *zConverted = 0; + if( zFull==0 ){ + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + if( winFullPathname(pVfs, zFilename, nFull, zFull)!=SQLITE_OK ){ + sqlite3_free(zFull); + OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); + return 0; + } + zConverted = winConvertFromUtf8Filename(zFull); + sqlite3_free(zFull); +#else void *zConverted = winConvertFromUtf8Filename(zFilename); UNUSED_PARAMETER(pVfs); +#endif if( zConverted==0 ){ OSTRACE(("DLOPEN name=%s, handle=%p\n", zFilename, (void*)0)); return 0; diff --git a/src/shell.c b/src/shell.c index 7ecedfd3c..2cff102e9 100644 --- a/src/shell.c +++ b/src/shell.c @@ -1184,6 +1184,7 @@ static int str_in_array(const char *zStr, const char **azArray){ ** * For each "Goto", if the jump destination is earlier in the program ** and ends on one of: ** Yield SeekGt SeekLt RowSetRead Rewind +** or if the P1 parameter is one instead of zero, ** then indent all opcodes between the earlier instruction ** and "Goto" by 2 spaces. */ @@ -1231,7 +1232,9 @@ static void explain_data_prepare(struct callback_data *p, sqlite3_stmt *pSql){ if( str_in_array(zOp, azNext) ){ for(i=p2op; i<iOp; i++) p->aiIndent[i] += 2; } - if( str_in_array(zOp, azGoto) && p2op<p->nIndent && abYield[p2op] ){ + if( str_in_array(zOp, azGoto) && p2op<p->nIndent + && (abYield[p2op] || sqlite3_column_int(pSql, 2)) + ){ for(i=p2op+1; i<iOp; i++) p->aiIndent[i] += 2; } } @@ -3817,8 +3820,8 @@ int main(int argc, char **argv){ ); if( warnInmemoryDb ){ printf("Connected to a "); - printBold("transient in-memory database."); - printf("\nUse \".open FILENAME\" to reopen on a " + printBold("transient in-memory database"); + printf(".\nUse \".open FILENAME\" to reopen on a " "persistent database.\n"); } zHome = find_home_dir(); diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 69a61ad5a..a9a6e60d1 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -47,8 +47,41 @@ # define _LARGEFILE_SOURCE 1 #endif +/* +** For MinGW, check to see if we can include the header file containing its +** version information, among other things. Normally, this internal MinGW +** header file would [only] be included automatically by other MinGW header +** files; however, the contained version information is now required by this +** header file to work around binary compatibility issues (see below) and +** this is the only known way to reliably obtain it. This entire #if block +** would be completely unnecessary if there was any other way of detecting +** MinGW via their preprocessor (e.g. if they customized their GCC to define +** some MinGW-specific macros). When compiling for MinGW, either the +** _HAVE_MINGW_H or _HAVE__MINGW_H (note the extra underscore) macro must be +** defined; otherwise, detection of conditions specific to MinGW will be +** disabled. +*/ +#if defined(_HAVE_MINGW_H) +# include "mingw.h" +#elif defined(_HAVE__MINGW_H) +# include "_mingw.h" +#endif + +/* +** For MinGW version 4.x (and higher), check to see if the _USE_32BIT_TIME_T +** define is required to maintain binary compatibility with the MSVC runtime +** library in use (e.g. for Windows XP). +*/ +#if !defined(_USE_32BIT_TIME_T) && !defined(_USE_64BIT_TIME_T) && \ + defined(_WIN32) && !defined(_WIN64) && \ + defined(__MINGW_MAJOR_VERSION) && __MINGW_MAJOR_VERSION >= 4 && \ + defined(__MSVCRT__) +# define _USE_32BIT_TIME_T +#endif + /* The public SQLite interface. The _FILE_OFFSET_BITS macro must appear -** first in QNX. +** first in QNX. Also, the _USE_32BIT_TIME_T macro must appear first for +** MinGW. */ #include "sqlite3.h" diff --git a/src/vdbe.c b/src/vdbe.c index f5a3e1afb..782564e19 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -28,7 +28,7 @@ ** pointer to the string or blob, not the content. If the original ** is changed while the copy is still in use, the string or blob might ** be changed out from under the copy. This macro verifies that nothing -** like that every happens. +** like that ever happens. */ #ifdef SQLITE_DEBUG # define memAboutToChange(P,M) sqlite3VdbeMemAboutToChange(P,M) @@ -681,6 +681,11 @@ int sqlite3VdbeExec( ** The next instruction executed will be ** the one at index P2 from the beginning of ** the program. +** +** The P1 parameter is not actually used by this opcode. However, it +** is sometimes set to 1 instead of 0 as a hint to the command-line shell +** that this Goto is the bottom of a loop and that the lines from P2 down +** to the current line should be indented for EXPLAIN output. */ case OP_Goto: { /* jump */ pc = pOp->p2 - 1; @@ -2176,8 +2181,8 @@ case OP_BitNot: { /* same as TK_BITNOT, in1, out2 */ ** ** Check if OP_Once flag P1 is set. If so, jump to instruction P2. Otherwise, ** set the flag and fall through to the next instruction. In other words, -** this opcode causes all following up codes up through P2 (but not including -** P2) to run just once and skipped on subsequent times through the loop. +** this opcode causes all following opcodes up through P2 (but not including +** P2) to run just once and to be skipped on subsequent times through the loop. */ case OP_Once: { /* jump */ assert( pOp->p1<p->nOnceFlag ); diff --git a/src/vdbeaux.c b/src/vdbeaux.c index d13dbaadd..edfeedb5a 100644 --- a/src/vdbeaux.c +++ b/src/vdbeaux.c @@ -1235,6 +1235,10 @@ static void releaseMemArray(Mem *p, int N){ ** with no indexes using a single prepared INSERT statement, bind() ** and reset(). Inserts are grouped into a transaction. */ + testcase( p->flags & MEM_Agg ); + testcase( p->flags & MEM_Dyn ); + testcase( p->flags & MEM_Frame ); + testcase( p->flags & MEM_RowSet ); if( p->flags&(MEM_Agg|MEM_Dyn|MEM_Frame|MEM_RowSet) ){ sqlite3VdbeMemRelease(p); }else if( p->zMalloc ){ @@ -2963,27 +2967,32 @@ u32 sqlite3VdbeSerialGet( case 1: { /* 1-byte signed integer */ pMem->u.i = ONE_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 1; } case 2: { /* 2-byte signed integer */ pMem->u.i = TWO_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 2; } case 3: { /* 3-byte signed integer */ pMem->u.i = THREE_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 3; } case 4: { /* 4-byte signed integer */ y = FOUR_BYTE_UINT(buf); pMem->u.i = (i64)*(int*)&y; pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 4; } case 5: { /* 6-byte signed integer */ pMem->u.i = FOUR_BYTE_UINT(buf+2) + (((i64)1)<<32)*TWO_BYTE_INT(buf); pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); return 6; } case 6: /* 8-byte signed integer */ @@ -3006,6 +3015,7 @@ u32 sqlite3VdbeSerialGet( if( serial_type==6 ){ pMem->u.i = *(i64*)&x; pMem->flags = MEM_Int; + testcase( pMem->u.i<0 ); }else{ assert( sizeof(x)==8 && sizeof(pMem->r)==8 ); swapMixedEndianFloat(x); @@ -3352,20 +3362,26 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){ switch( serial_type ){ case 0: case 1: + testcase( aKey[0]&0x80 ); return ONE_BYTE_INT(aKey); case 2: + testcase( aKey[0]&0x80 ); return TWO_BYTE_INT(aKey); case 3: + testcase( aKey[0]&0x80 ); return THREE_BYTE_INT(aKey); case 4: { + testcase( aKey[0]&0x80 ); y = FOUR_BYTE_UINT(aKey); return (i64)*(int*)&y; } case 5: { + testcase( aKey[0]&0x80 ); return FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); } case 6: { u64 x = FOUR_BYTE_UINT(aKey); + testcase( aKey[0]&0x80 ); x = (x<<32) | FOUR_BYTE_UINT(aKey+4); return (i64)*(i64*)&x; } @@ -3433,6 +3449,7 @@ int sqlite3VdbeRecordCompare( /* RHS is an integer */ if( pRhs->flags & MEM_Int ){ serial_type = aKey1[idx1]; + testcase( serial_type==12 ); if( serial_type>=12 ){ rc = +1; }else if( serial_type==0 ){ @@ -3483,12 +3500,15 @@ int sqlite3VdbeRecordCompare( /* RHS is a string */ else if( pRhs->flags & MEM_Str ){ getVarint32(&aKey1[idx1], serial_type); + testcase( serial_type==12 ); if( serial_type<12 ){ rc = -1; }else if( !(serial_type & 0x01) ){ rc = +1; }else{ mem1.n = (serial_type - 12) / 2; + testcase( (d1+mem1.n)==(unsigned)nKey1 ); + testcase( (d1+mem1.n+1)==(unsigned)nKey1 ); if( (d1+mem1.n) > (unsigned)nKey1 ){ rc = 1; /* Corruption */ }else if( pKeyInfo->aColl[i] ){ @@ -3508,10 +3528,13 @@ int sqlite3VdbeRecordCompare( /* RHS is a blob */ else if( pRhs->flags & MEM_Blob ){ getVarint32(&aKey1[idx1], serial_type); + testcase( serial_type==12 ); if( serial_type<12 || (serial_type & 0x01) ){ rc = -1; }else{ int nStr = (serial_type - 12) / 2; + testcase( (d1+nStr)==(unsigned)nKey1 ); + testcase( (d1+nStr+1)==(unsigned)nKey1 ); if( (d1+nStr) > (unsigned)nKey1 ){ rc = 1; /* Corruption */ }else{ @@ -3585,29 +3608,35 @@ static int vdbeRecordCompareInt( switch( serial_type ){ case 1: { /* 1-byte signed integer */ lhs = ONE_BYTE_INT(aKey); + testcase( lhs<0 ); break; } case 2: { /* 2-byte signed integer */ lhs = TWO_BYTE_INT(aKey); + testcase( lhs<0 ); break; } case 3: { /* 3-byte signed integer */ lhs = THREE_BYTE_INT(aKey); + testcase( lhs<0 ); break; } case 4: { /* 4-byte signed integer */ y = FOUR_BYTE_UINT(aKey); lhs = (i64)*(int*)&y; + testcase( lhs<0 ); break; } case 5: { /* 6-byte signed integer */ lhs = FOUR_BYTE_UINT(aKey+2) + (((i64)1)<<32)*TWO_BYTE_INT(aKey); + testcase( lhs<0 ); break; } case 6: { /* 8-byte signed integer */ x = FOUR_BYTE_UINT(aKey); x = (x<<32) | FOUR_BYTE_UINT(aKey+4); lhs = *(i64*)&x; + testcase( lhs<0 ); break; } case 8: @@ -3744,9 +3773,11 @@ RecordCompare sqlite3VdbeFindCompare(UnpackedRecord *p){ if( (flags & MEM_Int) ){ return vdbeRecordCompareInt; } - if( (flags & (MEM_Int|MEM_Real|MEM_Null|MEM_Blob))==0 - && p->pKeyInfo->aColl[0]==0 - ){ + testcase( flags & MEM_Real ); + testcase( flags & MEM_Null ); + testcase( flags & MEM_Blob ); + if( (flags & (MEM_Real|MEM_Null|MEM_Blob))==0 && p->pKeyInfo->aColl[0]==0 ){ + assert( flags & MEM_Str ); return vdbeRecordCompareString; } } diff --git a/src/where.c b/src/where.c index c29c94ae0..963878d00 100644 --- a/src/where.c +++ b/src/where.c @@ -3057,13 +3057,13 @@ static Bitmask codeOneLoopStart( pRangeEnd = pLoop->aLTerm[j++]; nExtraReg = 1; if( pRangeStart==0 - && (pRangeEnd->wtFlags & TERM_VNULL)==0 && (j = pIdx->aiColumn[nEq])>=0 && pIdx->pTable->aCol[j].notNull==0 ){ bSeekPastNull = 1; } } + assert( pRangeEnd==0 || (pRangeEnd->wtFlags & TERM_VNULL)==0 ); /* Generate code to evaluate all constraint terms using == or IN ** and store the values of those terms in an array of registers |