SQLite

Check-in [6bb1b1bc18]
Login

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

Overview
Comment:Modify OP_RegMakeRec to take a base register and count and optionally store results in the register specified by P3. (CVS 4689)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 6bb1b1bc1858028b743a4f660d42d5e9595dc022
User & Date: drh 2008-01-05 18:48:24.000
Context
2008-01-06
00:25
Registerify the SRT_Subroutine destination for SELECT results. (CVS 4690) (check-in: 8201f71729 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: 6bb1b1bc18 user: drh tags: trunk)
18:44
Fix a memory leak introduced with #4687. (CVS 4688) (check-in: 2b98b0fca8 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/build.c.
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
**     CREATE INDEX
**     DROP INDEX
**     creating ID lists
**     BEGIN TRANSACTION
**     COMMIT
**     ROLLBACK
**
** $Id: build.c,v 1.459 2008/01/05 05:20:10 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.







|







18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
**     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.
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
    **
    ** 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, 1, 0};
      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 ){







|







1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
    **
    ** 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 ){
Changes to src/select.c.
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.388 2008/01/05 18:44:29 danielk1977 Exp $
*/
#include "sqliteInt.h"


/*
** Delete all the content of a Select structure but do not deallocate
** the select structure itself.







|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
**    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.
459
460
461
462
463
464
465

466
467
468
469
470
471
472
473
474
475
** A jump to addrRepeat is made and the N+1 values are popped from the
** stack if the top N elements are not distinct.
*/
static void codeDistinct(
  Vdbe *v,           /* Generate code into this VM */
  int iTab,          /* A sorting index used to test for distinctness */
  int addrRepeat,    /* Jump to here if not distinct */

  int iMem           /* First element */
){
  sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
  sqlite3VdbeAddOp2(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
  sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrRepeat);
  VdbeComment((v, "skip indistinct records"));
  sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, 0);
}








>


|







459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
** A jump to addrRepeat is made and the N+1 values are popped from the
** stack if the top N elements are not distinct.
*/
static void codeDistinct(
  Vdbe *v,           /* Generate code into this VM */
  int iTab,          /* A sorting index used to test for distinctness */
  int addrRepeat,    /* Jump to here if not distinct */
  int N,             /* Number of elements */
  int iMem           /* First element */
){
  sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, N);
  sqlite3VdbeAddOp2(v, OP_Distinct, iTab, sqlite3VdbeCurrentAddr(v)+3);
  sqlite3VdbeAddOp2(v, OP_Pop, 1, 0);
  sqlite3VdbeAddOp2(v, OP_Goto, 0, addrRepeat);
  VdbeComment((v, "skip indistinct records"));
  sqlite3VdbeAddOp2(v, OP_IdxInsert, iTab, 0);
}

537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  /* Pull the requested columns.
  */
  if( nColumn>0 ){
    n = nColumn;
  }else{
    n = pEList->nExpr;
  }
  iMem = ++pParse->nMem;
  pParse->nMem += n+1;
  sqlite3VdbeAddOp2(v, OP_Integer, n, iMem);
  if( nColumn>0 ){
    for(i=0; i<nColumn; i++){
      sqlite3VdbeAddOp3(v, OP_Column, srcTab, i, iMem+i+1);
    }
  }else if( eDest!=SRT_Exists ){
    /* If the destination is an EXISTS(...) expression, the actual
    ** values returned by the SELECT are not required.
    */
    for(i=0; i<n; i++){
      sqlite3ExprCode(pParse, pEList->a[i].pExpr, iMem+i+1);
    }
  }
  nColumn = n;

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( hasDistinct ){
    assert( pEList!=0 );
    assert( pEList->nExpr==nColumn );
    codeDistinct(v, distinct, iContinue, iMem);
    if( pOrderBy==0 ){
      codeOffset(v, p, iContinue, nColumn);
    }
  }

  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
    return 0;
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.
    */
#ifndef SQLITE_OMIT_COMPOUND_SELECT
    case SRT_Union: {
      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
      if( aff ){
        sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
      }
      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      break;
    }

    /* Construct a record from the query result, but instead of
    ** saving that record, use it as a key to delete elements from
    ** the temporary table iParm.
    */
    case SRT_Except: {
      int addr;
      addr = sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
      sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
      sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3);
      sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0);
      break;
    }
#endif

    /* Store the result as data using a unique key.
    */
    case SRT_Table:
    case SRT_EphemTab: {
      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp1(v, OP_NewRowid, iParm);
        sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
        sqlite3CodeInsert(pParse, iParm, OPFLAG_APPEND);
      }
      break;
    }

