]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Optimizations to vdbeaux.c and printf.c (CVS 1980)
authordrh <drh@noemail.net>
Fri, 24 Sep 2004 22:32:30 +0000 (22:32 +0000)
committerdrh <drh@noemail.net>
Fri, 24 Sep 2004 22:32:30 +0000 (22:32 +0000)
FossilOrigin-Name: eabc77c99b3e78b4c620a1736d9acfa6cb1e7b67

manifest
manifest.uuid
src/pager.c
src/printf.c
src/vdbeaux.c

index 1cc17456857a9f3f9a1a6f04928008904f956d72..98f9d9d666668006d6437b8d13469185ccf8996d 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Improvements\sto\sthe\sdebugging\scode.\s(CVS\s1979)
-D 2004-09-24T19:39:27
+C Optimizations\sto\svdbeaux.c\sand\sprintf.c\s(CVS\s1980)
+D 2004-09-24T22:32:31
 F Makefile.in abdeb5bd9d017822691884935c320037c33f6ee6
 F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -51,11 +51,11 @@ F src/os_unix.c a5625eed7ab071d1715df783f4684945ae538a22
 F src/os_unix.h f3097815e041e82e24d92505e1ff61ba24172d13
 F src/os_win.c 9e2887825b1a32f0ceb1b73b93ffe29a112cd86f
 F src/os_win.h babd4e912967c6b09088cfe38a45e8005a07ba44
-F src/pager.c db8f6cb80798091fcff95c1f86873381fbfefee6
+F src/pager.c 705a61117f05d7dd031762408f9a279834e88c3a
 F src/pager.h 67739fe649f33be55dba522ca8a9cc4e42d14f71
 F src/parse.y 9389af67bd49b8e5c9d2968b3315a30565b4a200
 F src/pragma.c 5fb6647fda4c95edb08447a505e6c98c041e5b31
-F src/printf.c 74ee8eed5983226d1953b46b8ed7d9a55937c145
+F src/printf.c 40770e1f553612d13dfc86d236086e69baa62fe1
 F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
 F src/select.c 13a4e6d0ca2bce8be60e26a499060524fef2e28c
 F src/shell.c 0856973c2b94e22664bc43f398ba3fc22d5e080c
@@ -78,7 +78,7 @@ F src/vdbe.c 0542852785220807feb02b9dee1150ac2e592c8d
 F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
 F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b
 F src/vdbeapi.c f1e060aae5adace5f3a6ae2b0527cfe73e880f1c
-F src/vdbeaux.c 082d63e06c276bd600c7d8ddad361cb9f67590ea
+F src/vdbeaux.c dc3848209aee05b32636a9c1dd913a56ef8dac79
 F src/vdbemem.c ef9ac7d32acfe4bce5c5b408b1294c8d9e0cdb56
 F src/where.c 5d573333c07f259c8d3b8423d82ba774b78b63a9
 F test/all.test 929bfa932b55e75c96fe2203f7650ba451c1862c
@@ -247,7 +247,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
 F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
 F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
 F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 1ee3a787ada5abd460200d5812474161bfd1cc71
-R 15484f1b24114da1012f0baff327a290
+P bdc3bb070f7f29713b7bb9a6454a7ecbee6cf36d
+R 07e2fbac83a5f125e4876d6fcf9bf7e8
 U drh
-Z 4e3ae2dfcca5df52050a8ce4b9bedbca
+Z 242bf20dc4f04b5461b10f0143a31a44
index 11d5355ef9ad6d051bf75d579d70963492669e87..287b4f3d72d8b1cd6fb8f6cd536e46845e7e168c 100644 (file)
@@ -1 +1 @@
-bdc3bb070f7f29713b7bb9a6454a7ecbee6cf36d
\ No newline at end of file
+eabc77c99b3e78b4c620a1736d9acfa6cb1e7b67
\ No newline at end of file
index c246ff8745f6464bb13db4bbad1ba79ca2055e4a..a40df566aea54f78afb13db4fef91ff2082e2842 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.163 2004/09/08 20:13:05 drh Exp $
+** @(#) $Id: pager.c,v 1.164 2004/09/24 22:32:31 drh Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -228,12 +228,12 @@ struct Pager {
   PgHdr *pFirstSynced;        /* First free page with PgHdr.needSync==0 */
   PgHdr *pAll;                /* List of all pages */
   PgHdr *pStmt;               /* List of pages in the statement subjournal */
-  PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number to PgHdr */
   off_t journalOff;           /* Current byte offset in the journal file */
   off_t journalHdr;           /* Byte offset to previous journal header */
   off_t stmtHdrOff;           /* First journal header written this statement */
   off_t stmtCksum;            /* cksumInit when statement was started */
   int sectorSize;             /* Assumed sector size during rollback */
+  PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number to PgHdr */
 };
 
 /*
index 768e331bfa2edfa67d370d319f1c07bc34845455..716e59d556b2efba2669c20409fd8bbadb65df74 100644 (file)
@@ -90,8 +90,8 @@ typedef struct et_info {   /* Information about each format field */
   etByte base;             /* The base for radix conversion */
   etByte flags;            /* One or more of FLAG_ constants below */
   etByte type;             /* Conversion paradigm */
