/ Check-in [9aa30342]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Experimental code to measure memory consumed by database schemas and prepared statements.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | experimental
Files: files | file ages | folders
SHA1:9aa30342f4de4eff630520ea8e07ad253d3f0877
User & Date: dan 2010-07-24 11:28:29
Context
2010-07-26
11:07
Make sure all memory from sqlite3DbMalloc() is freed by sqlite3DbFree() and all memory from sqlite3_malloc() is freed by sqlite3_free(). check-in: 629e38a8 user: drh tags: experimental
2010-07-24
11:28
Experimental code to measure memory consumed by database schemas and prepared statements. check-in: 9aa30342 user: dan tags: experimental
2010-07-23
22:26
Fix a typo in the OS/2 vfs code. check-in: a6bb2108 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/analyze.c.

   486    486     return 0;
   487    487   }
   488    488   
   489    489   /*
   490    490   ** If the Index.aSample variable is not NULL, delete the aSample[] array
   491    491   ** and its contents.
   492    492   */
   493         -void sqlite3DeleteIndexSamples(Index *pIdx){
          493  +void sqlite3DeleteIndexSamples(sqlite3 *db, Index *pIdx){
   494    494   #ifdef SQLITE_ENABLE_STAT2
   495    495     if( pIdx->aSample ){
   496    496       int j;
   497    497       for(j=0; j<SQLITE_INDEX_SAMPLES; j++){
   498    498         IndexSample *p = &pIdx->aSample[j];
   499    499         if( p->eType==SQLITE_TEXT || p->eType==SQLITE_BLOB ){
   500         -        sqlite3_free(p->u.z);
          500  +        sqlite3DbFree(db, p->u.z);
   501    501         }
   502    502       }
   503         -    sqlite3DbFree(0, pIdx->aSample);
   504         -    pIdx->aSample = 0;
          503  +    sqlite3DbFree(db, pIdx->aSample);
   505    504     }
   506    505   #else
   507    506     UNUSED_PARAMETER(pIdx);
   508    507   #endif
   509    508   }
   510    509   
   511    510   /*
................................................................................
   538    537     assert( db->aDb[iDb].pBt!=0 );
   539    538     assert( sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
   540    539   
   541    540     /* Clear any prior statistics */
   542    541     for(i=sqliteHashFirst(&db->aDb[iDb].pSchema->idxHash);i;i=sqliteHashNext(i)){
   543    542       Index *pIdx = sqliteHashData(i);
   544    543       sqlite3DefaultRowEst(pIdx);
   545         -    sqlite3DeleteIndexSamples(pIdx);
          544  +    sqlite3DeleteIndexSamples(db, pIdx);
          545  +    pIdx->aSample = 0;
   546    546     }
   547    547   
   548    548     /* Check to make sure the sqlite_stat1 table exists */
   549    549     sInfo.db = db;
   550    550     sInfo.zDatabase = db->aDb[iDb].zName;
   551    551     if( sqlite3FindTable(db, "sqlite_stat1", sInfo.zDatabase)==0 ){
   552    552       return SQLITE_ERROR;

Changes to src/build.c.

   343    343   }
   344    344   
   345    345   /*
   346    346   ** Reclaim the memory used by an index
   347    347   */
   348    348   static void freeIndex(sqlite3 *db, Index *p){
   349    349   #ifndef SQLITE_OMIT_ANALYZE
   350         -  sqlite3DeleteIndexSamples(p);
          350  +  sqlite3DeleteIndexSamples(db, p);
   351    351   #endif
   352    352     sqlite3DbFree(db, p->zColAff);
   353    353     sqlite3DbFree(db, p);
   354    354   }
   355    355   
   356         -/*
   357         -** Remove the given index from the index hash table, and free
   358         -** its memory structures.
   359         -**
   360         -** The index is removed from the database hash tables but
   361         -** it is not unlinked from the Table that it indexes.
   362         -** Unlinking from the Table must be done by the calling function.
   363         -*/
   364         -static void sqlite3DeleteIndex(sqlite3 *db, Index *p){
   365         -  Index *pOld;
   366         -  const char *zName = p->zName;
   367         -
   368         -  pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName,
   369         -                           sqlite3Strlen30(zName), 0);
   370         -  assert( pOld==0 || pOld==p );
   371         -  freeIndex(db, p);
   372         -}
   373         -
   374    356   /*
   375    357   ** For the index called zIdxName which is found in the database iDb,
   376    358   ** unlike that index from its Table then remove the index from
   377    359   ** the index hash table and free all memory structures associated
   378    360   ** with the index.
   379    361   */
   380    362   void sqlite3UnlinkAndDeleteIndex(sqlite3 *db, int iDb, const char *zIdxName){
................................................................................
   464    446   ** This routine is called when a commit occurs.
   465    447   */
   466    448   void sqlite3CommitInternalChanges(sqlite3 *db){
   467    449     db->flags &= ~SQLITE_InternChanges;
   468    450   }
   469    451   
   470    452   /*
   471         -** Clear the column names from a table or view.
          453  +** Delete memory allocated for the column names of a table or view (the
          454  +** Table.aCol[] array).
   472    455   */
   473         -static void sqliteResetColumnNames(sqlite3 *db, Table *pTable){
          456  +static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){
   474    457     int i;
   475    458     Column *pCol;
   476    459     assert( pTable!=0 );
   477    460     if( (pCol = pTable->aCol)!=0 ){
   478    461       for(i=0; i<pTable->nCol; i++, pCol++){
   479    462         sqlite3DbFree(db, pCol->zName);
   480    463         sqlite3ExprDelete(db, pCol->pDflt);
   481    464         sqlite3DbFree(db, pCol->zDflt);
   482    465         sqlite3DbFree(db, pCol->zType);
   483    466         sqlite3DbFree(db, pCol->zColl);
   484    467       }
   485    468       sqlite3DbFree(db, pTable->aCol);
   486    469     }
   487         -  pTable->aCol = 0;
   488         -  pTable->nCol = 0;
   489    470   }
   490    471   
   491    472   /*
   492    473   ** Remove the memory data structures associated with the given
   493    474   ** Table.  No changes are made to disk by this routine.
   494    475   **
   495    476   ** This routine just deletes the data structure.  It does not unlink
................................................................................
   496    477   ** the table data structure from the hash table.  But it does destroy
   497    478   ** memory structures of the indices and foreign keys associated with 
   498    479   ** the table.
   499    480   */
   500    481   void sqlite3DeleteTable(sqlite3 *db, Table *pTable){
   501    482     Index *pIndex, *pNext;
   502    483   
   503         -  if( pTable==0 ) return;
          484  +  assert( !pTable || pTable->nRef>0 );
   504    485   
   505    486     /* Do not delete the table until the reference count reaches zero. */
   506         -  pTable->nRef--;
   507         -  if( pTable->nRef>0 ){
   508         -    return;
   509         -  }
   510         -  assert( pTable->nRef==0 );
          487  +  if( !pTable ) return;
          488  +  if( ((!db || db->pnBytesFreed==0) && (--pTable->nRef)>0) ) return;
   511    489   
   512         -  /* Delete all indices associated with this table
   513         -  */
          490  +  /* Delete all indices associated with this table. */
   514    491     for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){
   515    492       pNext = pIndex->pNext;
   516    493       assert( pIndex->pSchema==pTable->pSchema );
   517         -    sqlite3DeleteIndex(db, pIndex);
          494  +    if( !db || db->pnBytesFreed==0 ){
          495  +      char *zName = pIndex->zName; 
          496  +      TESTONLY ( Index *pOld = ) sqlite3HashInsert(
          497  +	  &pIndex->pSchema->idxHash, zName, sqlite3Strlen30(zName), 0
          498  +      );
          499  +      assert( pOld==pIndex || pOld==0 );
          500  +    }
          501  +    freeIndex(db, pIndex);
   518    502     }
   519    503   
   520    504     /* Delete any foreign keys attached to this table. */
   521    505     sqlite3FkDelete(db, pTable);
   522    506   
   523    507     /* Delete the Table structure itself.
   524    508     */
   525         -  sqliteResetColumnNames(db, pTable);
          509  +  sqliteDeleteColumnNames(db, pTable);
   526    510     sqlite3DbFree(db, pTable->zName);
   527    511     sqlite3DbFree(db, pTable->zColAff);
   528    512     sqlite3SelectDelete(db, pTable->pSelect);
   529    513   #ifndef SQLITE_OMIT_CHECK
   530    514     sqlite3ExprDelete(db, pTable->pCheck);
   531    515   #endif
   532    516     sqlite3VtabClear(db, pTable);
................................................................................
  1813   1797   */
  1814   1798   static void sqliteViewResetAll(sqlite3 *db, int idx){
  1815   1799     HashElem *i;
  1816   1800     if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  1817   1801     for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
  1818   1802       Table *pTab = sqliteHashData(i);
  1819   1803       if( pTab->pSelect ){
  1820         -      sqliteResetColumnNames(db, pTab);
         1804  +      sqliteDeleteColumnNames(db, pTab);
         1805  +      pTab->aCol = 0;
         1806  +      pTab->nCol = 0;
  1821   1807       }
  1822   1808     }
  1823   1809     DbClearProperty(db, idx, DB_UnresetViews);
  1824   1810   }
  1825   1811   #else
  1826   1812   # define sqliteViewResetAll(A,B)
  1827   1813   #endif /* SQLITE_OMIT_VIEW */

