/ Check-in [8201f717]
Login

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

Overview
Comment:Registerify the SRT_Subroutine destination for SELECT results. (CVS 4690)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:8201f71729c3afbb41764cea3cda65b03150cb0c
User & Date: drh 2008-01-06 00:25:22
Context
2008-01-07
10:16
Comment changes in select.c. (CVS 4691) check-in: 38020592 user: danielk1977 tags: trunk
2008-01-06
00:25
Registerify the SRT_Subroutine destination for SELECT results. (CVS 4690) check-in: 8201f717 user: drh tags: trunk
2008-01-05
18:48
Modify OP_RegMakeRec to take a base register and count and optionally store results in the register specified by P3. (CVS 4689) check-in: 6bb1b1bc user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/build.c.

18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
....
1487
1488
1489
1490
1491
1492
1493
1494
1495

1496
1497
1498

1499
1500
1501
1502
1503
1504
1505
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.460 2008/01/05 18:48:24 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
    **
    ** A shared-cache write-lock is not required to write to the new table,
    ** as a schema-lock must have already been obtained to create it. Since
    ** a schema-lock excludes all other database users, the write-lock would
    ** be redundant.
    */
    if( pSelect ){
      SelectDest dest = {SRT_Table, 0, 1};
      Table *pSelTab;

      sqlite3VdbeAddOp0(v, OP_Copy);
      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
      pParse->nTab = 2;

      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
      sqlite3VdbeAddOp1(v, OP_Close, 1);
      if( pParse->nErr==0 ){
        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
        if( pSelTab==0 ) return;
        assert( p->aCol==0 );
        p->nCol = pSelTab->nCol;







|







 







|

>



>







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
....
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.461 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** This routine is called when a new SQL statement is beginning to
** be parsed.  Initialize the pParse structure as needed.
................................................................................
    **
    ** A shared-cache write-lock is not required to write to the new table,
    ** as a schema-lock must have already been obtained to create it. Since
    ** a schema-lock excludes all other database users, the write-lock would
    ** be redundant.
    */
    if( pSelect ){
      SelectDest dest;
      Table *pSelTab;

      sqlite3VdbeAddOp0(v, OP_Copy);
      sqlite3VdbeAddOp3(v, OP_OpenWrite, 1, 0, iDb);
      pParse->nTab = 2;
      sqlite3SelectDestInit(&dest, SRT_Table, 1);
      sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
      sqlite3VdbeAddOp1(v, OP_Close, 1);
      if( pParse->nErr==0 ){
        pSelTab = sqlite3ResultSetOfSelect(pParse, 0, pSelect);
        if( pSelTab==0 ) return;
        assert( p->aCol==0 );
        p->nCol = pSelTab->nCol;

Changes to src/delete.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
257
258
259
260
261
262
263
264


265
266
267

268
269
270
271
272
273
274
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.151 2008/01/05 17:39:30 danielk1977 Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
    sqlite3VdbeJumpHere(v, iGoto);
  }

  /* If we are trying to delete from a view, realize that view into
  ** a ephemeral table.
  */
  if( isView ){
    SelectDest dest = {SRT_EphemTab, 0, 0};


    Select *pView = sqlite3SelectDup(db, pTab->pSelect);
    sqlite3SelectMask(pParse, pView, old_col_mask);
    dest.iParm = iCur;

    sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
    sqlite3SelectDelete(pView);
  }

  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */







|







 







|
>
>
|

<
>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273
274
275
276
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** in order to generate code for DELETE FROM statements.
**
** $Id: delete.c,v 1.152 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** Look up every table that is named in pSrc.  If any table is not found,
** add an error message to pParse->zErrMsg and return NULL.  If all tables
** are found, return a pointer to the last table.
................................................................................
    sqlite3VdbeJumpHere(v, iGoto);
  }

  /* If we are trying to delete from a view, realize that view into
  ** a ephemeral table.
  */
  if( isView ){
    SelectDest dest;
    Select *pView;

    pView = sqlite3SelectDup(db, pTab->pSelect);
    sqlite3SelectMask(pParse, pView, old_col_mask);

    sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
    sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
    sqlite3SelectDelete(pView);
  }

  /* Initialize the counter of the number of rows deleted, if
  ** we are counting rows.
  */

Changes to src/expr.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1734
1735
1736
1737
1738
1739
1740
1741
1742


1743
1744
1745
1746
1747
1748
1749
1750
1751
....
1799
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.334 2008/01/05 16:29:28 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................

      if( pExpr->pSelect ){
        /* Case 1:     expr IN (SELECT ...)
        **
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        SelectDest dest = {SRT_Set, 0, 0};
        dest.iParm = pExpr->iTable;


        dest.affinity = (int)affinity;
        ExprList *pEList;
        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
        if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0, 0) ){
          return;
        }
        pEList = pExpr->pSelect->pEList;
        if( pEList && pEList->nExpr>0 ){ 
          keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
................................................................................
      ** of the memory cell in iColumn.
      */
      static const Token one = { (u8*)"1", 0, 1 };
      Select *pSel;
      SelectDest dest;

      pSel = pExpr->pSelect;
      dest.iParm = ++pParse->nMem;
      if( pExpr->op==TK_SELECT ){
        dest.eDest = SRT_Mem;
        sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iParm);
        VdbeComment((v, "Init subquery result"));
      }else{
        dest.eDest = SRT_Exists;
        sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm);







|







 







|
|
>
>

<







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
....
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745

1746
1747
1748
1749
1750
1751
1752
....
1800
1801
1802
1803
1804
1805
1806
1807
1808
1809
1810
1811
1812
1813
1814
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.335 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>

/*
** Return the 'affinity' of the expression pExpr if any.
**
................................................................................

      if( pExpr->pSelect ){
        /* Case 1:     expr IN (SELECT ...)
        **
        ** Generate code to write the results of the select into the temporary
        ** table allocated and opened above.
        */
        SelectDest dest;
        ExprList *pEList;

        sqlite3SelectDestInit(&dest, SRT_Set, pExpr->iTable);
        dest.affinity = (int)affinity;

        assert( (pExpr->iTable&0x0000FFFF)==pExpr->iTable );
        if( sqlite3Select(pParse, pExpr->pSelect, &dest, 0, 0, 0, 0) ){
          return;
        }
        pEList = pExpr->pSelect->pEList;
        if( pEList && pEList->nExpr>0 ){ 
          keyInfo.aColl[0] = sqlite3BinaryCompareCollSeq(pParse, pExpr->pLeft,
................................................................................
      ** of the memory cell in iColumn.
      */
      static const Token one = { (u8*)"1", 0, 1 };
      Select *pSel;
      SelectDest dest;

      pSel = pExpr->pSelect;
      sqlite3SelectDestInit(&dest, 0, ++pParse->nMem);
      if( pExpr->op==TK_SELECT ){
        dest.eDest = SRT_Mem;
        sqlite3VdbeAddOp2(v, OP_Null, 0, dest.iParm);
        VdbeComment((v, "Init subquery result"));
      }else{
        dest.eDest = SRT_Exists;
        sqlite3VdbeAddOp2(v, OP_Integer, 0, dest.iParm);

Changes to src/insert.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
355
356
357
358
359
360
361

362
363
364
365
366
367
368
...
467
468
469
470
471
472
473
474
475

476
477
478
479
480
481
482
483
484
485
486

487
488
489
490
491
492
493
...
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
...
636
637
638
639
640
641
642

643
644
645
646
647
648
649
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.213 2008/01/05 05:20:10 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
  int endOfLoop;        /* Label for the end of the insertion loop */
  int useTempTable = 0; /* Store SELECT results in intermediate table */
  int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
  int iSelectLoop = 0;  /* Address of code that implements the SELECT */
  int iCleanup = 0;     /* Address of the cleanup code */
  int iInsertBlock = 0; /* Address of the subroutine used to insert data */
  int iCntMem = 0;      /* Memory cell used for the row counter */

  int newIdx = -1;      /* Cursor for the NEW table */
  Db *pDb;              /* The database containing table being inserted into */
  int counterMem = 0;   /* Memory cell holding AUTOINCREMENT counter */
  int appendFlag = 0;   /* True if the insert is likely to be an append */
  int iDb;

  int nHidden = 0;
................................................................................
  ** statement uses the the table that is being inserted into, then the
  ** subroutine is also coded here.  That subroutine stores the SELECT
  ** results in a temporary table. (Template 3.)
  */
  if( pSelect ){
    /* Data is coming from a SELECT.  Generate code to implement that SELECT
    */
    SelectDest dest = {SRT_Subroutine, 0, 0};
    int rc, iInitCode;

    iInitCode = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
    iSelectLoop = sqlite3VdbeCurrentAddr(v);
    iInsertBlock = sqlite3VdbeMakeLabel(v);
    dest.iParm = iInsertBlock;

    /* Resolve the expressions in the SELECT statement and execute it. */
    rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
    if( rc || pParse->nErr || db->mallocFailed ){
      goto insert_cleanup;
    }


    iCleanup = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup);
    assert( pSelect->pEList );
    nColumn = pSelect->pEList->nExpr;

    /* Set useTempTable to TRUE if the result of the SELECT statement
    ** should be written into a temporary table.  Set to FALSE if each
................................................................................

    if( useTempTable ){
      /* Generate the subroutine that SELECT calls to process each row of
      ** the result.  Store the result in a temporary table
      */
      srcTab = pParse->nTab++;
      sqlite3VdbeResolveLabel(v, iInsertBlock);
      sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
      sqlite3VdbeAddOp2(v, OP_MakeRecord, nColumn, 0);
      sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab);
      sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
      sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND);
      sqlite3VdbeAddOp2(v, OP_Return, 0, 0);

      /* The following code runs first because the GOTO at the very top
      ** of the program jumps to it.  Create the temporary table, then jump
................................................................................
  if( useTempTable ){
    iBreak = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, srcTab, iBreak);
    iCont = sqlite3VdbeCurrentAddr(v);
  }else if( pSelect ){
    sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
    sqlite3VdbeResolveLabel(v, iInsertBlock);

    sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
  }

  /* Run the BEFORE and INSTEAD OF triggers, if there are any
  */
  endOfLoop = sqlite3VdbeMakeLabel(v);
  if( triggers_exist & TRIGGER_BEFORE ){







|







 







>







 







|

>



|







>







 







|
<







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
...
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
...
506
507
508
509
510
511
512
513

514
515
516
517
518
519
520
...
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.214 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"

/*
** Set P4 of the most recently inserted opcode to a column affinity
** string for index pIdx. A column affinity string has one character
** for each column in the table, according to the affinity of the column:
................................................................................
  int endOfLoop;        /* Label for the end of the insertion loop */
  int useTempTable = 0; /* Store SELECT results in intermediate table */
  int srcTab = 0;       /* Data comes from this temporary cursor if >=0 */
  int iSelectLoop = 0;  /* Address of code that implements the SELECT */
  int iCleanup = 0;     /* Address of the cleanup code */
  int iInsertBlock = 0; /* Address of the subroutine used to insert data */
  int iCntMem = 0;      /* Memory cell used for the row counter */
  int iBaseReg;         /* Base register for data */
  int newIdx = -1;      /* Cursor for the NEW table */
  Db *pDb;              /* The database containing table being inserted into */
  int counterMem = 0;   /* Memory cell holding AUTOINCREMENT counter */
  int appendFlag = 0;   /* True if the insert is likely to be an append */
  int iDb;

  int nHidden = 0;
................................................................................
  ** statement uses the the table that is being inserted into, then the
  ** subroutine is also coded here.  That subroutine stores the SELECT
  ** results in a temporary table. (Template 3.)
  */
  if( pSelect ){
    /* Data is coming from a SELECT.  Generate code to implement that SELECT
    */
    SelectDest dest;
    int rc, iInitCode;

    iInitCode = sqlite3VdbeAddOp2(v, OP_Goto, 0, 0);
    iSelectLoop = sqlite3VdbeCurrentAddr(v);
    iInsertBlock = sqlite3VdbeMakeLabel(v);
    sqlite3SelectDestInit(&dest, SRT_Subroutine, iInsertBlock);

    /* Resolve the expressions in the SELECT statement and execute it. */
    rc = sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);
    if( rc || pParse->nErr || db->mallocFailed ){
      goto insert_cleanup;
    }

    iBaseReg = dest.iMem;
    iCleanup = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Goto, 0, iCleanup);
    assert( pSelect->pEList );
    nColumn = pSelect->pEList->nExpr;

    /* Set useTempTable to TRUE if the result of the SELECT statement
    ** should be written into a temporary table.  Set to FALSE if each
................................................................................

    if( useTempTable ){
      /* Generate the subroutine that SELECT calls to process each row of
      ** the result.  Store the result in a temporary table
      */
      srcTab = pParse->nTab++;
      sqlite3VdbeResolveLabel(v, iInsertBlock);
      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iBaseReg, nColumn);

      sqlite3VdbeAddOp1(v, OP_NewRowid, srcTab);
      sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
      sqlite3CodeInsert(pParse, srcTab, OPFLAG_APPEND);
      sqlite3VdbeAddOp2(v, OP_Return, 0, 0);

      /* The following code runs first because the GOTO at the very top
      ** of the program jumps to it.  Create the temporary table, then jump
................................................................................
  if( useTempTable ){
    iBreak = sqlite3VdbeMakeLabel(v);
    sqlite3VdbeAddOp2(v, OP_Rewind, srcTab, iBreak);
    iCont = sqlite3VdbeCurrentAddr(v);
  }else if( pSelect ){
    sqlite3VdbeAddOp2(v, OP_Goto, 0, iSelectLoop);
    sqlite3VdbeResolveLabel(v, iInsertBlock);
    sqlite3RegToStack(pParse, iBaseReg, nColumn);
    sqlite3VdbeAddOp2(v, OP_StackDepth, -1, 0);
  }

  /* Run the BEFORE and INSTEAD OF triggers, if there are any
  */
  endOfLoop = sqlite3VdbeMakeLabel(v);
  if( triggers_exist & TRIGGER_BEFORE ){

Changes to src/select.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
28
29
30
31
32
33
34










35
36
37
38
39
40
41
...
538
539
540
541
542
543
544



545
546

547
548
549
550
551
552
553
...
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
...
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
....
1863
1864
1865
1866
1867
1868
1869

1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
....
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
....
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
....
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
....
2252
2253
2254
2255
2256
2257
2258

2259
2260
2261
2262
2263
2264
2265
....
3248
3249
3250
3251
3252
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
....
3268
3269
3270
3271
3272
3273
3274
3275
3276
3277
3278
3279
3280
3281
3282
....
3643
3644
3645
3646
3647
3648
3649
3650
3651

3652
3653
3654
3655
3656
3657
3658
3659
3660
3661
3662
3663
3664
3665
3666
3667
3668
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.389 2008/01/05 18:48:24 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
................................................................................
  sqlite3ExprListDelete(p->pGroupBy);
  sqlite3ExprDelete(p->pHaving);
  sqlite3ExprListDelete(p->pOrderBy);
  sqlite3SelectDelete(p->pPrior);
  sqlite3ExprDelete(p->pLimit);
  sqlite3ExprDelete(p->pOffset);
}












/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
Select *sqlite3SelectNew(
................................................................................
  /* Pull the requested columns.
  */
  if( nColumn>0 ){
    n = nColumn;
  }else{
    n = pEList->nExpr;
  }



  iMem = pParse->nMem+1;
  pParse->nMem += n;

  if( nColumn>0 ){
    for(i=0; i<nColumn; i++){
      sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, iMem+i);
    }
  }else if( eDest!=SRT_Exists ){
    /* If the destination is an EXISTS(...) expression, the actual
    ** values returned by the SELECT are not required.
................................................................................
    */
    case SRT_Subroutine:
    case SRT_Callback: {
      if( pOrderBy ){
        sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
        pushOntoSorter(pParse, pOrderBy, p);
      }else if( eDest==SRT_Subroutine ){
        for(i=0; i<nColumn; i++) sqlite3VdbeAddOp2(v, OP_SCopy, iMem+i, 0);
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, iMem, nColumn);
      }
      break;
    }

................................................................................
    }
#endif
    case SRT_Callback:
    case SRT_Subroutine: {
      int i;
      sqlite3CodeInsert(pParse, pseudoTab, 0);
      for(i=0; i<nColumn; i++){
        sqlite3VdbeAddOp2(v, OP_Column, pseudoTab, i);
      }
      if( eDest==SRT_Callback ){
        sqlite3VdbeAddOp2(v, OP_Callback, nColumn, 0);
      }else{
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }
      break;
    }
    default: {
      /* Do nothing */
................................................................................
  int rc = SQLITE_OK;   /* Success code from a subroutine */
  Select *pPrior;       /* Another SELECT immediately to our left */
  Vdbe *v;              /* Generate code to this VDBE */
  int nCol;             /* Number of columns in the result set */
  ExprList *pOrderBy;   /* The ORDER BY clause on p */
  int aSetP2[2];        /* Set P2 value of these op to number of columns */
  int nSetP2 = 0;       /* Number of slots in aSetP2[] used */


  SelectDest dest;
  dest.eDest = pDest->eDest;
  dest.iParm = pDest->iParm;
  dest.affinity = pDest->affinity;

  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  */
  if( p==0 || p->pPrior==0 ){
    rc = 1;
    goto multi_select_end;
................................................................................
        createSortingIndex(pParse, p, pOrderBy);
        assert( p->pEList );
      }

      /* Code the SELECT statements to our left
      */
      assert( !pPrior->pOrderBy );
      uniondest.eDest = priorOp;
      uniondest.iParm = unionTab;
      rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT statement
      */
................................................................................
      break;
    }
    case TK_INTERSECT: {
      int tab1, tab2;
      int iCont, iBreak, iStart;
      Expr *pLimit, *pOffset;
      int addr;
      SelectDest intersectdest = {SRT_Union, 0, 0};

      /* INTERSECT is different from the others since it requires
      ** two temporary tables.  Hence it has its own case.  Begin
      ** by allocating the tables we will need.
      */
      tab1 = pParse->nTab++;
      tab2 = pParse->nTab++;
................................................................................
      assert( p->addrOpenEphm[0] == -1 );
      p->addrOpenEphm[0] = addr;
      p->pRightmost->usesEphm = 1;
      assert( p->pEList );

      /* Code the SELECTs to our left into temporary table "tab1".
      */
      intersectdest.iParm = tab1;
      rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT into temporary table "tab2"
      */
................................................................................
      generateSortTail(pParse, p, v, p->pEList->nExpr, &dest);
    }

    sqlite3_free(pKeyInfo);
  }

