/ Check-in [8d9eab17]
Login

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

Overview
Comment:Cache record headers in the OP_Column opcode. (CVS 1382)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:8d9eab178f285415775060369f372a88c7091f9f
User & Date: drh 2004-05-14 21:12:23
Context
2004-05-14
21:59
Allocates VDBE cursors one by one in separate memory so that pointers to cursors can persist through a realloc(). (CVS 1383) check-in: d8bacc16 user: drh tags: trunk
21:12
Cache record headers in the OP_Column opcode. (CVS 1382) check-in: 8d9eab17 user: drh tags: trunk
19:08
More speed improvements. (CVS 1381) check-in: cf75cac9 user: drh tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btree.c.

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
1454
1455
1456
1457
1458
1459
1460

















1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476

1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
....
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
....
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
** 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.
**
*************************************************************************
** $Id: btree.c,v 1.138 2004/05/14 19:08:18 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
** function above.
*/
static void releaseTempCursor(BtCursor *pCur){
  if( pCur->pPage ){
    sqlite3pager_unref(pCur->pPage->aData);
  }
}


















/*
** Set *pSize to the size of the buffer needed to hold the value of
** the key for the current entry.  If the cursor is not pointing
** to a valid entry, *pSize is set to 0. 
**
** For a table with the INTKEY flag set, this routine returns the key
** itself, not the number of bytes in the key.
*/
int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
  MemPage *pPage;
  unsigned char *cell;

  if( !pCur->isValid ){
    *pSize = 0;
  }else{

    pPage = pCur->pPage;
    pageIntegrity(pPage);
    assert( pPage!=0 );
    assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
    cell = pPage->aCell[pCur->idx];
    cell += 2;   /* Skip the offset to the next cell */
    if( !pPage->leaf ){
      cell += 4;  /* Skip the child pointer */
    }
    if( pPage->hasData ){
      while( (0x80&*(cell++))!=0 ){}  /* Skip the data size number */
    }
    getVarint(cell, pSize);
  }
  return SQLITE_OK;
}

/*
** Set *pSize to the number of bytes of data in the entry the
** cursor currently points to.  Always return SQLITE_OK.
** Failure is not possible.  If the cursor is not currently
** pointing to an entry (which can happen, for example, if
** the database is empty) then *pSize is set to 0.
*/
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
  MemPage *pPage;
  unsigned char *cell;

  if( !pCur->isValid ){
    /* Not pointing at a valid entry - set *pSize to 0. */
    *pSize = 0;
  }else{
    pPage = pCur->pPage;
    assert( pPage!=0 );
    assert( pPage->isInit );
    pageIntegrity(pPage);
    if( !pPage->hasData ){
      *pSize = 0;
    }else{
      assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
      cell = pPage->aCell[pCur->idx];
      cell += 2;   /* Skip the offset to the next cell */
      if( !pPage->leaf ){
        cell += 4;  /* Skip the child pointer */
      }
      getVarint32(cell, pSize);
    }
  }
  return SQLITE_OK;
}

/*
** Read payload information from the entry that the pCur cursor is
** pointing to.  Begin reading the payload at "offset" and read
................................................................................
  assert( pCur!=0 && pCur->pPage!=0 );
  assert( pCur->isValid );
  pBt = pCur->pBt;
  pPage = pCur->pPage;
  pageIntegrity(pPage);
  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  aPayload = pPage->aCell[pCur->idx];
  if( !pCur->infoValid ){
    parseCell(pPage, aPayload, &pCur->info);
    pCur->infoValid = 1;
  }else{
#ifndef NDEBUG
    CellInfo info;
    parseCell(pPage, aPayload, &info);
    assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
#endif
  }
  aPayload += pCur->info.nHeader;
  if( pPage->intKey ){
    nKey = 0;
  }else{
    nKey = pCur->info.nKey;
  }
  assert( offset>=0 );
................................................................................
  assert( pCur!=0 && pCur->pPage!=0 );
  assert( pCur->isValid );
  pBt = pCur->pBt;
  pPage = pCur->pPage;
  pageIntegrity(pPage);
  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  aPayload = pPage->aCell[pCur->idx];
  if( !pCur->infoValid ){
    parseCell(pPage, aPayload, &pCur->info);
    pCur->infoValid = 1;
  }else{
#ifndef NDEBUG
    CellInfo info;
    parseCell(pPage, aPayload, &info);
    assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
#endif
  }
  aPayload += pCur->info.nHeader;
  if( pPage->intKey ){
    nKey = 0;
  }else{
    nKey = pCur->info.nKey;
  }
  if( skipKey ){







|







 







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










<
<
<



>
|
<
<
<
<
<
<
<
<
<
<
<
<












<
<
<




|
<
<
<
<
|
<
<
<
<
<
<
<
<
<







 







<
<
<
<
<
|
<
<
<
<







 







<
<
<
<
<
|
<
<
<
<







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487



1488
1489
1490
1491
1492












1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504



1505
1506
1507
1508
1509




1510









1511
1512
1513
1514
1515
1516
1517
....
1538
1539
1540
1541
1542
1543
1544





1545




1546
1547
1548
1549
1550
1551
1552
....
1677
1678
1679
1680
1681
1682
1683





1684




1685
1686
1687
1688
1689
1690
1691
** 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.
**
*************************************************************************
** $Id: btree.c,v 1.139 2004/05/14 21:12:23 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
**
**     Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3:
**     "Sorting And Searching", pages 473-480. Addison-Wesley
**     Publishing Company, Reading, Massachusetts.
................................................................................
** function above.
*/
static void releaseTempCursor(BtCursor *pCur){
  if( pCur->pPage ){
    sqlite3pager_unref(pCur->pPage->aData);
  }
}

