const char *zTbl, /* Name of content table */
const char ***pazCol, /* OUT: Malloc'd array of column names */
int *pnCol, /* OUT: Size of array *pazCol */
- int *pnStr /* OUT: Bytes of string content */
+ int *pnStr, /* OUT: Bytes of string content */
+ char **pzErr /* OUT: error message */
){
int rc = SQLITE_OK; /* Return code */
char *zSql; /* "SELECT *" statement on zTbl */
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ){
+ *pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
+ }
}
sqlite3_free(zSql);
if( nCol==0 ){
sqlite3_free((void*)aCol);
aCol = 0;
- rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
+ rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
/* If a languageid= option was specified, remove the language id
** column from the aCol[] array. */
-C Fix\sincorrect\scolumn\snames\sin\sUPDATE\sstatements\sgenerated\sby\sthe\ssqldiff\nutility.
-D 2015-04-09T19:39:54.853
+C Do\snot\sallow\svirtual\stable\sconstructors\sto\sbe\scalled\srecursively.
+D 2015-04-10T07:55:07.186
F Makefile.arm-wince-mingw32ce-gcc d6df77f1f48d690bd73162294bbba7f59507c72f
F Makefile.in 5f78b1ab81b64e7c57a75d170832443e66c0880a
F Makefile.linux-gcc 91d710bdc4998cb015f39edf3cb314ec4f4d7e23
F ext/fts3/README.syntax a19711dc5458c20734b8e485e75fb1981ec2427a
F ext/fts3/README.tokenizers e0a8b81383ea60d0334d274fadf305ea14a8c314
F ext/fts3/README.txt 8c18f41574404623b76917b9da66fcb0ab38328d
-F ext/fts3/fts3.c 23bd9d37a777342f5c22a648e9b4b005dde9e58f
+F ext/fts3/fts3.c 57d863c3bd360e575ecc293570af7c9b0bdd2209
F ext/fts3/fts3.h 3a10a0af180d502cecc50df77b1b22df142817fe
F ext/fts3/fts3Int.h 394858c12a17740f7a1f6bd372c4606d4425a8d1
F ext/fts3/fts3_aux.c 5c211e17a64885faeb16b9ba7772f9d5445c2365
F src/vdbemem.c c0dc81285b7571b0a31c40f17846fe2397ec1cd9
F src/vdbesort.c 919717d7599fa31d343ec28bffd0f9e91a4ff5f6
F src/vdbetrace.c 7e4222955e07dd707a2f360c0eb73452be1cb010
-F src/vtab.c 62d49237bd8f3be4863815a39387b0f9897fa5e1
+F src/vtab.c ff722a886ed61e2e2889ee221b0a4f6dcaabb8e1
F src/vxworks.h c18586c8edc1bddbc15c004fa16aeb1e1342b4fb
F src/wal.c 878c8e1a51cb2ec45c395d26b7d5cd9e1a098e4a
F src/wal.h df01efe09c5cb8c8e391ff1715cca294f89668a4
F test/fts3varint.test 752c08ed5d32c5d7dc211b056f4ed68a76b7e36e
F test/fts4aa.test 10aac8e9d62c7357590acfabe3fad01e9a9ce1cb
F test/fts4check.test 74d77f6cdb768ac49df5afda575cef14ae3d239a
-F test/fts4content.test 2e7252557d6d24afa101d9ba1de710d6140e6d06
+F test/fts4content.test abb0c77bc3da3df64fec72e00844d2257a90025d
F test/fts4docid.test e33c383cfbdff0284685604d256f347a18fdbf01
F test/fts4growth.test df10fde9f47cf5c71861e63fd8efcd573c4f7e53
F test/fts4growth2.test 2f063be1902a73cd087355837c52fed42ac11a5d
F tool/warnings-clang.sh f6aa929dc20ef1f856af04a730772f59283631d4
F tool/warnings.sh 0abfd78ceb09b7f7c27c688c8e3fe93268a13b32
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
-P 5063f9070afde9374ea0f2bc338fee840d8b3dd4
-R b81a13af06affec3f4deb7b3b6092ef8
-U drh
-Z 7a24354f8d3816810c976cc3a62d01ee
+P ee53b46011852e27db23708387fe1e918cc8284c
+R 7e9242555b174ae9f2c42129917fe80c
+U dan
+Z a71357da8ab26f740f6d9ebc28389132
-ee53b46011852e27db23708387fe1e918cc8284c
\ No newline at end of file
+0a72726da21581ab16cb3e964bd825b8f2e931e4
\ No newline at end of file
struct VtabCtx {
VTable *pVTable; /* The virtual table being constructed */
Table *pTab; /* The Table object to which the virtual table belongs */
+ VtabCtx *pPrior; /* Parent context (if any) */
+ int bDeclared; /* True after sqlite3_declare_vtab() is called */
};
/*
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
char **pzErr
){
- VtabCtx sCtx, *pPriorCtx;
+ VtabCtx sCtx;
VTable *pVTable;
int rc;
const char *const*azArg = (const char *const*)pTab->azModuleArg;
int nArg = pTab->nModuleArg;
char *zErr = 0;
- char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+ char *zModuleName;
int iDb;
+ VtabCtx *pCtx;
+
+ /* Check that the virtual-table is not already being initialized */
+ for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
+ if( pCtx->pTab==pTab ){
+ *pzErr = sqlite3MPrintf(db,
+ "vtable constructor called recursively: %s", pTab->zName
+ );
+ return SQLITE_LOCKED;
+ }
+ }
+ zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
if( !zModuleName ){
return SQLITE_NOMEM;
}
assert( xConstruct );
sCtx.pTab = pTab;
sCtx.pVTable = pVTable;
- pPriorCtx = db->pVtabCtx;
+ sCtx.pPrior = db->pVtabCtx;
+ sCtx.bDeclared = 0;
db->pVtabCtx = &sCtx;
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
- db->pVtabCtx = pPriorCtx;
+ db->pVtabCtx = sCtx.pPrior;
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+ assert( sCtx.pTab==pTab );
if( SQLITE_OK!=rc ){
if( zErr==0 ){
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
pVTable->pVtab->pModule = pMod->pModule;
pVTable->nRef = 1;
- if( sCtx.pTab ){
+ if( sCtx.bDeclared==0 ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
sqlite3VtabUnlock(pVTable);
** virtual table module.
*/
int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
+ VtabCtx *pCtx = db->pVtabCtx;
Parse *pParse;
-
int rc = SQLITE_OK;
Table *pTab;
char *zErr = 0;
}
#endif
sqlite3_mutex_enter(db->mutex);
- if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
+ if( !pCtx || pCtx->bDeclared ){
sqlite3Error(db, SQLITE_MISUSE);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE_BKPT;
}
+ pTab = pCtx->pTab;
assert( (pTab->tabFlags & TF_Virtual)!=0 );
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
pParse->pNewTable->nCol = 0;
pParse->pNewTable->aCol = 0;
}
- db->pVtabCtx->pTab = 0;
+ pCtx->bDeclared = 1;
}else{
sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
#
# 9.* - Test using content=xxx where xxx is a virtual table.
#
+# 11.* - Test that circular references (e.g. "t1(content=t1)") are
+# detected.
+#
do_execsql_test 1.1.1 {
CREATE TABLE t1(a, b, c);
#
do_catchsql_test 6.1.1 {
CREATE VIRTUAL TABLE ft7 USING fts4(content=t7);
-} {1 {vtable constructor failed: ft7}}
+} {1 {no such table: main.t7}}
do_execsql_test 6.2.1 {
CREATE TABLE t7(one, two);
}
do_catchsql_test 6.2.4 {
SELECT * FROM ft7;
-} {1 {vtable constructor failed: ft7}}
+} {1 {no such table: main.t7}}
do_execsql_test 6.2.5 {
CREATE TABLE t7(x, y);
INSERT INTO t7 VALUES('A B', 'B A');
{...c d [e] f g...}
}
+#-------------------------------------------------------------------------
+# Test cases 11.*
+#
+reset_db
+
+do_catchsql_test 11.1 {
+ CREATE VIRTUAL TABLE x1 USING fts4(content=x1);
+} {1 {vtable constructor called recursively: x1}}
+
+
finish_test
+