Index: third_party/sqlite/src/src/vtab.c |
diff --git a/third_party/sqlite/src/src/vtab.c b/third_party/sqlite/src/src/vtab.c |
index 6054df3d710d06067da60002bc5410237e46791d..30079cbb5ea94dff5fe2aa0d2e80233ac63b0b47 100644 |
--- a/third_party/sqlite/src/src/vtab.c |
+++ b/third_party/sqlite/src/src/vtab.c |
@@ -29,6 +29,41 @@ struct VtabCtx { |
}; |
/* |
+** Construct and install a Module object for a virtual table. When this |
+** routine is called, it is guaranteed that all appropriate locks are held |
+** and the module is not already part of the connection. |
+*/ |
+Module *sqlite3VtabCreateModule( |
+ sqlite3 *db, /* Database in which module is registered */ |
+ const char *zName, /* Name assigned to this module */ |
+ const sqlite3_module *pModule, /* The definition of the module */ |
+ void *pAux, /* Context pointer for xCreate/xConnect */ |
+ void (*xDestroy)(void *) /* Module destructor function */ |
+){ |
+ Module *pMod; |
+ int nName = sqlite3Strlen30(zName); |
+ pMod = (Module *)sqlite3DbMallocRawNN(db, sizeof(Module) + nName + 1); |
+ if( pMod ){ |
+ Module *pDel; |
+ char *zCopy = (char *)(&pMod[1]); |
+ memcpy(zCopy, zName, nName+1); |
+ pMod->zName = zCopy; |
+ pMod->pModule = pModule; |
+ pMod->pAux = pAux; |
+ pMod->xDestroy = xDestroy; |
+ pMod->pEpoTab = 0; |
+ pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
+ assert( pDel==0 || pDel==pMod ); |
+ if( pDel ){ |
+ sqlite3OomFault(db); |
+ sqlite3DbFree(db, pDel); |
+ pMod = 0; |
+ } |
+ } |
+ return pMod; |
+} |
+ |
+/* |
** The actual function that does the work of creating a new module. |
** This function implements the sqlite3_create_module() and |
** sqlite3_create_module_v2() interfaces. |
@@ -41,35 +76,15 @@ static int createModule( |
void (*xDestroy)(void *) /* Module destructor function */ |
){ |
int rc = SQLITE_OK; |
- int nName; |
sqlite3_mutex_enter(db->mutex); |
- nName = sqlite3Strlen30(zName); |
if( sqlite3HashFind(&db->aModule, zName) ){ |
rc = SQLITE_MISUSE_BKPT; |
}else{ |
- Module *pMod; |
- pMod = (Module *)sqlite3DbMallocRaw(db, sizeof(Module) + nName + 1); |
- if( pMod ){ |
- Module *pDel; |
- char *zCopy = (char *)(&pMod[1]); |
- memcpy(zCopy, zName, nName+1); |
- pMod->zName = zCopy; |
- pMod->pModule = pModule; |
- pMod->pAux = pAux; |
- pMod->xDestroy = xDestroy; |
- pMod->pEpoTab = 0; |
- pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod); |
- assert( pDel==0 || pDel==pMod ); |
- if( pDel ){ |
- db->mallocFailed = 1; |
- sqlite3DbFree(db, pDel); |
- } |
- } |
+ (void)sqlite3VtabCreateModule(db, zName, pModule, pAux, xDestroy); |
} |
rc = sqlite3ApiExit(db, rc); |
if( rc!=SQLITE_OK && xDestroy ) xDestroy(pAux); |
- |
sqlite3_mutex_leave(db->mutex); |
return rc; |
} |
@@ -344,7 +359,7 @@ void sqlite3VtabBeginParse( |
*/ |
if( pTable->azModuleArg ){ |
sqlite3AuthCheck(pParse, SQLITE_CREATE_VTABLE, pTable->zName, |
- pTable->azModuleArg[0], pParse->db->aDb[iDb].zName); |
+ pTable->azModuleArg[0], pParse->db->aDb[iDb].zDbSName); |
} |
#endif |
} |
@@ -408,7 +423,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ |
"UPDATE %Q.%s " |
"SET type='table', name=%Q, tbl_name=%Q, rootpage=0, sql=%Q " |
"WHERE rowid=#%d", |
- db->aDb[iDb].zName, SCHEMA_TABLE(iDb), |
+ db->aDb[iDb].zDbSName, MASTER_NAME, |
pTab->zName, |
pTab->zName, |
zStmt, |
@@ -418,7 +433,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ |
v = sqlite3GetVdbe(pParse); |
sqlite3ChangeCookie(pParse, iDb); |
- sqlite3VdbeAddOp2(v, OP_Expire, 0, 0); |
+ sqlite3VdbeAddOp0(v, OP_Expire); |
zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName); |
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere); |
@@ -439,7 +454,7 @@ void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){ |
assert( sqlite3SchemaMutexHeld(db, 0, pSchema) ); |
pOld = sqlite3HashInsert(&pSchema->tblHash, zName, pTab); |
if( pOld ){ |
- db->mallocFailed = 1; |
+ sqlite3OomFault(db); |
assert( pTab==pOld ); /* Malloc must have failed inside HashInsert() */ |
return; |
} |
@@ -506,19 +521,19 @@ static int vtabCallConstructor( |
zModuleName = sqlite3MPrintf(db, "%s", pTab->zName); |
if( !zModuleName ){ |
- return SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
} |
pVTable = sqlite3DbMallocZero(db, sizeof(VTable)); |
if( !pVTable ){ |
sqlite3DbFree(db, zModuleName); |
- return SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
} |
pVTable->db = db; |
pVTable->pMod = pMod; |
iDb = sqlite3SchemaToIndex(db, pTab->pSchema); |
- pTab->azModuleArg[1] = db->aDb[iDb].zName; |
+ pTab->azModuleArg[1] = db->aDb[iDb].zDbSName; |
/* Invoke the virtual table constructor */ |
assert( &db->pVtabCtx ); |
@@ -530,7 +545,7 @@ static int vtabCallConstructor( |
db->pVtabCtx = &sCtx; |
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr); |
db->pVtabCtx = sCtx.pPrior; |
- if( rc==SQLITE_NOMEM ) db->mallocFailed = 1; |
+ if( rc==SQLITE_NOMEM ) sqlite3OomFault(db); |
assert( sCtx.pTab==pTab ); |
if( SQLITE_OK!=rc ){ |
@@ -564,22 +579,16 @@ static int vtabCallConstructor( |
pTab->pVTable = pVTable; |
for(iCol=0; iCol<pTab->nCol; iCol++){ |
- char *zType = pTab->aCol[iCol].zType; |
+ char *zType = sqlite3ColumnType(&pTab->aCol[iCol], ""); |
int nType; |
int i = 0; |
- if( !zType ){ |
- pTab->tabFlags |= oooHidden; |
- continue; |
- } |
nType = sqlite3Strlen30(zType); |
- if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){ |
- for(i=0; i<nType; i++){ |
- if( (0==sqlite3StrNICmp(" hidden", &zType[i], 7)) |
- && (zType[i+7]=='\0' || zType[i+7]==' ') |
- ){ |
- i++; |
- break; |
- } |
+ for(i=0; i<nType; i++){ |
+ if( 0==sqlite3StrNICmp("hidden", &zType[i], 6) |
+ && (i==0 || zType[i-1]==' ') |
+ && (zType[i+6]=='\0' || zType[i+6]==' ') |
+ ){ |
+ break; |
} |
} |
if( i<nType ){ |
@@ -655,7 +664,7 @@ static int growVTrans(sqlite3 *db){ |
int nBytes = sizeof(sqlite3_vtab *) * (db->nVTrans + ARRAY_INCR); |
aVTrans = sqlite3DbRealloc(db, (void *)db->aVTrans, nBytes); |
if( !aVTrans ){ |
- return SQLITE_NOMEM; |
+ return SQLITE_NOMEM_BKPT; |
} |
memset(&aVTrans[db->nVTrans], 0, sizeof(sqlite3_vtab *)*ARRAY_INCR); |
db->aVTrans = aVTrans; |
@@ -678,7 +687,7 @@ static void addToVTrans(sqlite3 *db, VTable *pVTab){ |
** This function is invoked by the vdbe to call the xCreate method |
** of the virtual table named zTab in database iDb. |
** |
-** If an error occurs, *pzErr is set to point an an English language |
+** If an error occurs, *pzErr is set to point to an English language |
** description of the error and an SQLITE_XXX error code is returned. |
** In this case the caller must call sqlite3DbFree(db, ) on *pzErr. |
*/ |
@@ -688,7 +697,7 @@ int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab, char **pzErr){ |
Module *pMod; |
const char *zMod; |
- pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
assert( pTab && (pTab->tabFlags & TF_Virtual)!=0 && !pTab->pVTable ); |
/* Locate the required virtual table module */ |
@@ -747,7 +756,7 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ |
pParse = sqlite3StackAllocZero(db, sizeof(*pParse)); |
if( pParse==0 ){ |
- rc = SQLITE_NOMEM; |
+ rc = SQLITE_NOMEM_BKPT; |
}else{ |
pParse->declareVtab = 1; |
pParse->db = db; |
@@ -760,10 +769,24 @@ int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){ |
&& (pParse->pNewTable->tabFlags & TF_Virtual)==0 |
){ |
if( !pTab->aCol ){ |
- pTab->aCol = pParse->pNewTable->aCol; |
- pTab->nCol = pParse->pNewTable->nCol; |
- pParse->pNewTable->nCol = 0; |
- pParse->pNewTable->aCol = 0; |
+ Table *pNew = pParse->pNewTable; |
+ Index *pIdx; |
+ pTab->aCol = pNew->aCol; |
+ pTab->nCol = pNew->nCol; |
+ pTab->tabFlags |= pNew->tabFlags & (TF_WithoutRowid|TF_NoVisibleRowid); |
+ pNew->nCol = 0; |
+ pNew->aCol = 0; |
+ assert( pTab->pIndex==0 ); |
+ if( !HasRowid(pNew) && pCtx->pVTable->pMod->pModule->xUpdate!=0 ){ |
+ rc = SQLITE_ERROR; |
+ } |
+ pIdx = pNew->pIndex; |
+ if( pIdx ){ |
+ assert( pIdx->pNext==0 ); |
+ pTab->pIndex = pIdx; |
+ pNew->pIndex = 0; |
+ pIdx->pTable = pTab; |
+ } |
} |
pCtx->bDeclared = 1; |
}else{ |
@@ -798,8 +821,8 @@ int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab){ |
int rc = SQLITE_OK; |
Table *pTab; |
- pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName); |
- if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){ |
+ pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zDbSName); |
+ if( pTab!=0 && ALWAYS(pTab->pVTable!=0) ){ |
VTable *p; |
int (*xDestroy)(sqlite3_vtab *); |
for(p=pTab->pVTable; p; p=p->pNext){ |
@@ -939,7 +962,10 @@ int sqlite3VtabBegin(sqlite3 *db, VTable *pVTab){ |
if( rc==SQLITE_OK ){ |
int iSvpt = db->nStatement + db->nSavepoint; |
addToVTrans(db, pVTab); |
- if( iSvpt ) rc = sqlite3VtabSavepoint(db, SAVEPOINT_BEGIN, iSvpt-1); |
+ if( iSvpt && pModule->xSavepoint ){ |
+ pVTab->iSavepoint = iSvpt; |
+ rc = pModule->xSavepoint(pVTab->pVtab, iSvpt-1); |
+ } |
} |
} |
} |
@@ -1016,7 +1042,7 @@ FuncDef *sqlite3VtabOverloadFunction( |
Table *pTab; |
sqlite3_vtab *pVtab; |
sqlite3_module *pMod; |
- void (*xFunc)(sqlite3_context*,int,sqlite3_value**) = 0; |
+ void (*xSFunc)(sqlite3_context*,int,sqlite3_value**) = 0; |
void *pArg = 0; |
FuncDef *pNew; |
int rc = 0; |
@@ -1044,7 +1070,7 @@ FuncDef *sqlite3VtabOverloadFunction( |
for(z=(unsigned char*)zLowerName; *z; z++){ |
*z = sqlite3UpperToLower[*z]; |
} |
- rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xFunc, &pArg); |
+ rc = pMod->xFindFunction(pVtab, nArg, zLowerName, &xSFunc, &pArg); |
sqlite3DbFree(db, zLowerName); |
} |
if( rc==0 ){ |
@@ -1059,9 +1085,9 @@ FuncDef *sqlite3VtabOverloadFunction( |
return pDef; |
} |
*pNew = *pDef; |
- pNew->zName = (char *)&pNew[1]; |
- memcpy(pNew->zName, pDef->zName, sqlite3Strlen30(pDef->zName)+1); |
- pNew->xFunc = xFunc; |
+ pNew->zName = (const char*)&pNew[1]; |
+ memcpy((char*)&pNew[1], pDef->zName, sqlite3Strlen30(pDef->zName)+1); |
+ pNew->xSFunc = xSFunc; |
pNew->pUserData = pArg; |
pNew->funcFlags |= SQLITE_FUNC_EPHEM; |
return pNew; |
@@ -1088,12 +1114,12 @@ void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){ |
pToplevel->apVtabLock = apVtabLock; |
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab; |
}else{ |
- pToplevel->db->mallocFailed = 1; |
+ sqlite3OomFault(pToplevel->db); |
} |
} |
/* |
-** Check to see if virtual tale module pMod can be have an eponymous |
+** Check to see if virtual table module pMod can be have an eponymous |
** virtual table instance. If it can, create one if one does not already |
** exist. Return non-zero if the eponymous virtual table instance exists |
** when this routine returns, and return zero if it does not exist. |
@@ -1110,18 +1136,19 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ |
const sqlite3_module *pModule = pMod->pModule; |
Table *pTab; |
char *zErr = 0; |
- int nName; |
int rc; |
sqlite3 *db = pParse->db; |
if( pMod->pEpoTab ) return 1; |
if( pModule->xCreate!=0 && pModule->xCreate!=pModule->xConnect ) return 0; |
- nName = sqlite3Strlen30(pMod->zName) + 1; |
- pTab = sqlite3DbMallocZero(db, sizeof(Table) + nName); |
+ pTab = sqlite3DbMallocZero(db, sizeof(Table)); |
if( pTab==0 ) return 0; |
+ pTab->zName = sqlite3DbStrDup(db, pMod->zName); |
+ if( pTab->zName==0 ){ |
+ sqlite3DbFree(db, pTab); |
+ return 0; |
+ } |
pMod->pEpoTab = pTab; |
- pTab->zName = (char*)&pTab[1]; |
- memcpy(pTab->zName, pMod->zName, nName); |
- pTab->nRef = 1; |
+ pTab->nTabRef = 1; |
pTab->pSchema = db->aDb[0].pSchema; |
pTab->tabFlags |= TF_Virtual; |
pTab->nModuleArg = 0; |
@@ -1146,9 +1173,11 @@ int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){ |
void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){ |
Table *pTab = pMod->pEpoTab; |
if( pTab!=0 ){ |
- sqlite3DeleteColumnNames(db, pTab); |
- sqlite3VtabClear(db, pTab); |
- sqlite3DbFree(db, pTab); |
+ /* Mark the table as Ephemeral prior to deleting it, so that the |
+ ** sqlite3DeleteTable() routine will know that it is not stored in |
+ ** the schema. */ |
+ pTab->tabFlags |= TF_Ephemeral; |
+ sqlite3DeleteTable(db, pTab); |
pMod->pEpoTab = 0; |
} |
} |