/*
** Make sure the BtCursor.info field of the given cursor is valid.
*/
static void getCellInfo(BtCursor *pCur){
  MemPage *pPage = pCur->pPage;
  if( !pCur->infoValid ){
    parseCell(pPage, pPage->aCell[pCur->idx], &pCur->info);
    pCur->infoValid = 1;
  }else{
#ifndef NDEBUG
    CellInfo info;
    parseCell(pPage, pPage->aCell[pCur->idx], &info);
    assert( memcmp(&info, &pCur->info, sizeof(info))==0 );
#endif
  }
}

/*
** Set *pSize to the size of the buffer needed to hold the value of
** the key for the current entry.  If the cursor is not pointing
** to a valid entry, *pSize is set to 0. 
**
** For a table with the INTKEY flag set, this routine returns the key
** itself, not the number of bytes in the key.
*/
int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){



  if( !pCur->isValid ){
    *pSize = 0;
  }else{
    getCellInfo(pCur);
    *pSize = pCur->info.nKey;












  }
  return SQLITE_OK;
}

/*
** Set *pSize to the number of bytes of data in the entry the
** cursor currently points to.  Always return SQLITE_OK.
** Failure is not possible.  If the cursor is not currently
** pointing to an entry (which can happen, for example, if
** the database is empty) then *pSize is set to 0.
*/
int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){



  if( !pCur->isValid ){
    /* Not pointing at a valid entry - set *pSize to 0. */
    *pSize = 0;
  }else{
    getCellInfo(pCur);




    *pSize = pCur->info.nData;









  }
  return SQLITE_OK;
}

/*
** Read payload information from the entry that the pCur cursor is
** pointing to.  Begin reading the payload at "offset" and read
................................................................................
  assert( pCur!=0 && pCur->pPage!=0 );
  assert( pCur->isValid );
  pBt = pCur->pBt;
  pPage = pCur->pPage;
  pageIntegrity(pPage);
  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  aPayload = pPage->aCell[pCur->idx];





  getCellInfo(pCur);




  aPayload += pCur->info.nHeader;
  if( pPage->intKey ){
    nKey = 0;
  }else{
    nKey = pCur->info.nKey;
  }
  assert( offset>=0 );
................................................................................
  assert( pCur!=0 && pCur->pPage!=0 );
  assert( pCur->isValid );
  pBt = pCur->pBt;
  pPage = pCur->pPage;
  pageIntegrity(pPage);
  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  aPayload = pPage->aCell[pCur->idx];





  getCellInfo(pCur);




  aPayload += pCur->info.nHeader;
  if( pPage->intKey ){
    nKey = 0;
  }else{
    nKey = pCur->info.nKey;
  }
  if( skipKey ){

Changes to src/vdbe.c.

39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
....
1901
1902
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
....
1920
1921
1922
1923
1924
1925
1926

1927
1928
1929
1930
1931
1932


1933
1934
1935
1936
1937
1938
1939
1940
1941
1942

1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957


1958
1959
1960
1961
1962
1963


1964
1965
1966
1967
1968
1969
1970
1971





1972



1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007

2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042


2043





2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087
2088
2089
2090
2091
2092
....
2818
2819
2820
2821
2822
2823
2824

2825
2826
2827
2828
2829
2830
2831
....
2895
2896
2897
2898
2899
2900
2901

2902
2903
2904
2905
2906
2907
2908
....
2964
2965
2966
2967
2968
2969
2970
2971

2972
2973
2974
2975
2976
2977
2978
....
3021
3022
3023
3024
3025
3026
3027

3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040

3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
....
3144
3145
3146
3147
3148
3149
3150

3151
3152
3153
3154
3155
3156
3157
....
3245
3246
3247
3248
3249
3250
3251

3252
3253
3254
3255
3256
3257
3258
....
3274
3275
3276
3277
3278
3279
3280

3281
3282
3283
3284
3285
3286
3287
....
3486
3487
3488
3489
3490
3491
3492

3493
3494
3495
3496
3497
3498
3499
....
3515
3516
3517
3518
3519
3520
3521

3522
3523
3524
3525
3526
3527
3528
....
3558
3559
3560
3561
3562
3563
3564

3565
3566
3567
3568
3569
3570
3571
....
3583
3584
3585
3586
3587
3588
3589

3590
3591
3592
3593
3594
3595
3596
3597
3598
3599
3600
3601
....
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
3616
3617
3618
3619
....
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631

3632
3633
3634
3635
3636
3637
3638
3639
3640
3641
3642
3643
3644

3645
3646
3647
3648
3649
3650
3651
3652
3653
3654
3655

3656
3657
3658
3659
3660
3661
3662
**
** 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.291 2004/05/14 15:27:29 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  assert( &pTos[1-cnt] >= p->aStack );
  for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
  if( i>=cnt ) pc = pOp->p2-1;
  if( pOp->p1>0 ) popStack(&pTos, cnt);
  break;
}

/* Opcode: Column3 P1 P2 *
**
** This opcode (not yet in use) is a replacement for the current OP_Column3
** that supports the SQLite3 manifest typing feature.
**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.) Push onto the stack the value
** of the P2-th column contained in the data.
**
** If the KeyAsData opcode has previously executed on this cursor, then the
................................................................................
  Cursor *pC;
  char *zRec;        /* Pointer to record-data from stack or pseudo-table. */
  BtCursor *pCrsr;

  char *zData;       
  int freeZdata = 0; /* zData requires sqliteFree() */

  u64 nFields;       /* number of fields in the record */
  u64 *aTypes;       /* An array of serial types (size nFields) */

  int len;           /* The length of the serialized data for the column */
  int offset;
  int nn;

  assert( i<p->nCursor );
  pTos++;
