Read the sqlite3_vtab.zErrMsg after each call to a virtual table
method and transfer any error into the database connection.
Fix the fts2.test and fts3.test scripts to that they return
silently rather than failing the test sequence if the appropriate
FTS implementation is unavailable. (CVS 5463)

FossilOrigin-Name: e2c6771d44f1b4fee16ef90e91c3498be2a7d2b1
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index cd976f1..07d7a3f 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.742 2008/07/12 14:52:20 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.743 2008/07/23 18:17:32 drh Exp $
 */
 #ifndef _SQLITEINT_H_
 #define _SQLITEINT_H_
@@ -2215,11 +2215,13 @@
 #  define sqlite3VtabSync(X,Y) (Y)
 #  define sqlite3VtabRollback(X)
 #  define sqlite3VtabCommit(X)
+#  define sqlite3VtabTransferError(A,B,C)
 #else
    void sqlite3VtabClear(Table*);
    int sqlite3VtabSync(sqlite3 *db, int rc);
    int sqlite3VtabRollback(sqlite3 *db);
    int sqlite3VtabCommit(sqlite3 *db);
+   void sqlite3VtabTransferError(sqlite3 *db, int, sqlite3_vtab*);
 #endif
 void sqlite3VtabMakeWritable(Parse*,Table*);
 void sqlite3VtabLock(sqlite3_vtab*);
diff --git a/src/test8.c b/src/test8.c
index 9e4bcb2..c64e55d 100644
--- a/src/test8.c
+++ b/src/test8.c
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test8.c,v 1.67 2008/07/07 14:50:14 drh Exp $
+** $Id: test8.c,v 1.68 2008/07/23 18:17:32 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -987,6 +987,9 @@
   if( pRowid && rc==SQLITE_OK ){
     *pRowid = sqlite3_last_insert_rowid(db);
   }
+  if( rc!=SQLITE_OK ){
+    tab->zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", sqlite3_errmsg(db));
+  }
 
   return rc;
 }
diff --git a/src/vdbe.c b/src/vdbe.c
index d65995b..c1d3c51 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.761 2008/07/11 21:02:54 drh Exp $
+** $Id: vdbe.c,v 1.762 2008/07/23 18:17:32 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -4621,6 +4621,7 @@
   assert(pVtab && pModule);
   if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
   rc = pModule->xOpen(pVtab, &pVtabCursor);
+  sqlite3VtabTransferError(db, rc, pVtab);
   if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
   if( SQLITE_OK==rc ){
     /* Initialize sqlite3_vtab_cursor base class */
@@ -4665,12 +4666,16 @@
   const sqlite3_module *pModule;
   Mem *pQuery = &p->aMem[pOp->p3];
   Mem *pArgc = &pQuery[1];
+  sqlite3_vtab_cursor *pVtabCursor;
+  sqlite3_vtab *pVtab;
 
   Cursor *pCur = p->apCsr[pOp->p1];
 
   REGISTER_TRACE(pOp->p3, pQuery);
   assert( pCur->pVtabCursor );
-  pModule = pCur->pVtabCursor->pVtab->pModule;
+  pVtabCursor = pCur->pVtabCursor;
+  pVtab = pVtabCursor->pVtab;
+  pModule = pVtab->pModule;
 
   /* Grab the index number and argc parameters */
   assert( (pQuery->flags&MEM_Int)!=0 && pArgc->flags==MEM_Int );
@@ -4689,10 +4694,10 @@
 
     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
     p->inVtabMethod = 1;
-    rc = pModule->xFilter(pCur->pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
+    rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
     p->inVtabMethod = 0;
     if( rc==SQLITE_OK ){
-      res = pModule->xEof(pCur->pVtabCursor);
+      res = pModule->xEof(pVtabCursor);
     }
     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
 
@@ -4847,6 +4852,7 @@
   sqlite3VtabLock(pVtab);
   rc = pVtab->pModule->xRename(pVtab, pName->z);
   sqlite3VtabUnlock(db, pVtab);
+  sqlite3VtabTransferError(db, rc, pVtab);
   if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
 
   break;
@@ -4899,6 +4905,7 @@
     sqlite3VtabLock(pVtab);
     rc = pModule->xUpdate(pVtab, nArg, apArg, &rowid);
     sqlite3VtabUnlock(db, pVtab);
+    sqlite3VtabTransferError(db, rc, pVtab);
     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
     if( pOp->p1 && rc==SQLITE_OK ){
       assert( nArg>1 && apArg[0] && (apArg[0]->flags&MEM_Null) );
diff --git a/src/vtab.c b/src/vtab.c
index ab96023..2c71215 100644
--- a/src/vtab.c
+++ b/src/vtab.c
@@ -11,7 +11,7 @@
 *************************************************************************
 ** This file contains code used to help implement virtual tables.
 **
-** $Id: vtab.c,v 1.70 2008/06/23 17:44:19 danielk1977 Exp $
+** $Id: vtab.c,v 1.71 2008/07/23 18:17:32 drh Exp $
 */
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 #include "sqliteInt.h"
@@ -726,6 +726,7 @@
 
     /* Invoke the xBegin method */
     rc = pModule->xBegin(pVtab);
+    sqlite3VtabTransferError(db, rc, pVtab);
     if( rc!=SQLITE_OK ){
       return rc;
     }
@@ -787,6 +788,7 @@
     }
     rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg);
     sqlite3_free(zLowerName);
+    sqlite3VtabTransferError(db, rc, pVtab);
   }
   if( rc==0 ){
     return pDef;
@@ -827,4 +829,15 @@
   }
 }
 
+/*
+** Transfer a virtual table error into the database connection.
+*/
+void sqlite3VtabTransferError(sqlite3 *db, int rc, sqlite3_vtab *pVtab){
+  if( pVtab->zErrMsg ){
+    sqlite3Error(db, rc, "%s", pVtab->zErrMsg);
+    sqlite3_free(pVtab->zErrMsg);
+    pVtab->zErrMsg = 0;
+  }
+}
+
 #endif /* SQLITE_OMIT_VIRTUALTABLE */