/ Check-in [ef5cdf94]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Add header comments on new routines. Rework the sqlite3Stat4Column() routine so that is (in theory) able to deal with corrupt samples.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | stat4-skipscan
Files: files | file ages | folders
SHA1: ef5cdf949bb53a2958fa34e176b4b9eeda269de5
User & Date: drh 2014-06-28 16:06:44
Context
2014-06-28
17:35
Add further tests to skipscan5.test. check-in: 4b8230e8 user: dan tags: stat4-skipscan
16:06
Add header comments on new routines. Rework the sqlite3Stat4Column() routine so that is (in theory) able to deal with corrupt samples. check-in: ef5cdf94 user: drh tags: stat4-skipscan
15:26
Fix a problem with using stat4 samples of type text when estimating the rows visited by a range-query/skip-scan loop. check-in: dfb09db6 user: dan tags: stat4-skipscan
Changes
Hide Diffs Side-by-Side Diffs Show Whitespace Changes Patch

Changes to src/vdbemem.c.

  1148   1148     FuncDefHash *pHash = &GLOBAL(FuncDefHash, sqlite3GlobalFunctions);
  1149   1149     FuncDef *aFunc = (FuncDef*)&GLOBAL(FuncDef, aAnalyzeTableFuncs);
  1150   1150     for(i=0; i<ArraySize(aAnalyzeTableFuncs); i++){
  1151   1151       sqlite3FuncDefInsert(pHash, &aFunc[i]);
  1152   1152     }
  1153   1153   }
  1154   1154   
         1155  +/*
         1156  +** Attempt to extract a value from pExpr and use it to construct *ppVal.
         1157  +**
         1158  +** If pAlloc is not NULL, then an UnpackedRecord object is created for
         1159  +** pAlloc if one does not exist and the new value is added to the
         1160  +** UnpackedRecord object.
         1161  +**
         1162  +** A value is extracted in the following cases:
         1163  +**
         1164  +**  * (pExpr==0). In this case the value is assumed to be an SQL NULL,
         1165  +**
         1166  +**  * The expression is a bound variable, and this is a reprepare, or
         1167  +**
         1168  +**  * The expression is a literal value.
         1169  +**
         1170  +** On success, *ppVal is made to point to the extracted value.  The caller
         1171  +** is responsible for ensuring that the value is eventually freed.
         1172  +*/
  1155   1173   static int stat4ValueFromExpr(
  1156   1174     Parse *pParse,                  /* Parse context */
  1157   1175     Expr *pExpr,                    /* The expression to extract a value from */
  1158   1176     u8 affinity,                    /* Affinity to use */
  1159         -  struct ValueNewStat4Ctx *pAlloc,/* How to allocate space */
         1177  +  struct ValueNewStat4Ctx *pAlloc,/* How to allocate space.  Or NULL */
  1160   1178     sqlite3_value **ppVal           /* OUT: New value object (or NULL) */
  1161   1179   ){
  1162   1180     int rc = SQLITE_OK;
  1163   1181     sqlite3_value *pVal = 0;
  1164   1182     sqlite3 *db = pParse->db;
  1165   1183   
  1166   1184     /* Skip over any TK_COLLATE nodes */
................................................................................
  1265   1283     Expr *pExpr,                    /* The expression to extract a value from */
  1266   1284     u8 affinity,                    /* Affinity to use */
  1267   1285     sqlite3_value **ppVal           /* OUT: New value object (or NULL) */
  1268   1286   ){
  1269   1287     return stat4ValueFromExpr(pParse, pExpr, affinity, 0, ppVal);
  1270   1288   }
  1271   1289   
         1290  +/*
         1291  +** Extract the iCol-th column from the nRec-byte record in pRec.  Write
         1292  +** the column value into *ppVal.  If *ppVal is initially NULL then a new
         1293  +** sqlite3_value object is allocated.
         1294  +**
         1295  +** If *ppVal is initially NULL then the caller is responsible for 
         1296  +** ensuring that the value written into *ppVal is eventually freed.
         1297  +*/
  1272   1298   int sqlite3Stat4Column(
  1273   1299     sqlite3 *db,                    /* Database handle */
  1274   1300     const void *pRec,               /* Pointer to buffer containing record */
  1275   1301     int nRec,                       /* Size of buffer pRec in bytes */
  1276   1302     int iCol,                       /* Column to extract */
  1277   1303     sqlite3_value **ppVal           /* OUT: Extracted value */
  1278   1304   ){
  1279         -  int rc = SQLITE_OK;
  1280         -  Mem *pMem = *ppVal;
  1281         -  if( pMem==0 ){
  1282         -    pMem = (Mem*)sqlite3ValueNew(db);
  1283         -    if( pMem==0 ){
  1284         -      rc = SQLITE_NOMEM;
  1285         -    }
  1286         -  }
         1305  +  u32 t;                          /* a column type code */
         1306  +  int nHdr;                       /* Size of the header in the record */
         1307  +  int iHdr;                       /* Next unread header byte */
         1308  +  int iField;                     /* Next unread data byte */
         1309  +  int szField;                    /* Size of the current data field */
         1310  +  int i;                          /* Column index */
         1311  +  u8 *a = (u8*)pRec;              /* Typecast byte array */
         1312  +  Mem *pMem = *ppVal;             /* Write result into this Mem object */
  1287   1313   
  1288         -  if( rc==SQLITE_OK ){
  1289         -    u32 t;
  1290         -    int nHdr;
  1291         -    int iHdr;
  1292         -    int iField;
  1293         -    int i;
  1294         -    u8 *a = (u8*)pRec;
  1295         -
         1314  +  assert( iCol>0 );
  1296   1315       iHdr = getVarint32(a, nHdr);
         1316  +  if( nHdr>nRec || iHdr>=nHdr ) return SQLITE_CORRUPT_BKPT;
  1297   1317       iField = nHdr;
  1298         -    for(i=0; i<iCol; i++){
         1318  +  for(i=0; i<=iCol; i++){
  1299   1319         iHdr += getVarint32(&a[iHdr], t);
  1300         -      iField += sqlite3VdbeSerialTypeLen(t);
         1320  +    testcase( iHdr==nHdr );
         1321  +    testcase( iHdr==nHdr+1 );
         1322  +    if( iHdr>nHdr ) return SQLITE_CORRUPT_BKPT;
         1323  +    szField = sqlite3VdbeSerialTypeLen(t);
         1324  +    iField += szField;
  1301   1325       }
  1302         -
  1303         -    iHdr = getVarint32(&a[iHdr], t);
  1304         -    pMem->enc = ENC(db);
  1305         -    sqlite3VdbeSerialGet(&a[iField], t, pMem);
         1326  +  testcase( iField==nRec );
         1327  +  testcase( iField==nRec+1 );
         1328  +  if( iField>nRec ) return SQLITE_CORRUPT_BKPT;
         1329  +  if( pMem==0 ){
         1330  +    pMem = *ppVal = sqlite3ValueNew(db);
         1331  +    if( pMem==0 ) return SQLITE_NOMEM;
  1306   1332     }
  1307         -
  1308         -  *ppVal = pMem;
  1309         -  return rc;
         1333  +  sqlite3VdbeSerialGet(&a[iField-szField], t, pMem);
         1334  +  pMem->enc = ENC(db);
         1335  +  return SQLITE_OK;
  1310   1336   }
  1311   1337   
  1312   1338   /*
  1313   1339   ** Unless it is NULL, the argument must be an UnpackedRecord object returned
  1314   1340   ** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
  1315   1341   ** the object.
  1316   1342   */