/ Check-in [8bbfa978]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:The compound-select merge optimization passes quick.test with no errors. (CVS 5299)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 8bbfa97837a74ef0514e0c92ea2a6576f02cc361
User & Date: drh 2008-06-25 00:12:41
References
2013-05-06
15:21 New ticket [6709574d] COLLATE clause in ORDER BY causes incorrect EXCEPT. artifact: 5bbf9ac1 user: drh
Context
2008-06-25
02:22
Add new test script for compound select statements. (CVS 5300) check-in: a193b161 user: drh tags: trunk
00:12
The compound-select merge optimization passes quick.test with no errors. (CVS 5299) check-in: 8bbfa978 user: drh tags: trunk
2008-06-24
22:50
OS/2 fixes for pre-C99 compilers and a return code correction in os2Access(). (CVS 5298) check-in: 3241a3bd user: pweilbacher tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/select.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains C code routines that are called by the parser
    13     13   ** to handle SELECT statements in SQLite.
    14     14   **
    15         -** $Id: select.c,v 1.435 2008/06/24 12:46:31 drh Exp $
           15  +** $Id: select.c,v 1.436 2008/06/25 00:12:41 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   
    20     20   /*
    21     21   ** Delete all the content of a Select structure but do not deallocate
    22     22   ** the select structure itself.
................................................................................
   426    426     sqlite3VdbeAddOp3(v, OP_MakeRecord, regBase, nExpr + 2, regRecord);
   427    427     sqlite3VdbeAddOp2(v, OP_IdxInsert, pOrderBy->iECursor, regRecord);
   428    428     sqlite3ReleaseTempReg(pParse, regRecord);
   429    429     sqlite3ReleaseTempRange(pParse, regBase, nExpr+2);
   430    430     if( pSelect->iLimit ){
   431    431       int addr1, addr2;
   432    432       int iLimit;
   433         -    if( pSelect->pOffset ){
          433  +    if( pSelect->iOffset ){
   434    434         iLimit = pSelect->iOffset+1;
   435    435       }else{
   436    436         iLimit = pSelect->iLimit;
   437    437       }
   438    438       addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit);
   439    439       sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
   440    440       addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
................................................................................
   557    557     */
   558    558     if( nColumn>0 ){
   559    559       nResultCol = nColumn;
   560    560     }else{
   561    561       nResultCol = pEList->nExpr;
   562    562     }
   563    563     if( pDest->iMem==0 ){
   564         -    pDest->iMem = sqlite3GetTempRange(pParse, nResultCol);
          564  +    pDest->iMem = pParse->nMem+1;
   565    565       pDest->nMem = nResultCol;
          566  +    pParse->nMem += nResultCol;
   566    567     }else if( pDest->nMem!=nResultCol ){
   567    568       /* This happens when two SELECTs of a compound SELECT have differing
   568    569       ** numbers of result columns.  The error message will be generated by
   569    570       ** a higher-level routine. */
   570    571       return;
   571    572     }
   572    573     regResult = pDest->iMem;
................................................................................
  1783   1784   ** SELECT statements.
  1784   1785   */
  1785   1786   static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
  1786   1787     Vdbe *v = 0;
  1787   1788     int iLimit = 0;
  1788   1789     int iOffset;
  1789   1790     int addr1;
         1791  +  if( p->iLimit ) return;
  1790   1792   
  1791   1793     /* 
  1792   1794     ** "LIMIT -1" always shows all rows.  There is some
  1793   1795     ** contraversy about what the correct behavior should be.
  1794   1796     ** The current implementation interprets "LIMIT 0" to mean
  1795   1797     ** no rows.
  1796   1798     */
................................................................................
  1967   1969     if( p->pEList->nExpr!=pPrior->pEList->nExpr ){
  1968   1970       sqlite3ErrorMsg(pParse, "SELECTs to the left and right of %s"
  1969   1971         " do not have the same number of result columns", selectOpName(p->op));
  1970   1972       rc = 1;
  1971   1973       goto multi_select_end;
  1972   1974     }
  1973   1975   
  1974         -#if 0
         1976  +#if 1
  1975   1977     if( p->pOrderBy ){
  1976   1978       return multiSelectOrderBy(pParse, p, pDest, aff);
  1977   1979     }
  1978   1980   #endif
  1979   1981   
  1980   1982     /* Generate code for the left and right SELECT statements.
  1981   1983     */
