Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch debug-loopcounters Excluding Merge-Ins
This is equivalent to a diff from 3c933bf9 to c6a5b67a
2014-10-23
| ||
17:26 | Add debugging code to count the number of iterations of each loop made as part of statement execution. (Leaf check-in: c6a5b67a user: dan tags: debug-loopcounters) | |
2014-10-22
| ||
19:57 | Change the 0x800 bit of SQLITE_TESTCTRL_OPTIMIZATIONS so that it disables the loading of STAT3 and STAT4 content, not just the using of that content. Change the internal name of that bit to SQLITE_Stat34. (check-in: ca3b00c4 user: drh tags: trunk) | |
18:42 | Merge latest trunk with this branch. (check-in: 854a54c6 user: dan tags: defrag-opt) | |
16:25 | The _beginthreadex() / _endthreadex() functions should only be used when compiling with MSVC. (Closed-Leaf check-in: 1a5a5da3 user: mistachkin tags: msvcThreads) | |
15:27 | Take steps to avoid misestimating range query costs based on STAT4 data due to the roundoff error of converting from integers to LogEst and back to integers. (check-in: 3c933bf9 user: drh tags: trunk) | |
2014-10-21
| ||
21:56 | Call fsync() right after ftruncate() when in journal_mode=TRUNCATE and when synchronous=FULL in order to ensure that transactions are durable across a power loss that happens moments after the commit. Proposed fix for https://bugzilla.mozilla.org/show_bug.cgi?id=1072773. (check-in: 3e922208 user: drh tags: trunk) | |
Changes to src/shell.c.
︙ | |||
453 454 455 456 457 458 459 460 461 462 463 464 465 466 | 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 | + | */ typedef struct ShellState ShellState; struct ShellState { sqlite3 *db; /* The database */ int echoOn; /* True to echo input commands */ int autoEQP; /* Run EXPLAIN QUERY PLAN prior to seach SQL stmt */ int statsOn; /* True to display memory stats before each finalize */ int loopCountersOn; /* True to display loop counters */ int outCount; /* Revert to stdout when reaching zero */ int cnt; /* Number of records displayed so far */ FILE *out; /* Write results here */ FILE *traceOut; /* Output for sqlite3_trace() */ int nErr; /* Number of errors seen */ int mode; /* An output mode setting */ int writableSchema; /* True if PRAGMA writable_schema=ON */ |
︙ | |||
1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 | 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 | + + + + + + + + + + + + + + + + + + + + + + + + | int nErrMsg = 1+strlen30(sqlite3_errmsg(db)); char *zErrMsg = sqlite3_malloc(nErrMsg); if( zErrMsg ){ memcpy(zErrMsg, sqlite3_errmsg(db), nErrMsg); } return zErrMsg; } static void display_loop_counters( sqlite3 *db, /* Database to query */ ShellState *pArg /* Pointer to ShellState */ ){ #if !defined(SQLITE_DEBUG) || !defined(SQLITE_ENABLE_LOOPCOUNTERS) fprintf(pArg->out, "No loop counters. " "Rebuild with SQLITE_DEBUG and SQLITE_ENABLE_LOOPCOUNTERS" ); #else int i; for(i=0; 1; i++){ int nTest; int nVisit; int iSub; int iLoop; const char *zLoop; zLoop = sqlite3_stmt_loopcounter(pArg->pStmt, i, &iSub, &iLoop, &nTest, &nVisit); if( zLoop==0 ) break; fprintf(pArg->out, "loop %d.%d: (%d/%d) %s\n", iSub, iLoop, nVisit, nTest, zLoop); } #endif } /* ** Display memory stats. */ static int display_stats( sqlite3 *db, /* Database to query */ ShellState *pArg, /* Pointer to ShellState */ |
︙ | |||
1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 | 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 | + + + + + | explain_data_delete(pArg); /* print usage stats if stats on */ if( pArg && pArg->statsOn ){ display_stats(db, pArg, 0); } /* print loop-counters if required */ if( pArg && pArg->loopCountersOn ){ display_loop_counters(db, pArg); } /* Finalize the statement just executed. If this fails, save a ** copy of the error message. Otherwise, set zSql to point to the ** next statement to execute. */ rc2 = sqlite3_finalize(pStmt); if( rc!=SQLITE_NOMEM ) rc = rc2; if( rc==SQLITE_OK ){ |
︙ | |||
2814 2815 2816 2817 2818 2819 2820 2821 2822 2823 2824 2825 2826 2827 | 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862 2863 2864 2865 2866 2867 | + + + + + + + + + + | rc = 1; }else{ const char *zFile = azArg[1]; output_file_close(p->pLog); p->pLog = output_file_open(zFile); } }else if( c=='l' && strncmp(azArg[0], "loopcounters", n)==0 ){ if( nArg==2 ){ p->loopCountersOn = booleanValue(azArg[1]); }else{ fprintf(stderr, "Usage: .loopcounters on|off\n"); rc = 1; } }else if( c=='m' && strncmp(azArg[0], "mode", n)==0 ){ const char *zMode = nArg>=2 ? azArg[1] : ""; int n2 = (int)strlen(zMode); int c2 = zMode[0]; if( c2=='l' && n2>2 && strncmp(azArg[1],"lines",n2)==0 ){ p->mode = MODE_Line; |
︙ | |||
4136 4137 4138 4139 4140 4141 4142 4143 4144 4145 4146 4147 4148 4149 | 4176 4177 4178 4179 4180 4181 4182 4183 4184 4185 4186 4187 4188 4189 4190 4191 | + + | data.showHeader = 0; }else if( strcmp(z,"-echo")==0 ){ data.echoOn = 1; }else if( strcmp(z,"-eqp")==0 ){ data.autoEQP = 1; }else if( strcmp(z,"-stats")==0 ){ data.statsOn = 1; }else if( strcmp(z,"-loopcounters")==0 ){ data.loopCountersOn = 1; }else if( strcmp(z,"-bail")==0 ){ bail_on_error = 1; }else if( strcmp(z,"-version")==0 ){ printf("%s %s\n", sqlite3_libversion(), sqlite3_sourceid()); return 0; }else if( strcmp(z,"-interactive")==0 ){ stdin_is_interactive = 1; |
︙ |
Changes to src/sqlite.h.in.
︙ | |||
7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 | 7402 7403 7404 7405 7406 7407 7408 7409 7410 7411 7412 7413 7414 7415 7416 7417 7418 7419 7420 7421 7422 7423 7424 7425 7426 7427 7428 7429 7430 7431 7432 7433 7434 7435 7436 7437 7438 | + + + + + + + + + + + + + + + + + + + + + + + | */ #define SQLITE_ROLLBACK 1 /* #define SQLITE_IGNORE 2 // Also used by sqlite3_authorizer() callback */ #define SQLITE_FAIL 3 /* #define SQLITE_ABORT 4 // Also an error code */ #define SQLITE_REPLACE 5 /* ** This API function is only available if SQLite is compiled with both ** SQLITE_DEBUG and SQLITE_ENABLE_LOOPCOUNTERS defined. It is primarily ** useful with SELECT statements. ** ** Each call returns information corresponding to a single "loop" run as ** part of the statement. Each loop corresponds to a single "SEARCH" or "SCAN" ** row that would be returned by EXPLAIN QUERY PLAN on the same SQL statement. ** The second parameter - idx - determines which loop information is returned ** regarding. If idx is less than 0 or greater than or equal to the number of ** loops in the statement, NULL Is returned and the final values of the four ** output parameters are undefined. Otherwise, the return value points to a ** string describing the loop in question - the same string as would appear as ** the fourth column of EXPLAIN QUERY PLAN output. The first two integer output ** parameters are set to the values that would be returned as the first two ** columns of the same row of EQP output. ** ** The third output parameter is set to the number of rows that were visited ** by the loop the last time the statement was run. The fourth output parameter ** is set to the number of rows visited including those excluded by non-indexed ** WHERE terms. */ const char *sqlite3_stmt_loopcounter(sqlite3_stmt*, int idx, int*, int*, int*, int*); /* ** Undo the hack that converts floating point types to integer for ** builds on processors without floating point support. */ #ifdef SQLITE_OMIT_FLOATING_POINT |
︙ |
Changes to src/vdbe.c.
︙ | |||
601 602 603 604 605 606 607 608 609 610 611 612 613 614 | 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 | + + + | sqlite3EndBenignMalloc(); #endif for(pc=p->pc; rc==SQLITE_OK; pc++){ assert( pc>=0 && pc<p->nOp ); if( db->mallocFailed ) goto no_mem; #ifdef VDBE_PROFILE start = sqlite3Hwtime(); #endif #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) if( p->pFrame==0 ) p->anExec[pc]++; #endif nVmStep++; pOp = &aOp[pc]; /* Only allow tracing if SQLITE_DEBUG is defined. */ #ifdef SQLITE_DEBUG |
︙ |
Changes to src/vdbe.h.
︙ | |||
277 278 279 280 281 282 283 284 285 | 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 | + + + + + + | #else # define VdbeCoverage(v) # define VdbeCoverageIf(v,x) # define VdbeCoverageAlwaysTaken(v) # define VdbeCoverageNeverTaken(v) # define VDBE_OFFSET_LINENO(x) 0 #endif #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) void sqlite3VdbeLoopCounter(Vdbe*, int addrExplain, int addrTest, int addrBody); #else # define sqlite3VdbeLoopCounter(a,b,c,d) #endif #endif |
Changes to src/vdbeInt.h.
︙ | |||
291 292 293 294 295 296 297 298 299 300 301 302 303 304 | 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 | + + + + + + + | }; /* 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 LoopCounter LoopCounter; struct LoopCounter { int addrExplain; /* OP_Explain for loop */ int addrTest; /* Address of non-indexed WHERE term tests */ int addrBody; /* Address of loop body */ }; /* ** An instance of the virtual machine. This structure contains the complete ** state of the virtual machine. ** ** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare() ** is really a pointer to an instance of this structure. ** |
︙ | |||
363 364 365 366 367 368 369 370 371 372 373 374 375 376 | 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 | + + + + + | VdbeFrame *pDelFrame; /* List of frame objects to free on VM reset */ int nFrame; /* Number of frames in pFrame list */ u32 expmask; /* Binding to these vars invalidates VM */ 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 */ #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) int *anExec; /* Number of times each op has been executed */ int nLoop; /* Entries in aLoop[] */ LoopCounter *aLoop; /* Loop definitions for sqlite3_stmt_loopcounter() */ #endif }; /* ** The following are allowed values for Vdbe.magic */ #define VDBE_MAGIC_INIT 0x26bceaa5 /* Building a VDBE program */ #define VDBE_MAGIC_RUN 0xbdf20da3 /* VDBE is ready to execute */ |
︙ |
Changes to src/vdbeapi.c.
︙ | |||
478 479 480 481 482 483 484 485 486 487 488 489 490 491 | 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 | + + + | ); #ifndef SQLITE_OMIT_TRACE if( db->xProfile && !db->init.busy ){ sqlite3OsCurrentTimeInt64(db->pVfs, &p->startTime); } #endif #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) memset(p->anExec, 0, sizeof(int) * p->nOp); #endif db->nVdbeActive++; if( p->readOnly==0 ) db->nVdbeWrite++; if( p->bIsReader ) db->nVdbeRead++; p->pc = 0; } #ifndef SQLITE_OMIT_EXPLAIN |
︙ | |||
1450 1451 1452 1453 1454 1455 1456 | 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 | + + + + + + + + + + + + + + + + | */ int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ Vdbe *pVdbe = (Vdbe*)pStmt; u32 v = pVdbe->aCounter[op]; if( resetFlag ) pVdbe->aCounter[op] = 0; return (int)v; } #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) const char *sqlite3_stmt_loopcounter( sqlite3_stmt *pStmt, int idx, int *piSub, int *piLoop, int *pnTest, int *pnVisit ){ Vdbe *p = (Vdbe*)pStmt; if( idx>=p->nLoop || idx<0 ) return 0; *piSub = p->aOp[p->aLoop[idx].addrExplain].p1; *piLoop = p->aOp[p->aLoop[idx].addrExplain].p2; *pnTest = p->anExec[ p->aLoop[idx].addrTest ]; *pnVisit = p->anExec[ p->aLoop[idx].addrBody ]; return p->aOp[p->aLoop[idx].addrExplain].p4.z; } #endif |
Changes to src/vdbeaux.c.
︙ | |||
593 594 595 596 597 598 599 600 601 602 603 604 605 606 | 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 618 619 620 621 622 623 624 625 626 627 628 629 | + + + + + + + + + + + + + + + + + + + + + + + | #endif } p->nOp += nOp; } return addr; } #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) void sqlite3VdbeLoopCounter( Vdbe *p, int addrExplain, int addrTest, int addrBody ){ int nByte = (p->nLoop+1) * sizeof(LoopCounter); if( addrTest>=0 ){ p->aLoop = (LoopCounter*)sqlite3DbReallocOrFree(p->db, p->aLoop, nByte); p->nLoop++; } if( p->aLoop ){ LoopCounter *pNew = &p->aLoop[p->nLoop-1]; pNew->addrExplain = addrExplain; if( addrTest>=0 ){ pNew->addrTest = addrTest; pNew->addrBody = addrBody; } } } #endif /* ** Change the value of the P1 operand for a specific instruction. ** This routine is useful when a large program is loaded from a ** static array using sqlite3VdbeAddOpList but we want to make a ** few minor changes to the program. */ void sqlite3VdbeChangeP1(Vdbe *p, u32 addr, int val){ |
︙ | |||
1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 | 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 | + + + + | p->aOnceFlag = allocSpace(p->aOnceFlag, nOnce, &zCsr, zEnd, &nByte); if( nByte ){ p->pFree = sqlite3DbMallocZero(db, nByte); } zCsr = p->pFree; zEnd = &zCsr[nByte]; }while( nByte && !db->mallocFailed ); #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) p->anExec = (int*)sqlite3DbMallocZero(db, sizeof(int) * p->nOp); #endif p->nCursor = nCursor; p->nOnceFlag = nOnce; if( p->aVar ){ p->nVar = (ynVar)nVar; for(n=0; n<nVar; n++){ p->aVar[n].flags = MEM_Null; |
︙ | |||
2675 2676 2677 2678 2679 2680 2681 2682 2683 2684 2685 2686 2687 2688 | 2702 2703 2704 2705 2706 2707 2708 2709 2710 2711 2712 2713 2714 2715 2716 2717 2718 2719 | + + + + | sqlite3DbFree(db, pSub); } for(i=p->nzVar-1; i>=0; i--) sqlite3DbFree(db, p->azVar[i]); vdbeFreeOpArray(db, p->aOp, p->nOp); sqlite3DbFree(db, p->aColName); sqlite3DbFree(db, p->zSql); sqlite3DbFree(db, p->pFree); #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) sqlite3DbFree(db, p->aLoop); sqlite3DbFree(db, p->anExec); #endif } /* ** Delete an entire VDBE. */ void sqlite3VdbeDelete(Vdbe *p){ sqlite3 *db; |
︙ |
Changes to src/where.c.
︙ | |||
2904 2905 2906 2907 2908 2909 2910 | 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918 2919 2920 2921 2922 2923 2924 2925 2926 2927 2928 2929 2930 | - + - + + + + + - - | int addrNxt; /* Where to jump to continue with the next IN case */ int omitTable; /* True if we use the index only */ int bRev; /* True if we need to scan in reverse order */ WhereLevel *pLevel; /* The where level to be coded */ WhereLoop *pLoop; /* The WhereLoop object being coded */ WhereClause *pWC; /* Decomposition of the entire WHERE clause */ WhereTerm *pTerm; /* A WHERE clause term */ |
︙ | |||
3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 | 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 | + | /* Loop through table entries that match term pOrTerm. */ WHERETRACE(0xffff, ("Subplan for OR-clause:\n")); pSubWInfo = sqlite3WhereBegin(pParse, pOrTab, pOrExpr, 0, 0, wctrlFlags, iCovCur); assert( pSubWInfo || pParse->nErr || db->mallocFailed ); if( pSubWInfo ){ WhereLoop *pSubLoop; sqlite3VdbeLoopCounter(v, sqlite3VdbeCurrentAddr(v), -1, -1); explainOneScan( pParse, pOrTab, &pSubWInfo->a[0], iLevel, pLevel->iFrom, 0 ); /* This is the sub-WHERE clause body. First skip over ** duplicate rows from prior sub-WHERE clauses, and record the ** rowid (or PRIMARY KEY) for the current row so that the same ** row will be skipped in subsequent sub-WHERE clauses. |
︙ | |||
3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 | 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 3698 3699 3700 3701 3702 3703 | + + + + | pLevel->p1 = iCur; pLevel->p2 = 1 + sqlite3VdbeAddOp2(v, aStart[bRev], iCur, addrBrk); VdbeCoverageIf(v, bRev==0); VdbeCoverageIf(v, bRev!=0); pLevel->p5 = SQLITE_STMTSTATUS_FULLSCAN_STEP; } } #if defined(SQLITE_DEBUG) && defined(SQLITE_ENABLE_LOOPCOUNTERS) addrTest = sqlite3VdbeCurrentAddr(v); #endif /* Insert code to test every subexpression that can be completely ** computed using the current set of tables. */ for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){ Expr *pE; testcase( pTerm->wtFlags & TERM_VIRTUAL ); |
︙ | |||
3761 3762 3763 3764 3765 3766 3767 3768 3769 3770 3771 3772 3773 3774 | 3768 3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784 3785 | + + + + | continue; } assert( pTerm->pExpr ); sqlite3ExprIfFalse(pParse, pTerm->pExpr, addrCont, SQLITE_JUMPIFNULL); pTerm->wtFlags |= TERM_CODED; } } if( pParse->pTriggerTab==0 && 0==(pLoop->wsFlags & WHERE_MULTI_OR) ){ sqlite3VdbeLoopCounter(v, addrExplain, addrTest, sqlite3VdbeCurrentAddr(v)); } return pLevel->notReady; } #ifdef WHERETRACE_ENABLED /* ** Print the content of a WhereTerm object |
︙ |