/ Check-in [eabc77c9]
Login

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

Overview
Comment:Optimizations to vdbeaux.c and printf.c (CVS 1980)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:eabc77c99b3e78b4c620a1736d9acfa6cb1e7b67
User & Date: drh 2004-09-24 22:32:31
Context
2004-09-24
23:20
Save a few bytes in utf.c. (CVS 1981) check-in: 8154d545 user: drh tags: trunk
22:32
Optimizations to vdbeaux.c and printf.c (CVS 1980) check-in: eabc77c9 user: drh tags: trunk
19:39
Improvements to the debugging code. (CVS 1979) check-in: bdc3bb07 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/pager.c.

    14     14   ** The pager is used to access a database disk file.  It implements
    15     15   ** atomic commit and rollback through the use of a journal file that
    16     16   ** is separate from the database file.  The pager also implements file
    17     17   ** locking to prevent two processes from writing the same database
    18     18   ** file simultaneously, or one process from reading the database while
    19     19   ** another is writing.
    20     20   **
    21         -** @(#) $Id: pager.c,v 1.163 2004/09/08 20:13:05 drh Exp $
           21  +** @(#) $Id: pager.c,v 1.164 2004/09/24 22:32:31 drh Exp $
    22     22   */
    23     23   #include "os.h"         /* Must be first to enable large file support */
    24     24   #include "sqliteInt.h"
    25     25   #include "pager.h"
    26     26   #include <assert.h>
    27     27   #include <string.h>
    28     28   
................................................................................
   224    224     u8 *aInStmt;                /* One bit for each page in the database */
   225    225     u8 setMaster;               /* True if a m-j name has been written to jrnl */
   226    226     BusyHandler *pBusyHandler;  /* Pointer to sqlite.busyHandler */
   227    227     PgHdr *pFirst, *pLast;      /* List of free pages */
   228    228     PgHdr *pFirstSynced;        /* First free page with PgHdr.needSync==0 */
   229    229     PgHdr *pAll;                /* List of all pages */
   230    230     PgHdr *pStmt;               /* List of pages in the statement subjournal */
   231         -  PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number to PgHdr */
   232    231     off_t journalOff;           /* Current byte offset in the journal file */
   233    232     off_t journalHdr;           /* Byte offset to previous journal header */
   234    233     off_t stmtHdrOff;           /* First journal header written this statement */
   235    234     off_t stmtCksum;            /* cksumInit when statement was started */
   236    235     int sectorSize;             /* Assumed sector size during rollback */
          236  +  PgHdr *aHash[N_PG_HASH];    /* Hash table to map page number to PgHdr */
   237    237   };
   238    238   
   239    239   /*
   240    240   ** These are bits that can be set in Pager.errMask.
   241    241   */
   242    242   #define PAGER_ERR_FULL     0x01  /* a write() failed */
   243    243   #define PAGER_ERR_MEM      0x02  /* malloc() failed */

Changes to src/printf.c.

    86     86   ** by an instance of the following structure
    87     87   */
    88     88   typedef struct et_info {   /* Information about each format field */
    89     89     char fmttype;            /* The format field code letter */
    90     90     etByte base;             /* The base for radix conversion */
    91     91     etByte flags;            /* One or more of FLAG_ constants below */
    92     92     etByte type;             /* Conversion paradigm */
    93         -  char *charset;           /* The character set for conversion */
    94         -  char *prefix;            /* Prefix on non-zero values in alt format */
           93  +  etByte charset;          /* Offset into aDigits[] of the digits string */
           94  +  etByte prefix;           /* Offset into aPrefix[] of the prefix string */
    95     95   } et_info;
    96     96   
    97     97   /*
    98     98   ** Allowed values for et_info.flags
    99     99   */
   100    100   #define FLAG_SIGNED  1     /* True if the value to convert is signed */
   101    101   #define FLAG_INTERN  2     /* True if for internal use only */
   102    102   
   103    103   
   104    104   /*
   105    105   ** The following table is searched linearly, so it is good to put the
   106    106   ** most frequently used conversion types first.
   107    107   */
          108  +static const char aDigits[] = "0123456789ABCDEF0123456789abcdef";
          109  +static const char aPrefix[] = "-x0\000X0";
   108    110   static et_info fmtinfo[] = {
   109         -  {  'd', 10, 1, etRADIX,      "0123456789",       0    },
   110         -  {  's',  0, 0, etSTRING,     0,                  0    },
   111         -  {  'z',  0, 2, etDYNSTRING,  0,                  0    },
   112         -  {  'q',  0, 0, etSQLESCAPE,  0,                  0    },
   113         -  {  'Q',  0, 0, etSQLESCAPE2, 0,                  0    },
   114         -  {  'c',  0, 0, etCHARX,      0,                  0    },
   115         -  {  'o',  8, 0, etRADIX,      "01234567",         "0"  },
   116         -  {  'u', 10, 0, etRADIX,      "0123456789",       0    },
   117         -  {  'x', 16, 0, etRADIX,      "0123456789abcdef", "x0" },
   118         -  {  'X', 16, 0, etRADIX,      "0123456789ABCDEF", "X0" },
   119         -  {  'f',  0, 1, etFLOAT,      0,                  0    },
   120         -  {  'e',  0, 1, etEXP,        "e",                0    },
   121         -  {  'E',  0, 1, etEXP,        "E",                0    },
   122         -  {  'g',  0, 1, etGENERIC,    "e",                0    },
   123         -  {  'G',  0, 1, etGENERIC,    "E",                0    },
   124         -  {  'i', 10, 1, etRADIX,      "0123456789",       0    },
   125         -  {  'n',  0, 0, etSIZE,       0,                  0    },
   126         -  {  '%',  0, 0, etPERCENT,    0,                  0    },
   127         -  {  'p', 16, 0, etPOINTER,    "0123456789abcdef", "x0" },
   128         -  {  'T',  0, 2, etTOKEN,      0,                  0    },
   129         -  {  'S',  0, 2, etSRCLIST,    0,                  0    },
          111  +  {  'd', 10, 1, etRADIX,      0,  0 },
          112  +  {  's',  0, 0, etSTRING,     0,  0 },
          113  +  {  'z',  0, 2, etDYNSTRING,  0,  0 },
          114  +  {  'q',  0, 0, etSQLESCAPE,  0,  0 },
          115  +  {  'Q',  0, 0, etSQLESCAPE2, 0,  0 },
          116  +  {  'c',  0, 0, etCHARX,      0,  0 },
          117  +  {  'o',  8, 0, etRADIX,      0,  2 },
          118  +  {  'u', 10, 0, etRADIX,      0,  0 },
          119  +  {  'x', 16, 0, etRADIX,      16, 1 },
          120  +  {  'X', 16, 0, etRADIX,      0,  4 },
          121  +  {  'f',  0, 1, etFLOAT,      0,  0 },
          122  +  {  'e',  0, 1, etEXP,        30, 0 },
          123  +  {  'E',  0, 1, etEXP,        14, 0 },
          124  +  {  'g',  0, 1, etGENERIC,    30, 0 },
          125  +  {  'G',  0, 1, etGENERIC,    14, 0 },
          126  +  {  'i', 10, 1, etRADIX,      0,  0 },
          127  +  {  'n',  0, 0, etSIZE,       0,  0 },
          128  +  {  '%',  0, 0, etPERCENT,    0,  0 },
          129  +  {  'p', 16, 0, etPOINTER,    0,  1 },
          130  +  {  'T',  0, 2, etTOKEN,      0,  0 },
          131  +  {  'S',  0, 2, etSRCLIST,    0,  0 },
   130    132   };
   131    133   #define etNINFO  (sizeof(fmtinfo)/sizeof(fmtinfo[0]))
   132    134   
   133    135   /*
   134    136   ** If NOFLOATINGPOINT is defined, then none of the floating point
   135    137   ** conversions will work.
   136    138   */
................................................................................
   373    375           }
   374    376           if( longvalue==0 ) flag_alternateform = 0;
   375    377           if( flag_zeropad && precision<width-(prefix!=0) ){
   376    378             precision = width-(prefix!=0);
   377    379           }
   378    380           bufpt = &buf[etBUFSIZE-1];
   379    381           {
   380         -          register char *cset;      /* Use registers for speed */
          382  +          register const char *cset;      /* Use registers for speed */
   381    383             register int base;
   382         -          cset = infop->charset;
          384  +          cset = &aDigits[infop->charset];
   383    385             base = infop->base;
   384    386             do{                                           /* Convert to ascii */
   385    387               *(--bufpt) = cset[longvalue%base];
   386    388               longvalue = longvalue/base;
   387    389             }while( longvalue>0 );
   388    390           }
   389    391           length = &buf[etBUFSIZE-1]-bufpt;
   390    392           for(idx=precision-length; idx>0; idx--){
   391    393             *(--bufpt) = '0';                             /* Zero pad */
   392    394           }
   393    395           if( prefix ) *(--bufpt) = prefix;               /* Add sign */
   394    396           if( flag_alternateform && infop->prefix ){      /* Add "0" or "0x" */
   395         -          char *pre, x;
   396         -          pre = infop->prefix;
          397  +          const char *pre;
          398  +          char x;
          399  +          pre = &aPrefix[infop->prefix];
   397    400             if( *bufpt!=pre[0] ){
   398         -            for(pre=infop->prefix; (x=(*pre))!=0; pre++) *(--bufpt) = x;
          401  +            for(; (x=(*pre))!=0; pre++) *(--bufpt) = x;
   399    402             }
   400    403           }
   401    404           length = &buf[etBUFSIZE-1]-bufpt;
   402    405           break;
   403    406         case etFLOAT:
   404    407         case etEXP:
   405    408         case etGENERIC:
