/ Check-in [353950a5]
Login

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

Overview
Comment:When estimating the number of rows scanned using data from the sqlite_stat4 table, avoid allocating UnpackedRecord and KeyInfo structures until they are definitely required.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sqlite_stat4
Files: files | file ages | folders
SHA1: 353950a5269fa439cc3e57b62e16558a84ea2557
User & Date: dan 2013-08-07 15:52:41
Context
2013-08-07
15:57
Remove the unused sqlite3Utf8to16() utility function. check-in: 9159b43e user: drh tags: sqlite_stat4
15:52
When estimating the number of rows scanned using data from the sqlite_stat4 table, avoid allocating UnpackedRecord and KeyInfo structures until they are definitely required. check-in: 353950a5 user: dan tags: sqlite_stat4
2013-08-06
20:15
Fixes for builds without SQLITE_ENABLE_STAT4. check-in: 84999e27 user: dan tags: sqlite_stat4
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
....
3097
3098
3099
3100
3101
3102
3103
3104
3105
3106
3107
3108
3109
3110
3111
3112
3113
  Expr *pPartIdxWhere;     /* WHERE clause for partial indices */
  int tnum;                /* DB Page containing root of this index */
  u16 nColumn;             /* Number of columns in table used by this index */
  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
#ifdef SQLITE_ENABLE_STAT3
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

/*
................................................................................
void sqlite3StrAccumReset(StrAccum*);
void sqlite3SelectDestInit(SelectDest*,int,int);
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);

void sqlite3BackupRestart(sqlite3_backup *);
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

int sqlite3Stat4ProbeSetValue(Parse*, UnpackedRecord*, Expr*, u8, int, int*);
void sqlite3Stat4ProbeFree(UnpackedRecord*);
int sqlite3Stat4ProbeNew(Parse*, Index*, UnpackedRecord**);

/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);







|







 







|

<







1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
....
3097
3098
3099
3100
3101
3102
3103
3104
3105

3106
3107
3108
3109
3110
3111
3112
  Expr *pPartIdxWhere;     /* WHERE clause for partial indices */
  int tnum;                /* DB Page containing root of this index */
  u16 nColumn;             /* Number of columns in table used by this index */
  u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  unsigned autoIndex:2;    /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
  unsigned bUnordered:1;   /* Use this index for == or IN queries only */
  unsigned uniqNotNull:1;  /* True if UNIQUE and NOT NULL for all columns */
#ifdef SQLITE_ENABLE_STAT4
  int nSample;             /* Number of elements in aSample[] */
  tRowcnt avgEq;           /* Average nEq value for key values not in aSample */
  IndexSample *aSample;    /* Samples of the left-most key */
#endif
};

/*
................................................................................
void sqlite3StrAccumReset(StrAccum*);
void sqlite3SelectDestInit(SelectDest*,int,int);
Expr *sqlite3CreateColumnExpr(sqlite3 *, SrcList *, int, int);

void sqlite3BackupRestart(sqlite3_backup *);
void sqlite3BackupUpdate(sqlite3_backup *, Pgno, const u8 *);

int sqlite3Stat4ProbeSetValue(Parse*,Index*,UnpackedRecord**,Expr*,u8,int,int*);
void sqlite3Stat4ProbeFree(UnpackedRecord*);


/*
** The interface to the LEMON-generated parser
*/
void *sqlite3ParserAlloc(void*(*)(size_t));
void sqlite3ParserFree(void*, void(*)(void*));
void sqlite3Parser(void*, int, Token, Parse*);

Changes to src/vdbemem.c.

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
....
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
....
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
....
1122
1123
1124
1125
1126
1127
1128
1129




















1130






















































































1131
1132
1133


1134
1135
1136
1137
1138
1139
1140






1141
1142
1143
1144
1145
1146


1147
1148

1149
1150
1151
1152
1153
1154
1155


1156
1157
1158
1159
1160
1161
1162

1163
1164
1165
1166
1167

1168

1169
1170

1171
1172
1173
1174





