1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-07 02:42:48 +03:00

Change the way token memory is allocated in an effort to fix ticket #136.

There is now a memory leak when using views of views. (CVS 725)

FossilOrigin-Name: 22d8726e61eec0e53893f492cb2163824b87a23e
This commit is contained in:
drh
2002-08-24 18:24:51 +00:00
parent 79983d03e8
commit 4b59ab5e64
18 changed files with 515 additions and 343 deletions

View File

@@ -12,6 +12,24 @@
*/
#include "sqliteInt.h"
/*
** Delete a linked list of TriggerStep structures.
*/
static void sqliteDeleteTriggerStep(TriggerStep *pTriggerStep){
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
if( pTmp->target.dyn ) sqliteFree(pTmp->target.z);
sqliteExprDelete(pTmp->pWhere);
sqliteExprListDelete(pTmp->pExprList);
sqliteSelectDelete(pTmp->pSelect);
sqliteIdListDelete(pTmp->pIdList);
sqliteFree(pTmp);
}
}
/*
** This is called by the parser when it sees a CREATE TRIGGER statement. See
** comments surrounding struct Trigger in sqliteInt.h for a description of
@@ -27,13 +45,10 @@ void sqliteCreateTrigger(
int foreach, /* One of TK_ROW or TK_STATEMENT */
Expr *pWhen, /* WHEN clause */
TriggerStep *pStepList, /* The triggered program */
char const *zData, /* The string data to make persistent */
int zDataLen
Token *pAll /* Token that describes the complete CREATE TRIGGER */
){
Trigger *nt;
Table *tab;
int offset;
TriggerStep *ss;
/* Check that:
** 1. the trigger name does not already exist.
@@ -98,28 +113,15 @@ void sqliteCreateTrigger(
if( nt==0 ) goto trigger_cleanup;
nt->name = sqliteStrNDup(pName->z, pName->n);
nt->table = sqliteStrNDup(pTableName->z, pTableName->n);
nt->strings = sqliteStrNDup(zData, zDataLen);
if( sqlite_malloc_failed ) goto trigger_cleanup;
nt->op = op;
nt->tr_tm = tr_tm;
nt->pWhen = pWhen;
nt->pColumns = pColumns;
nt->pWhen = sqliteExprDup(pWhen);
sqliteExprDelete(pWhen);
nt->pColumns = sqliteIdListDup(pColumns);
sqliteIdListDelete(pColumns);
nt->foreach = foreach;
nt->step_list = pStepList;
offset = (int)(nt->strings - zData);
sqliteExprMoveStrings(nt->pWhen, offset);
ss = nt->step_list;
while( ss ){
sqliteSelectMoveStrings(ss->pSelect, offset);
if( ss->target.z ){
ss->target.z += offset;
}
sqliteExprMoveStrings(ss->pWhere, offset);
sqliteExprListMoveStrings(ss->pExprList, offset);
ss = ss->pNext;
}
/* if we are not initializing, and this trigger is not on a TEMP table,
** build the sqlite_master entry
@@ -148,7 +150,7 @@ void sqliteCreateTrigger(
P3_STATIC);
sqliteVdbeChangeP3(v, addr+2, nt->name, 0);
sqliteVdbeChangeP3(v, addr+3, nt->table, 0);
sqliteVdbeChangeP3(v, addr+5, nt->strings, 0);
sqliteVdbeChangeP3(v, addr+5, pAll->z, pAll->n);
if( !tab->isTemp ){
sqliteChangeCookie(pParse->db, v);
}
@@ -165,7 +167,6 @@ void sqliteCreateTrigger(
tab->pTrigger = nt;
return;
}else{
sqliteFree(nt->strings);
sqliteFree(nt->name);
sqliteFree(nt->table);
sqliteFree(nt);
@@ -175,20 +176,43 @@ trigger_cleanup:
sqliteIdListDelete(pColumns);
sqliteExprDelete(pWhen);
{
TriggerStep * pp;
TriggerStep * nn;
sqliteDeleteTriggerStep(pStepList);
}
pp = pStepList;
while( pp ){
nn = pp->pNext;
sqliteExprDelete(pp->pWhere);
sqliteExprListDelete(pp->pExprList);
sqliteSelectDelete(pp->pSelect);
sqliteIdListDelete(pp->pIdList);
sqliteFree(pp);
pp = nn;
}
/*
** Make a copy of all components of the given trigger step. This has
** the effect of copying all Expr.token.z values into memory obtained
** from sqliteMalloc(). As initially created, the Expr.token.z values
** all point to the input string that was fed to the parser. But that
** string is ephemeral - it will go away as soon as the sqlite_exec()
** call that started the parser exits. This routine makes a persistent
** copy of all the Expr.token.z strings so that the TriggerStep structure
** will be valid even after the sqlite_exec() call returns.
*/
static void sqlitePersistTriggerStep(TriggerStep *p){
if( p->target.z ){
p->target.z = sqliteStrNDup(p->target.z, p->target.n);
p->target.dyn = 1;
}
if( p->pSelect ){
Select *pNew = sqliteSelectDup(p->pSelect);
sqliteSelectDelete(p->pSelect);
p->pSelect = pNew;
}
if( p->pWhere ){
Expr *pNew = sqliteExprDup(p->pWhere);
sqliteExprDelete(p->pWhere);
p->pWhere = pNew;
}
if( p->pExprList ){
ExprList *pNew = sqliteExprListDup(p->pExprList);
sqliteExprListDelete(p->pExprList);
p->pExprList = pNew;
}
if( p->pIdList ){
IdList *pNew = sqliteIdListDup(p->pIdList);
sqliteIdListDelete(p->pIdList);
p->pIdList = pNew;
}
}
@@ -206,6 +230,7 @@ TriggerStep *sqliteTriggerSelectStep(Select *pSelect){
pTriggerStep->op = TK_SELECT;
pTriggerStep->pSelect = pSelect;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
@@ -236,6 +261,7 @@ TriggerStep *sqliteTriggerInsertStep(
pTriggerStep->pIdList = pColumn;
pTriggerStep->pExprList = pEList;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
@@ -259,6 +285,7 @@ TriggerStep *sqliteTriggerUpdateStep(
pTriggerStep->pExprList = pEList;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = orconf;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
@@ -276,6 +303,7 @@ TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
pTriggerStep->target = *pTableName;
pTriggerStep->pWhere = pWhere;
pTriggerStep->orconf = OE_Default;
sqlitePersistTriggerStep(pTriggerStep);
return pTriggerStep;
}
@@ -286,24 +314,11 @@ TriggerStep *sqliteTriggerDeleteStep(Token *pTableName, Expr *pWhere){
void sqliteDeleteTrigger(Trigger *pTrigger){
TriggerStep *pTriggerStep;
pTriggerStep = pTrigger->step_list;
while( pTriggerStep ){
TriggerStep * pTmp = pTriggerStep;
pTriggerStep = pTriggerStep->pNext;
sqliteExprDelete(pTmp->pWhere);
sqliteExprListDelete(pTmp->pExprList);
sqliteSelectDelete(pTmp->pSelect);
sqliteIdListDelete(pTmp->pIdList);
sqliteFree(pTmp);
}
sqliteDeleteTriggerStep(pTrigger->step_list);
sqliteFree(pTrigger->name);
sqliteFree(pTrigger->table);
sqliteExprDelete(pTrigger->pWhen);
sqliteIdListDelete(pTrigger->pColumns);
sqliteFree(pTrigger->strings);
sqliteFree(pTrigger);
}