Add the "columnsize=" option to fts5, similar to fts4's "matchinfo=fts3".
FossilOrigin-Name: aa12f9d9b79c2f523fd6b00e47bcb66dba09ce0c
This commit is contained in:
parent
90502c3dc7
commit
bcc2f04c68
@ -1039,6 +1039,7 @@ static int fts5FilterMethod(
|
||||
sqlite3_value **apVal /* Arguments for the indexing scheme */
|
||||
){
|
||||
Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
|
||||
int rc = SQLITE_OK; /* Error code */
|
||||
int iVal = 0; /* Counter for apVal[] */
|
||||
@ -1049,7 +1050,7 @@ static int fts5FilterMethod(
|
||||
sqlite3_value *pRowidEq = 0; /* rowid = ? expression (or NULL) */
|
||||
sqlite3_value *pRowidLe = 0; /* rowid <= ? expression (or NULL) */
|
||||
sqlite3_value *pRowidGe = 0; /* rowid >= ? expression (or NULL) */
|
||||
char **pzErrmsg = pTab->pConfig->pzErrmsg;
|
||||
char **pzErrmsg = pConfig->pzErrmsg;
|
||||
|
||||
assert( pCsr->pStmt==0 );
|
||||
assert( pCsr->pExpr==0 );
|
||||
@ -1059,7 +1060,7 @@ static int fts5FilterMethod(
|
||||
assert( pCsr->zRankArgs==0 );
|
||||
|
||||
assert( pzErrmsg==0 || pzErrmsg==&pTab->base.zErrMsg );
|
||||
pTab->pConfig->pzErrmsg = &pTab->base.zErrMsg;
|
||||
pConfig->pzErrmsg = &pTab->base.zErrMsg;
|
||||
|
||||
/* Decode the arguments passed through to this function.
|
||||
**
|
||||
@ -1107,7 +1108,7 @@ static int fts5FilterMethod(
|
||||
}else if( pMatch ){
|
||||
const char *zExpr = (const char*)sqlite3_value_text(apVal[0]);
|
||||
|
||||
rc = fts5CursorParseRank(pTab->pConfig, pCsr, pRank);
|
||||
rc = fts5CursorParseRank(pConfig, pCsr, pRank);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( zExpr[0]=='*' ){
|
||||
/* The user has issued a query of the form "MATCH '*...'". This
|
||||
@ -1116,7 +1117,7 @@ static int fts5FilterMethod(
|
||||
rc = fts5SpecialMatch(pTab, pCsr, &zExpr[1]);
|
||||
}else{
|
||||
char **pzErr = &pTab->base.zErrMsg;
|
||||
rc = sqlite3Fts5ExprNew(pTab->pConfig, zExpr, &pCsr->pExpr, pzErr);
|
||||
rc = sqlite3Fts5ExprNew(pConfig, zExpr, &pCsr->pExpr, pzErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
if( bOrderByRank ){
|
||||
pCsr->ePlan = FTS5_PLAN_SORTED_MATCH;
|
||||
@ -1128,6 +1129,11 @@ static int fts5FilterMethod(
|
||||
}
|
||||
}
|
||||
}
|
||||
}else if( pConfig->zContent==0 ){
|
||||
*pConfig->pzErrmsg = sqlite3_mprintf(
|
||||
"%s: table does not support scanning", pConfig->zName
|
||||
);
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
|
||||
** by rowid (ePlan==FTS5_PLAN_ROWID). */
|
||||
@ -1146,7 +1152,7 @@ static int fts5FilterMethod(
|
||||
}
|
||||
}
|
||||
|
||||
pTab->pConfig->pzErrmsg = pzErrmsg;
|
||||
pConfig->pzErrmsg = pzErrmsg;
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -1621,23 +1627,58 @@ static int fts5ApiColumnText(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5ColumnSizeCb(
|
||||
void *pContext, /* Pointer to int */
|
||||
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 *pCnt = (int*)pContext;
|
||||
*pCnt = *pCnt + 1;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static int fts5ApiColumnSize(Fts5Context *pCtx, int iCol, int *pnToken){
|
||||
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
|
||||
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
|
||||
Fts5Config *pConfig = pTab->pConfig;
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_DOCSIZE) ){
|
||||
i64 iRowid = fts5CursorRowid(pCsr);
|
||||
rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
|
||||
if( pConfig->bColumnsize ){
|
||||
i64 iRowid = fts5CursorRowid(pCsr);
|
||||
rc = sqlite3Fts5StorageDocsize(pTab->pStorage, iRowid, pCsr->aColumnSize);
|
||||
}else if( pConfig->zContent==0 ){
|
||||
int i;
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
pCsr->aColumnSize[i] = -1;
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int i;
|
||||
for(i=0; rc==SQLITE_OK && i<pConfig->nCol; i++){
|
||||
if( pConfig->abUnindexed[i]==0 ){
|
||||
const char *z; int n;
|
||||
void *p = (void*)(&pCsr->aColumnSize[i]);
|
||||
pCsr->aColumnSize[i] = 0;
|
||||
rc = fts5ApiColumnText(pCtx, i, &z, &n);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5Tokenize(pConfig, z, n, p, fts5ColumnSizeCb);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
CsrFlagClear(pCsr, FTS5CSR_REQUIRE_DOCSIZE);
|
||||
}
|
||||
if( iCol<0 ){
|
||||
int i;
|
||||
*pnToken = 0;
|
||||
for(i=0; i<pTab->pConfig->nCol; i++){
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
*pnToken += pCsr->aColumnSize[i];
|
||||
}
|
||||
}else if( iCol<pTab->pConfig->nCol ){
|
||||
}else if( iCol<pConfig->nCol ){
|
||||
*pnToken = pCsr->aColumnSize[iCol];
|
||||
}else{
|
||||
*pnToken = 0;
|
||||
@ -1956,7 +1997,7 @@ static int fts5FindFunctionMethod(
|
||||
}
|
||||
|
||||
/*
|
||||
** Implementation of FTS3 xRename method. Rename an fts5 table.
|
||||
** Implementation of FTS5 xRename method. Rename an fts5 table.
|
||||
*/
|
||||
static int fts5RenameMethod(
|
||||
sqlite3_vtab *pVtab, /* Virtual table handle */
|
||||
|
@ -105,6 +105,9 @@ typedef struct Fts5Config Fts5Config;
|
||||
** decent error message if it encounters a file-format version it does
|
||||
** not understand.
|
||||
**
|
||||
** bColumnsize:
|
||||
** True if the %_docsize table is created.
|
||||
**
|
||||
*/
|
||||
struct Fts5Config {
|
||||
sqlite3 *db; /* Database handle */
|
||||
@ -118,6 +121,7 @@ struct Fts5Config {
|
||||
int eContent; /* An FTS5_CONTENT value */
|
||||
char *zContent; /* content table */
|
||||
char *zContentRowid; /* "content_rowid=" option value */
|
||||
int bColumnsize; /* "columnsize=" option value (dflt==1) */
|
||||
char *zContentExprlist;
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
@ -196,6 +200,8 @@ void sqlite3Fts5BufferSet(int*, Fts5Buffer*, int, const u8*);
|
||||
void sqlite3Fts5BufferAppendPrintf(int *, Fts5Buffer*, char *zFmt, ...);
|
||||
void sqlite3Fts5BufferAppend32(int*, Fts5Buffer*, int);
|
||||
|
||||
char *sqlite3Fts5Mprintf(int *pRc, char *zFmt, ...);
|
||||
|
||||
#define fts5BufferZero(x) sqlite3Fts5BufferZero(x)
|
||||
#define fts5BufferGrow(a,b,c) sqlite3Fts5BufferGrow(a,b,c)
|
||||
#define fts5BufferAppendVarint(a,b,c) sqlite3Fts5BufferAppendVarint(a,b,c)
|
||||
|
@ -125,6 +125,21 @@ void sqlite3Fts5BufferAppendPrintf(
|
||||
}
|
||||
}
|
||||
|
||||
char *sqlite3Fts5Mprintf(int *pRc, char *zFmt, ...){
|
||||
char *zRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
va_list ap;
|
||||
va_start(ap, zFmt);
|
||||
zRet = sqlite3_vmprintf(zFmt, ap);
|
||||
va_end(ap);
|
||||
if( zRet==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
return zRet;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Free any buffer allocated by pBuf. Zero the structure before returning.
|
||||
*/
|
||||
|
@ -196,7 +196,7 @@ void sqlite3Fts5Dequote(char *z){
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse the "special" CREATE VIRTUAL TABLE directive and update
|
||||
** Parse a "special" CREATE VIRTUAL TABLE directive and update
|
||||
** configuration object pConfig as appropriate.
|
||||
**
|
||||
** If successful, object pConfig is updated and SQLITE_OK returned. If
|
||||
@ -211,10 +211,10 @@ static int fts5ConfigParseSpecial(
|
||||
const char *zArg, /* Argument to parse */
|
||||
char **pzErr /* OUT: Error message */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int nCmd = strlen(zCmd);
|
||||
if( sqlite3_strnicmp("prefix", zCmd, nCmd)==0 ){
|
||||
const int nByte = sizeof(int) * FTS5_MAX_PREFIX_INDEXES;
|
||||
int rc = SQLITE_OK;
|
||||
const char *p;
|
||||
if( pConfig->aPrefix ){
|
||||
*pzErr = sqlite3_mprintf("multiple prefix=... directives");
|
||||
@ -248,7 +248,6 @@ static int fts5ConfigParseSpecial(
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("tokenize", zCmd, nCmd)==0 ){
|
||||
int rc = SQLITE_OK;
|
||||
const char *p = (const char*)zArg;
|
||||
int nArg = strlen(zArg) + 1;
|
||||
char **azArg = sqlite3Fts5MallocZero(&rc, sizeof(char*) * nArg);
|
||||
@ -293,7 +292,6 @@ static int fts5ConfigParseSpecial(
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
|
||||
int rc = SQLITE_OK;
|
||||
if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
|
||||
*pzErr = sqlite3_mprintf("multiple content=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
@ -301,19 +299,15 @@ static int fts5ConfigParseSpecial(
|
||||
if( zArg[0] ){
|
||||
pConfig->eContent = FTS5_CONTENT_EXTERNAL;
|
||||
pConfig->zContent = sqlite3_mprintf("%Q.%Q", pConfig->zDb, zArg);
|
||||
if( pConfig->zContent==0 ) rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
pConfig->eContent = FTS5_CONTENT_NONE;
|
||||
pConfig->zContent = sqlite3_mprintf(
|
||||
"%Q.'%q_docsize'", pConfig->zDb, pConfig->zName
|
||||
);
|
||||
}
|
||||
if( pConfig->zContent==0 ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("content_rowid", zCmd, nCmd)==0 ){
|
||||
int rc = SQLITE_OK;
|
||||
if( pConfig->zContentRowid ){
|
||||
*pzErr = sqlite3_mprintf("multiple content_rowid=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
@ -323,6 +317,16 @@ static int fts5ConfigParseSpecial(
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("columnsize", zCmd, nCmd)==0 ){
|
||||
if( (zArg[0]!='0' && zArg[0]!='1') || zArg[1]!='\0' ){
|
||||
*pzErr = sqlite3_mprintf("malformed columnsize=... directive");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pConfig->bColumnsize = (zArg[0]=='1');
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
*pzErr = sqlite3_mprintf("unrecognized option: \"%.*s\"", nCmd, zCmd);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
@ -477,6 +481,7 @@ int sqlite3Fts5ConfigParse(
|
||||
pRet->abUnindexed = (u8*)&pRet->azCol[nArg];
|
||||
pRet->zDb = sqlite3Fts5Strndup(&rc, azArg[1], -1);
|
||||
pRet->zName = sqlite3Fts5Strndup(&rc, azArg[2], -1);
|
||||
pRet->bColumnsize = 1;
|
||||
if( rc==SQLITE_OK && sqlite3_stricmp(pRet->zName, FTS5_RANK_NAME)==0 ){
|
||||
*pzErr = sqlite3_mprintf("reserved fts5 table name: %s", pRet->zName);
|
||||
rc = SQLITE_ERROR;
|
||||
@ -530,15 +535,24 @@ int sqlite3Fts5ConfigParse(
|
||||
}
|
||||
|
||||
/* If no zContent option was specified, fill in the default values. */
|
||||
if( rc==SQLITE_OK && pRet->eContent==FTS5_CONTENT_NORMAL ){
|
||||
pRet->zContent = sqlite3_mprintf("%Q.'%q_content'", pRet->zDb, pRet->zName);
|
||||
if( pRet->zContent==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
sqlite3_free(pRet->zContentRowid);
|
||||
pRet->zContentRowid = 0;
|
||||
if( rc==SQLITE_OK && pRet->zContent==0 ){
|
||||
const char *zTail = 0;
|
||||
assert( pRet->eContent==FTS5_CONTENT_NORMAL
|
||||
|| pRet->eContent==FTS5_CONTENT_NONE
|
||||
);
|
||||
if( pRet->eContent==FTS5_CONTENT_NORMAL ){
|
||||
zTail = "content";
|
||||
}else if( pRet->bColumnsize ){
|
||||
zTail = "docsize";
|
||||
}
|
||||
|
||||
if( zTail ){
|
||||
pRet->zContent = sqlite3Fts5Mprintf(
|
||||
&rc, "%Q.'%q_%s'", pRet->zDb, pRet->zName, zTail
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK && pRet->zContentRowid==0 ){
|
||||
pRet->zContentRowid = sqlite3Fts5Strndup(&rc, "rowid", -1);
|
||||
}
|
||||
|
@ -39,15 +39,11 @@ struct Fts5Storage {
|
||||
|
||||
#define FTS5_STMT_INSERT_CONTENT 3
|
||||
#define FTS5_STMT_REPLACE_CONTENT 4
|
||||
|
||||
#define FTS5_STMT_DELETE_CONTENT 5
|
||||
#define FTS5_STMT_REPLACE_DOCSIZE 6
|
||||
#define FTS5_STMT_DELETE_DOCSIZE 7
|
||||
|
||||
#define FTS5_STMT_LOOKUP_DOCSIZE 8
|
||||
|
||||
#define FTS5_STMT_REPLACE_CONFIG 9
|
||||
|
||||
#define FTS5_STMT_SCAN 10
|
||||
|
||||
/*
|
||||
@ -64,6 +60,14 @@ static int fts5StorageGetStmt(
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
/* If there is no %_docsize table, there should be no requests for
|
||||
** statements to operate on it. */
|
||||
assert( p->pConfig->bColumnsize || (
|
||||
eStmt!=FTS5_STMT_REPLACE_DOCSIZE
|
||||
&& eStmt!=FTS5_STMT_DELETE_DOCSIZE
|
||||
&& eStmt!=FTS5_STMT_LOOKUP_DOCSIZE
|
||||
));
|
||||
|
||||
assert( eStmt>=0 && eStmt<ArraySize(p->aStmt) );
|
||||
if( p->aStmt[eStmt]==0 ){
|
||||
const char *azStmt[] = {
|
||||
@ -175,12 +179,16 @@ static int fts5ExecPrintf(
|
||||
int sqlite3Fts5DropAll(Fts5Config *pConfig){
|
||||
int rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DROP TABLE IF EXISTS %Q.'%q_data';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_docsize';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_config';",
|
||||
pConfig->zDb, pConfig->zName,
|
||||
pConfig->zDb, pConfig->zName,
|
||||
pConfig->zDb, pConfig->zName
|
||||
);
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DROP TABLE IF EXISTS %Q.'%q_docsize';",
|
||||
pConfig->zDb, pConfig->zName
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK && pConfig->eContent==FTS5_CONTENT_NORMAL ){
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DROP TABLE IF EXISTS %Q.'%q_content';",
|
||||
@ -266,7 +274,7 @@ int sqlite3Fts5StorageOpen(
|
||||
sqlite3_free(zDefn);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
rc = sqlite3Fts5CreateTable(
|
||||
pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr
|
||||
);
|
||||
@ -374,19 +382,25 @@ static int fts5StorageDeleteFromIndex(Fts5Storage *p, i64 iDel){
|
||||
** Insert a record into the %_docsize table. Specifically, do:
|
||||
**
|
||||
** INSERT OR REPLACE INTO %_docsize(id, sz) VALUES(iRowid, pBuf);
|
||||
**
|
||||
** If there is no %_docsize table (as happens if the columnsize=0 option
|
||||
** is specified when the FTS5 table is created), this function is a no-op.
|
||||
*/
|
||||
static int fts5StorageInsertDocsize(
|
||||
Fts5Storage *p, /* Storage module to write to */
|
||||
i64 iRowid, /* id value */
|
||||
Fts5Buffer *pBuf /* sz value */
|
||||
){
|
||||
sqlite3_stmt *pReplace = 0;
|
||||
int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pReplace, 1, iRowid);
|
||||
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
int rc = SQLITE_OK;
|
||||
if( p->pConfig->bColumnsize ){
|
||||
sqlite3_stmt *pReplace = 0;
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pReplace, 1, iRowid);
|
||||
sqlite3_bind_blob(pReplace, 2, pBuf->p, pBuf->n, SQLITE_STATIC);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -455,6 +469,7 @@ static int fts5StorageSaveTotals(Fts5Storage *p){
|
||||
** Remove a row from the FTS table.
|
||||
*/
|
||||
int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
int rc;
|
||||
sqlite3_stmt *pDel;
|
||||
|
||||
@ -466,7 +481,7 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
|
||||
}
|
||||
|
||||
/* Delete the %_docsize record */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
@ -528,13 +543,15 @@ int sqlite3Fts5StorageSpecialDelete(
|
||||
}
|
||||
|
||||
/* Delete the %_docsize record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pDel, 1, iDel);
|
||||
sqlite3_step(pDel);
|
||||
rc = sqlite3_reset(pDel);
|
||||
if( pConfig->bColumnsize ){
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pDel, 1, iDel);
|
||||
sqlite3_step(pDel);
|
||||
rc = sqlite3_reset(pDel);
|
||||
}
|
||||
}
|
||||
|
||||
/* Write the averages record */
|
||||
@ -554,11 +571,15 @@ int sqlite3Fts5StorageDeleteAll(Fts5Storage *p){
|
||||
|
||||
/* Delete the contents of the %_data and %_docsize tables. */
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DELETE FROM %Q.'%q_data';"
|
||||
"DELETE FROM %Q.'%q_docsize';",
|
||||
pConfig->zDb, pConfig->zName,
|
||||
"DELETE FROM %Q.'%q_data';",
|
||||
pConfig->zDb, pConfig->zName
|
||||
);
|
||||
if( rc==SQLITE_OK && pConfig->bColumnsize ){
|
||||
rc = fts5ExecPrintf(pConfig->db, 0,
|
||||
"DELETE FROM %Q.'%q_docsize';",
|
||||
pConfig->zDb, pConfig->zName
|
||||
);
|
||||
}
|
||||
|
||||
/* Reinitialize the %_data table. This call creates the initial structure
|
||||
** and averages records. */
|
||||
@ -635,18 +656,24 @@ int sqlite3Fts5StorageMerge(Fts5Storage *p, int nMerge){
|
||||
** a NULL value is inserted into the rowid column. The new rowid is allocated
|
||||
** by inserting a dummy row into the %_docsize table. The dummy will be
|
||||
** overwritten later.
|
||||
**
|
||||
** If the %_docsize table does not exist, SQLITE_MISMATCH is returned. In
|
||||
** this case the user is required to provide a rowid explicitly.
|
||||
*/
|
||||
static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
|
||||
sqlite3_stmt *pReplace = 0;
|
||||
int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_null(pReplace, 1);
|
||||
sqlite3_bind_null(pReplace, 2);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
*piRowid = sqlite3_last_insert_rowid(p->pConfig->db);
|
||||
int rc = SQLITE_MISMATCH;
|
||||
if( p->pConfig->bColumnsize ){
|
||||
sqlite3_stmt *pReplace = 0;
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_null(pReplace, 1);
|
||||
sqlite3_bind_null(pReplace, 2);
|
||||
sqlite3_step(pReplace);
|
||||
rc = sqlite3_reset(pReplace);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
*piRowid = sqlite3_last_insert_rowid(p->pConfig->db);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
@ -958,6 +985,7 @@ int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
|
||||
rc = FTS5_CORRUPT;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
@ -148,7 +148,7 @@ do_execsql_test 5.2 {
|
||||
1 {4 6}
|
||||
}
|
||||
|
||||
do_execsql_test 5.2 {
|
||||
do_execsql_test 5.3 {
|
||||
SELECT rowid, fts5_test_columntext(t5) FROM t5 WHERE t5 MATCH 'a'
|
||||
ORDER BY rowid DESC;
|
||||
} {
|
||||
@ -157,7 +157,7 @@ do_execsql_test 5.2 {
|
||||
1 {{a b c d} {e f g h i j}}
|
||||
}
|
||||
|
||||
do_execsql_test 5.3 {
|
||||
do_execsql_test 5.4 {
|
||||
SELECT rowid, fts5_test_columntotalsize(t5) FROM t5 WHERE t5 MATCH 'a'
|
||||
ORDER BY rowid DESC;
|
||||
} {
|
||||
@ -166,7 +166,7 @@ do_execsql_test 5.3 {
|
||||
1 {5 7}
|
||||
}
|
||||
|
||||
do_execsql_test 5.4 {
|
||||
do_execsql_test 5.5 {
|
||||
INSERT INTO t5 VALUES('x y z', 'v w x y z');
|
||||
SELECT rowid, fts5_test_columntotalsize(t5) FROM t5 WHERE t5 MATCH 'a'
|
||||
ORDER BY rowid DESC;
|
||||
|
112
ext/fts5/test/fts5columnsize.test
Normal file
112
ext/fts5/test/fts5columnsize.test
Normal file
@ -0,0 +1,112 @@
|
||||
# 2015 Jun 10
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
# Tests focusing on fts5 tables with the columnsize=0 option.
|
||||
#
|
||||
|
||||
source [file join [file dirname [info script]] fts5_common.tcl]
|
||||
set testprefix fts5columnsize
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Check that the option can be parsed and that the %_docsize table is
|
||||
# only created if it is set to true.
|
||||
#
|
||||
foreach {tn outcome stmt} {
|
||||
1 0 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=0) }
|
||||
2 1 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=1) }
|
||||
3 0 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize='0') }
|
||||
4 1 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize='1') }
|
||||
5 2 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize='') }
|
||||
6 2 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=2) }
|
||||
7 1 { CREATE VIRTUAL TABLE t1 USING fts5(x, columnsize=0, columnsize=1) }
|
||||
8 1 { CREATE VIRTUAL TABLE t1 USING fts5(x) }
|
||||
} {
|
||||
execsql {
|
||||
DROP TABLE IF EXISTS t1;
|
||||
}
|
||||
if {$outcome==2} {
|
||||
do_catchsql_test 1.$tn.1 $stmt {1 {malformed columnsize=... directive}}
|
||||
} else {
|
||||
do_execsql_test 1.$tn.2 $stmt
|
||||
do_execsql_test 1.$tn.3 {
|
||||
SELECT count(*) FROM sqlite_master WHERE name = 't1_docsize'
|
||||
} $outcome
|
||||
}
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Run tests on a table with no %_content or %_docsize backing store.
|
||||
#
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE t2 USING fts5(x, columnsize=0, content='');
|
||||
}
|
||||
do_catchsql_test 2.1 {
|
||||
INSERT INTO t2 VALUES('a b c d e f');
|
||||
} {1 {datatype mismatch}}
|
||||
do_execsql_test 2.2 {
|
||||
INSERT INTO t2(rowid, x) VALUES(1, 'c d e f');
|
||||
INSERT INTO t2(rowid, x) VALUES(2, 'c d e f g h');
|
||||
INSERT INTO t2(rowid, x) VALUES(3, 'a b c d e f g h');
|
||||
} {}
|
||||
do_execsql_test 2.3 {
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'b'; SELECT '::';
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'e'; SELECT '::';
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'h';
|
||||
} {3 :: 1 2 3 :: 2 3}
|
||||
do_execsql_test 2.4 {
|
||||
INSERT INTO t2(t2, rowid, x) VALUES('delete', 2, 'c d e f g h');
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'b'; SELECT '::';
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'e'; SELECT '::';
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'h';
|
||||
} {3 :: 1 3 :: 3}
|
||||
do_execsql_test 2.5 {
|
||||
INSERT INTO t2(t2) VALUES('delete-all');
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'b'; SELECT '::';
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'e'; SELECT '::';
|
||||
SELECT rowid FROM t2 WHERE t2 MATCH 'h';
|
||||
} {:: ::}
|
||||
do_execsql_test 2.6 {
|
||||
INSERT INTO t2(rowid, x) VALUES(1, 'o t t f');
|
||||
INSERT INTO t2(rowid, x) VALUES(2, 'f s s e');
|
||||
INSERT INTO t2(rowid, x) VALUES(3, 'n t e t');
|
||||
}
|
||||
|
||||
do_catchsql_test 2.7.1 {
|
||||
SELECT rowid FROM t2
|
||||
} {1 {t2: table does not support scanning}}
|
||||
do_catchsql_test 2.7.2 {
|
||||
SELECT rowid FROM t2 WHERE rowid=2
|
||||
} {1 {t2: table does not support scanning}}
|
||||
do_catchsql_test 2.7.3 {
|
||||
SELECT rowid FROM t2 WHERE rowid BETWEEN 1 AND 3
|
||||
} {1 {t2: table does not support scanning}}
|
||||
|
||||
do_execsql_test 2.X {
|
||||
DROP TABLE t2
|
||||
}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Test the xColumnSize() API
|
||||
#
|
||||
fts5_aux_test_functions db
|
||||
|
||||
do_execsql_test 3.0 {
|
||||
CREATE VIRTUAL TABLE t3 USING fts5(x, y UNINDEXED, z, columnsize=0);
|
||||
INSERT INTO t3 VALUES('a a', 'b b b', 'c');
|
||||
INSERT INTO t3 VALUES('x a x', 'b b b y', '');
|
||||
}
|
||||
do_execsql_test 3.1 {
|
||||
SELECT rowid, fts5_test_columnsize(t3) FROM t3 WHERE t3 MATCH 'a'
|
||||
} {
|
||||
1 {2 0 1} 2 {3 0 0}
|
||||
}
|
||||
|
||||
finish_test
|
23
manifest
23
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sa\scomment\sin\sfts5.h.
|
||||
D 2015-06-06T19:23:32.945
|
||||
C Add\sthe\s"columnsize="\soption\sto\sfts5,\ssimilar\sto\sfts4's\s"matchinfo=fts3".
|
||||
D 2015-06-09T20:58:39.182
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in d272f8755b464f20e02dd7799bfe16794c9574c4
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -105,16 +105,16 @@ F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl ed0534dd51efce39878bce33944c6073d37a1e20
|
||||
F ext/fts3/unicode/parseunicode.tcl da577d1384810fb4e2b209bf3313074353193e95
|
||||
F ext/fts5/extract_api_docs.tcl 55a6d648d516f35d9a1e580ac00de27154e1904a
|
||||
F ext/fts5/fts5.c 1c7424b9ba39f1e244f776556a4fface71abe772
|
||||
F ext/fts5/fts5.c 8af8014b40c382a987998a27f72490b339ce3726
|
||||
F ext/fts5/fts5.h 81d1a92fc2b4bd477af7e4e0b38b456f3e199fba
|
||||
F ext/fts5/fts5Int.h 3de83c9639bd8332eb84a13c1eb2387e83e128bf
|
||||
F ext/fts5/fts5Int.h a6d1c30e1655bd91484cb98661581e35a130b87b
|
||||
F ext/fts5/fts5_aux.c d53f00f31ad615ca4f139dd8751f9041afa00971
|
||||
F ext/fts5/fts5_buffer.c 9ec57c75c81e81dca118568876b1caead0aadadf
|
||||
F ext/fts5/fts5_config.c 11f969ed711a0a8b611d47431d74c372ad78c713
|
||||
F ext/fts5/fts5_buffer.c be0dc80a9406151b350be27c7ec2956722578771
|
||||
F ext/fts5/fts5_config.c 6ae691e36f90185896f4db0a819ae2394f880ca1
|
||||
F ext/fts5/fts5_expr.c 549bda1f7edcf10365fbfbc002bdea1be3c287bb
|
||||
F ext/fts5/fts5_hash.c c1cfdb2cae0fad00b06fae38a40eaf9261563ccc
|
||||
F ext/fts5/fts5_index.c 7cea402924cd3d8cd5943a7f9514c9153696571b
|
||||
F ext/fts5/fts5_storage.c 770ab52377c18a9aa4dc843ee79388febdb184d4
|
||||
F ext/fts5/fts5_storage.c 684ef9575dd1709c3faacbfd1765e623fb1d0505
|
||||
F ext/fts5/fts5_tcl.c 7ea165878e4ae3598e89acd470a0ee1b5a00e33c
|
||||
F ext/fts5/fts5_tokenize.c 97251d68d7a6a9415bde1203f9382864dfc1f989
|
||||
F ext/fts5/fts5_unicode2.c da3cf712f05cd8347c8c5bc00964cc0361c88da9
|
||||
@ -127,7 +127,7 @@ F ext/fts5/test/fts5aa.test 0be21c89fd66b588db355a6398911fd875bdcc6c
|
||||
F ext/fts5/test/fts5ab.test 6fe3a56731d15978afbb74ae51b355fc9310f2ad
|
||||
F ext/fts5/test/fts5ac.test 0990ae7497ebaea2ab5f7fd5caedd93a71a905fc
|
||||
F ext/fts5/test/fts5ad.test 312f3c8ed9592533499c5b94d2059ae6382913a0
|
||||
F ext/fts5/test/fts5ae.test 9175201baf8c885fc1cbb2da11a0c61fd11224db
|
||||
F ext/fts5/test/fts5ae.test ddc558e3e3b52db0101f7541b2e3849b77052c92
|
||||
F ext/fts5/test/fts5af.test c2501ec2b61d6b179c305f5d2b8782ab3d4f832a
|
||||
F ext/fts5/test/fts5ag.test ec3e119b728196620a31507ef503c455a7a73505
|
||||
F ext/fts5/test/fts5ah.test b9e78fa986a7bd564ebadfb244de02c84d7ac3ae
|
||||
@ -139,6 +139,7 @@ F ext/fts5/test/fts5auto.test caa5bcf917db11944655a2a9bd38c67c520376ca
|
||||
F ext/fts5/test/fts5aux.test e5631607bbc05ac1c38cf7d691000509aca71ef3
|
||||
F ext/fts5/test/fts5auxdata.test c69b86092bf1a157172de5f9169731af3403179b
|
||||
F ext/fts5/test/fts5bigpl.test b1cfd00561350ab04994ba7dd9d48468e5e0ec3b
|
||||
F ext/fts5/test/fts5columnsize.test c7333cf079022c1ad25d04538b8f279fad4c2f8d
|
||||
F ext/fts5/test/fts5config.test c9cc535f3b36cde1e5a32bf579f3f5962a9e82b2
|
||||
F ext/fts5/test/fts5content.test e46904decd896e38c848ad4f38fa4e80251a028b
|
||||
F ext/fts5/test/fts5corrupt.test 35bfdbbb3cdcea46ae7385f6432e9b5c574e70a1
|
||||
@ -1357,7 +1358,7 @@ F tool/vdbe_profile.tcl 67746953071a9f8f2f668b73fe899074e2c6d8c1
|
||||
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
|
||||
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 3a9cb648138a059862fb438c0787fdd888f5e88e
|
||||
R 01f96e31f05863ae01feddea5f82854e
|
||||
P e964b5877497b16cf985d3d847e82529bb3fa4a3
|
||||
R 26fe69b53869c7d4cebecf3b1c47f607
|
||||
U dan
|
||||
Z 479453162469a9d47c2a3d0d93cd23e2
|
||||
Z 7aaa26406a2384f1f8538b962eb28bef
|
||||
|
@ -1 +1 @@
|
||||
e964b5877497b16cf985d3d847e82529bb3fa4a3
|
||||
aa12f9d9b79c2f523fd6b00e47bcb66dba09ce0c
|
Loading…
x
Reference in New Issue
Block a user