1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
    p->flags = MEM_Null;
    p->type = SQLITE_NULL;
    p->db = db;
  }
  return p;
}








static sqlite3_value *valueNew(sqlite3 *db, sqlite3_value *pOld){
  if( pOld ) return pOld;
  return sqlite3ValueNew(db);
}

/*
** Create a new sqlite3_value object, containing the value of pExpr.
**
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite3ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.
*/
int sqlite3ValueFromExpr(
  sqlite3 *db,              /* The database connection */
  Expr *pExpr,              /* The expression to evaluate */
  u8 enc,                   /* Encoding to use */
  u8 affinity,              /* Affinity to use */
  sqlite3_value **ppVal     /* Write the new value here */


){
  int op;
  char *zVal = 0;
  sqlite3_value *pVal = 0;
  int negInt = 1;
  const char *zNeg = "";

................................................................................
    pExpr = pExpr->pLeft;
    op = pExpr->op;
    negInt = -1;
    zNeg = "-";
  }

  if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
    pVal = valueNew(db, *ppVal);
    if( pVal==0 ) goto no_mem;
    if( ExprHasProperty(pExpr, EP_IntValue) ){
      sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
    }else{
      zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
      if( zVal==0 ) goto no_mem;
      sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
................................................................................
      }else{
        pVal->u.i = -pVal->u.i;
      }
      pVal->r = -pVal->r;
      sqlite3ValueApplyAffinity(pVal, affinity, enc);
    }
  }else if( op==TK_NULL ){
    pVal = valueNew(db, *ppVal);
    if( pVal==0 ) goto no_mem;
  }
#ifndef SQLITE_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
    assert( pExpr->u.zToken[1]=='\'' );
    pVal = valueNew(db, *ppVal);
    if( !pVal ) goto no_mem;
    zVal = &pExpr->u.zToken[2];
    nVal = sqlite3Strlen30(zVal)-1;
    assert( zVal[nVal]=='\'' );
    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
                         0, SQLITE_DYNAMIC);
  }
................................................................................
no_mem:
  db->mallocFailed = 1;
  sqlite3DbFree(db, zVal);
  if( *ppVal==0 ) sqlite3ValueFree(pVal);
  *ppVal = 0;
  return SQLITE_NOMEM;
}





















#ifdef SQLITE_ENABLE_STAT4






















































































int sqlite3Stat4ProbeSetValue(
  Parse *pParse,                  /* Parse context */
  UnpackedRecord *pRec,           /* Set field in this probe */


  Expr *pExpr,                    /* The expression to extract a value from */
  u8 affinity,                    /* Affinity to use */
  int iVal,                       /* Array element to populate */
  int *pbOk                       /* OUT: True if value was extracted */
){
  int rc = SQLITE_OK;
  sqlite3_value *pVal = &pRec->aMem[iVal];







#if 0
  if( iVal>0 ){ *pbOk = 0; return SQLITE_OK; }
#endif

  if( !pExpr ){


    sqlite3VdbeMemSetNull((Mem*)pVal);
    *pbOk = 1;

  }else if( pExpr->op==TK_VARIABLE
        || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    Vdbe *v;
    int iVar = pExpr->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
    if( v = pParse->pReprepare ){


      rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iVal-1]);
      if( rc==SQLITE_OK ){
        sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
      }
      pVal->db = pParse->db;
      *pbOk = 1;
      sqlite3VdbeMemStoreType((Mem*)pVal);

    }else{
      *pbOk = 0;
    }
  }else{
    sqlite3 *db = pRec->aMem[0].db;

    rc = sqlite3ValueFromExpr(db, pExpr, ENC(db), affinity, &pVal);

    *pbOk = (pVal!=0);
  }

  assert( pVal==0 || pVal->db==pParse->db );
  return rc;
}






void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
  if( pRec ){
    int i;
    Mem *aMem = pRec->aMem;
    sqlite3 *db = aMem[0].db;
    for(i=0; i<pRec->pKeyInfo->nField; i++){
      sqlite3DbFree(db, aMem[i].zMalloc);
    }
    sqlite3DbFree(db, pRec->pKeyInfo);
    sqlite3DbFree(db, pRec);
  }
}