-  char *charset;           /* The character set for conversion */
-  char *prefix;            /* Prefix on non-zero values in alt format */
+  etByte charset;          /* Offset into aDigits[] of the digits string */
+  etByte prefix;           /* Offset into aPrefix[] of the prefix string */
 } et_info;
 
 /*
@@ -105,28 +105,30 @@ typedef struct et_info {   /* Information about each format field */
 ** The following table is searched linearly, so it is good to put the
 ** most frequently used conversion types first.
 */
+static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
+static const char aPrefix[] = "-x0\000X0";
 static et_info fmtinfo[] = {
-  {  'd', 10, 1, etRADIX,      "0123456789",       0    },
-  {  's',  0, 0, etSTRING,     0,                  0    },
-  {  'z',  0, 2, etDYNSTRING,  0,                  0    },
-  {  'q',  0, 0, etSQLESCAPE,  0,                  0    },
-  {  'Q',  0, 0, etSQLESCAPE2, 0,                  0    },
-  {  'c',  0, 0, etCHARX,      0,                  0    },
-  {  'o',  8, 0, etRADIX,      "01234567",         "0"  },
-  {  'u', 10, 0, etRADIX,      "0123456789",       0    },
-  {  'x', 16, 0, etRADIX,      "0123456789abcdef", "x0" },
-  {  'X', 16, 0, etRADIX,      "0123456789ABCDEF", "X0" },
-  {  'f',  0, 1, etFLOAT,      0,                  0    },
-  {  'e',  0, 1, etEXP,        "e",                0    },
-  {  'E',  0, 1, etEXP,        "E",                0    },
-  {  'g',  0, 1, etGENERIC,    "e",                0    },
-  {  'G',  0, 1, etGENERIC,    "E",                0    },
-  {  'i', 10, 1, etRADIX,      "0123456789",       0    },
-  {  'n',  0, 0, etSIZE,       0,                  0    },
-  {  '%',  0, 0, etPERCENT,    0,                  0    },
-  {  'p', 16, 0, etPOINTER,    "0123456789abcdef", "x0" },
-  {  'T',  0, 2, etTOKEN,      0,                  0    },
-  {  'S',  0, 2, etSRCLIST,    0,                  0    },
+  {  'd', 10, 1, etRADIX,      0,  0 },
+  {  's',  0, 0, etSTRING,     0,  0 },
+  {  'z',  0, 2, etDYNSTRING,  0,  0 },
+  {  'q',  0, 0, etSQLESCAPE,  0,  0 },
+  {  'Q',  0, 0, etSQLESCAPE2, 0,  0 },
+  {  'c',  0, 0, etCHARX,      0,  0 },
+  {  'o',  8, 0, etRADIX,      0,  2 },
+  {  'u', 10, 0, etRADIX,      0,  0 },
+  {  'x', 16, 0, etRADIX,      16, 1 },
+  {  'X', 16, 0, etRADIX,      0,  4 },
+  {  'f',  0, 1, etFLOAT,      0,  0 },
+  {  'e',  0, 1, etEXP,        30, 0 },
+  {  'E',  0, 1, etEXP,        14, 0 },
+  {  'g',  0, 1, etGENERIC,    30, 0 },
+  {  'G',  0, 1, etGENERIC,    14, 0 },
+  {  'i', 10, 1, etRADIX,      0,  0 },
+  {  'n',  0, 0, etSIZE,       0,  0 },
+  {  '%',  0, 0, etPERCENT,    0,  0 },
+  {  'p', 16, 0, etPOINTER,    0,  1 },
+  {  'T',  0, 2, etTOKEN,      0,  0 },
+  {  'S',  0, 2, etSRCLIST,    0,  0 },
 };
 #define etNINFO  (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
 