multi_select_end:

  return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

#ifndef SQLITE_OMIT_VIEW
/* Forward Declarations */
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
................................................................................
  /* Generate code for all sub-queries in the FROM clause
  */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  for(i=0; i<pTabList->nSrc; i++){
    const char *zSavedAuthContext = 0;
    int needRestoreContext;
    struct SrcList_item *pItem = &pTabList->a[i];
    SelectDest dest = {SRT_EphemTab, 0, 0};

    if( pItem->pSelect==0 || pItem->isPopulated ) continue;
    if( pItem->zName!=0 ){
      zSavedAuthContext = pParse->zAuthContext;
      pParse->zAuthContext = pItem->zName;
      needRestoreContext = 1;
    }else{
................................................................................
    ** may contain expression trees of at most
    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
    ** more conservative than necessary, but much easier than enforcing
    ** an exact limit.
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);
#endif
    dest.iParm = pItem->iCursor;
    sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0);
    if( db->mallocFailed ){
      goto select_end;
    }
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
    pParse->nHeight -= sqlite3SelectExprHeight(p);
#endif
................................................................................

      flag = minMaxQuery(pParse, p);
      if( flag ){
        pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
        if( pMinMax ){
          pMinMax->a[0].sortOrder = ((flag==ORDERBY_MIN)?0:1);
          pMinMax->a[0].pExpr->op = TK_COLUMN;
        }
	pDel = pMinMax;

      }

      /* This case runs if the aggregate has no GROUP BY clause.  The
      ** processing is much simpler since there is only a single row
      ** of output.
      */
      resetAccumulator(pParse, &sAggInfo);
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
      if( pWInfo==0 ){
        sqlite3ExprListDelete(pMinMax);
        goto select_end;
      }
      updateAccumulator(pParse, &sAggInfo);
      if( !pMinMax && flag ){
        sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
        VdbeComment((v, "%s() by index", (flag==ORDERBY_MIN?"min":"max")));
      }