................................................................................
  ** from a real cursor, then zRec is left as NULL.
  */
  if( i<0 ){
    assert( &pTos[i]>=p->aStack );
    assert( pTos[i].flags & MEM_Str );
    zRec = pTos[i].z;
    payloadSize = pTos[i].n;

  }else if( (pC = &p->aCsr[i])->pCursor!=0 ){
    sqlite3VdbeCursorMoveto(pC);
    zRec = 0;
    pCrsr = pC->pCursor;
    if( pC->nullRow ){
      payloadSize = 0;


    }else if( pC->keyAsData ){
      i64 payloadSize64;
      sqlite3BtreeKeySize(pCrsr, &payloadSize64);
      payloadSize = payloadSize64;
    }else{
      sqlite3BtreeDataSize(pCrsr, &payloadSize);
    }
  }else if( pC->pseudoTable ){
    payloadSize = pC->nData;
    zRec = pC->pData;

    assert( payloadSize==0 || zRec!=0 );
  }else{
    payloadSize = 0;
  }

  /* If payloadSize is 0, then just push a NULL onto the stack. */
  if( payloadSize==0 ){
    pTos->flags = MEM_Null;
    break;
  }

  /* Read the number of fields for the record.
  ** FIX ME: The Cursor object should cache this data and the array of
  ** field types for subsequent OP_Column instructions.
  */


  if( zRec ){
    zData = zRec;
  }else{
    /* We can assume that 9 bytes (maximum length of a varint) fits
    ** on the main page in all cases.
    */


    if( pC->keyAsData ){
      zData = (char *)sqlite3BtreeKeyFetch(pCrsr, 9>payloadSize?payloadSize:9);
    }else{
      zData = (char *)sqlite3BtreeDataFetch(pCrsr, 9>payloadSize?payloadSize:9);
    }
    assert( zData );
  }
  offset = sqlite3GetVarint(zData, &nFields);









  if( !zRec ){
    /* If the record is stored in a table, see if enough of it is on
    ** the main page to use sqlite3BtreeDataFetch() to get the data
    ** containing the nFields serial types (varints). This will almost
    ** always work, but if it doesn't sqliteMalloc() space and use
    ** sqlite3BtreeData().
    **
    ** Estimate the maximum space required by the nFields varints by
    ** assuming the maximum space for each is the length required to store:
    **
    **     (<record length> * 2) + 13
    **
    ** This is the serial-type for a text object as long as the record
    ** itself. In all cases the length required to store this is three
    ** bytes or less. 
    */
    int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nFields;
    max_space += offset;
    if( max_space>payloadSize ){
      max_space = payloadSize;
    }

    if( pC->keyAsData ){
      zData = (char *)sqlite3BtreeKeyFetch(pCrsr, max_space);
    }else{
      zData = (char *)sqlite3BtreeDataFetch(pCrsr, max_space);
    }
    if( !zData ){
      /* This code will run very infrequently (e.g. tables with several
      ** hundred columns).
      */
      zData = (char *)sqliteMallocRaw(offset+max_space);
      if( !zData ){
        rc = SQLITE_NOMEM;
        goto abort_due_to_error;

      }
      if( pC->keyAsData ){
        rc = sqlite3BtreeKey(pCrsr, 0, max_space, zData);
      }else{
        rc = sqlite3BtreeData(pCrsr, 0, max_space, zData);
      }
      if( rc!=SQLITE_OK ){
        sqliteFree(zData);
        goto abort_due_to_error;
      }
      freeZdata = 1;
    }
  }

  /* Dynamically allocate space for the aTypes array. and read all
  ** the serial types for the record. At the end of this block variable
  ** offset is set to the offset to the start of Data0 in the record.
  */
  aTypes = (u64 *)sqliteMallocRaw(sizeof(u64)*nFields);
  if( !aTypes ){
    if( freeZdata ){
      sqliteFree(zData);
      freeZdata = 0;
    }
    rc = SQLITE_NOMEM;
    goto abort_due_to_error;
  }
  for(nn=0; nn<nFields; nn++){
    offset += sqlite3GetVarint(&zData[offset], &aTypes[nn]);
  }
 
  if( freeZdata ){
    freeZdata = 0;
    sqliteFree(zData);
  }








  for(nn=0; nn<p2; nn++){
    offset += sqlite3VdbeSerialTypeLen(aTypes[nn]);
  }
  len = sqlite3VdbeSerialTypeLen(aTypes[p2]);

  if( !zRec ){
    /* If the record is stored in a table, see if enough of it
    ** is on the main page to read our column using
    ** sqlite3BtreeDataFetch(). If not sqliteMalloc() space and read data
    ** with sqlite3BtreeData().
    */
    if( pC->keyAsData ){
      zData = (char *)sqlite3BtreeKeyFetch(pCrsr, offset+len);
    }else{
      zData = (char *)sqlite3BtreeDataFetch(pCrsr, offset+len);
    }
    if( !zData && len>0 ){
      zData = (char *)sqliteMallocRaw(len);
      if( !zData ){
        sqliteFree(aTypes);
        rc = SQLITE_NOMEM;
        goto abort_due_to_error;
      }
      if( pC->keyAsData ){
        rc = sqlite3BtreeKey(pCrsr, offset, len, zData);
      }else{
        rc = sqlite3BtreeData(pCrsr, offset, len, zData);
      }
      if( rc!=SQLITE_OK ){
        sqliteFree( aTypes );
        sqliteFree( zData );
        goto abort_due_to_error;
      }
      freeZdata = 1;
      offset = 0;
    }
  }

  /* Deserialize the value directly into the top of the stack */
  sqlite3VdbeSerialGet(&zData[offset], aTypes[p2], pTos);

  sqliteFree(aTypes);
  if( freeZdata ){
    sqliteFree(zData);
  }
  break;
}

