mirror of
https://github.com/php/php-src.git
synced 2025-08-20 01:14:28 +02:00
MFB: Upgraded libsqlite in pdo_sqlite to 3.3.7
This commit is contained in:
parent
3717342c9f
commit
5c01690d9b
83 changed files with 17303 additions and 7927 deletions
|
@ -11,7 +11,6 @@
|
|||
*
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "vdbe.h"
|
||||
|
||||
#ifndef SQLITE_OMIT_TRIGGER
|
||||
/*
|
||||
|
@ -59,10 +58,13 @@ void sqlite3BeginTrigger(
|
|||
int iDb; /* The database to store the trigger in */
|
||||
Token *pName; /* The unqualified db name */
|
||||
DbFixer sFix;
|
||||
int iTabDb;
|
||||
|
||||
assert( pName1!=0 ); /* pName1->z might be NULL, but not pName1 itself */
|
||||
assert( pName2!=0 );
|
||||
if( isTemp ){
|
||||
/* If TEMP was specified, then the trigger name may not be qualified. */
|
||||
if( pName2 && pName2->n>0 ){
|
||||
if( pName2->n>0 ){
|
||||
sqlite3ErrorMsg(pParse, "temporary trigger may not have qualified name");
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
|
@ -81,14 +83,16 @@ void sqlite3BeginTrigger(
|
|||
** If sqlite3SrcListLookup() returns 0, indicating the table does not
|
||||
** exist, the error is caught by the block below.
|
||||
*/
|
||||
if( !pTableName || sqlite3_malloc_failed ) goto trigger_cleanup;
|
||||
if( !pTableName || sqlite3MallocFailed() ){
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
pTab = sqlite3SrcListLookup(pParse, pTableName);
|
||||
if( pName2->n==0 && pTab && pTab->iDb==1 ){
|
||||
if( pName2->n==0 && pTab && pTab->pSchema==db->aDb[1].pSchema ){
|
||||
iDb = 1;
|
||||
}
|
||||
|
||||
/* Ensure the table name matches database name and that the table exists */
|
||||
if( sqlite3_malloc_failed ) goto trigger_cleanup;
|
||||
if( sqlite3MallocFailed() ) goto trigger_cleanup;
|
||||
assert( pTableName->nSrc==1 );
|
||||
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", pName) &&
|
||||
sqlite3FixSrcList(&sFix, pTableName) ){
|
||||
|
@ -99,6 +103,10 @@ void sqlite3BeginTrigger(
|
|||
/* The table does not exist. */
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if( IsVirtual(pTab) ){
|
||||
sqlite3ErrorMsg(pParse, "cannot create triggers on virtual tables");
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
|
||||
/* Check that the trigger name is not reserved and that no trigger of the
|
||||
** specified name exists */
|
||||
|
@ -106,7 +114,7 @@ void sqlite3BeginTrigger(
|
|||
if( !zName || SQLITE_OK!=sqlite3CheckObjectName(pParse, zName) ){
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if( sqlite3HashFind(&(db->aDb[iDb].trigHash), zName,pName->n+1) ){
|
||||
if( sqlite3HashFind(&(db->aDb[iDb].pSchema->trigHash), zName,strlen(zName)) ){
|
||||
sqlite3ErrorMsg(pParse, "trigger %T already exists", pName);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
|
@ -131,17 +139,18 @@ void sqlite3BeginTrigger(
|
|||
" trigger on table: %S", pTableName, 0);
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
iTabDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code = SQLITE_CREATE_TRIGGER;
|
||||
const char *zDb = db->aDb[pTab->iDb].zName;
|
||||
const char *zDb = db->aDb[iTabDb].zName;
|
||||
const char *zDbTrig = isTemp ? db->aDb[1].zName : zDb;
|
||||
if( pTab->iDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
|
||||
if( iTabDb==1 || isTemp ) code = SQLITE_CREATE_TEMP_TRIGGER;
|
||||
if( sqlite3AuthCheck(pParse, code, zName, pTab->zName, zDbTrig) ){
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(pTab->iDb),0,zDb)){
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, SCHEMA_TABLE(iTabDb),0,zDb)){
|
||||
goto trigger_cleanup;
|
||||
}
|
||||
}
|
||||
|
@ -162,8 +171,8 @@ void sqlite3BeginTrigger(
|
|||
pTrigger->name = zName;
|
||||
zName = 0;
|
||||
pTrigger->table = sqliteStrDup(pTableName->a[0].zName);
|
||||
pTrigger->iDb = iDb;
|
||||
pTrigger->iTabDb = pTab->iDb;
|
||||
pTrigger->pSchema = db->aDb[iDb].pSchema;
|
||||
pTrigger->pTabSchema = pTab->pSchema;
|
||||
pTrigger->op = op;
|
||||
pTrigger->tr_tm = tr_tm==TK_BEFORE ? TRIGGER_BEFORE : TRIGGER_AFTER;
|
||||
pTrigger->pWhen = sqlite3ExprDup(pWhen);
|
||||
|
@ -197,16 +206,18 @@ void sqlite3FinishTrigger(
|
|||
Trigger *pTrig = 0; /* The trigger whose construction is finishing up */
|
||||
sqlite3 *db = pParse->db; /* The database */
|
||||
DbFixer sFix;
|
||||
int iDb; /* Database containing the trigger */
|
||||
|
||||
pTrig = pParse->pNewTrigger;
|
||||
pParse->pNewTrigger = 0;
|
||||
if( pParse->nErr || pTrig==0 ) goto triggerfinish_cleanup;
|
||||
if( pParse->nErr || !pTrig ) goto triggerfinish_cleanup;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrig->pSchema);
|
||||
pTrig->step_list = pStepList;
|
||||
while( pStepList ){
|
||||
pStepList->pTrig = pTrig;
|
||||
pStepList = pStepList->pNext;
|
||||
}
|
||||
if( sqlite3FixInit(&sFix, pParse, pTrig->iDb, "trigger", &pTrig->nameToken)
|
||||
if( sqlite3FixInit(&sFix, pParse, iDb, "trigger", &pTrig->nameToken)
|
||||
&& sqlite3FixTriggerStep(&sFix, pTrig->step_list) ){
|
||||
goto triggerfinish_cleanup;
|
||||
}
|
||||
|
@ -224,7 +235,7 @@ void sqlite3FinishTrigger(
|
|||
{ OP_String8, 0, 0, "CREATE TRIGGER "},
|
||||
{ OP_String8, 0, 0, 0 }, /* 6: SQL */
|
||||
{ OP_Concat, 0, 0, 0 },
|
||||
{ OP_MakeRecord, 5, 0, "tttit" },
|
||||
{ OP_MakeRecord, 5, 0, "aaada" },
|
||||
{ OP_Insert, 0, 0, 0 },
|
||||
};
|
||||
int addr;
|
||||
|
@ -233,28 +244,30 @@ void sqlite3FinishTrigger(
|
|||
/* Make an entry in the sqlite_master table */
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
if( v==0 ) goto triggerfinish_cleanup;
|
||||
sqlite3BeginWriteOperation(pParse, 0, pTrig->iDb);
|
||||
sqlite3OpenMasterTable(v, pTrig->iDb);
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3OpenMasterTable(pParse, iDb);
|
||||
addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig);
|
||||
sqlite3VdbeChangeP3(v, addr+2, pTrig->name, 0);
|
||||
sqlite3VdbeChangeP3(v, addr+3, pTrig->table, 0);
|
||||
sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n);
|
||||
sqlite3ChangeCookie(db, v, pTrig->iDb);
|
||||
sqlite3VdbeChangeP3(v, addr+6, (char*)pAll->z, pAll->n);
|
||||
sqlite3ChangeCookie(db, v, iDb);
|
||||
sqlite3VdbeAddOp(v, OP_Close, 0, 0);
|
||||
sqlite3VdbeOp3(v, OP_ParseSchema, pTrig->iDb, 0,
|
||||
sqlite3VdbeOp3(v, OP_ParseSchema, iDb, 0,
|
||||
sqlite3MPrintf("type='trigger' AND name='%q'", pTrig->name), P3_DYNAMIC);
|
||||
}
|
||||
|
||||
if( db->init.busy ){
|
||||
int n;
|
||||
Table *pTab;
|
||||
Trigger *pDel;
|
||||
pDel = sqlite3HashInsert(&db->aDb[pTrig->iDb].trigHash,
|
||||
pTrig->name, strlen(pTrig->name)+1, pTrig);
|
||||
pDel = sqlite3HashInsert(&db->aDb[iDb].pSchema->trigHash,
|
||||
pTrig->name, strlen(pTrig->name), pTrig);
|
||||
if( pDel ){
|
||||
assert( sqlite3_malloc_failed && pDel==pTrig );
|
||||
assert( sqlite3MallocFailed() && pDel==pTrig );
|
||||
goto triggerfinish_cleanup;
|
||||
}
|
||||
pTab = sqlite3LocateTable(pParse,pTrig->table,db->aDb[pTrig->iTabDb].zName);
|
||||
n = strlen(pTrig->table) + 1;
|
||||
pTab = sqlite3HashFind(&pTrig->pTabSchema->tblHash, pTrig->table, n);
|
||||
assert( pTab!=0 );
|
||||
pTrig->pNext = pTab->pTrigger;
|
||||
pTab->pTrigger = pTrig;
|
||||
|
@ -279,7 +292,7 @@ triggerfinish_cleanup:
|
|||
*/
|
||||
static void sqlitePersistTriggerStep(TriggerStep *p){
|
||||
if( p->target.z ){
|
||||
p->target.z = sqliteStrNDup(p->target.z, p->target.n);
|
||||
p->target.z = (u8*)sqliteStrNDup((char*)p->target.z, p->target.n);
|
||||
p->target.dyn = 1;
|
||||
}
|
||||
if( p->pSelect ){
|
||||
|
@ -313,7 +326,10 @@ static void sqlitePersistTriggerStep(TriggerStep *p){
|
|||
*/
|
||||
TriggerStep *sqlite3TriggerSelectStep(Select *pSelect){
|
||||
TriggerStep *pTriggerStep = sqliteMalloc(sizeof(TriggerStep));
|
||||
if( pTriggerStep==0 ) return 0;
|
||||
if( pTriggerStep==0 ) {
|
||||
sqlite3SelectDelete(pSelect);
|
||||
return 0;
|
||||
}
|
||||
|
||||
pTriggerStep->op = TK_SELECT;
|
||||
pTriggerStep->pSelect = pSelect;
|
||||
|
@ -431,7 +447,7 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
|
|||
int nName;
|
||||
sqlite3 *db = pParse->db;
|
||||
|
||||
if( sqlite3_malloc_failed ) goto drop_trigger_cleanup;
|
||||
if( sqlite3MallocFailed() ) goto drop_trigger_cleanup;
|
||||
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
|
||||
goto drop_trigger_cleanup;
|
||||
}
|
||||
|
@ -443,14 +459,14 @@ void sqlite3DropTrigger(Parse *pParse, SrcList *pName){
|
|||
for(i=OMIT_TEMPDB; i<db->nDb; i++){
|
||||
int j = (i<2) ? i^1 : i; /* Search TEMP before MAIN */
|
||||
if( zDb && sqlite3StrICmp(db->aDb[j].zName, zDb) ) continue;
|
||||
pTrigger = sqlite3HashFind(&(db->aDb[j].trigHash), zName, nName+1);
|
||||
pTrigger = sqlite3HashFind(&(db->aDb[j].pSchema->trigHash), zName, nName);
|
||||
if( pTrigger ) break;
|
||||
}
|
||||
if( !pTrigger ){
|
||||
sqlite3ErrorMsg(pParse, "no such trigger: %S", pName, 0);
|
||||
goto drop_trigger_cleanup;
|
||||
}
|
||||
sqlite3DropTriggerPtr(pParse, pTrigger, 0);
|
||||
sqlite3DropTriggerPtr(pParse, pTrigger);
|
||||
|
||||
drop_trigger_cleanup:
|
||||
sqlite3SrcListDelete(pName);
|
||||
|
@ -460,27 +476,26 @@ drop_trigger_cleanup:
|
|||
** Return a pointer to the Table structure for the table that a trigger
|
||||
** is set on.
|
||||
*/
|
||||
static Table *tableOfTrigger(sqlite3 *db, Trigger *pTrigger){
|
||||
return sqlite3FindTable(db,pTrigger->table,db->aDb[pTrigger->iTabDb].zName);
|
||||
static Table *tableOfTrigger(Trigger *pTrigger){
|
||||
int n = strlen(pTrigger->table) + 1;
|
||||
return sqlite3HashFind(&pTrigger->pTabSchema->tblHash, pTrigger->table, n);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Drop a trigger given a pointer to that trigger. If nested is false,
|
||||
** then also generate code to remove the trigger from the SQLITE_MASTER
|
||||
** table.
|
||||
** Drop a trigger given a pointer to that trigger.
|
||||
*/
|
||||
void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
|
||||
void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger){
|
||||
Table *pTable;
|
||||
Vdbe *v;
|
||||
sqlite3 *db = pParse->db;
|
||||
int iDb;
|
||||
|
||||
iDb = pTrigger->iDb;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pTrigger->pSchema);
|
||||
assert( iDb>=0 && iDb<db->nDb );
|
||||
pTable = tableOfTrigger(db, pTrigger);
|
||||
assert(pTable);
|
||||
assert( pTable->iDb==iDb || iDb==1 );
|
||||
pTable = tableOfTrigger(pTrigger);
|
||||
assert( pTable );
|
||||
assert( pTable->pSchema==pTrigger->pSchema || iDb==1 );
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
{
|
||||
int code = SQLITE_DROP_TRIGGER;
|
||||
|
@ -496,7 +511,8 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
|
|||
|
||||
/* Generate code to destroy the database record of the trigger.
|
||||
*/
|
||||
if( pTable!=0 && (v = sqlite3GetVdbe(pParse))!=0 ){
|
||||
assert( pTable!=0 );
|
||||
if( (v = sqlite3GetVdbe(pParse))!=0 ){
|
||||
int base;
|
||||
static const VdbeOpList dropTrigger[] = {
|
||||
{ OP_Rewind, 0, ADDR(9), 0},
|
||||
|
@ -511,7 +527,7 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
|
|||
};
|
||||
|
||||
sqlite3BeginWriteOperation(pParse, 0, iDb);
|
||||
sqlite3OpenMasterTable(v, iDb);
|
||||
sqlite3OpenMasterTable(pParse, iDb);
|
||||
base = sqlite3VdbeAddOpList(v, ArraySize(dropTrigger), dropTrigger);
|
||||
sqlite3VdbeChangeP3(v, base+1, pTrigger->name, 0);
|
||||
sqlite3ChangeCookie(db, v, iDb);
|
||||
|
@ -526,9 +542,10 @@ void sqlite3DropTriggerPtr(Parse *pParse, Trigger *pTrigger, int nested){
|
|||
void sqlite3UnlinkAndDeleteTrigger(sqlite3 *db, int iDb, const char *zName){
|
||||
Trigger *pTrigger;
|
||||
int nName = strlen(zName);
|
||||
pTrigger = sqlite3HashInsert(&(db->aDb[iDb].trigHash), zName, nName+1, 0);
|
||||
pTrigger = sqlite3HashInsert(&(db->aDb[iDb].pSchema->trigHash),
|
||||
zName, nName, 0);
|
||||
if( pTrigger ){
|
||||
Table *pTable = tableOfTrigger(db, pTrigger);
|
||||
Table *pTable = tableOfTrigger(pTrigger);
|
||||
assert( pTable!=0 );
|
||||
if( pTable->pTrigger == pTrigger ){
|
||||
pTable->pTrigger = pTrigger->pNext;
|
||||
|
@ -581,19 +598,13 @@ int sqlite3TriggersExist(
|
|||
int op, /* one of TK_DELETE, TK_INSERT, TK_UPDATE */
|
||||
ExprList *pChanges /* Columns that change in an UPDATE statement */
|
||||
){
|
||||
Trigger *pTrigger = pTab->pTrigger;
|
||||
Trigger *pTrigger;
|
||||
int mask = 0;
|
||||
|
||||
pTrigger = IsVirtual(pTab) ? 0 : pTab->pTrigger;
|
||||
while( pTrigger ){
|
||||
if( pTrigger->op==op && checkColumnOverLap(pTrigger->pColumns, pChanges) ){
|
||||
TriggerStack *ss;
|
||||
ss = pParse->trigStack;
|
||||
while( ss && ss->pTrigger!=pTab->pTrigger ){
|
||||
ss = ss->pNext;
|
||||
}
|
||||
if( ss==0 ){
|
||||
mask |= pTrigger->tr_tm;
|
||||
}
|
||||
mask |= pTrigger->tr_tm;
|
||||
}
|
||||
pTrigger = pTrigger->pNext;
|
||||
}
|
||||
|
@ -618,11 +629,11 @@ static SrcList *targetSrcList(
|
|||
int iDb; /* Index of the database to use */
|
||||
SrcList *pSrc; /* SrcList to be returned */
|
||||
|
||||
iDb = pStep->pTrig->iDb;
|
||||
iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
|
||||
if( iDb==0 || iDb>=2 ){
|
||||
assert( iDb<pParse->db->nDb );
|
||||
sDb.z = pParse->db->aDb[iDb].zName;
|
||||
sDb.n = strlen(sDb.z);
|
||||
sDb.z = (u8*)pParse->db->aDb[iDb].zName;
|
||||
sDb.n = strlen((char*)sDb.z);
|
||||
pSrc = sqlite3SrcListAppend(0, &sDb, &pStep->target);
|
||||
} else {
|
||||
pSrc = sqlite3SrcListAppend(0, &pStep->target, 0);
|
||||
|
@ -731,8 +742,7 @@ int sqlite3CodeRowTrigger(
|
|||
int orconf, /* ON CONFLICT policy */
|
||||
int ignoreJump /* Instruction to jump to for RAISE(IGNORE) */
|
||||
){
|
||||
Trigger *pTrigger;
|
||||
TriggerStack *pStack;
|
||||
Trigger *p;
|
||||
TriggerStack trigStackEntry;
|
||||
|
||||
assert(op == TK_UPDATE || op == TK_INSERT || op == TK_DELETE);
|
||||
|
@ -740,22 +750,28 @@ int sqlite3CodeRowTrigger(
|
|||
|
||||
assert(newIdx != -1 || oldIdx != -1);
|
||||
|
||||
pTrigger = pTab->pTrigger;
|
||||
while( pTrigger ){
|
||||
for(p=pTab->pTrigger; p; p=p->pNext){
|
||||
int fire_this = 0;
|
||||
|
||||
/* determine whether we should code this trigger */
|
||||
if( pTrigger->op == op && pTrigger->tr_tm == tr_tm ){
|
||||
fire_this = 1;
|
||||
for(pStack=pParse->trigStack; pStack; pStack=pStack->pNext){
|
||||
if( pStack->pTrigger==pTrigger ){
|
||||
fire_this = 0;
|
||||
}
|
||||
/* Determine whether we should code this trigger */
|
||||
if(
|
||||
p->op==op &&
|
||||
p->tr_tm==tr_tm &&
|
||||
(p->pSchema==p->pTabSchema || p->pSchema==pParse->db->aDb[1].pSchema) &&
|
||||
(op!=TK_UPDATE||!p->pColumns||checkColumnOverLap(p->pColumns,pChanges))
|
||||
){
|
||||
TriggerStack *pS; /* Pointer to trigger-stack entry */
|
||||
for(pS=pParse->trigStack; pS && p!=pS->pTrigger; pS=pS->pNext){}
|
||||
if( !pS ){
|
||||
fire_this = 1;
|
||||
}
|
||||
if( op == TK_UPDATE && pTrigger->pColumns &&
|
||||
!checkColumnOverLap(pTrigger->pColumns, pChanges) ){
|
||||
fire_this = 0;
|
||||
#if 0 /* Give no warning for recursive triggers. Just do not do them */
|
||||
else{
|
||||
sqlite3ErrorMsg(pParse, "recursive triggers not supported (%s)",
|
||||
p->name);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if( fire_this ){
|
||||
|
@ -768,18 +784,18 @@ int sqlite3CodeRowTrigger(
|
|||
sNC.pParse = pParse;
|
||||
|
||||
/* Push an entry on to the trigger stack */
|
||||
trigStackEntry.pTrigger = pTrigger;
|
||||
trigStackEntry.pTrigger = p;
|
||||
trigStackEntry.newIdx = newIdx;
|
||||
trigStackEntry.oldIdx = oldIdx;
|
||||
trigStackEntry.pTab = pTab;
|
||||
trigStackEntry.pNext = pParse->trigStack;
|
||||
trigStackEntry.ignoreJump = ignoreJump;
|
||||
pParse->trigStack = &trigStackEntry;
|
||||
sqlite3AuthContextPush(pParse, &sContext, pTrigger->name);
|
||||
sqlite3AuthContextPush(pParse, &sContext, p->name);
|
||||
|
||||
/* code the WHEN clause */
|
||||
endTrigger = sqlite3VdbeMakeLabel(pParse->pVdbe);
|
||||
whenExpr = sqlite3ExprDup(pTrigger->pWhen);
|
||||
whenExpr = sqlite3ExprDup(p->pWhen);
|
||||
if( sqlite3ExprResolveNames(&sNC, whenExpr) ){
|
||||
pParse->trigStack = trigStackEntry.pNext;
|
||||
sqlite3ExprDelete(whenExpr);
|
||||
|
@ -788,7 +804,7 @@ int sqlite3CodeRowTrigger(
|
|||
sqlite3ExprIfFalse(pParse, whenExpr, endTrigger, 1);
|
||||
sqlite3ExprDelete(whenExpr);
|
||||
|
||||
codeTriggerProgram(pParse, pTrigger->step_list, orconf);
|
||||
codeTriggerProgram(pParse, p->step_list, orconf);
|
||||
|
||||
/* Pop the entry off the trigger stack */
|
||||
pParse->trigStack = trigStackEntry.pNext;
|
||||
|
@ -796,7 +812,6 @@ int sqlite3CodeRowTrigger(
|
|||
|
||||
sqlite3VdbeResolveLabel(pParse->pVdbe, endTrigger);
|
||||
}
|
||||
pTrigger = pTrigger->pNext;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue