/ Check-in [a675ac49]
Login

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

Overview
Comment:Updates to sqlite3BtreeKeyFetch() and sqlite3BtreeDataFetch(). (CVS 1347)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:a675ac49882887dfcbf671e9092a29aca9eb694e
User & Date: drh 2004-05-11 00:58:56
Context
2004-05-11
01:18
Update the main.mk makefile so that it builds everything again. (CVS 1348) check-in: e6e52fc2 user: drh tags: trunk
00:58
Updates to sqlite3BtreeKeyFetch() and sqlite3BtreeDataFetch(). (CVS 1347) check-in: a675ac49 user: drh tags: trunk
00:28
Change to OP_PutIntKey to use new btree API. (CVS 1346) check-in: c080fed7 user: danielk1977 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
....
1411
1412
1413
1414
1415
1416
1417



































1418
1419
1420
1421
1422
1423
1424
....
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
1564
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
....
1635
1636
1637
1638
1639
1640
1641































































































1642
1643
1644
1645
1646
1647
1648
....
1903
1904
1905
1906
1907
1908
1909
1910
1911
1912
1913
1914
1915
1916
1917
1918
1919
1920
1921
1922
1923
1924
1925
1926
1927
1928
1929
1930
1931
1932
** 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.124 2004/05/10 23:29:49 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.
................................................................................
    if( !pPage->zeroData ){
      while( (0x80&*(cell++))!=0 ){}  /* Skip the data size number */
    }
    getVarint(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
** a total of "amt" bytes.  Put the result in zBuf.
**
** This routine does not make a distinction between key and data.
................................................................................
  }
  assert( pCur->pPage!=0 );
  assert( pCur->pPage->intKey==0 );
  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
  return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}

/*
** Return a pointer to the key of record that cursor pCur
** is point to if the entire key is in contiguous memory.
** If the key is split up among multiple tables, return 0.
** If pCur is not pointing to a valid entry return 0.
**
** The pointer returned is ephemeral.  The key may move
** or be destroyed on the next call to any Btree routine.
**
** This routine is used to do quick key comparisons in the
** common case where the entire key fits in the payload area
** of a cell and does not overflow onto secondary pages.  If
** this routine returns 0 for a valid cursor, the caller will
** need to allocate a buffer big enough to hold the whole key
** then use sqlite3BtreeKey() to copy the key value into the
** buffer.  That is substantially slower.  But fortunately,
** most keys are small enough to fit in the payload area so
** the slower method is rarely needed.
*/
void *sqlite3BtreeKeyFetch(BtCursor *pCur){
  unsigned char *aPayload;
  MemPage *pPage;
  Btree *pBt;
  u64 nData, nKey;

  assert( pCur!=0 );
  if( !pCur->isValid ){
    return 0;
  }
  assert( pCur->pPage!=0 );
  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
  pBt = pCur->pBt;
  pPage = pCur->pPage;
  pageIntegrity(pPage);
  assert( pCur->idx>=0 && pCur->idx<pPage->nCell );
  assert( pPage->intKey==0 );
  aPayload = pPage->aCell[pCur->idx];
  aPayload += 2;  /* Skip the next cell index */
  if( !pPage->leaf ){
    aPayload += 4;  /* Skip the child pointer */
  }
  if( !pPage->zeroData ){
    aPayload += getVarint(aPayload, &nData);
  }
  aPayload += getVarint(aPayload, &nKey);
  if( nKey>pBt->maxLocal ){
    return 0;
  }
  return aPayload;
}


/*
** 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;
  u64 size;

  if( !pCur->isValid ){
    return pCur->status ? pCur->status : SQLITE_INTERNAL;
  }
  pPage = pCur->pPage;
  assert( pPage!=0 );
  assert( pPage->isInit );
  pageIntegrity(pPage);
  if( pPage->zeroData ){
    *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 */
    }
    getVarint(cell, &size);
    assert( (size & 0x00000000ffffffff)==size );
    *pSize = (u32)size;
  }
  return SQLITE_OK;
}

