mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-21 09:00:59 +03:00
Merge the latest 3.8.4 tweaks from trunk.
FossilOrigin-Name: 1ed463d91866182fbc884fb88770717ee5bf33ce
This commit is contained in:
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
17
src/os_win.c
17
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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
11
src/vdbe.c
11
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 );
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user