/* Opcode MakeRecord P1 * P3
................................................................................
      }
      Stringify(pTos);
      sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
      pC->incrKey = 0;
      pC->recnoIsValid = 0;
    }
    pC->deferredMoveto = 0;

    pC->incrKey = 0;
    sqlite3_search_count++;
    oc = pOp->opcode;
    if( oc==OP_MoveTo && res<0 ){
      sqlite3BtreeNext(pC->pCursor, &res);
      pC->recnoIsValid = 0;
      if( res && pOp->p2>0 ){
................................................................................
  if( (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx;
    assert( pC->intKey==0 );
    Stringify(pTos);
    rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
    alreadyExists = rx==SQLITE_OK && res==0;
    pC->deferredMoveto = 0;

  }
  if( pOp->opcode==OP_Found ){
    if( alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !alreadyExists ) pc = pOp->p2 - 1;
  }
  if( pOp->opcode!=OP_Distinct ){
................................................................................
    assert( nKey >= 2 );
    len = nKey-2;
    while( zKey[len] && --len );

    /* Search for an entry in P1 where all but the last four bytes match K.
    ** If there is no such entry, jump immediately to P2.
    */
    assert( p->aCsr[i].deferredMoveto==0 );

    rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
    if( rc!=SQLITE_OK ) goto abort_due_to_error;
    if( res<0 ){
      rc = sqlite3BtreeNext(pCrsr, &res);
      if( res ){
        pc = pOp->p2 - 1;
        break;
................................................................................
** operation assumes the key is an integer and NotFound assumes it
** is a string.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {
  int i = pOp->p1;

  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int res, rx;
    u64 iKey;
    assert( pTos->flags & MEM_Int );
    assert( p->aCsr[i].intKey );
    iKey = intToKey(pTos->i);
    rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
    p->aCsr[i].lastRecno = pTos->i;
    p->aCsr[i].recnoIsValid = res==0;
    p->aCsr[i].nullRow = 0;

    if( rx!=SQLITE_OK || res!=0 ){
      pc = pOp->p2 - 1;
      p->aCsr[i].recnoIsValid = 0;
    }
  }
  Release(pTos);
  pTos--;
  break;
}

................................................................................
      if( rx==SQLITE_OK && res==0 ){
        rc = SQLITE_FULL;
        goto abort_due_to_error;
      }
    }
    pC->recnoIsValid = 0;
    pC->deferredMoveto = 0;

  }
  pTos++;
  pTos->i = v;
  pTos->flags = MEM_Int;
  break;
}

................................................................................
      }
      pC->nullRow = 0;
    }else{
      rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
    }
    pC->recnoIsValid = 0;
    pC->deferredMoveto = 0;

  }
  popStack(&pTos, 2);
  break;
}

/* Opcode: Delete P1 P2 *
**
................................................................................
  Cursor *pC;
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  if( pC->pCursor!=0 ){
    sqlite3VdbeCursorMoveto(pC);
    rc = sqlite3BtreeDelete(pC->pCursor);
    pC->nextRowidValid = 0;

  }
  if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
  if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
  break;
}

/* Opcode: SetCounts * * *
................................................................................
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  if( (pCrsr = pC->pCursor)!=0 ){
    int res;
    rc = sqlite3BtreeLast(pCrsr, &res);
    pC->nullRow = res;
    pC->deferredMoveto = 0;

    if( res && pOp->p2>0 ){
      pc = pOp->p2 - 1;
    }
  }else{
    pC->nullRow = 0;
  }
  break;
................................................................................

  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  if( (pCrsr = pC->pCursor)!=0 ){
    rc = sqlite3BtreeFirst(pCrsr, &res);
    pC->atFirst = res==0;
    pC->deferredMoveto = 0;

  }else{
    res = 1;
  }
  pC->nullRow = res;
  if( res && pOp->p2>0 ){
    pc = pOp->p2 - 1;
  }
................................................................................
    if( pC->nullRow ){
      res = 1;
    }else{
      assert( pC->deferredMoveto==0 );
      rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
                                  sqlite3BtreePrevious(pCrsr, &res);
      pC->nullRow = res;

    }
    if( res==0 ){
      pc = pOp->p2 - 1;
      sqlite3_search_count++;
    }
  }else{
    pC->nullRow = 1;
................................................................................
** If P2==1, then the key must be unique.  If the key is not unique,
** the program aborts with a SQLITE_CONSTRAINT error and the database
** is rolled back.  If P3 is not null, then it becomes part of the
** error message returned with the SQLITE_CONSTRAINT.
*/
case OP_IdxPut: {
  int i = pOp->p1;

  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  assert( pTos->flags & MEM_Str );
  if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int nKey = pTos->n;
    const char *zKey = pTos->z;
    if( pOp->p2 ){
      int res;
      int len;
      u64 n;
   
................................................................................

      rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
      if( rc!=SQLITE_OK ) goto abort_due_to_error;
      while( res!=0 ){
        int c;
        sqlite3BtreeKeySize(pCrsr, &n);
        if( n==nKey && 
            sqlite3VdbeIdxKeyCompare(&p->aCsr[i], len, zKey, 0, &c)==SQLITE_OK
            && c==0
        ){
          rc = SQLITE_CONSTRAINT;
          if( pOp->p3 && pOp->p3[0] ){
            sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
          }
          goto abort_due_to_error;
................................................................................
          sqlite3BtreeNext(pCrsr, &res);
          res = +1;
        }else{
          break;
        }
      }
    }
    assert( p->aCsr[i].intKey==0 );
    rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
    assert( p->aCsr[i].deferredMoveto==0 );

  }
  Release(pTos);
  pTos--;
  break;
}