Changes to src/fkey.c.

  1154   1154   void sqlite3FkDelete(sqlite3 *db, Table *pTab){
  1155   1155     FKey *pFKey;                    /* Iterator variable */
  1156   1156     FKey *pNext;                    /* Copy of pFKey->pNextFrom */
  1157   1157   
  1158   1158     for(pFKey=pTab->pFKey; pFKey; pFKey=pNext){
  1159   1159   
  1160   1160       /* Remove the FK from the fkeyHash hash table. */
  1161         -    if( pFKey->pPrevTo ){
  1162         -      pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
  1163         -    }else{
  1164         -      void *data = (void *)pFKey->pNextTo;
  1165         -      const char *z = (data ? pFKey->pNextTo->zTo : pFKey->zTo);
  1166         -      sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), data);
         1161  +    if( !db || db->pnBytesFreed==0 ){
         1162  +      if( pFKey->pPrevTo ){
         1163  +        pFKey->pPrevTo->pNextTo = pFKey->pNextTo;
         1164  +      }else{
         1165  +        void *p = (void *)pFKey->pNextTo;
         1166  +        const char *z = (p ? pFKey->pNextTo->zTo : pFKey->zTo);
         1167  +        sqlite3HashInsert(&pTab->pSchema->fkeyHash, z, sqlite3Strlen30(z), p);
         1168  +      }
         1169  +      if( pFKey->pNextTo ){
         1170  +        pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
         1171  +      }
  1167   1172       }
  1168         -    if( pFKey->pNextTo ){
  1169         -      pFKey->pNextTo->pPrevTo = pFKey->pPrevTo;
  1170         -    }
         1173  +
         1174  +    /* EV: R-30323-21917 Each foreign key constraint in SQLite is
         1175  +    ** classified as either immediate or deferred.
         1176  +    */
         1177  +    assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );
  1171   1178   
  1172   1179       /* Delete any triggers created to implement actions for this FK. */
  1173   1180   #ifndef SQLITE_OMIT_TRIGGER
  1174   1181       fkTriggerDelete(db, pFKey->apTrigger[0]);
  1175   1182       fkTriggerDelete(db, pFKey->apTrigger[1]);
  1176   1183   #endif
  1177   1184   
  1178         -    /* EV: R-30323-21917 Each foreign key constraint in SQLite is
  1179         -    ** classified as either immediate or deferred.
  1180         -    */
  1181         -    assert( pFKey->isDeferred==0 || pFKey->isDeferred==1 );
  1182         -
  1183   1185       pNext = pFKey->pNextFrom;
  1184   1186       sqlite3DbFree(db, pFKey);
  1185   1187     }
  1186   1188   }
  1187   1189   #endif /* ifndef SQLITE_OMIT_FOREIGN_KEY */

