Index: src/sqliteInt.h ================================================================== --- src/sqliteInt.h +++ src/sqliteInt.h @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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_ /* @@ -2213,15 +2213,17 @@ #ifdef SQLITE_OMIT_VIRTUALTABLE # define sqlite3VtabClear(X) # 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*); void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*); void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*); Index: src/test8.c ================================================================== --- src/test8.c +++ src/test8.c @@ -11,11 +11,11 @@ ************************************************************************* ** Code for testing the virtual table interfaces. This code ** 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" #include #include @@ -985,10 +985,13 @@ } 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; } /* Index: src/vdbe.c ================================================================== --- src/vdbe.c +++ src/vdbe.c @@ -41,11 +41,11 @@ ** documentation, headers files, or other derived files. The formatting ** of the code in this file is, therefore, important. See other comments ** 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 #include "vdbeInt.h" @@ -4619,10 +4619,11 @@ sqlite3_module *pModule = (sqlite3_module *)pVtab->pModule; 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 */ pVtabCursor->pVtab = pVtab; @@ -4663,16 +4664,20 @@ int nArg; int iQuery; 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 ); nArg = pArgc->u.i; iQuery = pQuery->u.i; @@ -4687,14 +4692,14 @@ storeTypeInfo(apArg[i], 0); } 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; if( res ){ pc = pOp->p2 - 1; @@ -4845,10 +4850,11 @@ if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 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; } #endif @@ -4897,10 +4903,11 @@ } if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse; 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) ); db->lastRowid = rowid; } Index: src/vtab.c ================================================================== --- src/vtab.c +++ src/vtab.c @@ -9,11 +9,11 @@ ** May you share freely, never taking more than you give. ** ************************************************************************* ** 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" static int createModule( @@ -724,10 +724,11 @@ } } /* Invoke the xBegin method */ rc = pModule->xBegin(pVtab); + sqlite3VtabTransferError(db, rc, pVtab); if( rc!=SQLITE_OK ){ return rc; } rc = addToVTrans(db, pVtab); @@ -785,10 +786,11 @@ for(z=(unsigned char*)zLowerName; *z; z++){ *z = sqlite3UpperToLower[*z]; } rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); sqlite3_free(zLowerName); + sqlite3VtabTransferError(db, rc, pVtab); } if( rc==0 ){ return pDef; } @@ -824,7 +826,18 @@ pParse->apVtabLock[pParse->nVtabLock++] = pTab; }else{ pParse->db->mallocFailed = 1; } } + +/* +** 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 */ Index: test/fts2.test ================================================================== --- test/fts2.test +++ test/fts2.test @@ -1,14 +1,15 @@ +# 2008 July 22 # # 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. # #*********************************************************************** # This file runs all tests. # -# $Id: fts2.test,v 1.1 2008/07/22 22:57:54 shess Exp $ +# $Id: fts2.test,v 1.2 2008/07/23 18:17:32 drh Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] @@ -31,12 +32,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl # If SQLITE_ENABLE_FTS2 is defined, omit this file. ifcapable !fts2 { - puts stderr "this build does not include FTS2 capability" - exit 1 + return } rename finish_test really_finish_test proc finish_test {} {} set ISQUICK 1 Index: test/fts3.test ================================================================== --- test/fts3.test +++ test/fts3.test @@ -1,14 +1,15 @@ +# 2007 November 23 # # 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. # #*********************************************************************** # This file runs all tests. # -# $Id: fts3.test,v 1.1 2007/11/23 17:31:19 drh Exp $ +# $Id: fts3.test,v 1.2 2008/07/23 18:17:32 drh Exp $ proc lshift {lvar} { upvar $lvar l set ret [lindex $l 0] set l [lrange $l 1 end] @@ -31,12 +32,11 @@ set testdir [file dirname $argv0] source $testdir/tester.tcl # If SQLITE_ENABLE_FTS3 is defined, omit this file. ifcapable !fts3 { - puts stderr "this build does not include FTS3 capability" - exit 1 + return } rename finish_test really_finish_test proc finish_test {} {} set ISQUICK 1