From fe1368ee086c8e87ea440561411ab70ff3f94c38 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 10 Sep 2006 17:08:29 +0000 Subject: [PATCH] Add a new zErrMsg field to the sqlite3_vtab structure to support returning error messages from virtual table constructors. This change means that virtual table implementations compiled as loadable extensions for version 3.3.7 will need to be recompile for version 3.3.8 and will not be usable by both versions at one. The virtual table mechanism is still considered experimental so we feel justified in breaking backwards compatibility in this way. Additional interface changes might occurs in the future. (CVS 3401) FossilOrigin-Name: 36693a5cb72b4363010f9ab0866e1f7865f65275 --- manifest | 14 +++++++------- manifest.uuid | 2 +- src/sqlite.h.in | 13 ++++++++++++- src/vtab.c | 24 +++++++++++++++++------- 4 files changed, 37 insertions(+), 16 deletions(-) diff --git a/manifest b/manifest index b8a242e0e5..c241e31be5 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\ssome\ssimple\stest\scases\sfor\sthe\sOR\sand\sNOT\slogic\sof\sthe\sfts1\smodule.\nFix\slots\sof\sbugs\sdiscovered\swhile\sdeveloping\sthese\stest\scases.\s(CVS\s3400) -D 2006-09-10T03:34:06 +C Add\sa\snew\szErrMsg\sfield\sto\sthe\ssqlite3_vtab\sstructure\sto\ssupport\sreturning\nerror\smessages\sfrom\svirtual\stable\sconstructors.\s\sThis\schange\smeans\sthat\nvirtual\stable\simplementations\scompiled\sas\sloadable\sextensions\sfor\sversion\n3.3.7\swill\sneed\sto\sbe\srecompile\sfor\sversion\s3.3.8\sand\swill\snot\sbe\susable\nby\sboth\sversions\sat\sone.\s\sThe\svirtual\stable\smechanism\sis\sstill\sconsidered\nexperimental\sso\swe\sfeel\sjustified\sin\sbreaking\sbackwards\scompatibility\nin\sthis\sway.\s\sAdditional\sinterface\schanges\smight\soccurs\sin\sthe\sfuture.\s(CVS\s3401) +D 2006-09-10T17:08:30 F Makefile.in cabd42d34340f49260bc2a7668c38eba8d4cfd99 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -86,7 +86,7 @@ F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261 F src/select.c 0d4724930a1f34c747105ed1802fa4af0d8eb519 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96 F src/shell.c 233f7766e532a204bed465249ffc584424ed1757 -F src/sqlite.h.in 84ac26ca94a84dd603fb57a27d862f51bfd9f687 +F src/sqlite.h.in 364f2aac46a3f2435ff30ccae1f34b53d667b0af F src/sqlite3ext.h 11a046b3519c4b9b7709e6d6a95c3a36366f684a F src/sqliteInt.h 259adce944cc3b28da1fa3df9beb9ba86017a45d F src/table.c d8817f43a6c6bf139487db161760b9e1e02da3f1 @@ -119,7 +119,7 @@ F src/vdbeapi.c 81f531d7dc5c898131b02ef85f6c6144ab2892cf F src/vdbeaux.c 9fab61427a0741c9c123e8ff16e349b1f90397be F src/vdbefifo.c 9efb94c8c3f4c979ebd0028219483f88e57584f5 F src/vdbemem.c 26623176bf1c616aa478da958fac49502491a921 -F src/vtab.c 7fc0624c2bb6156c3d99e2ce706f2a5b54094e36 +F src/vtab.c c68946eda1e9259582836d3fec39272fd3647b4d F src/where.c 75a89957fcb8c068bec55caa4e9d2ed5fa0b0724 F tclinstaller.tcl 046e3624671962dc50f0481d7c25b38ef803eb42 F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 @@ -397,7 +397,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513 -P ae50265791d1a7500aa3c405a78a9bca8ff0cc08 -R 102c1a21ff09d0f20e46f405978da02e +P 70bcff024b44d1b40afac6eba959fa89fb993147 +R 49ee6571b74bcd7a8b8e06a293fd1796 U drh -Z f515ac19d2cdc367f4c6838848ae4bb1 +Z e7e707b3d9d576052a0534936bdcea9b diff --git a/manifest.uuid b/manifest.uuid index d8f8de95b4..948d54bf70 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -70bcff024b44d1b40afac6eba959fa89fb993147 \ No newline at end of file +36693a5cb72b4363010f9ab0866e1f7865f65275 \ No newline at end of file diff --git a/src/sqlite.h.in b/src/sqlite.h.in index a1fbf7e825..1d559db5ac 100644 --- a/src/sqlite.h.in +++ b/src/sqlite.h.in @@ -12,7 +12,7 @@ ** This header file defines the interface that the SQLite library ** presents to client programs. ** -** @(#) $Id: sqlite.h.in,v 1.189 2006/08/24 14:59:46 drh Exp $ +** @(#) $Id: sqlite.h.in,v 1.190 2006/09/10 17:08:30 drh Exp $ */ #ifndef _SQLITE3_H_ #define _SQLITE3_H_ @@ -1705,10 +1705,21 @@ int sqlite3_create_module( ** be taylored to the specific needs of the module implementation. The ** purpose of this superclass is to define certain fields that are common ** to all module implementations. +** +** Virtual tables methods can set an error message by assigning a +** string obtained from sqlite3_mprintf() to zErrMsg. The method should +** take care that any prior string is freed by a call to sqlite3_free() +** prior to assigning a new string to zErrMsg. After the error message +** is delivered up to the client application, the string will be automatically +** freed by sqlite3_free() and the zErrMsg field will be zeroed. Note +** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field +** since virtual tables are commonly implemented in loadable extensions which +** do not have access to sqlite3MPrintf() or sqlite3Free(). */ struct sqlite3_vtab { const sqlite3_module *pModule; /* The module for this virtual table */ int nRef; /* Used internally */ + char *zErrMsg; /* Error message text */ /* Virtual table implementations will typically add additional fields */ }; diff --git a/src/vtab.c b/src/vtab.c index 9207fc485b..bb4634a46a 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.31 2006/09/02 20:57:52 drh Exp $ +** $Id: vtab.c,v 1.32 2006/09/10 17:08:30 drh Exp $ */ #ifndef SQLITE_OMIT_VIRTUALTABLE #include "sqliteInt.h" @@ -59,6 +59,8 @@ void sqlite3VtabLock(sqlite3_vtab *pVtab){ void sqlite3VtabUnlock(sqlite3_vtab *pVtab){ pVtab->nRef--; if( pVtab->nRef==0 ){ + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; pVtab->pModule->xDisconnect(pVtab); } } @@ -291,6 +293,7 @@ static int vtabCallConstructor( ){ int rc; int rc2; + sqlite3_vtab *pVtab; char **azArg = pTab->azModuleArg; int nArg = pTab->nModuleArg; char *zErr = sqlite3MPrintf("vtable constructor failed: %s", pTab->zName); @@ -303,15 +306,22 @@ static int vtabCallConstructor( assert( rc==SQLITE_OK ); rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab); rc2 = sqlite3SafetyOn(db); - if( rc==SQLITE_OK && pTab->pVtab ){ - pTab->pVtab->pModule = pMod->pModule; - pTab->pVtab->nRef = 1; + pVtab = pTab->pVtab; + if( rc==SQLITE_OK && pVtab ){ + pVtab->pModule = pMod->pModule; + pVtab->nRef = 1; } if( SQLITE_OK!=rc ){ - *pzErr = zErr; - zErr = 0; - } else if( db->pVTab ){ + if( pVtab && pVtab->zErrMsg ){ + *pzErr = sqlite3MPrintf("%s", pVtab->zErrMsg); + sqlite3_free(pVtab->zErrMsg); + pVtab->zErrMsg = 0; + }else{ + *pzErr = zErr; + zErr = 0; + } + }else if( db->pVTab ){ const char *zFormat = "vtable constructor did not declare schema: %s"; *pzErr = sqlite3MPrintf(zFormat, pTab->zName); rc = SQLITE_ERROR;