mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-01 06:27:03 +03:00
Merge latest trunk changes into this branch.
FossilOrigin-Name: b1533bc455f52f570c0f4b8aaa0da802757dc89b0e45b9a9b31aa591a44bf7bd
This commit is contained in:
@ -28,9 +28,13 @@ typedef struct IdxStatement IdxStatement;
|
|||||||
typedef struct IdxTable IdxTable;
|
typedef struct IdxTable IdxTable;
|
||||||
typedef struct IdxWrite IdxWrite;
|
typedef struct IdxWrite IdxWrite;
|
||||||
|
|
||||||
|
/*
|
||||||
|
** A temp table name that we assume no user database will actually use.
|
||||||
|
** If this assumption proves incorrect triggers on the table with the
|
||||||
|
** conflicting name will be ignored.
|
||||||
|
*/
|
||||||
#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
|
#define UNIQUE_TABLE_NAME "t592690916721053953805701627921227776"
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
|
** A single constraint. Equivalent to either "col = ?" or "col < ?" (or
|
||||||
** any other type of single-ended range constraint on a column).
|
** any other type of single-ended range constraint on a column).
|
||||||
@ -238,6 +242,10 @@ static int idxHashAdd(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
** If zKey/nKey is present in the hash table, return a pointer to the
|
||||||
|
** hash-entry object.
|
||||||
|
*/
|
||||||
static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
|
static IdxHashEntry *idxHashFind(IdxHash *pHash, const char *zKey, int nKey){
|
||||||
int iHash;
|
int iHash;
|
||||||
IdxHashEntry *pEntry;
|
IdxHashEntry *pEntry;
|
||||||
|
266
ext/fts3/fts3.c
266
ext/fts3/fts3.c
@ -372,8 +372,8 @@ int sqlite3Fts3GetVarint(const char *pBuf, sqlite_int64 *v){
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to a
|
** Similar to sqlite3Fts3GetVarint(), except that the output is truncated to
|
||||||
** 32-bit integer before it is returned.
|
** a non-negative 32-bit integer before it is returned.
|
||||||
*/
|
*/
|
||||||
int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
||||||
u32 a;
|
u32 a;
|
||||||
@ -389,7 +389,9 @@ int sqlite3Fts3GetVarint32(const char *p, int *pi){
|
|||||||
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
|
GETVARINT_STEP(a, p, 14, 0x3FFF, 0x200000, *pi, 3);
|
||||||
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
GETVARINT_STEP(a, p, 21, 0x1FFFFF, 0x10000000, *pi, 4);
|
||||||
a = (a & 0x0FFFFFFF );
|
a = (a & 0x0FFFFFFF );
|
||||||
*pi = (int)(a | ((u32)(*p & 0x0F) << 28));
|
*pi = (int)(a | ((u32)(*p & 0x07) << 28));
|
||||||
|
assert( 0==(a & 0x80000000) );
|
||||||
|
assert( *pi>=0 );
|
||||||
return 5;
|
return 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1219,65 +1221,66 @@ static int fts3InitVtab(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( iOpt==SizeofArray(aFts4Opt) ){
|
switch( iOpt ){
|
||||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
|
case 0: /* MATCHINFO */
|
||||||
rc = SQLITE_ERROR;
|
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
|
||||||
}else{
|
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
|
||||||
switch( iOpt ){
|
rc = SQLITE_ERROR;
|
||||||
case 0: /* MATCHINFO */
|
}
|
||||||
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
|
bNoDocsize = 1;
|
||||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
|
break;
|
||||||
rc = SQLITE_ERROR;
|
|
||||||
}
|
|
||||||
bNoDocsize = 1;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 1: /* PREFIX */
|
case 1: /* PREFIX */
|
||||||
sqlite3_free(zPrefix);
|
sqlite3_free(zPrefix);
|
||||||
zPrefix = zVal;
|
zPrefix = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 2: /* COMPRESS */
|
case 2: /* COMPRESS */
|
||||||
sqlite3_free(zCompress);
|
sqlite3_free(zCompress);
|
||||||
zCompress = zVal;
|
zCompress = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 3: /* UNCOMPRESS */
|
case 3: /* UNCOMPRESS */
|
||||||
sqlite3_free(zUncompress);
|
sqlite3_free(zUncompress);
|
||||||
zUncompress = zVal;
|
zUncompress = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4: /* ORDER */
|
case 4: /* ORDER */
|
||||||
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
|
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
|
||||||
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
|
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
|
||||||
){
|
){
|
||||||
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
|
sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
|
||||||
rc = SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
|
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5: /* CONTENT */
|
case 5: /* CONTENT */
|
||||||
sqlite3_free(zContent);
|
sqlite3_free(zContent);
|
||||||
zContent = zVal;
|
zContent = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 6: /* LANGUAGEID */
|
case 6: /* LANGUAGEID */
|
||||||
assert( iOpt==6 );
|
assert( iOpt==6 );
|
||||||
sqlite3_free(zLanguageid);
|
sqlite3_free(zLanguageid);
|
||||||
zLanguageid = zVal;
|
zLanguageid = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 7: /* NOTINDEXED */
|
case 7: /* NOTINDEXED */
|
||||||
azNotindexed[nNotindexed++] = zVal;
|
azNotindexed[nNotindexed++] = zVal;
|
||||||
zVal = 0;
|
zVal = 0;
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
default:
|
||||||
|
assert( iOpt==SizeofArray(aFts4Opt) );
|
||||||
|
sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
|
||||||
|
rc = SQLITE_ERROR;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
sqlite3_free(zVal);
|
sqlite3_free(zVal);
|
||||||
}
|
}
|
||||||
@ -1846,7 +1849,8 @@ static int fts3ScanInteriorNode(
|
|||||||
isFirstTerm = 0;
|
isFirstTerm = 0;
|
||||||
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
zCsr += fts3GetVarint32(zCsr, &nSuffix);
|
||||||
|
|
||||||
if( nPrefix<0 || nSuffix<0 || &zCsr[nSuffix]>zEnd ){
|
assert( nPrefix>=0 && nSuffix>=0 );
|
||||||
|
if( &zCsr[nSuffix]>zEnd ){
|
||||||
rc = FTS_CORRUPT_VTAB;
|
rc = FTS_CORRUPT_VTAB;
|
||||||
goto finish_scan;
|
goto finish_scan;
|
||||||
}
|
}
|
||||||
@ -2656,7 +2660,7 @@ int sqlite3Fts3FirstFilter(
|
|||||||
fts3ColumnlistCopy(0, &p);
|
fts3ColumnlistCopy(0, &p);
|
||||||
}
|
}
|
||||||
|
|
||||||
while( p<pEnd && *p==0x01 ){
|
while( p<pEnd ){
|
||||||
sqlite3_int64 iCol;
|
sqlite3_int64 iCol;
|
||||||
p++;
|
p++;
|
||||||
p += sqlite3Fts3GetVarint(p, &iCol);
|
p += sqlite3Fts3GetVarint(p, &iCol);
|
||||||
@ -3336,33 +3340,38 @@ static int fts3ColumnMethod(
|
|||||||
/* The column value supplied by SQLite must be in range. */
|
/* The column value supplied by SQLite must be in range. */
|
||||||
assert( iCol>=0 && iCol<=p->nColumn+2 );
|
assert( iCol>=0 && iCol<=p->nColumn+2 );
|
||||||
|
|
||||||
if( iCol==p->nColumn+1 ){
|
switch( iCol-p->nColumn ){
|
||||||
/* This call is a request for the "docid" column. Since "docid" is an
|
case 0:
|
||||||
** alias for "rowid", use the xRowid() method to obtain the value.
|
/* The special 'table-name' column */
|
||||||
*/
|
sqlite3_result_blob(pCtx, &pCsr, sizeof(Fts3Cursor*), SQLITE_TRANSIENT);
|
||||||
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
sqlite3_result_subtype(pCtx, SQLITE_BLOB);
|
||||||
}else if( iCol==p->nColumn ){
|
break;
|
||||||
/* The extra column whose name is the same as the table.
|
|
||||||
** Return a blob which is a pointer to the cursor. */
|
|
||||||
sqlite3_result_blob(pCtx, &pCsr, sizeof(pCsr), SQLITE_TRANSIENT);
|
|
||||||
}else if( iCol==p->nColumn+2 && pCsr->pExpr ){
|
|
||||||
sqlite3_result_int64(pCtx, pCsr->iLangid);
|
|
||||||
}else{
|
|
||||||
/* The requested column is either a user column (one that contains
|
|
||||||
** indexed data), or the language-id column. */
|
|
||||||
rc = fts3CursorSeek(0, pCsr);
|
|
||||||
|
|
||||||
if( rc==SQLITE_OK ){
|
case 1:
|
||||||
if( iCol==p->nColumn+2 ){
|
/* The docid column */
|
||||||
int iLangid = 0;
|
sqlite3_result_int64(pCtx, pCsr->iPrevId);
|
||||||
if( p->zLanguageid ){
|
break;
|
||||||
iLangid = sqlite3_column_int(pCsr->pStmt, p->nColumn+1);
|
|
||||||
}
|
case 2:
|
||||||
sqlite3_result_int(pCtx, iLangid);
|
if( pCsr->pExpr ){
|
||||||
}else if( sqlite3_data_count(pCsr->pStmt)>(iCol+1) ){
|
sqlite3_result_int64(pCtx, pCsr->iLangid);
|
||||||
|
break;
|
||||||
|
}else if( p->zLanguageid==0 ){
|
||||||
|
sqlite3_result_int(pCtx, 0);
|
||||||
|
break;
|
||||||
|
}else{
|
||||||
|
iCol = p->nColumn;
|
||||||
|
/* fall-through */
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* A user column. Or, if this is a full-table scan, possibly the
|
||||||
|
** language-id column. Seek the cursor. */
|
||||||
|
rc = fts3CursorSeek(0, pCsr);
|
||||||
|
if( rc==SQLITE_OK && sqlite3_data_count(pCsr->pStmt)-1>iCol ){
|
||||||
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
|
||||||
}
|
}
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
assert( ((Fts3Table *)pCsr->base.pVtab)->pSegments==0 );
|
||||||
@ -3442,17 +3451,11 @@ static int fts3SyncMethod(sqlite3_vtab *pVtab){
|
|||||||
static int fts3SetHasStat(Fts3Table *p){
|
static int fts3SetHasStat(Fts3Table *p){
|
||||||
int rc = SQLITE_OK;
|
int rc = SQLITE_OK;
|
||||||
if( p->bHasStat==2 ){
|
if( p->bHasStat==2 ){
|
||||||
const char *zFmt ="SELECT 1 FROM %Q.sqlite_master WHERE tbl_name='%q_stat'";
|
char *zTbl = sqlite3_mprintf("%s_stat", p->zName);
|
||||||
char *zSql = sqlite3_mprintf(zFmt, p->zDb, p->zName);
|
if( zTbl ){
|
||||||
if( zSql ){
|
int res = sqlite3_table_column_metadata(p->db, p->zDb, zTbl, 0,0,0,0,0,0);
|
||||||
sqlite3_stmt *pStmt = 0;
|
sqlite3_free(zTbl);
|
||||||
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pStmt, 0);
|
p->bHasStat = (res==SQLITE_OK);
|
||||||
if( rc==SQLITE_OK ){
|
|
||||||
int bHasStat = (sqlite3_step(pStmt)==SQLITE_ROW);
|
|
||||||
rc = sqlite3_finalize(pStmt);
|
|
||||||
if( rc==SQLITE_OK ) p->bHasStat = (u8)bHasStat;
|
|
||||||
}
|
|
||||||
sqlite3_free(zSql);
|
|
||||||
}else{
|
}else{
|
||||||
rc = SQLITE_NOMEM;
|
rc = SQLITE_NOMEM;
|
||||||
}
|
}
|
||||||
@ -3559,18 +3562,16 @@ static int fts3FunctionArg(
|
|||||||
sqlite3_value *pVal, /* argv[0] passed to function */
|
sqlite3_value *pVal, /* argv[0] passed to function */
|
||||||
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
Fts3Cursor **ppCsr /* OUT: Store cursor handle here */
|
||||||
){
|
){
|
||||||
Fts3Cursor *pRet;
|
int rc = SQLITE_OK;
|
||||||
if( sqlite3_value_type(pVal)!=SQLITE_BLOB
|
if( sqlite3_value_subtype(pVal)==SQLITE_BLOB ){
|
||||||
|| sqlite3_value_bytes(pVal)!=sizeof(Fts3Cursor *)
|
*ppCsr = *(Fts3Cursor**)sqlite3_value_blob(pVal);
|
||||||
){
|
}else{
|
||||||
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
char *zErr = sqlite3_mprintf("illegal first argument to %s", zFunc);
|
||||||
sqlite3_result_error(pContext, zErr, -1);
|
sqlite3_result_error(pContext, zErr, -1);
|
||||||
sqlite3_free(zErr);
|
sqlite3_free(zErr);
|
||||||
return SQLITE_ERROR;
|
rc = SQLITE_ERROR;
|
||||||
}
|
}
|
||||||
memcpy(&pRet, sqlite3_value_blob(pVal), sizeof(Fts3Cursor *));
|
return rc;
|
||||||
*ppCsr = pRet;
|
|
||||||
return SQLITE_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3957,7 +3958,7 @@ int sqlite3Fts3Init(sqlite3 *db){
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create the virtual table wrapper around the hash-table and overload
|
/* Create the virtual table wrapper around the hash-table and overload
|
||||||
** the two scalar functions. If this is successful, register the
|
** the four scalar functions. If this is successful, register the
|
||||||
** module with sqlite.
|
** module with sqlite.
|
||||||
*/
|
*/
|
||||||
if( SQLITE_OK==rc
|
if( SQLITE_OK==rc
|
||||||
@ -4540,7 +4541,7 @@ static int fts3EvalIncrPhraseNext(
|
|||||||
** one incremental token. In which case the bIncr flag is set. */
|
** one incremental token. In which case the bIncr flag is set. */
|
||||||
assert( p->bIncr==1 );
|
assert( p->bIncr==1 );
|
||||||
|
|
||||||
if( p->nToken==1 && p->bIncr ){
|
if( p->nToken==1 ){
|
||||||
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
|
rc = sqlite3Fts3MsrIncrNext(pTab, p->aToken[0].pSegcsr,
|
||||||
&pDL->iDocid, &pDL->pList, &pDL->nList
|
&pDL->iDocid, &pDL->pList, &pDL->nList
|
||||||
);
|
);
|
||||||
@ -4773,6 +4774,7 @@ static void fts3EvalTokenCosts(
|
|||||||
** the number of overflow pages consumed by a record B bytes in size.
|
** the number of overflow pages consumed by a record B bytes in size.
|
||||||
*/
|
*/
|
||||||
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
||||||
|
int rc = SQLITE_OK;
|
||||||
if( pCsr->nRowAvg==0 ){
|
if( pCsr->nRowAvg==0 ){
|
||||||
/* The average document size, which is required to calculate the cost
|
/* The average document size, which is required to calculate the cost
|
||||||
** of each doclist, has not yet been determined. Read the required
|
** of each doclist, has not yet been determined. Read the required
|
||||||
@ -4812,11 +4814,10 @@ static int fts3EvalAverageDocsize(Fts3Cursor *pCsr, int *pnPage){
|
|||||||
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
|
pCsr->nRowAvg = (int)(((nByte / nDoc) + p->nPgsz) / p->nPgsz);
|
||||||
assert( pCsr->nRowAvg>0 );
|
assert( pCsr->nRowAvg>0 );
|
||||||
rc = sqlite3_reset(pStmt);
|
rc = sqlite3_reset(pStmt);
|
||||||
if( rc!=SQLITE_OK ) return rc;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*pnPage = pCsr->nRowAvg;
|
*pnPage = pCsr->nRowAvg;
|
||||||
return SQLITE_OK;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5166,7 +5167,8 @@ static void fts3EvalNextRow(
|
|||||||
pExpr->iDocid = pLeft->iDocid;
|
pExpr->iDocid = pLeft->iDocid;
|
||||||
pExpr->bEof = (pLeft->bEof || pRight->bEof);
|
pExpr->bEof = (pLeft->bEof || pRight->bEof);
|
||||||
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
|
if( pExpr->eType==FTSQUERY_NEAR && pExpr->bEof ){
|
||||||
if( pRight->pPhrase && pRight->pPhrase->doclist.aAll ){
|
assert( pRight->eType==FTSQUERY_PHRASE );
|
||||||
|
if( pRight->pPhrase->doclist.aAll ){
|
||||||
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
|
Fts3Doclist *pDl = &pRight->pPhrase->doclist;
|
||||||
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
|
while( *pRc==SQLITE_OK && pRight->bEof==0 ){
|
||||||
memset(pDl->pList, 0, pDl->nList);
|
memset(pDl->pList, 0, pDl->nList);
|
||||||
@ -5195,7 +5197,7 @@ static void fts3EvalNextRow(
|
|||||||
|
|
||||||
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
if( pRight->bEof || (pLeft->bEof==0 && iCmp<0) ){
|
||||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||||
}else if( pLeft->bEof || (pRight->bEof==0 && iCmp>0) ){
|
}else if( pLeft->bEof || iCmp>0 ){
|
||||||
fts3EvalNextRow(pCsr, pRight, pRc);
|
fts3EvalNextRow(pCsr, pRight, pRc);
|
||||||
}else{
|
}else{
|
||||||
fts3EvalNextRow(pCsr, pLeft, pRc);
|
fts3EvalNextRow(pCsr, pLeft, pRc);
|
||||||
@ -5287,7 +5289,6 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
|||||||
*/
|
*/
|
||||||
if( *pRc==SQLITE_OK
|
if( *pRc==SQLITE_OK
|
||||||
&& pExpr->eType==FTSQUERY_NEAR
|
&& pExpr->eType==FTSQUERY_NEAR
|
||||||
&& pExpr->bEof==0
|
|
||||||
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
|
&& (pExpr->pParent==0 || pExpr->pParent->eType!=FTSQUERY_NEAR)
|
||||||
){
|
){
|
||||||
Fts3Expr *p;
|
Fts3Expr *p;
|
||||||
@ -5296,42 +5297,39 @@ static int fts3EvalNearTest(Fts3Expr *pExpr, int *pRc){
|
|||||||
|
|
||||||
/* Allocate temporary working space. */
|
/* Allocate temporary working space. */
|
||||||
for(p=pExpr; p->pLeft; p=p->pLeft){
|
for(p=pExpr; p->pLeft; p=p->pLeft){
|
||||||
|
assert( p->pRight->pPhrase->doclist.nList>0 );
|
||||||
nTmp += p->pRight->pPhrase->doclist.nList;
|
nTmp += p->pRight->pPhrase->doclist.nList;
|
||||||
}
|
}
|
||||||
nTmp += p->pPhrase->doclist.nList;
|
nTmp += p->pPhrase->doclist.nList;
|
||||||
if( nTmp==0 ){
|
aTmp = sqlite3_malloc(nTmp*2);
|
||||||
|
if( !aTmp ){
|
||||||
|
*pRc = SQLITE_NOMEM;
|
||||||
res = 0;
|
res = 0;
|
||||||
}else{
|
}else{
|
||||||
aTmp = sqlite3_malloc(nTmp*2);
|
char *aPoslist = p->pPhrase->doclist.pList;
|
||||||
if( !aTmp ){
|
int nToken = p->pPhrase->nToken;
|
||||||
*pRc = SQLITE_NOMEM;
|
|
||||||
res = 0;
|
|
||||||
}else{
|
|
||||||
char *aPoslist = p->pPhrase->doclist.pList;
|
|
||||||
int nToken = p->pPhrase->nToken;
|
|
||||||
|
|
||||||
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
|
for(p=p->pParent;res && p && p->eType==FTSQUERY_NEAR; p=p->pParent){
|
||||||
Fts3Phrase *pPhrase = p->pRight->pPhrase;
|
Fts3Phrase *pPhrase = p->pRight->pPhrase;
|
||||||
int nNear = p->nNear;
|
int nNear = p->nNear;
|
||||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
||||||
}
|
|
||||||
|
|
||||||
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
|
|
||||||
nToken = pExpr->pRight->pPhrase->nToken;
|
|
||||||
for(p=pExpr->pLeft; p && res; p=p->pLeft){
|
|
||||||
int nNear;
|
|
||||||
Fts3Phrase *pPhrase;
|
|
||||||
assert( p->pParent && p->pParent->pLeft==p );
|
|
||||||
nNear = p->pParent->nNear;
|
|
||||||
pPhrase = (
|
|
||||||
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
|
|
||||||
);
|
|
||||||
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sqlite3_free(aTmp);
|
aPoslist = pExpr->pRight->pPhrase->doclist.pList;
|
||||||
|
nToken = pExpr->pRight->pPhrase->nToken;
|
||||||
|
for(p=pExpr->pLeft; p && res; p=p->pLeft){
|
||||||
|
int nNear;
|
||||||
|
Fts3Phrase *pPhrase;
|
||||||
|
assert( p->pParent && p->pParent->pLeft==p );
|
||||||
|
nNear = p->pParent->nNear;
|
||||||
|
pPhrase = (
|
||||||
|
p->eType==FTSQUERY_NEAR ? p->pRight->pPhrase : p->pPhrase
|
||||||
|
);
|
||||||
|
res = fts3EvalNearTrim(nNear, aTmp, &aPoslist, &nToken, pPhrase);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sqlite3_free(aTmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
58
ext/misc/anycollseq.c
Normal file
58
ext/misc/anycollseq.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
/*
|
||||||
|
** 2017-04-16
|
||||||
|
**
|
||||||
|
** The author disclaims copyright to this source code. In place of
|
||||||
|
** a legal notice, here is a blessing:
|
||||||
|
**
|
||||||
|
** May you do good and not evil.
|
||||||
|
** May you find forgiveness for yourself and forgive others.
|
||||||
|
** May you share freely, never taking more than you give.
|
||||||
|
**
|
||||||
|
*************************************************************************
|
||||||
|
**
|
||||||
|
** This file implements a run-time loadable extension to SQLite that
|
||||||
|
** registers a sqlite3_collation_needed() callback to register a fake
|
||||||
|
** collating function for any unknown collating sequence. The fake
|
||||||
|
** collating function works like BINARY.
|
||||||
|
**
|
||||||
|
** This extension can be used to load schemas that contain one or more
|
||||||
|
** unknown collating sequences.
|
||||||
|
*/
|
||||||
|
#include "sqlite3ext.h"
|
||||||
|
SQLITE_EXTENSION_INIT1
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
static int anyCollFunc(
|
||||||
|
void *NotUsed,
|
||||||
|
int nKey1, const void *pKey1,
|
||||||
|
int nKey2, const void *pKey2
|
||||||
|
){
|
||||||
|
int rc, n;
|
||||||
|
n = nKey1<nKey2 ? nKey1 : nKey2;
|
||||||
|
rc = memcmp(pKey1, pKey2, n);
|
||||||
|
if( rc==0 ) rc = nKey1 - nKey2;
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void anyCollNeeded(
|
||||||
|
void *NotUsed,
|
||||||
|
sqlite3 *db,
|
||||||
|
int eTextRep,
|
||||||
|
const char *zCollName
|
||||||
|
){
|
||||||
|
sqlite3_create_collation(db, zCollName, eTextRep, 0, anyCollFunc);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
__declspec(dllexport)
|
||||||
|
#endif
|
||||||
|
int sqlite3_anycollseq_init(
|
||||||
|
sqlite3 *db,
|
||||||
|
char **pzErrMsg,
|
||||||
|
const sqlite3_api_routines *pApi
|
||||||
|
){
|
||||||
|
int rc = SQLITE_OK;
|
||||||
|
SQLITE_EXTENSION_INIT2(pApi);
|
||||||
|
rc = sqlite3_collation_needed(db, 0, anyCollNeeded);
|
||||||
|
return rc;
|
||||||
|
}
|
51
manifest
51
manifest
@ -1,5 +1,5 @@
|
|||||||
C Avoid\screating\sa\stemp\stable\sin\sthe\suser\sdatabase\sin\sthe\ssqlite3_expert\scode.
|
C Merge\slatest\strunk\schanges\sinto\sthis\sbranch.
|
||||||
D 2017-04-20T17:03:32.652
|
D 2017-04-20T17:35:46.403
|
||||||
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
|
F Makefile.in 1cc758ce3374a32425e4d130c2fe7b026b20de5b8843243de75f087c0a2661fb
|
||||||
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
F Makefile.linux-gcc 7bc79876b875010e8c8f9502eb935ca92aa3c434
|
||||||
F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6
|
F Makefile.msc 6a8c838220f7c00820e1fc0ac1bccaaa8e5676067e1dbfa1bafa7a4ffecf8ae6
|
||||||
@ -43,7 +43,7 @@ F ext/async/sqlite3async.h f489b080af7e72aec0e1ee6f1d98ab6cf2e4dcef
|
|||||||
F ext/expert/README.md 9f15075ec5ad772808eff55ef044c31140fd1146aa0a3c47eafd155e71851b01
|
F ext/expert/README.md 9f15075ec5ad772808eff55ef044c31140fd1146aa0a3c47eafd155e71851b01
|
||||||
F ext/expert/expert.c 33842ef151d84c5f8000f9c7b938998c6b999eaef7ce1f4eeb0df8ffe6739496
|
F ext/expert/expert.c 33842ef151d84c5f8000f9c7b938998c6b999eaef7ce1f4eeb0df8ffe6739496
|
||||||
F ext/expert/expert1.test 1033e43071b69dc2f4e88fbf03fc7f18846c9865cac14f28c80f581437f09acb
|
F ext/expert/expert1.test 1033e43071b69dc2f4e88fbf03fc7f18846c9865cac14f28c80f581437f09acb
|
||||||
F ext/expert/sqlite3expert.c fde366d8c1b1970b2c18196ca2e64d01c2106bd9431c371a26e8d5b79f37f90b
|
F ext/expert/sqlite3expert.c 4bc1820a70d68b478884a26a2215df8c1f2d44fb40d9cd8c47d2046c8ce0c8bc
|
||||||
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
|
F ext/expert/sqlite3expert.h af6354f8ee5c9e025024e63fec3bd640a802afcc3099a44d804752cf0791d811
|
||||||
F ext/expert/test_expert.c b01a5115f9444a9b416582c985138f5dfdb279848ce8b7452be383530be27f01
|
F ext/expert/test_expert.c b01a5115f9444a9b416582c985138f5dfdb279848ce8b7452be383530be27f01
|
||||||
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
F ext/fts1/README.txt 20ac73b006a70bcfd80069bdaf59214b6cf1db5e
|
||||||
@ -76,7 +76,7 @@ F ext/fts3/README.content fdc666a70d5257a64fee209f97cf89e0e6e32b51
|
|||||||
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
|
||||||
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
|
||||||
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
|
||||||
F ext/fts3/fts3.c f0d5de1bc2155ba7cd7c0c1a751779a3a8857fa34d5c12f3b233a23fa2e79ea2
|
F ext/fts3/fts3.c 10fc22119e3d91997eb5820d96ff709ca7c61b6f767e09b360b986b897ad74c6
|
||||||
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
|
||||||
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
|
F ext/fts3/fts3Int.h eb2502000148e80913b965db3e59f29251266d0a
|
||||||
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
F ext/fts3/fts3_aux.c 9edc3655fcb287f0467d0a4b886a01c6185fe9f1
|
||||||
@ -215,6 +215,7 @@ F ext/icu/icu.c 84900472a088a3a172c6c079f58a1d3a1952c332
|
|||||||
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
F ext/icu/sqliteicu.h 728867a802baa5a96de7495e9689a8e01715ef37
|
||||||
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
|
F ext/misc/README.md 8e008c8d2b02e09096b31dfba033253ac27c6c06a18aa5826e299fa7601d90b2
|
||||||
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
|
F ext/misc/amatch.c 211108e201105e4bb0c076527b8cfd34330fc234
|
||||||
|
F ext/misc/anycollseq.c 5ffdfde9829eeac52219136ad6aa7cd9a4edb3b15f4f2532de52f4a22525eddb
|
||||||
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
|
F ext/misc/carray.c 40c27641010a4dc67e3690bdb7c9d36ca58b3c2d
|
||||||
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
F ext/misc/closure.c 0d2a038df8fbae7f19de42e7c7d71f2e4dc88704
|
||||||
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
F ext/misc/compress.c 122faa92d25033d6c3f07c39231de074ab3d2e83
|
||||||
@ -360,7 +361,7 @@ F src/ctime.c 47d91a25ad8f199a71a5b1b7b169d6dd0d6e98c5719eca801568798743d1161c
|
|||||||
F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae
|
F src/date.c ee676e7694dfadbdd2fde1a258a71be8360ba5ae
|
||||||
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
F src/dbstat.c 19ee7a4e89979d4df8e44cfac7a8f905ec89b77d
|
||||||
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
|
F src/delete.c 0d9d5549d42e79ce4d82ff1db1e6c81e36d2f67c
|
||||||
F src/expr.c f6914d6d06c9a1e488f49cd51a0ef12d8073231e9c1a25c4c821262686cadcbf
|
F src/expr.c f10e35dc50be4c8f82eb99bf5d8530229d1d60957cc3c9473ffe584d0444087c
|
||||||
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007
|
||||||
F src/fkey.c db65492ae549c3b548c9ef1f279ce1684f1c473b116e1c56a90878cd5dcf968d
|
F src/fkey.c db65492ae549c3b548c9ef1f279ce1684f1c473b116e1c56a90878cd5dcf968d
|
||||||
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
|
F src/func.c 9d52522cc8ae7f5cdadfe14594262f1618bc1f86083c4cd6da861b4cf5af6174
|
||||||
@ -396,19 +397,19 @@ F src/os_win.c 2a6c73eef01c51a048cc4ddccd57f981afbec18a
|
|||||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||||
F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b
|
F src/pager.c ff1232b3088a39806035ecfac4fffeb22717d80b
|
||||||
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
|
F src/pager.h f2a99646c5533ffe11afa43e9e0bea74054e4efa
|
||||||
F src/parse.y 48b03113704ee8bd78ee6996d81de7fbee22e105
|
F src/parse.y 0513387ce02fea97897d8caef82d45f347818593f24f1bdc48e0c530a8af122d
|
||||||
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
|
F src/pcache.c 62835bed959e2914edd26afadfecce29ece0e870
|
||||||
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
|
F src/pcache.h 2cedcd8407eb23017d92790b112186886e179490
|
||||||
F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
|
F src/pcache1.c 1195a21fe28e223e024f900b2011e80df53793f0356a24caace4188b098540dc
|
||||||
F src/pragma.c 150821702fc90694b46c3432c1402fc970a4c5b8595cb13c21aeb568f9a78fc3
|
F src/pragma.c 7fef375edafdb7ae9ba938b992aa726e18bf07b0599cfed040a088a262744b7a
|
||||||
F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921
|
F src/pragma.h 37a1311d0388db480388d7ec09054f7103045eff20d4971f8a433b77f40b9921
|
||||||
F src/prepare.c 7c46b5c7be9e19a1bf87777f0b7f9fb257b5ff9856c46de49f2354acfbeb4c86
|
F src/prepare.c 7c46b5c7be9e19a1bf87777f0b7f9fb257b5ff9856c46de49f2354acfbeb4c86
|
||||||
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
|
F src/printf.c 8757834f1b54dae512fb25eb1acc8e94a0d15dd2290b58f2563f65973265adb2
|
||||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||||
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
|
F src/resolve.c 3e518b962d932a997fae373366880fc028c75706
|
||||||
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
F src/rowset.c 7b7e7e479212e65b723bf40128c7b36dc5afdfac
|
||||||
F src/select.c 4588dcfb0fa430012247a209ba08e17904dd32ec7690e9cb6c85e0ef012b0518
|
F src/select.c bf8ab605e49717c222136380453cfb7eda564f8e500d5ff6a01341ea59fefe80
|
||||||
F src/shell.c 70f4957b988572315e97c56941fdc81fd35907fee36b7b2e7be5ec4c7e9d065d
|
F src/shell.c 21b79c0e1b93f8e35fd7b4087d6ba438326c3d7e285d0dd51dfd741475f858a1
|
||||||
F src/sqlite.h.in 900a07463a87be50b9954817f4c24a0660b4c4ddc1bfe83dedea484c6ac98425
|
F src/sqlite.h.in 900a07463a87be50b9954817f4c24a0660b4c4ddc1bfe83dedea484c6ac98425
|
||||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||||
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
|
F src/sqlite3ext.h 58fd0676d3111d02e62e5a35992a7d3da5d3f88753acc174f2d37b774fbbdd28
|
||||||
@ -468,19 +469,19 @@ F src/test_windirent.h 5d67483a55442e31e1bde0f4a230e6e932ad5906
|
|||||||
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
F src/test_wsd.c 41cadfd9d97fe8e3e4e44f61a4a8ccd6f7ca8fe9
|
||||||
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
F src/threads.c 4ae07fa022a3dc7c5beb373cf744a85d3c5c6c3c
|
||||||
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
|
F src/tokenize.c 1003d6d90c6783206c711f0a9397656fa5b055209f4d092caa43bb3bf5215db5
|
||||||
F src/treeview.c b92d57c1ac59f4a3f6b189506921a2b48098f6f4d6afd0b715bc2815ef6af092
|
F src/treeview.c 6cf8d7fe9e63fae57dad1bb57f6615e14eac0c527e43d868e805042cae8ed1f7
|
||||||
F src/trigger.c 134b8e7b61317ab7b2a2dd12eb1b9aa2e23ac5bc4a05e63e35b3609b6b30a7c0
|
F src/trigger.c 134b8e7b61317ab7b2a2dd12eb1b9aa2e23ac5bc4a05e63e35b3609b6b30a7c0
|
||||||
F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
|
F src/update.c c443935c652af9365e033f756550b5032d02e1b06eb2cb890ed7511ae0c051dc
|
||||||
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
F src/utf.c 699001c79f28e48e9bcdf8a463da029ea660540c
|
||||||
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
|
F src/util.c ca8440ede81e155d15cff7c101654f60b55a9ae6
|
||||||
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
|
F src/vacuum.c 1fe4555cd8c9b263afb85b5b4ee3a4a4181ad569
|
||||||
F src/vdbe.c 314f0a70ddc29e63f131dfbe6f53c277875d3028cdf5654a709e21cab39fe0c9
|
F src/vdbe.c 857fd5fe839b2ce4b999f4c0e17106963f0cb96f5e8ba20ebb22701267c09af2
|
||||||
F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848
|
F src/vdbe.h f7d1456e28875c2dcb964056589b5b7149ab7edf39edeca801596a39bb3d3848
|
||||||
F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade
|
F src/vdbeInt.h c070bc5c8b913bda0ceaa995cd4d939ded5e4fc96cf7c3c1c602d41b871f8ade
|
||||||
F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860
|
F src/vdbeapi.c 5b08d82592bcff4470601fe78aaabebd50837860
|
||||||
F src/vdbeaux.c 526b617ac6b5e167a6bd581e067f1ee1dbcb06e7802cff46b76fb1c02ed7d34e
|
F src/vdbeaux.c 526b617ac6b5e167a6bd581e067f1ee1dbcb06e7802cff46b76fb1c02ed7d34e
|
||||||
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
|
F src/vdbeblob.c 359891617358deefc85bef7bcf787fa6b77facb9
|
||||||
F src/vdbemem.c 3122f5a21064198c10ee1b4686937aab27d5395712d9af905b7fa1affc47a453
|
F src/vdbemem.c 2c70f8f5de6c71fb99a22c5b83be9fab5c47cdd8e279fa44a8c00cfed06d7e89
|
||||||
F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c
|
F src/vdbesort.c e72fe02a2121386ba767ede8942e9450878b8fc873abf3d1b6824485f092570c
|
||||||
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
F src/vdbetrace.c 41963d5376f0349842b5fc4aaaaacd7d9cdc0834
|
||||||
F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790
|
F src/vtab.c 007513c2ef52472fcdea6a741683d50662e82790
|
||||||
@ -488,7 +489,7 @@ F src/vxworks.h d2988f4e5a61a4dfe82c6524dd3d6e4f2ce3cdb9
|
|||||||
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
F src/wal.c 40c543f0a2195d1b0dc88ef12142bea690009344
|
||||||
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
F src/wal.h 06b2a0b599cc0f53ea97f497cf8c6b758c999f71
|
||||||
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
|
F src/walker.c b71a992b413b3a022572eccf29ef4b4890223791
|
||||||
F src/where.c d22a2ae7f823f5405e5d00c3397204ce1272d53bc3f2fc0c516315f143eb1a24
|
F src/where.c a12df4e97aec78ec37e3aa92eea6d889ef3cd9ce5cfe6b682bf1243c743d897c
|
||||||
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
|
F src/whereInt.h 2a4b634d63ce488b46d4b0da8f2eaa8f9aeab202bc25ef76f007de5e3fba1f20
|
||||||
F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681
|
F src/wherecode.c 943e32e9dccd0af802e0683ae11071c8bd808364e5908a5fb66758bd404c8681
|
||||||
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
|
F src/whereexpr.c e913aaa7b73ffcce66abcea5f197e2c538d48b5df78d0b7bba8ff4d73cc2e745
|
||||||
@ -713,7 +714,7 @@ F test/fkey1.test ba64806ff9a04eecab2679caad377ae99a5e94e4
|
|||||||
F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c
|
F test/fkey2.test 155809016fad6b2a1491facf2ac53a551bc57c2c
|
||||||
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49
|
||||||
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d
|
||||||
F test/fkey5.test 5a373303f201ac03c22ba1ef17a733d3f56e611a
|
F test/fkey5.test 19a9b73bafd78323c37fc883dba060191541503d6094f8aea67fe94d33118e20
|
||||||
F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
|
F test/fkey6.test d078a1e323a740062bed38df32b8a736fd320dc0
|
||||||
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
F test/fkey7.test 72e915890ee4a005daaf3002cb208e8fe973ac13
|
||||||
F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
|
F test/fkey8.test e5372e32cdb4481f121ec3550703eeb7b4e0762c
|
||||||
@ -757,7 +758,7 @@ F test/fts2r.test b154c30b63061d8725e320fba1a39e2201cadd5e
|
|||||||
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
F test/fts2token.test d8070b241a15ff13592a9ae4a8b7c171af6f445a
|
||||||
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
F test/fts3.test 672a040ea57036fb4b6fdc09027c18d7d24ab654
|
||||||
F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
|
F test/fts3_common.tcl 99cf6659b87c0f74f55963c2aea03b3a7d66ceb0
|
||||||
F test/fts3aa.test 6c263a6f8845205ee02550981a94c2e8dc1e7058
|
F test/fts3aa.test 39b65c11913d277c91d7426c62cfc1d147d1b4e9a48fecd9e38f60d0b5a5f505
|
||||||
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
F test/fts3ab.test 7f6cf260ae80dda064023df8e8e503e9a412b91f
|
||||||
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
|
F test/fts3ac.test 636ed7486043055d4f126a0e385f2d5a82ebbf63
|
||||||
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
F test/fts3ad.test e40570cb6f74f059129ad48bcef3d7cbc20dda49
|
||||||
@ -782,6 +783,7 @@ F test/fts3comp1.test a0f5b16a2df44dd0b15751787130af2183167c0c
|
|||||||
F test/fts3conf.test 60317efd562080e198b5bdc9fcd222ce32cf01d7
|
F test/fts3conf.test 60317efd562080e198b5bdc9fcd222ce32cf01d7
|
||||||
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
F test/fts3corrupt.test 2710b77983cc7789295ddbffea52c1d3b7506dbb
|
||||||
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
F test/fts3corrupt2.test 6d96efae2f8a6af3eeaf283aba437e6d0e5447ba
|
||||||
|
F test/fts3corrupt3.test 56e0ee83e90b57f5f3644cb7d1b36a067b7b8b19cdf0dedce45e5e13cf752f65
|
||||||
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
F test/fts3cov.test e0fb00d8b715ddae4a94c305992dfc3ef70353d7
|
||||||
F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
|
F test/fts3d.test d3e9c8fb75135ada06bf3bab4f9666224965d708
|
||||||
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
F test/fts3defer.test 0be4440b73a2e651fc1e472066686d6ada4b9963
|
||||||
@ -794,12 +796,13 @@ F test/fts3expr2.test 18da930352e5693eaa163a3eacf96233b7290d1a
|
|||||||
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
|
F test/fts3expr3.test c4d4a7d6327418428c96e0a3a1137c251b8dfbf8
|
||||||
F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3
|
F test/fts3expr4.test c39a15d676b14fc439d9bf845aa7bddcf4a74dc3
|
||||||
F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
|
F test/fts3expr5.test f9abfffbf5e53d48a33e12a1e8f8ba2c551c9b49
|
||||||
F test/fts3fault.test da49627b280b210ebc6657f76344c7851f10ce66
|
F test/fts3fault.test 268e9589f44f49d6694ef39a293f0e0f80c6230fb01cc6f34325412acceb99ae
|
||||||
F test/fts3fault2.test f953bb3cf903988172270a9a0aafd5a890b0f98f
|
F test/fts3fault2.test 536bbe01fe2946ec24b063a5eee813e8fd90354a6ca0b8f941d299c405edd17e
|
||||||
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
F test/fts3first.test dbdedd20914c8d539aa3206c9b34a23775644641
|
||||||
F test/fts3join.test 34750f3ce1e29b2749eaf0f1be2fa6301c5d50da
|
F test/fts3join.test 34750f3ce1e29b2749eaf0f1be2fa6301c5d50da
|
||||||
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
F test/fts3malloc.test b0e4c133b8d61d4f6d112d8110f8320e9e453ef6
|
||||||
F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a
|
F test/fts3matchinfo.test ce864e0bd92429df8008f31cf557269ba172482a
|
||||||
|
F test/fts3misc.test f481128013b9555babdf3bc04c58ab59d59bebc24b5f780f50342b9ffe05b547
|
||||||
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
F test/fts3near.test 7e3354d46f155a822b59c0e957fd2a70c1d7e905
|
||||||
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
|
F test/fts3offsets.test b85fd382abdc78ebce721d8117bd552dfb75094c
|
||||||
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
F test/fts3prefix.test fa794eaab0bdae466494947b0b153d7844478ab2
|
||||||
@ -819,7 +822,7 @@ F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
|
|||||||
F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
|
F test/fts4growth.test e5390da74619cacc389711bac9349640b32c4f9a
|
||||||
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
|
F test/fts4growth2.test 13ad4e76451af6e6906c95cdc725d01b00044269
|
||||||
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
|
F test/fts4incr.test 4e353a0bd886ea984e56fce9e77724fc923b8d0d
|
||||||
F test/fts4langid.test 65a7332c9bc257919e259a304aa8a38c41655b9d
|
F test/fts4langid.test 89a107d36710dc3f44dab0861a784ffab967bd1f32c8d700b031748b9d2703c6
|
||||||
F test/fts4lastrowid.test fa5e157955a3121615ef3e16ff5196e96c9e1e64
|
F test/fts4lastrowid.test fa5e157955a3121615ef3e16ff5196e96c9e1e64
|
||||||
F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47
|
F test/fts4merge.test d2b39f6b1bd4a9738a13540e2d044cba11c43d47
|
||||||
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
F test/fts4merge2.test 5faa558d1b672f82b847d2a337465fa745e46891
|
||||||
@ -1035,7 +1038,7 @@ F test/parser1.test 391b9bf9a229547a129c61ac345ed1a6f5eb1854
|
|||||||
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
F test/pcache.test c8acbedd3b6fd0f9a7ca887a83b11d24a007972b
|
||||||
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
F test/pcache2.test af7f3deb1a819f77a6d0d81534e97d1cf62cd442
|
||||||
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
F test/percentile.test 4243af26b8f3f4555abe166f723715a1f74c77ff
|
||||||
F test/permutations.test 9c0da2079fa37e7509957c9efbbdc282dea4ed0e732d19e6f216d53ae431a67d
|
F test/permutations.test 1d9e247280c1e656a1f2567a263b83561a29d8c3eca6a349ae939218e82a9cfc
|
||||||
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
|
F test/pragma.test 1e94755164a3a3264cd39836de4bebcb7809e5f8
|
||||||
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
F test/pragma2.test e5d5c176360c321344249354c0c16aec46214c9f
|
||||||
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
F test/pragma3.test 14c12bc5352b1e100e0b6b44f371053a81ccf8ed
|
||||||
@ -1490,7 +1493,7 @@ F test/zerodamage.test e59a56443d6298ecf7435f618f0b27654f0c849e
|
|||||||
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
F tool/GetFile.cs a15e08acb5dd7539b75ba23501581d7c2b462cb5
|
||||||
F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7
|
F tool/GetTclKit.bat 6afa640edc7810725aec61c3076ac617c4aaf0b7
|
||||||
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
F tool/Replace.cs 02c67258801c2fb5f63231e0ac0f220b4b36ba91
|
||||||
F tool/addopcodes.tcl 10c889c4a65ec6c5604e4a47306fa77ff57ae189
|
F tool/addopcodes.tcl edbd53806bf20e25af2373ad0c091be4385081c1aa1813b916bf093f94ed8380
|
||||||
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
|
F tool/build-all-msvc.bat c12328d06c45fec8baada5949e3d5af54bf8c887 x
|
||||||
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
F tool/build-shell.sh 950f47c6174f1eea171319438b93ba67ff5bf367
|
||||||
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
|
F tool/cg_anno.tcl f95b0006c52cf7f0496b506343415b6ee3cdcdd3 x
|
||||||
@ -1536,7 +1539,7 @@ F tool/showdb.c e6bc9dba233bf1b57ca0a525a2bba762db4e223de84990739db3f09c46151b1e
|
|||||||
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
F tool/showjournal.c 5bad7ae8784a43d2b270d953060423b8bd480818
|
||||||
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
F tool/showlocks.c 9920bcc64f58378ff1118caead34147201f48c68
|
||||||
F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
|
F tool/showstat4.c b14159aa062f661b394ba37b6b7b94bfb8012ab9
|
||||||
F tool/showwal.c ec79959834f7b21f1e0a2aa52bb7c056d2203977
|
F tool/showwal.c ad9d768f96ca6199ad3a8c9562d679680bd032dd01204ea3e5ea6fb931d81847
|
||||||
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
F tool/soak1.tcl 8d407956e1a45b485a8e072470a3e629a27037fe
|
||||||
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
|
F tool/spaceanal.tcl ab7d9bf68062907282a64b3e12ccbfad47193c5a
|
||||||
F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda
|
F tool/speed-check.sh 9630ba0468b609c52f48309243d4eb6e9c34deda
|
||||||
@ -1579,7 +1582,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
|||||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||||
P 4577fea5cd9d91ea241e9be82797ca1a4447f536e1e4b78a4a569aeb52e78fcb 8e57c31340dd9ffc457da63c5996fb1b573f8154f864ec2b52c15f399906ac8b
|
P 4e366996434e63f06cc451d2011f1f1464360f03430b8260e48f78a612b4e9d6 6b21d0fdebdccfaf63590d9ca9a279c22b8baec07c1a669b9f617f25bd857384
|
||||||
R 73307a63b82b2606f65f28fc989fd3ae
|
R 3ff876810132a5a27eb9c4a943446c06
|
||||||
U dan
|
U dan
|
||||||
Z a6caf6a2d1f5541a0691d13e2a47ea26
|
Z 9bcc0d98d05bcef127f4de36c5b9d364
|
||||||
|
@ -1 +1 @@
|
|||||||
4e366996434e63f06cc451d2011f1f1464360f03430b8260e48f78a612b4e9d6
|
b1533bc455f52f570c0f4b8aaa0da802757dc89b0e45b9a9b31aa591a44bf7bd
|
11
src/expr.c
11
src/expr.c
@ -3889,6 +3889,17 @@ int sqlite3ExprCodeTarget(Parse *pParse, Expr *pExpr, int target){
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case TK_IF_NULL_ROW: {
|
||||||
|
int addrINR;
|
||||||
|
addrINR = sqlite3VdbeAddOp1(v, OP_IfNullRow, pExpr->iTable);
|
||||||
|
sqlite3ExprCachePush(pParse);
|
||||||
|
inReg = sqlite3ExprCodeTarget(pParse, pExpr->pLeft, target);
|
||||||
|
sqlite3ExprCachePop(pParse);
|
||||||
|
sqlite3VdbeJumpHere(v, addrINR);
|
||||||
|
sqlite3VdbeChangeP3(v, addrINR, inReg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Form A:
|
** Form A:
|
||||||
** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
|
** CASE x WHEN e1 THEN r1 WHEN e2 THEN r2 ... WHEN eN THEN rN ELSE y END
|
||||||
|
34
src/parse.y
34
src/parse.y
@ -193,6 +193,23 @@ columnlist ::= columnlist COMMA columnname carglist.
|
|||||||
columnlist ::= columnname carglist.
|
columnlist ::= columnname carglist.
|
||||||
columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
|
columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
|
||||||
|
|
||||||
|
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
|
||||||
|
// fallback to ID if they will not parse as their original value.
|
||||||
|
// This obviates the need for the "id" nonterminal.
|
||||||
|
//
|
||||||
|
%fallback ID
|
||||||
|
ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
|
||||||
|
CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
|
||||||
|
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
|
||||||
|
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
|
||||||
|
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
|
||||||
|
%ifdef SQLITE_OMIT_COMPOUND_SELECT
|
||||||
|
EXCEPT INTERSECT UNION
|
||||||
|
%endif SQLITE_OMIT_COMPOUND_SELECT
|
||||||
|
REINDEX RENAME CTIME_KW IF
|
||||||
|
.
|
||||||
|
%wildcard ANY.
|
||||||
|
|
||||||
// Define operator precedence early so that this is the first occurrence
|
// Define operator precedence early so that this is the first occurrence
|
||||||
// of the operator tokens in the grammer. Keeping the operators together
|
// of the operator tokens in the grammer. Keeping the operators together
|
||||||
// causes them to be assigned integer values that are close together,
|
// causes them to be assigned integer values that are close together,
|
||||||
@ -222,23 +239,6 @@ columnname(A) ::= nm(A) typetoken(Y). {sqlite3AddColumn(pParse,&A,&Y);}
|
|||||||
//
|
//
|
||||||
%token_class id ID|INDEXED.
|
%token_class id ID|INDEXED.
|
||||||
|
|
||||||
// The following directive causes tokens ABORT, AFTER, ASC, etc. to
|
|
||||||
// fallback to ID if they will not parse as their original value.
|
|
||||||
// This obviates the need for the "id" nonterminal.
|
|
||||||
//
|
|
||||||
%fallback ID
|
|
||||||
ABORT ACTION AFTER ANALYZE ASC ATTACH BEFORE BEGIN BY CASCADE CAST COLUMNKW
|
|
||||||
CONFLICT DATABASE DEFERRED DESC DETACH EACH END EXCLUSIVE EXPLAIN FAIL FOR
|
|
||||||
IGNORE IMMEDIATE INITIALLY INSTEAD LIKE_KW MATCH NO PLAN
|
|
||||||
QUERY KEY OF OFFSET PRAGMA RAISE RECURSIVE RELEASE REPLACE RESTRICT ROW
|
|
||||||
ROLLBACK SAVEPOINT TEMP TRIGGER VACUUM VIEW VIRTUAL WITH WITHOUT
|
|
||||||
%ifdef SQLITE_OMIT_COMPOUND_SELECT
|
|
||||||
EXCEPT INTERSECT UNION
|
|
||||||
%endif SQLITE_OMIT_COMPOUND_SELECT
|
|
||||||
REINDEX RENAME CTIME_KW IF
|
|
||||||
.
|
|
||||||
%wildcard ANY.
|
|
||||||
|
|
||||||
|
|
||||||
// And "ids" is an identifer-or-string.
|
// And "ids" is an identifer-or-string.
|
||||||
//
|
//
|
||||||
|
56
src/pragma.c
56
src/pragma.c
@ -1330,33 +1330,37 @@ void sqlite3Pragma(
|
|||||||
assert( x==0 );
|
assert( x==0 );
|
||||||
}
|
}
|
||||||
addrOk = sqlite3VdbeMakeLabel(v);
|
addrOk = sqlite3VdbeMakeLabel(v);
|
||||||
if( pParent && pIdx==0 ){
|
|
||||||
int iKey = pFK->aCol[0].iFrom;
|
/* Generate code to read the child key values into registers
|
||||||
assert( iKey>=0 && iKey<pTab->nCol );
|
** regRow..regRow+n. If any of the child key values are NULL, this
|
||||||
if( iKey!=pTab->iPKey ){
|
** row cannot cause an FK violation. Jump directly to addrOk in
|
||||||
sqlite3VdbeAddOp3(v, OP_Column, 0, iKey, regRow);
|
** this case. */
|
||||||
sqlite3ColumnDefault(v, pTab, iKey, regRow);
|
for(j=0; j<pFK->nCol; j++){
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRow, addrOk); VdbeCoverage(v);
|
int iCol = aiCols ? aiCols[j] : pFK->aCol[j].iFrom;
|
||||||
}else{
|
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0, iCol, regRow+j);
|
||||||
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regRow);
|
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp3(v, OP_SeekRowid, i, 0, regRow); VdbeCoverage(v);
|
|
||||||
sqlite3VdbeGoto(v, addrOk);
|
/* Generate code to query the parent index for a matching parent
|
||||||
sqlite3VdbeJumpHere(v, sqlite3VdbeCurrentAddr(v)-2);
|
** key. If a match is found, jump to addrOk. */
|
||||||
}else{
|
if( pIdx ){
|
||||||
for(j=0; j<pFK->nCol; j++){
|
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
|
||||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, 0,
|
sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
|
||||||
aiCols ? aiCols[j] : pFK->aCol[j].iFrom, regRow+j);
|
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
|
||||||
sqlite3VdbeAddOp2(v, OP_IsNull, regRow+j, addrOk); VdbeCoverage(v);
|
VdbeCoverage(v);
|
||||||
}
|
}else if( pParent ){
|
||||||
if( pParent ){
|
int jmp = sqlite3VdbeCurrentAddr(v)+2;
|
||||||
sqlite3VdbeAddOp4(v, OP_MakeRecord, regRow, pFK->nCol, regKey,
|
sqlite3VdbeAddOp3(v, OP_SeekRowid, i, jmp, regRow); VdbeCoverage(v);
|
||||||
sqlite3IndexAffinityStr(db,pIdx), pFK->nCol);
|
sqlite3VdbeGoto(v, addrOk);
|
||||||
sqlite3VdbeAddOp4Int(v, OP_Found, i, addrOk, regKey, 0);
|
assert( pFK->nCol==1 );
|
||||||
VdbeCoverage(v);
|
}
|
||||||
}
|
|
||||||
|
/* Generate code to report an FK violation to the caller. */
|
||||||
|
if( HasRowid(pTab) ){
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
|
||||||
|
}else{
|
||||||
|
sqlite3VdbeAddOp2(v, OP_Null, 0, regResult+1);
|
||||||
}
|
}
|
||||||
sqlite3VdbeAddOp2(v, OP_Rowid, 0, regResult+1);
|
|
||||||
sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1);
|
sqlite3VdbeMultiLoad(v, regResult+2, "si", pFK->zTo, i-1);
|
||||||
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
|
sqlite3VdbeAddOp2(v, OP_ResultRow, regResult, 4);
|
||||||
sqlite3VdbeResolveLabel(v, addrOk);
|
sqlite3VdbeResolveLabel(v, addrOk);
|
||||||
|
62
src/select.c
62
src/select.c
@ -3154,6 +3154,8 @@ static int multiSelectOrderBy(
|
|||||||
typedef struct SubstContext {
|
typedef struct SubstContext {
|
||||||
Parse *pParse; /* The parsing context */
|
Parse *pParse; /* The parsing context */
|
||||||
int iTable; /* Replace references to this table */
|
int iTable; /* Replace references to this table */
|
||||||
|
int iNewTable; /* New table number */
|
||||||
|
int isLeftJoin; /* Add TK_IF_NULL_ROW opcodes on each replacement */
|
||||||
ExprList *pEList; /* Replacement expressions */
|
ExprList *pEList; /* Replacement expressions */
|
||||||
} SubstContext;
|
} SubstContext;
|
||||||
|
|
||||||
@ -3179,18 +3181,29 @@ static Expr *substExpr(
|
|||||||
Expr *pExpr /* Expr in which substitution occurs */
|
Expr *pExpr /* Expr in which substitution occurs */
|
||||||
){
|
){
|
||||||
if( pExpr==0 ) return 0;
|
if( pExpr==0 ) return 0;
|
||||||
|
if( ExprHasProperty(pExpr, EP_FromJoin) && pExpr->iRightJoinTable==pSubst->iTable ){
|
||||||
|
pExpr->iRightJoinTable = pSubst->iNewTable;
|
||||||
|
}
|
||||||
if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
|
if( pExpr->op==TK_COLUMN && pExpr->iTable==pSubst->iTable ){
|
||||||
if( pExpr->iColumn<0 ){
|
if( pExpr->iColumn<0 ){
|
||||||
pExpr->op = TK_NULL;
|
pExpr->op = TK_NULL;
|
||||||
}else{
|
}else{
|
||||||
Expr *pNew;
|
Expr *pNew;
|
||||||
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
|
Expr *pCopy = pSubst->pEList->a[pExpr->iColumn].pExpr;
|
||||||
|
Expr ifNullRow;
|
||||||
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
|
assert( pSubst->pEList!=0 && pExpr->iColumn<pSubst->pEList->nExpr );
|
||||||
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
assert( pExpr->pLeft==0 && pExpr->pRight==0 );
|
||||||
if( sqlite3ExprIsVector(pCopy) ){
|
if( sqlite3ExprIsVector(pCopy) ){
|
||||||
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
|
sqlite3VectorErrorMsg(pSubst->pParse, pCopy);
|
||||||
}else{
|
}else{
|
||||||
sqlite3 *db = pSubst->pParse->db;
|
sqlite3 *db = pSubst->pParse->db;
|
||||||
|
if( pSubst->isLeftJoin && pCopy->op!=TK_COLUMN ){
|
||||||
|
memset(&ifNullRow, 0, sizeof(ifNullRow));
|
||||||
|
ifNullRow.op = TK_IF_NULL_ROW;
|
||||||
|
ifNullRow.pLeft = pCopy;
|
||||||
|
ifNullRow.iTable = pSubst->iNewTable;
|
||||||
|
pCopy = &ifNullRow;
|
||||||
|
}
|
||||||
pNew = sqlite3ExprDup(db, pCopy, 0);
|
pNew = sqlite3ExprDup(db, pCopy, 0);
|
||||||
if( pNew && (pExpr->flags & EP_FromJoin) ){
|
if( pNew && (pExpr->flags & EP_FromJoin) ){
|
||||||
pNew->iRightJoinTable = pExpr->iRightJoinTable;
|
pNew->iRightJoinTable = pExpr->iRightJoinTable;
|
||||||
@ -3284,8 +3297,8 @@ static void substSelect(
|
|||||||
** FROM-clause subquery that is a candidate for flattening. (2b is
|
** FROM-clause subquery that is a candidate for flattening. (2b is
|
||||||
** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
|
** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
|
||||||
**
|
**
|
||||||
** (3) The subquery is not the right operand of a left outer join
|
** (3) The subquery is not the right operand of a LEFT JOIN
|
||||||
** (Originally ticket #306. Strengthened by ticket #3300)
|
** or the subquery is not itself a join.
|
||||||
**
|
**
|
||||||
** (4) The subquery is not DISTINCT.
|
** (4) The subquery is not DISTINCT.
|
||||||
**
|
**
|
||||||
@ -3297,7 +3310,7 @@ static void substSelect(
|
|||||||
** DISTINCT.
|
** DISTINCT.
|
||||||
**
|
**
|
||||||
** (7) The subquery has a FROM clause. TODO: For subqueries without
|
** (7) The subquery has a FROM clause. TODO: For subqueries without
|
||||||
** A FROM clause, consider adding a FROM close with the special
|
** A FROM clause, consider adding a FROM clause with the special
|
||||||
** table sqlite_once that consists of a single row containing a
|
** table sqlite_once that consists of a single row containing a
|
||||||
** single NULL.
|
** single NULL.
|
||||||
**
|
**
|
||||||
@ -3403,6 +3416,8 @@ static int flattenSubquery(
|
|||||||
SrcList *pSubSrc; /* The FROM clause of the subquery */
|
SrcList *pSubSrc; /* The FROM clause of the subquery */
|
||||||
ExprList *pList; /* The result set of the outer query */
|
ExprList *pList; /* The result set of the outer query */
|
||||||
int iParent; /* VDBE cursor number of the pSub result set temp table */
|
int iParent; /* VDBE cursor number of the pSub result set temp table */
|
||||||
|
int iNewParent = -1;/* Replacement table for iParent */
|
||||||
|
int isLeftJoin = 0; /* True if pSub is the right side of a LEFT JOIN */
|
||||||
int i; /* Loop counter */
|
int i; /* Loop counter */
|
||||||
Expr *pWhere; /* The WHERE clause */
|
Expr *pWhere; /* The WHERE clause */
|
||||||
struct SrcList_item *pSubitem; /* The subquery */
|
struct SrcList_item *pSubitem; /* The subquery */
|
||||||
@ -3429,7 +3444,7 @@ static int flattenSubquery(
|
|||||||
return 0; /* Restriction (2b) */
|
return 0; /* Restriction (2b) */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pSubSrc = pSub->pSrc;
|
pSubSrc = pSub->pSrc;
|
||||||
assert( pSubSrc );
|
assert( pSubSrc );
|
||||||
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
|
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
|
||||||
@ -3467,10 +3482,9 @@ static int flattenSubquery(
|
|||||||
return 0; /* Restriction (23) */
|
return 0; /* Restriction (23) */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* OBSOLETE COMMENT 1:
|
/*
|
||||||
** Restriction 3: If the subquery is a join, make sure the subquery is
|
** If the subquery is the right operand of a LEFT JOIN, then the
|
||||||
** not used as the right operand of an outer join. Examples of why this
|
** subquery may not be a join itself. Example of why this is not allowed:
|
||||||
** is not allowed:
|
|
||||||
**
|
**
|
||||||
** t1 LEFT OUTER JOIN (t2 JOIN t3)
|
** t1 LEFT OUTER JOIN (t2 JOIN t3)
|
||||||
**
|
**
|
||||||
@ -3480,27 +3494,13 @@ static int flattenSubquery(
|
|||||||
**
|
**
|
||||||
** which is not at all the same thing.
|
** which is not at all the same thing.
|
||||||
**
|
**
|
||||||
** OBSOLETE COMMENT 2:
|
** See also tickets #306, #350, and #3300.
|
||||||
** Restriction 12: If the subquery is the right operand of a left outer
|
|
||||||
** join, make sure the subquery has no WHERE clause.
|
|
||||||
** An examples of why this is not allowed:
|
|
||||||
**
|
|
||||||
** t1 LEFT OUTER JOIN (SELECT * FROM t2 WHERE t2.x>0)
|
|
||||||
**
|
|
||||||
** If we flatten the above, we would get
|
|
||||||
**
|
|
||||||
** (t1 LEFT OUTER JOIN t2) WHERE t2.x>0
|
|
||||||
**
|
|
||||||
** But the t2.x>0 test will always fail on a NULL row of t2, which
|
|
||||||
** effectively converts the OUTER JOIN into an INNER JOIN.
|
|
||||||
**
|
|
||||||
** THIS OVERRIDES OBSOLETE COMMENTS 1 AND 2 ABOVE:
|
|
||||||
** Ticket #3300 shows that flattening the right term of a LEFT JOIN
|
|
||||||
** is fraught with danger. Best to avoid the whole thing. If the
|
|
||||||
** subquery is the right term of a LEFT JOIN, then do not flatten.
|
|
||||||
*/
|
*/
|
||||||
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
|
if( (pSubitem->fg.jointype & JT_OUTER)!=0 ){
|
||||||
return 0;
|
isLeftJoin = 1;
|
||||||
|
if( pSubSrc->nSrc>1 ){
|
||||||
|
return 0; /* Restriction (3) */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Restriction 17: If the sub-query is a compound SELECT, then it must
|
/* Restriction 17: If the sub-query is a compound SELECT, then it must
|
||||||
@ -3709,6 +3709,7 @@ static int flattenSubquery(
|
|||||||
sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
|
sqlite3IdListDelete(db, pSrc->a[i+iFrom].pUsing);
|
||||||
assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
|
assert( pSrc->a[i+iFrom].fg.isTabFunc==0 );
|
||||||
pSrc->a[i+iFrom] = pSubSrc->a[i];
|
pSrc->a[i+iFrom] = pSubSrc->a[i];
|
||||||
|
iNewParent = pSubSrc->a[i].iCursor;
|
||||||
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
|
memset(&pSubSrc->a[i], 0, sizeof(pSubSrc->a[i]));
|
||||||
}
|
}
|
||||||
pSrc->a[iFrom].fg.jointype = jointype;
|
pSrc->a[iFrom].fg.jointype = jointype;
|
||||||
@ -3754,6 +3755,9 @@ static int flattenSubquery(
|
|||||||
pSub->pOrderBy = 0;
|
pSub->pOrderBy = 0;
|
||||||
}
|
}
|
||||||
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
|
pWhere = sqlite3ExprDup(db, pSub->pWhere, 0);
|
||||||
|
if( isLeftJoin ){
|
||||||
|
setJoinExpr(pWhere, iNewParent);
|
||||||
|
}
|
||||||
if( subqueryIsAgg ){
|
if( subqueryIsAgg ){
|
||||||
assert( pParent->pHaving==0 );
|
assert( pParent->pHaving==0 );
|
||||||
pParent->pHaving = pParent->pWhere;
|
pParent->pHaving = pParent->pWhere;
|
||||||
@ -3770,6 +3774,8 @@ static int flattenSubquery(
|
|||||||
SubstContext x;
|
SubstContext x;
|
||||||
x.pParse = pParse;
|
x.pParse = pParse;
|
||||||
x.iTable = iParent;
|
x.iTable = iParent;
|
||||||
|
x.iNewTable = iNewParent;
|
||||||
|
x.isLeftJoin = isLeftJoin;
|
||||||
x.pEList = pSub->pEList;
|
x.pEList = pSub->pEList;
|
||||||
substSelect(&x, pParent, 0);
|
substSelect(&x, pParent, 0);
|
||||||
}
|
}
|
||||||
@ -3878,6 +3884,8 @@ static int pushDownWhereTerms(
|
|||||||
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
|
pNew = sqlite3ExprDup(pParse->db, pWhere, 0);
|
||||||
x.pParse = pParse;
|
x.pParse = pParse;
|
||||||
x.iTable = iCursor;
|
x.iTable = iCursor;
|
||||||
|
x.iNewTable = iCursor;
|
||||||
|
x.isLeftJoin = 0;
|
||||||
x.pEList = pSubq->pEList;
|
x.pEList = pSubq->pEList;
|
||||||
pNew = substExpr(&x, pNew);
|
pNew = substExpr(&x, pNew);
|
||||||
pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
|
pSubq->pWhere = sqlite3ExprAnd(pParse->db, pSubq->pWhere, pNew);
|
||||||
|
50
src/shell.c
50
src/shell.c
@ -427,6 +427,36 @@ static void SQLITE_CDECL iotracePrintf(const char *zFormat, ...){
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Output string zUtf to stream pOut as w characters. If w is negative,
|
||||||
|
** then right-justify the text. W is the width in UTF-8 characters, not
|
||||||
|
** in bytes. This is different from the %*.*s specification in printf
|
||||||
|
** since with %*.*s the width is measured in bytes, not characters.
|
||||||
|
*/
|
||||||
|
static void utf8_width_print(FILE *pOut, int w, const char *zUtf){
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
int aw = w<0 ? -w : w;
|
||||||
|
char zBuf[1000];
|
||||||
|
if( aw>sizeof(zBuf)/3 ) aw = sizeof(zBuf)/3;
|
||||||
|
for(i=n=0; zUtf[i]; i++){
|
||||||
|
if( (zUtf[i]&0xc0)!=0x80 ){
|
||||||
|
n++;
|
||||||
|
if( n==aw ){
|
||||||
|
do{ i++; }while( (zUtf[i]&0xc0)==0x80 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if( n>=aw ){
|
||||||
|
utf8_printf(pOut, "%.*s", i, zUtf);
|
||||||
|
}else if( w<0 ){
|
||||||
|
utf8_printf(pOut, "%*s%s", aw-n, "", zUtf);
|
||||||
|
}else{
|
||||||
|
utf8_printf(pOut, "%s%*s", zUtf, aw-n, "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Determines if a string is a number of not.
|
** Determines if a string is a number of not.
|
||||||
@ -1878,13 +1908,8 @@ static int shell_callback(
|
|||||||
p->actualWidth[i] = w;
|
p->actualWidth[i] = w;
|
||||||
}
|
}
|
||||||
if( showHdr ){
|
if( showHdr ){
|
||||||
if( w<0 ){
|
utf8_width_print(p->out, w, azCol[i]);
|
||||||
utf8_printf(p->out,"%*.*s%s",-w,-w,azCol[i],
|
utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
|
||||||
i==nArg-1 ? rowSep : " ");
|
|
||||||
}else{
|
|
||||||
utf8_printf(p->out,"%-*.*s%s",w,w,azCol[i],
|
|
||||||
i==nArg-1 ? rowSep : " ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if( showHdr ){
|
if( showHdr ){
|
||||||
@ -1920,15 +1945,8 @@ static int shell_callback(
|
|||||||
}
|
}
|
||||||
p->iIndent++;
|
p->iIndent++;
|
||||||
}
|
}
|
||||||
if( w<0 ){
|
utf8_width_print(p->out, w, azArg[i] ? azArg[i] : p->nullValue);
|
||||||
utf8_printf(p->out,"%*.*s%s",-w,-w,
|
utf8_printf(p->out, "%s", i==nArg-1 ? rowSep : " ");
|
||||||
azArg[i] ? azArg[i] : p->nullValue,
|
|
||||||
i==nArg-1 ? rowSep : " ");
|
|
||||||
}else{
|
|
||||||
utf8_printf(p->out,"%-*.*s%s",w,w,
|
|
||||||
azArg[i] ? azArg[i] : p->nullValue,
|
|
||||||
i==nArg-1 ? rowSep : " ");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -470,6 +470,11 @@ void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
|
|||||||
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
|
sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case TK_IF_NULL_ROW: {
|
||||||
|
sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
|
||||||
|
sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
|
sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
|
||||||
break;
|
break;
|
||||||
|
23
src/vdbe.c
23
src/vdbe.c
@ -486,6 +486,7 @@ static void registerTrace(int iReg, Mem *p){
|
|||||||
printf("REG[%d] = ", iReg);
|
printf("REG[%d] = ", iReg);
|
||||||
memTracePrint(p);
|
memTracePrint(p);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
sqlite3VdbeCheckMemInvariants(p);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -1151,7 +1152,7 @@ case OP_Null: { /* out2 */
|
|||||||
case OP_SoftNull: {
|
case OP_SoftNull: {
|
||||||
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
|
assert( pOp->p1>0 && pOp->p1<=(p->nMem+1 - p->nCursor) );
|
||||||
pOut = &aMem[pOp->p1];
|
pOut = &aMem[pOp->p1];
|
||||||
pOut->flags = (pOut->flags|MEM_Null)&~MEM_Undefined;
|
pOut->flags = (pOut->flags&~(MEM_Undefined|MEM_AffMask))|MEM_Null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1494,7 +1495,6 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
|||||||
type2 = numericType(pIn2);
|
type2 = numericType(pIn2);
|
||||||
pOut = &aMem[pOp->p3];
|
pOut = &aMem[pOp->p3];
|
||||||
flags = pIn1->flags | pIn2->flags;
|
flags = pIn1->flags | pIn2->flags;
|
||||||
if( (flags & MEM_Null)!=0 ) goto arithmetic_result_is_null;
|
|
||||||
if( (type1 & type2 & MEM_Int)!=0 ){
|
if( (type1 & type2 & MEM_Int)!=0 ){
|
||||||
iA = pIn1->u.i;
|
iA = pIn1->u.i;
|
||||||
iB = pIn2->u.i;
|
iB = pIn2->u.i;
|
||||||
@ -1518,6 +1518,8 @@ case OP_Remainder: { /* same as TK_REM, in1, in2, out3 */
|
|||||||
}
|
}
|
||||||
pOut->u.i = iB;
|
pOut->u.i = iB;
|
||||||
MemSetTypeFlag(pOut, MEM_Int);
|
MemSetTypeFlag(pOut, MEM_Int);
|
||||||
|
}else if( (flags & MEM_Null)!=0 ){
|
||||||
|
goto arithmetic_result_is_null;
|
||||||
}else{
|
}else{
|
||||||
bIntint = 0;
|
bIntint = 0;
|
||||||
fp_math:
|
fp_math:
|
||||||
@ -2429,6 +2431,23 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Opcode: IfNullRow P1 P2 P3 * *
|
||||||
|
** Synopsis: if P1.nullRow then r[P3]=NULL, goto P2
|
||||||
|
**
|
||||||
|
** Check the cursor P1 to see if it is currently pointing at a NULL row.
|
||||||
|
** If it is, then set register P3 to NULL and jump immediately to P2.
|
||||||
|
** If P1 is not on a NULL row, then fall through without making any
|
||||||
|
** changes.
|
||||||
|
*/
|
||||||
|
case OP_IfNullRow: { /* jump */
|
||||||
|
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
|
||||||
|
if( p->apCsr[pOp->p1]->nullRow ){
|
||||||
|
sqlite3VdbeMemSetNull(aMem + pOp->p3);
|
||||||
|
goto jump_to_p2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
/* Opcode: Column P1 P2 P3 P4 P5
|
/* Opcode: Column P1 P2 P3 P4 P5
|
||||||
** Synopsis: r[P3]=PX
|
** Synopsis: r[P3]=PX
|
||||||
**
|
**
|
||||||
|
@ -40,6 +40,10 @@ int sqlite3VdbeCheckMemInvariants(Mem *p){
|
|||||||
/* Cannot be both MEM_Int and MEM_Real at the same time */
|
/* Cannot be both MEM_Int and MEM_Real at the same time */
|
||||||
assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
|
assert( (p->flags & (MEM_Int|MEM_Real))!=(MEM_Int|MEM_Real) );
|
||||||
|
|
||||||
|
/* Cannot be both MEM_Null and some other type */
|
||||||
|
assert( (p->flags & MEM_Null)==0 ||
|
||||||
|
(p->flags & (MEM_Int|MEM_Real|MEM_Str|MEM_Blob))==0 );
|
||||||
|
|
||||||
/* The szMalloc field holds the correct memory allocation size */
|
/* The szMalloc field holds the correct memory allocation size */
|
||||||
assert( p->szMalloc==0
|
assert( p->szMalloc==0
|
||||||
|| p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
|
|| p->szMalloc==sqlite3DbMallocSize(p->db,p->zMalloc) );
|
||||||
|
@ -5048,6 +5048,8 @@ void sqlite3WhereEnd(WhereInfo *pWInfo){
|
|||||||
}else if( pOp->opcode==OP_Rowid ){
|
}else if( pOp->opcode==OP_Rowid ){
|
||||||
pOp->p1 = pLevel->iIdxCur;
|
pOp->p1 = pLevel->iIdxCur;
|
||||||
pOp->opcode = OP_IdxRowid;
|
pOp->opcode = OP_IdxRowid;
|
||||||
|
}else if( pOp->opcode==OP_IfNullRow ){
|
||||||
|
pOp->p1 = pLevel->iIdxCur;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -388,5 +388,40 @@ do_execsql_test 9.4 {
|
|||||||
PRAGMA foreign_key_check(k2);
|
PRAGMA foreign_key_check(k2);
|
||||||
} {k2 3 s1 0}
|
} {k2 3 s1 0}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test using a WITHOUT ROWID table as the child table with an INTEGER
|
||||||
|
# PRIMARY KEY as the parent key.
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 10.1 {
|
||||||
|
CREATE TABLE p30 (id INTEGER PRIMARY KEY);
|
||||||
|
CREATE TABLE IF NOT EXISTS c30 (
|
||||||
|
line INTEGER,
|
||||||
|
master REFERENCES p30(id),
|
||||||
|
PRIMARY KEY(master)
|
||||||
|
) WITHOUT ROWID;
|
||||||
|
|
||||||
|
INSERT INTO p30 (id) VALUES (1);
|
||||||
|
INSERT INTO c30 (master, line) VALUES (1, 999);
|
||||||
|
}
|
||||||
|
do_execsql_test 10.2 {
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
}
|
||||||
|
do_execsql_test 10.3 {
|
||||||
|
INSERT INTO c30 VALUES(45, 45);
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
} {c30 {} p30 0}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test "foreign key mismatch" errors.
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 11.0 {
|
||||||
|
CREATE TABLE tt(y);
|
||||||
|
CREATE TABLE c11(x REFERENCES tt(y));
|
||||||
|
}
|
||||||
|
do_catchsql_test 11.1 {
|
||||||
|
PRAGMA foreign_key_check;
|
||||||
|
} {1 {foreign key mismatch - "c11" referencing "tt"}}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -243,5 +243,11 @@ do_execsql_test 8.5 {
|
|||||||
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
SELECT docid FROM t0 WHERE t0 MATCH '"abc abc"';
|
||||||
} {}
|
} {}
|
||||||
|
|
||||||
|
do_execsql_test 9.1 {
|
||||||
|
CREATE VIRTUAL TABLE t9 USING fts4(a, "", '---');
|
||||||
|
}
|
||||||
|
do_execsql_test 9.2 {
|
||||||
|
CREATE VIRTUAL TABLE t10 USING fts3(<, b, c);
|
||||||
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
65
test/fts3corrupt3.test
Normal file
65
test/fts3corrupt3.test
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
# 2010 October 27
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#***********************************************************************
|
||||||
|
# Test that the FTS3 extension does not crash when it encounters a
|
||||||
|
# corrupt data structure on disk.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
|
||||||
|
# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
|
||||||
|
ifcapable !fts3 { finish_test ; return }
|
||||||
|
|
||||||
|
set ::testprefix fts3corrupt3
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Test that fts3 does not choke on an oversized varint.
|
||||||
|
#
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
PRAGMA page_size = 512;
|
||||||
|
CREATE VIRTUAL TABLE t1 USING fts3;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t1 VALUES('one');
|
||||||
|
INSERT INTO t1 VALUES('one');
|
||||||
|
INSERT INTO t1 VALUES('one');
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
do_execsql_test 1.1 {
|
||||||
|
SELECT quote(root) from t1_segdir;
|
||||||
|
} {X'00036F6E6509010200010200010200'}
|
||||||
|
do_execsql_test 1.2 {
|
||||||
|
UPDATE t1_segdir SET root = X'00036F6E650EFFFFFFFFFFFFFFFFFFFFFFFF0200';
|
||||||
|
}
|
||||||
|
do_catchsql_test 1.3 {
|
||||||
|
SELECT rowid FROM t1 WHERE t1 MATCH 'one'
|
||||||
|
} {0 -1}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Interior node with the prefix or suffix count of an entry set to a
|
||||||
|
# negative value.
|
||||||
|
#
|
||||||
|
set doc1 [string repeat "x " 600]
|
||||||
|
set doc2 [string repeat "y " 600]
|
||||||
|
set doc3 [string repeat "z " 600]
|
||||||
|
|
||||||
|
do_execsql_test 2.0 {
|
||||||
|
CREATE VIRTUAL TABLE t2 USING fts3;
|
||||||
|
BEGIN;
|
||||||
|
INSERT INTO t2 VALUES($doc1);
|
||||||
|
INSERT INTO t2 VALUES($doc2);
|
||||||
|
INSERT INTO t2 VALUES($doc3);
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
do_execsql_test 2.1 {
|
||||||
|
SELECT quote(root) from t2_segdir;
|
||||||
|
} {X'0101017900017A'}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
@ -18,8 +18,6 @@ set ::testprefix fts3fault
|
|||||||
# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
|
# If SQLITE_ENABLE_FTS3 is not defined, omit this file.
|
||||||
ifcapable !fts3 { finish_test ; return }
|
ifcapable !fts3 { finish_test ; return }
|
||||||
|
|
||||||
if 0 {
|
|
||||||
|
|
||||||
# Test error handling in the sqlite3Fts3Init() function. This is the
|
# Test error handling in the sqlite3Fts3Init() function. This is the
|
||||||
# function that registers the FTS3 module and various support functions
|
# function that registers the FTS3 module and various support functions
|
||||||
# with SQLite.
|
# with SQLite.
|
||||||
@ -160,8 +158,6 @@ do_faultsim_test 7.3 -prep {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
proc mit {blob} {
|
proc mit {blob} {
|
||||||
set scan(littleEndian) i*
|
set scan(littleEndian) i*
|
||||||
set scan(bigEndian) I*
|
set scan(bigEndian) I*
|
||||||
@ -234,4 +230,12 @@ do_faultsim_test 9.1 -prep {
|
|||||||
faultsim_test_result {0 {{0 0 20 39 0 0 64 2}}}
|
faultsim_test_result {0 {{0 0 20 39 0 0 64 2}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_faultsim_test 10.1 -prep {
|
||||||
|
faultsim_delete_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { CREATE VIRTUAL TABLE t1 USING fts4(a, b, languageid=d) }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {}}
|
||||||
|
}
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
@ -174,4 +174,76 @@ do_faultsim_test 6.1 -faults oom* -prep {
|
|||||||
faultsim_test_result {0 -1}
|
faultsim_test_result {0 -1}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Inject faults into a query for an N-byte prefix that uses a prefix=N+1
|
||||||
|
# index.
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 7.0 {
|
||||||
|
CREATE VIRTUAL TABLE t7 USING fts4(x,prefix=2);
|
||||||
|
INSERT INTO t7 VALUES('the quick brown fox');
|
||||||
|
INSERT INTO t7 VALUES('jumped over the');
|
||||||
|
INSERT INTO t7 VALUES('lazy dog');
|
||||||
|
}
|
||||||
|
do_faultsim_test 7.1 -faults oom* -body {
|
||||||
|
execsql { SELECT docid FROM t7 WHERE t7 MATCH 't*' }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {1 2}}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Inject faults into a opening an existing fts3 table that has been
|
||||||
|
# upgraded to add an %_stat table.
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 8.0 {
|
||||||
|
CREATE VIRTUAL TABLE t8 USING fts3;
|
||||||
|
INSERT INTO t8 VALUES('the quick brown fox');
|
||||||
|
INSERT INTO t8 VALUES('jumped over the');
|
||||||
|
INSERT INTO t8 VALUES('lazy dog');
|
||||||
|
INSERT INTO t8(t8) VALUES('automerge=8');
|
||||||
|
SELECT name FROM sqlite_master WHERE name LIKE 't8%';
|
||||||
|
} {
|
||||||
|
t8 t8_content t8_segments t8_segdir t8_stat
|
||||||
|
}
|
||||||
|
faultsim_save_and_close
|
||||||
|
|
||||||
|
do_faultsim_test 8.1 -faults oom* -prep {
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { INSERT INTO t8 VALUES('one two three') }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {}}
|
||||||
|
}
|
||||||
|
|
||||||
|
do_faultsim_test 8.2 -faults oom* -prep {
|
||||||
|
faultsim_restore_and_reopen
|
||||||
|
} -body {
|
||||||
|
execsql { ALTER TABLE t8 RENAME TO t8ii }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 {}}
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
reset_db
|
||||||
|
set chunkconfig [fts3_configure_incr_load 1 1]
|
||||||
|
do_execsql_test 9.0 {
|
||||||
|
PRAGMA page_size = 512;
|
||||||
|
CREATE VIRTUAL TABLE t9 USING fts3;
|
||||||
|
WITH s(i) AS (
|
||||||
|
SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50
|
||||||
|
)
|
||||||
|
INSERT INTO t9 SELECT 'one two three' FROM s;
|
||||||
|
}
|
||||||
|
|
||||||
|
do_faultsim_test 8.2 -faults io* -body {
|
||||||
|
execsql { SELECT count(*) FROM t9 WHERE t9 MATCH '"one two three"' }
|
||||||
|
} -test {
|
||||||
|
faultsim_test_result {0 50}
|
||||||
|
}
|
||||||
|
|
||||||
|
eval fts3_configure_incr_load $chunkconfig
|
||||||
|
|
||||||
|
|
||||||
finish_test
|
finish_test
|
||||||
|
|
||||||
|
|
||||||
|
228
test/fts3misc.test
Normal file
228
test/fts3misc.test
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
# 2017 March 22
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source code. In place of
|
||||||
|
# a legal notice, here is a blessing:
|
||||||
|
#
|
||||||
|
# May you do good and not evil.
|
||||||
|
# May you find forgiveness for yourself and forgive others.
|
||||||
|
# May you share freely, never taking more than you give.
|
||||||
|
#
|
||||||
|
#*************************************************************************
|
||||||
|
# This file implements regression tests for SQLite library. The
|
||||||
|
# focus of this script is testing the FTS3 module.
|
||||||
|
#
|
||||||
|
|
||||||
|
set testdir [file dirname $argv0]
|
||||||
|
source $testdir/tester.tcl
|
||||||
|
set testprefix fts3misc
|
||||||
|
|
||||||
|
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||||
|
ifcapable !fts3 {
|
||||||
|
finish_test
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# A self-join.
|
||||||
|
#
|
||||||
|
do_execsql_test 1.0 {
|
||||||
|
CREATE VIRTUAL TABLE t1 USING fts3(a, b);
|
||||||
|
INSERT INTO t1 VALUES('one', 'i');
|
||||||
|
INSERT INTO t1 VALUES('one', 'ii');
|
||||||
|
INSERT INTO t1 VALUES('two', 'i');
|
||||||
|
INSERT INTO t1 VALUES('two', 'ii');
|
||||||
|
}
|
||||||
|
|
||||||
|
do_execsql_test 1.1 {
|
||||||
|
SELECT a.a, b.b FROM t1 a, t1 b WHERE a.t1 MATCH 'two' AND b.t1 MATCH 'i'
|
||||||
|
} {two i two i two i two i}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# FTS tables with 128 or more columns.
|
||||||
|
#
|
||||||
|
proc v1 {v} {
|
||||||
|
set vector [list a b c d e f g h]
|
||||||
|
set res [list]
|
||||||
|
for {set i 0} {$i<8} {incr i} {
|
||||||
|
if {$v & (1 << $i)} { lappend res [lindex $vector $i] }
|
||||||
|
}
|
||||||
|
set res
|
||||||
|
}
|
||||||
|
proc v2 {v} {
|
||||||
|
set vector [list d e f g h i j k]
|
||||||
|
set res [list]
|
||||||
|
for {set i 0} {$i<8} {incr i} {
|
||||||
|
if {$v & (1 << $i)} { lappend res [lindex $vector $i] }
|
||||||
|
}
|
||||||
|
set res
|
||||||
|
}
|
||||||
|
db func v1 v1
|
||||||
|
db func v2 v2
|
||||||
|
|
||||||
|
do_test 2.0 {
|
||||||
|
set cols [list]
|
||||||
|
for {set i 0} {$i<200} {incr i} {
|
||||||
|
lappend cols "c$i"
|
||||||
|
}
|
||||||
|
execsql "CREATE VIRTUAL TABLE t2 USING fts3([join $cols ,])"
|
||||||
|
execsql {
|
||||||
|
WITH data(i) AS (
|
||||||
|
SELECT 1 UNION ALL SELECT i+1 FROM data WHERE i<200
|
||||||
|
)
|
||||||
|
INSERT INTO t2(c198, c199) SELECT v1(i), v2(i) FROM data;
|
||||||
|
}
|
||||||
|
} {}
|
||||||
|
do_execsql_test 2.1 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH '"a b c"'
|
||||||
|
} {
|
||||||
|
7 15 23 31 39 47 55 63 71 79 87 95 103 111
|
||||||
|
119 127 135 143 151 159 167 175 183 191 199
|
||||||
|
}
|
||||||
|
do_execsql_test 2.2 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH '"g h i"'
|
||||||
|
} {
|
||||||
|
56 57 58 59 60 61 62 63 120 121 122 123 124
|
||||||
|
125 126 127 184 185 186 187 188 189 190 191
|
||||||
|
}
|
||||||
|
do_execsql_test 2.3 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH '"i h"'
|
||||||
|
} {
|
||||||
|
}
|
||||||
|
do_execsql_test 2.4 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH '"f e"'
|
||||||
|
} {
|
||||||
|
}
|
||||||
|
do_execsql_test 2.5 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH '"e f"'
|
||||||
|
} {
|
||||||
|
6 7 14 15 22 23 30 31 38 39 46 47 48 49 50 51 52 53 54 55 56
|
||||||
|
57 58 59 60 61 62 63 70 71 78 79 86 87 94 95 102 103 110
|
||||||
|
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127
|
||||||
|
134 135 142 143 150 151 158 159 166 167 174 175 176 177 178 179 180
|
||||||
|
181 182 183 184 185 186 187 188 189 190 191 198 199
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Range constraints on the docid using non-integer values.
|
||||||
|
#
|
||||||
|
do_execsql_test 2.6 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH 'e' AND rowid BETWEEN NULL AND 45;
|
||||||
|
} {}
|
||||||
|
do_execsql_test 2.7 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH 'e' AND rowid BETWEEN 11.5 AND 48.2;
|
||||||
|
} {
|
||||||
|
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
||||||
|
29 30 31 34 35 38 39 42 43 46 47 48
|
||||||
|
}
|
||||||
|
do_execsql_test 2.8 {
|
||||||
|
SELECT rowid FROM t2 WHERE t2 MATCH 'e' AND rowid BETWEEN '11.5' AND '48.2';
|
||||||
|
} {
|
||||||
|
14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
||||||
|
29 30 31 34 35 38 39 42 43 46 47 48
|
||||||
|
}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
# Phrase query tests.
|
||||||
|
#
|
||||||
|
do_execsql_test 3.1.1 {
|
||||||
|
CREATE VIRTUAL TABLE t3 USING fts3;
|
||||||
|
INSERT INTO t3 VALUES('a b c');
|
||||||
|
INSERT INTO t3 VALUES('d e f');
|
||||||
|
INSERT INTO t3 VALUES('a b d');
|
||||||
|
INSERT INTO t3 VALUES('1 2 3 4 5 6 7 8 9 10 11');
|
||||||
|
}
|
||||||
|
do_execsql_test 3.1.2 {
|
||||||
|
SELECT * FROM t3 WHERE t3 MATCH '"a b x y"' ORDER BY docid DESC
|
||||||
|
}
|
||||||
|
do_execsql_test 3.1.3 {
|
||||||
|
SELECT * FROM t3 WHERE t3 MATCH '"a b c" OR "a b x y"' ORDER BY docid DESC
|
||||||
|
} {{a b c}}
|
||||||
|
do_execsql_test 3.1.4 {
|
||||||
|
SELECT * FROM t3 WHERE t3 MATCH '"a* b* x* a*"'
|
||||||
|
}
|
||||||
|
do_execsql_test 3.1.5 {
|
||||||
|
SELECT rowid FROM t3 WHERE t3 MATCH '"2 3 4 5 6 7 8 9"'
|
||||||
|
} {4}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 4.0 {
|
||||||
|
PRAGMA page_size = 512;
|
||||||
|
CREATE VIRTUAL TABLE t4 USING fts4;
|
||||||
|
WITH s(i) AS ( SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<8000 )
|
||||||
|
INSERT INTO t4 SELECT 'a b c a b c a b c' FROM s;
|
||||||
|
}
|
||||||
|
do_execsql_test 4.1 {
|
||||||
|
SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"'
|
||||||
|
} {8000}
|
||||||
|
do_execsql_test 4.2 {
|
||||||
|
SELECT quote(value) from t4_stat where id=0
|
||||||
|
} {X'C03EC0B204C0A608'}
|
||||||
|
do_execsql_test 4.3 {
|
||||||
|
UPDATE t4_stat SET value = X'C03EC0B204C0A60800' WHERE id=0;
|
||||||
|
}
|
||||||
|
do_catchsql_test 4.4 {
|
||||||
|
SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"'
|
||||||
|
} {1 {database disk image is malformed}}
|
||||||
|
do_execsql_test 4.5 {
|
||||||
|
UPDATE t4_stat SET value = X'00C03EC0B204C0A608' WHERE id=0;
|
||||||
|
}
|
||||||
|
do_catchsql_test 4.6 {
|
||||||
|
SELECT count(*) FROM t4 WHERE t4 MATCH '"a b c" OR "c a b"'
|
||||||
|
} {1 {database disk image is malformed}}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 5.0 {
|
||||||
|
CREATE VIRTUAL TABLE t5 USING fts4;
|
||||||
|
INSERT INTO t5 VALUES('a x x x x b x x x x c');
|
||||||
|
INSERT INTO t5 VALUES('a x x x x b x x x x c');
|
||||||
|
INSERT INTO t5 VALUES('a x x x x b x x x x c');
|
||||||
|
}
|
||||||
|
do_execsql_test 5.1 {
|
||||||
|
SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/4 b NEAR/4 c'
|
||||||
|
} {1 2 3}
|
||||||
|
do_execsql_test 5.2 {
|
||||||
|
SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/3 b NEAR/4 c'
|
||||||
|
} {}
|
||||||
|
do_execsql_test 5.3 {
|
||||||
|
SELECT rowid FROM t5 WHERE t5 MATCH 'a NEAR/4 b NEAR/3 c'
|
||||||
|
} {}
|
||||||
|
do_execsql_test 5.4 {
|
||||||
|
SELECT rowid FROM t5 WHERE t5 MATCH 'y NEAR/4 b NEAR/4 c'
|
||||||
|
} {}
|
||||||
|
do_execsql_test 5.5 {
|
||||||
|
SELECT rowid FROM t5 WHERE t5 MATCH 'x OR a NEAR/3 b NEAR/3 c'
|
||||||
|
} {1 2 3}
|
||||||
|
do_execsql_test 5.5 {
|
||||||
|
SELECT rowid FROM t5 WHERE t5 MATCH 'x OR y NEAR/3 b NEAR/3 c'
|
||||||
|
} {1 2 3}
|
||||||
|
|
||||||
|
#-------------------------------------------------------------------------
|
||||||
|
#
|
||||||
|
reset_db
|
||||||
|
do_execsql_test 6.0 {
|
||||||
|
CREATE VIRTUAL TABLE t6 USING fts4;
|
||||||
|
|
||||||
|
BEGIN;
|
||||||
|
WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
|
||||||
|
INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s;
|
||||||
|
|
||||||
|
INSERT INTO t6 VALUES('x x x x x x x x x x x A');
|
||||||
|
INSERT INTO t6 VALUES('x x x x x x x x x x x B');
|
||||||
|
INSERT INTO t6 VALUES('x x x x x x x x x x x A');
|
||||||
|
INSERT INTO t6 VALUES('x x x x x x x x x x x B');
|
||||||
|
|
||||||
|
WITH s(i) AS (SELECT 1 UNION ALL SELECT i+1 FROM s WHERE i<50000)
|
||||||
|
INSERT INTO t6 SELECT 'x x x x x x x x x x x' FROM s;
|
||||||
|
COMMIT;
|
||||||
|
}
|
||||||
|
breakpoint
|
||||||
|
do_execsql_test 6.1 {
|
||||||
|
SELECT rowid FROM t6 WHERE t6 MATCH 'b OR "x a"'
|
||||||
|
} {50001 50002 50003 50004}
|
||||||
|
|
||||||
|
|
||||||
|
finish_test
|
@ -14,7 +14,6 @@
|
|||||||
|
|
||||||
set testdir [file dirname $argv0]
|
set testdir [file dirname $argv0]
|
||||||
source $testdir/tester.tcl
|
source $testdir/tester.tcl
|
||||||
set ::testprefix fts4content
|
|
||||||
|
|
||||||
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
# If SQLITE_ENABLE_FTS3 is defined, omit this file.
|
||||||
ifcapable !fts3 {
|
ifcapable !fts3 {
|
||||||
@ -341,6 +340,13 @@ do_test_query1 3.3.4 {"zero one" OR "one two"} {
|
|||||||
or_merge_lists [rowid_list "zero one"] [rowid_list "one two"]
|
or_merge_lists [rowid_list "zero one"] [rowid_list "one two"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
do_execsql_test 3.4 {
|
||||||
|
CREATE TABLE t8c(a, b);
|
||||||
|
CREATE VIRTUAL TABLE t8 USING fts4(content=t8c, languageid=langid);
|
||||||
|
INSERT INTO t8(docid, a, b) VALUES(-1, 'one two three', 'x y z');
|
||||||
|
SELECT docid FROM t8 WHERE t8 MATCH 'one x' AND langid=0
|
||||||
|
} {-1}
|
||||||
|
|
||||||
#-------------------------------------------------------------------------
|
#-------------------------------------------------------------------------
|
||||||
# Test cases 4.*
|
# Test cases 4.*
|
||||||
#
|
#
|
||||||
|
@ -266,6 +266,8 @@ test_suite "fts3" -prefix "" -description {
|
|||||||
fts4incr.test fts4langid.test fts4lastrowid.test fts4merge2.test
|
fts4incr.test fts4langid.test fts4lastrowid.test fts4merge2.test
|
||||||
fts4merge4.test fts4merge.test fts4noti.test fts4onepass.test
|
fts4merge4.test fts4merge.test fts4noti.test fts4onepass.test
|
||||||
fts4opt.test fts4unicode.test
|
fts4opt.test fts4unicode.test
|
||||||
|
fts3corrupt3.test
|
||||||
|
fts3misc.test
|
||||||
}
|
}
|
||||||
|
|
||||||
test_suite "fts5" -prefix "" -description {
|
test_suite "fts5" -prefix "" -description {
|
||||||
|
@ -39,6 +39,7 @@ set extras {
|
|||||||
REGISTER
|
REGISTER
|
||||||
VECTOR
|
VECTOR
|
||||||
SELECT_COLUMN
|
SELECT_COLUMN
|
||||||
|
IF_NULL_ROW
|
||||||
ASTERISK
|
ASTERISK
|
||||||
SPAN
|
SPAN
|
||||||
SPACE
|
SPACE
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
#if !defined(_MSC_VER)
|
#if !defined(_MSC_VER)
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#else
|
#else
|
||||||
#include <io.h>
|
#include <io.h>
|
||||||
#endif
|
#endif
|
||||||
@ -579,6 +580,14 @@ int main(int argc, char **argv){
|
|||||||
decode_btree_page(a, iStart, hdrSize, zLeft+1);
|
decode_btree_page(a, iStart, hdrSize, zLeft+1);
|
||||||
free(a);
|
free(a);
|
||||||
continue;
|
continue;
|
||||||
|
#if !defined(_MSC_VER)
|
||||||
|
}else if( zLeft && strcmp(zLeft,"truncate")==0 ){
|
||||||
|
/* Frame number followed by "truncate" truncates the WAL file
|
||||||
|
** after that frame */
|
||||||
|
off_t newSize = 32 + iStart*(pagesize+24);
|
||||||
|
truncate(argv[1], newSize);
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
}else{
|
}else{
|
||||||
iEnd = iStart;
|
iEnd = iStart;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user