/* Opcode: IdxDelete P1 * *
**
** The top of the stack is an index key built using the MakeIdxKey opcode.
** This opcode removes that entry from the index.
*/
case OP_IdxDelete: {
  int i = pOp->p1;

  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( pTos->flags & MEM_Str );
  assert( i>=0 && i<p->nCursor );
  if( (pCrsr = p->aCsr[i].pCursor)!=0 ){
    int rx, res;
    rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
    if( rx==SQLITE_OK && res==0 ){
      rc = sqlite3BtreeDelete(pCrsr);
    }
    assert( p->aCsr[i].deferredMoveto==0 );

  }
  Release(pTos);
  pTos--;
  break;
}

/* Opcode: IdxRecno P1 * *







|







 







|
<
<
<







 







|
<







 







>






>
>










>











<
|
|

>
>
|
|
|
|
|
|
>
>
|
|
|
|
|
|
|
|
>
>
>
>
>
|
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|

|
|
|
|
|
|
|
|
|
|
|
<
<
>
|
|
|
|
|
|
|
|
|
|
|
|
|

<
|
|
|
<
<
<
<
<
<
<
<
<
|
|
|
<
|
|
|
|
>
>
|
>
>
>
>
>

|

|












|


|
<
<







<









|

<







 







>







 







>







 







|
>







 







>



|






|
|
|
>


|







 







>







 







>







 







>







 







>







 







>







 







>







 







>




|







 







|







 







|

|
>













>




|





|
>







39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
....
1871
1872
1873
1874
1875
1876
1877
1878



1879
1880
1881
1882
1883
1884
1885
....
1898
1899
1900
1901
1902
1903
1904
1905

1906
1907
1908
1909
1910
1911
1912
....
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953

1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016


2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
2027
2028
2029
2030
2031

2032
2033
2034









2035
2036
2037

2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049
2050
2051
2052
2053
2054
2055
2056
2057
2058
2059
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069


2070
2071
2072
2073
2074
2075
2076

2077
2078
2079
2080
2081
2082
2083
2084
2085
2086
2087

2088
2089
2090
2091
2092
2093
2094
....
2820
2821
2822
2823
2824
2825
2826
2827
2828
2829
2830
2831
2832
2833
2834
....
2898
2899
2900
2901
2902
2903
2904
2905
2906
2907
2908
2909
2910
2911
2912
....
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
....
3026
3027
3028
3029
3030
3031
3032
3033
3034
3035
3036
3037
3038
3039
3040
3041
3042
3043
3044
3045
3046
3047
3048
3049
3050
3051
3052
3053
3054
3055
3056
3057
....
3151
3152
3153
3154
3155
3156
3157
3158
3159
3160
3161
3162
3163
3164
3165
....
3253
3254
3255
3256
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267
....
3283
3284
3285
3286
3287
3288
3289
3290
3291
3292
3293
3294
3295
3296
3297
....
3496
3497
3498
3499
3500
3501
3502
3503
3504
3505
3506
3507
3508
3509
3510
....
3526
3527
3528
3529
3530
3531
3532
3533
3534
3535
3536
3537
3538
3539
3540
....
3570
3571
3572
3573
3574
3575
3576
3577
3578
3579
3580
3581
3582
3583
3584
....
3596
3597
3598
3599
3600
3601
3602
3603
3604
3605
3606
3607
3608
3609
3610
3611
3612
3613
3614
3615
....
3619
3620
3621
3622
3623
3624
3625
3626
3627
3628
3629
3630
3631
3632
3633
....
3636
3637
3638
3639
3640
3641
3642
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
3669
3670
3671
3672
3673
3674
3675
3676
3677
3678
3679
**
** 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.292 2004/05/14 21:12:23 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
................................................................................
  assert( &pTos[1-cnt] >= p->aStack );
  for(i=0; i<cnt && (pTos[1+i-cnt].flags & MEM_Null)==0; i++){}
  if( i>=cnt ) pc = pOp->p2-1;
  if( pOp->p1>0 ) popStack(&pTos, cnt);
  break;
}

/* Opcode: Column P1 P2 *



**
** Interpret the data that cursor P1 points to as a structure built using
** the MakeRecord instruction.  (See the MakeRecord opcode for additional
** information about the format of the data.) Push onto the stack the value
** of the P2-th column contained in the data.
**
** If the KeyAsData opcode has previously executed on this cursor, then the
................................................................................
  Cursor *pC;
  char *zRec;        /* Pointer to record-data from stack or pseudo-table. */
  BtCursor *pCrsr;

  char *zData;       
  int freeZdata = 0; /* zData requires sqliteFree() */

  u64 nField;        /* number of fields in the record */


  int len;           /* The length of the serialized data for the column */
  int offset;
  int nn;

  assert( i<p->nCursor );
  pTos++;