Changes to src/malloc.c.

   451    451   
   452    452   /*
   453    453   ** Free memory that might be associated with a particular database
   454    454   ** connection.
   455    455   */
   456    456   void sqlite3DbFree(sqlite3 *db, void *p){
   457    457     assert( db==0 || sqlite3_mutex_held(db->mutex) );
   458         -  if( isLookaside(db, p) ){
          458  +  if( db && db->pnBytesFreed ){
          459  +    if( isLookaside(db, p) ){
          460  +      *db->pnBytesFreed += db->lookaside.sz;
          461  +    }else{
          462  +      *db->pnBytesFreed += sqlite3MallocSize(p);
          463  +    }
          464  +  }else if( isLookaside(db, p) ){
   459    465       LookasideSlot *pBuf = (LookasideSlot*)p;
   460    466       pBuf->pNext = db->lookaside.pFree;
   461    467       db->lookaside.pFree = pBuf;
   462    468       db->lookaside.nOut--;
   463    469     }else{
   464    470       assert( sqlite3MemdebugHasType(p,
   465    471                          db ? (MEMTYPE_DB|MEMTYPE_HEAP) : MEMTYPE_HEAP) );

Changes to src/sqlite.h.in.

  5248   5248   ** memory used by all pager caches associated with the database connection.
  5249   5249   ** ^The highwater mark associated with SQLITE_DBSTATUS_CACHE_USED is always 0.
  5250   5250   ** </dd>
  5251   5251   ** </dl>
  5252   5252   */
  5253   5253   #define SQLITE_DBSTATUS_LOOKASIDE_USED     0
  5254   5254   #define SQLITE_DBSTATUS_CACHE_USED         1
  5255         -#define SQLITE_DBSTATUS_MAX                1   /* Largest defined DBSTATUS */
         5255  +#define SQLITE_DBSTATUS_SCHEMA_USED        2
         5256  +#define SQLITE_DBSTATUS_STMT_USED          3
         5257  +#define SQLITE_DBSTATUS_MAX                3   /* Largest defined DBSTATUS */
  5256   5258   
  5257   5259   
  5258   5260   /*
  5259   5261   ** CAPI3REF: Prepared Statement Status
  5260   5262   **
  5261   5263   ** ^(Each prepared statement maintains various
  5262   5264   ** [SQLITE_STMTSTATUS_SORT | counters] that measure the number

Changes to src/sqliteInt.h.

   856    856     int busyTimeout;              /* Busy handler timeout, in msec */
   857    857     Db aDbStatic[2];              /* Static space for the 2 default backends */
   858    858     Savepoint *pSavepoint;        /* List of active savepoints */
   859    859     int nSavepoint;               /* Number of non-transaction savepoints */
   860    860     int nStatement;               /* Number of nested statement-transactions  */
   861    861     u8 isTransactionSavepoint;    /* True if the outermost savepoint is a TS */
   862    862     i64 nDeferredCons;            /* Net deferred constraints this transaction. */
          863  +  int *pnBytesFreed;            /* If not NULL, increment this in DbFree() */
          864  +  SubProgram *pSubProgram;      /* List of sub-programs already visited*/
   863    865   
   864    866   #ifdef SQLITE_ENABLE_UNLOCK_NOTIFY
   865    867     /* The following variables are all protected by the STATIC_MASTER 
   866    868     ** mutex, not by sqlite3.mutex. They are used by code in notify.c. 
   867    869     **
   868    870     ** When X.pUnlockConnection==Y, that means that X is waiting for Y to
   869    871     ** unlock so that it can proceed.
................................................................................
  2904   2906   CollSeq *sqlite3GetCollSeq(sqlite3*, u8, CollSeq *, const char*);
  2905   2907   char sqlite3AffinityType(const char*);
  2906   2908   void sqlite3Analyze(Parse*, Token*, Token*);
  2907   2909   int sqlite3InvokeBusyHandler(BusyHandler*);
  2908   2910   int sqlite3FindDb(sqlite3*, Token*);
  2909   2911   int sqlite3FindDbName(sqlite3 *, const char *);
  2910   2912   int sqlite3AnalysisLoad(sqlite3*,int iDB);
  2911         -void sqlite3DeleteIndexSamples(Index*);
         2913  +void sqlite3DeleteIndexSamples(sqlite3*,Index*);
  2912   2914   void sqlite3DefaultRowEst(Index*);
  2913   2915   void sqlite3RegisterLikeFunctions(sqlite3*, int);
  2914   2916   int sqlite3IsLikeFunction(sqlite3*,Expr*,int*,char*);
  2915   2917   void sqlite3MinimumFileFormat(Parse*, int, int);
  2916   2918   void sqlite3SchemaFree(void *);
  2917   2919   Schema *sqlite3SchemaGet(sqlite3 *, Btree *);
  2918   2920   int sqlite3SchemaToIndex(sqlite3 *db, Schema *);

Changes to src/status.c.

    10     10   **
    11     11   *************************************************************************
    12     12   **
    13     13   ** This module implements the sqlite3_status() interface and related
    14     14   ** functionality.
    15     15   */
    16     16   #include "sqliteInt.h"
           17  +#include "vdbeInt.h"
    17     18   
    18     19   /*
    19     20   ** Variables in which to record status information.
    20     21   */
    21     22   typedef struct sqlite3StatType sqlite3StatType;
    22     23   static SQLITE_WSD struct sqlite3StatType {
    23     24     int nowValue[9];         /* Current value */
................................................................................
   132    133           }
   133    134         }
   134    135         sqlite3BtreeLeaveAll(db);
   135    136         *pCurrent = totalUsed;
   136    137         *pHighwater = 0;
   137    138         break;
   138    139       }
          140  +
          141  +    case SQLITE_DBSTATUS_SCHEMA_USED: {
          142  +      int i;                      /* Used to iterate through schemas */
          143  +      int nByte = 0;              /* Used to accumulate return value */
          144  +
          145  +      assert( db->pSubProgram==0 );
          146  +      db->pnBytesFreed = &nByte;
          147  +      for(i=0; i<db->nDb; i++){
          148  +	Schema *pSchema = db->aDb[i].pSchema;
          149  +	if( pSchema ){
          150  +  	  HashElem *p;
          151  +
          152  +	  nByte += sizeof(HashElem) * (
          153  +	      pSchema->tblHash.count 
          154  +	    + pSchema->trigHash.count
          155  +	    + pSchema->idxHash.count
          156  +	    + pSchema->fkeyHash.count
          157  +	  );
          158  +	  nByte += sqlite3MallocSize(pSchema->tblHash.ht);
          159  +	  nByte += sqlite3MallocSize(pSchema->trigHash.ht);
          160  +	  nByte += sqlite3MallocSize(pSchema->idxHash.ht);
          161  +	  nByte += sqlite3MallocSize(pSchema->fkeyHash.ht);
          162  +
          163  +          for(p=sqliteHashFirst(&pSchema->trigHash); p; p=sqliteHashNext(p)){
          164  +            sqlite3DeleteTrigger(db, (Trigger*)sqliteHashData(p));
          165  +          }
          166  +          for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
          167  +            sqlite3DeleteTable(db, (Table *)sqliteHashData(p));
          168  +          }
          169  +	}
          170  +      }
          171  +      db->pnBytesFreed = 0;
          172  +
          173  +      *pHighwater = 0;
          174  +      *pCurrent = nByte;
          175  +      break;
          176  +    }
          177  +
          178  +    case SQLITE_DBSTATUS_STMT_USED: {
          179  +      struct Vdbe *pVdbe;         /* Used to iterate through VMs */
          180  +      int nByte = 0;              /* Used to accumulate return value */
          181  +
          182  +      db->pnBytesFreed = &nByte;
          183  +      for(pVdbe=db->pVdbe; pVdbe; pVdbe=pVdbe->pNext){
          184  +        SubProgram *pSub, *pNext;
          185  +	sqlite3VdbeDeleteObject(db, pVdbe);
          186  +        for(pSub=db->pSubProgram; pSub; pSub=pNext){
          187  +	  pNext = pSub->pNext;
          188  +	  pSub->pNext = 0;
          189  +        }
          190  +	db->pSubProgram = 0;
          191  +      }
          192  +      db->pnBytesFreed = 0;
          193  +
          194  +      *pHighwater = 0;
          195  +      *pCurrent = nByte;
          196  +
          197  +      break;
          198  +    }
          199  +
   139    200       default: {
   140    201         rc = SQLITE_ERROR;
   141    202       }
   142    203     }
   143    204     sqlite3_mutex_leave(db->mutex);
   144    205     return rc;
   145    206   }