|







 







>
>
>
>
>
>
>
>
>
>







 







>
>
>
|
|
>







 







<







 







|


|







 







>

<
|
<
<







 







|
<







 







|







 







|







 







>







 







|







 







|







 







<
|
>









|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
...
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
...
689
690
691
692
693
694
695

696
697
698
699
700
701
702
...
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
....
1876
1877
1878
1879
1880
1881
1882
1883
1884

1885


1886
1887
1888
1889
1890
1891
1892
....
1995
1996
1997
1998
1999
2000
2001
2002

2003
2004
2005
2006
2007
2008
2009
....
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
....
2088
2089
2090
2091
2092
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
....
2262
2263
2264
2265
2266
2267
2268
2269
2270
2271
2272
2273
2274
2275
2276
....
3259
3260
3261
3262
3263
3264
3265
3266
3267
3268
3269
3270
3271
3272
3273
....
3279
3280
3281
3282
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
....
3654
3655
3656
3657
3658
3659
3660

3661
3662
3663
3664
3665
3666
3667
3668
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle SELECT statements in SQLite.
**
** $Id: select.c,v 1.390 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.
................................................................................
  sqlite3ExprListDelete(p->pGroupBy);
  sqlite3ExprDelete(p->pHaving);
  sqlite3ExprListDelete(p->pOrderBy);
  sqlite3SelectDelete(p->pPrior);
  sqlite3ExprDelete(p->pLimit);
  sqlite3ExprDelete(p->pOffset);
}

