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