| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/sqlite/src/src/dbpage.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | /* | - | ||||||||||||||||||
| 2 | ** 2017-10-11 | - | ||||||||||||||||||
| 3 | ** | - | ||||||||||||||||||
| 4 | ** The author disclaims copyright to this source code. In place of | - | ||||||||||||||||||
| 5 | ** a legal notice, here is a blessing: | - | ||||||||||||||||||
| 6 | ** | - | ||||||||||||||||||
| 7 | ** May you do good and not evil. | - | ||||||||||||||||||
| 8 | ** May you find forgiveness for yourself and forgive others. | - | ||||||||||||||||||
| 9 | ** May you share freely, never taking more than you give. | - | ||||||||||||||||||
| 10 | ** | - | ||||||||||||||||||
| 11 | ****************************************************************************** | - | ||||||||||||||||||
| 12 | ** | - | ||||||||||||||||||
| 13 | ** This file contains an implementation of the "sqlite_dbpage" virtual table. | - | ||||||||||||||||||
| 14 | ** | - | ||||||||||||||||||
| 15 | ** The sqlite_dbpage virtual table is used to read or write whole raw | - | ||||||||||||||||||
| 16 | ** pages of the database file. The pager interface is used so that | - | ||||||||||||||||||
| 17 | ** uncommitted changes and changes recorded in the WAL file are correctly | - | ||||||||||||||||||
| 18 | ** retrieved. | - | ||||||||||||||||||
| 19 | ** | - | ||||||||||||||||||
| 20 | ** Usage example: | - | ||||||||||||||||||
| 21 | ** | - | ||||||||||||||||||
| 22 | ** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123; | - | ||||||||||||||||||
| 23 | ** | - | ||||||||||||||||||
| 24 | ** This is an eponymous virtual table so it does not need to be created before | - | ||||||||||||||||||
| 25 | ** use. The optional argument to the sqlite_dbpage() table name is the | - | ||||||||||||||||||
| 26 | ** schema for the database file that is to be read. The default schema is | - | ||||||||||||||||||
| 27 | ** "main". | - | ||||||||||||||||||
| 28 | ** | - | ||||||||||||||||||
| 29 | ** The data field of sqlite_dbpage table can be updated. The new | - | ||||||||||||||||||
| 30 | ** value must be a BLOB which is the correct page size, otherwise the | - | ||||||||||||||||||
| 31 | ** update fails. Rows may not be deleted or inserted. | - | ||||||||||||||||||
| 32 | */ | - | ||||||||||||||||||
| 33 | - | |||||||||||||||||||
| 34 | #include "sqliteInt.h" /* Requires access to internal data structures */ | - | ||||||||||||||||||
| 35 | #if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ | - | ||||||||||||||||||
| 36 | && !defined(SQLITE_OMIT_VIRTUALTABLE) | - | ||||||||||||||||||
| 37 | - | |||||||||||||||||||
| 38 | typedef struct DbpageTable DbpageTable; | - | ||||||||||||||||||
| 39 | typedef struct DbpageCursor DbpageCursor; | - | ||||||||||||||||||
| 40 | - | |||||||||||||||||||
| 41 | struct DbpageCursor { | - | ||||||||||||||||||
| 42 | sqlite3_vtab_cursor base; /* Base class. Must be first */ | - | ||||||||||||||||||
| 43 | int pgno; /* Current page number */ | - | ||||||||||||||||||
| 44 | int mxPgno; /* Last page to visit on this scan */ | - | ||||||||||||||||||
| 45 | Pager *pPager; /* Pager being read/written */ | - | ||||||||||||||||||
| 46 | DbPage *pPage1; /* Page 1 of the database */ | - | ||||||||||||||||||
| 47 | int iDb; /* Index of database to analyze */ | - | ||||||||||||||||||
| 48 | int szPage; /* Size of each page in bytes */ | - | ||||||||||||||||||
| 49 | }; | - | ||||||||||||||||||
| 50 | - | |||||||||||||||||||
| 51 | struct DbpageTable { | - | ||||||||||||||||||
| 52 | sqlite3_vtab base; /* Base class. Must be first */ | - | ||||||||||||||||||
| 53 | sqlite3 *db; /* The database */ | - | ||||||||||||||||||
| 54 | }; | - | ||||||||||||||||||
| 55 | - | |||||||||||||||||||
| 56 | /* Columns */ | - | ||||||||||||||||||
| 57 | #define DBPAGE_COLUMN_PGNO 0 | - | ||||||||||||||||||
| 58 | #define DBPAGE_COLUMN_DATA 1 | - | ||||||||||||||||||
| 59 | #define DBPAGE_COLUMN_SCHEMA 2 | - | ||||||||||||||||||
| 60 | - | |||||||||||||||||||
| 61 | - | |||||||||||||||||||
| 62 | - | |||||||||||||||||||
| 63 | /* | - | ||||||||||||||||||
| 64 | ** Connect to or create a dbpagevfs virtual table. | - | ||||||||||||||||||
| 65 | */ | - | ||||||||||||||||||
| 66 | static int dbpageConnect( | - | ||||||||||||||||||
| 67 | sqlite3 *db, | - | ||||||||||||||||||
| 68 | void *pAux, | - | ||||||||||||||||||
| 69 | int argc, const char *const*argv, | - | ||||||||||||||||||
| 70 | sqlite3_vtab **ppVtab, | - | ||||||||||||||||||
| 71 | char **pzErr | - | ||||||||||||||||||
| 72 | ){ | - | ||||||||||||||||||
| 73 | DbpageTable *pTab = 0; | - | ||||||||||||||||||
| 74 | int rc = SQLITE_OK; | - | ||||||||||||||||||
| 75 | - | |||||||||||||||||||
| 76 | rc = sqlite3_declare_vtab(db, | - | ||||||||||||||||||
| 77 | "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)"); | - | ||||||||||||||||||
| 78 | if( rc==SQLITE_OK ){
| 0-5 | ||||||||||||||||||
| 79 | pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable)); | - | ||||||||||||||||||
| 80 | if( pTab==0 ) rc = SQLITE_NOMEM_BKPT; never executed: rc = 7;
| 0-5 | ||||||||||||||||||
| 81 | } executed 5 times by 1 test: end of blockExecuted by:
| 5 | ||||||||||||||||||
| 82 | - | |||||||||||||||||||
| 83 | assert( rc==SQLITE_OK || pTab==0 ); | - | ||||||||||||||||||
| 84 | if( rc==SQLITE_OK ){
| 0-5 | ||||||||||||||||||
| 85 | memset(pTab, 0, sizeof(DbpageTable)); | - | ||||||||||||||||||
| 86 | pTab->db = db; | - | ||||||||||||||||||
| 87 | } executed 5 times by 1 test: end of blockExecuted by:
| 5 | ||||||||||||||||||
| 88 | - | |||||||||||||||||||
| 89 | *ppVtab = (sqlite3_vtab*)pTab; | - | ||||||||||||||||||
| 90 | return rc; executed 5 times by 1 test: return rc;Executed by:
| 5 | ||||||||||||||||||
| 91 | } | - | ||||||||||||||||||
| 92 | - | |||||||||||||||||||
| 93 | /* | - | ||||||||||||||||||
| 94 | ** Disconnect from or destroy a dbpagevfs virtual table. | - | ||||||||||||||||||
| 95 | */ | - | ||||||||||||||||||
| 96 | static int dbpageDisconnect(sqlite3_vtab *pVtab){ | - | ||||||||||||||||||
| 97 | sqlite3_free(pVtab); | - | ||||||||||||||||||
| 98 | return SQLITE_OK; executed 5 times by 1 test: return 0;Executed by:
| 5 | ||||||||||||||||||
| 99 | } | - | ||||||||||||||||||
| 100 | - | |||||||||||||||||||
| 101 | /* | - | ||||||||||||||||||
| 102 | ** idxNum: | - | ||||||||||||||||||
| 103 | ** | - | ||||||||||||||||||
| 104 | ** 0 schema=main, full table scan | - | ||||||||||||||||||
| 105 | ** 1 schema=main, pgno=?1 | - | ||||||||||||||||||
| 106 | ** 2 schema=?1, full table scan | - | ||||||||||||||||||
| 107 | ** 3 schema=?1, pgno=?2 | - | ||||||||||||||||||
| 108 | */ | - | ||||||||||||||||||
| 109 | static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ | - | ||||||||||||||||||
| 110 | int i; | - | ||||||||||||||||||
| 111 | int iPlan = 0; | - | ||||||||||||||||||
| 112 | - | |||||||||||||||||||
| 113 | /* If there is a schema= constraint, it must be honored. Report a | - | ||||||||||||||||||
| 114 | ** ridiculously large estimated cost if the schema= constraint is | - | ||||||||||||||||||
| 115 | ** unavailable | - | ||||||||||||||||||
| 116 | */ | - | ||||||||||||||||||
| 117 | for(i=0; i<pIdxInfo->nConstraint; i++){
| 11-21 | ||||||||||||||||||
| 118 | struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; | - | ||||||||||||||||||
| 119 | if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue; executed 13 times by 1 test: continue;Executed by:
| 8-13 | ||||||||||||||||||
| 120 | if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue; never executed: continue;
| 0-8 | ||||||||||||||||||
| 121 | if( !p->usable ){
| 1-7 | ||||||||||||||||||
| 122 | /* No solution. Use the default SQLITE_BIG_DBL cost */ | - | ||||||||||||||||||
| 123 | pIdxInfo->estimatedRows = 0x7fffffff; | - | ||||||||||||||||||
| 124 | return SQLITE_OK; executed 1 time by 1 test: return 0;Executed by:
| 1 | ||||||||||||||||||
| 125 | } | - | ||||||||||||||||||
| 126 | iPlan = 2; | - | ||||||||||||||||||
| 127 | pIdxInfo->aConstraintUsage[i].argvIndex = 1; | - | ||||||||||||||||||
| 128 | pIdxInfo->aConstraintUsage[i].omit = 1; | - | ||||||||||||||||||
| 129 | break; executed 7 times by 1 test: break;Executed by:
| 7 | ||||||||||||||||||
| 130 | } | - | ||||||||||||||||||
| 131 | - | |||||||||||||||||||
| 132 | /* If we reach this point, it means that either there is no schema= | - | ||||||||||||||||||
| 133 | ** constraint (in which case we use the "main" schema) or else the | - | ||||||||||||||||||
| 134 | ** schema constraint was accepted. Lower the estimated cost accordingly | - | ||||||||||||||||||
| 135 | */ | - | ||||||||||||||||||
| 136 | pIdxInfo->estimatedCost = 1.0e6; | - | ||||||||||||||||||
| 137 | - | |||||||||||||||||||
| 138 | /* Check for constraints against pgno */ | - | ||||||||||||||||||
| 139 | for(i=0; i<pIdxInfo->nConstraint; i++){
| 3-20 | ||||||||||||||||||
| 140 | struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i]; | - | ||||||||||||||||||
| 141 | if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
| 0-20 | ||||||||||||||||||
| 142 | pIdxInfo->estimatedRows = 1; | - | ||||||||||||||||||
| 143 | pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE; | - | ||||||||||||||||||
| 144 | pIdxInfo->estimatedCost = 1.0; | - | ||||||||||||||||||
| 145 | pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1;
| 4-11 | ||||||||||||||||||
| 146 | pIdxInfo->aConstraintUsage[i].omit = 1; | - | ||||||||||||||||||
| 147 | iPlan |= 1; | - | ||||||||||||||||||
| 148 | break; executed 15 times by 1 test: break;Executed by:
| 15 | ||||||||||||||||||
| 149 | } | - | ||||||||||||||||||
| 150 | } executed 5 times by 1 test: end of blockExecuted by:
| 5 | ||||||||||||||||||
| 151 | pIdxInfo->idxNum = iPlan; | - | ||||||||||||||||||
| 152 | - | |||||||||||||||||||
| 153 | if( pIdxInfo->nOrderBy>=1
| 2-16 | ||||||||||||||||||
| 154 | && pIdxInfo->aOrderBy[0].iColumn<=0
| 0-2 | ||||||||||||||||||
| 155 | && pIdxInfo->aOrderBy[0].desc==0
| 0-2 | ||||||||||||||||||
| 156 | ){ | - | ||||||||||||||||||
| 157 | pIdxInfo->orderByConsumed = 1; | - | ||||||||||||||||||
| 158 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||
| 159 | return SQLITE_OK; executed 18 times by 1 test: return 0;Executed by:
| 18 | ||||||||||||||||||
| 160 | } | - | ||||||||||||||||||
| 161 | - | |||||||||||||||||||
| 162 | /* | - | ||||||||||||||||||
| 163 | ** Open a new dbpagevfs cursor. | - | ||||||||||||||||||
| 164 | */ | - | ||||||||||||||||||
| 165 | static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ | - | ||||||||||||||||||
| 166 | DbpageCursor *pCsr; | - | ||||||||||||||||||
| 167 | - | |||||||||||||||||||
| 168 | pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor)); | - | ||||||||||||||||||
| 169 | if( pCsr==0 ){
| 0-18 | ||||||||||||||||||
| 170 | return SQLITE_NOMEM_BKPT; never executed: return 7; | 0 | ||||||||||||||||||
| 171 | }else{ | - | ||||||||||||||||||
| 172 | memset(pCsr, 0, sizeof(DbpageCursor)); | - | ||||||||||||||||||
| 173 | pCsr->base.pVtab = pVTab; | - | ||||||||||||||||||
| 174 | pCsr->pgno = -1; | - | ||||||||||||||||||
| 175 | } executed 18 times by 1 test: end of blockExecuted by:
| 18 | ||||||||||||||||||
| 176 | - | |||||||||||||||||||
| 177 | *ppCursor = (sqlite3_vtab_cursor *)pCsr; | - | ||||||||||||||||||
| 178 | return SQLITE_OK; executed 18 times by 1 test: return 0;Executed by:
| 18 | ||||||||||||||||||
| 179 | } | - | ||||||||||||||||||
| 180 | - | |||||||||||||||||||
| 181 | /* | - | ||||||||||||||||||
| 182 | ** Close a dbpagevfs cursor. | - | ||||||||||||||||||
| 183 | */ | - | ||||||||||||||||||
| 184 | static int dbpageClose(sqlite3_vtab_cursor *pCursor){ | - | ||||||||||||||||||
| 185 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; | - | ||||||||||||||||||
| 186 | if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); executed 18 times by 1 test: sqlite3PagerUnrefPageOne(pCsr->pPage1);Executed by:
| 0-18 | ||||||||||||||||||
| 187 | sqlite3_free(pCsr); | - | ||||||||||||||||||
| 188 | return SQLITE_OK; executed 18 times by 1 test: return 0;Executed by:
| 18 | ||||||||||||||||||
| 189 | } | - | ||||||||||||||||||
| 190 | - | |||||||||||||||||||
| 191 | /* | - | ||||||||||||||||||
| 192 | ** Move a dbpagevfs cursor to the next entry in the file. | - | ||||||||||||||||||
| 193 | */ | - | ||||||||||||||||||
| 194 | static int dbpageNext(sqlite3_vtab_cursor *pCursor){ | - | ||||||||||||||||||
| 195 | int rc = SQLITE_OK; | - | ||||||||||||||||||
| 196 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; | - | ||||||||||||||||||
| 197 | pCsr->pgno++; | - | ||||||||||||||||||
| 198 | return rc; executed 16 times by 1 test: return rc;Executed by:
| 16 | ||||||||||||||||||
| 199 | } | - | ||||||||||||||||||
| 200 | - | |||||||||||||||||||
| 201 | static int dbpageEof(sqlite3_vtab_cursor *pCursor){ | - | ||||||||||||||||||
| 202 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; | - | ||||||||||||||||||
| 203 | return pCsr->pgno > pCsr->mxPgno; executed 35 times by 1 test: return pCsr->pgno > pCsr->mxPgno;Executed by:
| 35 | ||||||||||||||||||
| 204 | } | - | ||||||||||||||||||
| 205 | - | |||||||||||||||||||
| 206 | /* | - | ||||||||||||||||||
| 207 | ** idxNum: | - | ||||||||||||||||||
| 208 | ** | - | ||||||||||||||||||
| 209 | ** 0 schema=main, full table scan | - | ||||||||||||||||||
| 210 | ** 1 schema=main, pgno=?1 | - | ||||||||||||||||||
| 211 | ** 2 schema=?1, full table scan | - | ||||||||||||||||||
| 212 | ** 3 schema=?1, pgno=?2 | - | ||||||||||||||||||
| 213 | ** | - | ||||||||||||||||||
| 214 | ** idxStr is not used | - | ||||||||||||||||||
| 215 | */ | - | ||||||||||||||||||
| 216 | static int dbpageFilter( | - | ||||||||||||||||||
| 217 | sqlite3_vtab_cursor *pCursor, | - | ||||||||||||||||||
| 218 | int idxNum, const char *idxStr, | - | ||||||||||||||||||
| 219 | int argc, sqlite3_value **argv | - | ||||||||||||||||||
| 220 | ){ | - | ||||||||||||||||||
| 221 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; | - | ||||||||||||||||||
| 222 | DbpageTable *pTab = (DbpageTable *)pCursor->pVtab; | - | ||||||||||||||||||
| 223 | int rc; | - | ||||||||||||||||||
| 224 | sqlite3 *db = pTab->db; | - | ||||||||||||||||||
| 225 | Btree *pBt; | - | ||||||||||||||||||
| 226 | - | |||||||||||||||||||
| 227 | /* Default setting is no rows of result */ | - | ||||||||||||||||||
| 228 | pCsr->pgno = 1; | - | ||||||||||||||||||
| 229 | pCsr->mxPgno = 0; | - | ||||||||||||||||||
| 230 | - | |||||||||||||||||||
| 231 | if( idxNum & 2 ){
| 8-11 | ||||||||||||||||||
| 232 | const char *zSchema; | - | ||||||||||||||||||
| 233 | assert( argc>=1 ); | - | ||||||||||||||||||
| 234 | zSchema = (const char*)sqlite3_value_text(argv[0]); | - | ||||||||||||||||||
| 235 | pCsr->iDb = sqlite3FindDbName(db, zSchema); | - | ||||||||||||||||||
| 236 | if( pCsr->iDb<0 ) return SQLITE_OK; never executed: return 0;
| 0-8 | ||||||||||||||||||
| 237 | }else{ executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||
| 238 | pCsr->iDb = 0; | - | ||||||||||||||||||
| 239 | } executed 11 times by 1 test: end of blockExecuted by:
| 11 | ||||||||||||||||||
| 240 | pBt = db->aDb[pCsr->iDb].pBt; | - | ||||||||||||||||||
| 241 | if( pBt==0 ) return SQLITE_OK; never executed: return 0;
| 0-19 | ||||||||||||||||||
| 242 | pCsr->pPager = sqlite3BtreePager(pBt); | - | ||||||||||||||||||
| 243 | pCsr->szPage = sqlite3BtreeGetPageSize(pBt); | - | ||||||||||||||||||
| 244 | pCsr->mxPgno = sqlite3BtreeLastPage(pBt); | - | ||||||||||||||||||
| 245 | if( idxNum & 1 ){
| 3-16 | ||||||||||||||||||
| 246 | assert( argc>(idxNum>>1) ); | - | ||||||||||||||||||
| 247 | pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]); | - | ||||||||||||||||||
| 248 | if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
| 1-15 | ||||||||||||||||||
| 249 | pCsr->pgno = 1; | - | ||||||||||||||||||
| 250 | pCsr->mxPgno = 0; | - | ||||||||||||||||||
| 251 | }else{ executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||||||||||||||
| 252 | pCsr->mxPgno = pCsr->pgno; | - | ||||||||||||||||||
| 253 | } executed 14 times by 1 test: end of blockExecuted by:
| 14 | ||||||||||||||||||
| 254 | }else{ | - | ||||||||||||||||||
| 255 | assert( pCsr->pgno==1 ); | - | ||||||||||||||||||
| 256 | } executed 3 times by 1 test: end of blockExecuted by:
| 3 | ||||||||||||||||||
| 257 | if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1); executed 1 time by 1 test: sqlite3PagerUnrefPageOne(pCsr->pPage1);Executed by:
| 1-18 | ||||||||||||||||||
| 258 | rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0); | - | ||||||||||||||||||
| 259 | return rc; executed 19 times by 1 test: return rc;Executed by:
| 19 | ||||||||||||||||||
| 260 | } | - | ||||||||||||||||||
| 261 | - | |||||||||||||||||||
| 262 | static int dbpageColumn( | - | ||||||||||||||||||
| 263 | sqlite3_vtab_cursor *pCursor, | - | ||||||||||||||||||
| 264 | sqlite3_context *ctx, | - | ||||||||||||||||||
| 265 | int i | - | ||||||||||||||||||
| 266 | ){ | - | ||||||||||||||||||
| 267 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; | - | ||||||||||||||||||
| 268 | int rc = SQLITE_OK; | - | ||||||||||||||||||
| 269 | switch( i ){ | - | ||||||||||||||||||
| 270 | case 0: { /* pgno */ executed 22 times by 1 test: case 0:Executed by:
| 22 | ||||||||||||||||||
| 271 | sqlite3_result_int(ctx, pCsr->pgno); | - | ||||||||||||||||||
| 272 | break; executed 22 times by 1 test: break;Executed by:
| 22 | ||||||||||||||||||
| 273 | } | - | ||||||||||||||||||
| 274 | case 1: { /* data */ executed 16 times by 1 test: case 1:Executed by:
| 16 | ||||||||||||||||||
| 275 | DbPage *pDbPage = 0; | - | ||||||||||||||||||
| 276 | rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0); | - | ||||||||||||||||||
| 277 | if( rc==SQLITE_OK ){
| 0-16 | ||||||||||||||||||
| 278 | sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage, | - | ||||||||||||||||||
| 279 | SQLITE_TRANSIENT); | - | ||||||||||||||||||
| 280 | } executed 16 times by 1 test: end of blockExecuted by:
| 16 | ||||||||||||||||||
| 281 | sqlite3PagerUnref(pDbPage); | - | ||||||||||||||||||
| 282 | break; executed 16 times by 1 test: break;Executed by:
| 16 | ||||||||||||||||||
| 283 | } | - | ||||||||||||||||||
| 284 | default: { /* schema */ executed 10 times by 1 test: default:Executed by:
| 10 | ||||||||||||||||||
| 285 | sqlite3 *db = sqlite3_context_db_handle(ctx); | - | ||||||||||||||||||
| 286 | sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC); | - | ||||||||||||||||||
| 287 | break; executed 10 times by 1 test: break;Executed by:
| 10 | ||||||||||||||||||
| 288 | } | - | ||||||||||||||||||
| 289 | } | - | ||||||||||||||||||
| 290 | return SQLITE_OK; executed 48 times by 1 test: return 0;Executed by:
| 48 | ||||||||||||||||||
| 291 | } | - | ||||||||||||||||||
| 292 | - | |||||||||||||||||||
| 293 | static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){ | - | ||||||||||||||||||
| 294 | DbpageCursor *pCsr = (DbpageCursor *)pCursor; | - | ||||||||||||||||||
| 295 | *pRowid = pCsr->pgno; | - | ||||||||||||||||||
| 296 | return SQLITE_OK; executed 16 times by 1 test: return 0;Executed by:
| 16 | ||||||||||||||||||
| 297 | } | - | ||||||||||||||||||
| 298 | - | |||||||||||||||||||
| 299 | static int dbpageUpdate( | - | ||||||||||||||||||
| 300 | sqlite3_vtab *pVtab, | - | ||||||||||||||||||
| 301 | int argc, | - | ||||||||||||||||||
| 302 | sqlite3_value **argv, | - | ||||||||||||||||||
| 303 | sqlite_int64 *pRowid | - | ||||||||||||||||||
| 304 | ){ | - | ||||||||||||||||||
| 305 | DbpageTable *pTab = (DbpageTable *)pVtab; | - | ||||||||||||||||||
| 306 | Pgno pgno; | - | ||||||||||||||||||
| 307 | DbPage *pDbPage = 0; | - | ||||||||||||||||||
| 308 | int rc = SQLITE_OK; | - | ||||||||||||||||||
| 309 | char *zErr = 0; | - | ||||||||||||||||||
| 310 | const char *zSchema; | - | ||||||||||||||||||
| 311 | int iDb; | - | ||||||||||||||||||
| 312 | Btree *pBt; | - | ||||||||||||||||||
| 313 | Pager *pPager; | - | ||||||||||||||||||
| 314 | int szPage; | - | ||||||||||||||||||
| 315 | - | |||||||||||||||||||
| 316 | if( argc==1 ){
| 0-8 | ||||||||||||||||||
| 317 | zErr = "cannot delete"; | - | ||||||||||||||||||
| 318 | goto update_fail; never executed: goto update_fail; | 0 | ||||||||||||||||||
| 319 | } | - | ||||||||||||||||||
| 320 | pgno = sqlite3_value_int(argv[0]); | - | ||||||||||||||||||
| 321 | if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
| 0-8 | ||||||||||||||||||
| 322 | zErr = "cannot insert"; | - | ||||||||||||||||||
| 323 | goto update_fail; never executed: goto update_fail; | 0 | ||||||||||||||||||
| 324 | } | - | ||||||||||||||||||
| 325 | zSchema = (const char*)sqlite3_value_text(argv[4]); | - | ||||||||||||||||||
| 326 | iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
| 0-8 | ||||||||||||||||||
| 327 | if( iDb<0 ){
| 0-8 | ||||||||||||||||||
| 328 | zErr = "no such schema"; | - | ||||||||||||||||||
| 329 | goto update_fail; never executed: goto update_fail; | 0 | ||||||||||||||||||
| 330 | } | - | ||||||||||||||||||
| 331 | pBt = pTab->db->aDb[iDb].pBt; | - | ||||||||||||||||||
| 332 | if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
| 0-8 | ||||||||||||||||||
| 333 | zErr = "bad page number"; | - | ||||||||||||||||||
| 334 | goto update_fail; never executed: goto update_fail; | 0 | ||||||||||||||||||
| 335 | } | - | ||||||||||||||||||
| 336 | szPage = sqlite3BtreeGetPageSize(pBt); | - | ||||||||||||||||||
| 337 | if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
| 0-8 | ||||||||||||||||||
| 338 | || sqlite3_value_bytes(argv[3])!=szPage
| 0-8 | ||||||||||||||||||
| 339 | ){ | - | ||||||||||||||||||
| 340 | zErr = "bad page value"; | - | ||||||||||||||||||
| 341 | goto update_fail; never executed: goto update_fail; | 0 | ||||||||||||||||||
| 342 | } | - | ||||||||||||||||||
| 343 | pPager = sqlite3BtreePager(pBt); | - | ||||||||||||||||||
| 344 | rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0); | - | ||||||||||||||||||
| 345 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||
| 346 | rc = sqlite3PagerWrite(pDbPage); | - | ||||||||||||||||||
| 347 | if( rc==SQLITE_OK ){
| 0-8 | ||||||||||||||||||
| 348 | memcpy(sqlite3PagerGetData(pDbPage), | - | ||||||||||||||||||
| 349 | sqlite3_value_blob(argv[3]), | - | ||||||||||||||||||
| 350 | szPage); | - | ||||||||||||||||||
| 351 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||
| 352 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||||||||||||||
| 353 | sqlite3PagerUnref(pDbPage); | - | ||||||||||||||||||
| 354 | return rc; executed 8 times by 1 test: return rc;Executed by:
| 8 | ||||||||||||||||||
| 355 | - | |||||||||||||||||||
| 356 | update_fail: | - | ||||||||||||||||||
| 357 | sqlite3_free(pVtab->zErrMsg); | - | ||||||||||||||||||
| 358 | pVtab->zErrMsg = sqlite3_mprintf("%s", zErr); | - | ||||||||||||||||||
| 359 | return SQLITE_ERROR; never executed: return 1; | 0 | ||||||||||||||||||
| 360 | } | - | ||||||||||||||||||
| 361 | - | |||||||||||||||||||
| 362 | /* Since we do not know in advance which database files will be | - | ||||||||||||||||||
| 363 | ** written by the sqlite_dbpage virtual table, start a write transaction | - | ||||||||||||||||||
| 364 | ** on them all. | - | ||||||||||||||||||
| 365 | */ | - | ||||||||||||||||||
| 366 | static int dbpageBegin(sqlite3_vtab *pVtab){ | - | ||||||||||||||||||
| 367 | DbpageTable *pTab = (DbpageTable *)pVtab; | - | ||||||||||||||||||
| 368 | sqlite3 *db = pTab->db; | - | ||||||||||||||||||
| 369 | int i; | - | ||||||||||||||||||
| 370 | for(i=0; i<db->nDb; i++){
| 8-20 | ||||||||||||||||||
| 371 | Btree *pBt = db->aDb[i].pBt; | - | ||||||||||||||||||
| 372 | if( pBt ) sqlite3BtreeBeginTrans(pBt, 1, 0); executed 19 times by 1 test: sqlite3BtreeBeginTrans(pBt, 1, 0);Executed by:
| 1-19 | ||||||||||||||||||
| 373 | } executed 20 times by 1 test: end of blockExecuted by:
| 20 | ||||||||||||||||||
| 374 | return SQLITE_OK; executed 8 times by 1 test: return 0;Executed by:
| 8 | ||||||||||||||||||
| 375 | } | - | ||||||||||||||||||
| 376 | - | |||||||||||||||||||
| 377 | - | |||||||||||||||||||
| 378 | /* | - | ||||||||||||||||||
| 379 | ** Invoke this routine to register the "dbpage" virtual table module | - | ||||||||||||||||||
| 380 | */ | - | ||||||||||||||||||
| 381 | int sqlite3DbpageRegister(sqlite3 *db){ | - | ||||||||||||||||||
| 382 | static sqlite3_module dbpage_module = { | - | ||||||||||||||||||
| 383 | 0, /* iVersion */ | - | ||||||||||||||||||
| 384 | dbpageConnect, /* xCreate */ | - | ||||||||||||||||||
| 385 | dbpageConnect, /* xConnect */ | - | ||||||||||||||||||
| 386 | dbpageBestIndex, /* xBestIndex */ | - | ||||||||||||||||||
| 387 | dbpageDisconnect, /* xDisconnect */ | - | ||||||||||||||||||
| 388 | dbpageDisconnect, /* xDestroy */ | - | ||||||||||||||||||
| 389 | dbpageOpen, /* xOpen - open a cursor */ | - | ||||||||||||||||||
| 390 | dbpageClose, /* xClose - close a cursor */ | - | ||||||||||||||||||
| 391 | dbpageFilter, /* xFilter - configure scan constraints */ | - | ||||||||||||||||||
| 392 | dbpageNext, /* xNext - advance a cursor */ | - | ||||||||||||||||||
| 393 | dbpageEof, /* xEof - check for end of scan */ | - | ||||||||||||||||||
| 394 | dbpageColumn, /* xColumn - read data */ | - | ||||||||||||||||||
| 395 | dbpageRowid, /* xRowid - read data */ | - | ||||||||||||||||||
| 396 | dbpageUpdate, /* xUpdate */ | - | ||||||||||||||||||
| 397 | dbpageBegin, /* xBegin */ | - | ||||||||||||||||||
| 398 | 0, /* xSync */ | - | ||||||||||||||||||
| 399 | 0, /* xCommit */ | - | ||||||||||||||||||
| 400 | 0, /* xRollback */ | - | ||||||||||||||||||
| 401 | 0, /* xFindMethod */ | - | ||||||||||||||||||
| 402 | 0, /* xRename */ | - | ||||||||||||||||||
| 403 | 0, /* xSavepoint */ | - | ||||||||||||||||||
| 404 | 0, /* xRelease */ | - | ||||||||||||||||||
| 405 | 0, /* xRollbackTo */ | - | ||||||||||||||||||
| 406 | }; | - | ||||||||||||||||||
| 407 | return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0); executed 31552 times by 438 tests: return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);Executed by:
| 31552 | ||||||||||||||||||
| 408 | } | - | ||||||||||||||||||
| 409 | #elif defined(SQLITE_ENABLE_DBPAGE_VTAB) | - | ||||||||||||||||||
| 410 | int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; } | - | ||||||||||||||||||
| 411 | #endif /* SQLITE_ENABLE_DBSTAT_VTAB */ | - | ||||||||||||||||||
| Source code | Switch to Preprocessed file |