/*
** Initialize a SelectDest structure.
*/
void sqlite3SelectDestInit(SelectDest *pDest, int eDest, int iParm){
  pDest->eDest = eDest;
  pDest->iParm = iParm;
  pDest->affinity = 0;
  pDest->iMem = 0;
}


/*
** Allocate a new Select structure and return a pointer to that
** structure.
*/
Select *sqlite3SelectNew(
................................................................................
  /* Pull the requested columns.
  */
  if( nColumn>0 ){
    n = nColumn;
  }else{
    n = pEList->nExpr;
  }
  if( pDest->iMem>0 ){
    iMem = pDest->iMem;
  }else{
    pDest->iMem = iMem = pParse->nMem+1;
    pParse->nMem += n;
  }
  if( nColumn>0 ){
    for(i=0; i<nColumn; i++){
      sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, iMem+i);
    }
  }else if( eDest!=SRT_Exists ){
    /* If the destination is an EXISTS(...) expression, the actual
    ** values returned by the SELECT are not required.
................................................................................
    */
    case SRT_Subroutine:
    case SRT_Callback: {
      if( pOrderBy ){
        sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
        pushOntoSorter(pParse, pOrderBy, p);
      }else if( eDest==SRT_Subroutine ){

        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, iMem, nColumn);
      }
      break;
    }