................................................................................
  2308   2310     return rc;
  2309   2311   }
  2310   2312   #endif /* SQLITE_OMIT_COMPOUND_SELECT */
  2311   2313   
  2312   2314   /*
  2313   2315   ** Code an output subroutine for a coroutine implementation of a
  2314   2316   ** SELECT statment.
         2317  +**
         2318  +** The data to be output is contained in pIn->iMem.  There are
         2319  +** pIn->nMem columns to be output.  pDest is where the output should
         2320  +** be sent.
         2321  +**
         2322  +** regReturn is the number of the register holding the subroutine
         2323  +** return address.
         2324  +**
         2325  +** If regPrev>0 then it is a the first register in a vector that
         2326  +** records the previous output.  mem[regPrev] is a flag that is false
         2327  +** if there has been no previous output.  If regPrev>0 then code is
         2328  +** generated to suppress duplicates.  pKeyInfo is used for comparing
         2329  +** keys.
         2330  +**
         2331  +** If the LIMIT found in p->iLimit is reached, jump immediately to
         2332  +** iBreak.
  2315   2333   */
  2316         -static int outputSubroutine(
         2334  +static int generateOutputSubroutine(
  2317   2335     Parse *pParse,          /* Parsing context */
  2318   2336     Select *p,              /* The SELECT statement */
  2319   2337     SelectDest *pIn,        /* Coroutine supplying data */
  2320   2338     SelectDest *pDest,      /* Where to send the data */
  2321   2339     int regReturn,          /* The return address register */
         2340  +  int regPrev,            /* Previous result register.  No uniqueness if 0 */
         2341  +  KeyInfo *pKeyInfo,      /* For comparing with previous entry */
         2342  +  int p4type,             /* The p4 type for pKeyInfo */
  2322   2343     int iBreak              /* Jump here if we hit the LIMIT */
  2323   2344   ){
  2324   2345     Vdbe *v = pParse->pVdbe;
  2325   2346     int iContinue;
  2326   2347     int addr;
  2327   2348     if( v==0 ) return 0;
  2328   2349   
  2329   2350     addr = sqlite3VdbeCurrentAddr(v);
  2330   2351     iContinue = sqlite3VdbeMakeLabel(v);
         2352  +
         2353  +  /* Suppress duplicates for UNION, EXCEPT, and INTERSECT 
         2354  +  */
         2355  +  if( regPrev ){
         2356  +    int j1, j2;
         2357  +    j1 = sqlite3VdbeAddOp1(v, OP_IfNot, regPrev);
         2358  +    j2 = sqlite3VdbeAddOp4(v, OP_Compare, pIn->iMem, regPrev+1, pIn->nMem,
         2359  +                              (char*)pKeyInfo, p4type);
         2360  +    sqlite3VdbeAddOp3(v, OP_Jump, j2+2, iContinue, j2+2);
         2361  +    sqlite3VdbeJumpHere(v, j1);
         2362  +    sqlite3ExprCodeCopy(pParse, pIn->iMem, regPrev+1, pIn->nMem);
         2363  +    sqlite3VdbeAddOp2(v, OP_Integer, 1, regPrev);
         2364  +  }
         2365  +
         2366  +  /* Suppress the the first OFFSET entries if there is an OFFSET clause
         2367  +  */
  2331   2368     codeOffset(v, p, iContinue);
  2332   2369   
  2333   2370     switch( pDest->eDest ){
  2334   2371       /* Store the result as data using a unique key.
  2335   2372       */
  2336   2373       case SRT_Table:
  2337   2374       case SRT_EphemTab: {
................................................................................
  2421   2458     /* Jump to the end of the loop if the LIMIT is reached.
  2422   2459     */
  2423   2460     if( p->iLimit ){
  2424   2461       sqlite3VdbeAddOp2(v, OP_AddImm, p->iLimit, -1);
  2425   2462       sqlite3VdbeAddOp2(v, OP_IfZero, p->iLimit, iBreak);
  2426   2463     }
  2427   2464   
  2428         -  /* Advance the coroutine to its next value.
  2429         -  */
  2430         -  sqlite3VdbeResolveLabel(v, iContinue);
  2431         -  sqlite3VdbeAddOp1(v, OP_Yield, pIn->iParm);
  2432         -
  2433   2465     /* Generate the subroutine return
  2434   2466     */
         2467  +  sqlite3VdbeResolveLabel(v, iContinue);
  2435   2468     sqlite3VdbeAddOp1(v, OP_Return, regReturn);
  2436   2469   
  2437   2470     return addr;
  2438   2471   }
  2439   2472   
  2440   2473   /*
  2441   2474   ** Alternative compound select code generator for cases when there
................................................................................
  2471   2504   **
  2472   2505   ** The implementation of the latter five subroutines depend on which 
  2473   2506   ** <operator> is used:
  2474   2507   **
  2475   2508   **
  2476   2509   **             UNION ALL         UNION            EXCEPT          INTERSECT
  2477   2510   **          -------------  -----------------  --------------  -----------------
  2478         -**   AltB:   outA, nextA      outA, nextA       outA, nextA        nextA
         2511  +**   AltB:   outA, nextA      outA, nextA       outA, nextA         nextA
  2479   2512   **
  2480         -**   AeqB:   outA, nextA         nextA             nextA           outA
  2481         -**                                                            nextA while A==B
         2513  +**   AeqB:   outA, nextA         nextA             nextA         outA, nextA
  2482   2514   **
  2483         -**   AgtB:   outB, nextB      outB, nextB          nextB           nextB
         2515  +**   AgtB:   outB, nextB      outB, nextB          nextB            nextB
  2484   2516   **
  2485         -**   EofA:   outB, nextB      A<-B, outB,          halt            halt
  2486         -**                          nextB while A==B
         2517  +**   EofA:   outB, nextB      outB, nextB          halt             halt
  2487   2518   **
  2488         -**   EofB:   outA, nextA      B<-A, outA        outA, nextA        halt
  2489         -**                          nextA while A==B
         2519  +**   EofB:   outA, nextA      outA, nextA       outA, nextA         halt
         2520  +**
         2521  +** In the AltB, AeqB, and AgtB subroutines, an EOF on A following nextA
         2522  +** causes an immediate jump to EofA and an EOF on B following nextB causes
         2523  +** an immediate jump to EofB.  Within EofA and EofB, and EOF on entry or
         2524  +** following nextX causes a jump to the end of the select processing.
         2525  +**
         2526  +** Duplicate removal in the UNION, EXCEPT, and INTERSECT cases is handled
         2527  +** within the output subroutine.  The regPrev register set holds the previously
         2528  +** output value.  A comparison is made against this value and the output
         2529  +** is skipped if the next results would be the same as the previous.
  2490   2530   **
  2491   2531   ** The implementation plan is to implement the two coroutines and seven
  2492   2532   ** subroutines first, then put the control logic at the bottom.  Like this:
  2493   2533   **
  2494   2534   **          goto Init
  2495   2535   **     coA: coroutine for left query (A)
  2496   2536   **     coB: coroutine for right query (B)
................................................................................
  2517   2557   */
  2518   2558   static int multiSelectOrderBy(
  2519   2559     Parse *pParse,        /* Parsing context */
  2520   2560     Select *p,            /* The right-most of SELECTs to be coded */
  2521   2561     SelectDest *pDest,    /* What to do with query results */
  2522   2562     char *aff             /* If eDest is SRT_Union, the affinity string */
  2523   2563   ){
         2564  +  int i, j;             /* Loop counters */
  2524   2565     Select *pPrior;       /* Another SELECT immediately to our left */
  2525   2566     Vdbe *v;              /* Generate code to this VDBE */
  2526   2567     SelectDest destA;     /* Destination for coroutine A */
  2527   2568     SelectDest destB;     /* Destination for coroutine B */
  2528   2569     int regAddrA;         /* Address register for select-A coroutine */
  2529   2570     int regEofA;          /* Flag to indicate when select-A is complete */
  2530   2571     int regAddrB;         /* Address register for select-B coroutine */
................................................................................
  2538   2579     int addrEofA;         /* Address of the select-A-exhausted subroutine */
  2539   2580     int addrEofB;         /* Address of the select-B-exhausted subroutine */
  2540   2581     int addrAltB;         /* Address of the A<B subroutine */
  2541   2582     int addrAeqB;         /* Address of the A==B subroutine */
  2542   2583     int addrAgtB;         /* Address of the A>B subroutine */
  2543   2584     int regLimitA;        /* Limit register for select-A */
  2544   2585     int regLimitB;        /* Limit register for select-A */
         2586  +  int regPrev;          /* A range of registers to hold previous output */
  2545   2587     int savedLimit;       /* Saved value of p->iLimit */
  2546   2588     int savedOffset;      /* Saved value of p->iOffset */
  2547   2589     int labelCmpr;        /* Label for the start of the merge algorithm */
  2548   2590     int labelEnd;         /* Label for the end of the overall SELECT stmt */
  2549         -  int j1, j2, j3;       /* Jump instructions that get retargetted */
         2591  +  int j1;               /* Jump instructions that get retargetted */
  2550   2592     int op;               /* One of TK_ALL, TK_UNION, TK_EXCEPT, TK_INTERSECT */
  2551         -  KeyInfo *pKeyInfo;    /* Type data for comparisons */
  2552         -  int p4type;           /* P4 type used for pKeyInfo */
         2593  +  KeyInfo *pKeyDup;     /* Comparison information for duplicate removal */
         2594  +  KeyInfo *pKeyMerge;   /* Comparison information for merging rows */
         2595  +  sqlite3 *db;          /* Database connection */
         2596  +  ExprList *pOrderBy;   /* The ORDER BY clause */
         2597  +  int nOrderBy;         /* Number of terms in the ORDER BY clause */
         2598  +  int *aPermute;        /* Mapping from ORDER BY terms to result set columns */
         2599  +  u8 NotUsed;           /* Dummy variables */
  2553   2600   
  2554   2601     assert( p->pOrderBy!=0 );
         2602  +  db = pParse->db;
  2555   2603     v = pParse->pVdbe;
  2556   2604     if( v==0 ) return SQLITE_NOMEM;
  2557   2605     labelEnd = sqlite3VdbeMakeLabel(v);
  2558   2606     labelCmpr = sqlite3VdbeMakeLabel(v);
  2559         -  pKeyInfo = keyInfoFromExprList(pParse, p->pEList);
  2560         -  p4type = P4_KEYINFO_HANDOFF;
         2607  +
  2561   2608   
  2562   2609     /* Patch up the ORDER BY clause
  2563   2610     */
  2564   2611     op = p->op;  
  2565   2612     pPrior = p->pPrior;
  2566   2613     assert( pPrior->pOrderBy==0 );
  2567         -  if( processCompoundOrderBy(pParse, p, 0) ){
  2568         -    return SQLITE_ERROR;
  2569         -  }
  2570         -  pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, p->pOrderBy);
         2614  +  pOrderBy = p->pOrderBy;
         2615  +  if( pOrderBy ){
         2616  +    if( processCompoundOrderBy(pParse, p, 0) ){
         2617  +      return SQLITE_ERROR;
         2618  +    }
         2619  +    nOrderBy = pOrderBy->nExpr;
         2620  +  }else{
         2621  +    nOrderBy = 0;
         2622  +  }
         2623  +  /* For operators other than UNION ALL we have to make sure that
         2624  +  ** the ORDER BY clause covers every term of the result set.  Add
         2625  +  ** terms to the ORDER BY clause as necessary.
         2626  +  */
         2627  +  if( op!=TK_ALL ){
         2628  +    for(i=1; db->mallocFailed==0 && i<=p->pEList->nExpr; i++){
         2629  +      for(j=0; j<nOrderBy; j++){
         2630  +        Expr *pTerm = pOrderBy->a[j].pExpr;
         2631  +        assert( pTerm->op==TK_INTEGER );
         2632  +        assert( (pTerm->flags & EP_IntValue)!=0 );
         2633  +        if( pTerm->iTable==i ) break;
         2634  +      }
         2635  +      if( j==nOrderBy ){
         2636  +        Expr *pNew = sqlite3PExpr(pParse, TK_INTEGER, 0, 0, 0);
         2637  +        if( pNew==0 ) return SQLITE_NOMEM;
         2638  +        pNew->flags |= EP_IntValue;
         2639  +        pNew->iTable = i;
         2640  +        pOrderBy = sqlite3ExprListAppend(pParse, pOrderBy, pNew, 0);
         2641  +        nOrderBy++;
         2642  +      }
         2643  +    }
         2644  +  }
         2645  +
         2646  +  /* Compute the comparison permutation and keyinfo that is used with
         2647  +  ** the permutation in order to comparisons to determine if the next
         2648  +  ** row of results comes from selectA or selectB.  Also add explicit
         2649  +  ** collations to the ORDER BY clause terms so that when the subqueries
         2650  +  ** to the right and the left are evaluated, they use the correct
         2651  +  ** collation.
         2652  +  */
         2653  +  aPermute = sqlite3DbMallocRaw(db, sizeof(int)*nOrderBy);
         2654  +  if( aPermute ){
         2655  +    for(i=0; i<nOrderBy; i++){
         2656  +      Expr *pTerm = pOrderBy->a[i].pExpr;
         2657  +      assert( pTerm->op==TK_INTEGER );
         2658  +      assert( (pTerm->flags & EP_IntValue)!=0 );
         2659  +      aPermute[i] = pTerm->iTable-1;
         2660  +      assert( aPermute[i]>=0 && aPermute[i]<p->pEList->nExpr );
         2661  +    }
         2662  +    pKeyMerge =
         2663  +      sqlite3DbMallocRaw(db, sizeof(*pKeyMerge)+nOrderBy*(sizeof(CollSeq*)+1));
         2664  +    if( pKeyMerge ){
         2665  +      pKeyMerge->aSortOrder = (u8*)&pKeyMerge->aColl[nOrderBy];
         2666  +      pKeyMerge->nField = nOrderBy;
         2667  +      pKeyMerge->enc = ENC(db);
         2668  +      for(i=0; i<nOrderBy; i++){
         2669  +        CollSeq *pColl;
         2670  +        Expr *pTerm = pOrderBy->a[i].pExpr;
         2671  +        if( pTerm->flags & EP_ExpCollate ){
         2672  +          pColl = pTerm->pColl;
         2673  +        }else{
         2674  +          pColl = multiSelectCollSeq(pParse, p, aPermute[i]);
         2675  +          pTerm->flags |= EP_ExpCollate;
         2676  +          pTerm->pColl = pColl;
         2677  +        }
         2678  +        pKeyMerge->aColl[i] = pColl;
         2679  +        pKeyMerge->aSortOrder[i] = pOrderBy->a[i].sortOrder;
         2680  +      }
         2681  +    }
         2682  +  }else{
         2683  +    pKeyMerge = 0;
         2684  +  }
         2685  +
         2686  +  /* Reattach the ORDER BY clause to the query.
         2687  +  */
         2688  +  p->pOrderBy = pOrderBy;
         2689  +  pPrior->pOrderBy = sqlite3ExprListDup(pParse->db, pOrderBy);
         2690  +
         2691  +  /* Allocate a range of temporary registers and the KeyInfo needed
         2692  +  ** for the logic that removes duplicate result rows when the
         2693  +  ** operator is UNION, EXCEPT, or INTERSECT (but not UNION ALL).
         2694  +  */
         2695  +  if( op==TK_ALL ){
         2696  +    regPrev = 0;
         2697  +  }else{
         2698  +    int nExpr = p->pEList->nExpr;
         2699  +    assert( nOrderBy>=nExpr );
         2700  +    regPrev = sqlite3GetTempRange(pParse, nExpr+1);
         2701  +    sqlite3VdbeAddOp2(v, OP_Integer, 0, regPrev);
         2702  +    pKeyDup = sqlite3DbMallocZero(db,
         2703  +                  sizeof(*pKeyDup) + nExpr*(sizeof(CollSeq*)+1) );
         2704  +    if( pKeyDup ){
         2705  +      pKeyDup->aSortOrder = (u8*)&pKeyDup->aColl[nExpr];
         2706  +      pKeyDup->nField = nExpr;
         2707  +      pKeyDup->enc = ENC(db);
         2708  +      for(i=0; i<nExpr; i++){
         2709  +        pKeyDup->aColl[i] = multiSelectCollSeq(pParse, p, i);
         2710  +        pKeyDup->aSortOrder[i] = 0;
         2711  +      }
         2712  +    }
         2713  +  }
  2571   2714    
  2572   2715     /* Separate the left and the right query from one another
  2573   2716     */
  2574   2717     p->pPrior = 0;
  2575   2718     pPrior->pRightmost = 0;
  2576         -  
         2719  +  processOrderGroupBy(pParse, p, p->pOrderBy, 1, &NotUsed);
         2720  +  if( pPrior->pPrior==0 ){
         2721  +    processOrderGroupBy(pParse, pPrior, pPrior->pOrderBy, 1, &NotUsed);
         2722  +  }
         2723  +
  2577   2724     /* Compute the limit registers */
  2578   2725     computeLimitRegisters(pParse, p, labelEnd);
  2579         -  if( p->iLimit ){
         2726  +  if( p->iLimit && op==TK_ALL ){
  2580   2727       regLimitA = ++pParse->nMem;
  2581   2728       regLimitB = ++pParse->nMem;
  2582   2729       sqlite3VdbeAddOp2(v, OP_Copy, p->iOffset ? p->iOffset+1 : p->iLimit,
  2583   2730                                     regLimitA);
  2584   2731       sqlite3VdbeAddOp2(v, OP_Copy, regLimitA, regLimitB);
  2585   2732     }else{
  2586   2733       regLimitA = regLimitB = 0;
  2587   2734     }
         2735  +  sqlite3ExprDelete(p->pLimit);
         2736  +  p->pLimit = 0;
         2737  +  sqlite3ExprDelete(p->pOffset);
         2738  +  p->pOffset = 0;
  2588   2739   
  2589   2740     regAddrA = ++pParse->nMem;
  2590   2741     regEofA = ++pParse->nMem;
  2591   2742     regAddrB = ++pParse->nMem;
  2592   2743     regEofB = ++pParse->nMem;
  2593   2744     regOutA = ++pParse->nMem;
  2594   2745     regOutB = ++pParse->nMem;
................................................................................
  2596   2747     sqlite3SelectDestInit(&destB, SRT_Coroutine, regAddrB);
  2597   2748   
  2598   2749     /* Jump past the various subroutines and coroutines to the main
  2599   2750     ** merge loop
  2600   2751     */
  2601   2752     j1 = sqlite3VdbeAddOp0(v, OP_Goto);
  2602   2753     addrSelectA = sqlite3VdbeCurrentAddr(v);
         2754  +
  2603   2755   
  2604   2756     /* Generate a coroutine to evaluate the SELECT statement to the
  2605         -  ** left of the compound operator - the "A" select. */
         2757  +  ** left of the compound operator - the "A" select.
         2758  +  */
  2606   2759     VdbeNoopComment((v, "Begin coroutine for left SELECT"));
  2607   2760     pPrior->iLimit = regLimitA;
  2608   2761     sqlite3Select(pParse, pPrior, &destA, 0, 0, 0, 0);
  2609   2762     sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofA);
  2610   2763     sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
  2611   2764     VdbeNoopComment((v, "End coroutine for left SELECT"));
  2612   2765   
................................................................................
  2623   2776     p->iLimit = savedLimit;
  2624   2777     p->iOffset = savedOffset;
  2625   2778     sqlite3VdbeAddOp2(v, OP_Integer, 1, regEofB);
  2626   2779     sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
  2627   2780     VdbeNoopComment((v, "End coroutine for right SELECT"));
  2628   2781   
  2629   2782     /* Generate a subroutine that outputs the current row of the A
  2630         -  ** select as the next output row of the compound select and then
  2631         -  ** advances the A select to its next row
         2783  +  ** select as the next output row of the compound select.
  2632   2784     */
  2633   2785     VdbeNoopComment((v, "Output routine for A"));
  2634         -  addrOutA = outputSubroutine(pParse, p, &destA, pDest, regOutA, labelEnd);
         2786  +  addrOutA = generateOutputSubroutine(pParse,
         2787  +                 p, &destA, pDest, regOutA,
         2788  +                 regPrev, pKeyDup, P4_KEYINFO_HANDOFF, labelEnd);
  2635   2789     
  2636   2790     /* Generate a subroutine that outputs the current row of the B
  2637         -  ** select as the next output row of the compound select and then
  2638         -  ** advances the B select to its next row
         2791  +  ** select as the next output row of the compound select.
  2639   2792     */
  2640         -  VdbeNoopComment((v, "Output routine for B"));
  2641         -  addrOutB = outputSubroutine(pParse, p, &destB, pDest, regOutB, labelEnd);
         2793  +  if( op==TK_ALL || op==TK_UNION ){
         2794  +    VdbeNoopComment((v, "Output routine for B"));
         2795  +    addrOutB = generateOutputSubroutine(pParse,
         2796  +                 p, &destB, pDest, regOutB,
         2797  +                 regPrev, pKeyDup, P4_KEYINFO_STATIC, labelEnd);
         2798  +  }
  2642   2799   
  2643   2800     /* Generate a subroutine to run when the results from select A
  2644   2801     ** are exhausted and only data in select B remains.
  2645   2802     */
  2646   2803     VdbeNoopComment((v, "eof-A subroutine"));
  2647         -  addrEofA = sqlite3VdbeCurrentAddr(v);
  2648   2804     if( op==TK_EXCEPT || op==TK_INTERSECT ){
  2649         -    sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
         2805  +    addrEofA = sqlite3VdbeAddOp2(v, OP_Goto, 0, labelEnd);
  2650   2806     }else{  
  2651         -    if( op==TK_ALL ){
  2652         -      j2 = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
  2653         -      sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
  2654         -      sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
  2655         -    }else{
  2656         -      assert( op==TK_UNION );
  2657         -      sqlite3ExprCodeCopy(pParse, destB.iMem, destA.iMem, destB.nMem);
  2658         -      j2 = sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
  2659         -      sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
  2660         -      sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destB.nMem,
  2661         -                           (char*)pKeyInfo, p4type);
  2662         -      p4type = P4_KEYINFO_STATIC;
  2663         -      sqlite3VdbeAddOp3(v, OP_Jump, j2, j2+4, j2);
  2664         -      sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
  2665         -      sqlite3VdbeAddOp2(v, OP_Goto, 0, j2+1);
  2666         -    }
         2807  +    addrEofA = sqlite3VdbeAddOp2(v, OP_If, regEofB, labelEnd);
         2808  +    sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
         2809  +    sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
         2810  +    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofA);
  2667   2811     }
  2668   2812   
  2669   2813     /* Generate a subroutine to run when the results from select B
  2670   2814     ** are exhausted and only data in select A remains.
  2671   2815     */
  2672   2816     if( op==TK_INTERSECT ){
  2673   2817       addrEofB = addrEofA;
  2674   2818     }else{  
  2675   2819       VdbeNoopComment((v, "eof-B subroutine"));
  2676         -    addrEofB = sqlite3VdbeCurrentAddr(v);
  2677         -    if( op==TK_ALL || op==TK_EXCEPT ){
  2678         -      j2 = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
  2679         -      sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
  2680         -      sqlite3VdbeAddOp2(v, OP_Goto, 0, j2);
  2681         -    }else{
  2682         -      assert( op==TK_UNION );
  2683         -      sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
  2684         -      sqlite3ExprCodeCopy(pParse, destA.iMem, destB.iMem, destA.nMem);
  2685         -      j2 = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
  2686         -      sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
  2687         -      sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destB.nMem,
  2688         -                           (char*)pKeyInfo, p4type);
  2689         -      p4type = P4_KEYINFO_STATIC;
  2690         -      sqlite3VdbeAddOp3(v, OP_Jump, j2, j2+4, j2);
  2691         -      sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
  2692         -      sqlite3VdbeAddOp2(v, OP_Goto, 0, j2+1);
  2693         -    }
         2820  +    addrEofB = sqlite3VdbeAddOp2(v, OP_If, regEofA, labelEnd);
         2821  +    sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
         2822  +    sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
         2823  +    sqlite3VdbeAddOp2(v, OP_Goto, 0, addrEofB);
  2694   2824     }
  2695   2825   
  2696   2826     /* Generate code to handle the case of A<B
  2697   2827     */
  2698   2828     VdbeNoopComment((v, "A-lt-B subroutine"));
  2699         -  addrAltB = sqlite3VdbeCurrentAddr(v);
  2700         -  if( op==TK_INTERSECT ){
  2701         -    sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
  2702         -  }else{
  2703         -    sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
  2704         -  }
         2829  +  addrAltB = sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
         2830  +  sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
  2705   2831     sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  2706   2832     sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
  2707   2833   
  2708   2834     /* Generate code to handle the case of A==B
  2709   2835     */
  2710   2836     if( op==TK_ALL ){
  2711   2837       addrAeqB = addrAltB;
         2838  +  }else if( op==TK_INTERSECT ){
         2839  +    addrAeqB = addrAltB;
         2840  +    addrAltB++;
  2712   2841     }else{
  2713   2842       VdbeNoopComment((v, "A-eq-B subroutine"));
  2714         -    addrAeqB = sqlite3VdbeCurrentAddr(v);
  2715         -    if( op==TK_INTERSECT ){
  2716         -      sqlite3VdbeAddOp2(v, OP_Gosub, regOutA, addrOutA);
  2717         -      j2 = sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
  2718         -      sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  2719         -      sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destA.nMem,
  2720         -                           (char*)pKeyInfo, p4type);
  2721         -      p4type = P4_KEYINFO_STATIC;
  2722         -      j3 = sqlite3VdbeCurrentAddr(v)+1;
  2723         -      sqlite3VdbeAddOp3(v, OP_Jump, j3, j2, j3);
  2724         -      sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
  2725         -    }else{
  2726         -      sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
  2727         -      sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  2728         -      sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
  2729         -    }
         2843  +    addrAeqB =
         2844  +    sqlite3VdbeAddOp1(v, OP_Yield, regAddrA);
         2845  +    sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
         2846  +    sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
  2730   2847     }
  2731   2848   
  2732   2849     /* Generate code to handle the case of A>B
  2733   2850     */
  2734   2851     VdbeNoopComment((v, "A-gt-B subroutine"));
  2735   2852     addrAgtB = sqlite3VdbeCurrentAddr(v);
  2736   2853     if( op==TK_ALL || op==TK_UNION ){
  2737   2854       sqlite3VdbeAddOp2(v, OP_Gosub, regOutB, addrOutB);
  2738         -  }else{
  2739         -    sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
  2740   2855     }
         2856  +  sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
  2741   2857     sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
  2742   2858     sqlite3VdbeAddOp2(v, OP_Goto, 0, labelCmpr);
  2743   2859   
  2744   2860     /* This code runs once to initialize everything.
  2745   2861     */
  2746   2862     sqlite3VdbeJumpHere(v, j1);
  2747   2863     sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofA);
  2748   2864     sqlite3VdbeAddOp2(v, OP_Integer, 0, regEofB);
  2749         -  sqlite3VdbeAddOp2(v, OP_Integer, addrSelectB, regAddrB);
  2750   2865     sqlite3VdbeAddOp2(v, OP_Gosub, regAddrA, addrSelectA);
         2866  +  sqlite3VdbeAddOp2(v, OP_Gosub, regAddrB, addrSelectB);
  2751   2867     sqlite3VdbeAddOp2(v, OP_If, regEofA, addrEofA);
  2752         -  sqlite3VdbeAddOp1(v, OP_Yield, regAddrB);
  2753   2868     sqlite3VdbeAddOp2(v, OP_If, regEofB, addrEofB);
  2754   2869   
  2755   2870     /* Implement the main merge loop
  2756   2871     */
  2757   2872     sqlite3VdbeResolveLabel(v, labelCmpr);
  2758         -  sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, destA.nMem,
  2759         -                         (char*)pKeyInfo, p4type);
  2760         -  p4type = P4_KEYINFO_STATIC;
         2873  +  sqlite3VdbeAddOp4(v, OP_Permutation, 0, 0, 0, (char*)aPermute, P4_INTARRAY);
         2874  +  sqlite3VdbeAddOp4(v, OP_Compare, destA.iMem, destB.iMem, nOrderBy,
         2875  +                         (char*)pKeyMerge, P4_KEYINFO_HANDOFF);
  2761   2876     sqlite3VdbeAddOp3(v, OP_Jump, addrAltB, addrAeqB, addrAgtB);
         2877  +
         2878  +  /* Release temporary registers
         2879  +  */
         2880  +  if( regPrev ){
         2881  +    sqlite3ReleaseTempRange(pParse, regPrev, nOrderBy+1);
         2882  +  }
  2762   2883   
  2763   2884     /* Jump to the this point in order to terminate the query.
  2764   2885     */
  2765   2886     sqlite3VdbeResolveLabel(v, labelEnd);
  2766   2887   
  2767   2888     /* Set the number of output columns
  2768   2889     */
  2769   2890     if( pDest->eDest==SRT_Callback ){
  2770         -    Select *pFirst = p;
         2891  +    Select *pFirst = pPrior;
  2771   2892       while( pFirst->pPrior ) pFirst = pFirst->pPrior;
  2772   2893       generateColumnNames(pParse, 0, pFirst->pEList);
  2773   2894     }
  2774   2895   
  2775         -  /* Free the KeyInfo if unused.
  2776         -  */
  2777         -  if( p4type==P4_KEYINFO_HANDOFF ){
  2778         -    sqlite3_free(pKeyInfo);
  2779         -  }
         2896  +  /* Reassembly the compound query so that it will be freed correctly
         2897  +  ** by the calling function */
         2898  +  p->pPrior = pPrior;
  2780   2899   
  2781   2900     /*** TBD:  Insert subroutine calls to close cursors on incomplete
  2782   2901     **** subqueries ****/
  2783   2902     return SQLITE_OK;
  2784   2903   }
  2785   2904   
  2786   2905   #ifndef SQLITE_OMIT_VIEW

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.754 2008/06/23 18:49:44 danielk1977 Exp $
           46  +** $Id: vdbe.c,v 1.755 2008/06/25 00:12:41 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include <ctype.h>
    50     50   #include "vdbeInt.h"
    51     51   
    52     52   /*
    53     53   ** The following global variable is incremented every time a cursor
................................................................................
   542    542     Op *pOp;                   /* Current operation */
   543    543     int rc = SQLITE_OK;        /* Value to return */
   544    544     sqlite3 *db = p->db;       /* The database */
   545    545     u8 encoding = ENC(db);     /* The database encoding */
   546    546     Mem *pIn1, *pIn2, *pIn3;   /* Input operands */
   547    547     Mem *pOut;                 /* Output operand */
   548    548     u8 opProperty;
          549  +  int iCompare = 0;          /* Result of last OP_Compare operation */
          550  +  int *aPermute = 0;         /* Permuation of columns for OP_Compare */
   549    551   #ifdef VDBE_PROFILE
   550    552     u64 start;                 /* CPU clock count at start of opcode */
   551    553     int origPc;                /* Program counter at start of opcode */
   552    554   #endif
   553    555   #ifndef SQLITE_OMIT_PROGRESS_CALLBACK
   554    556     int nProgressOps = 0;      /* Opcodes executed since progress callback. */
   555    557   #endif
