Add support for external content tables to fts5.
FossilOrigin-Name: 17ef5b59f789e9fa35c4f053246d819987fd06f8
This commit is contained in:
parent
ade921c3ad
commit
0fbc269fef
@ -1056,6 +1056,20 @@ static int fts5SpecialInsert(
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int fts5SpecialDelete(
|
||||
Fts5Table *pTab,
|
||||
sqlite3_value **apVal,
|
||||
sqlite3_int64 *piRowid
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
int eType1 = sqlite3_value_type(apVal[1]);
|
||||
if( eType1==SQLITE_INTEGER ){
|
||||
sqlite3_int64 iDel = sqlite3_value_int64(apVal[1]);
|
||||
rc = sqlite3Fts5StorageSpecialDelete(pTab->pStorage, iDel, &apVal[2]);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** This function is the implementation of the xUpdate callback used by
|
||||
** FTS3 virtual tables. It is invoked by SQLite each time a row is to be
|
||||
@ -1086,17 +1100,25 @@ static int fts5UpdateMethod(
|
||||
*/
|
||||
assert( nArg==1 || nArg==(2 + pConfig->nCol + 2) );
|
||||
|
||||
if( nArg>1 && SQLITE_NULL!=sqlite3_value_type(apVal[2 + pConfig->nCol]) ){
|
||||
return fts5SpecialInsert(pTab,
|
||||
apVal[2 + pConfig->nCol], apVal[2 + pConfig->nCol + 1]
|
||||
);
|
||||
if( nArg>1 ){
|
||||
sqlite3_value *pCmd = sqlite3_value_type(apVal[2 + pConfig->nCol]);
|
||||
if( SQLITE_NULL!=sqlite3_value_type(pCmd) ){
|
||||
const char *z = sqlite3_value_text(pCmd);
|
||||
if( pConfig->bExternalContent && sqlite3_stricmp("delete", z) ){
|
||||
return fts5SpecialDelete(pTab, apVal, pRowid);
|
||||
}else{
|
||||
return fts5SpecialInsert(pTab, pCmd, apVal[2 + pConfig->nCol + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
eType0 = sqlite3_value_type(apVal[0]);
|
||||
eConflict = sqlite3_vtab_on_conflict(pConfig->db);
|
||||
|
||||
assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
|
||||
if( eType0==SQLITE_INTEGER ){
|
||||
assert( pVtab->zErrMsg==0 );
|
||||
|
||||
if( rc==SQLITE_OK && eType0==SQLITE_INTEGER ){
|
||||
i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
|
||||
rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel);
|
||||
}
|
||||
|
@ -76,6 +76,9 @@ struct Fts5Config {
|
||||
char **azCol; /* Column names */
|
||||
int nPrefix; /* Number of prefix indexes */
|
||||
int *aPrefix; /* Sizes in bytes of nPrefix prefix indexes */
|
||||
int bExternalContent; /* Content is external */
|
||||
char *zContent; /* "content=" option value (or NULL) */
|
||||
char *zContentRowid; /* "content_rowid=" option value (or NULL) */
|
||||
Fts5Tokenizer *pTok;
|
||||
fts5_tokenizer *pTokApi;
|
||||
|
||||
@ -410,6 +413,8 @@ int sqlite3Fts5StorageRollback(Fts5Storage *p);
|
||||
|
||||
int sqlite3Fts5StorageConfigValue(Fts5Storage *p, const char*, sqlite3_value*);
|
||||
|
||||
int sqlite3Fts5StorageSpecialDelete(Fts5Storage *p, i64 iDel, sqlite3_value**);
|
||||
|
||||
/*
|
||||
** End of interface to code in fts5_storage.c.
|
||||
**************************************************************************/
|
||||
|
@ -192,6 +192,47 @@ static char *fts5TrimString(char *z){
|
||||
return z;
|
||||
}
|
||||
|
||||
/*
|
||||
** Duplicate the string passed as the only argument into a buffer allocated
|
||||
** by sqlite3_malloc().
|
||||
**
|
||||
** Return 0 if an OOM error is encountered.
|
||||
*/
|
||||
static char *fts5Strdup(int *pRc, const char *z){
|
||||
char *pRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
pRet = sqlite3_mprintf("%s", z);
|
||||
if( pRet==0 ) *pRc = SQLITE_NOMEM;
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument z points to a nul-terminated string containing an SQL identifier.
|
||||
** This function returns a copy of the identifier enclosed in backtick
|
||||
** quotes.
|
||||
*/
|
||||
static char *fts5EscapeName(int *pRc, const char *z){
|
||||
char *pRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
int n = strlen(z);
|
||||
pRet = (char*)sqlite3_malloc(2 * 2*n + 1);
|
||||
if( pRet==0 ){
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int i;
|
||||
char *p = pRet;
|
||||
for(i=0; i<n; i++){
|
||||
if( z[i]=='`' ) *p++ = '`';
|
||||
*p++ = z[i];
|
||||
}
|
||||
*p++ = '`';
|
||||
*p++ = '\0';
|
||||
}
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Parse the "special" CREATE VIRTUAL TABLE directive and update
|
||||
** configuration object pConfig as appropriate.
|
||||
@ -291,25 +332,34 @@ static int fts5ConfigParseSpecial(
|
||||
return rc;
|
||||
}
|
||||
|
||||
if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
|
||||
int rc = SQLITE_OK;
|
||||
if( pConfig->zContent ){
|
||||
*pzErr = sqlite3_mprintf("multiple content=... directives");
|
||||
rc = SQLITE_ERROR;
|
||||
}else{
|
||||
pConfig->zContent = sqlite3_mprintf("%Q.%Q", pConfig->zDb, zArg);
|
||||
pConfig->bExternalContent = 1;
|
||||
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;
|
||||
}else{
|
||||
pConfig->zContentRowid = fts5EscapeName(&rc, zArg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
*pzErr = sqlite3_mprintf("unrecognized directive: \"%s\"", zCmd);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
/*
|
||||
** Duplicate the string passed as the only argument into a buffer allocated
|
||||
** by sqlite3_malloc().
|
||||
**
|
||||
** Return 0 if an OOM error is encountered.
|
||||
*/
|
||||
static char *fts5Strdup(int *pRc, const char *z){
|
||||
char *pRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
pRet = sqlite3_mprintf("%s", z);
|
||||
if( pRet==0 ) *pRc = SQLITE_NOMEM;
|
||||
}
|
||||
return pRet;
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate an instance of the default tokenizer ("simple") at
|
||||
** Fts5Config.pTokenizer. Return SQLITE_OK if successful, or an SQLite error
|
||||
@ -422,6 +472,20 @@ int sqlite3Fts5ConfigParse(
|
||||
rc = fts5ConfigDefaultTokenizer(pGlobal, pRet);
|
||||
}
|
||||
|
||||
/* If no zContent option was specified, fill in the default values. */
|
||||
if( rc==SQLITE_OK && pRet->zContent==0 ){
|
||||
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->zContentRowid==0 ){
|
||||
pRet->zContentRowid = fts5Strdup(&rc, "rowid");
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3Fts5ConfigFree(pRet);
|
||||
*ppOut = 0;
|
||||
@ -447,6 +511,8 @@ void sqlite3Fts5ConfigFree(Fts5Config *pConfig){
|
||||
sqlite3_free(pConfig->aPrefix);
|
||||
sqlite3_free(pConfig->zRank);
|
||||
sqlite3_free(pConfig->zRankArgs);
|
||||
sqlite3_free(pConfig->zContent);
|
||||
sqlite3_free(pConfig->zContentRowid);
|
||||
sqlite3_free(pConfig);
|
||||
}
|
||||
}
|
||||
|
@ -1041,19 +1041,24 @@ i64 sqlite3Fts5ExprRowid(Fts5Expr *p){
|
||||
** It is the responsibility of the caller to eventually free the returned
|
||||
** buffer using sqlite3_free(). If an OOM error occurs, NULL is returned.
|
||||
*/
|
||||
static char *fts5Strndup(const char *pIn, int nIn){
|
||||
char *zRet = (char*)sqlite3_malloc(nIn+1);
|
||||
if( zRet ){
|
||||
memcpy(zRet, pIn, nIn);
|
||||
zRet[nIn] = '\0';
|
||||
static char *fts5Strndup(int *pRc, const char *pIn, int nIn){
|
||||
char *zRet = 0;
|
||||
if( *pRc==SQLITE_OK ){
|
||||
zRet = (char*)sqlite3_malloc(nIn+1);
|
||||
if( zRet ){
|
||||
memcpy(zRet, pIn, nIn);
|
||||
zRet[nIn] = '\0';
|
||||
}else{
|
||||
*pRc = SQLITE_NOMEM;
|
||||
}
|
||||
}
|
||||
return zRet;
|
||||
}
|
||||
|
||||
static int fts5ParseStringFromToken(Fts5Token *pToken, char **pz){
|
||||
*pz = fts5Strndup(pToken->p, pToken->n);
|
||||
if( *pz==0 ) return SQLITE_NOMEM;
|
||||
return SQLITE_OK;
|
||||
int rc = SQLITE_OK;
|
||||
*pz = fts5Strndup(&rc, pToken->p, pToken->n);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1139,6 +1144,7 @@ static int fts5ParseTokenize(
|
||||
int iEnd, /* End offset of token */
|
||||
int iPos /* Position offset of token */
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
const int SZALLOC = 8;
|
||||
TokenCtx *pCtx = (TokenCtx*)pContext;
|
||||
Fts5ExprPhrase *pPhrase = pCtx->pPhrase;
|
||||
@ -1159,9 +1165,9 @@ static int fts5ParseTokenize(
|
||||
|
||||
pTerm = &pPhrase->aTerm[pPhrase->nTerm++];
|
||||
memset(pTerm, 0, sizeof(Fts5ExprTerm));
|
||||
pTerm->zTerm = fts5Strndup(pToken, nToken);
|
||||
pTerm->zTerm = fts5Strndup(&rc, pToken, nToken);
|
||||
|
||||
return pTerm->zTerm ? SQLITE_OK : SQLITE_NOMEM;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
|
@ -61,9 +61,9 @@ static int fts5StorageGetStmt(
|
||||
assert( eStmt>=0 && eStmt<ArraySize(p->aStmt) );
|
||||
if( p->aStmt[eStmt]==0 ){
|
||||
const char *azStmt[] = {
|
||||
"SELECT * FROM %Q.'%q_content' ORDER BY id ASC", /* SCAN_ASC */
|
||||
"SELECT * FROM %Q.'%q_content' ORDER BY id DESC", /* SCAN_DESC */
|
||||
"SELECT * FROM %Q.'%q_content' WHERE rowid=?", /* LOOKUP */
|
||||
"SELECT * FROM %s ORDER BY id ASC", /* SCAN_ASC */
|
||||
"SELECT * FROM %s ORDER BY id DESC", /* SCAN_DESC */
|
||||
"SELECT * FROM %s WHERE %s=?", /* LOOKUP */
|
||||
|
||||
"INSERT INTO %Q.'%q_content' VALUES(%s)", /* INSERT_CONTENT */
|
||||
"REPLACE INTO %Q.'%q_content' VALUES(%s)", /* REPLACE_CONTENT */
|
||||
@ -75,32 +75,47 @@ static int fts5StorageGetStmt(
|
||||
|
||||
"REPLACE INTO %Q.'%q_config' VALUES(?,?)", /* REPLACE_CONFIG */
|
||||
};
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
Fts5Config *pC = p->pConfig;
|
||||
char *zSql = 0;
|
||||
|
||||
if( eStmt==FTS5_STMT_INSERT_CONTENT || eStmt==FTS5_STMT_REPLACE_CONTENT ){
|
||||
int nCol = pConfig->nCol + 1;
|
||||
char *zBind;
|
||||
int i;
|
||||
switch( eStmt ){
|
||||
case FTS5_STMT_SCAN_ASC:
|
||||
case FTS5_STMT_SCAN_DESC:
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContent);
|
||||
break;
|
||||
|
||||
zBind = sqlite3_malloc(1 + nCol*2);
|
||||
if( zBind ){
|
||||
for(i=0; i<nCol; i++){
|
||||
zBind[i*2] = '?';
|
||||
zBind[i*2 + 1] = ',';
|
||||
case FTS5_STMT_LOOKUP:
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zContent, pC->zContentRowid);
|
||||
break;
|
||||
|
||||
case FTS5_STMT_INSERT_CONTENT:
|
||||
case FTS5_STMT_REPLACE_CONTENT: {
|
||||
int nCol = pC->nCol + 1;
|
||||
char *zBind;
|
||||
int i;
|
||||
|
||||
zBind = sqlite3_malloc(1 + nCol*2);
|
||||
if( zBind ){
|
||||
for(i=0; i<nCol; i++){
|
||||
zBind[i*2] = '?';
|
||||
zBind[i*2 + 1] = ',';
|
||||
}
|
||||
zBind[i*2-1] = '\0';
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName, zBind);
|
||||
sqlite3_free(zBind);
|
||||
}
|
||||
zBind[i*2-1] = '\0';
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt],pConfig->zDb,pConfig->zName,zBind);
|
||||
sqlite3_free(zBind);
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pConfig->zDb, pConfig->zName);
|
||||
|
||||
default:
|
||||
zSql = sqlite3_mprintf(azStmt[eStmt], pC->zDb, pC->zName);
|
||||
break;
|
||||
}
|
||||
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_prepare_v2(pConfig->db, zSql, -1, &p->aStmt[eStmt], 0);
|
||||
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
@ -190,18 +205,21 @@ int sqlite3Fts5StorageOpen(
|
||||
p->pIndex = pIndex;
|
||||
|
||||
if( bCreate ){
|
||||
int i;
|
||||
char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
|
||||
if( zDefn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int iOff = sprintf(zDefn, "id INTEGER PRIMARY KEY");
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
iOff += sprintf(&zDefn[iOff], ", c%d", i);
|
||||
if( pConfig->bExternalContent==0 ){
|
||||
char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
|
||||
if( zDefn==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
int i;
|
||||
int iOff = sprintf(zDefn, "id INTEGER PRIMARY KEY");
|
||||
for(i=0; i<pConfig->nCol; i++){
|
||||
iOff += sprintf(&zDefn[iOff], ", c%d", i);
|
||||
}
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
}
|
||||
rc = sqlite3Fts5CreateTable(pConfig, "content", zDefn, 0, pzErr);
|
||||
sqlite3_free(zDefn);
|
||||
}
|
||||
sqlite3_free(zDefn);
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3Fts5CreateTable(
|
||||
pConfig, "docsize", "id INTEGER PRIMARY KEY, sz BLOB", 0, pzErr
|
||||
@ -432,6 +450,78 @@ int sqlite3Fts5StorageDelete(Fts5Storage *p, i64 iDel){
|
||||
return rc;
|
||||
}
|
||||
|
||||
int sqlite3Fts5StorageSpecialDelete(
|
||||
Fts5Storage *p,
|
||||
i64 iDel,
|
||||
sqlite3_value **apVal
|
||||
){
|
||||
Fts5Config *pConfig = p->pConfig;
|
||||
int rc;
|
||||
sqlite3_stmt *pDel;
|
||||
|
||||
assert( p->pConfig->bExternalContent );
|
||||
rc = fts5StorageLoadTotals(p, 1);
|
||||
|
||||
/* Delete the index records */
|
||||
if( rc==SQLITE_OK ){
|
||||
int iCol;
|
||||
Fts5InsertCtx ctx;
|
||||
ctx.pStorage = p;
|
||||
ctx.iCol = -1;
|
||||
|
||||
rc = sqlite3Fts5IndexBeginWrite(p->pIndex, iDel);
|
||||
for(iCol=0; rc==SQLITE_OK && iCol<pConfig->nCol; iCol++){
|
||||
rc = sqlite3Fts5Tokenize(pConfig,
|
||||
(const char*)sqlite3_value_text(apVal[iCol]),
|
||||
sqlite3_value_bytes(apVal[iCol]),
|
||||
(void*)&ctx,
|
||||
fts5StorageInsertCallback
|
||||
);
|
||||
p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
|
||||
}
|
||||
p->nTotalRow--;
|
||||
}
|
||||
|
||||
/* Delete the %_docsize record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_int64(pDel, 1, iDel);
|
||||
sqlite3_step(pDel);
|
||||
rc = sqlite3_reset(pDel);
|
||||
}
|
||||
|
||||
/* Write the averages record */
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageSaveTotals(p);
|
||||
}
|
||||
|
||||
return rc;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
** Allocate a new rowid. This is used for "external content" tables when
|
||||
** 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.
|
||||
*/
|
||||
static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
|
||||
sqlite3_stmt *pReplace = 0;
|
||||
int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
** Insert a new row into the FTS table.
|
||||
*/
|
||||
@ -453,27 +543,35 @@ int sqlite3Fts5StorageInsert(
|
||||
rc = fts5StorageLoadTotals(p, 1);
|
||||
|
||||
/* Insert the new row into the %_content table. */
|
||||
if( rc==SQLITE_OK ){
|
||||
if( eConflict==SQLITE_REPLACE ){
|
||||
eStmt = FTS5_STMT_REPLACE_CONTENT;
|
||||
if( rc==SQLITE_OK && pConfig->bExternalContent==0 ){
|
||||
if( pConfig->bExternalContent ){
|
||||
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
|
||||
rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
|
||||
*piRowid = sqlite3_value_int64(apVal[1]);
|
||||
}else{
|
||||
rc = fts5StorageNewRowid(p, piRowid);
|
||||
}
|
||||
}else{
|
||||
eStmt = FTS5_STMT_INSERT_CONTENT;
|
||||
if( eConflict==SQLITE_REPLACE ){
|
||||
eStmt = FTS5_STMT_REPLACE_CONTENT;
|
||||
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
|
||||
rc = fts5StorageDeleteFromIndex(p, sqlite3_value_int64(apVal[1]));
|
||||
}
|
||||
}else{
|
||||
eStmt = FTS5_STMT_INSERT_CONTENT;
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, eStmt, &pInsert);
|
||||
}
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
rc = sqlite3_bind_value(pInsert, i, apVal[i]);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
rc = sqlite3_reset(pInsert);
|
||||
}
|
||||
*piRowid = sqlite3_last_insert_rowid(pConfig->db);
|
||||
}
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = fts5StorageGetStmt(p, eStmt, &pInsert);
|
||||
}
|
||||
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
|
||||
rc = sqlite3_bind_value(pInsert, i, apVal[i]);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_step(pInsert);
|
||||
rc = sqlite3_reset(pInsert);
|
||||
}
|
||||
*piRowid = sqlite3_last_insert_rowid(pConfig->db);
|
||||
|
||||
/* Add new entries to the FTS index */
|
||||
if( rc==SQLITE_OK ){
|
||||
|
20
manifest
20
manifest
@ -1,5 +1,5 @@
|
||||
C Allow\sthe\srank\scolumn\sto\sbe\sremapped\son\sa\sper-query\sbasis\sby\sincluding\sa\sterm\ssimilar\sto\s"rank\smatch\s'bm25(10,2)'"\sin\sa\swhere\sclause.
|
||||
D 2015-01-02T14:55:22.175
|
||||
C Add\ssupport\sfor\sexternal\scontent\stables\sto\sfts5.
|
||||
D 2015-01-03T20:44:58.134
|
||||
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
|
||||
F Makefile.in 7cd23e4fc91004a6bd081623e1bc6932e44828c0
|
||||
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
|
||||
@ -104,16 +104,16 @@ F ext/fts3/unicode/CaseFolding.txt 8c678ca52ecc95e16bc7afc2dbf6fc9ffa05db8c
|
||||
F ext/fts3/unicode/UnicodeData.txt cd07314edb62d49fde34debdaf92fa2aa69011e7
|
||||
F ext/fts3/unicode/mkunicode.tcl 4199cb887040ee3c3cd59a5171ddb0566904586e
|
||||
F ext/fts5/extract_api_docs.tcl 6320db4a1d0722a4e2069e661381ad75e9889786
|
||||
F ext/fts5/fts5.c a80283dca24506f1c748fffbba8d87ae4d348b50
|
||||
F ext/fts5/fts5.c 16177d7f81af1852cf7f477b5ae119215ad6044a
|
||||
F ext/fts5/fts5.h 4f9d2c477c0ee1907164642471329a82cb6b203b
|
||||
F ext/fts5/fts5Int.h b5d7970b851d2b4f1745cd2d5c95216c9847aef2
|
||||
F ext/fts5/fts5Int.h 8062dc2363c863dc8a5b2e5651cb8c966bd6c4cb
|
||||
F ext/fts5/fts5_aux.c 445e54031ff94174673f4f5aac6c064df20a2a6b
|
||||
F ext/fts5/fts5_buffer.c 1bc5c762bb2e9b4a40b2e8a820a31b809e72eec1
|
||||
F ext/fts5/fts5_config.c 74a860e10c5583831f04d0088c4a49a3c6eca43d
|
||||
F ext/fts5/fts5_expr.c 27d3d2deebae277c34ae2bb3d501dd879c442ba5
|
||||
F ext/fts5/fts5_config.c 16d647c7bfe50d4e823267188e12e2d001d655e0
|
||||
F ext/fts5/fts5_expr.c 317093f00a2ccdaaee0a5290f9f228c600189c41
|
||||
F ext/fts5/fts5_hash.c 63fa8379c5f2ac107d47c2b7d9ac04c95ef8a279
|
||||
F ext/fts5/fts5_index.c 4a8e8535b4303400ddb5f6fb08152da0d88ebf6f
|
||||
F ext/fts5/fts5_storage.c 13794781977c9a624eb8bd7b9509de241e405853
|
||||
F ext/fts5/fts5_storage.c b95fcca70f94656854e7afcfbb9896455f6b034d
|
||||
F ext/fts5/fts5_tcl.c 664e710e2bbeed505cb91848772ca7538623a67f
|
||||
F ext/fts5/fts5_tokenize.c 5a0ad46408d09bcda2bf0addb5af42fdb75ebabb
|
||||
F ext/fts5/fts5_unicode2.c 9c7dd640d1f014bf5c3ee029759adfbb4d7e95a9
|
||||
@ -1270,7 +1270,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 4b3651677e7132c4c45605bc1f216fc08ef31198
|
||||
R 691df06fdaf9c3542bb10cf702e4a0f8
|
||||
P 1cd15a1759004d5d321056905dbb6acff20dc7d9
|
||||
R d21eb6bee3b06e51f22d32d1e0bd7016
|
||||
U dan
|
||||
Z 12262406c5f3f18d2ab88add956e21a6
|
||||
Z e88e77f44b464406d3184a89736eaa7d
|
||||
|
@ -1 +1 @@
|
||||
1cd15a1759004d5d321056905dbb6acff20dc7d9
|
||||
17ef5b59f789e9fa35c4f053246d819987fd06f8
|
Loading…
x
Reference in New Issue
Block a user