Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fixes for SQLITE4_ENABLE_STAT3 builds. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
d5d0e93a57390c343fe9cdf4c6eb88c9 |
User & Date: | dan 2013-06-22 19:57:26.884 |
Context
2013-06-24
| ||
19:03 | Fixes for the sqlite_stat3 related ANALYZE functionality. check-in: f93e75f2b1 user: dan tags: trunk | |
2013-06-22
| ||
19:57 | Fixes for SQLITE4_ENABLE_STAT3 builds. check-in: d5d0e93a57 user: dan tags: trunk | |
2013-06-17
| ||
20:15 | Modifications to make the ANALYZE command work (sqlite_stat1 only). check-in: 7d8efac62f user: dan tags: trunk | |
Changes
Changes to src/analyze.c.
︙ | ︙ | |||
171 172 173 174 175 176 177 | ** Recommended number of samples for sqlite_stat3 */ #ifndef SQLITE4_STAT3_SAMPLES # define SQLITE4_STAT3_SAMPLES 24 #endif /* | | | > > > > > > > > > > | | | < | | > | | 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 | ** Recommended number of samples for sqlite_stat3 */ #ifndef SQLITE4_STAT3_SAMPLES # define SQLITE4_STAT3_SAMPLES 24 #endif /* ** Three SQL functions - stat3_init(), stat3_push(), and stat3_get() - ** share an instance of the following structure to hold their state ** information. */ typedef struct Stat3Accum Stat3Accum; struct Stat3Accum { tRowcnt nRow; /* Number of rows in the entire table */ tRowcnt nPSample; /* How often to do a periodic sample */ int iMin; /* Index of entry with minimum nEq and hash */ int mxSample; /* Maximum number of samples to accumulate */ int nSample; /* Current number of samples */ u32 iPrn; /* Pseudo-random number used for sampling */ struct Stat3Sample { void *pKey; /* Index key for this sample */ int nKey; /* Bytes of pKey in use */ int nAlloc; /* Bytes of space allocated at pKey */ tRowcnt nEq; /* sqlite_stat3.nEq */ tRowcnt nLt; /* sqlite_stat3.nLt */ tRowcnt nDLt; /* sqlite_stat3.nDLt */ u8 isPSample; /* True if a periodic sample */ u32 iHash; /* Tiebreaker hash */ } *a; /* An array of samples */ }; #ifdef SQLITE4_ENABLE_STAT3 static void delStat3Accum(void *pCtx, void *p){ sqlite4 *db = (sqlite4*)pCtx; sqlite4DbFree(db, p); } /* ** Implementation of the stat3_init(C,S) SQL function. The two parameters ** are the number of rows in the table or index (C) and the number of samples ** to accumulate (S). ** ** This routine allocates the Stat3Accum object. ** ** The return value is the Stat3Accum object (P). */ static void stat3Init( sqlite4_context *context, int argc, sqlite4_value **argv ){ sqlite4 *db = sqlite4_context_db_handle(context); Stat3Accum *p; tRowcnt nRow; int mxSample; int n; UNUSED_PARAMETER(argc); nRow = (tRowcnt)sqlite4_value_int64(argv[0]); mxSample = sqlite4_value_int(argv[1]); n = sizeof(*p) + sizeof(p->a[0])*mxSample; p = (Stat3Accum *)sqlite4DbMallocZero(db, n); if( p==0 ){ sqlite4_result_error_nomem(context); return; } p->a = (struct Stat3Sample*)&p[1]; p->nRow = nRow; p->mxSample = mxSample; p->nPSample = p->nRow/(mxSample/3+1) + 1; sqlite4_randomness(sqlite4_db_env(db), sizeof(p->iPrn), &p->iPrn); sqlite4_result_blob(context, p, sizeof(p), delStat3Accum, (void*)db); } static const FuncDef stat3InitFuncdef = { 2, /* nArg */ 0, /* flags */ 0, /* pUserData */ 0, /* pNext */ stat3Init, /* xFunc */ 0, /* xStep */ 0, /* xFinalize */ "stat3_init", /* zName */ 0, /* pHash */ 0 /* pDestructor */ }; /* ** Implementation of the stat3_push(nEq,nLt,nDLt,idxkey,P) SQL function. The ** arguments describe a single key instance. This routine makes the ** decision about whether or not to retain this key for the sqlite_stat3 ** table. ** ** The return value is NULL. */ static void stat3Push( sqlite4_context *context, int argc, sqlite4_value **argv ){ Stat3Accum *p = (Stat3Accum*)sqlite4_value_blob(argv[4], 0); tRowcnt nEq = sqlite4_value_int64(argv[0]); tRowcnt nLt = sqlite4_value_int64(argv[1]); tRowcnt nDLt = sqlite4_value_int64(argv[2]); const void *pKey; int nKey; u8 isPSample = 0; u8 doInsert = 0; int iMin = p->iMin; struct Stat3Sample *pSample; int i; u32 h; |
︙ | ︙ | |||
290 291 292 293 294 295 296 | if( p->nSample==p->mxSample ){ assert( p->nSample - iMin - 1 >= 0 ); memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1)); pSample = &p->a[p->nSample-1]; }else{ pSample = &p->a[p->nSample++]; } | > > > > > > > > > > | | 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 | if( p->nSample==p->mxSample ){ assert( p->nSample - iMin - 1 >= 0 ); memmove(&p->a[iMin], &p->a[iMin+1], sizeof(p->a[0])*(p->nSample-iMin-1)); pSample = &p->a[p->nSample-1]; }else{ pSample = &p->a[p->nSample++]; } pKey = sqlite4_value_blob(argv[3], &nKey); if( nKey>pSample->nAlloc ){ sqlite4 *db = sqlite4_context_db_handle(context); int nReq = nKey*4; pSample->pKey = sqlite4DbReallocOrFree(db, pSample->pKey, nReq); if( pSample->pKey==0 ) return; pSample->nAlloc = nReq; } memcpy(pSample->pKey, pKey, nKey); pSample->nKey = nKey; pSample->nEq = nEq; pSample->nLt = nLt; pSample->nDLt = nDLt; pSample->iHash = h; pSample->isPSample = isPSample; /* Find the new minimum */ |
︙ | ︙ | |||
324 325 326 327 328 329 330 | } } p->iMin = iMin; } } static const FuncDef stat3PushFuncdef = { 5, /* nArg */ | < > > | | | | | < | | | > > > > > > > < | | 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 | } } p->iMin = iMin; } } static const FuncDef stat3PushFuncdef = { 5, /* nArg */ 0, /* flags */ 0, /* pUserData */ 0, /* pNext */ stat3Push, /* xFunc */ 0, /* xStep */ 0, /* xFinalize */ "stat3_push", /* zName */ 0, /* pHash */ 0 /* pDestructor */ }; /* ** Implementation of the stat3_get(P,N,...) SQL function. This routine is ** used to query the results. Content is returned for the Nth sqlite_stat3 ** row where N is between 0 and S-1 and S is the number of samples. The ** value returned depends on the number of arguments. ** ** CREATE TABLE sqlite_stat3(tbl, idx, nEq, nLt, nDLt, sample); ** argc==2 result: nEq ** argc==3 result: nLt ** argc==4 result: nDLt ** argc==5 result: sample */ static void stat3Get( sqlite4_context *context, int argc, sqlite4_value **argv ){ int n = sqlite4_value_int(argv[1]); Stat3Accum *p = (Stat3Accum*)sqlite4_value_blob(argv[0], 0); assert( p!=0 ); if( p->nSample<=n ) return; switch( argc ){ case 2: sqlite4_result_int64(context, p->a[n].nEq); break; case 3: sqlite4_result_int64(context, p->a[n].nLt); break; case 4: sqlite4_result_int64(context, p->a[n].nDLt); break; default: { assert( argc==5 ); sqlite4_result_blob( context, p->a[n].pKey, p->a[n].nKey, SQLITE4_TRANSIENT, 0 ); break; } } } static const FuncDef stat3GetFuncdef = { -1, /* nArg */ 0, /* flags */ 0, /* pUserData */ 0, /* pNext */ stat3Get, /* xFunc */ 0, /* xStep */ 0, /* xFinalize */ "stat3_get", /* zName */ 0, /* pHash */ 0 /* pDestructor */ }; #endif /* SQLITE4_ENABLE_STAT3 */ |
︙ | ︙ | |||
410 411 412 413 414 415 416 | int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* The stat column of sqlite_stat1 */ #ifdef SQLITE4_ENABLE_STAT3 int regNumEq = regStat1; /* Number of instances. Same as regStat1 */ int regNumLt = iMem++; /* Number of keys less than regSample */ int regNumDLt = iMem++; /* Number of distinct keys less than regSample */ int regSample = iMem++; /* The next sample value */ | < < > < | 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 | int regIdxname = iMem++; /* Register containing index name */ int regStat1 = iMem++; /* The stat column of sqlite_stat1 */ #ifdef SQLITE4_ENABLE_STAT3 int regNumEq = regStat1; /* Number of instances. Same as regStat1 */ int regNumLt = iMem++; /* Number of keys less than regSample */ int regNumDLt = iMem++; /* Number of distinct keys less than regSample */ int regSample = iMem++; /* The next sample value */ int regAccum = iMem++; /* Register to hold Stat3Accum object */ int regLoop = iMem++; /* Loop counter */ int regCount = iMem++; /* Number of rows in the table or index */ int regTemp1 = iMem++; /* Intermediate register */ int regTemp2 = iMem++; /* Intermediate register */ int once = 1; /* One-time initialization */ int iTabCur = pParse->nTab++; /* Table cursor */ int addrEq; #endif int regRec = iMem++; /* Register holding completed record */ int regTemp = iMem++; /* Temporary use register */ int regNewRowid = iMem++; /* Rowid for the inserted record */ v = sqlite4GetVdbe(pParse); if( v==0 || NEVER(pTab==0) ){ return; |
︙ | ︙ | |||
451 452 453 454 455 456 457 | #endif iIdxCur = pParse->nTab++; sqlite4VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int nCol; KeyInfo *pKey; | < < > > > > | 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 | #endif iIdxCur = pParse->nTab++; sqlite4VdbeAddOp4(v, OP_String8, 0, regTabname, 0, pTab->zName, 0); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ int nCol; KeyInfo *pKey; int *aChngAddr; /* Array of jump instruction addresses */ int regCnt; /* Total number of rows in table. */ int regPrev; /* Previous index key read from database */ int aregCard; /* Cardinality array registers */ #ifdef SQLITE4_ENABLE_STAT3 int addrAddimm; /* Address at top of stat3 output loop */ int addrIsnull; /* Another address within the stat3 loop */ #endif if( pOnlyIdx && pOnlyIdx!=pIdx ) continue; VdbeNoopComment((v, "Begin analysis of %s", pIdx->zName)); nCol = pIdx->nColumn; aChngAddr = sqlite4DbMallocRaw(db, sizeof(int)*nCol); if( aChngAddr==0 ) continue; pKey = sqlite4IndexKeyinfo(pParse, pIdx); |
︙ | ︙ | |||
482 483 484 485 486 487 488 | sqlite4VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); #ifdef SQLITE4_ENABLE_STAT3 if( once ){ once = 0; sqlite4OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); } | | | | | | > > > > | 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 | sqlite4VdbeAddOp4(v, OP_String8, 0, regIdxname, 0, pIdx->zName, 0); #ifdef SQLITE4_ENABLE_STAT3 if( once ){ once = 0; sqlite4OpenTable(pParse, iTabCur, iDb, pTab, OP_OpenRead); } sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumEq); sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumLt); sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumDLt); assert( regAccum==regSample+1 ); sqlite4VdbeAddOp3(v, OP_Null, 0, regSample, regAccum); assert( regTemp1==regCount+1 ); sqlite4VdbeAddOp2(v, OP_Count, iIdxCur, regCount); sqlite4VdbeAddOp2(v, OP_Integer, SQLITE4_STAT3_SAMPLES, regTemp1); sqlite4VdbeAddOp4(v, OP_Function, 1, regCount, regAccum, (char*)&stat3InitFuncdef, P4_FUNCDEF); sqlite4VdbeChangeP5(v, 2); #endif /* SQLITE4_ENABLE_STAT3 */ /* The block of memory cells initialized here is used as follows. ** |
︙ | ︙ | |||
513 514 515 516 517 518 519 | regCnt = iMem; regPrev = iMem+1; aregCard = iMem+2; sqlite4VdbeAddOp2(v, OP_Integer, 0, regCnt); sqlite4VdbeAddOp2(v, OP_Null, 0, regPrev); for(i=0; i<nCol; i++){ | | < < < < < < < < < < < < < < < < < < | < < > | > | < | > > | > | < | | > | < | | | < < | < < < > > > > > > < | > | | | > | < < < < < < < < < < < < | | | | 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | regCnt = iMem; regPrev = iMem+1; aregCard = iMem+2; sqlite4VdbeAddOp2(v, OP_Integer, 0, regCnt); sqlite4VdbeAddOp2(v, OP_Null, 0, regPrev); for(i=0; i<nCol; i++){ sqlite4VdbeAddOp2(v, OP_Integer, 0, aregCard+i); } /* Start the analysis loop. This loop runs through all the entries in ** the index b-tree. */ endOfLoop = sqlite4VdbeMakeLabel(v); sqlite4VdbeAddOp2(v, OP_Rewind, iIdxCur, endOfLoop); topOfLoop = sqlite4VdbeCurrentAddr(v); sqlite4VdbeAddOp2(v, OP_AddImm, regCnt, 1); /* Increment row counter */ #ifdef SQLITE4_ENABLE_STAT3 sqlite4VdbeAddOp2(v, OP_Copy, aregCard, regTemp1); #endif sqlite4VdbeAddOp4Int(v, OP_AnalyzeKey, iIdxCur, regPrev, aregCard, nCol); #ifdef SQLITE4_ENABLE_STAT3 sqlite4VdbeAddOp2(v, OP_AddImm, regNumEq, 1); addrEq = sqlite4VdbeAddOp3(v, OP_Eq, aregCard, 0,regTemp1); assert( regNumEq==regNumLt-1 && regNumEq==regNumDLt-2 && regNumEq==regSample-3 && regNumEq==regAccum-4 ); sqlite4VdbeAddOp2(v, OP_RowKey, iIdxCur, regSample); sqlite4VdbeChangeP5(v, 1); sqlite4VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2, (char*)&stat3PushFuncdef, P4_FUNCDEF ); sqlite4VdbeChangeP5(v, 5); sqlite4VdbeAddOp3(v, OP_Add, regNumEq, regNumLt, regNumLt); sqlite4VdbeAddOp2(v, OP_AddImm, regNumDLt, 1); sqlite4VdbeAddOp2(v, OP_Integer, 0, regNumEq); sqlite4VdbeJumpHere(v, addrEq); #endif /* Always jump here after updating the iMem+1...iMem+1+nCol counters */ sqlite4VdbeResolveLabel(v, endOfLoop); sqlite4VdbeAddOp2(v, OP_Next, iIdxCur, topOfLoop); sqlite4VdbeAddOp1(v, OP_Close, iIdxCur); #ifdef SQLITE4_ENABLE_STAT3 /* Push the last record (if any) to the accumulator. */ sqlite4VdbeAddOp4(v, OP_Function, 1, regNumEq, regTemp2, (char*)&stat3PushFuncdef, P4_FUNCDEF); sqlite4VdbeChangeP5(v, 5); /* This block codes a loop that iterates through all entries stored ** by the accumulator (the Stat3Accum object). */ sqlite4VdbeAddOp2(v, OP_Integer, -1, regLoop); addrAddimm = sqlite4VdbeAddOp2(v, OP_AddImm, regLoop, 1); for(i=0; i<4; i++){ sqlite4VdbeAddOp3(v, OP_Function, 1, regAccum, regNumEq+i); sqlite4VdbeChangeP4(v, -1, (char*)&stat3GetFuncdef, P4_FUNCDEF); sqlite4VdbeChangeP5(v, i+2); } addrIsnull = sqlite4VdbeAddOp1(v, OP_IsNull, regNumEq); sqlite4VdbeAddOp4(v, OP_MakeRecord, regTabname, 6, regRec, "bbbbbb", 0); sqlite4VdbeAddOp2(v, OP_NewRowid, iStatCur+1, regNewRowid); sqlite4VdbeAddOp3(v, OP_Insert, iStatCur+1, regRec, regNewRowid); sqlite4VdbeAddOp2(v, OP_Goto, 0, addrAddimm); sqlite4VdbeJumpHere(v, addrIsnull); #endif /* Store the results in sqlite_stat1. ** ** The result is a single row of the sqlite_stat1 table. The first ** two columns are the names of the table and index. The third column ** is a string composed of a list of integer statistics about the ** index. The first integer in the list is the total number of entries |
︙ | ︙ | |||
850 851 852 853 854 855 856 | /* ** If the Index.aSample variable is not NULL, delete the aSample[] array ** and its contents. */ void sqlite4DeleteIndexSamples(sqlite4 *db, Index *pIdx){ #ifdef SQLITE4_ENABLE_STAT3 | < < < < < < < < | < | 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 | /* ** If the Index.aSample variable is not NULL, delete the aSample[] array ** and its contents. */ void sqlite4DeleteIndexSamples(sqlite4 *db, Index *pIdx){ #ifdef SQLITE4_ENABLE_STAT3 sqlite4DbFree(db, pIdx->aSample); if( db && db->pnBytesFreed==0 ){ pIdx->nSample = 0; pIdx->aSample = 0; } #else UNUSED_PARAMETER(db); UNUSED_PARAMETER(pIdx); |
︙ | ︙ | |||
881 882 883 884 885 886 887 | */ static int loadStat3(sqlite4 *db, const char *zDb){ int rc; /* Result codes from subroutines */ sqlite4_stmt *pStmt = 0; /* An SQL statement being run */ char *zSql; /* Text of the SQL statement */ Index *pPrevIdx = 0; /* Previous index in the loop */ int idx = 0; /* slot in pIdx->aSample[] for next sample */ | < > | > > | > > | | > > | > < < < < < < | < < < < < < < < < < | < < < | < | < < < < < < < | < < < > | 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 | */ static int loadStat3(sqlite4 *db, const char *zDb){ int rc; /* Result codes from subroutines */ sqlite4_stmt *pStmt = 0; /* An SQL statement being run */ char *zSql; /* Text of the SQL statement */ Index *pPrevIdx = 0; /* Previous index in the loop */ int idx = 0; /* slot in pIdx->aSample[] for next sample */ IndexSample *pSample; /* A slot in pIdx->aSample[] */ u8 *pSpace; /* Space for copy of all samples */ assert( db->lookaside.bEnabled==0 ); if( !sqlite4FindTable(db, "sqlite_stat3", zDb) ){ return SQLITE4_OK; } zSql = sqlite4MPrintf(db, "SELECT idx, count(*), sum(length(sample)) FROM %Q.sqlite_stat3" " GROUP BY idx", zDb); if( !zSql ){ return SQLITE4_NOMEM; } rc = sqlite4_prepare(db, zSql, -1, &pStmt, 0); sqlite4DbFree(db, zSql); if( rc ) return rc; while( sqlite4_step(pStmt)==SQLITE4_ROW ){ char *zIndex; /* Index name */ Index *pIdx; /* Pointer to the index object */ int nSample; /* Number of samples */ int nSpace; /* Bytes of space required for all samples */ int nAlloc; /* Bytes of space to allocate */ zIndex = (char *)sqlite4_column_text(pStmt, 0, 0); if( zIndex==0 ) continue; nSample = sqlite4_column_int(pStmt, 1); nSpace = sqlite4_column_int(pStmt, 2); pIdx = sqlite4FindIndex(db, zIndex, zDb); if( pIdx==0 ) continue; assert( pIdx->nSample==0 ); nAlloc = nSample*sizeof(IndexSample) + nSpace; pIdx->nSample = nSample; pIdx->aSample = (IndexSample*)sqlite4DbMallocZero(db, nAlloc); pIdx->avgEq = pIdx->aiRowEst[1]; if( pIdx->aSample==0 ){ db->mallocFailed = 1; sqlite4_finalize(pStmt); return SQLITE4_NOMEM; } } rc = sqlite4_finalize(pStmt); if( rc ) return rc; zSql = sqlite4MPrintf(db, "SELECT idx,neq,nlt,ndlt,sample FROM %Q.sqlite_stat3", zDb); if( !zSql ){ return SQLITE4_NOMEM; } rc = sqlite4_prepare(db, zSql, -1, &pStmt, 0); sqlite4DbFree(db, zSql); if( rc ) return rc; while( sqlite4_step(pStmt)==SQLITE4_ROW && 0 ){ char *zIndex; /* Index name */ Index *pIdx; /* Pointer to the index object */ int i; /* Loop counter */ tRowcnt sumEq; /* Sum of the nEq values */ const u8 *aVal; int nVal; zIndex = (char *)sqlite4_column_text(pStmt, 0, 0); if( zIndex==0 ) continue; pIdx = sqlite4FindIndex(db, zIndex, zDb); if( pIdx==0 ) continue; if( pIdx==pPrevIdx ){ idx++; }else{ pPrevIdx = pIdx; idx = 0; pSpace = (u8*)&pIdx->aSample[pIdx->nSample]; } assert( idx<pIdx->nSample ); pSample = &pIdx->aSample[idx]; pSample->nEq = (tRowcnt)sqlite4_column_int64(pStmt, 1); pSample->nLt = (tRowcnt)sqlite4_column_int64(pStmt, 2); pSample->nDLt = (tRowcnt)sqlite4_column_int64(pStmt, 3); if( idx==pIdx->nSample-1 ){ if( pSample->nDLt>0 ){ for(i=0, sumEq=0; i<=idx-1; i++) sumEq += pIdx->aSample[i].nEq; pIdx->avgEq = (pSample->nLt - sumEq)/pSample->nDLt; } if( pIdx->avgEq<=0 ) pIdx->avgEq = 1; } aVal = sqlite4_column_blob(pStmt, 4, &nVal); pSample->aVal = pSpace; pSample->nVal = nVal; memcpy(pSample->aVal, aVal, nVal); pSpace += nVal; } return sqlite4_finalize(pStmt); } #endif /* SQLITE4_ENABLE_STAT3 */ /* ** Load the content of the sqlite_stat1 and sqlite_stat3 tables. The |
︙ | ︙ |
Changes to src/mem.c.
︙ | ︙ | |||
762 763 764 765 766 767 768 769 770 771 772 773 774 775 | rc = sqlite4_buffer_resize(pBuf, nOrig+n); if( rc==SQLITE4_OK ){ memcpy(&((u8 *)pBuf->p)[nOrig], p, n); } return rc; } void sqlite4_buffer_clear(sqlite4_buffer *pBuf){ sqlite4_mm_free(pBuf->pMM, pBuf->p); sqlite4_buffer_init(pBuf, pBuf->pMM); } | > > > > > > > > > | 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 | rc = sqlite4_buffer_resize(pBuf, nOrig+n); if( rc==SQLITE4_OK ){ memcpy(&((u8 *)pBuf->p)[nOrig], p, n); } return rc; } int sqlite4_buffer_set( sqlite4_buffer *pBuf, const void *p, sqlite4_size_t n ){ pBuf->n = 0; return sqlite4_buffer_append(pBuf, p, n); } void sqlite4_buffer_clear(sqlite4_buffer *pBuf){ sqlite4_mm_free(pBuf->pMM, pBuf->p); sqlite4_buffer_init(pBuf, pBuf->pMM); } |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
233 234 235 236 237 238 239 240 241 242 243 244 245 246 | sqlite4_size_t n; }; void sqlite4_buffer_init(sqlite4_buffer *, sqlite4_mm *); void sqlite4_buffer_clear(sqlite4_buffer *); int sqlite4_buffer_resize(sqlite4_buffer *, sqlite4_size_t); int sqlite4_buffer_append(sqlite4_buffer *, const void *, sqlite4_size_t); /* ** CAPIREF: Translate Text Encodings ** ** This API function is used to translate between utf-8 and utf-16 text ** encodings. ** | > | 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 | sqlite4_size_t n; }; void sqlite4_buffer_init(sqlite4_buffer *, sqlite4_mm *); void sqlite4_buffer_clear(sqlite4_buffer *); int sqlite4_buffer_resize(sqlite4_buffer *, sqlite4_size_t); int sqlite4_buffer_append(sqlite4_buffer *, const void *, sqlite4_size_t); int sqlite4_buffer_set(sqlite4_buffer *, const void *, sqlite4_size_t); /* ** CAPIREF: Translate Text Encodings ** ** This API function is used to translate between utf-8 and utf-16 text ** encodings. ** |
︙ | ︙ |
Changes to src/sqliteInt.h.
︙ | ︙ | |||
1401 1402 1403 1404 1405 1406 1407 | /* ** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the ** analyze.c source file for additional information. */ struct IndexSample { | < < < | < | < | 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 | /* ** Each sample stored in the sqlite_stat3 table is represented in memory ** using a structure of this type. See documentation at the top of the ** analyze.c source file for additional information. */ struct IndexSample { u8 *aVal; /* Pointer to index-key encoded value blob */ int nVal; /* Size of array aKey[] in bytes */ tRowcnt nEq; /* Est. number of rows where the key equals this sample */ tRowcnt nLt; /* Est. number of rows where key is less than this sample */ tRowcnt nDLt; /* Est. number of distinct keys less than this sample */ }; /* ** Each token coming out of the lexer is an instance of |
︙ | ︙ |
Changes to src/vdbe.c.
︙ | ︙ | |||
2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 | rc = sqlite4VdbeSeekEnd(pC, +1); nEntry = 0; while( rc!=SQLITE4_NOTFOUND ){ nEntry++; rc = sqlite4VdbeNext(pC); } sqlite4VdbeMemSetInt64(pOut, nEntry); break; } /* Opcode: Savepoint P1 * * P4 * ** ** This opcode is used to implement the SQL BEGIN, COMMIT, ROLLBACK, ** SAVEPOINT, RELEASE and ROLLBACK TO commands. As follows: | > | 2378 2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 | rc = sqlite4VdbeSeekEnd(pC, +1); nEntry = 0; while( rc!=SQLITE4_NOTFOUND ){ nEntry++; rc = sqlite4VdbeNext(pC); } sqlite4VdbeMemSetInt64(pOut, nEntry); if( rc==SQLITE4_NOTFOUND ) rc = SQLITE4_OK; break; } /* Opcode: Savepoint P1 * * P4 * ** ** This opcode is used to implement the SQL BEGIN, COMMIT, ROLLBACK, ** SAVEPOINT, RELEASE and ROLLBACK TO commands. As follows: |
︙ | ︙ | |||
3299 3300 3301 3302 3303 3304 3305 | if( rc==SQLITE4_OK ){ n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v); if( n==0 ) rc = SQLITE4_CORRUPT_BKPT; if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT; } if( rc==SQLITE4_OK ){ n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v); | | > > > > | 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 | if( rc==SQLITE4_OK ){ n = sqlite4GetVarint64((u8 *)aKey, nKey, (u64 *)&v); if( n==0 ) rc = SQLITE4_CORRUPT_BKPT; if( v!=pC->iRoot ) rc = SQLITE4_CORRUPT_BKPT; } if( rc==SQLITE4_OK ){ n = sqlite4VdbeDecodeIntKey(&aKey[n], nKey-n, &v); if( n==0 || v==LARGEST_INT64 ){ assert( 0 ); rc = SQLITE4_FULL; } } }else{ break; } #ifndef SQLITE_OMIT_AUTOINCREMENT if( pOp->p3 && rc==SQLITE4_OK ){ pIn3 = sqlite4RegisterInRootFrame(p, pOp->p3); assert( memIsValid(pIn3) ); REGISTER_TRACE(pOp->p3, pIn3); sqlite4VdbeMemIntegerify(pIn3); assert( (pIn3->flags & MEM_Int)!=0 ); /* mem(P3) holds an integer */ i3 = sqlite4_num_to_int64(pIn3->u.num, 0); if( i3==MAX_ROWID ){ rc = SQLITE4_FULL; assert( 0 ); } if( v<i3 ) v = i3; } #endif pOut->flags = MEM_Int; pOut->u.num = sqlite4_num_from_int64(v+1); break; |
︙ | ︙ | |||
3538 3539 3540 3541 3542 3543 3544 | ** There is no interpretation of the data. ** It is just copied onto the P2 register exactly as ** it is found in the database file. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. */ | | | < | | | > > > > > > > > > > > > > > > | | > > > < > > | > | | | | | | | | < < | 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 | ** There is no interpretation of the data. ** It is just copied onto the P2 register exactly as ** it is found in the database file. ** ** If the P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. */ /* Opcode: RowKey P1 P2 * * P5 ** ** Write into register P2 the complete row key for cursor P1. There is ** no interpretation of the data. The key is copied onto the P3 register ** exactly as it is found in the database file. ** ** The P1 cursor must be pointing to a valid row (not a NULL row) ** of a real table, not a pseudo-table. ** ** If P5 is non-zero, it is a flag indicating that this value will be ** stored as a sample in the sqlite_stat3 table. At present, this means ** that the table number is stripped from the start of the record, and ** then all but the initial field removed from the end. In other words, ** the blob copied into register P2 is the first field of the index-key ** only. */ case OP_SorterData: case OP_RowKey: case OP_RowData: { VdbeCursor *pC; KVCursor *pCrsr; const KVByteArray *pData; KVSize nData; int nVarint; u64 dummy; pOut = &aMem[pOp->p2]; memAboutToChange(p, pOut); /* Note that RowKey and RowData are really exactly the same instruction */ assert( pOp->p1>=0 && pOp->p1<p->nCursor ); pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->nullRow==0 ); assert( pC->pseudoTableReg==0 ); assert( pC->pKVCur!=0 ); pCrsr = pC->pKVCur; if( pOp->opcode==OP_RowKey ){ rc = sqlite4KVCursorKey(pCrsr, &pData, &nData); if( pOp->p5 ){ nData = sqlite4VdbeShortKey(pData, nData, 1, 0); nVarint = sqlite4GetVarint64(pData, nData, &dummy); pData += nVarint; nData -= nVarint; } }else{ rc = sqlite4KVCursorData(pCrsr, 0, -1, &pData, &nData); } if( rc==SQLITE4_OK && nData>db->aLimit[SQLITE4_LIMIT_LENGTH] ){ goto too_big; } sqlite4VdbeMemSetStr(pOut, (const char*)pData, nData, 0, SQLITE4_TRANSIENT,0); pOut->enc = SQLITE4_UTF8; /* In case the blob is ever cast to text */ UPDATE_MAX_BLOBSIZE(pOut); break; } /* Opcode: AnalyzeKey P1 P2 P3 P4 ** ** P1 is an open cursor that currently points to a valid row. P2 is a ** register that contains either a NULL value, or an index key. If it is ** not NULL, this opcode compares the key in register P2 with the key of ** the row P1 currently points to and determines the number of fields in ** the prefix that the two keys share in common (which may be zero). ** Call this value N. If P2 is NULL, set N to zero. ** ** P3 is the first in an array of P4 registers containing integer values. ** The first N of these are left as is by this instruction. The remaining ** (P4-N) are incremented. ** ** Finally, the key belonging to the current row of cursor P1 is copied ** into register P2. */ case OP_AnalyzeKey: { VdbeCursor *pC; const KVByteArray *pNew; KVSize nNew; Mem *pKey; Mem *aIncr; int nEq; int nTotal; int i; pKey = &aMem[pOp->p2]; aIncr = &aMem[pOp->p3]; nTotal = pOp->p4.i; pC = p->apCsr[pOp->p1]; assert( pC!=0 ); assert( pC->nullRow==0 ); assert( pC->pseudoTableReg==0 ); assert( pC->pKVCur!=0 ); assert( pOp->p4type==P4_INT32 ); rc = sqlite4KVCursorKey(pC->pKVCur, &pNew, &nNew); if( rc==SQLITE4_OK ){ assert( pKey->flags & (MEM_Blob|MEM_Null) ); if( pKey->flags & MEM_Blob ){ for(i=0; i<nNew && i<pKey->n && pNew[i]==(KVByteArray)pKey->z[i]; i++); /* The two keys share i bytes in common. Figure out how many fields ** this corresponds to. Store said value in variable nEq. */ sqlite4VdbeShortKey(pNew, i, LARGEST_INT32, &nEq); }else{ nEq = 0; } /* Increment nTotal-nEq registers */ for(i=nEq; i<nTotal; i++){ memAboutToChange(p, &aIncr[i]); sqlite4VdbeMemIntegerify(&aIncr[i]); aIncr[i].u.num = sqlite4_num_add( aIncr[i].u.num, sqlite4_num_from_int64(1) ); REGISTER_TRACE(pOp->p1, &aIncr[i]); } /* Copy the new key into register P2 */ memAboutToChange(p, pKey); sqlite4VdbeMemSetStr(pKey, (const char*)pNew, nNew, 0, SQLITE4_TRANSIENT,0); pKey->enc = SQLITE4_UTF8; UPDATE_MAX_BLOBSIZE(pKey); } break; } /* Opcode: Rowid P1 P2 * * * ** ** Store in register P2 an integer which is the key of the table entry that |
︙ | ︙ |
Changes to src/vdbecodec.c.
︙ | ︙ | |||
630 631 632 633 634 635 636 | ** be freed by the caller using sqlite4DbFree() to avoid a memory leak. */ int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ int nIn, /* Number of entries in aIn[] */ int nInTotal, /* Number of values in a complete key */ | | | 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 | ** be freed by the caller using sqlite4DbFree() to avoid a memory leak. */ int sqlite4VdbeEncodeKey( sqlite4 *db, /* The database connection */ Mem *aIn, /* Values to be encoded */ int nIn, /* Number of entries in aIn[] */ int nInTotal, /* Number of values in a complete key */ int iTabno, /* The table this key applies to, or negative */ KeyInfo *pKeyInfo, /* Collating sequence and sort-order info */ u8 **paOut, /* Write the resulting key here */ int *pnOut, /* Number of bytes in the key */ int nExtra /* extra bytes of space appended to the key */ ){ int i; int rc = SQLITE4_OK; |
︙ | ︙ | |||
653 654 655 656 657 658 659 | x.aOut = 0; x.nOut = 0; x.nAlloc = 0; *paOut = 0; *pnOut = 0; if( enlargeEncoderAllocation(&x, (nIn+1)*10) ) return SQLITE4_NOMEM; | > | > | 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 | x.aOut = 0; x.nOut = 0; x.nAlloc = 0; *paOut = 0; *pnOut = 0; if( enlargeEncoderAllocation(&x, (nIn+1)*10) ) return SQLITE4_NOMEM; if( iTabno>=0 ){ x.nOut = sqlite4PutVarint64(x.aOut, iTabno); } aColl = pKeyInfo->aColl; so = pKeyInfo->aSortOrder; for(i=0; i<nIn && rc==SQLITE4_OK; i++){ rc = encodeOneKeyValue(&x, aIn+i, so ? so[i] : SQLITE4_SO_ASC, i==nInTotal-1, aColl[i]); } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ #include "sqliteInt.h" /* ** Trace output macros */ #if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG) int sqlite4WhereTrace = 0; #endif | > > > | 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | ** generating the code that loops through a table looking for applicable ** rows. Indices are selected and used to speed the search when doing ** so is applicable. Because this module is responsible for selecting ** indices, you might also think of this module as the "query optimizer". */ #include "sqliteInt.h" /* For VdbeCodecEncodeKey() - revisit this */ #include "vdbeInt.h" /* ** Trace output macros */ #if defined(SQLITE4_TEST) || defined(SQLITE4_DEBUG) int sqlite4WhereTrace = 0; #endif |
︙ | ︙ | |||
2478 2479 2480 2481 2482 2483 2484 | ** aStat[1] Est. number of rows equal to pVal ** ** Return SQLITE4_OK on success. */ static int whereKeyStats( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ | | | < < > | < < < < < < < < < < < | < < | | < < < < | < | < < < < < < < < < | < < < | < < < < | < < < < < < < < < < < < < < < < < | < < < < < < < | < < | < < < < < < < < < < < < < < < < < < < | | | < < | 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 2518 2519 2520 2521 2522 2523 2524 | ** aStat[1] Est. number of rows equal to pVal ** ** Return SQLITE4_OK on success. */ static int whereKeyStats( Parse *pParse, /* Database connection */ Index *pIdx, /* Index to consider domain of */ sqlite4_buffer *pBuf, /* Buffer containing encoded value to consider */ int roundUp, /* Round up if true. Round down if false */ tRowcnt *aStat /* OUT: stats written here */ ){ tRowcnt n; IndexSample *aSample; int i; int isEq = 0; assert( roundUp==0 || roundUp==1 ); assert( pIdx->nSample>0 ); assert( pBuf->n>0 ); n = pIdx->aiRowEst[0]; aSample = pIdx->aSample; /* Set variable i to the index of the first sample equal to or larger ** than the value in pBuf. Set isEq to true if the value is equal, or ** false otherwise. */ for(i=0; i<pIdx->nSample; i++){ int res; int n = pBuf->n; if( n>aSample[i].nVal ) n = aSample[i].nVal; res = memcmp(pBuf->p, aSample[i].aVal, n); if( res==0 ) res = pBuf->n - aSample[i].nVal; if( res>=0 ){ isEq = (res==0); break; } } /* At this point, aSample[i] is the first sample that is greater than ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less ** than pVal. If aSample[i]==pVal, then isEq==1. */ |
︙ | ︙ | |||
2628 2629 2630 2631 2632 2633 2634 | aStat[0] = iLower + iGap; } return SQLITE4_OK; } #endif /* SQLITE4_ENABLE_STAT3 */ /* | | | | < < | < | | > | | | > > > > > > | > > > > > > > > | > | > > | > > > > > > > > > > > > > > > > | 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 | aStat[0] = iLower + iGap; } return SQLITE4_OK; } #endif /* SQLITE4_ENABLE_STAT3 */ /* ** If expression pExpr represents a literal value, extract it and apply ** the affinity aff to it. Then encode the value using the database index ** key encoding and write the result into buffer pBuf. ** ** If the current parse is a recompile (sqlite4Reprepare()) and pExpr ** is an SQL variable that currently has a non-NULL value bound to it, ** do the same with the bound value. ** ** If neither of the above apply, leave the buffer empty. ** ** If an error occurs, return an error code. Otherwise, SQLITE4_OK. */ #ifdef SQLITE4_ENABLE_STAT3 static int valueFromExpr( Parse *pParse, /* Parse context */ KeyInfo *pKeyinfo, /* Collation sequence and sort order */ Expr *pExpr, /* Expression to extract value from */ u8 aff, /* Affinity to apply to value */ sqlite4_buffer *pBuf /* Buffer to populate */ ){ int rc = SQLITE4_OK; sqlite4 *db = pParse->db; sqlite4_value *pVal = 0; assert( pBuf->n==0 ); if( pExpr->op==TK_VARIABLE || (pExpr->op==TK_REGISTER && pExpr->op2==TK_VARIABLE) ){ int iVar = pExpr->iColumn; sqlite4VdbeSetVarmask(pParse->pVdbe, iVar); pVal = sqlite4VdbeGetValue(pParse->pReprepare, iVar, aff); }else{ rc = sqlite4ValueFromExpr(db, pExpr, SQLITE4_UTF8, aff, &pVal); } if( pVal && rc==SQLITE4_OK ){ u8 *aOut; int nOut; rc = sqlite4VdbeEncodeKey(db, pVal, 1, 2, -1, pKeyinfo, &aOut, &nOut, 0); if( rc==SQLITE4_OK ){ rc = sqlite4_buffer_set(pBuf, aOut, nOut); } sqlite4DbFree(db, aOut); } sqlite4ValueFree(pVal); return SQLITE4_OK; } #endif static int whereSampleKeyinfo(Parse *pParse, Index *p, KeyInfo *pKeyInfo){ CollSeq *pColl; memset(pKeyInfo, 0, sizeof(KeyInfo)); pKeyInfo->db = pParse->db; pKeyInfo->enc = SQLITE4_UTF8; pKeyInfo->nField = p->nColumn; pKeyInfo->nPK = 1; pKeyInfo->nData = 0; pKeyInfo->aSortOrder = p->aSortOrder; pKeyInfo->aColl[0] = pColl = sqlite4LocateCollSeq(pParse, p->azColl[0]); pKeyInfo->aColl[0] = pColl; return pColl ? SQLITE4_OK : SQLITE4_ERROR; } /* ** This function is used to estimate the number of rows that will be visited ** by scanning an index for a range of values. The range may have an upper ** bound, a lower bound, or both. The WHERE clause terms that set the upper ** and lower bounds are represented by pLower and pUpper respectively. For ** example, assuming that index p is on t1(a): |
︙ | ︙ | |||
2714 2715 2716 2717 2718 2719 2720 | double *pRangeDiv /* OUT: Reduce search space by this divisor */ ){ int rc = SQLITE4_OK; #ifdef SQLITE4_ENABLE_STAT3 if( nEq==0 && p->nSample ){ | | > > > > > | | | | | | < > | 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 2689 2690 2691 2692 2693 2694 2695 2696 2697 2698 2699 2700 2701 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 | double *pRangeDiv /* OUT: Reduce search space by this divisor */ ){ int rc = SQLITE4_OK; #ifdef SQLITE4_ENABLE_STAT3 if( nEq==0 && p->nSample ){ sqlite4 *db = pParse->db; KeyInfo keyinfo; sqlite4_buffer buf; /* Buffer used for index sample */ tRowcnt iLower = 0; tRowcnt iUpper = p->aiRowEst[0]; tRowcnt a[2]; u8 aff = p->pTable->aCol[p->aiColumn[0]].affinity; sqlite4_buffer_init(&buf, db->pEnv->pMM); rc = whereSampleKeyinfo(pParse, p, &keyinfo); if( rc==SQLITE4_OK && pLower ){ Expr *pExpr = pLower->pExpr->pRight; rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf); assert( pLower->eOperator==WO_GT || pLower->eOperator==WO_GE ); if( rc==SQLITE4_OK && whereKeyStats(pParse, p, &buf, 0, a)==SQLITE4_OK ){ iLower = a[0]; if( pLower->eOperator==WO_GT ) iLower += a[1]; } sqlite4_buffer_set(&buf, 0, 0); } if( rc==SQLITE4_OK && pUpper ){ Expr *pExpr = pUpper->pExpr->pRight; rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf); assert( pUpper->eOperator==WO_LT || pUpper->eOperator==WO_LE ); if( rc==SQLITE4_OK && whereKeyStats(pParse, p, &buf, 1, a)==SQLITE4_OK ){ iUpper = a[0]; if( pUpper->eOperator==WO_LE ) iUpper += a[1]; } } sqlite4_buffer_clear(&buf); if( rc==SQLITE4_OK ){ if( iUpper<=iLower ){ *pRangeDiv = (double)p->aiRowEst[0]; }else{ *pRangeDiv = (double)p->aiRowEst[0]/(double)(iUpper - iLower); } WHERETRACE(("range scan regions: %u..%u div=%g\n", |
︙ | ︙ | |||
2791 2792 2793 2794 2795 2796 2797 | */ static int whereEqualScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ double *pnRow /* Write the revised row estimate here */ ){ | | > > > > > | | > > > | > | | | | 2748 2749 2750 2751 2752 2753 2754 2755 2756 2757 2758 2759 2760 2761 2762 2763 2764 2765 2766 2767 2768 2769 2770 2771 2772 2773 2774 2775 2776 2777 2778 2779 2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 | */ static int whereEqualScanEst( Parse *pParse, /* Parsing & code generating context */ Index *p, /* The index whose left-most column is pTerm */ Expr *pExpr, /* Expression for VALUE in the x=VALUE constraint */ double *pnRow /* Write the revised row estimate here */ ){ sqlite4_buffer buf; u8 aff; /* Column affinity */ int rc; /* Subfunction return code */ tRowcnt a[2]; /* Statistics */ assert( p->aSample!=0 ); assert( p->nSample>0 ); sqlite4_buffer_init(&buf, pParse->db->pEnv->pMM); aff = p->pTable->aCol[p->aiColumn[0]].affinity; if( pExpr ){ KeyInfo keyinfo; rc = whereSampleKeyinfo(pParse, p, &keyinfo); if( rc==SQLITE4_OK ){ rc = valueFromExpr(pParse, &keyinfo, pExpr, aff, &buf); if( buf.n==0 ) return SQLITE4_NOTFOUND; } }else{ /* Populate the buffer with a NULL. */ u8 aNull[2] = {0x05, 0xfa}; /* ASC, DESC */ rc = sqlite4_buffer_set(&buf, &aNull[p->aSortOrder[0]], 1); } if( rc ) goto whereEqualScanEst_cancel; rc = whereKeyStats(pParse, p, &buf, 0, a); if( rc==SQLITE4_OK ){ WHERETRACE(("equality scan regions: %d\n", (int)a[1])); *pnRow = a[1]; } whereEqualScanEst_cancel: sqlite4_buffer_clear(&buf); return rc; } #endif /* defined(SQLITE4_ENABLE_STAT3) */ #ifdef SQLITE4_ENABLE_STAT3 /* ** Estimate the number of rows that will be returned based on |
︙ | ︙ |
Changes to test/analyze.test.
︙ | ︙ | |||
323 324 325 326 327 328 329 | } {t3 t3i1 t3i3 t4 t4i1 t4i2 t3 t4} ifcapable stat3 { do_test analyze-5.3 { execsql { SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1; } | | | | 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 | } {t3 t3i1 t3i3 t4 t4i1 t4i2 t3 t4} ifcapable stat3 { do_test analyze-5.3 { execsql { SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1; } } {t3 t3i1 t3i3 t4 t4i1 t4i2 t3 t4} } do_test analyze-5.4 { execsql { DROP TABLE t3; SELECT DISTINCT idx FROM sqlite_stat1 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat1 ORDER BY 1; } } {t4 t4i1 t4i2 t4} ifcapable stat3 { do_test analyze-5.5 { execsql { SELECT DISTINCT idx FROM sqlite_stat3 ORDER BY 1; SELECT DISTINCT tbl FROM sqlite_stat3 ORDER BY 1; } } {t4 t4i1 t4i2 t4} } # This test corrupts the database file so it must be the last test # in the series. # do_test analyze-99.1 { execsql { |
︙ | ︙ |
Changes to test/permutations.test.
︙ | ︙ | |||
215 216 217 218 219 220 221 | tkt-02a8e81d44.test tkt-26ff0c2d1e.test tkt-2d1a5c67d.test tkt-2ea2425d34.test tkt-31338dca7e.test tkt-38cb5df375.test tkt-3998683a16.test tkt-3a77c9714e.test tkt-3fe897352e.test tkt-4a03edc4c8.test tkt-54844eea3f.test tkt-5e10420e8d.test tkt-752e1646fc.test tkt-80ba201079.test tkt-80e031a00f.test tkt-91e2e8ba6f.test tkt-9d68c883.test tkt-b1d3a2e531.test tkt-b351d95f9.test tkt-b72787b1.test | | | 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 | tkt-02a8e81d44.test tkt-26ff0c2d1e.test tkt-2d1a5c67d.test tkt-2ea2425d34.test tkt-31338dca7e.test tkt-38cb5df375.test tkt-3998683a16.test tkt-3a77c9714e.test tkt-3fe897352e.test tkt-4a03edc4c8.test tkt-54844eea3f.test tkt-5e10420e8d.test tkt-752e1646fc.test tkt-80ba201079.test tkt-80e031a00f.test tkt-91e2e8ba6f.test tkt-9d68c883.test tkt-b1d3a2e531.test tkt-b351d95f9.test tkt-b72787b1.test tkt-bd484a090c.test tkt-d11f09d36e.test tkt-d635236375.test tkt-f973c7ac31.test tkt-fa7bf5ec.test tkt1443.test tkt1444.test tkt1449.test tkt1473.test tkt1501.test tkt1514.test tkt1537.test tkt1873.test tkt2141.test tkt2192.test tkt2213.test tkt2285.test tkt2339.test tkt2391.test tkt2450.test tkt2640.test tkt2767.test tkt2817.test tkt2822.test tkt2832.test tkt2927.test tkt2942.test tkt3121.test tkt3201.test tkt3292.test tkt3298.test tkt3334.test tkt3346.test |
︙ | ︙ |
Changes to test/simple.test.
︙ | ︙ | |||
1539 1540 1541 1542 1543 1544 1545 1546 1547 | do_test 79.1 { set r1 [expr 0.684377705997032] execsql "CREATE TABLE t1(x UNIQUE)" execsql "INSERT INTO t1 VALUES($r1)" execsql "PRAGMA integrity_check" } {ok} finish_test | > > > > > > > > > > > > > > > > > | 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 | do_test 79.1 { set r1 [expr 0.684377705997032] execsql "CREATE TABLE t1(x UNIQUE)" execsql "INSERT INTO t1 VALUES($r1)" execsql "PRAGMA integrity_check" } {ok} reset_db do_execsql_test 80.1 { CREATE TABLE t1(tbl, idx, nEq, nLt, nDLt, sample); INSERT INTO t1 VALUES('t1', 't1i3', 1, 0, 0, x'1802'); INSERT INTO t1 VALUES('t1', 't1i3', 1, 1, 1, x'1802'); INSERT INTO t1 VALUES('t1', 't1i2', 1, 0, 0, x'1804'); INSERT INTO t1 VALUES('t1', 't1i2', 1, 1, 1, x'1806'); INSERT INTO t1 VALUES('t1', 't1i1', 1, 0, 0, x'1802'); INSERT INTO t1 VALUES('t1', 't1i1', 1, 1, 1, x'1802'); INSERT INTO t1 VALUES('t1', 't1', 1, 0, 0, x'1802'); INSERT INTO t1 VALUES('t1', 't1', 1, 1, 1, x'1804'); } do_execsql_test 80.2 { SELECT idx, count(*), sum(length(sample)) FROM t1 GROUP BY idx } {t1 2 4 t1i1 2 4 t1i2 2 4 t1i3 2 4} finish_test |