File
Blob: patches/sqlite/0001-row-counts-plain.patch
| 1 | diff -u5 -r sqlite-src-pristine/src/shell.c.in sqlite-src-modified/src/shell.c.in |
| 2 | --- sqlite-src-pristine/src/shell.c.in 2024-10-21 11:47:53 |
| 3 | +++ sqlite-src-modified/src/shell.c.in 2024-11-05 08:16:15 |
| 4 | @@ -3411,10 +3411,15 @@ |
| 5 | sqlite3_fprintf(out, |
| 6 | "Number of times run: %d\n", iCur); |
| 7 | iCur = sqlite3_stmt_status(pArg->pStmt, SQLITE_STMTSTATUS_MEMUSED, bReset); |
| 8 | sqlite3_fprintf(out, |
| 9 | "Memory used by prepared stmt: %d\n", iCur); |
| 10 | + |
| 11 | + iCur = sqlite3_stmt_status(pArg->pStmt, LIBSQL_STMTSTATUS_ROWS_READ, bReset); |
| 12 | + sqlite3_fprintf(pArg->out, "Rows read: %d\n", iCur); |
| 13 | + iCur = sqlite3_stmt_status(pArg->pStmt, LIBSQL_STMTSTATUS_ROWS_WRITTEN, bReset); |
| 14 | + sqlite3_fprintf(pArg->out, "Rows written: %d\n", iCur); |
| 15 | } |
| 16 | |
| 17 | #ifdef __linux__ |
| 18 | displayLinuxIoStats(pArg->out); |
| 19 | #endif |
| 20 | diff -u5 -r sqlite-src-pristine/src/sqlite.h.in sqlite-src-modified/src/sqlite.h.in |
| 21 | --- sqlite-src-pristine/src/sqlite.h.in 2024-10-21 11:47:53 |
| 22 | +++ sqlite-src-modified/src/sqlite.h.in 2024-11-05 08:13:50 |
| 23 | @@ -8907,20 +8907,32 @@ |
| 24 | ** used to store the prepared statement. ^This value is not actually |
| 25 | ** a counter, and so the resetFlg parameter to sqlite3_stmt_status() |
| 26 | ** is ignored when the opcode is SQLITE_STMTSTATUS_MEMUSED. |
| 27 | ** </dd> |
| 28 | ** </dl> |
| 29 | +** |
| 30 | +** [[LIBSQL_STMTSTATUS_ROWS_READ]] |
| 31 | +** [[LIBSQL_STMTSTATUS_ROWS_WRITTEN]] |
| 32 | +** <dt>LIBSQL_STMTSTATUS_ROWS_READ<br> |
| 33 | +** LIBSQL_STMTSTATUS_ROWS_WRITTEN</dt> |
| 34 | +** <dd>^LIBSQL_STMTSTATUS_ROWS_READ is the number of rows read when executing |
| 35 | +** this statement. LIBSQL_STMTSTATUS_ROWS_WRITTEN value is the number of |
| 36 | +** rows written. |
| 37 | */ |
| 38 | #define SQLITE_STMTSTATUS_FULLSCAN_STEP 1 |
| 39 | #define SQLITE_STMTSTATUS_SORT 2 |
| 40 | #define SQLITE_STMTSTATUS_AUTOINDEX 3 |
| 41 | #define SQLITE_STMTSTATUS_VM_STEP 4 |
| 42 | #define SQLITE_STMTSTATUS_REPREPARE 5 |
| 43 | #define SQLITE_STMTSTATUS_RUN 6 |
| 44 | #define SQLITE_STMTSTATUS_FILTER_MISS 7 |
| 45 | #define SQLITE_STMTSTATUS_FILTER_HIT 8 |
| 46 | #define SQLITE_STMTSTATUS_MEMUSED 99 |
| 47 | + |
| 48 | +#define LIBSQL_STMTSTATUS_BASE 1024 |
| 49 | +#define LIBSQL_STMTSTATUS_ROWS_READ LIBSQL_STMTSTATUS_BASE + 1 |
| 50 | +#define LIBSQL_STMTSTATUS_ROWS_WRITTEN LIBSQL_STMTSTATUS_BASE + 2 |
| 51 | |
| 52 | /* |
| 53 | ** CAPI3REF: Custom Page Cache Object |
| 54 | ** |
| 55 | ** The sqlite3_pcache type is opaque. It is implemented by |
| 56 | diff -u5 -r sqlite-src-pristine/src/vdbe.c sqlite-src-modified/src/vdbe.c |
| 57 | --- sqlite-src-pristine/src/vdbe.c 2024-10-21 11:47:53 |
| 58 | +++ sqlite-src-modified/src/vdbe.c 2024-11-05 08:13:50 |
| 59 | @@ -3737,10 +3737,11 @@ |
| 60 | if( pOp->p3 ){ |
| 61 | nEntry = sqlite3BtreeRowCountEst(pCrsr); |
| 62 | }else{ |
| 63 | nEntry = 0; /* Not needed. Only used to silence a warning. */ |
| 64 | rc = sqlite3BtreeCount(db, pCrsr, &nEntry); |
| 65 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE] += nEntry; |
| 66 | if( rc ) goto abort_due_to_error; |
| 67 | } |
| 68 | pOut = out2Prerelease(p, pOp); |
| 69 | pOut->u.i = nEntry; |
| 70 | goto check_for_interrupt; |
| 71 | @@ -4900,10 +4901,11 @@ |
| 72 | if( eqOnly && r.eqSeen==0 ){ |
| 73 | assert( res!=0 ); |
| 74 | goto seek_not_found; |
| 75 | } |
| 76 | } |
| 77 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; |
| 78 | #ifdef SQLITE_TEST |
| 79 | sqlite3_search_count++; |
| 80 | #endif |
| 81 | if( oc>=OP_SeekGE ){ assert( oc==OP_SeekGE || oc==OP_SeekGT ); |
| 82 | if( res<0 || (res==0 && oc==OP_SeekGT) ){ |
| 83 | @@ -5470,10 +5472,11 @@ |
| 84 | pC->nullRow = 0; |
| 85 | pC->cacheStatus = CACHE_STALE; |
| 86 | pC->deferredMoveto = 0; |
| 87 | VdbeBranchTaken(res!=0,2); |
| 88 | pC->seekResult = res; |
| 89 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; |
| 90 | if( res!=0 ){ |
| 91 | assert( rc==SQLITE_OK ); |
| 92 | if( pOp->p2==0 ){ |
| 93 | rc = SQLITE_CORRUPT_BKPT; |
| 94 | }else{ |
| 95 | @@ -5727,10 +5730,11 @@ |
| 96 | } |
| 97 | if( pOp->p5 & OPFLAG_ISNOOP ) break; |
| 98 | #endif |
| 99 | |
| 100 | assert( (pOp->p5 & OPFLAG_LASTROWID)==0 || (pOp->p5 & OPFLAG_NCHANGE)!=0 ); |
| 101 | + if (!pC->isEphemeral) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; |
| 102 | if( pOp->p5 & OPFLAG_NCHANGE ){ |
| 103 | p->nChange++; |
| 104 | if( pOp->p5 & OPFLAG_LASTROWID ) db->lastRowid = x.nKey; |
| 105 | } |
| 106 | assert( (pData->flags & (MEM_Blob|MEM_Str))!=0 || pData->n==0 ); |
| 107 | @@ -5920,10 +5924,11 @@ |
| 108 | pC->seekResult = 0; |
| 109 | if( rc ) goto abort_due_to_error; |
| 110 | |
| 111 | /* Invoke the update-hook if required. */ |
| 112 | if( opflags & OPFLAG_NCHANGE ){ |
| 113 | + if (!pC->isEphemeral) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; |
| 114 | p->nChange++; |
| 115 | if( db->xUpdateCallback && ALWAYS(pTab!=0) && HasRowid(pTab) ){ |
| 116 | db->xUpdateCallback(db->pUpdateArg, SQLITE_DELETE, zDb, pTab->zName, |
| 117 | pC->movetoTarget); |
| 118 | assert( pC->iDb>=0 ); |
| 119 | @@ -6207,10 +6212,11 @@ |
| 120 | rc = sqlite3BtreeLast(pCrsr, &res); |
| 121 | pC->nullRow = (u8)res; |
| 122 | pC->deferredMoveto = 0; |
| 123 | pC->cacheStatus = CACHE_STALE; |
| 124 | if( rc ) goto abort_due_to_error; |
| 125 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; |
| 126 | if( pOp->p2>0 ){ |
| 127 | VdbeBranchTaken(res!=0,2); |
| 128 | if( res ) goto jump_to_p2; |
| 129 | } |
| 130 | break; |
| 131 | @@ -6326,10 +6332,11 @@ |
| 132 | pC->deferredMoveto = 0; |
| 133 | pC->cacheStatus = CACHE_STALE; |
| 134 | } |
| 135 | if( rc ) goto abort_due_to_error; |
| 136 | pC->nullRow = (u8)res; |
| 137 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; |
| 138 | if( pOp->p2>0 ){ |
| 139 | VdbeBranchTaken(res!=0,2); |
| 140 | if( res ) goto jump_to_p2; |
| 141 | } |
| 142 | break; |
| 143 | @@ -6431,10 +6438,11 @@ |
| 144 | pC->cacheStatus = CACHE_STALE; |
| 145 | VdbeBranchTaken(rc==SQLITE_OK,2); |
| 146 | if( rc==SQLITE_OK ){ |
| 147 | pC->nullRow = 0; |
| 148 | p->aCounter[pOp->p5]++; |
| 149 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; |
| 150 | #ifdef SQLITE_TEST |
| 151 | sqlite3_search_count++; |
| 152 | #endif |
| 153 | goto jump_to_p2_and_check_for_interrupt; |
| 154 | } |
| 155 | @@ -6482,10 +6490,11 @@ |
| 156 | assert( pC!=0 ); |
| 157 | assert( !isSorter(pC) ); |
| 158 | pIn2 = &aMem[pOp->p2]; |
| 159 | assert( (pIn2->flags & MEM_Blob) || (pOp->p5 & OPFLAG_PREFORMAT) ); |
| 160 | if( pOp->p5 & OPFLAG_NCHANGE ) p->nChange++; |
| 161 | + if (!pC->isEphemeral) p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; |
| 162 | assert( pC->eCurType==CURTYPE_BTREE ); |
| 163 | assert( pC->isTable==0 ); |
| 164 | rc = ExpandBlob(pIn2); |
| 165 | if( rc ) goto abort_due_to_error; |
| 166 | x.nKey = pIn2->n; |
| 167 | @@ -6882,10 +6891,11 @@ |
| 168 | assert( p->readOnly==0 ); |
| 169 | assert( DbMaskTest(p->btreeMask, pOp->p2) ); |
| 170 | rc = sqlite3BtreeClearTable(db->aDb[pOp->p2].pBt, (u32)pOp->p1, &nChange); |
| 171 | if( pOp->p3 ){ |
| 172 | p->nChange += nChange; |
| 173 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE] += nChange; |
| 174 | if( pOp->p3>0 ){ |
| 175 | assert( memIsValid(&aMem[pOp->p3]) ); |
| 176 | memAboutToChange(p, &aMem[pOp->p3]); |
| 177 | aMem[pOp->p3].u.i += nChange; |
| 178 | } |
| 179 | @@ -8466,10 +8476,11 @@ |
| 180 | ** some other method is next invoked on the save virtual table cursor. |
| 181 | */ |
| 182 | rc = pModule->xNext(pCur->uc.pVCur); |
| 183 | sqlite3VtabImportErrmsg(p, pVtab); |
| 184 | if( rc ) goto abort_due_to_error; |
| 185 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_READ - LIBSQL_STMTSTATUS_BASE]++; |
| 186 | res = pModule->xEof(pCur->uc.pVCur); |
| 187 | VdbeBranchTaken(!res,2); |
| 188 | if( !res ){ |
| 189 | /* If there is data, jump to P2 */ |
| 190 | goto jump_to_p2_and_check_for_interrupt; |
| 191 | @@ -8587,10 +8598,11 @@ |
| 192 | rc = SQLITE_OK; |
| 193 | }else{ |
| 194 | p->errorAction = ((pOp->p5==OE_Replace) ? OE_Abort : pOp->p5); |
| 195 | } |
| 196 | }else{ |
| 197 | + p->aLibsqlCounter[LIBSQL_STMTSTATUS_ROWS_WRITTEN - LIBSQL_STMTSTATUS_BASE]++; |
| 198 | p->nChange++; |
| 199 | } |
| 200 | if( rc ) goto abort_due_to_error; |
| 201 | } |
| 202 | break; |
| 203 | diff -u5 -r sqlite-src-pristine/src/vdbeInt.h sqlite-src-modified/src/vdbeInt.h |
| 204 | --- sqlite-src-pristine/src/vdbeInt.h 2024-10-21 11:47:53 |
| 205 | +++ sqlite-src-modified/src/vdbeInt.h 2024-11-05 08:13:50 |
| 206 | @@ -496,10 +496,11 @@ |
| 207 | bft bIsReader:1; /* True for statements that read */ |
| 208 | bft haveEqpOps:1; /* Bytecode supports EXPLAIN QUERY PLAN */ |
| 209 | yDbMask btreeMask; /* Bitmask of db->aDb[] entries referenced */ |
| 210 | yDbMask lockMask; /* Subset of btreeMask that requires a lock */ |
| 211 | u32 aCounter[9]; /* Counters used by sqlite3_stmt_status() */ |
| 212 | + u32 aLibsqlCounter[3]; /* libSQL extension: Counters used by sqlite3_stmt_status()*/ |
| 213 | char *zSql; /* Text of the SQL statement that generated this */ |
| 214 | #ifdef SQLITE_ENABLE_NORMALIZE |
| 215 | char *zNormSql; /* Normalization of the associated SQL statement */ |
| 216 | DblquoteStr *pDblStr; /* List of double-quoted string literals */ |
| 217 | #endif |
| 218 | diff -u5 -r sqlite-src-pristine/src/vdbeapi.c sqlite-src-modified/src/vdbeapi.c |
| 219 | --- sqlite-src-pristine/src/vdbeapi.c 2024-10-21 11:47:53 |
| 220 | +++ sqlite-src-modified/src/vdbeapi.c 2024-11-05 08:13:50 |
| 221 | @@ -2072,11 +2072,11 @@ |
| 222 | int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){ |
| 223 | Vdbe *pVdbe = (Vdbe*)pStmt; |
| 224 | u32 v; |
| 225 | #ifdef SQLITE_ENABLE_API_ARMOR |
| 226 | if( !pStmt |
| 227 | - || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||op>=ArraySize(pVdbe->aCounter))) |
| 228 | + || (op!=SQLITE_STMTSTATUS_MEMUSED && (op<0||(op>=ArraySize(pVdbe->aCounter)&&op<LIBSQL_STMTSTATUS_BASE))) |
| 229 | ){ |
| 230 | (void)SQLITE_MISUSE_BKPT; |
| 231 | return 0; |
| 232 | } |
| 233 | #endif |
| 234 | @@ -2089,10 +2089,13 @@ |
| 235 | db->lookaside.pEnd = db->lookaside.pStart; |
| 236 | sqlite3VdbeDelete(pVdbe); |
| 237 | db->pnBytesFreed = 0; |
| 238 | db->lookaside.pEnd = db->lookaside.pTrueEnd; |
| 239 | sqlite3_mutex_leave(db->mutex); |
| 240 | + }else if( op>=LIBSQL_STMTSTATUS_BASE ){ |
| 241 | + v = pVdbe->aLibsqlCounter[op - LIBSQL_STMTSTATUS_BASE]; |
| 242 | + if( resetFlag ) pVdbe->aLibsqlCounter[op - LIBSQL_STMTSTATUS_BASE] = 0; |
| 243 | }else{ |
| 244 | v = pVdbe->aCounter[op]; |
| 245 | if( resetFlag ) pVdbe->aCounter[op] = 0; |
| 246 | } |
| 247 | return (int)v; |