................................................................................
    }
#endif
    case SRT_Callback:
    case SRT_Subroutine: {
      int i;
      sqlite3CodeInsert(pParse, pseudoTab, 0);
      for(i=0; i<nColumn; i++){
        sqlite3VdbeAddOp3(v, OP_Column, pseudoTab, i, pDest->iMem+i);
      }
      if( eDest==SRT_Callback ){
        sqlite3VdbeAddOp2(v, OP_ResultRow, pDest->iMem, nColumn);
      }else{
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }
      break;
    }
    default: {
      /* Do nothing */
................................................................................
  int rc = SQLITE_OK;   /* Success code from a subroutine */
  Select *pPrior;       /* Another SELECT immediately to our left */
  Vdbe *v;              /* Generate code to this VDBE */
  int nCol;             /* Number of columns in the result set */
  ExprList *pOrderBy;   /* The ORDER BY clause on p */
  int aSetP2[2];        /* Set P2 value of these op to number of columns */
  int nSetP2 = 0;       /* Number of slots in aSetP2[] used */
  SelectDest dest;      /* Alternative data destination */


  dest = *pDest;



  /* Make sure there is no ORDER BY or LIMIT clause on prior SELECTs.  Only
  ** the last (right-most) SELECT in the series may have an ORDER BY or LIMIT.
  */
  if( p==0 || p->pPrior==0 ){
    rc = 1;
    goto multi_select_end;
................................................................................
        createSortingIndex(pParse, p, pOrderBy);
        assert( p->pEList );
      }

      /* Code the SELECT statements to our left
      */
      assert( !pPrior->pOrderBy );
      sqlite3SelectDestInit(&uniondest, priorOp, unionTab);

      rc = sqlite3Select(pParse, pPrior, &uniondest, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT statement
      */
................................................................................
      break;
    }
    case TK_INTERSECT: {
      int tab1, tab2;
      int iCont, iBreak, iStart;
      Expr *pLimit, *pOffset;
      int addr;
      SelectDest intersectdest;

      /* INTERSECT is different from the others since it requires
      ** two temporary tables.  Hence it has its own case.  Begin
      ** by allocating the tables we will need.
      */
      tab1 = pParse->nTab++;
      tab2 = pParse->nTab++;
................................................................................
      assert( p->addrOpenEphm[0] == -1 );
      p->addrOpenEphm[0] = addr;
      p->pRightmost->usesEphm = 1;
      assert( p->pEList );

      /* Code the SELECTs to our left into temporary table "tab1".
      */
      sqlite3SelectDestInit(&intersectdest, SRT_Union, tab1);
      rc = sqlite3Select(pParse, pPrior, &intersectdest, 0, 0, 0, aff);
      if( rc ){
        goto multi_select_end;
      }

      /* Code the current SELECT into temporary table "tab2"
      */
................................................................................
      generateSortTail(pParse, p, v, p->pEList->nExpr, &dest);
    }

    sqlite3_free(pKeyInfo);
  }