................................................................................
  ** from a real cursor, then zRec is left as NULL.
  */
  if( i<0 ){
    assert( &pTos[i]>=p->aStack );
    assert( pTos[i].flags & MEM_Str );
    zRec = pTos[i].z;
    payloadSize = pTos[i].n;
    pC->cacheValid = 0;
  }else if( (pC = &p->aCsr[i])->pCursor!=0 ){
    sqlite3VdbeCursorMoveto(pC);
    zRec = 0;
    pCrsr = pC->pCursor;
    if( pC->nullRow ){
      payloadSize = 0;
    }else if( pC->cacheValid ){
      payloadSize = pC->payloadSize;
    }else if( pC->keyAsData ){
      i64 payloadSize64;
      sqlite3BtreeKeySize(pCrsr, &payloadSize64);
      payloadSize = payloadSize64;
    }else{
      sqlite3BtreeDataSize(pCrsr, &payloadSize);
    }
  }else if( pC->pseudoTable ){
    payloadSize = pC->nData;
    zRec = pC->pData;
    pC->cacheValid = 0;
    assert( payloadSize==0 || zRec!=0 );
  }else{
    payloadSize = 0;
  }

  /* If payloadSize is 0, then just push a NULL onto the stack. */
  if( payloadSize==0 ){
    pTos->flags = MEM_Null;
    break;
  }


  /* Read and parse the table header.  Store the results of the parse
  ** into the record header cache fields of the cursor.
  */
  if( !pC->cacheValid ){
    pC->payloadSize = payloadSize;
    if( zRec ){
      zData = zRec;
    }else{
      /* We can assume that 9 bytes (maximum length of a varint) fits
      ** on the main page in all cases.
      */
      int n = 9;
      if( payloadSize<9 ) n = payloadSize;
      if( pC->keyAsData ){
        zData = (char *)sqlite3BtreeKeyFetch(pCrsr, n);
      }else{
        zData = (char *)sqlite3BtreeDataFetch(pCrsr, n);
      }
      assert( zData );
    }
    offset = sqlite3GetVarint(zData, &nField);
    if( nField>pC->nField ){
      sqliteFree(pC->aType);
      pC->aType = sqliteMallocRaw( nField*sizeof(pC->aType[0]) );
      if( pC->aType==0 ){
        goto no_mem;
      }
    }
    pC->nField = nField;

    if( !zRec ){
      /* If the record is stored in a table, see if enough of it is on
      ** the main page to use sqlite3BtreeDataFetch() to get the data
      ** containing the nField serial types (varints). This will almost
      ** always work, but if it doesn't sqliteMalloc() space and use
      ** sqlite3BtreeData().
      **
      ** Estimate the maximum space required by the nField varints by
      ** assuming the maximum space for each is the length required to store:
      **
      **     (<record length> * 2) + 13
      **
      ** This is the serial-type for a text object as long as the record
      ** itself. In all cases the length required to store this is three
      ** bytes or less. 
      */
      int max_space = sqlite3VarintLen((((u64)payloadSize)<<1)+13)*nField;
      max_space += offset;
      if( max_space>payloadSize ){
        max_space = payloadSize;
      }

      if( pC->keyAsData ){
        zData = (char *)sqlite3BtreeKeyFetch(pCrsr, max_space);
      }else{
        zData = (char *)sqlite3BtreeDataFetch(pCrsr, max_space);
      }
      if( !zData ){
        /* This code will run very infrequently (e.g. tables with several
        ** hundred columns).
        */
        zData = (char *)sqliteMallocRaw(max_space);
        if( !zData ){


          goto no_mem;
        }
        if( pC->keyAsData ){
          rc = sqlite3BtreeKey(pCrsr, 0, max_space, zData);
        }else{
          rc = sqlite3BtreeData(pCrsr, 0, max_space, zData);
        }
        if( rc!=SQLITE_OK ){
          sqliteFree(zData);
          goto abort_due_to_error;
        }
        freeZdata = 1;
      }
    }


    /* Read all the serial types for the record.  At the end of this block
    ** variable offset is set to the offset to the start of Data0 in the record.
    */









    for(nn=0; nn<nField; nn++){
      offset += sqlite3GetVarint(&zData[offset], &pC->aType[nn]);
    }

    if( freeZdata ){
      freeZdata = 0;
      sqliteFree(zData);
    }
    pC->nHeader = offset;
    pC->cacheValid = 1;
  }

  /* Compute the offset from the beginning of the record to the beginning
  ** of the data.  And get the length of the data.
  */
  offset = pC->nHeader;
  for(nn=0; nn<p2; nn++){
    offset += sqlite3VdbeSerialTypeLen(pC->aType[nn]);
  }
  len = sqlite3VdbeSerialTypeLen(pC->aType[p2]);

  if( !zRec ){
    /* If the record is stored in a table, see if enough of it
    ** is on the main page to read our column using
    ** sqlite3BtreeDataFetch(). If not sqliteMalloc() space and read data
    ** with sqlite3BtreeData().
    */
    if( pC->keyAsData ){
      zData = (char *)sqlite3BtreeKeyFetch(pCrsr, offset+len);
    }else{
      zData = (char *)sqlite3BtreeDataFetch(pCrsr, offset+len);
    }
    if( !zData ){
      zData = (char *)sqliteMallocRaw(len);
      if( !zData ){
        goto no_mem;


      }
      if( pC->keyAsData ){
        rc = sqlite3BtreeKey(pCrsr, offset, len, zData);
      }else{
        rc = sqlite3BtreeData(pCrsr, offset, len, zData);
      }
      if( rc!=SQLITE_OK ){

        sqliteFree( zData );
        goto abort_due_to_error;
      }
      freeZdata = 1;
      offset = 0;
    }
  }

  /* Deserialize the value directly into the top of the stack */
  sqlite3VdbeSerialGet(&zData[offset], pC->aType[p2], pTos);


  if( freeZdata ){
    sqliteFree(zData);
  }
  break;
}