#ifndef SQLITE_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
      int addr2;

      assert( nColumn==1 );
      addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem+1, 0);
      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
      if( pOrderBy ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 0, 0, &p->affinity, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      }
      sqlite3VdbeJumpHere(v, addr2);
      break;
    }

    /* If any row exist in the result set, record that fact and abort.
    */
    case SRT_Exists: {
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3VdbeAddOp2(v, OP_SCopy, iMem+1, 0);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp2(v, OP_Move, 0, iParm);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    /* Send the data to the callback function or to a subroutine.  In the
    ** case of a subroutine, the subroutine itself is responsible for
    ** popping the data from the stack.
    */
    case SRT_Subroutine:
    case SRT_Callback: {
      if( pOrderBy ){
        sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else if( eDest==SRT_Subroutine ){
        for(i=0; i<nColumn; i++) sqlite3VdbeAddOp2(v, OP_SCopy, iMem+i+1, 0);
        sqlite3VdbeAddOp2(v, OP_Gosub, 0, iParm);
      }else{
        sqlite3VdbeAddOp2(v, OP_ResultRow, iMem+1, nColumn);
      }
      break;
    }

#if !defined(SQLITE_OMIT_TRIGGER)
    /* Discard the results.  This is used for SELECT statements inside
    ** the body of a TRIGGER.  The purpose of such selects is to call







|
|
<


|






|











|















|













|











|



















|






|


|




















|

















|


|


|







538
539
540
541
542
543
544
545
546

547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
  /* 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.
    */
    for(i=0; i<n; i++){
      sqlite3ExprCode(pParse, pEList->a[i].pExpr, iMem+i);
    }
  }
  nColumn = n;

  /* If the DISTINCT keyword was present on the SELECT statement
  ** and this row has been seen before, then do not make this row
  ** part of the result.
  */
  if( hasDistinct ){
    assert( pEList!=0 );
    assert( pEList->nExpr==nColumn );
    codeDistinct(v, distinct, iContinue, nColumn, iMem);
    if( pOrderBy==0 ){
      codeOffset(v, p, iContinue, nColumn);
    }
  }

  if( checkForMultiColumnSelectError(pParse, pDest, pEList->nExpr) ){
    return 0;
  }

  switch( eDest ){
    /* In this mode, write each query result to the key of the temporary
    ** table iParm.
    */
#ifndef SQLITE_OMIT_COMPOUND_SELECT
    case SRT_Union: {
      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
      if( aff ){
        sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
      }
      sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      break;
    }

    /* Construct a record from the query result, but instead of
    ** saving that record, use it as a key to delete elements from
    ** the temporary table iParm.
    */
    case SRT_Except: {
      int addr;
      addr = sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
      sqlite3VdbeChangeP4(v, -1, aff, P4_STATIC);
      sqlite3VdbeAddOp2(v, OP_NotFound, iParm, addr+3);
      sqlite3VdbeAddOp2(v, OP_Delete, iParm, 0);
      break;
    }
#endif

    /* Store the result as data using a unique key.
    */
    case SRT_Table:
    case SRT_EphemTab: {
      sqlite3VdbeAddOp2(v, OP_RegMakeRec, iMem, nColumn);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp1(v, OP_NewRowid, iParm);
        sqlite3VdbeAddOp2(v, OP_Pull, 1, 0);
        sqlite3CodeInsert(pParse, iParm, OPFLAG_APPEND);
      }
      break;
    }

#ifndef SQLITE_OMIT_SUBQUERY
    /* If we are creating a set for an "expr IN (SELECT ...)" construct,
    ** then there should be a single item on the stack.  Write this
    ** item into the set table with bogus data.
    */
    case SRT_Set: {
      int addr2;

      assert( nColumn==1 );
      addr2 = sqlite3VdbeAddOp2(v, OP_IfMemNull, iMem, 0);
      p->affinity = sqlite3CompareAffinity(pEList->a[0].pExpr, pDest->affinity);
      if( pOrderBy ){
        /* At first glance you would think we could optimize out the
        ** ORDER BY in this case since the order of entries in the set
        ** does not matter.  But there might be a LIMIT clause, in which
        ** case the order does matter */
        sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0);
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp4(v, OP_RegMakeRec, iMem, 1, 0, &p->affinity, 1);
        sqlite3VdbeAddOp2(v, OP_IdxInsert, iParm, 0);
      }
      sqlite3VdbeJumpHere(v, addr2);
      break;
    }

    /* If any row exist in the result set, record that fact and abort.
    */
    case SRT_Exists: {
      sqlite3VdbeAddOp2(v, OP_Integer, 1, iParm);
      /* The LIMIT clause will terminate the loop for us */
      break;
    }

    /* If this is a scalar select that is part of an expression, then
    ** store the results in the appropriate memory cell and break out
    ** of the scan loop.
    */
    case SRT_Mem: {
      assert( nColumn==1 );
      sqlite3VdbeAddOp2(v, OP_SCopy, iMem, 0);
      if( pOrderBy ){
        pushOntoSorter(pParse, pOrderBy, p);
      }else{
        sqlite3VdbeAddOp2(v, OP_Move, 0, iParm);
        /* The LIMIT clause will jump out of the loop for us */
      }
      break;
    }