................................................................................
   489    492             bufpt--;                            /* point to last digit */
   490    493             if( flag_rtz && flag_dp ){          /* Remove tail zeros */
   491    494               while( bufpt>=buf && *bufpt=='0' ) *(bufpt--) = 0;
   492    495               if( bufpt>=buf && *bufpt=='.' ) *(bufpt--) = 0;
   493    496             }
   494    497             bufpt++;                            /* point to next free slot */
   495    498             if( exp || flag_exp ){
   496         -            *(bufpt++) = infop->charset[0];
          499  +            *(bufpt++) = aDigits[infop->charset];
   497    500               if( exp<0 ){ *(bufpt++) = '-'; exp = -exp; } /* sign of exp */
   498    501               else       { *(bufpt++) = '+'; }
   499    502               if( exp>=100 ){
   500    503                 *(bufpt++) = (exp/100)+'0';                /* 100's digit */
   501    504                 exp %= 100;
   502    505               }
   503    506               *(bufpt++) = exp/10+'0';                     /* 10's digit */
................................................................................
   805    808   #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
   806    809   /*
   807    810   ** A version of printf() that understands %lld.  Used for debugging.
   808    811   ** The printf() built into some versions of windows does not understand %lld
   809    812   ** and segfaults if you give it a long long int.
   810    813   */
   811    814   void sqlite3DebugPrintf(const char *zFormat, ...){
          815  +  extern int getpid(void);
   812    816     va_list ap;
   813    817     char zBuf[500];
   814    818     va_start(ap, zFormat);
   815    819     base_vprintf(0, 0, zBuf, sizeof(zBuf), zFormat, ap);
   816    820     va_end(ap);
   817    821     fprintf(stdout,"%d: %s", getpid(), zBuf);
   818    822     fflush(stdout);
   819    823   }
   820    824   #endif

Changes to src/vdbeaux.c.

    50     50   
    51     51   /*
    52     52   ** Turn tracing on or off
    53     53   */
    54     54   void sqlite3VdbeTrace(Vdbe *p, FILE *trace){
    55     55     p->trace = trace;
    56     56   }
           57  +
           58  +/*
           59  +** Resize the Vdbe.aOp array so that it contains at least N
           60  +** elements.
           61  +*/
           62  +static void resizeOpArray(Vdbe *p, int N){
           63  +  if( p->nOpAlloc<N ){
           64  +    int oldSize = p->nOpAlloc;
           65  +    p->nOpAlloc = N+100;
           66  +    p->aOp = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
           67  +    if( p->aOp ){
           68  +      memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
           69  +    }
           70  +  }
           71  +}
    57     72   
    58     73   /*
    59     74   ** Add a new instruction to the list of instructions current in the
    60     75   ** VDBE.  Return the address of the new instruction.
    61     76   **
    62     77   ** Parameters:
    63     78   **
................................................................................
    74     89   int sqlite3VdbeAddOp(Vdbe *p, int op, int p1, int p2){
    75     90     int i;
    76     91     VdbeOp *pOp;
    77     92   
    78     93     i = p->nOp;
    79     94     p->nOp++;
    80     95     assert( p->magic==VDBE_MAGIC_INIT );
    81         -  if( i>=p->nOpAlloc ){
    82         -    int oldSize = p->nOpAlloc;
    83         -    Op *aNew;
    84         -    p->nOpAlloc = p->nOpAlloc*2 + 100;
    85         -    aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
    86         -    if( aNew==0 ){
    87         -      p->nOpAlloc = oldSize;
    88         -      return 0;
    89         -    }
    90         -    p->aOp = aNew;
    91         -    memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
           96  +  resizeOpArray(p, i+1);
           97  +  if( p->aOp==0 ){
           98  +    return 0;
    92     99     }
    93    100     pOp = &p->aOp[i];
    94    101     pOp->opcode = op;
    95    102     pOp->p1 = p1;
    96         -  if( p2<0 && (-1-p2)<p->nLabel && p->aLabel[-1-p2]>=0 ){
    97         -    p2 = p->aLabel[-1-p2];
    98         -  }
    99    103     pOp->p2 = p2;
   100    104     pOp->p3 = 0;
   101    105     pOp->p3type = P3_NOTUSED;
   102    106   #ifndef NDEBUG
   103    107     if( sqlite3_vdbe_addop_trace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
   104    108   #endif
   105    109     return i;
................................................................................
   129    133   ** Zero is returned if a malloc() fails.
   130    134   */
   131    135   int sqlite3VdbeMakeLabel(Vdbe *p){
   132    136     int i;
   133    137     i = p->nLabel++;
   134    138     assert( p->magic==VDBE_MAGIC_INIT );
   135    139     if( i>=p->nLabelAlloc ){
   136         -    int *aNew;
   137    140       p->nLabelAlloc = p->nLabelAlloc*2 + 10;
   138         -    aNew = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
   139         -    if( aNew==0 ){
   140         -      sqliteFree(p->aLabel);
   141         -    }
   142         -    p->aLabel = aNew;
          141  +    p->aLabel = sqliteRealloc( p->aLabel, p->nLabelAlloc*sizeof(p->aLabel[0]));
   143    142     }
   144         -  if( p->aLabel==0 ){
   145         -    p->nLabel = 0;
   146         -    p->nLabelAlloc = 0;
   147         -    return 0;
          143  +  if( p->aLabel ){
          144  +    p->aLabel[i] = -1;
   148    145     }
   149         -  p->aLabel[i] = -1;
   150    146     return -1-i;
   151    147   }
   152    148   
   153    149   /*
   154    150   ** Resolve label "x" to be the address of the next instruction to
   155    151   ** be inserted.  The parameter "x" must have been obtained from
   156    152   ** a prior call to sqlite3VdbeMakeLabel().
   157    153   */
   158    154   void sqlite3VdbeResolveLabel(Vdbe *p, int x){
   159         -  int j;
          155  +  int j = -1-x;
   160    156     assert( p->magic==VDBE_MAGIC_INIT );
   161         -  if( x<0 && (-x)<=p->nLabel && p->aOp ){
   162         -    if( p->aLabel[-1-x]==p->nOp ) return;
   163         -    assert( p->aLabel[-1-x]<0 );
   164         -    p->aLabel[-1-x] = p->nOp;
   165         -    for(j=0; j<p->nOp; j++){
   166         -      if( p->aOp[j].p2==x ) p->aOp[j].p2 = p->nOp;
   167         -    }
          157  +  assert( j>=0 && j<p->nLabel );
          158  +  if( p->aLabel ){
          159  +    p->aLabel[j] = p->nOp;
   168    160     }
   169    161   }
          162  +
          163  +/*
          164  +** Loop through the program looking for P2 values that are negative.
          165  +** Each such value is a label.  Resolve the label by setting the P2
          166  +** value to its correct non-zero value.
          167  +**
          168  +** This routine is called once after all opcodes have been inserted.
          169  +*/
          170  +static void resolveP2Values(Vdbe *p){
          171  +  int i;
          172  +  Op *pOp;
          173  +  int *aLabel = p->aLabel;
          174  +  if( aLabel==0 ) return;
          175  +  for(pOp=p->aOp, i=p->nOp-1; i>=0; i--, pOp++){
          176  +    if( pOp->p2>=0 ) continue;
          177  +    assert( -1-pOp->p2<p->nLabel );
          178  +    pOp->p2 = aLabel[-1-pOp->p2];
          179  +  }
          180  +  sqliteFree(p->aLabel);
          181  +  p->aLabel = 0;
          182  +}
   170    183   
   171    184   /*
   172    185   ** Return the address of the next instruction to be inserted.
   173    186   */
   174    187   int sqlite3VdbeCurrentAddr(Vdbe *p){
   175    188     assert( p->magic==VDBE_MAGIC_INIT );
   176    189     return p->nOp;
................................................................................
   179    192   /*
   180    193   ** Add a whole list of operations to the operation stack.  Return the
   181    194   ** address of the first operation added.
   182    195   */
   183    196   int sqlite3VdbeAddOpList(Vdbe *p, int nOp, VdbeOpList const *aOp){
   184    197     int addr;
   185    198     assert( p->magic==VDBE_MAGIC_INIT );
   186         -  if( p->nOp + nOp >= p->nOpAlloc ){
   187         -    int oldSize = p->nOpAlloc;
   188         -    Op *aNew;
   189         -    p->nOpAlloc = p->nOpAlloc*2 + nOp + 10;
   190         -    aNew = sqliteRealloc(p->aOp, p->nOpAlloc*sizeof(Op));
   191         -    if( aNew==0 ){
   192         -      p->nOpAlloc = oldSize;
   193         -      return 0;
   194         -    }
   195         -    p->aOp = aNew;
   196         -    memset(&p->aOp[oldSize], 0, (p->nOpAlloc-oldSize)*sizeof(Op));
          199  +  resizeOpArray(p, p->nOp + nOp);
          200  +  if( p->aOp==0 ){
          201  +    return 0;
   197    202     }
   198    203     addr = p->nOp;
   199    204     if( nOp>0 ){
   200    205       int i;
   201    206       VdbeOpList const *pIn = aOp;
   202    207       for(i=0; i<nOp; i++, pIn++){
   203    208         int p2 = pIn->p2;
................................................................................
   308    313   /*
   309    314   ** Replace the P3 field of the most recently coded instruction with
   310    315   ** comment text.
   311    316   */
   312    317   void sqlite3VdbeComment(Vdbe *p, const char *zFormat, ...){
   313    318     va_list ap;
   314    319     assert( p->nOp>0 );
   315         -  assert( p->aOp[p->nOp-1].p3==0 );
          320  +  assert( p->aOp==0 || p->aOp[p->nOp-1].p3==0 );
   316    321     va_start(ap, zFormat);
   317    322     sqlite3VdbeChangeP3(p, -1, sqlite3VMPrintf(zFormat, ap), P3_DYNAMIC);
   318    323     va_end(ap);
   319    324   }
   320    325   #endif
   321    326   
   322    327   /*
................................................................................
   451    456     if( pOut==0 ) pOut = stdout;
   452    457     zP3 = displayP3(pOp, zPtr, sizeof(zPtr));
   453    458     fprintf(pOut, zFormat1,
   454    459         pc, sqlite3OpcodeNames[pOp->opcode], pOp->p1, pOp->p2, zP3);
   455    460     fflush(pOut);
   456    461   }
   457    462   #endif
          463  +
          464  +/*
          465  +** Release an array of N Mem elements
          466  +*/
          467  +static void releaseMemArray(Mem *p, int N){
          468  +  if( p ){
          469  +    while( N-->0 ){
          470  +      sqlite3VdbeMemRelease(p++);
          471  +    }
          472  +  }
          473  +}
   458    474   
   459    475   /*
   460    476   ** Give a listing of the program in the virtual machine.
   461    477   **
   462    478   ** The interface is the same as sqlite3VdbeExec().  But instead of
   463    479   ** running the code, it invokes the callback once for each instruction.
   464    480   ** This feature is used to implement "EXPLAIN".
................................................................................
   473    489     assert( p->explain );
   474    490   
   475    491     /* Even though this opcode does not put dynamic strings onto the
   476    492     ** the stack, they may become dynamic if the user calls
   477    493     ** sqlite3_column_text16(), causing a translation to UTF-16 encoding.
   478    494     */
   479    495     if( p->pTos==&p->aStack[4] ){
   480         -    for(i=0; i<5; i++){
   481         -      sqlite3VdbeMemRelease(&p->aStack[i]);
   482         -      p->aStack[i].flags = 0;
   483         -    }
          496  +    releaseMemArray(p->aStack, 5);
   484    497     }
   485    498     p->resOnStack = 0;
   486    499   
   487    500     i = p->pc++;
   488    501     if( i>=p->nOp ){
   489    502       p->rc = SQLITE_OK;
   490    503       rc = SQLITE_DONE;
................................................................................
   582    595     ** stack.  And the stack never grows on successive executions of the
   583    596     ** same loop.  So the total number of instructions is an upper bound
   584    597     ** on the maximum stack depth required.
   585    598     **
   586    599     ** Allocation all the stack space we will ever need.
   587    600     */
   588    601     if( p->aStack==0 ){
          602  +    resolveP2Values(p);
   589    603       assert( nVar>=0 );
   590    604       n = isExplain ? 10 : p->nOp;
   591    605       p->aStack = sqliteMalloc(
   592    606         n*(sizeof(p->aStack[0])+sizeof(Mem*))          /* aStack, apArg */
   593    607         + nVar*sizeof(Mem)                             /* aVar */
   594    608         + nVar*sizeof(char*)                           /* azVar */
   595    609         + nMem*sizeof(Mem)                             /* aMem */
................................................................................
   842    856   ** This routine will automatically close any cursors, lists, and/or
   843    857   ** sorters that were left open.  It also deletes the values of
   844    858   ** variables in the aVar[] array.
   845    859   */
   846    860   static void Cleanup(Vdbe *p){
   847    861     int i;
   848    862     if( p->aStack ){
   849         -    Mem *pTos = p->pTos;
   850         -    while( pTos>=p->aStack ){
   851         -      sqlite3VdbeMemRelease(pTos);
   852         -      pTos--;
   853         -    }
   854         -    p->pTos = pTos;
          863  +    releaseMemArray(p->aStack, 1 + (p->pTos - p->aStack));
          864  +    p->pTos = &p->aStack[-1];
   855    865     }
   856    866     closeAllCursors(p);
   857         -  for(i=0; i<p->nMem; i++){
   858         -    sqlite3VdbeMemRelease(&p->aMem[i]);
   859         -  }
          867  +  releaseMemArray(p->aMem, p->nMem);
   860    868     if( p->pList ){
   861    869       sqlite3VdbeKeylistFree(p->pList);
   862    870       p->pList = 0;
   863    871     }
   864         -  for(i=0; i<p->contextStackTop; i++){
   865         -    sqlite3VdbeKeylistFree(p->contextStack[i].pList);
          872  +  if( p->contextStack ){
          873  +    for(i=0; i<p->contextStackTop; i++){
          874  +      sqlite3VdbeKeylistFree(p->contextStack[i].pList);
          875  +    }
          876  +    sqliteFree(p->contextStack);
   866    877     }
   867    878     sqlite3VdbeSorterReset(p);
   868    879     sqlite3VdbeAggReset(0, &p->agg, 0);
   869         -  sqliteFree(p->contextStack);
   870    880     p->contextStack = 0;
   871    881     p->contextStackDepth = 0;
   872    882     p->contextStackTop = 0;
   873    883     sqliteFree(p->zErrMsg);
   874    884     p->zErrMsg = 0;
   875    885   }
   876    886   
................................................................................
   877    887   /*
   878    888   ** Set the number of result columns that will be returned by this SQL
   879    889   ** statement. This is now set at compile time, rather than during
   880    890   ** execution of the vdbe program so that sqlite3_column_count() can
   881    891   ** be called on an SQL statement before sqlite3_step().
   882    892   */
   883    893   void sqlite3VdbeSetNumCols(Vdbe *p, int nResColumn){
          894  +  Mem *pColName;
          895  +  int n;
   884    896     assert( 0==p->nResColumn );
   885    897     p->nResColumn = nResColumn;
          898  +  n = nResColumn*2;
          899  +  p->aColName = pColName = (Mem*)sqliteMalloc( sizeof(Mem)*n );
          900  +  if( p->aColName==0 ) return;
          901  +  while( n-- > 0 ){
          902  +    (pColName++)->flags = MEM_Null;
          903  +  }
   886    904   }
   887    905   
   888    906   /*
   889    907   ** Set the name of the idx'th column to be returned by the SQL statement.
   890    908   ** zName must be a pointer to a nul terminated string.
   891    909   **
   892    910   ** This call must be made after a call to sqlite3VdbeSetNumCols().
................................................................................
   896    914   ** the string is freed using sqliteFree() when the vdbe is finished with
   897    915   ** it. Otherwise, N bytes of zName are copied.
   898    916   */
   899    917   int sqlite3VdbeSetColName(Vdbe *p, int idx, const char *zName, int N){
   900    918     int rc;
   901    919     Mem *pColName;
   902    920     assert( idx<(2*p->nResColumn) );
   903         -
   904         -  /* If the Vdbe.aColName array has not yet been allocated, allocate
   905         -  ** it now.
   906         -  */
   907         -  if( !p->aColName ){
   908         -    int i;
   909         -    p->aColName = (Mem *)sqliteMalloc(sizeof(Mem)*p->nResColumn*2);
   910         -    if( !p->aColName ){
   911         -      return SQLITE_NOMEM;
   912         -    }
   913         -    for(i=0; i<(2*p->nResColumn); i++){
   914         -      p->aColName[i].flags = MEM_Null;
   915         -    }
   916         -  }
   917         -
          921  +  if( sqlite3_malloc_failed ) return SQLITE_NOMEM;
          922  +  assert( p->aColName!=0 );
   918    923     pColName = &(p->aColName[idx]);
   919    924     if( N==P3_DYNAMIC || N==P3_STATIC ){
   920    925       rc = sqlite3VdbeMemSetStr(pColName, zName, -1, SQLITE_UTF8, SQLITE_STATIC);
   921    926     }else{
   922    927       rc = sqlite3VdbeMemSetStr(pColName, zName, N, SQLITE_UTF8,SQLITE_TRANSIENT);
   923    928     }
   924    929     if( rc==SQLITE_OK && N==P3_DYNAMIC ){
................................................................................
  1377   1382     }else{
  1378   1383       assert( p->db->pVdbe==p );
  1379   1384       p->db->pVdbe = p->pNext;
  1380   1385     }
  1381   1386     if( p->pNext ){
  1382   1387       p->pNext->pPrev = p->pPrev;
  1383   1388     }
  1384         -  p->pPrev = p->pNext = 0;
  1385         -  if( p->nOpAlloc==0 ){
  1386         -    p->aOp = 0;
  1387         -    p->nOp = 0;
  1388         -  }
  1389         -  for(i=0; i<p->nOp; i++){
  1390         -    Op *pOp = &p->aOp[i];
  1391         -    if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
  1392         -      sqliteFree(pOp->p3);
         1389  +  if( p->aOp ){
         1390  +    for(i=0; i<p->nOp; i++){
         1391  +      Op *pOp = &p->aOp[i];
         1392  +      if( pOp->p3type==P3_DYNAMIC || pOp->p3type==P3_KEYINFO ){
         1393  +        sqliteFree(pOp->p3);
         1394  +      }
         1395  +      if( pOp->p3type==P3_VDBEFUNC ){
         1396  +        VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
         1397  +        sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
         1398  +        sqliteFree(pVdbeFunc);
         1399  +      }
  1393   1400       }
  1394         -    if( pOp->p3type==P3_VDBEFUNC ){
  1395         -      VdbeFunc *pVdbeFunc = (VdbeFunc *)pOp->p3;
  1396         -      sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
  1397         -      sqliteFree(pVdbeFunc);
  1398         -    }
         1401  +    sqliteFree(p->aOp);
  1399   1402     }
  1400         -  for(i=0; i<p->nVar; i++){
  1401         -    sqlite3VdbeMemRelease(&p->aVar[i]);
  1402         -  }
  1403         -  sqliteFree(p->aOp);
         1403  +  releaseMemArray(p->aVar, p->nVar);
  1404   1404     sqliteFree(p->aLabel);
  1405   1405     sqliteFree(p->aStack);
  1406         -  if( p->aColName ){
  1407         -    for(i=0; i<(p->nResColumn)*2; i++){
  1408         -      sqlite3VdbeMemRelease(&(p->aColName[i]));
  1409         -    }
  1410         -    sqliteFree(p->aColName);
  1411         -  }
         1406  +  releaseMemArray(p->aColName, p->nResColumn*2);
         1407  +  sqliteFree(p->aColName);
  1412   1408     p->magic = VDBE_MAGIC_DEAD;
  1413   1409     sqliteFree(p);
  1414   1410   }
  1415   1411   
  1416   1412   /*
  1417   1413   ** If a MoveTo operation is pending on the given cursor, then do that
  1418   1414   ** MoveTo now.  Return an error code.  If no MoveTo is pending, this