/*
** Read part of the data associated with cursor pCur.  Exactly
** "amt" bytes will be transfered into pBuf[].  The transfer
** begins at "offset".
**
** Return SQLITE_OK on success or an error code if anything goes
** wrong.  An error is returned if "offset+amt" is larger than
................................................................................
  }
  assert( amt>=0 );
  assert( offset>=0 );
  assert( pCur->pPage!=0 );
  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
  return getPayload(pCur, offset, amt, pBuf, 1);
}
































































































/*
** Move the cursor down to a new child page.  The newPgno argument is the
** page number of the child page in the byte order of the disk image.
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
  int rc;
................................................................................
    Pgno chldPg;
    MemPage *pPage = pCur->pPage;
    int c = -1;  /* pRes return if table is empty must be -1 */
    lwr = 0;
    upr = pPage->nCell-1;
    pageIntegrity(pPage);
    while( lwr<=upr ){
      void *pCellKey;
      u64 nCellKey;
      pCur->idx = (lwr+upr)/2;
      sqlite3BtreeKeySize(pCur, &nCellKey);
      if( pPage->intKey ){
        if( nCellKey<nKey ){
          c = -1;
        }else if( nCellKey>nKey ){
          c = +1;
        }else{
          c = 0;
        }
      }else if( (pCellKey = sqlite3BtreeKeyFetch(pCur))!=0 ){
        c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
      }else{
        pCellKey = sqliteMalloc( nCellKey );
        if( pCellKey==0 ) return SQLITE_NOMEM;
        rc = sqlite3BtreeKey(pCur, 0, nCellKey, pCellKey);
        c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
        sqliteFree(pCellKey);
        if( rc ) return rc;
      }
      if( c==0 ){







|







 







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







 







<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<







 







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







 







|











|


|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
....
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
....
1564
1565
1566
1567
1568
1569
1570























































































1571
1572
1573
1574
1575
1576
1577
....
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
1596
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
1631
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684
1685
1686
1687
1688
1689
1690
1691
....
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
** 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.125 2004/05/11 00:58:56 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.
................................................................................
    if( !pPage->zeroData ){
      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;
  u64 size;

  if( !pCur->isValid ){
    return pCur->status ? pCur->status : SQLITE_INTERNAL;
  }
  pPage = pCur->pPage;
  assert( pPage!=0 );
  assert( pPage->isInit );
  pageIntegrity(pPage);
  if( pPage->zeroData ){
    *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 */
    }
    getVarint(cell, &size);
    assert( (size & 0x00000000ffffffff)==size );
    *pSize = (u32)size;
  }
  return SQLITE_OK;
}

/*
** Read payload information from the entry that the pCur cursor is
** pointing to.  Begin reading the payload at "offset" and read
** a total of "amt" bytes.  Put the result in zBuf.
**
** This routine does not make a distinction between key and data.
................................................................................
  }
  assert( pCur->pPage!=0 );
  assert( pCur->pPage->intKey==0 );
  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
  return getPayload(pCur, offset, amt, (unsigned char*)pBuf, 0);
}
























































































/*
** Read part of the data associated with cursor pCur.  Exactly
** "amt" bytes will be transfered into pBuf[].  The transfer
** begins at "offset".
**
** Return SQLITE_OK on success or an error code if anything goes
** wrong.  An error is returned if "offset+amt" is larger than
................................................................................
  }
  assert( amt>=0 );
  assert( offset>=0 );
  assert( pCur->pPage!=0 );
  assert( pCur->idx>=0 && pCur->idx<pCur->pPage->nCell );
  return getPayload(pCur, offset, amt, pBuf, 1);
}

/*
** Return a pointer to payload information from the entry that the 
** pCur cursor is pointing to.  The pointer is to the beginning of
** the key if skipKey==0 and it points to the beginning of data if
** skipKey==1.
**
** At least amt bytes of information must be available on the local
** page or else this routine returns NULL.  If amt<0 then the entire
** key/data must be available.
**
** This routine is an optimization.  It is common for the entire key
** and data to fit on the local page and for there to be no overflow
** pages.  When that is so, this routine can be used to access the
** key and data without making a copy.  If the key and/or data spills
** onto overflow pages, then getPayload() must be used to reassembly
** the key/data and copy it into a preallocated buffer.
**
** The pointer returned by this routine looks directly into the cached
** page of the database.  The data might change or move the next time
** any btree routine is called.
*/
static const unsigned char *fetchPayload(
  BtCursor *pCur,      /* Cursor pointing to entry to read from */
  int amt,             /* Amount requested */
  int skipKey          /* read beginning at data if this is true */
){
  unsigned char *aPayload;
  MemPage *pPage;
  Btree *pBt;
  u64 nData, nKey;
  int maxLocal;

  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];
  aPayload += 2;  /* Skip the next cell index */
  if( !pPage->leaf ){
    aPayload += 4;  /* Skip the child pointer */
  }
  if( pPage->zeroData ){
    nData = 0;
  }else{
    aPayload += getVarint(aPayload, &nData);
  }
  aPayload += getVarint(aPayload, &nKey);
  if( pPage->intKey ){
    nKey = 0;
  }
  maxLocal = pBt->maxLocal;
  if( skipKey ){
    aPayload += nKey;
    maxLocal -= nKey;
    if( amt<0 ) amt = nData;
    assert( amt<=nData );
  }else{
    if( amt<0 ) amt = nKey;
    assert( amt<=nKey );
  }
  if( amt>maxLocal ){
    return 0;  /* If any of the data is not local, return nothing */
  }
  return aPayload;
}