int sqlite3Stat4ProbeNew(
  Parse *pParse,                  /* Parse context */
  Index *pIdx,                    /* Allocate record for this index */
  UnpackedRecord **ppRec          /* OUT: Allocated record */
){
  sqlite3 *db = pParse->db;       /* Database handle */
  UnpackedRecord *pRec;           /* Return value */
  int nByte;                      /* Bytes of space to allocate */
  int i;                          /* Counter variable */

  assert( *ppRec==0 );
  if( pIdx->nSample==0 ) return SQLITE_OK;

  nByte = sizeof(Mem) * pIdx->nColumn + sizeof(UnpackedRecord);
  *ppRec = pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
  if( !pRec ) return SQLITE_NOMEM;
  pRec->pKeyInfo = sqlite3IndexKeyinfo(pParse, pIdx);
  if( !pRec->pKeyInfo ){
    sqlite3DbFree(db, pRec);
    *ppRec = 0;
    return SQLITE_NOMEM;
  }
  pRec->pKeyInfo->enc = ENC(pParse->db);
  pRec->flags = UNPACKED_PREFIX_MATCH;
  pRec->aMem = (Mem *)&pRec[1];
  for(i=0; i<pIdx->nColumn; i++){
    pRec->aMem[i].flags = MEM_Null;
    pRec->aMem[i].type = SQLITE_NULL;
    pRec->aMem[i].db = db;
  }

  return SQLITE_OK;
}
#endif /* ifdef SQLITE_ENABLE_STAT4 */

/*
** Change the string value of an sqlite3_value object
*/
void sqlite3ValueSetStr(
  sqlite3_value *v,     /* Value to be set */







>
>
>
>
>
>
>
|
<
|



|
|
|
<
<
<
<
<

|
|
|
|
|
|
>
>







 







|







 







|







|







 








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

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


<
>
>






|
>
>
>
>
>
>






>
>
|
|
>






|
>
>
|
|
|
|
|
|
|
>




|
>
|
>


>




>
>
>
>
>












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







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
....
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
....
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
....
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241

1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316


































1317
1318
1319
1320
1321
1322
1323
    p->flags = MEM_Null;
    p->type = SQLITE_NULL;
    p->db = db;
  }
  return p;
}

/*
** Argument pCtx is actually a pointer to a database handle. Allocate and
** return an sqlite3_value object associated with this database handle.
**
** This function used as the xAlloc callback for valueFromExpr() when
** it is called by sqlite3ValueFromExpr().
*/
static sqlite3_value *valueNew(void *pCtx){

  return sqlite3ValueNew((sqlite3*)pCtx);
}

/*
** This function is the same as sqlite3ValueFromExpr(), except that instead
** of allocating any required sqlite3_value object by calling 
** sqlite3ValueNew(), it does so by calling the supplied xAlloc hook. 





*/
int valueFromExpr(
  sqlite3 *db,                         /* The database connection */
  Expr *pExpr,                         /* The expression to evaluate */
  u8 enc,                              /* Encoding to use */
  u8 affinity,                         /* Affinity to use */
  sqlite3_value **ppVal,               /* Write the new value here */
  sqlite3_value *(*xAlloc)(void*),     /* Used to allocate new sqlite3_value */
  void *pAlloc                         /* Argument passed to xAlloc */
){
  int op;
  char *zVal = 0;
  sqlite3_value *pVal = 0;
  int negInt = 1;
  const char *zNeg = "";

................................................................................
    pExpr = pExpr->pLeft;
    op = pExpr->op;
    negInt = -1;
    zNeg = "-";
  }

  if( op==TK_STRING || op==TK_FLOAT || op==TK_INTEGER ){
    pVal = xAlloc(pAlloc);
    if( pVal==0 ) goto no_mem;
    if( ExprHasProperty(pExpr, EP_IntValue) ){
      sqlite3VdbeMemSetInt64(pVal, (i64)pExpr->u.iValue*negInt);
    }else{
      zVal = sqlite3MPrintf(db, "%s%s", zNeg, pExpr->u.zToken);
      if( zVal==0 ) goto no_mem;
      sqlite3ValueSetStr(pVal, -1, zVal, SQLITE_UTF8, SQLITE_DYNAMIC);
................................................................................
      }else{
        pVal->u.i = -pVal->u.i;
      }
      pVal->r = -pVal->r;
      sqlite3ValueApplyAffinity(pVal, affinity, enc);
    }
  }else if( op==TK_NULL ){
    pVal = xAlloc(pAlloc);
    if( pVal==0 ) goto no_mem;
  }