Changes to src/test_malloc.c.

  1284   1284     int getDbPointer(Tcl_Interp*, const char*, sqlite3**);
  1285   1285     static const struct {
  1286   1286       const char *zName;
  1287   1287       int op;
  1288   1288     } aOp[] = {
  1289   1289       { "SQLITE_DBSTATUS_LOOKASIDE_USED",    SQLITE_DBSTATUS_LOOKASIDE_USED   },
  1290   1290       { "SQLITE_DBSTATUS_CACHE_USED",        SQLITE_DBSTATUS_CACHE_USED       },
         1291  +    { "SQLITE_DBSTATUS_SCHEMA_USED",       SQLITE_DBSTATUS_SCHEMA_USED      },
         1292  +    { "SQLITE_DBSTATUS_STMT_USED",         SQLITE_DBSTATUS_STMT_USED        }
  1291   1293     };
  1292   1294     Tcl_Obj *pResult;
  1293   1295     if( objc!=4 ){
  1294   1296       Tcl_WrongNumArgs(interp, 1, objv, "PARAMETER RESETFLAG");
  1295   1297       return TCL_ERROR;
  1296   1298     }
  1297   1299     if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ) return TCL_ERROR;

Changes to src/vdbe.h.

    79     79   struct SubProgram {
    80     80     VdbeOp *aOp;                  /* Array of opcodes for sub-program */
    81     81     int nOp;                      /* Elements in aOp[] */
    82     82     int nMem;                     /* Number of memory cells required */
    83     83     int nCsr;                     /* Number of cursors required */
    84     84     int nRef;                     /* Number of pointers to this structure */
    85     85     void *token;                  /* id that may be used to recursive triggers */
           86  +  SubProgram *pNext;            /* Next sub-program already visited */
    86     87   };
    87     88   
    88     89   /*
    89     90   ** A smaller version of VdbeOp used for the VdbeAddOpList() function because
    90     91   ** it takes up less space.
    91     92   */
    92     93   struct VdbeOpList {
................................................................................
   180    181   void sqlite3VdbeChangeToNoop(Vdbe*, int addr, int N);
   181    182   void sqlite3VdbeChangeP4(Vdbe*, int addr, const char *zP4, int N);
   182    183   void sqlite3VdbeUsesBtree(Vdbe*, int);
   183    184   VdbeOp *sqlite3VdbeGetOp(Vdbe*, int);
   184    185   int sqlite3VdbeMakeLabel(Vdbe*);
   185    186   void sqlite3VdbeRunOnlyOnce(Vdbe*);
   186    187   void sqlite3VdbeDelete(Vdbe*);
          188  +void sqlite3VdbeDeleteObject(sqlite3*,Vdbe*);
   187    189   void sqlite3VdbeMakeReady(Vdbe*,int,int,int,int,int,int);
   188    190   int sqlite3VdbeFinalize(Vdbe*);
   189    191   void sqlite3VdbeResolveLabel(Vdbe*, int);
   190    192   int sqlite3VdbeCurrentAddr(Vdbe*);
   191    193   #ifdef SQLITE_DEBUG
   192    194     int sqlite3VdbeAssertMayAbort(Vdbe *, int);
   193    195     void sqlite3VdbeTrace(Vdbe*,FILE*);

Changes to src/vdbeaux.c.

   569    569   */
   570    570   static void freeEphemeralFunction(sqlite3 *db, FuncDef *pDef){
   571    571     if( ALWAYS(pDef) && (pDef->flags & SQLITE_FUNC_EPHEM)!=0 ){
   572    572       sqlite3DbFree(db, pDef);
   573    573     }
   574    574   }
   575    575   
          576  +static void vdbeFreeOpArray(sqlite3 *, Op *, int);
          577  +
   576    578   /*
   577    579   ** Delete a P4 value if necessary.
   578    580   */
   579    581   static void freeP4(sqlite3 *db, int p4type, void *p4){
   580    582     if( p4 ){
          583  +    assert( db );
   581    584       switch( p4type ){
   582    585         case P4_REAL:
   583    586         case P4_INT64:
   584    587         case P4_MPRINTF:
   585    588         case P4_DYNAMIC:
   586    589         case P4_KEYINFO:
   587    590         case P4_INTARRAY:
................................................................................
   588    591         case P4_KEYINFO_HANDOFF: {
   589    592           sqlite3DbFree(db, p4);
   590    593           break;
   591    594         }
   592    595         case P4_VDBEFUNC: {
   593    596           VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
   594    597           freeEphemeralFunction(db, pVdbeFunc->pFunc);
   595         -        sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
          598  +        if( db->pnBytesFreed==0 ) sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
   596    599           sqlite3DbFree(db, pVdbeFunc);
   597    600           break;
   598    601         }
   599    602         case P4_FUNCDEF: {
   600    603           freeEphemeralFunction(db, (FuncDef*)p4);
   601    604           break;
   602    605         }
   603    606         case P4_MEM: {
   604    607           sqlite3ValueFree((sqlite3_value*)p4);
   605    608           break;
   606    609         }
   607    610         case P4_VTAB : {
   608         -        sqlite3VtabUnlock((VTable *)p4);
          611  +        if( db->pnBytesFreed==0 ) sqlite3VtabUnlock((VTable *)p4);
   609    612           break;
   610    613         }
   611    614         case P4_SUBPROGRAM : {
   612         -        sqlite3VdbeProgramDelete(db, (SubProgram *)p4, 1);
          615  +        if( db->pnBytesFreed ){
          616  +	  SubProgram *p = (SubProgram *)p4;
          617  +	  SubProgram *pDone;
          618  +	  for(pDone=db->pSubProgram; pDone; pDone=pDone->pNext){
          619  +	    if( pDone==p ) break;
          620  +	  }
          621  +	  if( !pDone ){
          622  +	    p->pNext = db->pSubProgram;
          623  +	    db->pSubProgram = p;
          624  +            vdbeFreeOpArray(db, p->aOp, p->nOp);
          625  +            sqlite3DbFree(db, p);
          626  +	  }
          627  +	}else{
          628  +	  sqlite3VdbeProgramDelete(db, (SubProgram *)p4, 1);
          629  +	}
   613    630           break;
   614    631         }
   615    632       }
   616    633     }
   617    634   }
   618    635   
   619    636   /*
................................................................................
   999   1016   ** Release an array of N Mem elements
  1000   1017   */
  1001   1018   static void releaseMemArray(Mem *p, int N){
  1002   1019     if( p && N ){
  1003   1020       Mem *pEnd;
  1004   1021       sqlite3 *db = p->db;
  1005   1022       u8 malloc_failed = db->mallocFailed;
         1023  +    if( db->pnBytesFreed ){
         1024  +      for(pEnd=&p[N]; p<pEnd; p++){
         1025  +        sqlite3DbFree(db, p->zMalloc);
         1026  +      }
         1027  +    }else
  1006   1028       for(pEnd=&p[N]; p<pEnd; p++){
  1007   1029         assert( (&p[1])==pEnd || p[0].db==p[1].db );
  1008   1030   
  1009   1031         /* This block is really an inlined version of sqlite3VdbeMemRelease()
  1010   1032         ** that takes advantage of the fact that the memory cell value is 
  1011   1033         ** being set to NULL after releasing any dynamic resources.
  1012   1034         **
................................................................................
  2330   2352         if( pAux->xDelete ){
  2331   2353           pAux->xDelete(pAux->pAux);
  2332   2354         }
  2333   2355         pAux->pAux = 0;
  2334   2356       }
  2335   2357     }
  2336   2358   }
         2359  +
         2360  +/*
         2361  +** Free all memory associated with the Vdbe passed as the second argument.
         2362  +** The difference between this function and sqlite3VdbeDelete() is that
         2363  +** VdbeDelete() also unlinks the Vdbe from the list of VMs associated with
         2364  +** the database connection.
         2365  +*/
         2366  +void sqlite3VdbeDeleteObject(sqlite3 *db, Vdbe *p){
         2367  +  assert( p->db==0 || p->db==db );
         2368  +  releaseMemArray(p->aVar, p->nVar);
         2369  +  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
         2370  +  vdbeFreeOpArray(db, p->aOp, p->nOp);
         2371  +  sqlite3DbFree(db, p->aLabel);
         2372  +  sqlite3DbFree(db, p->aColName);
         2373  +  sqlite3DbFree(db, p->zSql);
         2374  +  sqlite3DbFree(db, p->pFree);
         2375  +  sqlite3DbFree(db, p);
         2376  +}
  2337   2377   
  2338   2378   /*
  2339   2379   ** Delete an entire VDBE.
  2340   2380   */
  2341   2381   void sqlite3VdbeDelete(Vdbe *p){
  2342   2382     sqlite3 *db;
  2343   2383   
................................................................................
  2348   2388     }else{
  2349   2389       assert( db->pVdbe==p );
  2350   2390       db->pVdbe = p->pNext;
  2351   2391     }
  2352   2392     if( p->pNext ){
  2353   2393       p->pNext->pPrev = p->pPrev;
  2354   2394     }
  2355         -  releaseMemArray(p->aVar, p->nVar);
  2356         -  releaseMemArray(p->aColName, p->nResColumn*COLNAME_N);
  2357         -  vdbeFreeOpArray(db, p->aOp, p->nOp);
  2358         -  sqlite3DbFree(db, p->aLabel);
  2359         -  sqlite3DbFree(db, p->aColName);
  2360         -  sqlite3DbFree(db, p->zSql);
  2361   2395     p->magic = VDBE_MAGIC_DEAD;
  2362         -  sqlite3DbFree(db, p->pFree);
  2363   2396     p->db = 0;
  2364         -  sqlite3DbFree(db, p);
         2397  +  sqlite3VdbeDeleteObject(db, p);
  2365   2398   }
  2366   2399   
  2367   2400   /*
  2368   2401   ** Make sure the cursor p is ready to read or write the row to which it
  2369   2402   ** was last positioned.  Return an error code if an OOM fault or I/O error
  2370   2403   ** prevents us from positioning the cursor to its correct position.
  2371   2404   **

Changes to src/vtab.c.

   218    218   ** The reference count of the VTable structure associated with database 
   219    219   ** connection db is decremented immediately (which may lead to the 
   220    220   ** structure being xDisconnected and free). Any other VTable structures
   221    221   ** in the list are moved to the sqlite3.pDisconnect list of the associated 
   222    222   ** database connection.
   223    223   */
   224    224   void sqlite3VtabClear(sqlite3 *db, Table *p){
   225         -  vtabDisconnectAll(0, p);
          225  +  if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
   226    226     if( p->azModuleArg ){
   227    227       int i;
   228    228       for(i=0; i<p->nModuleArg; i++){
   229    229         sqlite3DbFree(db, p->azModuleArg[i]);
   230    230       }
   231    231       sqlite3DbFree(db, p->azModuleArg);
   232    232     }

Changes to test/dbstatus.test.

    38     38   do_test dbstatus-1.2 {
    39     39     db eval {
    40     40       INSERT INTO t1 VALUES(zeroblob(9000));
    41     41     }
    42     42     lindex [sqlite3_db_status db SQLITE_DBSTATUS_CACHE_USED 0] 1
    43     43   } [expr {$BASESZ + 10*$PAGESZ}]
    44     44   
           45  +
           46  +proc lookaside {db} {
           47  +  expr { $::lookaside_buffer_size *
           48  +    [lindex [sqlite3_db_status $db SQLITE_DBSTATUS_LOOKASIDE_USED 0] 1]
           49  +  }
           50  +}
           51  +
           52  +#---------------------------------------------------------------------------
           53  +# Run the dbstatus-2 and dbstatus-3 tests with a couple of different
           54  +# lookaside buffer sizes.
           55  +#
           56  +foreach ::lookaside_buffer_size {0 64 120} {
           57  +
           58  +  #-------------------------------------------------------------------------
           59  +  # Tests for SQLITE_DBSTATUS_SCHEMA_USED.
           60  +  #
           61  +  # Each test in the following block works as follows. Each test uses a
           62  +  # different database schema.
           63  +  #
           64  +  #   1. Open a connection to an empty database. Disable statement caching.
           65  +  #
           66  +  #   2. Execute the SQL to create the database schema. Measure the total 
           67  +  #      heap and lookaside memory allocated by SQLite, and the memory 
           68  +  #      allocated for the database schema according to sqlite3_db_status().
           69  +  #
           70  +  #   3. Drop all tables in the database schema. Measure the total memory 
           71  +  #      and the schema memory again.
           72  +  #
           73  +  #   4. Repeat step 2.
           74  +  #
           75  +  #   5. Repeat step 3.
           76  +  #
           77  +  # Then test that:
           78  +  #
           79  +  #   a) The difference in schema memory quantities in steps 2 and 3 is the
           80  +  #      same as the difference in total memory in steps 2 and 3.
           81  +  #
           82  +  #   b) Step 4 reports the same amount of schema and total memory used as
           83  +  #      in step 2.
           84  +  #
           85  +  #   c) Step 5 reports the same amount of schema and total memory used as
           86  +  #      in step 3.
           87  +  #
           88  +  foreach {tn schema} { 
           89  +    1 { CREATE TABLE t1(a, b) }
           90  +    2 { CREATE TABLE t1(a PRIMARY KEY, b REFERENCES t1, c UNIQUE) }
           91  +    3 {
           92  +      CREATE TABLE t1(a, b);
           93  +      CREATE INDEX i1 ON t1(a, b);
           94  +    }
           95  +    4 {
           96  +      CREATE TABLE t1(a, b);
           97  +      CREATE TABLE t2(c, d);
           98  +      CREATE TRIGGER AFTER INSERT ON t1 BEGIN
           99  +        INSERT INTO t2 VALUES(new.a, new.b);
          100  +        SELECT * FROM t1, t2 WHERE a=c AND b=d GROUP BY b HAVING a>5 ORDER BY a;
          101  +      END;
          102  +    }
          103  +    5 {
          104  +      CREATE TABLE t1(a, b);
          105  +      CREATE TABLE t2(c, d);
          106  +      CREATE VIEW v1 AS SELECT * FROM t1 UNION SELECT * FROM t2;
          107  +    }
          108  +    6 {
          109  +      CREATE TABLE t1(a, b);
          110  +      CREATE INDEX i1 ON t1(a);
          111  +      CREATE INDEX i2 ON t1(a,b);
          112  +      CREATE INDEX i3 ON t1(b,b);
          113  +      INSERT INTO t1 VALUES(randomblob(20), randomblob(25));
          114  +      INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
          115  +      INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
          116  +      INSERT INTO t1 SELECT randomblob(20), randomblob(25) FROM t1;
          117  +      ANALYZE;
          118  +    }
          119  +    7 {
          120  +      CREATE TABLE t1(a, b);
          121  +      CREATE TABLE t2(c, d);
          122  +      CREATE VIEW v1 AS 
          123  +        SELECT * FROM t1 
          124  +        UNION 
          125  +        SELECT * FROM t2
          126  +        UNION ALL
          127  +        SELECT c||b, d||a FROM t2 LEFT OUTER JOIN t1 GROUP BY c, d
          128  +        ORDER BY 1, 2
          129  +      ;
          130  +      CREATE TRIGGER tr1 INSTEAD OF INSERT ON v1 BEGIN
          131  +        SELECT * FROM v1;
          132  +        UPDATE t1 SET a=5, b=(SELECT c FROM t2);
          133  +      END;
          134  +      SELECT * FROM v1;
          135  +    }
          136  +  } {
          137  +    set tn "$::lookaside_buffer_size-$tn"
          138  +  
          139  +    # Step 1.
          140  +    db close
          141  +    file delete -force test.db
          142  +    sqlite3 db test.db
          143  +    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
          144  +    db cache size 0
          145  +  
          146  +    # Step 2.
          147  +    execsql $schema
          148  +    set nAlloc1  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          149  +    incr nAlloc1 [lookaside db]
          150  +    set nSchema1 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
          151  +  
          152  +    # Step 3.
          153  +    drop_all_tables
          154  +    set nAlloc2  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          155  +    incr nAlloc2 [lookaside db]
          156  +    set nSchema2 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
          157  +  
          158  +    # Step 4.
          159  +    execsql $schema
          160  +    set nAlloc3  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          161  +    incr nAlloc3 [lookaside db]
          162  +    set nSchema3 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
          163  +    
          164  +    # Step 5.
          165  +    drop_all_tables
          166  +    set nAlloc4  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          167  +    incr nAlloc4 [lookaside db]
          168  +    set nSchema4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_SCHEMA_USED 0] 1]
          169  +  
          170  +    set nFree [expr {$nAlloc1-$nAlloc2}]
          171  +    do_test dbstatus-2.$tn.a { expr {$nSchema1-$nSchema2} } $nFree
          172  +    do_test dbstatus-2.$tn.b { list $nAlloc1 $nSchema1 } "$nAlloc3 $nSchema3"
          173  +    do_test dbstatus-2.$tn.c { list $nAlloc2 $nSchema2 } "$nAlloc4 $nSchema4"
          174  +  }
          175  +  
          176  +  #-------------------------------------------------------------------------
          177  +  # Tests for SQLITE_DBSTATUS_STMT_USED.
          178  +  #
          179  +  # Each test in the following block works as follows. Each test uses a
          180  +  # different database schema.
          181  +  #
          182  +  #   1. Open a connection to an empty database. Initialized the database
          183  +  #      schema.
          184  +  #
          185  +  #   2. Prepare a bunch of SQL statements. Measure the total heap and 
          186  +  #      lookaside memory allocated by SQLite, and the memory allocated 
          187  +  #      for the prepared statements according to sqlite3_db_status().
          188  +  #
          189  +  #   3. Finalize all prepared statements Measure the total memory 
          190  +  #      and the prepared statement memory again.
          191  +  #
          192  +  #   4. Repeat step 2.
          193  +  #
          194  +  #   5. Repeat step 3.
          195  +  #
          196  +  # Then test that:
          197  +  #
          198  +  #   a) The difference in schema memory quantities in steps 2 and 3 is the
          199  +  #      same as the difference in total memory in steps 2 and 3.
          200  +  #
          201  +  #   b) Step 4 reports the same amount of schema and total memory used as
          202  +  #      in step 2.
          203  +  #
          204  +  #   c) Step 5 reports the same amount of schema and total memory used as
          205  +  #      in step 3.
          206  +  #
          207  +  foreach {tn schema statements} { 
          208  +    1 { CREATE TABLE t1(a, b) } {
          209  +      SELECT * FROM t1;
          210  +      INSERT INTO t1 VALUES(1, 2);
          211  +      INSERT INTO t1 SELECT * FROM t1;
          212  +      UPDATE t1 SET a=5;
          213  +      DELETE FROM t1;
          214  +    }
          215  +    2 {
          216  +      PRAGMA recursive_triggers = 1;
          217  +      CREATE TABLE t1(a, b);
          218  +      CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
          219  +        INSERT INTO t1 VALUES(new.a-1, new.b);
          220  +      END;
          221  +    } {
          222  +      INSERT INTO t1 VALUES(5, 'x');
          223  +    } 
          224  +    3 {
          225  +      PRAGMA recursive_triggers = 1;
          226  +      CREATE TABLE t1(a, b);
          227  +      CREATE TABLE t2(a, b);
          228  +      CREATE TRIGGER tr1 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
          229  +        INSERT INTO t2 VALUES(new.a-1, new.b);
          230  +      END;
          231  +      CREATE TRIGGER tr2 AFTER INSERT ON t1 WHEN (new.a>0) BEGIN
          232  +        INSERT INTO t1 VALUES(new.a-1, new.b);
          233  +      END;
          234  +    } {
          235  +      INSERT INTO t1 VALUES(10, 'x');
          236  +    } 
          237  +    4 {
          238  +      CREATE TABLE t1(a, b);
          239  +    } {
          240  +      SELECT count(*) FROM t1 WHERE upper(a)='ABC';
          241  +    }
          242  +  } {
          243  +    set tn "$::lookaside_buffer_size-$tn"
          244  +
          245  +    # Step 1.
          246  +    db close
          247  +    file delete -force test.db
          248  +    sqlite3 db test.db
          249  +    sqlite3_db_config_lookaside db 0 $::lookaside_buffer_size 500
          250  +    db cache size 1000
          251  +  
          252  +    execsql $schema
          253  +    db cache flush
          254  +  
          255  +    # Step 2.
          256  +    execsql $statements
          257  +    set nAlloc1  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          258  +    incr nAlloc1 [lookaside db]
          259  +    set nStmt1   [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
          260  +    execsql $statements
          261  +  
          262  +    # Step 3.
          263  +    db cache flush
          264  +    set nAlloc2  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          265  +    incr nAlloc3 [lookaside db]
          266  +    set nStmt2   [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
          267  +    
          268  +    # Step 3.
          269  +    execsql $statements
          270  +    set nAlloc3  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          271  +    incr nAlloc3 [lookaside db]
          272  +    set nStmt3   [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
          273  +    execsql $statements
          274  +  
          275  +    # Step 4.
          276  +    db cache flush
          277  +    set nAlloc4  [lindex [sqlite3_status SQLITE_STATUS_MEMORY_USED 0] 1]
          278  +    incr nAlloc4 [lookaside db]
          279  +    set nStmt4 [lindex [sqlite3_db_status db SQLITE_DBSTATUS_STMT_USED 0] 1]
          280  +  
          281  +    set nFree [expr {$nAlloc1-$nAlloc2}]
          282  +    do_test dbstatus-3.$tn.a { list $nStmt2 } {0}
          283  +    do_test dbstatus-3.$tn.b { list $nStmt1 } [list $nFree]
          284  +    do_test dbstatus-3.$tn.c { list $nAlloc1 $nStmt1 } [list $nAlloc3 $nStmt3]
          285  +    do_test dbstatus-3.$tn.d { list $nAlloc2 $nStmt2 } [list $nAlloc4 $nStmt4]
          286  +  }
          287  +}
          288  +
    45    289   finish_test