/*
** Return a pointer to the first amt bytes of the key or data
** for record that cursor pCur is point to if the entire request
** exists in contiguous memory on the main tree page.  If any
** any part of the request is on an overflow page, return 0.
** If pCur is not pointing to a valid entry return 0.
**
** If amt<0 then return the entire key or data.
**
** The pointer returned is ephemeral.  The key/data may move
** or be destroyed on the next call to any Btree routine.
**
** These routines is used to get quick access to key and data
** in the common case where no overflow pages are used.
**
** It is a fatal error to call these routines with amt values that
** are larger than the key/data size.
*/
const void *sqlite3BtreeKeyFetch(BtCursor *pCur, int amt){
  return (const void*)fetchPayload(pCur, amt, 0);
}
const void *sqlite3BtreeDataFetch(BtCursor *pCur, int amt){
  return (const void*)fetchPayload(pCur, amt, 1);
}


/*
** Move the cursor down to a new child page.  The newPgno argument is the
** page number of the child page in the byte order of the disk image.
*/
static int moveToChild(BtCursor *pCur, u32 newPgno){
  int rc;
................................................................................
    Pgno chldPg;
    MemPage *pPage = pCur->pPage;
    int c = -1;  /* pRes return if table is empty must be -1 */
    lwr = 0;
    upr = pPage->nCell-1;
    pageIntegrity(pPage);
    while( lwr<=upr ){
      const void *pCellKey;
      u64 nCellKey;
      pCur->idx = (lwr+upr)/2;
      sqlite3BtreeKeySize(pCur, &nCellKey);
      if( pPage->intKey ){
        if( nCellKey<nKey ){
          c = -1;
        }else if( nCellKey>nKey ){
          c = +1;
        }else{
          c = 0;
        }
      }else if( (pCellKey = sqlite3BtreeKeyFetch(pCur, nCellKey))!=0 ){
        c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
      }else{
        u8 *pCellKey = sqliteMalloc( nCellKey );
        if( pCellKey==0 ) return SQLITE_NOMEM;
        rc = sqlite3BtreeKey(pCur, 0, nCellKey, pCellKey);
        c = pCur->xCompare(pCur->pArg, nCellKey, pCellKey, nKey, pKey);
        sqliteFree(pCellKey);
        if( rc ) return rc;
      }
      if( c==0 ){

Changes to src/btree.h.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
81
82
83
84
85
86
87
88

89
90
91
92
93
94
95
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite B-Tree file
** subsystem.  See comments in the source code for a detailed description
** of what each interface routine does.
**
** @(#) $Id: btree.h,v 1.44 2004/05/10 23:29:50 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_

/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
................................................................................
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreeFlags(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, u64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
void *sqlite3BtreeKeyFetch(BtCursor*);

int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);

char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot);
struct Pager *sqlite3BtreePager(Btree*);









|







 







|
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
..
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
**    May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the interface that the sqlite B-Tree file
** subsystem.  See comments in the source code for a detailed description
** of what each interface routine does.
**
** @(#) $Id: btree.h,v 1.45 2004/05/11 00:58:56 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_

/* TODO: This definition is just included so other modules compile. It
** needs to be revisited.
*/
................................................................................
int sqlite3BtreeLast(BtCursor*, int *pRes);
int sqlite3BtreeNext(BtCursor*, int *pRes);
int sqlite3BtreeEof(BtCursor*);
int sqlite3BtreeFlags(BtCursor*);
int sqlite3BtreePrevious(BtCursor*, int *pRes);
int sqlite3BtreeKeySize(BtCursor*, u64 *pSize);
int sqlite3BtreeKey(BtCursor*, u32 offset, u32 amt, void*);
const void *sqlite3BtreeKeyFetch(BtCursor*, int amt);
const void *sqlite3BtreeDataFetch(BtCursor*, int amt);
int sqlite3BtreeDataSize(BtCursor*, u32 *pSize);
int sqlite3BtreeData(BtCursor*, u32 offset, u32 amt, void*);

char *sqlite3BtreeIntegrityCheck(Btree*, int *aRoot, int nRoot);
struct Pager *sqlite3BtreePager(Btree*);


Changes to src/test3.c.

9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
859
860
861
862
863
864
865
866

867
868
869
870
871
872
873
...
958
959
960
961
962
963
964










































































965
966
967
968
969
970
971
....
1092
1093
1094
1095
1096
1097
1098


1099
1100
1101
1102
1103
1104
1105
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.34 2004/05/10 16:18:48 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "btree.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

/*
** Usage:   btree_keysize ID
**
** Return the number of bytes of key.  

*/
static int btree_keysize(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
................................................................................
    return TCL_ERROR;
  }
  zBuf[n] = 0;
  Tcl_AppendResult(interp, zBuf, 0);
  free(zBuf);
  return SQLITE_OK;
}











































































/*
** Usage:   btree_payload_size ID
**
** Return the number of bytes of payload
*/
static int btree_payload_size(
................................................................................
     { "btree_insert",             (Tcl_CmdProc*)btree_insert             },
     { "btree_next",               (Tcl_CmdProc*)btree_next               },
     { "btree_prev",               (Tcl_CmdProc*)btree_prev               },
     { "btree_eof",                (Tcl_CmdProc*)btree_eof                },
     { "btree_keysize",            (Tcl_CmdProc*)btree_keysize            },
     { "btree_key",                (Tcl_CmdProc*)btree_key                },
     { "btree_data",               (Tcl_CmdProc*)btree_data               },


     { "btree_payload_size",       (Tcl_CmdProc*)btree_payload_size       },
     { "btree_first",              (Tcl_CmdProc*)btree_first              },
     { "btree_last",               (Tcl_CmdProc*)btree_last               },
     { "btree_cursor_info",        (Tcl_CmdProc*)btree_cursor_info        },
     { "btree_cursor_list",        (Tcl_CmdProc*)btree_cursor_list        },
     { "btree_integrity_check",    (Tcl_CmdProc*)btree_integrity_check    },
     { "btree_breakpoint",         (Tcl_CmdProc*)btree_breakpoint         },







|







 







|
>







 







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







 







>
>







9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
...
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
....
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
**    May you share freely, never taking more than you give.
**
*************************************************************************
** Code for testing the btree.c module in SQLite.  This code
** is not included in the SQLite library.  It is used for automated
** testing of the SQLite library.
**
** $Id: test3.c,v 1.35 2004/05/11 00:58:56 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
#include "btree.h"
#include "tcl.h"
#include <stdlib.h>
#include <string.h>
................................................................................
  Tcl_AppendResult(interp, zBuf, 0);
  return SQLITE_OK;
}

/*
** Usage:   btree_keysize ID
**
** Return the number of bytes of key.  For an INTKEY table, this
** returns the key itself.
*/
static int btree_keysize(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
................................................................................
    return TCL_ERROR;
  }
  zBuf[n] = 0;
  Tcl_AppendResult(interp, zBuf, 0);
  free(zBuf);
  return SQLITE_OK;
}

/*
** Usage:   btree_fetch_key ID AMT
**
** Use the sqlite3BtreeKeyFetch() routine to get AMT bytes of the key.
** If sqlite3BtreeKeyFetch() fails, return an empty string.
*/
static int btree_fetch_key(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
  BtCursor *pCur;
  int n;
  u64 nKey;
  const char *zBuf;
  char zStatic[1000];

  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID AMT\"", 0);
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
  sqlite3BtreeKeySize(pCur, &nKey);
  zBuf = sqlite3BtreeKeyFetch(pCur, n);
  if( zBuf ){
    assert( nKey<sizeof(zStatic) );
    if( n>0 ) nKey = n;
    memcpy(zStatic, zBuf, (int)nKey); 
    zStatic[nKey] = 0;
    Tcl_AppendResult(interp, zStatic, 0);
  }
  return TCL_OK;
}

/*
** Usage:   btree_fetch_data ID AMT
**
** Use the sqlite3BtreeDataFetch() routine to get AMT bytes of the key.
** If sqlite3BtreeDataFetch() fails, return an empty string.
*/
static int btree_fetch_data(
  void *NotUsed,
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int argc,              /* Number of arguments */
  const char **argv      /* Text of each argument */
){
  BtCursor *pCur;
  int n;
  u32 nData;
  const char *zBuf;
  char zStatic[1000];

  if( argc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
       " ID AMT \"", 0);
    return TCL_ERROR;
  }
  if( Tcl_GetInt(interp, argv[1], (int*)&pCur) ) return TCL_ERROR;
  if( Tcl_GetInt(interp, argv[2], &n) ) return TCL_ERROR;
  sqlite3BtreeDataSize(pCur, &nData);
  zBuf = sqlite3BtreeDataFetch(pCur, n);
  if( zBuf ){
    assert( nData<sizeof(zStatic) );
    if( n>0 ) nData = n;
    memcpy(zStatic, zBuf, (int)nData); 
    zStatic[nData] = 0;
    Tcl_AppendResult(interp, zStatic, 0);
  }
  return TCL_OK;
}

