xref: /sqlite-3.40.0/src/dbpage.c (revision c7dd9b60)
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 */
dbpageConnect(sqlite3 * db,void * pAux,int argc,const char * const * argv,sqlite3_vtab ** ppVtab,char ** pzErr)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   sqlite3_vtab_config(db, SQLITE_VTAB_DIRECTONLY);
77   rc = sqlite3_declare_vtab(db,
78           "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
79   if( rc==SQLITE_OK ){
80     pTab = (DbpageTable *)sqlite3_malloc64(sizeof(DbpageTable));
81     if( pTab==0 ) rc = SQLITE_NOMEM_BKPT;
82   }
83 
84   assert( rc==SQLITE_OK || pTab==0 );
85   if( rc==SQLITE_OK ){
86     memset(pTab, 0, sizeof(DbpageTable));
87     pTab->db = db;
88   }
89 
90   *ppVtab = (sqlite3_vtab*)pTab;
91   return rc;
92 }
93 
94 /*
95 ** Disconnect from or destroy a dbpagevfs virtual table.
96 */
dbpageDisconnect(sqlite3_vtab * pVtab)97 static int dbpageDisconnect(sqlite3_vtab *pVtab){
98   sqlite3_free(pVtab);
99   return SQLITE_OK;
100 }
101 
102 /*
103 ** idxNum:
104 **
105 **     0     schema=main, full table scan
106 **     1     schema=main, pgno=?1
107 **     2     schema=?1, full table scan
108 **     3     schema=?1, pgno=?2
109 */
dbpageBestIndex(sqlite3_vtab * tab,sqlite3_index_info * pIdxInfo)110 static int dbpageBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
111   int i;
112   int iPlan = 0;
113 
114   /* If there is a schema= constraint, it must be honored.  Report a
115   ** ridiculously large estimated cost if the schema= constraint is
116   ** unavailable
117   */
118   for(i=0; i<pIdxInfo->nConstraint; i++){
119     struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
120     if( p->iColumn!=DBPAGE_COLUMN_SCHEMA ) continue;
121     if( p->op!=SQLITE_INDEX_CONSTRAINT_EQ ) continue;
122     if( !p->usable ){
123       /* No solution. */
124       return SQLITE_CONSTRAINT;
125     }
126     iPlan = 2;
127     pIdxInfo->aConstraintUsage[i].argvIndex = 1;
128     pIdxInfo->aConstraintUsage[i].omit = 1;
129     break;
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++){
140     struct sqlite3_index_constraint *p = &pIdxInfo->aConstraint[i];
141     if( p->usable && p->iColumn<=0 && p->op==SQLITE_INDEX_CONSTRAINT_EQ ){
142       pIdxInfo->estimatedRows = 1;
143       pIdxInfo->idxFlags = SQLITE_INDEX_SCAN_UNIQUE;
144       pIdxInfo->estimatedCost = 1.0;
145       pIdxInfo->aConstraintUsage[i].argvIndex = iPlan ? 2 : 1;
146       pIdxInfo->aConstraintUsage[i].omit = 1;
147       iPlan |= 1;
148       break;
149     }
150   }
151   pIdxInfo->idxNum = iPlan;
152 
153   if( pIdxInfo->nOrderBy>=1
154    && pIdxInfo->aOrderBy[0].iColumn<=0
155    && pIdxInfo->aOrderBy[0].desc==0
156   ){
157     pIdxInfo->orderByConsumed = 1;
158   }
159   sqlite3VtabUsesAllSchemas(pIdxInfo);
160   return SQLITE_OK;
161 }
162 
163 /*
164 ** Open a new dbpagevfs cursor.
165 */
dbpageOpen(sqlite3_vtab * pVTab,sqlite3_vtab_cursor ** ppCursor)166 static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
167   DbpageCursor *pCsr;
168 
169   pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
170   if( pCsr==0 ){
171     return SQLITE_NOMEM_BKPT;
172   }else{
173     memset(pCsr, 0, sizeof(DbpageCursor));
174     pCsr->base.pVtab = pVTab;
175     pCsr->pgno = -1;
176   }
177 
178   *ppCursor = (sqlite3_vtab_cursor *)pCsr;
179   return SQLITE_OK;
180 }
181 
182 /*
183 ** Close a dbpagevfs cursor.
184 */
dbpageClose(sqlite3_vtab_cursor * pCursor)185 static int dbpageClose(sqlite3_vtab_cursor *pCursor){
186   DbpageCursor *pCsr = (DbpageCursor *)pCursor;
187   if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
188   sqlite3_free(pCsr);
189   return SQLITE_OK;
190 }
191 
192 /*
193 ** Move a dbpagevfs cursor to the next entry in the file.
194 */
dbpageNext(sqlite3_vtab_cursor * pCursor)195 static int dbpageNext(sqlite3_vtab_cursor *pCursor){
196   int rc = SQLITE_OK;
197   DbpageCursor *pCsr = (DbpageCursor *)pCursor;
198   pCsr->pgno++;
199   return rc;
200 }
201 
dbpageEof(sqlite3_vtab_cursor * pCursor)202 static int dbpageEof(sqlite3_vtab_cursor *pCursor){
203   DbpageCursor *pCsr = (DbpageCursor *)pCursor;
204   return pCsr->pgno > pCsr->mxPgno;
205 }
206 
207 /*
208 ** idxNum:
209 **
210 **     0     schema=main, full table scan
211 **     1     schema=main, pgno=?1
212 **     2     schema=?1, full table scan
213 **     3     schema=?1, pgno=?2
214 **
215 ** idxStr is not used
216 */
dbpageFilter(sqlite3_vtab_cursor * pCursor,int idxNum,const char * idxStr,int argc,sqlite3_value ** argv)217 static int dbpageFilter(
218   sqlite3_vtab_cursor *pCursor,
219   int idxNum, const char *idxStr,
220   int argc, sqlite3_value **argv
221 ){
222   DbpageCursor *pCsr = (DbpageCursor *)pCursor;
223   DbpageTable *pTab = (DbpageTable *)pCursor->pVtab;
224   int rc;
225   sqlite3 *db = pTab->db;
226   Btree *pBt;
227 
228   /* Default setting is no rows of result */
229   pCsr->pgno = 1;
230   pCsr->mxPgno = 0;
231 
232   if( idxNum & 2 ){
233     const char *zSchema;
234     assert( argc>=1 );
235     zSchema = (const char*)sqlite3_value_text(argv[0]);
236     pCsr->iDb = sqlite3FindDbName(db, zSchema);
237     if( pCsr->iDb<0 ) return SQLITE_OK;
238   }else{
239     pCsr->iDb = 0;
240   }
241   pBt = db->aDb[pCsr->iDb].pBt;
242   if( pBt==0 ) return SQLITE_OK;
243   pCsr->pPager = sqlite3BtreePager(pBt);
244   pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
245   pCsr->mxPgno = sqlite3BtreeLastPage(pBt);
246   if( idxNum & 1 ){
247     assert( argc>(idxNum>>1) );
248     pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
249     if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
250       pCsr->pgno = 1;
251       pCsr->mxPgno = 0;
252     }else{
253       pCsr->mxPgno = pCsr->pgno;
254     }
255   }else{
256     assert( pCsr->pgno==1 );
257   }
258   if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
259   rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0);
260   return rc;
261 }
262 
dbpageColumn(sqlite3_vtab_cursor * pCursor,sqlite3_context * ctx,int i)263 static int dbpageColumn(
264   sqlite3_vtab_cursor *pCursor,
265   sqlite3_context *ctx,
266   int i
267 ){
268   DbpageCursor *pCsr = (DbpageCursor *)pCursor;
269   int rc = SQLITE_OK;
270   switch( i ){
271     case 0: {           /* pgno */
272       sqlite3_result_int(ctx, pCsr->pgno);
273       break;
274     }
275     case 1: {           /* data */
276       DbPage *pDbPage = 0;
277       if( pCsr->pgno==((PENDING_BYTE/pCsr->szPage)+1) ){
278         /* The pending byte page. Assume it is zeroed out. Attempting to
279         ** request this page from the page is an SQLITE_CORRUPT error. */
280         sqlite3_result_zeroblob(ctx, pCsr->szPage);
281       }else{
282         rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
283         if( rc==SQLITE_OK ){
284           sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
285               SQLITE_TRANSIENT);
286         }
287         sqlite3PagerUnref(pDbPage);
288       }
289       break;
290     }
291     default: {          /* schema */
292       sqlite3 *db = sqlite3_context_db_handle(ctx);
293       sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC);
294       break;
295     }
296   }
297   return rc;
298 }
299 
dbpageRowid(sqlite3_vtab_cursor * pCursor,sqlite_int64 * pRowid)300 static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
301   DbpageCursor *pCsr = (DbpageCursor *)pCursor;
302   *pRowid = pCsr->pgno;
303   return SQLITE_OK;
304 }
305 
dbpageUpdate(sqlite3_vtab * pVtab,int argc,sqlite3_value ** argv,sqlite_int64 * pRowid)306 static int dbpageUpdate(
307   sqlite3_vtab *pVtab,
308   int argc,
309   sqlite3_value **argv,
310   sqlite_int64 *pRowid
311 ){
312   DbpageTable *pTab = (DbpageTable *)pVtab;
313   Pgno pgno;
314   DbPage *pDbPage = 0;
315   int rc = SQLITE_OK;
316   char *zErr = 0;
317   const char *zSchema;
318   int iDb;
319   Btree *pBt;
320   Pager *pPager;
321   int szPage;
322 
323   if( pTab->db->flags & SQLITE_Defensive ){
324     zErr = "read-only";
325     goto update_fail;
326   }
327   if( argc==1 ){
328     zErr = "cannot delete";
329     goto update_fail;
330   }
331   pgno = sqlite3_value_int(argv[0]);
332   if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){
333     zErr = "cannot insert";
334     goto update_fail;
335   }
336   zSchema = (const char*)sqlite3_value_text(argv[4]);
337   iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
338   if( iDb<0 ){
339     zErr = "no such schema";
340     goto update_fail;
341   }
342   pBt = pTab->db->aDb[iDb].pBt;
343   if( pgno<1 || pBt==0 || pgno>sqlite3BtreeLastPage(pBt) ){
344     zErr = "bad page number";
345     goto update_fail;
346   }
347   szPage = sqlite3BtreeGetPageSize(pBt);
348   if( sqlite3_value_type(argv[3])!=SQLITE_BLOB
349    || sqlite3_value_bytes(argv[3])!=szPage
350   ){
351     zErr = "bad page value";
352     goto update_fail;
353   }
354   pPager = sqlite3BtreePager(pBt);
355   rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
356   if( rc==SQLITE_OK ){
357     const void *pData = sqlite3_value_blob(argv[3]);
358     assert( pData!=0 || pTab->db->mallocFailed );
359     if( pData
360      && (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK
361     ){
362       memcpy(sqlite3PagerGetData(pDbPage), pData, szPage);
363     }
364   }
365   sqlite3PagerUnref(pDbPage);
366   return rc;
367 
368 update_fail:
369   sqlite3_free(pVtab->zErrMsg);
370   pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
371   return SQLITE_ERROR;
372 }
373 
374 /* Since we do not know in advance which database files will be
375 ** written by the sqlite_dbpage virtual table, start a write transaction
376 ** on them all.
377 */
dbpageBegin(sqlite3_vtab * pVtab)378 static int dbpageBegin(sqlite3_vtab *pVtab){
379   DbpageTable *pTab = (DbpageTable *)pVtab;
380   sqlite3 *db = pTab->db;
381   int i;
382   int rc = SQLITE_OK;
383   for(i=0; rc==SQLITE_OK && i<db->nDb; i++){
384     Btree *pBt = db->aDb[i].pBt;
385     if( pBt ) rc = sqlite3BtreeBeginTrans(pBt, 1, 0);
386   }
387   return rc;
388 }
389 
390 
391 /*
392 ** Invoke this routine to register the "dbpage" virtual table module
393 */
sqlite3DbpageRegister(sqlite3 * db)394 int sqlite3DbpageRegister(sqlite3 *db){
395   static sqlite3_module dbpage_module = {
396     0,                            /* iVersion */
397     dbpageConnect,                /* xCreate */
398     dbpageConnect,                /* xConnect */
399     dbpageBestIndex,              /* xBestIndex */
400     dbpageDisconnect,             /* xDisconnect */
401     dbpageDisconnect,             /* xDestroy */
402     dbpageOpen,                   /* xOpen - open a cursor */
403     dbpageClose,                  /* xClose - close a cursor */
404     dbpageFilter,                 /* xFilter - configure scan constraints */
405     dbpageNext,                   /* xNext - advance a cursor */
406     dbpageEof,                    /* xEof - check for end of scan */
407     dbpageColumn,                 /* xColumn - read data */
408     dbpageRowid,                  /* xRowid - read data */
409     dbpageUpdate,                 /* xUpdate */
410     dbpageBegin,                  /* xBegin */
411     0,                            /* xSync */
412     0,                            /* xCommit */
413     0,                            /* xRollback */
414     0,                            /* xFindMethod */
415     0,                            /* xRename */
416     0,                            /* xSavepoint */
417     0,                            /* xRelease */
418     0,                            /* xRollbackTo */
419     0                             /* xShadowName */
420   };
421   return sqlite3_create_module(db, "sqlite_dbpage", &dbpage_module, 0);
422 }
423 #elif defined(SQLITE_ENABLE_DBPAGE_VTAB)
sqlite3DbpageRegister(sqlite3 * db)424 int sqlite3DbpageRegister(sqlite3 *db){ return SQLITE_OK; }
425 #endif /* SQLITE_ENABLE_DBSTAT_VTAB */
426