................................................................................
   993    995     assert( p1+n<p->nMem );
   994    996     pIn1 = &p->aMem[p1];
   995    997     assert( p2>0 );
   996    998     assert( p2+n<p->nMem );
   997    999     pOut = &p->aMem[p2];
   998   1000     assert( p1+n<=p2 || p2+n<=p1 );
   999   1001     while( n-- ){
  1000         -    REGISTER_TRACE(p1++, pIn1);
  1001   1002       zMalloc = pOut->zMalloc;
  1002   1003       pOut->zMalloc = 0;
  1003   1004       sqlite3VdbeMemMove(pOut, pIn1);
  1004   1005       pIn1->zMalloc = zMalloc;
  1005   1006       REGISTER_TRACE(p2++, pOut);
  1006   1007       pIn1++;
  1007   1008       pOut++;
................................................................................
  1016   1017   ** This instruction makes a deep copy of the value.  A duplicate
  1017   1018   ** is made of any string or blob constant.  See also OP_SCopy.
  1018   1019   */
  1019   1020   case OP_Copy: {
  1020   1021     assert( pOp->p1>0 );
  1021   1022     assert( pOp->p1<=p->nMem );
  1022   1023     pIn1 = &p->aMem[pOp->p1];
  1023         -  REGISTER_TRACE(pOp->p1, pIn1);
  1024   1024     assert( pOp->p2>0 );
  1025   1025     assert( pOp->p2<=p->nMem );
  1026   1026     pOut = &p->aMem[pOp->p2];
  1027   1027     assert( pOut!=pIn1 );
  1028   1028     sqlite3VdbeMemShallowCopy(pOut, pIn1, MEM_Ephem);
  1029   1029     Deephemeralize(pOut);
  1030   1030     REGISTER_TRACE(pOp->p2, pOut);
................................................................................
  1079   1079     ** and have an assigned type.  The results are de-ephemeralized as
  1080   1080     ** as side effect.
  1081   1081     */
  1082   1082     pMem = p->pResultSet = &p->aMem[pOp->p1];
  1083   1083     for(i=0; i<pOp->p2; i++){
  1084   1084       sqlite3VdbeMemNulTerminate(&pMem[i]);
  1085   1085       storeTypeInfo(&pMem[i], encoding);
         1086  +    REGISTER_TRACE(pOp->p1+i, &pMem[i]);
  1086   1087     }
  1087   1088     if( db->mallocFailed ) goto no_mem;
  1088   1089   
  1089   1090     /* Return SQLITE_ROW
  1090   1091     */
  1091   1092     p->nCallback++;
  1092   1093     p->pc = pc + 1;
................................................................................
  1735   1736       pOut->u.i = res;
  1736   1737       REGISTER_TRACE(pOp->p2, pOut);
  1737   1738     }else if( res ){
  1738   1739       pc = pOp->p2-1;
  1739   1740     }
  1740   1741     break;
  1741   1742   }
         1743  +
         1744  +/* Opcode: Permutation * * * P4 *
         1745  +**
         1746  +** Set the permuation used by the OP_Compare operator to be the array
         1747  +** of integers in P4.
         1748  +**
         1749  +** The permutation is only valid until the next OP_Permutation, OP_Compare,
         1750  +** OP_Halt, or OP_ResultRow.  Typically the OP_Permutation should occur
         1751  +** immediately prior to the OP_Compare.
         1752  +*/
         1753  +case OP_Permutation: {
         1754  +  assert( pOp->p4type==P4_INTARRAY );
         1755  +  assert( pOp->p4.ai );
         1756  +  aPermute = pOp->p4.ai;
         1757  +  break;
         1758  +}
  1742   1759   
  1743   1760   /* Opcode: Compare P1 P2 P3 P4 *
  1744   1761   **
  1745   1762   ** Compare to vectors of registers in reg(P1)..reg(P1+P3-1) (all this
  1746   1763   ** one "A") and in reg(P2)..reg(P2+P3-1) ("B").  Save the result of
  1747   1764   ** the comparison for use by the next OP_Jump instruct.
  1748   1765   **
  1749         -** P4 is a KeyInfo structure that defines collating sequences usedused for affinity purposes.  The
  1750         -** comparison is done for sorting purposes, so NULLs compare
  1751         -** equal, NULLs are less than numbers, numbers are less than strings,
         1766  +** P4 is a KeyInfo structure that defines collating sequences and sort
         1767  +** orders for the comparison.  The permutation applies to registers
         1768  +** only.  The KeyInfo elements are used sequentially.
         1769  +**
         1770  +** The comparison is a sort comparison, so NULLs compare equal,
         1771  +** NULLs are less than numbers, numbers are less than strings,
  1752   1772   ** and strings are less than blobs.
  1753   1773   */
  1754   1774   case OP_Compare: {
  1755   1775     int n = pOp->p3;
  1756   1776     int i, p1, p2;
  1757   1777     const KeyInfo *pKeyInfo = pOp->p4.pKeyInfo;
  1758   1778     assert( n>0 );
  1759   1779     p1 = pOp->p1;
  1760   1780     assert( p1>0 && p1+n-1<p->nMem );
  1761   1781     p2 = pOp->p2;
  1762   1782     assert( p2>0 && p2+n-1<p->nMem );
  1763         -  for(i=0; i<n; i++, p1++, p2++){
  1764         -    REGISTER_TRACE(p1, &p->aMem[p1]);
  1765         -    REGISTER_TRACE(p2, &p->aMem[p2]);
  1766         -    p->iCompare = sqlite3MemCompare(&p->aMem[p1], &p->aMem[p2],
  1767         -                   pKeyInfo && i<pKeyInfo->nField ? pKeyInfo->aColl[i] : 0);
  1768         -    if( p->iCompare ) break;
         1783  +  for(i=0; i<n; i++){
         1784  +    int idx = aPermute ? aPermute[i] : i;
         1785  +    CollSeq *pColl;    /* Collating sequence to use on this term */
         1786  +    int bRev;          /* True for DESCENDING sort order */
         1787  +    assert( pKeyInfo==0 || i<pKeyInfo->nField );
         1788  +    REGISTER_TRACE(p1+idx, &p->aMem[p1+idx]);
         1789  +    REGISTER_TRACE(p2+idx, &p->aMem[p2+idx]);
         1790  +    if( pKeyInfo ){
         1791  +      assert( i<pKeyInfo->nField );
         1792  +      pColl = pKeyInfo->aColl[i];
         1793  +      bRev = pKeyInfo->aSortOrder[i];
         1794  +    }else{
         1795  +      pColl = 0;
         1796  +      bRev = 0;
         1797  +    }
         1798  +    iCompare = sqlite3MemCompare(&p->aMem[p1+idx], &p->aMem[p2+idx], pColl);
         1799  +    if( iCompare ){
         1800  +      if( bRev ) iCompare = -iCompare;
         1801  +      break;
         1802  +    }
  1769   1803     }
         1804  +  aPermute = 0;
  1770   1805     break;
  1771   1806   }
  1772   1807   
  1773   1808   /* Opcode: Jump P1 P2 P3 * *
  1774   1809   **
  1775   1810   ** Jump to the instruction at address P1, P2, or P3 depending on whether
  1776   1811   ** in the most recent OP_Compare instruction the P1 vector was less than
  1777   1812   ** equal to, or greater than the P2 vector, respectively.
  1778   1813   */
  1779         -case OP_Jump: {
  1780         -  if( p->iCompare<0 ){
         1814  +case OP_Jump: {             /* jump */
         1815  +  if( iCompare<0 ){
  1781   1816       pc = pOp->p1 - 1;
  1782         -  }else if( p->iCompare==0 ){
         1817  +  }else if( iCompare==0 ){
  1783   1818       pc = pOp->p2 - 1;
  1784   1819     }else{
  1785   1820       pc = pOp->p3 - 1;
  1786   1821     }
  1787   1822     break;
  1788   1823   }
  1789   1824   

Changes to src/vdbe.h.

    11     11   *************************************************************************
    12     12   ** Header file for the Virtual DataBase Engine (VDBE)
    13     13   **
    14     14   ** This header defines the interface to the virtual database engine
    15     15   ** or VDBE.  The VDBE implements an abstract machine that runs a
    16     16   ** simple program to access and modify the underlying database.
    17     17   **
    18         -** $Id: vdbe.h,v 1.133 2008/06/20 18:13:25 drh Exp $
           18  +** $Id: vdbe.h,v 1.134 2008/06/25 00:12:41 drh Exp $
    19     19   */
    20     20   #ifndef _SQLITE_VDBE_H_
    21     21   #define _SQLITE_VDBE_H_
    22     22   #include <stdio.h>
    23     23   
    24     24   /*
    25     25   ** A single VDBE is an opaque structure named "Vdbe".  Only routines
................................................................................
    57     57       double *pReal;         /* Used when p4type is P4_REAL */
    58     58       FuncDef *pFunc;        /* Used when p4type is P4_FUNCDEF */
    59     59       VdbeFunc *pVdbeFunc;   /* Used when p4type is P4_VDBEFUNC */
    60     60       CollSeq *pColl;        /* Used when p4type is P4_COLLSEQ */
    61     61       Mem *pMem;             /* Used when p4type is P4_MEM */
    62     62       sqlite3_vtab *pVtab;   /* Used when p4type is P4_VTAB */
    63     63       KeyInfo *pKeyInfo;     /* Used when p4type is P4_KEYINFO */
           64  +    int *ai;               /* Used when p4type is P4_INTARRAY */
    64     65     } p4;
    65     66   #ifdef SQLITE_DEBUG
    66     67     char *zComment;          /* Comment to improve readability */
    67     68   #endif
    68     69   #ifdef VDBE_PROFILE
    69     70     int cnt;                 /* Number of times this instruction was executed */
    70     71     u64 cycles;              /* Total time spent executing this instruction */
................................................................................
    97     98   #define P4_MEM      (-8)  /* P4 is a pointer to a Mem*    structure */
    98     99   #define P4_TRANSIENT (-9) /* P4 is a pointer to a transient string */
    99    100   #define P4_VTAB     (-10) /* P4 is a pointer to an sqlite3_vtab structure */
   100    101   #define P4_MPRINTF  (-11) /* P4 is a string obtained from sqlite3_mprintf() */
   101    102   #define P4_REAL     (-12) /* P4 is a 64-bit floating point value */
   102    103   #define P4_INT64    (-13) /* P4 is a 64-bit signed integer */
   103    104   #define P4_INT32    (-14) /* P4 is a 32-bit signed integer */
          105  +#define P4_INTARRAY (-15) /* P4 is a vector of 32-bit integers */
   104    106   
   105    107   /* When adding a P4 argument using P4_KEYINFO, a copy of the KeyInfo structure
   106    108   ** is made.  That copy is freed when the Vdbe is finalized.  But if the
   107    109   ** argument is P4_KEYINFO_HANDOFF, the passed in pointer is used.  It still
   108    110   ** gets freed when the Vdbe is finalized so it still should be obtained
   109    111   ** from a single sqliteMalloc().  But no copy is made and the calling
   110    112   ** function should *not* try to free the KeyInfo.
   111    113   */
   112         -#define P4_KEYINFO_HANDOFF (-15)
   113         -#define P4_KEYINFO_STATIC  (-16)
          114  +#define P4_KEYINFO_HANDOFF (-16)
          115  +#define P4_KEYINFO_STATIC  (-17)
   114    116   
   115    117   /*
   116    118   ** The Vdbe.aColName array contains 5n Mem structures, where n is the 
   117    119   ** number of columns of data returned by the statement.
   118    120   */
   119    121   #define COLNAME_NAME     0
   120    122   #define COLNAME_DECLTYPE 1

Changes to src/vdbeInt.h.

    11     11   *************************************************************************
    12     12   ** This is the header file for information that is private to the
    13     13   ** VDBE.  This information used to all be at the top of the single
    14     14   ** source code file "vdbe.c".  When that file became too big (over
    15     15   ** 6000 lines long) it was split up into several smaller files and
    16     16   ** this header information was factored out.
    17     17   **
    18         -** $Id: vdbeInt.h,v 1.148 2008/06/20 18:13:25 drh Exp $
           18  +** $Id: vdbeInt.h,v 1.149 2008/06/25 00:12:41 drh Exp $
    19     19   */
    20     20   #ifndef _VDBEINT_H_
    21     21   #define _VDBEINT_H_
    22     22   
    23     23   /*
    24     24   ** intToKey() and keyToInt() used to transform the rowid.  But with
    25     25   ** the latest versions of the design they are no-ops.
................................................................................
   317    317     Mem *pResultSet;        /* Pointer to an array of results */
   318    318     u8 explain;             /* True if EXPLAIN present on SQL command */
   319    319     u8 changeCntOn;         /* True to update the change-counter */
   320    320     u8 aborted;             /* True if ROLLBACK in another VM causes an abort */
   321    321     u8 expired;             /* True if the VM needs to be recompiled */
   322    322     u8 minWriteFileFormat;  /* Minimum file format for writable database files */
   323    323     u8 inVtabMethod;        /* See comments above */
   324         -  int iCompare;           /* Result of most recent OP_Compare comparison */
   325    324     int nChange;            /* Number of db changes made since last reset */
   326    325     i64 startTime;          /* Time when query started - used for profiling */
   327    326     int btreeMask;          /* Bitmask of db->aDb[] entries referenced */
   328    327     BtreeMutexArray aMutex; /* An array of Btree used here and needing locks */
   329    328     int nSql;             /* Number of bytes in zSql */
   330    329     char *zSql;           /* Text of the SQL statement that generated this */
   331    330   #ifdef SQLITE_DEBUG

Changes to src/vdbeaux.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used for creating, destroying, and populating
    13     13   ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
    14     14   ** to version 2.8.7, all this code was combined into the vdbe.c source file.
    15     15   ** But that file was getting too big so this subroutines were split out.
    16     16   **
    17         -** $Id: vdbeaux.c,v 1.392 2008/06/23 13:57:22 danielk1977 Exp $
           17  +** $Id: vdbeaux.c,v 1.393 2008/06/25 00:12:42 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   #include "vdbeInt.h"
    22     22   
    23     23   
    24     24   
................................................................................
   437    437       sqlite3_free(pDef);
   438    438     }
   439    439   }
   440    440   
   441    441   /*
   442    442   ** Delete a P4 value if necessary.
   443    443   */
   444         -static void freeP4(int p4type, void *p3){
   445         -  if( p3 ){
          444  +static void freeP4(int p4type, void *p4){
          445  +  if( p4 ){
   446    446       switch( p4type ){
   447    447         case P4_REAL:
   448    448         case P4_INT64:
   449    449         case P4_MPRINTF:
   450    450         case P4_DYNAMIC:
   451    451         case P4_KEYINFO:
          452  +      case P4_INTARRAY:
   452    453         case P4_KEYINFO_HANDOFF: {
   453         -        sqlite3_free(p3);
          454  +        sqlite3_free(p4);
   454    455           break;
   455    456         }
   456    457         case P4_VDBEFUNC: {
   457         -        VdbeFunc *pVdbeFunc = (VdbeFunc *)p3;
          458  +        VdbeFunc *pVdbeFunc = (VdbeFunc *)p4;
   458    459           freeEphemeralFunction(pVdbeFunc->pFunc);
   459    460           sqlite3VdbeDeleteAuxData(pVdbeFunc, 0);
   460    461           sqlite3_free(pVdbeFunc);
   461    462           break;
   462    463         }
   463    464         case P4_FUNCDEF: {
   464         -        freeEphemeralFunction((FuncDef*)p3);
          465  +        freeEphemeralFunction((FuncDef*)p4);
   465    466           break;
   466    467         }
   467    468         case P4_MEM: {
   468         -        sqlite3ValueFree((sqlite3_value*)p3);
          469  +        sqlite3ValueFree((sqlite3_value*)p4);
   469    470           break;
   470    471         }
   471    472       }
   472    473     }
   473    474   }
   474    475   
   475    476   
................................................................................
   693    694   #ifndef SQLITE_OMIT_VIRTUALTABLE
   694    695       case P4_VTAB: {
   695    696         sqlite3_vtab *pVtab = pOp->p4.pVtab;
   696    697         sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
   697    698         break;
   698    699       }
   699    700   #endif
          701  +    case P4_INTARRAY: {
          702  +      sqlite3_snprintf(nTemp, zTemp, "intarray");
          703  +      break;
          704  +    }
   700    705       default: {
   701    706         zP4 = pOp->p4.z;
   702    707         if( zP4==0 ){
   703    708           zP4 = zTemp;
   704    709           zTemp[0] = 0;
   705    710         }
   706    711       }