multi_select_end:
  pDest->iMem = dest.iMem;
  return rc;
}
#endif /* SQLITE_OMIT_COMPOUND_SELECT */

#ifndef SQLITE_OMIT_VIEW
/* Forward Declarations */
static void substExprList(sqlite3*, ExprList*, int, ExprList*);
................................................................................
  /* Generate code for all sub-queries in the FROM clause
  */
#if !defined(SQLITE_OMIT_SUBQUERY) || !defined(SQLITE_OMIT_VIEW)
  for(i=0; i<pTabList->nSrc; i++){
    const char *zSavedAuthContext = 0;
    int needRestoreContext;
    struct SrcList_item *pItem = &pTabList->a[i];
    SelectDest dest;

    if( pItem->pSelect==0 || pItem->isPopulated ) continue;
    if( pItem->zName!=0 ){
      zSavedAuthContext = pParse->zAuthContext;
      pParse->zAuthContext = pItem->zName;
      needRestoreContext = 1;
    }else{
................................................................................
    ** may contain expression trees of at most
    ** (SQLITE_MAX_EXPR_DEPTH-Parse.nHeight) height. This is a bit
    ** more conservative than necessary, but much easier than enforcing
    ** an exact limit.
    */
    pParse->nHeight += sqlite3SelectExprHeight(p);
#endif
    sqlite3SelectDestInit(&dest, SRT_EphemTab, pItem->iCursor);
    sqlite3Select(pParse, pItem->pSelect, &dest, p, i, &isAgg, 0);
    if( db->mallocFailed ){
      goto select_end;
    }
#if defined(SQLITE_TEST) || SQLITE_MAX_EXPR_DEPTH>0
    pParse->nHeight -= sqlite3SelectExprHeight(p);
#endif
................................................................................

      flag = minMaxQuery(pParse, p);
      if( flag ){
        pMinMax = sqlite3ExprListDup(db, p->pEList->a[0].pExpr->pList);
        if( pMinMax ){
          pMinMax->a[0].sortOrder = ((flag==ORDERBY_MIN)?0:1);
          pMinMax->a[0].pExpr->op = TK_COLUMN;

          pDel = pMinMax;
        }
      }

      /* This case runs if the aggregate has no GROUP BY clause.  The
      ** processing is much simpler since there is only a single row
      ** of output.
      */
      resetAccumulator(pParse, &sAggInfo);
      pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, &pMinMax, flag);
      if( pWInfo==0 ){
        sqlite3ExprListDelete(pDel);
        goto select_end;
      }
      updateAccumulator(pParse, &sAggInfo);
      if( !pMinMax && flag ){
        sqlite3VdbeAddOp2(v, OP_Goto, 0, pWInfo->iBreak);
        VdbeComment((v, "%s() by index", (flag==ORDERBY_MIN?"min":"max")));
      }

Changes to src/sqliteInt.h.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365
....
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932
1933
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.640 2008/01/05 18:48:24 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro likely() surrounds
................................................................................
** comments above sqlite3Select() for details.
*/
typedef struct SelectDest SelectDest;
struct SelectDest {
  u8 eDest;         /* How to dispose of the results */
  u8 affinity;      /* Affinity used when eDest==SRT_Set */
  int iParm;        /* A parameter used by the eDest disposal method */

};

/*
** An SQL parser context.  A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
................................................................................

void sqlite3StrAccumAppend(StrAccum*,const char*,int);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumReset(StrAccum*);
void sqlite3CodeInsert(Parse *, int, u8);
int sqlite3StackToReg(Parse *, int);
void sqlite3RegToStack(Parse *, int, int);


/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);







|







 







>







 







>







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
....
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
....
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
**    May you do good and not evil.
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.641 2008/01/06 00:25:22 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_

/*
** The macro unlikely() is a hint that surrounds a boolean
** expression that is usually false.  Macro likely() surrounds
................................................................................
** comments above sqlite3Select() for details.
*/
typedef struct SelectDest SelectDest;
struct SelectDest {
  u8 eDest;         /* How to dispose of the results */
  u8 affinity;      /* Affinity used when eDest==SRT_Set */
  int iParm;        /* A parameter used by the eDest disposal method */
  int iMem;         /* Base register where results are written */
};

/*
** An SQL parser context.  A copy of this structure is passed through
** the parser and down into all the parser action routine in order to
** carry around information that is global to the entire parse.
**
................................................................................

void sqlite3StrAccumAppend(StrAccum*,const char*,int);
char *sqlite3StrAccumFinish(StrAccum*);
void sqlite3StrAccumReset(StrAccum*);
void sqlite3CodeInsert(Parse *, int, u8);
int sqlite3StackToReg(Parse *, int);
void sqlite3RegToStack(Parse *, int, int);
void sqlite3SelectDestInit(SelectDest*,int,int);

/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);

Changes to src/trigger.c.

693
694
695
696
697
698
699
700


701
702
703
704
705
706
707
  while( pTriggerStep ){
    orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
    pParse->trigStack->orconf = orconf;
    switch( pTriggerStep->op ){
      case TK_SELECT: {
        Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect);
        if( ss ){
          SelectDest dest = {SRT_Discard, 0, 0};


          sqlite3SelectResolve(pParse, ss, 0);
          sqlite3Select(pParse, ss, &dest, 0, 0, 0, 0);
          sqlite3SelectDelete(ss);
        }
        break;
      }
      case TK_UPDATE: {







|
>
>







693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
  while( pTriggerStep ){
    orconf = (orconfin == OE_Default)?pTriggerStep->orconf:orconfin;
    pParse->trigStack->orconf = orconf;
    switch( pTriggerStep->op ){
      case TK_SELECT: {
        Select *ss = sqlite3SelectDup(db, pTriggerStep->pSelect);
        if( ss ){
          SelectDest dest;

          sqlite3SelectDestInit(&dest, SRT_Discard, 0);
          sqlite3SelectResolve(pParse, ss, 0);
          sqlite3Select(pParse, ss, &dest, 0, 0, 0, 0);
          sqlite3SelectDelete(ss);
        }
        break;
      }
      case TK_UPDATE: {

Changes to src/update.c.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
325
326
327
328
329
330
331
332

333
334
335

336
337
338
339
340
341
342
...
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
...
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.161 2008/01/05 17:39:30 danielk1977 Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
  }

  /* If we are trying to update a view, realize that view into
  ** a ephemeral table.
  */
  if( isView ){
    Select *pView;
    SelectDest dest = {SRT_EphemTab, 0, 0};

    pView = sqlite3SelectDup(db, pTab->pSelect);
    sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask);
    dest.iParm = iCur;

    sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
    sqlite3SelectDelete(pView);
  }

  /* Begin the database scan
  */
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
................................................................................
  Expr *pExpr;              /* Temporary expression */
  int ephemTab;             /* Table holding the result of the SELECT */
  int i;                    /* Loop counter */
  int addr;                 /* Address of top of loop */
  int iReg;                 /* First register in set passed to OP_VUpdate */
  sqlite3 *db = pParse->db; /* Database connection */
  const char *pVtab = (const char*)pTab->pVtab;
  SelectDest dest = {SRT_Table, 0, 0};

  /* Construct the SELECT statement that will find the new values for
  ** all updated rows. 
  */
  pEList = sqlite3ExprListAppend(pParse, 0, 
                                 sqlite3CreateIdExpr(pParse, "_rowid_"), 0);
  if( pRowid ){
................................................................................
  */
  assert( v );
  ephemTab = pParse->nTab++;
  sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));

  /* fill the ephemeral table 
  */
  dest.iParm = ephemTab;
  sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);

  /* Generate code to scan the ephemeral table and call VUpdate. */
  iReg = ++pParse->nMem;
  pParse->nMem += pTab->nCol+1;
  sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0);
  addr = sqlite3VdbeCurrentAddr(v);







