Index: src/btree.c ================================================================== --- src/btree.c +++ src/btree.c @@ -4574,11 +4574,11 @@ assert( pIdxKey->default_rc==1 || pIdxKey->default_rc==0 || pIdxKey->default_rc==-1 ); }else{ - xRecordCompare = 0; /* Not actually used. Avoids a compiler warning. */ + xRecordCompare = 0; /* All keys are integers */ } rc = moveToRoot(pCur); if( rc ){ return rc; Index: src/insert.c ================================================================== --- src/insert.c +++ src/insert.c @@ -99,17 +99,17 @@ /* ** 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 ** ------------------------------ ** 'a' TEXT ** 'b' NONE @@ -146,14 +146,13 @@ } } /* ** 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 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); int i; int iEnd = sqlite3VdbeCurrentAddr(v); Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -26,11 +26,11 @@ ** value of the cell. This macro verifies that shallow copies are ** not misused. A shallow copy of a string or blob just copies a ** 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) #else # define memAboutToChange(P,M) @@ -2164,12 +2164,12 @@ /* Opcode: Once P1 P2 * * * ** ** 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->p1nOnceFlag ); VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2); if( p->aOnceFlag[pOp->p1] ){ Index: src/vdbeaux.c ================================================================== --- src/vdbeaux.c +++ src/vdbeaux.c @@ -1232,10 +1232,14 @@ ** sqlite3MemRelease() were called from here. With -O2, this jumps ** to 6.6 percent. The test case is inserting 1000 rows into a table ** 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 ){ sqlite3DbFree(db, p->zMalloc); p->zMalloc = 0; @@ -2960,31 +2964,36 @@ break; } 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 */ case 7: { /* IEEE floating point */ #if !defined(NDEBUG) && !defined(SQLITE_OMIT_FLOATING_POINT) @@ -3003,10 +3012,11 @@ y = FOUR_BYTE_UINT(buf+4); x = (x<<32) | y; 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); memcpy(&pMem->r, &x, sizeof(x)); pMem->flags = sqlite3IsNaN(pMem->r) ? MEM_Null : MEM_Real; @@ -3348,24 +3358,30 @@ u32 y; assert( CORRUPT_DB || (serial_type>=1 && serial_type<=9 && serial_type!=7) ); 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; } } @@ -3429,10 +3445,11 @@ u32 serial_type; /* 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 ){ rc = -1; }else if( serial_type==7 ){ @@ -3479,16 +3496,19 @@ } /* 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] ){ mem1.enc = pKeyInfo->enc; mem1.db = pKeyInfo->db; @@ -3504,14 +3524,17 @@ } /* 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{ int nCmp = MIN(nStr, pRhs->n); rc = memcmp(&aKey1[d1], pRhs->z, nCmp); @@ -3581,33 +3604,39 @@ assert( bSkip==0 ); 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: lhs = 0; break; @@ -3740,13 +3769,15 @@ p->r2 = 1; } 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; } } return sqlite3VdbeRecordCompare;