aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2014-03-06 13:48:31 +0000
committerdrh <drh@noemail.net>2014-03-06 13:48:31 +0000
commitf2eded23f593efc061694c04a8f987f0831700aa (patch)
tree06e75392380dc4145da906559f2c7a7da425a516 /src
parent3bde1354ff995a17adbdd09bc55bc2bf67220966 (diff)
parentfe70510aa757c4579e9943052f828a3cad5d6d74 (diff)
downloadsqlite-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.c7
-rw-r--r--src/btree.c2
-rw-r--r--src/insert.c9
-rw-r--r--src/os_win.c17
-rw-r--r--src/shell.c9
-rw-r--r--src/sqliteInt.h35
-rw-r--r--src/vdbe.c11
-rw-r--r--src/vdbeaux.c37
-rw-r--r--src/where.c2
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