|







 







|
>


<
>







 







|







 







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
325
326
327
328
329
330
331
332
333
334
335

336
337
338
339
340
341
342
343
...
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
...
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
**    May you find forgiveness for yourself and forgive others.
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This file contains C code routines that are called by the parser
** to handle UPDATE statements.
**
** $Id: update.c,v 1.162 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"

#ifndef SQLITE_OMIT_VIRTUALTABLE
/* Forward declaration */
static void updateVirtualTable(
  Parse *pParse,       /* The parsing context */
................................................................................
  }

  /* If we are trying to update a view, realize that view into
  ** a ephemeral table.
  */
  if( isView ){
    Select *pView;
    SelectDest dest;

    pView = sqlite3SelectDup(db, pTab->pSelect);
    sqlite3SelectMask(pParse, pView, old_col_mask|new_col_mask);

    sqlite3SelectDestInit(&dest, SRT_EphemTab, iCur);
    sqlite3Select(pParse, pView, &dest, 0, 0, 0, 0);
    sqlite3SelectDelete(pView);
  }

  /* Begin the database scan
  */
  pWInfo = sqlite3WhereBegin(pParse, pTabList, pWhere, 0, 0);
................................................................................
  Expr *pExpr;              /* Temporary expression */
  int ephemTab;             /* Table holding the result of the SELECT */
  int i;                    /* Loop counter */
  int addr;                 /* Address of top of loop */
  int iReg;                 /* First register in set passed to OP_VUpdate */
  sqlite3 *db = pParse->db; /* Database connection */
  const char *pVtab = (const char*)pTab->pVtab;
  SelectDest dest;

  /* Construct the SELECT statement that will find the new values for
  ** all updated rows. 
  */
  pEList = sqlite3ExprListAppend(pParse, 0, 
                                 sqlite3CreateIdExpr(pParse, "_rowid_"), 0);
  if( pRowid ){
................................................................................
  */
  assert( v );
  ephemTab = pParse->nTab++;
  sqlite3VdbeAddOp2(v, OP_OpenEphemeral, ephemTab, pTab->nCol+1+(pRowid!=0));

  /* fill the ephemeral table 
  */
  sqlite3SelectDestInit(&dest, SRT_Table, ephemTab);
  sqlite3Select(pParse, pSelect, &dest, 0, 0, 0, 0);

  /* Generate code to scan the ephemeral table and call VUpdate. */
  iReg = ++pParse->nMem;
  pParse->nMem += pTab->nCol+1;
  sqlite3VdbeAddOp2(v, OP_Rewind, ephemTab, 0);
  addr = sqlite3VdbeCurrentAddr(v);

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2666
2667
2668
2669
2670
2671
2672

2673
2674
2675
2676
2677
2678
2679
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.685 2008/01/05 18:48:24 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
    pOut->xDel = 0;
  }
  if( nZero ){
    pOut->u.i = nZero;
    pOut->flags |= MEM_Zero;
  }
  pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */


  /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
  if( jumpIfNull && containsNull ){
    pc = jumpIfNull - 1;
  }
  break;
}