#ifndef SQLITE_OMIT_BLOB_LITERAL
  else if( op==TK_BLOB ){
    int nVal;
    assert( pExpr->u.zToken[0]=='x' || pExpr->u.zToken[0]=='X' );
    assert( pExpr->u.zToken[1]=='\'' );
    pVal = xAlloc(pAlloc);
    if( !pVal ) goto no_mem;
    zVal = &pExpr->u.zToken[2];
    nVal = sqlite3Strlen30(zVal)-1;
    assert( zVal[nVal]=='\'' );
    sqlite3VdbeMemSetStr(pVal, sqlite3HexToBlob(db, zVal, nVal), nVal/2,
                         0, SQLITE_DYNAMIC);
  }
................................................................................
no_mem:
  db->mallocFailed = 1;
  sqlite3DbFree(db, zVal);
  if( *ppVal==0 ) sqlite3ValueFree(pVal);
  *ppVal = 0;
  return SQLITE_NOMEM;
}

/*
** Create a new sqlite3_value object, containing the value of pExpr.
**
** This only works for very simple expressions that consist of one constant
** token (i.e. "5", "5.1", "'a string'"). If the expression can
** be converted directly into a value, then the value is allocated and
** a pointer written to *ppVal. The caller is responsible for deallocating
** the value by passing it to sqlite3ValueFree() later on. If the expression
** cannot be converted to a value, then *ppVal is set to NULL.
*/
int sqlite3ValueFromExpr(
  sqlite3 *db,              /* The database connection */
  Expr *pExpr,              /* The expression to evaluate */
  u8 enc,                   /* Encoding to use */
  u8 affinity,              /* Affinity to use */
  sqlite3_value **ppVal     /* Write the new value here */
){
  return valueFromExpr(db, pExpr, enc, affinity, ppVal, valueNew, (void*)db);
}

#ifdef SQLITE_ENABLE_STAT4
/*
** A pointer to an instance of this object is passed as the context 
** pointer to valueNewStat4() (see below.
*/
struct ValueNewStat4Ctx {
  Parse *pParse;
  Index *pIdx;
  UnpackedRecord **ppRec;
  int iVal;
};

/*
** This function is used as the xAlloc function with valueFromExpr() when
** it is called by sqlite3Stat4ProbeSetValue(). The argument points to
** an object of type ValueNewStat4Ctx (see above).
**
** If it has not already been allocated, this function allocates an 
** UnpackedRecord structure and space for up to N values, where N is the
** number of columns in the index being probed.
*/
static sqlite3_value *valueNewStat4(void *pCtx){
  struct ValueNewStat4Ctx *p = (struct ValueNewStat4Ctx*)pCtx;
  UnpackedRecord *pRec = p->ppRec[0];

  if( pRec==0 ){
    sqlite3 *db = p->pParse->db;  /* Database handle */
    Index *pIdx = p->pIdx;        /* Index being probed */
    int nByte;                    /* Bytes of space to allocate */
    int i;                        /* Counter variable */

    nByte = sizeof(Mem) * pIdx->nColumn + sizeof(UnpackedRecord);
    pRec = (UnpackedRecord*)sqlite3DbMallocZero(db, nByte);
    if( pRec ){
      pRec->pKeyInfo = sqlite3IndexKeyinfo(p->pParse, pIdx);
      if( pRec->pKeyInfo ){
        pRec->pKeyInfo->enc = ENC(db);
        pRec->flags = UNPACKED_PREFIX_MATCH;
        pRec->aMem = (Mem *)&pRec[1];
        for(i=0; i<pIdx->nColumn; i++){
          pRec->aMem[i].flags = MEM_Null;
          pRec->aMem[i].type = SQLITE_NULL;
          pRec->aMem[i].db = db;
        }
      }else{
        sqlite3DbFree(db, pRec);
        pRec = 0;
      }
    }
    if( pRec==0 ) return 0;
    p->ppRec[0] = pRec;
  }

  pRec->nField = p->iVal+1;
  return &pRec->aMem[p->iVal];
}