#endif /* #ifndef SQLITE_OMIT_SUBQUERY */

    /* Send the data to the callback function or to a subroutine.  In the
    ** case of a subroutine, the subroutine itself is responsible for
    ** popping the data from the stack.
    */
    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;
    }

#if !defined(SQLITE_OMIT_TRIGGER)
    /* Discard the results.  This is used for SELECT statements inside
    ** the body of a TRIGGER.  The purpose of such selects is to call
Changes to src/sqliteInt.h.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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.639 2008/01/05 17:39:30 danielk1977 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













|







1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
** 2001 September 15
**
** The author disclaims copyright to this source code.  In place of
** a legal notice, here is a blessing:
**
**    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
1349
1350
1351
1352
1353
1354
1355
1356

1357
1358
1359
1360
1361
1362
1363
1364
1365

/*
** A structure used to customize the behaviour of sqlite3Select(). See
** comments above sqlite3Select() for details.
*/
typedef struct SelectDest SelectDest;
struct SelectDest {
  int eDest;        /* How to dispose of the results */

  int iParm;        /* A parameter used by the eDest disposal method */
  int affinity;     /* Affinity used when eDest==SRT_Set */
};

/*
** 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.
**







|
>

<







1349
1350
1351
1352
1353
1354
1355
1356
1357
1358

1359
1360
1361
1362
1363
1364
1365

/*
** A structure used to customize the behaviour of sqlite3Select(). See
** 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.
**
Changes to src/vdbe.c.
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** 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.684 2008/01/05 16:29:28 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
** The following global variable is incremented every time a cursor







|







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
**
** 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
2126
2127
2128
2129
2130
2131
2132



















2133
2134
2135
2136
2137
2138
2139
    }
  }
  if( pOp->p1>0 ){
    popStack(&pTos, pOp->p1);
  }
  break;
}




















/* Opcode: NotNull P1 P2 *
**
** Jump to P2 if the top abs(P1) values on the stack are all not NULL.  
** Regardless of whether or not the jump is taken, pop the stack
** P1 times if P1 is greater than zero.  But if P1 is negative,
** leave the stack unchanged.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
    }
  }
  if( pOp->p1>0 ){
    popStack(&pTos, pOp->p1);
  }
  break;
}

/* Opcode: AnyNull P1 P2 P3 * *
**
** Check P3 registers beginning with P1.  If any are NULL then jump
** to P2.
*/
case OP_AnyNull: {            /* no-push, jump, in1 */
  int n = pOp->p3;
  assert( n>0 && pOp->p1+n<=p->nMem );
  while( n>0 ){
    if( pIn1->flags & MEM_Null ){
      pc = pOp->p2-1;
      break;
    }
    n--;
    pIn1++;
  }
  break;
}

