# define fts5CheckTransactionState(x,y,z)
#endif
+/*
+** Return true if pTab is a contentless table.
+*/
+static int fts5IsContentless(Fts5Table *pTab){
+ return pTab->pConfig->eContent==FTS5_CONTENT_NONE;
+}
/*
** Close a virtual table handle opened by fts5InitVtab(). If the bDestroy
/* This is either a full-table scan (ePlan==FTS5_PLAN_SCAN) or a lookup
** by rowid (ePlan==FTS5_PLAN_ROWID). */
int eStmt = fts5StmtType(idxNum);
- rc = sqlite3Fts5StorageStmt(pTab->pStorage, eStmt, &pCsr->pStmt);
+ rc = sqlite3Fts5StorageStmt(
+ pTab->pStorage, eStmt, &pCsr->pStmt, &pTab->base.zErrMsg
+ );
if( rc==SQLITE_OK ){
if( ePlan==FTS5_PLAN_ROWID ){
sqlite3_bind_value(pCsr->pStmt, 1, apVal[0]);
if( pCsr->pStmt==0 ){
Fts5Table *pTab = (Fts5Table*)(pCsr->base.pVtab);
int eStmt = fts5StmtType(pCsr->idxNum);
- rc = sqlite3Fts5StorageStmt(pTab->pStorage, eStmt, &pCsr->pStmt);
+ rc = sqlite3Fts5StorageStmt(
+ pTab->pStorage, eStmt, &pCsr->pStmt, &pTab->base.zErrMsg
+ );
assert( CsrFlagTest(pCsr, FTS5CSR_REQUIRE_CONTENT) );
}
*/
assert( nArg==1 || nArg==(2 + pConfig->nCol + 2) );
- if( nArg>1 ){
- sqlite3_value *pCmd = sqlite3_value_type(apVal[2 + pConfig->nCol]);
+ eType0 = sqlite3_value_type(apVal[0]);
+ eConflict = sqlite3_vtab_on_conflict(pConfig->db);
+
+ assert( eType0==SQLITE_INTEGER || eType0==SQLITE_NULL );
+ assert( pVtab->zErrMsg==0 );
+
+ if( rc==SQLITE_OK && eType0==SQLITE_INTEGER ){
+ if( fts5IsContentless(pTab) ){
+ pTab->base.zErrMsg = sqlite3_mprintf(
+ "cannot %s contentless fts5 table: %s",
+ (nArg>1 ? "UPDATE" : "DELETE from"), pConfig->zName
+ );
+ rc = SQLITE_ERROR;
+ }else{
+ i64 iDel = sqlite3_value_int64(apVal[0]); /* Rowid to delete */
+ rc = sqlite3Fts5StorageDelete(pTab->pStorage, iDel);
+ }
+ }else if( nArg>1 ){
+ sqlite3_value *pCmd = 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) ){
+ if( pConfig->eContent!=FTS5_CONTENT_NORMAL
+ && 0==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 );
- 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);
- }
if( rc==SQLITE_OK && nArg>1 ){
rc = sqlite3Fts5StorageInsert(pTab->pStorage, apVal, eConflict, pRowid);
const char **pz,
int *pn
){
+ int rc = SQLITE_OK;
Fts5Cursor *pCsr = (Fts5Cursor*)pCtx;
- int rc = fts5SeekCursor(pCsr);
- if( rc==SQLITE_OK ){
- *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
- *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
+ if( fts5IsContentless((Fts5Table*)(pCsr->base.pVtab)) ){
+ *pz = 0;
+ *pn = 0;
+ }else{
+ rc = fts5SeekCursor(pCsr);
+ if( rc==SQLITE_OK ){
+ *pz = (const char*)sqlite3_column_text(pCsr->pStmt, iCol+1);
+ *pn = sqlite3_column_bytes(pCsr->pStmt, iCol+1);
+ }
}
return rc;
}
sqlite3_context *pCtx, /* Context for sqlite3_result_xxx() calls */
int iCol /* Index of column to read value from */
){
- Fts5Config *pConfig = ((Fts5Table*)(pCursor->pVtab))->pConfig;
+ Fts5Table *pTab = (Fts5Table*)(pCursor->pVtab);
+ Fts5Config *pConfig = pTab->pConfig;
Fts5Cursor *pCsr = (Fts5Cursor*)pCursor;
int rc = SQLITE_OK;
fts5ApiInvoke(pCsr->pRank, pCsr, pCtx, pCsr->nRankArg, pCsr->apRankArg);
}
}
- }else{
+ }else if( !fts5IsContentless(pTab) ){
rc = fts5SeekCursor(pCsr);
if( rc==SQLITE_OK ){
sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pStmt, iCol+1));
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) */
+ int eContent; /* An FTS5_CONTENT value */
+ char *zContent; /* content table */
+ char *zContentRowid; /* "content_rowid=" option value */
Fts5Tokenizer *pTok;
fts5_tokenizer *pTokApi;
char *zRankArgs; /* Arguments to rank function */
};
+#define FTS5_CONTENT_NORMAL 0
+#define FTS5_CONTENT_NONE 1
+#define FTS5_CONTENT_EXTERNAL 2
+
+
+
int sqlite3Fts5ConfigParse(
Fts5Global*, sqlite3*, int, const char **, Fts5Config**, char**
);
int sqlite3Fts5StorageIntegrity(Fts5Storage *p);
-int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt **);
+int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt**, char**);
void sqlite3Fts5StorageStmtRelease(Fts5Storage *p, int eStmt, sqlite3_stmt*);
int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol);
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn);
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
- }
+ if( ctx.zIn ){
+ if( rc==SQLITE_OK ){
+ rc = fts5CInstIterInit(pApi, pFts, iCol, &ctx.iter);
+ }
- if( rc==SQLITE_OK ){
- rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx, fts5HighlightCb);
- }
- fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
+ if( rc==SQLITE_OK ){
+ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
+ }
+ fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
+ if( rc==SQLITE_OK ){
+ sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_error_code(pCtx, rc);
+ }
+ sqlite3_free(ctx.zOut);
}
- sqlite3_free(ctx.zOut);
}
/*
** End of highlight() implementation.
memset(&ctx, 0, sizeof(HighlightContext));
iCol = sqlite3_value_int(apVal[0]);
- rc = pApi->xColumnText(pFts, iCol, &ctx.zIn, &ctx.nIn);
ctx.zOpen = (const char*)sqlite3_value_text(apVal[1]);
ctx.zClose = (const char*)sqlite3_value_text(apVal[2]);
zEllips = (const char*)sqlite3_value_text(apVal[3]);
if( rc==SQLITE_OK ){
rc = pApi->xColumnText(pFts, iBestCol, &ctx.zIn, &ctx.nIn);
}
- if( rc==SQLITE_OK ){
- rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
- }
+ if( ctx.zIn ){
+ if( rc==SQLITE_OK ){
+ rc = fts5CInstIterInit(pApi, pFts, iBestCol, &ctx.iter);
+ }
- if( (iBestStart+nToken-1)>iBestLast ){
- iBestStart -= (iBestStart+nToken-1-iBestLast) / 2;
- }
- if( iBestStart+nToken>nColSize ){
- iBestStart = nColSize - nToken;
- }
- if( iBestStart<0 ) iBestStart = 0;
+ if( (iBestStart+nToken-1)>iBestLast ){
+ iBestStart -= (iBestStart+nToken-1-iBestLast) / 2;
+ }
+ if( iBestStart+nToken>nColSize ){
+ iBestStart = nColSize - nToken;
+ }
+ if( iBestStart<0 ) iBestStart = 0;
- ctx.iRangeStart = iBestStart;
- ctx.iRangeEnd = iBestStart + nToken - 1;
+ ctx.iRangeStart = iBestStart;
+ ctx.iRangeEnd = iBestStart + nToken - 1;
- if( iBestStart>0 ){
- fts5HighlightAppend(&rc, &ctx, zEllips, -1);
- }
- if( rc==SQLITE_OK ){
- rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx, fts5HighlightCb);
- }
- if( ctx.iRangeEnd>=(nColSize-1) ){
- fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
- }else{
- fts5HighlightAppend(&rc, &ctx, zEllips, -1);
- }
+ if( iBestStart>0 ){
+ fts5HighlightAppend(&rc, &ctx, zEllips, -1);
+ }
+ if( rc==SQLITE_OK ){
+ rc = pApi->xTokenize(pFts, ctx.zIn, ctx.nIn, (void*)&ctx,fts5HighlightCb);
+ }
+ if( ctx.iRangeEnd>=(nColSize-1) ){
+ fts5HighlightAppend(&rc, &ctx, &ctx.zIn[ctx.iOff], ctx.nIn - ctx.iOff);
+ }else{
+ fts5HighlightAppend(&rc, &ctx, zEllips, -1);
+ }
- if( rc==SQLITE_OK ){
- sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
- }else{
- sqlite3_result_error_code(pCtx, rc);
+ if( rc==SQLITE_OK ){
+ sqlite3_result_text(pCtx, (const char*)ctx.zOut, -1, SQLITE_TRANSIENT);
+ }else{
+ sqlite3_result_error_code(pCtx, rc);
+ }
+ sqlite3_free(ctx.zOut);
}
- sqlite3_free(ctx.zOut);
sqlite3_free(aSeen);
}
if( sqlite3_strnicmp("content", zCmd, nCmd)==0 ){
int rc = SQLITE_OK;
- if( pConfig->zContent ){
+ if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
*pzErr = sqlite3_mprintf("multiple content=... directives");
rc = SQLITE_ERROR;
}else{
- pConfig->zContent = sqlite3_mprintf("%Q.%Q", pConfig->zDb, zArg);
- pConfig->bExternalContent = 1;
+ if( zArg[0] ){
+ pConfig->eContent = FTS5_CONTENT_EXTERNAL;
+ pConfig->zContent = sqlite3_mprintf("%Q.%Q", pConfig->zDb, zArg);
+ }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 no zContent option was specified, fill in the default values. */
- if( rc==SQLITE_OK && pRet->zContent==0 ){
+ 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;
static int fts5StorageGetStmt(
Fts5Storage *p, /* Storage handle */
int eStmt, /* FTS5_STMT_XXX constant */
- sqlite3_stmt **ppStmt /* OUT: Prepared statement handle */
+ sqlite3_stmt **ppStmt, /* OUT: Prepared statement handle */
+ char **pzErrMsg /* OUT: Error message (if any) */
){
int rc = SQLITE_OK;
}else{
rc = sqlite3_prepare_v2(pC->db, zSql, -1, &p->aStmt[eStmt], 0);
sqlite3_free(zSql);
+ if( rc!=SQLITE_OK && pzErrMsg ){
+ *pzErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pC->db));
+ }
}
}
p->pIndex = pIndex;
if( bCreate ){
- if( pConfig->bExternalContent==0 ){
+ if( pConfig->eContent==FTS5_CONTENT_NORMAL ){
char *zDefn = sqlite3_malloc(32 + pConfig->nCol * 10);
if( zDefn==0 ){
rc = SQLITE_NOMEM;
/* If required, remove the shadow tables from the database */
if( bDestroy ){
- rc = sqlite3Fts5DropTable(p->pConfig, "content");
+ if( p->pConfig->eContent==FTS5_CONTENT_NORMAL ){
+ rc = sqlite3Fts5DropTable(p->pConfig, "content");
+ }
if( rc==SQLITE_OK ) rc = sqlite3Fts5DropTable(p->pConfig, "docsize");
if( rc==SQLITE_OK ) rc = sqlite3Fts5DropTable(p->pConfig, "config");
}
sqlite3_stmt *pSeek; /* SELECT to read row iDel from %_data */
int rc; /* Return code */
- rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek);
+ rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP, &pSeek, 0);
if( rc==SQLITE_OK ){
int rc2;
sqlite3_bind_int64(pSeek, 1, iDel);
Fts5Buffer *pBuf /* sz value */
){
sqlite3_stmt *pReplace = 0;
- int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace);
+ 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);
/* Delete the %_docsize record */
if( rc==SQLITE_OK ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel);
+ rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
}
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDel, 1, iDel);
/* Delete the %_content record */
if( rc==SQLITE_OK ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel);
+ rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_CONTENT, &pDel, 0);
}
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDel, 1, iDel);
int rc;
sqlite3_stmt *pDel;
- assert( p->pConfig->bExternalContent );
+ assert( p->pConfig->eContent!=FTS5_CONTENT_NORMAL );
rc = fts5StorageLoadTotals(p, 1);
/* Delete the index records */
(void*)&ctx,
fts5StorageInsertCallback
);
- p->aTotalSize[iCol-1] -= (i64)ctx.szCol;
+ p->aTotalSize[iCol] -= (i64)ctx.szCol;
}
p->nTotalRow--;
}
/* Delete the %_docsize record */
if( rc==SQLITE_OK ){
- rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel);
+ rc = fts5StorageGetStmt(p, FTS5_STMT_DELETE_DOCSIZE, &pDel, 0);
}
if( rc==SQLITE_OK ){
sqlite3_bind_int64(pDel, 1, iDel);
*/
static int fts5StorageNewRowid(Fts5Storage *p, i64 *piRowid){
sqlite3_stmt *pReplace = 0;
- int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace);
+ int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_DOCSIZE, &pReplace, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_null(pReplace, 1);
sqlite3_bind_null(pReplace, 2);
rc = fts5StorageLoadTotals(p, 1);
/* Insert the new row into the %_content table. */
- if( rc==SQLITE_OK && pConfig->bExternalContent==0 ){
- if( pConfig->bExternalContent ){
+ if( rc==SQLITE_OK ){
+ if( pConfig->eContent!=FTS5_CONTENT_NORMAL ){
if( sqlite3_value_type(apVal[1])==SQLITE_INTEGER ){
*piRowid = sqlite3_value_int64(apVal[1]);
}else{
eStmt = FTS5_STMT_INSERT_CONTENT;
}
if( rc==SQLITE_OK ){
- rc = fts5StorageGetStmt(p, eStmt, &pInsert);
+ rc = fts5StorageGetStmt(p, eStmt, &pInsert, 0);
}
for(i=1; rc==SQLITE_OK && i<=pConfig->nCol+1; i++){
rc = sqlite3_bind_value(pInsert, i, apVal[i]);
/* Generate the expected index checksum based on the contents of the
** %_content table. This block stores the checksum in ctx.cksum. */
- rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN_ASC, &pScan);
+ rc = fts5StorageGetStmt(p, FTS5_STMT_SCAN_ASC, &pScan, 0);
if( rc==SQLITE_OK ){
int rc2;
while( SQLITE_ROW==sqlite3_step(pScan) ){
** Obtain an SQLite statement handle that may be used to read data from the
** %_content table.
*/
-int sqlite3Fts5StorageStmt(Fts5Storage *p, int eStmt, sqlite3_stmt **pp){
+int sqlite3Fts5StorageStmt(
+ Fts5Storage *p,
+ int eStmt,
+ sqlite3_stmt **pp,
+ char **pzErrMsg
+){
int rc;
assert( eStmt==FTS5_STMT_SCAN_ASC
|| eStmt==FTS5_STMT_SCAN_DESC
|| eStmt==FTS5_STMT_LOOKUP
);
- rc = fts5StorageGetStmt(p, eStmt, pp);
+ rc = fts5StorageGetStmt(p, eStmt, pp, pzErrMsg);
if( rc==SQLITE_OK ){
assert( p->aStmt[eStmt]==*pp );
p->aStmt[eStmt] = 0;
int sqlite3Fts5StorageDocsize(Fts5Storage *p, i64 iRowid, int *aCol){
int nCol = p->pConfig->nCol;
sqlite3_stmt *pLookup = 0;
- int rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup);
+ int rc = fts5StorageGetStmt(p, FTS5_STMT_LOOKUP_DOCSIZE, &pLookup, 0);
if( rc==SQLITE_OK ){
int bCorrupt = 1;
sqlite3_bind_int64(pLookup, 1, iRowid);
sqlite3_value *pVal
){
sqlite3_stmt *pReplace = 0;
- int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_CONFIG, &pReplace);
+ int rc = fts5StorageGetStmt(p, FTS5_STMT_REPLACE_CONFIG, &pReplace, 0);
if( rc==SQLITE_OK ){
sqlite3_bind_text(pReplace, 1, z, -1, SQLITE_TRANSIENT);
sqlite3_bind_value(pReplace, 2, pVal);
--- /dev/null
+# 2014 Dec 20
+#
+# 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.
+#
+#***********************************************************************
+#
+#
+
+if {![info exists testdir]} {
+ set testdir [file join [file dirname [info script]] .. .. .. test]
+}
+source $testdir/tester.tcl
+set testprefix fts5content
+
+do_execsql_test 1.1 {
+ CREATE VIRTUAL TABLE f1 USING fts5(a, b, content='');
+ INSERT INTO f1(rowid, a, b) VALUES(1, 'one', 'o n e');
+ INSERT INTO f1(rowid, a, b) VALUES(2, 'two', 't w o');
+ INSERT INTO f1(rowid, a, b) VALUES(3, 'three', 't h r e e');
+}
+
+do_execsql_test 1.2 {
+ SELECT rowid FROM f1 WHERE f1 MATCH 'o';
+} {2 1}
+
+do_execsql_test 1.3 {
+ INSERT INTO f1(a, b) VALUES('four', 'f o u r');
+ SELECT rowid FROM f1 WHERE f1 MATCH 'o';
+} {4 2 1}
+
+do_execsql_test 1.4 {
+ SELECT rowid, a, b FROM f1 WHERE f1 MATCH 'o';
+} {4 {} {} 2 {} {} 1 {} {}}
+
+do_execsql_test 1.5 {
+ SELECT rowid, highlight(f1, 0, '[', ']') FROM f1 WHERE f1 MATCH 'o';
+} {4 {} 2 {} 1 {}}
+
+do_execsql_test 1.6 {
+ SELECT rowid, highlight(f1, 0, '[', ']') IS NULL FROM f1 WHERE f1 MATCH 'o';
+} {4 1 2 1 1 1}
+
+do_execsql_test 1.7 {
+ SELECT rowid, snippet(f1, -1, '[', ']', '...', 5) IS NULL
+ FROM f1 WHERE f1 MATCH 'o';
+} {4 1 2 1 1 1}
+
+do_execsql_test 1.8 {
+ SELECT rowid, snippet(f1, 1, '[', ']', '...', 5) IS NULL
+ FROM f1 WHERE f1 MATCH 'o';
+} {4 1 2 1 1 1}
+
+do_execsql_test 1.9 {
+ SELECT rowid FROM f1;
+} {4 3 2 1}
+
+do_execsql_test 1.10 {
+ SELECT * FROM f1;
+} {{} {} {} {} {} {} {} {}}
+
+do_execsql_test 1.11 {
+ SELECT rowid, a, b FROM f1 ORDER BY rowid ASC;
+} {1 {} {} 2 {} {} 3 {} {} 4 {} {}}
+
+do_execsql_test 1.12 {
+ SELECT a IS NULL FROM f1;
+} {1 1 1 1}
+
+do_catchsql_test 1.13 {
+ DELETE FROM f1 WHERE rowid = 2;
+} {1 {cannot DELETE from contentless fts5 table: f1}}
+
+do_catchsql_test 1.14 {
+ UPDATE f1 SET a = 'a b c' WHERE rowid = 2;
+} {1 {cannot UPDATE contentless fts5 table: f1}}
+
+do_execsql_test 1.15 {
+ INSERT INTO f1(f1, rowid, a, b) VALUES('delete', 2, 'two', 't w o');
+} {}
+
+db eval { SELECT fts5_decode(id, block) AS d FROM f1_data } { puts $d }
+
+breakpoint
+do_execsql_test 1.16 {
+ SELECT rowid FROM f1 WHERE f1 MATCH 'o';
+} {4 1}
+do_execsql_test 1.17 {
+ SELECT rowid FROM f1;
+} {4 3 1}
+
+
+
+
+finish_test
-C Add\ssupport\sfor\sexternal\scontent\stables\sto\sfts5.
-D 2015-01-03T20:44:58.134
+C Tests\sand\sfixes\sfor\sfts5\sexternal\scontent\stables.
+D 2015-01-05T20:41:39.791
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 7cd23e4fc91004a6bd081623e1bc6932e44828c0
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
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 16177d7f81af1852cf7f477b5ae119215ad6044a
+F ext/fts5/fts5.c e2c19b2c5ab96650732bb6904892a6fb9a27ab42
F ext/fts5/fts5.h 4f9d2c477c0ee1907164642471329a82cb6b203b
-F ext/fts5/fts5Int.h 8062dc2363c863dc8a5b2e5651cb8c966bd6c4cb
-F ext/fts5/fts5_aux.c 445e54031ff94174673f4f5aac6c064df20a2a6b
+F ext/fts5/fts5Int.h 9aafe97064e9c3380991abad4f51bee51021d18d
+F ext/fts5/fts5_aux.c a74523025a553f57c99c699b9e2d83c4506503b4
F ext/fts5/fts5_buffer.c 1bc5c762bb2e9b4a40b2e8a820a31b809e72eec1
-F ext/fts5/fts5_config.c 16d647c7bfe50d4e823267188e12e2d001d655e0
+F ext/fts5/fts5_config.c 630f92bb0a301c0b4e37a05ec4e38dc51ceeba37
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 b95fcca70f94656854e7afcfbb9896455f6b034d
+F ext/fts5/fts5_storage.c 68ce8ec98b009cbd350ff73df06a97b1a012e122
F ext/fts5/fts5_tcl.c 664e710e2bbeed505cb91848772ca7538623a67f
F ext/fts5/fts5_tokenize.c 5a0ad46408d09bcda2bf0addb5af42fdb75ebabb
F ext/fts5/fts5_unicode2.c 9c7dd640d1f014bf5c3ee029759adfbb4d7e95a9
F ext/fts5/test/fts5ak.test df2669fb76684f03d03918dfb2cf692012251b1f
F ext/fts5/test/fts5al.test bc873766fec3baae05ba6e76b379bc2f5e8eaf75
F ext/fts5/test/fts5auxdata.test fec4c9113176d351e567eab65fe9917e5ea0ab05
+F ext/fts5/test/fts5content.test 0f267ba2086f2dff81484c8ee71fa0d3990c41f7
F ext/fts5/test/fts5ea.test 0ef2c89e14c6360ad3905fae44409420d6b5a5c8
F ext/fts5/test/fts5fault1.test b95ed600b88bbbce5390f9097a5a5b7b01b3b9f7
F ext/fts5/test/fts5porter.test d8f7591b733bcc1f02ca0dd313bc891a4b289562
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 1cd15a1759004d5d321056905dbb6acff20dc7d9
-R d21eb6bee3b06e51f22d32d1e0bd7016
+P 17ef5b59f789e9fa35c4f053246d819987fd06f8
+R 6bfe2a49f6feaf1db299d5e29da25a24
U dan
-Z e88e77f44b464406d3184a89736eaa7d
+Z 3d2200ed8057fd64a39f743bdc333945
-17ef5b59f789e9fa35c4f053246d819987fd06f8
\ No newline at end of file
+047aaf830d1e72f0fdad3832a0b617e769d66468
\ No newline at end of file