/*
** Usage:   btree_payload_size ID
**
** Return the number of bytes of payload
*/
static int btree_payload_size(
................................................................................
     { "btree_insert",             (Tcl_CmdProc*)btree_insert             },
     { "btree_next",               (Tcl_CmdProc*)btree_next               },
     { "btree_prev",               (Tcl_CmdProc*)btree_prev               },
     { "btree_eof",                (Tcl_CmdProc*)btree_eof                },
     { "btree_keysize",            (Tcl_CmdProc*)btree_keysize            },
     { "btree_key",                (Tcl_CmdProc*)btree_key                },
     { "btree_data",               (Tcl_CmdProc*)btree_data               },
     { "btree_fetch_key",          (Tcl_CmdProc*)btree_fetch_key          },
     { "btree_fetch_data",         (Tcl_CmdProc*)btree_fetch_data         },
     { "btree_payload_size",       (Tcl_CmdProc*)btree_payload_size       },
     { "btree_first",              (Tcl_CmdProc*)btree_first              },
     { "btree_last",               (Tcl_CmdProc*)btree_last               },
     { "btree_cursor_info",        (Tcl_CmdProc*)btree_cursor_info        },
     { "btree_cursor_list",        (Tcl_CmdProc*)btree_cursor_list        },
     { "btree_integrity_check",    (Tcl_CmdProc*)btree_integrity_check    },
     { "btree_breakpoint",         (Tcl_CmdProc*)btree_breakpoint         },

Changes to src/vdbeaux.c.

1069
1070
1071
1072
1073
1074
1075
1076

1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
....
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
int sqlite2BtreeKeyCompare(
  BtCursor *pCur,       /* Pointer to entry to compare against */
  const void *pKey,     /* Key to compare against entry that pCur points to */
  int nKey,             /* Number of bytes in pKey */
  int nIgnore,          /* Ignore this many bytes at the end of pCur */
  int *pResult          /* Write the result here */
){
  void *pCellKey;

  u64 nCellKey;
  int rc;

  sqlite3BtreeKeySize(pCur, &nCellKey);
  nCellKey = nCellKey - nIgnore;
  if( nCellKey<=0 ){
    *pResult = 0;
    return SQLITE_OK;
  }

  pCellKey = sqlite3BtreeKeyFetch(pCur);
  if( pCellKey ){
    *pResult = memcmp(pCellKey, pKey, nKey>nCellKey?nCellKey:nKey);
    return SQLITE_OK;
  }

  pCellKey = sqliteMalloc( nCellKey );
  if( pCellKey==0 ) return SQLITE_NOMEM;

  rc = sqlite3BtreeKey(pCur, 0, nCellKey, pCellKey);
  *pResult = memcmp(pCellKey, pKey, nKey>nCellKey?nCellKey:nKey);
  sqliteFree(pCellKey);

  return rc;
}

/*
** The following three functions:
**
................................................................................
    int ii;
    int bytes = 1 << (data_type-1);

    pMem->flags = MEM_Int;
    pMem->i = 0;

    for(ii=0; ii<bytes; ii++){
      pMem->i = pMem->i<<8 + zBuf[ii+ret];
    }

    /* If this is a 1, 2 or 4 byte integer, extend the sign-bit if need be. */
    if( bytes<8 && pMem->i & (1<<(bytes*8-1)) ){
      pMem->i = pMem->i - (1<<(bytes*8));
    }








|
>










|





|
|

|
|
|







 







|







1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
....
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
int sqlite2BtreeKeyCompare(
  BtCursor *pCur,       /* Pointer to entry to compare against */
  const void *pKey,     /* Key to compare against entry that pCur points to */
  int nKey,             /* Number of bytes in pKey */
  int nIgnore,          /* Ignore this many bytes at the end of pCur */
  int *pResult          /* Write the result here */
){
  const void *pCellKey;
  void *pMallocedKey;
  u64 nCellKey;
  int rc;

  sqlite3BtreeKeySize(pCur, &nCellKey);
  nCellKey = nCellKey - nIgnore;
  if( nCellKey<=0 ){
    *pResult = 0;
    return SQLITE_OK;
  }

  pCellKey = sqlite3BtreeKeyFetch(pCur, nCellKey);
  if( pCellKey ){
    *pResult = memcmp(pCellKey, pKey, nKey>nCellKey?nCellKey:nKey);
    return SQLITE_OK;
  }

  pMallocedKey = sqliteMalloc( nCellKey );
  if( pMallocedKey==0 ) return SQLITE_NOMEM;

  rc = sqlite3BtreeKey(pCur, 0, nCellKey, pMallocedKey);
  *pResult = memcmp(pMallocedKey, pKey, nKey>nCellKey?nCellKey:nKey);
  sqliteFree(pMallocedKey);

  return rc;
}

/*
** The following three functions:
**
................................................................................
    int ii;
    int bytes = 1 << (data_type-1);

    pMem->flags = MEM_Int;
    pMem->i = 0;

    for(ii=0; ii<bytes; ii++){
      pMem->i = (pMem->i<<8) + zBuf[ii+ret];
    }

    /* If this is a 1, 2 or 4 byte integer, extend the sign-bit if need be. */
    if( bytes<8 && pMem->i & (1<<(bytes*8-1)) ){
      pMem->i = pMem->i - (1<<(bytes*8));
    }

Changes to test/btree5.test.

7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
112
113
114
115
116
117
118
119
120
















121
122
123
124
125
126
127
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend
#
# $Id: btree5.test,v 1.1 2004/05/10 18:45:10 drh Exp $


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

# Attempting to read table 1 of an empty file gives an SQLITE_EMPTY
# error.
................................................................................
# each entry agrees with its key.
#
proc check_table {N} {
  global c1
  btree_first $c1
  set cnt 0
  while {![btree_eof $c1]} {
    if {[btree_data $c1] ne "data-for-[btree_key $c1]"} {
      return "wrong data for entry $cnt"
















    }
    incr cnt
    btree_next $c1
  }
  if {$cnt!=$N} {
    return "wrong number of entries"
  }







|







 







|

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







7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
...
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is btree database backend
#
# $Id: btree5.test,v 1.2 2004/05/11 00:58:56 drh Exp $


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

# Attempting to read table 1 of an empty file gives an SQLITE_EMPTY
# error.
................................................................................
# each entry agrees with its key.
#
proc check_table {N} {
  global c1
  btree_first $c1
  set cnt 0
  while {![btree_eof $c1]} {
    if {[set data [btree_data $c1]] ne "data-for-[btree_key $c1]"} {
      return "wrong data for entry $cnt"
    }
    set n [string length $data]
    set fdata1 [btree_fetch_data $c1 $n]
    set fdata2 [btree_fetch_data $c1 -1]
    if {$fdata1 ne "" && $fdata1 ne $data} {
puts "fdata1=[list $fdata1] data=[list $data]"
      return "DataFetch returned the wrong value with amt=$n"
    }
    if {$fdata1 ne $fdata2} {
      return "DataFetch returned the wrong value when amt=-1"
    }
    if {$n>10} {
      set fdata3 [btree_fetch_data $c1 10]
      if {$fdata3 ne [string range $data 0 9]} {
        return "DataFetch returned the wrong value when amt=10"
      }
    }
    incr cnt
    btree_next $c1
  }
  if {$cnt!=$N} {
    return "wrong number of entries"
  }