/ Check-in [6f415833]
Login

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

Overview
Comment:Small performance increase and size decrease in the btreeInitPage() routine.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256:6f415833e0554706dcf04f68ecba4ca2e54c08f3bbf6a1dba182bb132c912a2e
User & Date: drh 2017-05-25 21:35:56
Context
2017-05-27
22:42
Smaller and faster vdbeSorterCompareText(). check-in: 542dc4c5 user: drh tags: trunk
2017-05-25
21:35
Small performance increase and size decrease in the btreeInitPage() routine. check-in: 6f415833 user: drh tags: trunk
17:27
Merge the LEFT JOIN query flattener fixes from 3.19.2. check-in: 6513e4a1 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/btree.c.

  1777   1777   ** Return SQLITE_OK on success.  If we see that the page does
  1778   1778   ** not contain a well-formed database page, then return 
  1779   1779   ** SQLITE_CORRUPT.  Note that a return of SQLITE_OK does not
  1780   1780   ** guarantee that the page is well-formed.  It only shows that
  1781   1781   ** we failed to detect any corruption.
  1782   1782   */
  1783   1783   static int btreeInitPage(MemPage *pPage){
         1784  +  int pc;            /* Address of a freeblock within pPage->aData[] */
         1785  +  u8 hdr;            /* Offset to beginning of page header */
         1786  +  u8 *data;          /* Equal to pPage->aData */
         1787  +  BtShared *pBt;        /* The main btree structure */
         1788  +  int usableSize;    /* Amount of usable space on each page */
         1789  +  u16 cellOffset;    /* Offset from start of page to first cell pointer */
         1790  +  int nFree;         /* Number of unused bytes on the page */
         1791  +  int top;           /* First byte of the cell content area */
         1792  +  int iCellFirst;    /* First allowable cell or freeblock offset */
         1793  +  int iCellLast;     /* Last possible cell or freeblock offset */
  1784   1794   
  1785   1795     assert( pPage->pBt!=0 );
  1786   1796     assert( pPage->pBt->db!=0 );
  1787   1797     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  1788   1798     assert( pPage->pgno==sqlite3PagerPagenumber(pPage->pDbPage) );
  1789   1799     assert( pPage == sqlite3PagerGetExtra(pPage->pDbPage) );
  1790   1800     assert( pPage->aData == sqlite3PagerGetData(pPage->pDbPage) );
  1791         -
  1792         -  if( !pPage->isInit ){
  1793         -    int pc;            /* Address of a freeblock within pPage->aData[] */
  1794         -    u8 hdr;            /* Offset to beginning of page header */
  1795         -    u8 *data;          /* Equal to pPage->aData */
  1796         -    BtShared *pBt;        /* The main btree structure */
  1797         -    int usableSize;    /* Amount of usable space on each page */
  1798         -    u16 cellOffset;    /* Offset from start of page to first cell pointer */
  1799         -    int nFree;         /* Number of unused bytes on the page */
  1800         -    int top;           /* First byte of the cell content area */
  1801         -    int iCellFirst;    /* First allowable cell or freeblock offset */
  1802         -    int iCellLast;     /* Last possible cell or freeblock offset */
  1803         -
  1804         -    pBt = pPage->pBt;
  1805         -
  1806         -    hdr = pPage->hdrOffset;
  1807         -    data = pPage->aData;
  1808         -    /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
  1809         -    ** the b-tree page type. */
  1810         -    if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
  1811         -    assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
  1812         -    pPage->maskPage = (u16)(pBt->pageSize - 1);
  1813         -    pPage->nOverflow = 0;
  1814         -    usableSize = pBt->usableSize;
  1815         -    pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
  1816         -    pPage->aDataEnd = &data[usableSize];
  1817         -    pPage->aCellIdx = &data[cellOffset];
  1818         -    pPage->aDataOfst = &data[pPage->childPtrSize];
  1819         -    /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
  1820         -    ** the start of the cell content area. A zero value for this integer is
  1821         -    ** interpreted as 65536. */
  1822         -    top = get2byteNotZero(&data[hdr+5]);
  1823         -    /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
  1824         -    ** number of cells on the page. */
  1825         -    pPage->nCell = get2byte(&data[hdr+3]);
  1826         -    if( pPage->nCell>MX_CELL(pBt) ){
  1827         -      /* To many cells for a single page.  The page must be corrupt */
  1828         -      return SQLITE_CORRUPT_BKPT;
  1829         -    }
  1830         -    testcase( pPage->nCell==MX_CELL(pBt) );
  1831         -    /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
  1832         -    ** possible for a root page of a table that contains no rows) then the
  1833         -    ** offset to the cell content area will equal the page size minus the
  1834         -    ** bytes of reserved space. */
  1835         -    assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
  1836         -
  1837         -    /* A malformed database page might cause us to read past the end
  1838         -    ** of page when parsing a cell.  
  1839         -    **
  1840         -    ** The following block of code checks early to see if a cell extends
  1841         -    ** past the end of a page boundary and causes SQLITE_CORRUPT to be 
  1842         -    ** returned if it does.
  1843         -    */
  1844         -    iCellFirst = cellOffset + 2*pPage->nCell;
  1845         -    iCellLast = usableSize - 4;
  1846         -    if( pBt->db->flags & SQLITE_CellSizeCk ){
  1847         -      int i;            /* Index into the cell pointer array */
  1848         -      int sz;           /* Size of a cell */
  1849         -
  1850         -      if( !pPage->leaf ) iCellLast--;
  1851         -      for(i=0; i<pPage->nCell; i++){
  1852         -        pc = get2byteAligned(&data[cellOffset+i*2]);
  1853         -        testcase( pc==iCellFirst );
  1854         -        testcase( pc==iCellLast );
  1855         -        if( pc<iCellFirst || pc>iCellLast ){
  1856         -          return SQLITE_CORRUPT_BKPT;
  1857         -        }
  1858         -        sz = pPage->xCellSize(pPage, &data[pc]);
  1859         -        testcase( pc+sz==usableSize );
  1860         -        if( pc+sz>usableSize ){
  1861         -          return SQLITE_CORRUPT_BKPT;
  1862         -        }
  1863         -      }
  1864         -      if( !pPage->leaf ) iCellLast++;
  1865         -    }  
  1866         -
  1867         -    /* Compute the total free space on the page
  1868         -    ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
  1869         -    ** start of the first freeblock on the page, or is zero if there are no
  1870         -    ** freeblocks. */
  1871         -    pc = get2byte(&data[hdr+1]);
  1872         -    nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
  1873         -    if( pc>0 ){
  1874         -      u32 next, size;
  1875         -      if( pc<iCellFirst ){
  1876         -        /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
  1877         -        ** always be at least one cell before the first freeblock.
  1878         -        */
  1879         -        return SQLITE_CORRUPT_BKPT; 
  1880         -      }
  1881         -      while( 1 ){
  1882         -        if( pc>iCellLast ){
  1883         -          return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */
  1884         -        }
  1885         -        next = get2byte(&data[pc]);
  1886         -        size = get2byte(&data[pc+2]);
  1887         -        nFree = nFree + size;
  1888         -        if( next<=pc+size+3 ) break;
  1889         -        pc = next;
  1890         -      }
  1891         -      if( next>0 ){
  1892         -        return SQLITE_CORRUPT_BKPT;  /* Freeblock not in ascending order */
  1893         -      }
  1894         -      if( pc+size>(unsigned int)usableSize ){
  1895         -        return SQLITE_CORRUPT_BKPT;  /* Last freeblock extends past page end */
  1896         -      }
  1897         -    }
  1898         -
  1899         -    /* At this point, nFree contains the sum of the offset to the start
  1900         -    ** of the cell-content area plus the number of free bytes within
  1901         -    ** the cell-content area. If this is greater than the usable-size
  1902         -    ** of the page, then the page must be corrupted. This check also
  1903         -    ** serves to verify that the offset to the start of the cell-content
  1904         -    ** area, according to the page header, lies within the page.
  1905         -    */
  1906         -    if( nFree>usableSize ){
         1801  +  assert( pPage->isInit==0 );
         1802  +
         1803  +  pBt = pPage->pBt;
         1804  +  hdr = pPage->hdrOffset;
         1805  +  data = pPage->aData;
         1806  +  /* EVIDENCE-OF: R-28594-02890 The one-byte flag at offset 0 indicating
         1807  +  ** the b-tree page type. */
         1808  +  if( decodeFlags(pPage, data[hdr]) ) return SQLITE_CORRUPT_BKPT;
         1809  +  assert( pBt->pageSize>=512 && pBt->pageSize<=65536 );
         1810  +  pPage->maskPage = (u16)(pBt->pageSize - 1);
         1811  +  pPage->nOverflow = 0;
         1812  +  usableSize = pBt->usableSize;
         1813  +  pPage->cellOffset = cellOffset = hdr + 8 + pPage->childPtrSize;
         1814  +  pPage->aDataEnd = &data[usableSize];
         1815  +  pPage->aCellIdx = &data[cellOffset];
         1816  +  pPage->aDataOfst = &data[pPage->childPtrSize];
         1817  +  /* EVIDENCE-OF: R-58015-48175 The two-byte integer at offset 5 designates
         1818  +  ** the start of the cell content area. A zero value for this integer is
         1819  +  ** interpreted as 65536. */
         1820  +  top = get2byteNotZero(&data[hdr+5]);
         1821  +  /* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
         1822  +  ** number of cells on the page. */
         1823  +  pPage->nCell = get2byte(&data[hdr+3]);
         1824  +  if( pPage->nCell>MX_CELL(pBt) ){
         1825  +    /* To many cells for a single page.  The page must be corrupt */
         1826  +    return SQLITE_CORRUPT_BKPT;
         1827  +  }
         1828  +  testcase( pPage->nCell==MX_CELL(pBt) );
         1829  +  /* EVIDENCE-OF: R-24089-57979 If a page contains no cells (which is only
         1830  +  ** possible for a root page of a table that contains no rows) then the
         1831  +  ** offset to the cell content area will equal the page size minus the
         1832  +  ** bytes of reserved space. */
         1833  +  assert( pPage->nCell>0 || top==usableSize || CORRUPT_DB );
         1834  +
         1835  +  /* A malformed database page might cause us to read past the end
         1836  +  ** of page when parsing a cell.  
         1837  +  **
         1838  +  ** The following block of code checks early to see if a cell extends
         1839  +  ** past the end of a page boundary and causes SQLITE_CORRUPT to be 
         1840  +  ** returned if it does.
         1841  +  */
         1842  +  iCellFirst = cellOffset + 2*pPage->nCell;
         1843  +  iCellLast = usableSize - 4;
         1844  +  if( pBt->db->flags & SQLITE_CellSizeCk ){
         1845  +    int i;            /* Index into the cell pointer array */
         1846  +    int sz;           /* Size of a cell */
         1847  +
         1848  +    if( !pPage->leaf ) iCellLast--;
         1849  +    for(i=0; i<pPage->nCell; i++){
         1850  +      pc = get2byteAligned(&data[cellOffset+i*2]);
         1851  +      testcase( pc==iCellFirst );
         1852  +      testcase( pc==iCellLast );
         1853  +      if( pc<iCellFirst || pc>iCellLast ){
         1854  +        return SQLITE_CORRUPT_BKPT;
         1855  +      }
         1856  +      sz = pPage->xCellSize(pPage, &data[pc]);
         1857  +      testcase( pc+sz==usableSize );
         1858  +      if( pc+sz>usableSize ){
         1859  +        return SQLITE_CORRUPT_BKPT;
         1860  +      }
         1861  +    }
         1862  +    if( !pPage->leaf ) iCellLast++;
         1863  +  }  
         1864  +
         1865  +  /* Compute the total free space on the page
         1866  +  ** EVIDENCE-OF: R-23588-34450 The two-byte integer at offset 1 gives the
         1867  +  ** start of the first freeblock on the page, or is zero if there are no
         1868  +  ** freeblocks. */
         1869  +  pc = get2byte(&data[hdr+1]);
         1870  +  nFree = data[hdr+7] + top;  /* Init nFree to non-freeblock free space */
         1871  +  if( pc>0 ){
         1872  +    u32 next, size;
         1873  +    if( pc<iCellFirst ){
         1874  +      /* EVIDENCE-OF: R-55530-52930 In a well-formed b-tree page, there will
         1875  +      ** always be at least one cell before the first freeblock.
         1876  +      */
  1907   1877         return SQLITE_CORRUPT_BKPT; 
  1908   1878       }
  1909         -    pPage->nFree = (u16)(nFree - iCellFirst);
  1910         -    pPage->isInit = 1;
         1879  +    while( 1 ){
         1880  +      if( pc>iCellLast ){
         1881  +        return SQLITE_CORRUPT_BKPT; /* Freeblock off the end of the page */
         1882  +      }
         1883  +      next = get2byte(&data[pc]);
         1884  +      size = get2byte(&data[pc+2]);
         1885  +      nFree = nFree + size;
         1886  +      if( next<=pc+size+3 ) break;
         1887  +      pc = next;
         1888  +    }
         1889  +    if( next>0 ){
         1890  +      return SQLITE_CORRUPT_BKPT;  /* Freeblock not in ascending order */
         1891  +    }
         1892  +    if( pc+size>(unsigned int)usableSize ){
         1893  +      return SQLITE_CORRUPT_BKPT;  /* Last freeblock extends past page end */
         1894  +    }
  1911   1895     }
         1896  +
         1897  +  /* At this point, nFree contains the sum of the offset to the start
         1898  +  ** of the cell-content area plus the number of free bytes within
         1899  +  ** the cell-content area. If this is greater than the usable-size
         1900  +  ** of the page, then the page must be corrupted. This check also
         1901  +  ** serves to verify that the offset to the start of the cell-content
         1902  +  ** area, according to the page header, lies within the page.
         1903  +  */
         1904  +  if( nFree>usableSize ){
         1905  +    return SQLITE_CORRUPT_BKPT; 
         1906  +  }
         1907  +  pPage->nFree = (u16)(nFree - iCellFirst);
         1908  +  pPage->isInit = 1;
  1912   1909     return SQLITE_OK;
  1913   1910   }
  1914   1911   
  1915   1912   /*
  1916   1913   ** Set up a raw page so that it looks like a database page holding
  1917   1914   ** no entries.
  1918   1915   */
................................................................................
  3356   3353     int i;                             /* Counter variable */
  3357   3354     int nCell;                         /* Number of cells in page pPage */
  3358   3355     int rc;                            /* Return code */
  3359   3356     BtShared *pBt = pPage->pBt;
  3360   3357     Pgno pgno = pPage->pgno;
  3361   3358   
  3362   3359     assert( sqlite3_mutex_held(pPage->pBt->mutex) );
  3363         -  rc = btreeInitPage(pPage);
         3360  +  rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
  3364   3361     if( rc!=SQLITE_OK ) return rc;
  3365   3362     nCell = pPage->nCell;
  3366   3363   
  3367   3364     for(i=0; i<nCell; i++){
  3368   3365       u8 *pCell = findCell(pPage, i);
  3369   3366   
  3370   3367       ptrmapPutOvflPtr(pPage, pCell, &rc);
................................................................................
  3407   3404       }
  3408   3405       put4byte(pPage->aData, iTo);
  3409   3406     }else{
  3410   3407       int i;
  3411   3408       int nCell;
  3412   3409       int rc;
  3413   3410   
  3414         -    rc = btreeInitPage(pPage);
         3411  +    rc = pPage->isInit ? SQLITE_OK : btreeInitPage(pPage);
  3415   3412       if( rc ) return rc;
  3416   3413       nCell = pPage->nCell;
  3417   3414   
  3418   3415       for(i=0; i<nCell; i++){
  3419   3416         u8 *pCell = findCell(pPage, i);
  3420   3417         if( eType==PTRMAP_OVERFLOW1 ){
  3421   3418           CellInfo info;