mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-29 08:01:23 +03:00
Fix a problem with fts5 synonyms and the xQueryPhrase() auxiliary function API.
FossilOrigin-Name: cf3e45e76d23e10ee06296c3561a341591597a04
This commit is contained in:
@ -251,79 +251,6 @@ int sqlite3Fts5ExprNew(
|
||||
return sParse.rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new FTS5 expression by cloning phrase iPhrase of the
|
||||
** expression passed as the second argument.
|
||||
*/
|
||||
int sqlite3Fts5ExprPhraseExpr(
|
||||
Fts5Config *pConfig,
|
||||
Fts5Expr *pExpr,
|
||||
int iPhrase,
|
||||
Fts5Expr **ppNew
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
|
||||
Fts5ExprPhrase *pCopy; /* Copy of pOrig */
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
pCopy = (Fts5ExprPhrase*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * pOrig->nTerm
|
||||
);
|
||||
if( pCopy ){
|
||||
int i; /* Used to iterate through phrase terms */
|
||||
Fts5ExprPhrase **apPhrase;
|
||||
Fts5ExprNode *pNode;
|
||||
Fts5ExprNearset *pNear;
|
||||
|
||||
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
|
||||
apPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprPhrase*)
|
||||
);
|
||||
pNode = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5ExprNode));
|
||||
pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*)
|
||||
);
|
||||
|
||||
for(i=0; i<pOrig->nTerm; i++){
|
||||
pCopy->aTerm[i].zTerm = sqlite3Fts5Strndup(&rc, pOrig->aTerm[i].zTerm,-1);
|
||||
pCopy->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* All the allocations succeeded. Put the expression object together. */
|
||||
pNew->pIndex = pExpr->pIndex;
|
||||
pNew->pRoot = pNode;
|
||||
pNew->nPhrase = 1;
|
||||
pNew->apExprPhrase = apPhrase;
|
||||
pNew->apExprPhrase[0] = pCopy;
|
||||
|
||||
pNode->eType = (pOrig->nTerm==1 ? FTS5_TERM : FTS5_STRING);
|
||||
pNode->pNear = pNear;
|
||||
|
||||
pNear->nPhrase = 1;
|
||||
pNear->apPhrase[0] = pCopy;
|
||||
|
||||
pCopy->nTerm = pOrig->nTerm;
|
||||
pCopy->pNode = pNode;
|
||||
}else{
|
||||
/* At least one allocation failed. Free them all. */
|
||||
for(i=0; i<pOrig->nTerm; i++){
|
||||
sqlite3_free(pCopy->aTerm[i].zTerm);
|
||||
}
|
||||
sqlite3_free(pCopy);
|
||||
sqlite3_free(pNear);
|
||||
sqlite3_free(pNode);
|
||||
sqlite3_free(apPhrase);
|
||||
sqlite3_free(pNew);
|
||||
pNew = 0;
|
||||
}
|
||||
}
|
||||
|
||||
*ppNew = pNew;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Free the expression node object passed as the only argument.
|
||||
*/
|
||||
@ -1550,8 +1477,8 @@ static int fts5ParseTokenize(
|
||||
int tflags, /* Mask of FTS5_TOKEN_* flags */
|
||||
const char *pToken, /* Buffer containing token */
|
||||
int nToken, /* Size of token in bytes */
|
||||
int iStart, /* Start offset of token */
|
||||
int iEnd /* End offset of token */
|
||||
int iUnused1, /* Start offset of token */
|
||||
int iUnused2 /* End offset of token */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
const int SZALLOC = 8;
|
||||
@ -1577,7 +1504,7 @@ static int fts5ParseTokenize(
|
||||
|
||||
pNew = (Fts5ExprPhrase*)sqlite3_realloc(pPhrase,
|
||||
sizeof(Fts5ExprPhrase) + sizeof(Fts5ExprTerm) * nNew
|
||||
);
|
||||
);
|
||||
if( pNew==0 ) return SQLITE_NOMEM;
|
||||
if( pPhrase==0 ) memset(pNew, 0, sizeof(Fts5ExprPhrase));
|
||||
pCtx->pPhrase = pPhrase = pNew;
|
||||
@ -1675,6 +1602,83 @@ Fts5ExprPhrase *sqlite3Fts5ParseTerm(
|
||||
return sCtx.pPhrase;
|
||||
}
|
||||
|
||||
/*
|
||||
** Create a new FTS5 expression by cloning phrase iPhrase of the
|
||||
** expression passed as the second argument.
|
||||
*/
|
||||
int sqlite3Fts5ExprClonePhrase(
|
||||
Fts5Config *pConfig,
|
||||
Fts5Expr *pExpr,
|
||||
int iPhrase,
|
||||
Fts5Expr **ppNew
|
||||
){
|
||||
int rc = SQLITE_OK; /* Return code */
|
||||
Fts5ExprPhrase *pOrig; /* The phrase extracted from pExpr */
|
||||
Fts5ExprPhrase *pCopy; /* Copy of pOrig */
|
||||
int i; /* Used to iterate through phrase terms */
|
||||
|
||||
Fts5Expr *pNew = 0; /* Expression to return via *ppNew */
|
||||
Fts5ExprPhrase **apPhrase; /* pNew->apPhrase */
|
||||
Fts5ExprNode *pNode; /* pNew->pRoot */
|
||||
Fts5ExprNearset *pNear; /* pNew->pRoot->pNear */
|
||||
|
||||
TokenCtx sCtx = {0}; /* Context object for fts5ParseTokenize */
|
||||
|
||||
|
||||
pOrig = pExpr->apExprPhrase[iPhrase];
|
||||
|
||||
pNew = (Fts5Expr*)sqlite3Fts5MallocZero(&rc, sizeof(Fts5Expr));
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->apExprPhrase = (Fts5ExprPhrase**)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pRoot = (Fts5ExprNode*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNode));
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
pNew->pRoot->pNear = (Fts5ExprNearset*)sqlite3Fts5MallocZero(&rc,
|
||||
sizeof(Fts5ExprNearset) + sizeof(Fts5ExprPhrase*));
|
||||
}
|
||||
|
||||
for(i=0; rc==SQLITE_OK && i<pOrig->nTerm; i++){
|
||||
int tflags = 0;
|
||||
Fts5ExprTerm *p;
|
||||
for(p=&pOrig->aTerm[i]; p && rc==SQLITE_OK; p=p->pSynonym){
|
||||
const char *zTerm = p->zTerm;
|
||||
rc = fts5ParseTokenize((void*)&sCtx, tflags, zTerm, strlen(zTerm), 0, 0);
|
||||
tflags = FTS5_TOKEN_COLOCATED;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sCtx.pPhrase->aTerm[i].bPrefix = pOrig->aTerm[i].bPrefix;
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
/* All the allocations succeeded. Put the expression object together. */
|
||||
pNew->pIndex = pExpr->pIndex;
|
||||
pNew->nPhrase = 1;
|
||||
pNew->apExprPhrase[0] = sCtx.pPhrase;
|
||||
pNew->pRoot->pNear->apPhrase[0] = sCtx.pPhrase;
|
||||
pNew->pRoot->pNear->nPhrase = 1;
|
||||
sCtx.pPhrase->pNode = pNew->pRoot;
|
||||
|
||||
if( pOrig->nTerm==1 && pOrig->aTerm[0].pSynonym==0 ){
|
||||
pNew->pRoot->eType = FTS5_TERM;
|
||||
}else{
|
||||
pNew->pRoot->eType = FTS5_STRING;
|
||||
}
|
||||
}else{
|
||||
sqlite3Fts5ExprFree(pNew);
|
||||
fts5ExprPhraseFree(sCtx.pPhrase);
|
||||
pNew = 0;
|
||||
}
|
||||
|
||||
*ppNew = pNew;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Token pTok has appeared in a MATCH expression where the NEAR operator
|
||||
** is expected. If token pTok does not contain "NEAR", store an error
|
||||
|
Reference in New Issue
Block a user