|







 







>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
**
** Various scripts scan this source file in order to generate HTML
** documentation, headers files, or other derived files.  The formatting
** of the code in this file is, therefore, important.  See other comments
** in this file for details.  If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.686 2008/01/06 00:25:22 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor
................................................................................
    pOut->xDel = 0;
  }
  if( nZero ){
    pOut->u.i = nZero;
    pOut->flags |= MEM_Zero;
  }
  pOut->enc = SQLITE_UTF8;  /* In case the blob is ever converted to text */
  REGISTER_TRACE(pOp->p3, pOut);

  /* If a NULL was encountered and jumpIfNull is non-zero, take the jump. */
  if( jumpIfNull && containsNull ){
    pc = jumpIfNull - 1;
  }
  break;
}

Changes to test/insert5.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The tests in this file ensure that a temporary table is used
# when required by an "INSERT INTO ... SELECT ..." statement.
#
# $Id: insert5.test,v 1.3 2007/12/13 07:58:51 danielk1977 Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !subquery {
  finish_test
  return
................................................................................
# Run the query.
#
do_test insert5-1.1 {
  execsql {
    INSERT INTO B 
      SELECT * FROM B UNION ALL 
      SELECT * FROM MAIN WHERE exists (select * FROM B WHERE B.Id = MAIN.Id);
    SELECT * FROM B;
  }
} {2 3 2 3 2 3}

do_test insert5-2.1 {
  uses_temp_table { INSERT INTO b SELECT * FROM main }
} {0}
do_test insert5-2.2 {
  uses_temp_table { INSERT INTO b SELECT * FROM b }
} {1}
do_test insert5-2.3 {







|







 







|


<







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
48
49
50
51
52
53
54
55
56
57

58
59
60
61
62
63
64
#    May you share freely, never taking more than you give.
#
#***********************************************************************
#
# The tests in this file ensure that a temporary table is used
# when required by an "INSERT INTO ... SELECT ..." statement.
#
# $Id: insert5.test,v 1.4 2008/01/06 00:25:22 drh Exp $

set testdir [file dirname $argv0]
source $testdir/tester.tcl

ifcapable !subquery {
  finish_test
  return
................................................................................
# Run the query.
#
do_test insert5-1.1 {
  execsql {
    INSERT INTO B 
      SELECT * FROM B UNION ALL 
      SELECT * FROM MAIN WHERE exists (select * FROM B WHERE B.Id = MAIN.Id);
      SELECT * FROM B;
  }
} {2 3 2 3 2 3}

do_test insert5-2.1 {
  uses_temp_table { INSERT INTO b SELECT * FROM main }
} {0}
do_test insert5-2.2 {
  uses_temp_table { INSERT INTO b SELECT * FROM b }
} {1}
do_test insert5-2.3 {