/* Opcode MakeRecord P1 * P3
................................................................................
      }
      Stringify(pTos);
      sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
      pC->incrKey = 0;
      pC->recnoIsValid = 0;
    }
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
    pC->incrKey = 0;
    sqlite3_search_count++;
    oc = pOp->opcode;
    if( oc==OP_MoveTo && res<0 ){
      sqlite3BtreeNext(pC->pCursor, &res);
      pC->recnoIsValid = 0;
      if( res && pOp->p2>0 ){
................................................................................
  if( (pC = &p->aCsr[i])->pCursor!=0 ){
    int res, rx;
    assert( pC->intKey==0 );
    Stringify(pTos);
    rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, &res);
    alreadyExists = rx==SQLITE_OK && res==0;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
  }
  if( pOp->opcode==OP_Found ){
    if( alreadyExists ) pc = pOp->p2 - 1;
  }else{
    if( !alreadyExists ) pc = pOp->p2 - 1;
  }
  if( pOp->opcode!=OP_Distinct ){
................................................................................
    assert( nKey >= 2 );
    len = nKey-2;
    while( zKey[len] && --len );

    /* Search for an entry in P1 where all but the last four bytes match K.
    ** If there is no such entry, jump immediately to P2.
    */
    assert( pCx->deferredMoveto==0 );
    pCx->cacheValid = 0;
    rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
    if( rc!=SQLITE_OK ) goto abort_due_to_error;
    if( res<0 ){
      rc = sqlite3BtreeNext(pCrsr, &res);
      if( res ){
        pc = pOp->p2 - 1;
        break;
................................................................................
** operation assumes the key is an integer and NotFound assumes it
** is a string.
**
** See also: Distinct, Found, MoveTo, NotFound, IsUnique
*/
case OP_NotExists: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
    int res, rx;
    u64 iKey;
    assert( pTos->flags & MEM_Int );
    assert( p->aCsr[i].intKey );
    iKey = intToKey(pTos->i);
    rx = sqlite3BtreeMoveto(pCrsr, 0, iKey, &res);
    pC->lastRecno = pTos->i;
    pC->recnoIsValid = res==0;
    pC->nullRow = 0;
    pC->cacheValid = 0;
    if( rx!=SQLITE_OK || res!=0 ){
      pc = pOp->p2 - 1;
      pC->recnoIsValid = 0;
    }
  }
  Release(pTos);
  pTos--;
  break;
}

................................................................................
      if( rx==SQLITE_OK && res==0 ){
        rc = SQLITE_FULL;
        goto abort_due_to_error;
      }
    }
    pC->recnoIsValid = 0;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
  }
  pTos++;
  pTos->i = v;
  pTos->flags = MEM_Int;
  break;
}

................................................................................
      }
      pC->nullRow = 0;
    }else{
      rc = sqlite3BtreeInsert(pC->pCursor, zKey, nKey, pTos->z, pTos->n);
    }
    pC->recnoIsValid = 0;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
  }
  popStack(&pTos, 2);
  break;
}

/* Opcode: Delete P1 P2 *
**
................................................................................
  Cursor *pC;
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  if( pC->pCursor!=0 ){
    sqlite3VdbeCursorMoveto(pC);
    rc = sqlite3BtreeDelete(pC->pCursor);
    pC->nextRowidValid = 0;
    pC->cacheValid = 0;
  }
  if( pOp->p2 & OPFLAG_NCHANGE ) db->nChange++;
  if( pOp->p2 & OPFLAG_CSCHANGE ) db->csChange++;
  break;
}

/* Opcode: SetCounts * * *
................................................................................
  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  if( (pCrsr = pC->pCursor)!=0 ){
    int res;
    rc = sqlite3BtreeLast(pCrsr, &res);
    pC->nullRow = res;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
    if( res && pOp->p2>0 ){
      pc = pOp->p2 - 1;
    }
  }else{
    pC->nullRow = 0;
  }
  break;
................................................................................

  assert( i>=0 && i<p->nCursor );
  pC = &p->aCsr[i];
  if( (pCrsr = pC->pCursor)!=0 ){
    rc = sqlite3BtreeFirst(pCrsr, &res);
    pC->atFirst = res==0;
    pC->deferredMoveto = 0;
    pC->cacheValid = 0;
  }else{
    res = 1;
  }
  pC->nullRow = res;
  if( res && pOp->p2>0 ){
    pc = pOp->p2 - 1;
  }
................................................................................
    if( pC->nullRow ){
      res = 1;
    }else{
      assert( pC->deferredMoveto==0 );
      rc = pOp->opcode==OP_Next ? sqlite3BtreeNext(pCrsr, &res) :
                                  sqlite3BtreePrevious(pCrsr, &res);
      pC->nullRow = res;
      pC->cacheValid = 0;
    }
    if( res==0 ){
      pc = pOp->p2 - 1;
      sqlite3_search_count++;
    }
  }else{
    pC->nullRow = 1;
................................................................................
** If P2==1, then the key must be unique.  If the key is not unique,
** the program aborts with a SQLITE_CONSTRAINT error and the database
** is rolled back.  If P3 is not null, then it becomes part of the
** error message returned with the SQLITE_CONSTRAINT.
*/
case OP_IdxPut: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( i>=0 && i<p->nCursor );
  assert( pTos->flags & MEM_Str );
  if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
    int nKey = pTos->n;
    const char *zKey = pTos->z;
    if( pOp->p2 ){
      int res;
      int len;
      u64 n;
   
................................................................................

      rc = sqlite3BtreeMoveto(pCrsr, zKey, len, &res);
      if( rc!=SQLITE_OK ) goto abort_due_to_error;
      while( res!=0 ){
        int c;
        sqlite3BtreeKeySize(pCrsr, &n);
        if( n==nKey && 
            sqlite3VdbeIdxKeyCompare(pC, len, zKey, 0, &c)==SQLITE_OK
            && c==0
        ){
          rc = SQLITE_CONSTRAINT;
          if( pOp->p3 && pOp->p3[0] ){
            sqlite3SetString(&p->zErrMsg, pOp->p3, (char*)0);
          }
          goto abort_due_to_error;
................................................................................
          sqlite3BtreeNext(pCrsr, &res);
          res = +1;
        }else{
          break;
        }
      }
    }
    assert( pC->intKey==0 );
    rc = sqlite3BtreeInsert(pCrsr, zKey, nKey, "", 0);
    assert( pC->deferredMoveto==0 );
    pC->cacheValid = 0;
  }
  Release(pTos);
  pTos--;
  break;
}