/*
** This function is used to allocate and populate UnpackedRecord 
** structures intended to be compared against sample index keys stored 
** in the sqlite_stat4 table.
**
** A single call to this function attempts to populates field iVal (leftmost 
** is 0 etc.) of the unpacked record with a value extracted from expression
** pExpr. Extraction of values is possible if:
**
**  * (pExpr==0). In this case the value is assumed to be an SQL NULL,
**
**  * The expression is a bound variable, and this is a reprepare, or
**
**  * The sqlite3ValueFromExpr() function is able to extract a value 
**    from the expression (i.e. the expression is a literal value).
**
** If a value can be extracted, the affinity passed as the 5th argument
** is applied to it before it is copied into the UnpackedRecord. Output
** parameter *pbOk is set to true if a value is extracted, or false 
** otherwise.
**
** When this function is called, *ppRec must either point to an object
** allocated by an earlier call to this function, or must be NULL. If it
** is NULL and a value can be successfully extracted, a new UnpackedRecord
** is allocated (and *ppRec set to point to it) before returning.
**
** Unless an error is encountered, SQLITE_OK is returned. It is not an
** error if a value cannot be extracted from pExpr. If an error does
** occur, an SQLite error code is returned.
*/
int sqlite3Stat4ProbeSetValue(
  Parse *pParse,                  /* Parse context */

  Index *pIdx,                    /* Index being probed */
  UnpackedRecord **ppRec,         /* IN/OUT: Probe record */
  Expr *pExpr,                    /* The expression to extract a value from */
  u8 affinity,                    /* Affinity to use */
  int iVal,                       /* Array element to populate */
  int *pbOk                       /* OUT: True if value was extracted */
){
  int rc = SQLITE_OK;
  sqlite3_value *pVal = 0;

  struct ValueNewStat4Ctx alloc;
  alloc.pParse = pParse;
  alloc.pIdx = pIdx;
  alloc.ppRec = ppRec;
  alloc.iVal = iVal;

#if 0
  if( iVal>0 ){ *pbOk = 0; return SQLITE_OK; }
#endif

  if( !pExpr ){
    pVal = valueNewStat4((void*)&alloc);
    if( pVal ){
      sqlite3VdbeMemSetNull((Mem*)pVal);
      *pbOk = 1;
    }
  }else if( pExpr->op==TK_VARIABLE
        || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE)
  ){
    Vdbe *v;
    int iVar = pExpr->iColumn;
    sqlite3VdbeSetVarmask(pParse->pVdbe, iVar);
    if( (v = pParse->pReprepare) ){
      pVal = valueNewStat4((void*)&alloc);
      if( pVal ){
        rc = sqlite3VdbeMemCopy((Mem*)pVal, &v->aVar[iVal-1]);
        if( rc==SQLITE_OK ){
          sqlite3ValueApplyAffinity(pVal, affinity, SQLITE_UTF8);
        }
        pVal->db = pParse->db;
        *pbOk = 1;
        sqlite3VdbeMemStoreType((Mem*)pVal);
      }
    }else{
      *pbOk = 0;
    }
  }else{
    sqlite3 *db = pParse->db;
    rc = valueFromExpr(
        db, pExpr, ENC(db), affinity, &pVal, valueNewStat4, (void*)&alloc
    );
    *pbOk = (pVal!=0);
  }

  assert( pVal==0 || pVal->db==pParse->db );
  return rc;
}