/* Opcode: NotNull P1 P2 *
**
** Jump to P2 if the top abs(P1) values on the stack are all not NULL.  
** Regardless of whether or not the jump is taken, pop the stack
** P1 times if P1 is greater than zero.  But if P1 is negative,
** leave the stack unchanged.
2459
2460
2461
2462
2463
2464
2465
2466
2467
2468
2469
2470
2471



2472
2473
2474
2475
2476
2477
2478
**
** This opcode works just OP_MakeRecord except that it reads an extra
** integer from the stack (thus reading a total of abs(P1+1) entries)
** and appends that extra integer to the end of the record as a varint.
** This results in an index key.
*/
/*
** Opcode: RegMakeRec P1 P2 P4
**
** Works like OP_MakeRecord except data is taken from registers
** rather than from the stack.  The P1 register is an integer which
** is the number of register to use in building the new record.
** Data is taken from P1+1, P1+2, ..., P1+mem[P1].



*/
/*
** Opcode: RegMakeIRec P1 P2 P4
**
** Works like OP_MakeIdxRec except data is taken from registers
** rather than from the stack.  The P1 register is an integer which
** is the number of register to use in building the new record.







|

|
<
<
|
>
>
>







2478
2479
2480
2481
2482
2483
2484
2485
2486
2487


2488
2489
2490
2491
2492
2493
2494
2495
2496
2497
2498
**
** This opcode works just OP_MakeRecord except that it reads an extra
** integer from the stack (thus reading a total of abs(P1+1) entries)
** and appends that extra integer to the end of the record as a varint.
** This results in an index key.
*/
/*
** Opcode: RegMakeRec P1 P2 P3 P4 *
**
** Builds a record like OP_MakeRecord.  But the data is taken from


** P2 registers beginning with P1:  P1, P1+1, P1+2, ..., P1+P2-1.
** The result is written into P3 or pushed onto the stack if P3 is zero.
** There is no jump on NULL - that can be done with a separate
** OP_AnyNull opcode.
*/
/*
** Opcode: RegMakeIRec P1 P2 P4
**
** Works like OP_MakeIdxRec except data is taken from registers
** rather than from the stack.  The P1 register is an integer which
** is the number of register to use in building the new record.
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543

2544
2545
2546
2547
2548
2549
2550
    assert( pOp->opcode==OP_MakeRecord || pOp->opcode==OP_MakeIdxRec );
    leaveOnStack = 1;
    nField = -pOp->p1;
  }else{
    leaveOnStack = 0;
    nField = pOp->p1;
  }
  jumpIfNull = pOp->p2;
  addRowid = pOp->opcode==OP_MakeIdxRec || pOp->opcode==OP_RegMakeIRec;
  zAffinity = pOp->p4.z;

  if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){
    Mem *pCount;
    assert( nField>0 && nField<=p->nMem );
    pCount = &p->aMem[nField];
    assert( pCount->flags & MEM_Int );
    assert( pCount->u.i>0 && pCount->u.i+nField<=p->nMem );
    leaveOnStack = 1;
    nField = pCount->u.i;
    pData0 = &pCount[1];
    pLast = &pData0[nField-1];
  }else{

    pData0 = &pTos[1-nField];
    pLast = pTos;
    assert( pData0>=p->aStack );
  }
  containsNull = 0;
  file_format = p->minWriteFileFormat;








<




<
|
|
<
|

<
|


>







2542
2543
2544
2545
2546
2547
2548

2549
2550
2551
2552

2553
2554

2555
2556

2557
2558
2559
2560
2561
2562
2563
2564
2565
2566
2567
    assert( pOp->opcode==OP_MakeRecord || pOp->opcode==OP_MakeIdxRec );
    leaveOnStack = 1;
    nField = -pOp->p1;
  }else{
    leaveOnStack = 0;
    nField = pOp->p1;
  }

  addRowid = pOp->opcode==OP_MakeIdxRec || pOp->opcode==OP_RegMakeIRec;
  zAffinity = pOp->p4.z;

  if( pOp->opcode==OP_RegMakeRec || pOp->opcode==OP_RegMakeIRec ){

    assert( nField>0 && pOp->p2>0 && pOp->p2+nField<=p->nMem );
    pData0 = &p->aMem[nField];

    nField = pOp->p2;
    leaveOnStack = 1;

    jumpIfNull = 0;
    pLast = &pData0[nField-1];
  }else{
    jumpIfNull = pOp->p2;
    pData0 = &pTos[1-nField];
    pLast = pTos;
    assert( pData0>=p->aStack );
  }
  containsNull = 0;
  file_format = p->minWriteFileFormat;

2626
2627
2628
2629
2630
2631
2632

2633




2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
  }
  assert( i==nByte );

  /* Pop entries off the stack if required. Push the new record on. */
  if( !leaveOnStack ){
    popStack(&pTos, nField+addRowid);
  }

  pTos++;




  pTos->n = nByte;
  if( nByte<=sizeof(zTemp) ){
    assert( zNewRecord==(unsigned char *)zTemp );
    pTos->z = pTos->zShort;
    memcpy(pTos->zShort, zTemp, nByte);
    pTos->flags = MEM_Blob | MEM_Short;
  }else{
    assert( zNewRecord!=(unsigned char *)zTemp );
    pTos->z = (char*)zNewRecord;
    pTos->flags = MEM_Blob | MEM_Dyn;
    pTos->xDel = 0;
  }
  if( nZero ){
    pTos->u.i = nZero;
    pTos->flags |= MEM_Zero;
  }
  pTos->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;
}







>
|
>
>
>
>
|


|
|
|


|
|
|


|
|

|







2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
  }
  assert( i==nByte );

  /* Pop entries off the stack if required. Push the new record on. */
  if( !leaveOnStack ){
    popStack(&pTos, nField+addRowid);
  }
  if( pOp->p3==0 ){
    pOut = ++pTos;
  }else{
    pOut = &p->aMem[pOp->p3];
    Release(pOut);
  }
  pOut->n = nByte;
  if( nByte<=sizeof(zTemp) ){
    assert( zNewRecord==(unsigned char *)zTemp );
    pOut->z = pOut->zShort;
    memcpy(pOut->zShort, zTemp, nByte);
    pOut->flags = MEM_Blob | MEM_Short;
  }else{
    assert( zNewRecord!=(unsigned char *)zTemp );
    pOut->z = (char*)zNewRecord;
    pOut->flags = MEM_Blob | MEM_Dyn;
    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;
}