SQLite

Check-in [2d74cc22de]
Login

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

Overview
Comment:Tweaks to make OP_Column run a fraction faster. (CVS 2941)
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 2d74cc22de2aa59329b1ea5c26acd6ebe46e16c2
User & Date: danielk1977 2006-01-13 17:12:01.000
Context
2006-01-13
18:06
Account for multi-byte characters in ALTER TABLE code. Fix for #1609. (CVS 2942) (check-in: d634f8b28a user: danielk1977 tags: trunk)
17:12
Tweaks to make OP_Column run a fraction faster. (CVS 2941) (check-in: 2d74cc22de user: danielk1977 tags: trunk)
15:58
Avoid parsing an entire record header when it is not required. (CVS 2940) (check-in: 0de729d914 user: danielk1977 tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
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.528 2006/01/13 15:58:43 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*







|







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.529 2006/01/13 17:12:01 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
#include <ctype.h>
#include "vdbeInt.h"

/*
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
  int p2 = pOp->p2;  /* column number to retrieve */
  Cursor *pC = 0;    /* The VDBE cursor */
  char *zRec;        /* Pointer to complete record-data */
  BtCursor *pCrsr;   /* The BTree cursor */
  u32 *aType;        /* aType[i] holds the numeric type of the i-th column */
  u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */
  u32 nField;        /* number of fields in the record */
  u32 szHdr;         /* Number of bytes in the record header */
  int len;           /* The length of the serialized data for the column */
  int offset = 0;    /* Offset into the data */
  int idx;           /* Index into the header */
  int i;             /* Loop counter */
  char *zData;       /* Part of the record being decoded */
  Mem sMem;          /* For storing the record being decoded */

  sMem.flags = 0;
  assert( p1<p->nCursor );
  pTos++;







<

<
<







1879
1880
1881
1882
1883
1884
1885

1886


1887
1888
1889
1890
1891
1892
1893
  int p2 = pOp->p2;  /* column number to retrieve */
  Cursor *pC = 0;    /* The VDBE cursor */
  char *zRec;        /* Pointer to complete record-data */
  BtCursor *pCrsr;   /* The BTree cursor */
  u32 *aType;        /* aType[i] holds the numeric type of the i-th column */
  u32 *aOffset;      /* aOffset[i] is offset to start of data for i-th column */
  u32 nField;        /* number of fields in the record */

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


  int i;             /* Loop counter */
  char *zData;       /* Part of the record being decoded */
  Mem sMem;          /* For storing the record being decoded */

  sMem.flags = 0;
  assert( p1<p->nCursor );
  pTos++;
1971
1972
1973
1974
1975
1976
1977



1978
1979
1980
1981
1982
1983
1984
1985
  /* Read and parse the table header.  Store the results of the parse
  ** into the record header cache fields of the cursor.
  */
  if( pC && pC->cacheStatus==p->cacheCtr ){
    aType = pC->aType;
    aOffset = pC->aOffset;
  }else{



    int avail;    /* Number of bytes of available data */
    if( pC && pC->aType ){
      aType = pC->aType;
    }else{
      aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
    }
    aOffset = &aType[nField];
    if( aType==0 ){







>
>
>
|







1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
  /* Read and parse the table header.  Store the results of the parse
  ** into the record header cache fields of the cursor.
  */
  if( pC && pC->cacheStatus==p->cacheCtr ){
    aType = pC->aType;
    aOffset = pC->aOffset;
  }else{
    u8 *zIdx;        /* Index into header */
    u8 *zEndHdr;     /* Pointer to first byte after the header */
    u32 offset;      /* Offset into the data */
    int avail;       /* Number of bytes of available data */
    if( pC && pC->aType ){
      aType = pC->aType;
    }else{
      aType = sqliteMallocRaw( 2*nField*sizeof(aType) );
    }
    aOffset = &aType[nField];
    if( aType==0 ){
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
      if( avail>=payloadSize ){
        zRec = zData;
        pC->aRow = (u8*)zData;
      }else{
        pC->aRow = 0;
      }
    }
    idx = GetVarint((u8*)zData, szHdr);


    /* The KeyFetch() or DataFetch() above are fast and will get the entire
    ** record header in most cases.  But they will fail to get the complete
    ** record header if the record header does not fit on a single page
    ** in the B-Tree.  When that happens, use sqlite3VdbeMemFromBtree() to
    ** acquire the complete header text.
    */
    if( !zRec && avail<szHdr ){
      rc = sqlite3VdbeMemFromBtree(pCrsr, 0, szHdr, pC->isIndex, &sMem);
      if( rc!=SQLITE_OK ){
        goto op_column_out;
      }
      zData = sMem.z;
    }



    /* Scan the header and use it to fill in the aType[] and aOffset[]
    ** arrays.  aType[i] will contain the type integer for the i-th
    ** column and aOffset[i] will contain the offset from the beginning
    ** of the record to the start of the data for the i-th column
    */
    offset = szHdr;
    assert( offset>0 );
    i = 0;
    while( idx<szHdr && i<nField && offset<=payloadSize ){
      aOffset[i] = offset;
      idx += GetVarint((u8*)&zData[idx], aType[i]);
      offset += sqlite3VdbeSerialTypeLen(aType[i]);
      i++;
    }
    Release(&sMem);
    sMem.flags = MEM_Null;

    /* If i is less that nField, then there are less fields in this
    ** record than SetNumColumns indicated there are columns in the
    ** table. Set the offset for any extra columns not present in
    ** the record to 0. This tells code below to push a NULL onto the
    ** stack instead of deserializing a value from the record.
    */
    while( i<nField ){
      aOffset[i++] = 0;
    }




    /* If we have read more header data than was contained in the header,
    ** or if the end of the last field appears to be past the end of the
    ** record, then we must be dealing with a corrupt database.
    */
    if( idx>szHdr || offset>payloadSize ){
      rc = SQLITE_CORRUPT_BKPT;
      goto op_column_out;
    }

    /* Remember all aType and aColumn information if we have a cursor
    ** to remember it in. */
    if( pC ){







|
<







|
|





>
>






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




|







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
      if( avail>=payloadSize ){
        zRec = zData;
        pC->aRow = (u8*)zData;
      }else{
        pC->aRow = 0;
      }
    }
    zIdx = (u8 *)GetVarint((u8*)zData, offset);


    /* The KeyFetch() or DataFetch() above are fast and will get the entire
    ** record header in most cases.  But they will fail to get the complete
    ** record header if the record header does not fit on a single page
    ** in the B-Tree.  When that happens, use sqlite3VdbeMemFromBtree() to
    ** acquire the complete header text.
    */
    if( !zRec && avail<offset ){
      rc = sqlite3VdbeMemFromBtree(pCrsr, 0, offset, pC->isIndex, &sMem);
      if( rc!=SQLITE_OK ){
        goto op_column_out;
      }
      zData = sMem.z;
    }
    zEndHdr = (u8 *)zData + offset;
    zIdx = zData + (int)zIdx;

    /* Scan the header and use it to fill in the aType[] and aOffset[]
    ** arrays.  aType[i] will contain the type integer for the i-th
    ** column and aOffset[i] will contain the offset from the beginning
    ** of the record to the start of the data for the i-th column
    */


    for(i=0; i<nField; i++){
      if( zIdx<zEndHdr ){
        aOffset[i] = offset;
        zIdx += GetVarint(zIdx, aType[i]);
        offset += sqlite3VdbeSerialTypeLen(aType[i]);

      }else{



        /* If i is less that nField, then there are less fields in this
        ** record than SetNumColumns indicated there are columns in the
        ** table. Set the offset for any extra columns not present in
        ** the record to 0. This tells code below to push a NULL onto the
        ** stack instead of deserializing a value from the record.
        */

        aOffset[i] = 0;
      }
    }
    Release(&sMem);
    sMem.flags = MEM_Null;

    /* If we have read more header data than was contained in the header,
    ** or if the end of the last field appears to be past the end of the
    ** record, then we must be dealing with a corrupt database.
    */
    if( zIdx>zEndHdr || offset>payloadSize ){
      rc = SQLITE_CORRUPT_BKPT;
      goto op_column_out;
    }

    /* Remember all aType and aColumn information if we have a cursor
    ** to remember it in. */
    if( pC ){