Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Remove unused variable from struct WhereInfo. Add some explanatory comments to new code. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | scanstatus |
Files: | files | file ages | folders |
SHA1: |
f5313e0c680d9baebefb1cf50ddadedd |
User & Date: | dan 2014-11-03 11:25:32.305 |
Context
2014-11-03
| ||
15:33 | Add further tests. Fixes so that compilation without ENABLE_STMT_SCANSTATUS works. (check-in: a2303c7192 user: dan tags: scanstatus) | |
11:25 | Remove unused variable from struct WhereInfo. Add some explanatory comments to new code. (check-in: f5313e0c68 user: dan tags: scanstatus) | |
2014-11-01
| ||
21:00 | Minor performance enhancements to SQLITE_ENABLE_STMT_SCANSTATUS code. (check-in: f13d6ba8a7 user: dan tags: scanstatus) | |
Changes
Changes to src/vdbe.h.
︙ | ︙ | |||
279 280 281 282 283 284 285 | # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS | | | | 279 280 281 282 283 284 285 286 287 288 289 290 291 | # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #ifdef SQLITE_ENABLE_STMT_SCANSTATUS void sqlite3VdbeScanStatus(Vdbe*, int, int, int, i64, const char*); #else # define sqlite3VdbeScanStatus(a,b,c,d,e) #endif #endif |
Changes to src/vdbeInt.h.
︙ | ︙ | |||
293 294 295 296 297 298 299 | }; /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ typedef unsigned bft; /* Bit Field Type */ | | | | 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 | }; /* A bitfield type for use inside of structures. Always follow with :N where ** N is the number of bits. */ typedef unsigned bft; /* Bit Field Type */ typedef struct ScanStatus ScanStatus; struct ScanStatus { int addrExplain; /* OP_Explain for loop */ int addrLoop; /* Address of "loops" counter */ int addrVisit; /* Address of "rows visited" counter */ i64 nEst; /* Estimated rows per loop */ char *zName; /* Name of table or index */ }; |
︙ | ︙ | |||
377 378 379 380 381 382 383 | SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ int nOnceFlag; /* Size of array aOnceFlag[] */ u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS i64 *anExec; /* Number of times each op has been executed */ int nScan; /* Entries in aScan[] */ | | | 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 | SubProgram *pProgram; /* Linked list of all sub-programs used by VM */ int nOnceFlag; /* Size of array aOnceFlag[] */ u8 *aOnceFlag; /* Flags for OP_Once */ AuxData *pAuxData; /* Linked list of auxdata allocations */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS i64 *anExec; /* Number of times each op has been executed */ int nScan; /* Entries in aScan[] */ ScanStatus *aScan; /* Scan definitions for sqlite3_stmt_scanstatus() */ #endif }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ |
︙ | ︙ |
Changes to src/vdbeapi.c.
︙ | ︙ | |||
1486 1487 1488 1489 1490 1491 1492 | sqlite3_int64 *pnLoop, /* OUT: Number of times loop was run */ sqlite3_int64 *pnVisit, /* OUT: Number of rows visited (all loops) */ sqlite3_int64 *pnEst, /* OUT: Number of rows estimated (per loop) */ const char **pzName, /* OUT: Object name (table or index) */ const char **pzExplain /* OUT: EQP string */ ){ Vdbe *p = (Vdbe*)pStmt; | | | 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 | sqlite3_int64 *pnLoop, /* OUT: Number of times loop was run */ sqlite3_int64 *pnVisit, /* OUT: Number of rows visited (all loops) */ sqlite3_int64 *pnEst, /* OUT: Number of rows estimated (per loop) */ const char **pzName, /* OUT: Object name (table or index) */ const char **pzExplain /* OUT: EQP string */ ){ Vdbe *p = (Vdbe*)pStmt; ScanStatus *pScan; if( idx<0 || idx>=p->nScan ) return 1; pScan = &p->aScan[idx]; if( pnLoop ) *pnLoop = p->anExec[pScan->addrLoop]; if( pnVisit ) *pnVisit = p->anExec[pScan->addrVisit]; if( pnEst ) *pnEst = pScan->nEst; if( *pzName ) *pzName = pScan->zName; if( *pzExplain ){ |
︙ | ︙ |
Changes to src/vdbeaux.c.
︙ | ︙ | |||
597 598 599 600 601 602 603 | return addr; } #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) /* ** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). */ | | | | | | | 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 | return addr; } #if defined(SQLITE_ENABLE_STMT_SCANSTATUS) /* ** Add an entry to the array of counters managed by sqlite3_stmt_scanstatus(). */ void sqlite3VdbeScanStatus( Vdbe *p, /* VM to add scanstatus() to */ int addrExplain, /* Address of OP_Explain (or 0) */ int addrLoop, /* Address of loop counter */ int addrVisit, /* Address of rows visited counter */ i64 nEst, /* Estimated number of rows */ const char *zName /* Name of table or index being scanned */ ){ int nByte = (p->nScan+1) * sizeof(ScanStatus); ScanStatus *aNew; aNew = (ScanStatus*)sqlite3DbRealloc(p->db, p->aScan, nByte); if( aNew ){ ScanStatus *pNew = &aNew[p->nScan++]; pNew->addrExplain = addrExplain; pNew->addrLoop = addrLoop; pNew->addrVisit = addrVisit; pNew->nEst = nEst; pNew->zName = sqlite3DbStrDup(p->db, zName); p->aScan = aNew; } |
︙ | ︙ |
Changes to src/where.c.
︙ | ︙ | |||
2804 2805 2806 2807 2808 2809 2810 | explainAppendTerm(pStr, i, z, "<"); } sqlite3StrAccumAppend(pStr, ")", 1); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN | | > | | > > | 2804 2805 2806 2807 2808 2809 2810 2811 2812 2813 2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 | explainAppendTerm(pStr, i, z, "<"); } sqlite3StrAccumAppend(pStr, ")", 1); } /* ** This function is a no-op unless currently processing an EXPLAIN QUERY PLAN ** command, or if either SQLITE_DEBUG or SQLITE_ENABLE_STMT_SCANSTATUS was ** defined at compile-time. If it is not a no-op, a single OP_Explain opcode ** is added to the output to describe the table scan strategy in pLevel. ** ** If an OP_Explain opcode is added to the VM, its address is returned. ** Otherwise, if no OP_Explain is coded, zero is returned. */ static int explainOneScan( Parse *pParse, /* Parse context */ SrcList *pTabList, /* Table list this loop refers to */ WhereLevel *pLevel, /* Scan to write OP_Explain opcode for */ int iLevel, /* Value for "level" column of output */ int iFrom, /* Value for "from" column of output */ |
︙ | ︙ | |||
2915 2916 2917 2918 2919 2920 2921 2922 | return ret; } #else # define explainOneScan(u,v,w,x,y,z) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS static void addScanStatus( | > > > > > > > > > | | | | | | 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 2931 2932 2933 2934 2935 2936 2937 2938 2939 2940 2941 2942 2943 2944 2945 2946 2947 2948 2949 2950 2951 2952 2953 2954 2955 2956 2957 2958 | return ret; } #else # define explainOneScan(u,v,w,x,y,z) 0 #endif /* SQLITE_OMIT_EXPLAIN */ #ifdef SQLITE_ENABLE_STMT_SCANSTATUS /* ** Configure the VM passed as the first argument with an ** sqlite3_stmt_scanstatus() entry corresponding to the scan used to ** implement level pLvl. Argument pSrclist is a pointer to the FROM ** clause that the scan reads data from. ** ** If argument addrExplain is not 0, it must be the address of an ** OP_Explain instruction that describes the same loop. */ static void addScanStatus( Vdbe *v, /* Vdbe to add scanstatus entry to */ SrcList *pSrclist, /* FROM clause pLvl reads data from */ WhereLevel *pLvl, /* Level to add scanstatus() entry for */ int addrExplain /* Address of OP_Explain (or 0) */ ){ const char *zObj = 0; i64 nEst = 1; WhereLoop *pLoop = pLvl->pWLoop; if( (pLoop->wsFlags & (WHERE_IPK|WHERE_VIRTUALTABLE))==0 ){ zObj = pLoop->u.btree.pIndex->zName; }else{ zObj = pSrclist->a[pLvl->iFrom].zName; } if( pLoop->nOut>=10 ){ nEst = sqlite3LogEstToInt(pLoop->nOut); } sqlite3VdbeScanStatus( v, addrExplain, pLvl->addrBody, pLvl->addrVisit, nEst, zObj ); } #else # define addScanStatus(a, b, c, d) #endif |
︙ | ︙ |
Changes to src/whereInt.h.
︙ | ︙ | |||
406 407 408 409 410 411 412 | u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ | < | 406 407 408 409 410 411 412 413 414 415 416 417 418 419 | u8 okOnePass; /* Ok to use one-pass algorithm for UPDATE/DELETE */ u8 untestedTerms; /* Not all WHERE terms resolved by outer loop */ u8 eDistinct; /* One of the WHERE_DISTINCT_* values below */ u8 nLevel; /* Number of nested loop */ int iTop; /* The very beginning of the WHERE loop */ int iContinue; /* Jump here to continue with next record */ int iBreak; /* Jump here to break out of the loop */ int savedNQueryLoop; /* pParse->nQueryLoop outside the WHERE loop */ int aiCurOnePass[2]; /* OP_OpenWrite cursors for the ONEPASS opt */ WhereMaskSet sMaskSet; /* Map cursor numbers to bitmasks */ WhereClause sWC; /* Decomposition of the WHERE clause */ WhereLevel a[1]; /* Information about each nest loop in WHERE */ }; |
︙ | ︙ |
Changes to test/scanstatus.test.
︙ | ︙ | |||
226 227 228 229 230 231 232 233 234 | do_execsql_test 3.4.1 { SELECT count(*) FROM a1 WHERE rowid IN (1, 5, 10, 15); } {4} do_scanstatus_test 3.4.2 { nLoop 1 nVisit 4 nEst 4 zName a1 zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)} } finish_test | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | do_execsql_test 3.4.1 { SELECT count(*) FROM a1 WHERE rowid IN (1, 5, 10, 15); } {4} do_scanstatus_test 3.4.2 { nLoop 1 nVisit 4 nEst 4 zName a1 zExplain {SEARCH TABLE a1 USING INTEGER PRIMARY KEY (rowid=?)} } #------------------------------------------------------------------------- # Test that scanstatus() data is not available for searches performed # by triggers. # # It is available for searches performed as part of FK processing, but # not FK action processing. # do_execsql_test 4.0 { CREATE TABLE t1(a, b, c); CREATE TABLE t2(x PRIMARY KEY, y, z); CREATE TRIGGER tr1 AFTER INSERT ON t1 BEGIN SELECT * FROM t2 WHERE x BETWEEN 20 AND 40; END; WITH d(x) AS (SELECT 1 UNION ALL SELECT x+1 AS n FROM d WHERE n<=100) INSERT INTO t2 SELECT x, x*2, x*3 FROM d; } do_execsql_test 4.1.1 { INSERT INTO t1 VALUES(1, 2, 3); } do_scanstatus_test 4.1.2 { } do_execsql_test 4.2 { CREATE TABLE p1(x PRIMARY KEY); INSERT INTO p1 VALUES(1), (2), (3), (4); CREATE TABLE c1(y REFERENCES p1); INSERT INTO c1 VALUES(1), (2), (3); PRAGMA foreign_keys=on; } do_execsql_test 4.2.1 { DELETE FROM p1 WHERE x=4 } do_scanstatus_test 4.2.2 { nLoop 1 nVisit 1 nEst 1 zName sqlite_autoindex_p1_1 zExplain {SEARCH TABLE p1 USING INDEX sqlite_autoindex_p1_1 (x=?)} nLoop 1 nVisit 3 nEst 524288 zName c1 zExplain {SCAN TABLE c1} } finish_test |