/*
** Unless it is NULL, the argument must be an UnpackedRecord object returned
** by an earlier call to sqlite3Stat4ProbeSetValue(). This call deletes
** the object.
*/
void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
  if( pRec ){
    int i;
    Mem *aMem = pRec->aMem;
    sqlite3 *db = aMem[0].db;
    for(i=0; i<pRec->pKeyInfo->nField; i++){
      sqlite3DbFree(db, aMem[i].zMalloc);
    }
    sqlite3DbFree(db, pRec->pKeyInfo);
    sqlite3DbFree(db, pRec);
  }
}


































#endif /* ifdef SQLITE_ENABLE_STAT4 */

/*
** Change the string value of an sqlite3_value object
*/
void sqlite3ValueSetStr(
  sqlite3_value *v,     /* Value to be set */

Changes to src/where.c.

2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540
2541
2542
2543
2544
2545
2546
2547
2548
2549

2550
2551
2552
2553
2554
2555
2556
....
2625
2626
2627
2628
2629
2630
2631
2632

2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
....
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
    tRowcnt iUpper = p->aiRowEst[0];
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
    if( pLower ){
      int bOk;                    /* True if value is extracted from pExpr */
      Expr *pExpr = pLower->pExpr->pRight;
      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
      rc = sqlite3Stat4ProbeSetValue(pParse, pRec, pExpr, aff, nEq, &bOk);
      pRec->nField = nEq+1;
      if( rc==SQLITE_OK && bOk
       && whereKeyStats(pParse, p, pRec, 0, a)==SQLITE_OK
      ){
        iLower = a[0];
        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
      }
    }
    if( rc==SQLITE_OK && pUpper ){
      int bOk;                    /* True if value is extracted from pExpr */
      Expr *pExpr = pUpper->pExpr->pRight;
      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
      rc = sqlite3Stat4ProbeSetValue(pParse, pRec, pExpr, aff, nEq, &bOk);
      pRec->nField = nEq+1;
      if( rc==SQLITE_OK && bOk
       && whereKeyStats(pParse, p, pRec, 1, a)==SQLITE_OK
      ){
        iUpper = a[0];
        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
      }
    }

    if( rc==SQLITE_OK ){
      WhereCost iBase = whereCost(p->aiRowEst[0]);
      if( iUpper>iLower ){
        iBase -= whereCost(iUpper - iLower);
      }
      if( pBuilder->nMaxRowcnt && iBase<pBuilder->nMaxRowcnt ){
        *pRangeDiv = pBuilder->nMaxRowcnt;
................................................................................

  if( nEq>p->nColumn ){
    *pnRow = 1;
    return SQLITE_OK;
  }

  aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  rc = sqlite3Stat4ProbeSetValue(pParse, pRec, pExpr, aff, nEq-1, &bOk);

  if( rc!=SQLITE_OK ) return rc;
  if( bOk==0 ) return SQLITE_NOTFOUND;

  pBuilder->nRecValid = nEq;
  pRec->nField = nEq;

  rc = whereKeyStats(pParse, p, pRec, 0, a);
  if( rc==SQLITE_OK ){
    WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
    *pnRow = a[1];
    if( pBuilder->nMaxRowcnt && *pnRow>pBuilder->nMaxRowcnt ){
      *pnRow = pBuilder->nMaxRowcnt;
................................................................................
          pNew->rRun = rSize + rLogSize;
        }
        rc = whereLoopInsert(pBuilder, pNew);
        if( rc ) break;
      }
    }

#ifdef SQLITE_ENABLE_STAT4
    assert( pBuilder->pRec==0 );
    rc = sqlite3Stat4ProbeNew(pWInfo->pParse, pProbe, &pBuilder->pRec);
    if( rc==SQLITE_OK ){
#endif
      rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
#ifdef SQLITE_ENABLE_STAT4
      sqlite3Stat4ProbeFree(pBuilder->pRec);
      pBuilder->nRecValid = 0;
      pBuilder->pRec = 0;
    }
    assert( pBuilder->pRec==0 );
#endif

    /* If there was an INDEXED BY clause, then only that one index is
    ** considered. */
    if( pSrc->pIndex ) break;
  }
  return rc;







|
<











|
<







>







 







|
>


<

<







 







<
<
<
<
<
|

|
|
|
<
<







2521
2522
2523
2524
2525
2526
2527
2528

2529
2530
2531
2532
2533
2534
2535
2536
2537
2538
2539
2540

2541
2542
2543
2544
2545
2546
2547
2548
2549
2550
2551
2552
2553
2554
2555
....
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634

2635

2636
2637
2638
2639
2640
2641
2642
....
4569
4570
4571
4572
4573
4574
4575





4576
4577
4578
4579
4580


4581
4582
4583
4584
4585
4586
4587
    tRowcnt iUpper = p->aiRowEst[0];
    tRowcnt a[2];
    u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity;
    if( pLower ){
      int bOk;                    /* True if value is extracted from pExpr */
      Expr *pExpr = pLower->pExpr->pRight;
      assert( (pLower->eOperator & (WO_GT|WO_GE))!=0 );
      rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);

      if( rc==SQLITE_OK && bOk
       && whereKeyStats(pParse, p, pRec, 0, a)==SQLITE_OK
      ){
        iLower = a[0];
        if( (pLower->eOperator & WO_GT)!=0 ) iLower += a[1];
      }
    }
    if( rc==SQLITE_OK && pUpper ){
      int bOk;                    /* True if value is extracted from pExpr */
      Expr *pExpr = pUpper->pExpr->pRight;
      assert( (pUpper->eOperator & (WO_LT|WO_LE))!=0 );
      rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq, &bOk);

      if( rc==SQLITE_OK && bOk
       && whereKeyStats(pParse, p, pRec, 1, a)==SQLITE_OK
      ){
        iUpper = a[0];
        if( (pUpper->eOperator & WO_LE)!=0 ) iUpper += a[1];
      }
    }
    pBuilder->pRec = pRec;
    if( rc==SQLITE_OK ){
      WhereCost iBase = whereCost(p->aiRowEst[0]);
      if( iUpper>iLower ){
        iBase -= whereCost(iUpper - iLower);
      }
      if( pBuilder->nMaxRowcnt && iBase<pBuilder->nMaxRowcnt ){
        *pRangeDiv = pBuilder->nMaxRowcnt;
................................................................................

  if( nEq>p->nColumn ){
    *pnRow = 1;
    return SQLITE_OK;
  }

  aff = p->pTable->aCol[p->aiColumn[0]].affinity;
  rc = sqlite3Stat4ProbeSetValue(pParse, p, &pRec, pExpr, aff, nEq-1, &bOk);
  pBuilder->pRec = pRec;
  if( rc!=SQLITE_OK ) return rc;
  if( bOk==0 ) return SQLITE_NOTFOUND;

  pBuilder->nRecValid = nEq;


  rc = whereKeyStats(pParse, p, pRec, 0, a);
  if( rc==SQLITE_OK ){
    WHERETRACE(0x100,("equality scan regions: %d\n", (int)a[1]));
    *pnRow = a[1];
    if( pBuilder->nMaxRowcnt && *pnRow>pBuilder->nMaxRowcnt ){
      *pnRow = pBuilder->nMaxRowcnt;
................................................................................
          pNew->rRun = rSize + rLogSize;
        }
        rc = whereLoopInsert(pBuilder, pNew);
        if( rc ) break;
      }
    }






    rc = whereLoopAddBtreeIndex(pBuilder, pSrc, pProbe, 0);
#ifdef SQLITE_ENABLE_STAT4
    sqlite3Stat4ProbeFree(pBuilder->pRec);
    pBuilder->nRecValid = 0;
    pBuilder->pRec = 0;


#endif

    /* If there was an INDEXED BY clause, then only that one index is
    ** considered. */
    if( pSrc->pIndex ) break;
  }
  return rc;