@@ -377,9 +379,9 @@ static int vxprintf(
         }
         bufpt = &buf[etBUFSIZE-1];
         {
-          register char *cset;      /* Use registers for speed */
+          register const char *cset;      /* Use registers for speed */
           register int base;
-          cset = infop->charset;
+          cset = &aDigits[infop->charset];
           base = infop->base;
           do{                                           /* Convert to ascii */
             *(--bufpt) = cset[longvalue%base];
@@ -392,10 +394,11 @@ static int vxprintf(
         }
         if( prefix ) *(--bufpt) = prefix;               /* Add sign */
         if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */
-          char *pre, x;
-          pre = infop->prefix;
+          const char *pre;
+          char x;
+          pre = &aPrefix[infop->prefix];
           if( *bufpt!=pre[0] ){
-            for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
+            for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
           }
         }
         length = &buf[etBUFSIZE-1]-bufpt;
@@ -493,7 +496,7 @@ static int vxprintf(
           }
           bufpt++;                            /* point to next free slot */
           if( exp || flag_exp ){
-            *(bufpt++) = infop->charset[0];
+            *(bufpt++) = aDigits[infop->charset];
             if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
             else       { *(bufpt++) = '+'; }
             if( exp>=100 ){
@@ -809,6 +812,7 @@ char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
 ** and segfaults if you give it a long long int.
 */
 void sqlite3DebugPrintf(const char *zFormat, ...){
+  extern int getpid(void);
   va_list ap;
   char zBuf[500];
   va_start(ap, zFormat);
index 7c34776004f9695c6c54fff58da3e60bba1e45ee..15a5b57bdda775197cf4ed124db20e9d5ccc7d3c 100644 (file)
@@ -55,6 +55,21 @@ void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
   p->trace = trace;
 }
 
+/*
+** Resize the Vdbe.aOp array so that it contains at least N
+** elements.
+*/
+static void resizeOpArray(Vdbe *p, int N){
+  if( p->nOpAlloc<N ){
+    int oldSize = p->nOpAlloc;
+    p->nOpAlloc = N+100;
+    p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
+    if( p->aOp ){
+      memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
+    }
+  }
+}
+
 /*
 ** Add a new instruction to the list of instructions current in the
 ** VDBE.  Return the address of the new instruction.
@@ -78,24 +93,13 @@ int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
   i = p->nOp;
   p->nOp++;
   assert( p->magic==VDBE_MAGIC_INIT );
-  if( i>=p->nOpAlloc ){
-    int oldSize = p->nOpAlloc;
-    Op *aNew;
-    p->nOpAlloc = p->nOpAlloc*2 + 100;
-    aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
-    if( aNew==0 ){
-      p->nOpAlloc = oldSize;
-      return 0;
-    }
-    p->aOp = aNew;
-    memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
+  resizeOpArray(p, i+1);
+  if( p->aOp==0 ){
+    return 0;
   }
   pOp = &p->aOp[i];
   pOp->opcode = op;
   pOp->p1 = p1;
-  if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){
-    p2 = p->aLabel[-1-p2];
-  }
   pOp->p2 = p2;
   pOp->p3 = 0;
   pOp->p3type = P3_NOTUSED;
@@ -133,20 +137,12 @@ int sqlite3VdbeMakeLabel(Vdbe *p){
   i = p->nLabel++;
   assert( p->magic==VDBE_MAGIC_INIT );
   if( i>=p->nLabelAlloc ){
-    int *aNew;
     p->nLabelAlloc = p->nLabelAlloc*2 + 10;
-    aNew = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
-    if( aNew==0 ){
-      sqliteFree(p->aLabel);
-    }
-    p->aLabel = aNew;
+    p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
   }
-  if( p->aLabel==0 ){
-    p->nLabel = 0;
-    p->nLabelAlloc = 0;
-    return 0;
+  if( p->aLabel ){
+    p->aLabel[i] = -1;
   }
-  p->aLabel[i] = -1;
   return -1-i;
 }
 
@@ -156,18 +152,35 @@ int sqlite3VdbeMakeLabel(Vdbe *p){
 ** a prior call to sqlite3VdbeMakeLabel().
 */
 void sqlite3VdbeResolveLabel(Vdbe *p, int x){
-  int j;
+  int j = -1-x;
   assert( p->magic==VDBE_MAGIC_INIT );
-  if( x<0 && (-x)<=p->nLabel && p->aOp ){
-    if( p->aLabel[-1-x]==p->nOp ) return;
-    assert( p->aLabel[-1-x]<0 );
-    p->aLabel[-1-x] = p->nOp;
-    for(j=0; j<p->nOp; j++){
-      if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp;
-    }
+  assert( j>=0 && j<p->nLabel );
+  if( p->aLabel ){
+    p->aLabel[j] = p->nOp;
   }
 }
 
+/*
+** Loop through the program looking for P2 values that are negative.
+** Each such value is a label.  Resolve the label by setting the P2
+** value to its correct non-zero value.
+**
+** This routine is called once after all opcodes have been inserted.
+*/
+static void resolveP2Values(Vdbe *p){
+  int i;
+  Op *pOp;
+  int *aLabel = p->aLabel;
+  if( aLabel==0 ) return;
+  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
+    if( pOp->p2>=0 ) continue;
+    assert( -1-pOp->p2<p->nLabel );
+    pOp->p2 = aLabel[-1-pOp->p2];
+  }
+  sqliteFree(p->aLabel);
+  p->aLabel = 0;
+}
+
 /*
 ** Return the address of the next instruction to be inserted.
 */
@@ -183,17 +196,9 @@ int sqlite3VdbeCurrentAddr(Vdbe *p){
 int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
   int addr;
   assert( p->magic==VDBE_MAGIC_INIT );
-  if( p->nOp + nOp >= p->nOpAlloc ){
-    int oldSize = p->nOpAlloc;
-    Op *aNew;
-    p->nOpAlloc = p->nOpAlloc*2 + nOp + 10;
-    aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
-    if( aNew==0 ){
-      p->nOpAlloc = oldSize;
-      return 0;
-    }
-    p->aOp = aNew;
-    memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
+  resizeOpArray(p, p->nOp + nOp);
+  if( p->aOp==0 ){
+    return 0;
   }
   addr = p->nOp;
   if( nOp>0 ){
@@ -312,7 +317,7 @@ void sqlite3VdbeChangeP3(Vdbe *p, int addr, const char *zP3, int n){
 void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
   va_list ap;
   assert( p->nOp>0 );
-  assert( p->aOp[p->nOp-1].p3==0 );
+  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 );
   va_start(ap, zFormat);
   sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC);
   va_end(ap);
@@ -456,6 +461,17 @@ void sqlite3VdbePrintOp(FILE *pOut, int pc, Op *pOp){
 }
 #endif
 
+/*
+** Release an array of N Mem elements
+*/
+static void releaseMemArray(Mem *p, int N){
+  if( p ){
+    while( N-->0 ){
+      sqlite3VdbeMemRelease(p++);
+    }
+  }
+}
+
 /*
 ** Give a listing of the program in the virtual machine.
 **
@@ -477,10 +493,7 @@ int sqlite3VdbeList(
   ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
   */
   if( p->pTos==&p->aStack[4] ){
-    for(i=0; i<5; i++){
-      sqlite3VdbeMemRelease(&p->aStack[i]);
-      p->aStack[i].flags = 0;
-    }
+    releaseMemArray(p->aStack, 5);
   }
   p->resOnStack = 0;
 
@@ -586,6 +599,7 @@ void sqlite3VdbeMakeReady(
   ** Allocation all the stack space we will ever need.
   */
   if( p->aStack==0 ){
+    resolveP2Values(p);
     assert( nVar>=0 );
     n = isExplain ? 10 : p->nOp;
     p->aStack = sqliteMalloc(
@@ -846,27 +860,23 @@ static void closeAllCursors(Vdbe *p){
 static void Cleanup(Vdbe *p){
   int i;
   if( p->aStack ){
-    Mem *pTos = p->pTos;
-    while( pTos>=p->aStack ){
-      sqlite3VdbeMemRelease(pTos);
-      pTos--;
-    }
-    p->pTos = pTos;
+    releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));
+    p->pTos = &p->aStack[-1];
   }
   closeAllCursors(p);
-  for(i=0; i<p->nMem; i++){
-    sqlite3VdbeMemRelease(&p->aMem[i]);
-  }
+  releaseMemArray(p->aMem, p->nMem);
   if( p->pList ){
     sqlite3VdbeKeylistFree(p->pList);
     p->pList = 0;
   }
-  for(i=0; i<p->contextStackTop; i++){
-    sqlite3VdbeKeylistFree(p->contextStack[i].pList);
+  if( p->contextStack ){
+    for(i=0; i<p->contextStackTop; i++){
+      sqlite3VdbeKeylistFree(p->contextStack[i].pList);
+    }
+    sqliteFree(p->contextStack);
   }
   sqlite3VdbeSorterReset(p);
   sqlite3VdbeAggReset(0, &p->agg, 0);
-  sqliteFree(p->contextStack);
   p->contextStack = 0;
   p->contextStackDepth = 0;
   p->contextStackTop = 0;
@@ -881,8 +891,16 @@ static void Cleanup(Vdbe *p){
 ** be called on an SQL statement before sqlite3_step().
 */
 void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
+  Mem *pColName;
+  int n;
   assert( 0==p->nResColumn );
   p->nResColumn = nResColumn;
+  n = nResColumn*2;
+  p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n );
+  if( p->aColName==0 ) return;
+  while( n-- > 0 ){
+    (pColName++)->flags = MEM_Null;
+  }
 }
 
 /*
@@ -900,21 +918,8 @@ int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){
   int rc;
   Mem *pColName;
   assert( idx<(2*p->nResColumn) );
-
-  /* If the Vdbe.aColName array has not yet been allocated, allocate
-  ** it now.
-  */
-  if( !p->aColName ){
-    int i;
-    p->aColName = (Mem *)sqliteMalloc(sizeof(Mem)*p->nResColumn*2);
-    if( !p->aColName ){
-      return SQLITE_NOMEM;
-    }
-    for(i=0; i<(2*p->nResColumn); i++){
-      p->aColName[i].flags = MEM_Null;
-    }
-  }
-
+  if( sqlite3_malloc_failed ) return SQLITE_NOMEM;
+  assert( p->aColName!=0 );
   pColName = &(p->aColName[idx]);
   if( N==P3_DYNAMIC || N==P3_STATIC ){
     rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC);
@@ -1381,34 +1386,25 @@ void sqlite3VdbeDelete(Vdbe *p){
   if( p->pNext ){
     p->pNext->pPrev = p->pPrev;
   }
-  p->pPrev = p->pNext = 0;
-  if( p->nOpAlloc==0 ){
-    p->aOp = 0;
-    p->nOp = 0;
-  }
-  for(i=0; i<p->nOp; i++){
-    Op *pOp = &p->aOp[i];
-    if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
-      sqliteFree(pOp->p3);
-    }
-    if( pOp->p3type==P3_VDBEFUNC ){
-      VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
-      sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
-      sqliteFree(pVdbeFunc);
+  if( p->aOp ){
+    for(i=0; i<p->nOp; i++){
+      Op *pOp = &p->aOp[i];
+      if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
+        sqliteFree(pOp->p3);
+      }
+      if( pOp->p3type==P3_VDBEFUNC ){
+        VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
+        sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
+        sqliteFree(pVdbeFunc);
+      }
     }
+    sqliteFree(p->aOp);
   }
-  for(i=0; i<p->nVar; i++){
-    sqlite3VdbeMemRelease(&p->aVar[i]);
-  }
-  sqliteFree(p->aOp);
+  releaseMemArray(p->aVar, p->nVar);
   sqliteFree(p->aLabel);
   sqliteFree(p->aStack);
-  if( p->aColName ){
-    for(i=0; i<(p->nResColumn)*2; i++){
-      sqlite3VdbeMemRelease(&(p->aColName[i]));
-    }
-    sqliteFree(p->aColName);
-  }
+  releaseMemArray(p->aColName, p->nResColumn*2);
+  sqliteFree(p->aColName);
   p->magic = VDBE_MAGIC_DEAD;
   sqliteFree(p);
 }