/* Opcode: IdxDelete P1 * *
**
** The top of the stack is an index key built using the MakeIdxKey opcode.
** This opcode removes that entry from the index.
*/
case OP_IdxDelete: {
  int i = pOp->p1;
  Cursor *pC;
  BtCursor *pCrsr;
  assert( pTos>=p->aStack );
  assert( pTos->flags & MEM_Str );
  assert( i>=0 && i<p->nCursor );
  if( (pCrsr = (pC = &p->aCsr[i])->pCursor)!=0 ){
    int rx, res;
    rx = sqlite3BtreeMoveto(pCrsr, pTos->z, pTos->n, &res);
    if( rx==SQLITE_OK && res==0 ){
      rc = sqlite3BtreeDelete(pCrsr);
    }
    assert( pC->deferredMoveto==0 );
    pC->cacheValid = 0;
  }
  Release(pTos);
  pTos--;
  break;
}

/* Opcode: IdxRecno P1 * *

Changes to src/vdbeInt.h.

74
75
76
77
78
79
80








81
82
83
84
85
86
87
  Bool zeroData;        /* True if table contains keys only - no data */
  Bool incrKey;         /* Searches on the table simulate OP_IncrKey */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  Btree *pBt;           /* Separate file holding temporary table */
  int nData;            /* Number of bytes in pData */
  char *pData;          /* Data for a NEW or OLD pseudo-table */
  i64 iKey;             /* Key for the NEW or OLD pseudo-table row */








};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
*/







>
>
>
>
>
>
>
>







74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
  Bool zeroData;        /* True if table contains keys only - no data */
  Bool incrKey;         /* Searches on the table simulate OP_IncrKey */
  i64 movetoTarget;     /* Argument to the deferred sqlite3BtreeMoveto() */
  Btree *pBt;           /* Separate file holding temporary table */
  int nData;            /* Number of bytes in pData */
  char *pData;          /* Data for a NEW or OLD pseudo-table */
  i64 iKey;             /* Key for the NEW or OLD pseudo-table row */

  /* Cached information about the header for the data record that the
  ** cursor is currently pointing to */
  Bool cacheValid;      /* True if the cache is valid */
  int nField;           /* Number of fields in the header */
  int nHeader;          /* Number of bytes in the entire header */
  int payloadSize;      /* Total number of bytes in the record */
  u64 *aType;           /* Type values for all entries in the record */
};
typedef struct Cursor Cursor;

/*
** A sorter builds a list of elements to be sorted.  Each element of
** the list is an instance of the following structure.
*/

Changes to src/vdbeaux.c.

731
732
733
734
735
736
737

738
739
740
741
742
743
744
....
1058
1059
1060
1061
1062
1063
1064

1065
1066
1067
1068
1069
1070
1071
  if( pCx->pCursor ){
    sqlite3BtreeCloseCursor(pCx->pCursor);
  }
  if( pCx->pBt ){
    sqlite3BtreeClose(pCx->pBt);
  }
  sqliteFree(pCx->pData);

  memset(pCx, 0, sizeof(Cursor));
}

/*
** Close all cursors
*/
static void closeAllCursors(Vdbe *p){
................................................................................
    p->lastRecno = keyToInt(p->movetoTarget);
    p->recnoIsValid = res==0;
    if( res<0 ){
      sqlite3BtreeNext(p->pCursor, &res);
    }
    sqlite3_search_count++;
    p->deferredMoveto = 0;

  }
  return SQLITE_OK;
}

/*
** FIX ME
**







>







 







>







731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
....
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
  if( pCx->pCursor ){
    sqlite3BtreeCloseCursor(pCx->pCursor);
  }
  if( pCx->pBt ){
    sqlite3BtreeClose(pCx->pBt);
  }
  sqliteFree(pCx->pData);
  sqliteFree(pCx->aType);
  memset(pCx, 0, sizeof(Cursor));
}

/*
** Close all cursors
*/
static void closeAllCursors(Vdbe *p){
................................................................................
    p->lastRecno = keyToInt(p->movetoTarget);
    p->recnoIsValid = res==0;
    if( res<0 ){
      sqlite3BtreeNext(p->pCursor, &res);
    }
    sqlite3_search_count++;
    p->deferredMoveto = 0;
    p->cacheValid = 0;
  }
  return SQLITE_OK;
}

/*
** FIX ME
**

Changes to test/limit.test.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
86
87
88
89
90
91
92

93
94
95
96
97
98
99
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.11 2004/03/08 13:26:18 drh Exp $

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

# Build some test data
#
set fd [open data1.txt w]
................................................................................
do_test limit-3.1 {
  execsql {
    SELECT z FROM (SELECT y*10+x AS z FROM t1 ORDER BY x LIMIT 10)
    ORDER BY z LIMIT 5;
  }
} {50 51 52 53 54}


do_test limit-4.1 {
  execsql {
    BEGIN;
    CREATE TABLE t3(x);
    INSERT INTO t3 SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;







|







 







>







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
..
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this file is testing the LIMIT ... OFFSET ... clause
#  of SELECT statements.
#
# $Id: limit.test,v 1.12 2004/05/14 21:12:24 drh Exp $

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

# Build some test data
#
set fd [open data1.txt w]
................................................................................
do_test limit-3.1 {
  execsql {
    SELECT z FROM (SELECT y*10+x AS z FROM t1 ORDER BY x LIMIT 10)
    ORDER BY z LIMIT 5;
  }
} {50 51 52 53 54}

btree_breakpoint
do_test limit-4.1 {
  execsql {
    BEGIN;
    CREATE TABLE t3(x);
    INSERT INTO t3 SELECT x FROM t1 ORDER BY x LIMIT 10 OFFSET 1;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;
    INSERT INTO t3 SELECT x+(SELECT max(x) FROM t3) FROM t3;