4 ** The author disclaims copyright to this source code. In place of
5 ** a legal notice, here is a blessing:
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.
11 ******************************************************************************
13 ** This file contains an implementation of the "sqlite_dbpage" virtual table.
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
22 ** SELECT data FROM sqlite_dbpage('aux1') WHERE pgno=123;
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
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.
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)
38 typedef struct DbpageTable DbpageTable
;
39 typedef struct DbpageCursor 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 */
52 sqlite3_vtab base
; /* Base class. Must be first */
53 sqlite3
*db
; /* The database */
57 #define DBPAGE_COLUMN_PGNO 0
58 #define DBPAGE_COLUMN_DATA 1
59 #define DBPAGE_COLUMN_SCHEMA 2
64 ** Connect to or create a dbpagevfs virtual table.
66 static int dbpageConnect(
69 int argc
, const char *const*argv
,
70 sqlite3_vtab
**ppVtab
,
73 DbpageTable
*pTab
= 0;
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)");
80 pTab
= (DbpageTable
*)sqlite3_malloc64(sizeof(DbpageTable
));
81 if( pTab
==0 ) rc
= SQLITE_NOMEM_BKPT
;
84 assert( rc
==SQLITE_OK
|| pTab
==0 );
86 memset(pTab
, 0, sizeof(DbpageTable
));
90 *ppVtab
= (sqlite3_vtab
*)pTab
;
95 ** Disconnect from or destroy a dbpagevfs virtual table.
97 static int dbpageDisconnect(sqlite3_vtab
*pVtab
){
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
110 static int dbpageBestIndex(sqlite3_vtab
*tab
, sqlite3_index_info
*pIdxInfo
){
114 /* If there is a schema= constraint, it must be honored. Report a
115 ** ridiculously large estimated cost if the schema= constraint is
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;
124 return SQLITE_CONSTRAINT
;
127 pIdxInfo
->aConstraintUsage
[i
].argvIndex
= 1;
128 pIdxInfo
->aConstraintUsage
[i
].omit
= 1;
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
136 pIdxInfo
->estimatedCost
= 1.0e6
;
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;
151 pIdxInfo
->idxNum
= iPlan
;
153 if( pIdxInfo
->nOrderBy
>=1
154 && pIdxInfo
->aOrderBy
[0].iColumn
<=0
155 && pIdxInfo
->aOrderBy
[0].desc
==0
157 pIdxInfo
->orderByConsumed
= 1;
159 sqlite3VtabUsesAllSchemas(pIdxInfo
);
164 ** Open a new dbpagevfs cursor.
166 static int dbpageOpen(sqlite3_vtab
*pVTab
, sqlite3_vtab_cursor
**ppCursor
){
169 pCsr
= (DbpageCursor
*)sqlite3_malloc64(sizeof(DbpageCursor
));
171 return SQLITE_NOMEM_BKPT
;
173 memset(pCsr
, 0, sizeof(DbpageCursor
));
174 pCsr
->base
.pVtab
= pVTab
;
178 *ppCursor
= (sqlite3_vtab_cursor
*)pCsr
;
183 ** Close a dbpagevfs cursor.
185 static int dbpageClose(sqlite3_vtab_cursor
*pCursor
){
186 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
187 if( pCsr
->pPage1
) sqlite3PagerUnrefPageOne(pCsr
->pPage1
);
193 ** Move a dbpagevfs cursor to the next entry in the file.
195 static int dbpageNext(sqlite3_vtab_cursor
*pCursor
){
197 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
202 static int dbpageEof(sqlite3_vtab_cursor
*pCursor
){
203 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
204 return pCsr
->pgno
> pCsr
->mxPgno
;
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
215 ** idxStr is not used
217 static int dbpageFilter(
218 sqlite3_vtab_cursor
*pCursor
,
219 int idxNum
, const char *idxStr
,
220 int argc
, sqlite3_value
**argv
222 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
223 DbpageTable
*pTab
= (DbpageTable
*)pCursor
->pVtab
;
225 sqlite3
*db
= pTab
->db
;
228 /* Default setting is no rows of result */
235 zSchema
= (const char*)sqlite3_value_text(argv
[0]);
236 pCsr
->iDb
= sqlite3FindDbName(db
, zSchema
);
237 if( pCsr
->iDb
<0 ) return SQLITE_OK
;
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
);
247 assert( argc
>(idxNum
>>1) );
248 pCsr
->pgno
= sqlite3_value_int(argv
[idxNum
>>1]);
249 if( pCsr
->pgno
<1 || pCsr
->pgno
>pCsr
->mxPgno
){
253 pCsr
->mxPgno
= pCsr
->pgno
;
256 assert( pCsr
->pgno
==1 );
258 if( pCsr
->pPage1
) sqlite3PagerUnrefPageOne(pCsr
->pPage1
);
259 rc
= sqlite3PagerGet(pCsr
->pPager
, 1, &pCsr
->pPage1
, 0);
263 static int dbpageColumn(
264 sqlite3_vtab_cursor
*pCursor
,
265 sqlite3_context
*ctx
,
268 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
272 sqlite3_result_int(ctx
, pCsr
->pgno
);
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
);
282 rc
= sqlite3PagerGet(pCsr
->pPager
, pCsr
->pgno
, (DbPage
**)&pDbPage
, 0);
284 sqlite3_result_blob(ctx
, sqlite3PagerGetData(pDbPage
), pCsr
->szPage
,
287 sqlite3PagerUnref(pDbPage
);
291 default: { /* schema */
292 sqlite3
*db
= sqlite3_context_db_handle(ctx
);
293 sqlite3_result_text(ctx
, db
->aDb
[pCsr
->iDb
].zDbSName
, -1, SQLITE_STATIC
);
300 static int dbpageRowid(sqlite3_vtab_cursor
*pCursor
, sqlite_int64
*pRowid
){
301 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
302 *pRowid
= pCsr
->pgno
;
306 static int dbpageUpdate(
309 sqlite3_value
**argv
,
312 DbpageTable
*pTab
= (DbpageTable
*)pVtab
;
323 if( pTab
->db
->flags
& SQLITE_Defensive
){
328 zErr
= "cannot delete";
331 pgno
= sqlite3_value_int(argv
[0]);
332 if( (Pgno
)sqlite3_value_int(argv
[1])!=pgno
){
333 zErr
= "cannot insert";
336 zSchema
= (const char*)sqlite3_value_text(argv
[4]);
337 iDb
= zSchema
? sqlite3FindDbName(pTab
->db
, zSchema
) : -1;
339 zErr
= "no such schema";
342 pBt
= pTab
->db
->aDb
[iDb
].pBt
;
343 if( pgno
<1 || pBt
==0 || pgno
>sqlite3BtreeLastPage(pBt
) ){
344 zErr
= "bad page number";
347 szPage
= sqlite3BtreeGetPageSize(pBt
);
348 if( sqlite3_value_type(argv
[3])!=SQLITE_BLOB
349 || sqlite3_value_bytes(argv
[3])!=szPage
351 zErr
= "bad page value";
354 pPager
= sqlite3BtreePager(pBt
);
355 rc
= sqlite3PagerGet(pPager
, pgno
, (DbPage
**)&pDbPage
, 0);
357 const void *pData
= sqlite3_value_blob(argv
[3]);
358 assert( pData
!=0 || pTab
->db
->mallocFailed
);
360 && (rc
= sqlite3PagerWrite(pDbPage
))==SQLITE_OK
362 memcpy(sqlite3PagerGetData(pDbPage
), pData
, szPage
);
365 sqlite3PagerUnref(pDbPage
);
369 sqlite3_free(pVtab
->zErrMsg
);
370 pVtab
->zErrMsg
= sqlite3_mprintf("%s", zErr
);
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
378 static int dbpageBegin(sqlite3_vtab
*pVtab
){
379 DbpageTable
*pTab
= (DbpageTable
*)pVtab
;
380 sqlite3
*db
= pTab
->db
;
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);
392 ** Invoke this routine to register the "dbpage" virtual table module
394 int sqlite3DbpageRegister(sqlite3
*db
){
395 static sqlite3_module dbpage_module
= {
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 */
421 return sqlite3_create_module(db
, "sqlite_dbpage", &dbpage_module
, 0);
423 #elif defined(SQLITE_ENABLE_DBPAGE_VTAB)
424 int sqlite3DbpageRegister(sqlite3
*db
){ return SQLITE_OK
; }
425 #endif /* SQLITE_ENABLE_DBSTAT_VTAB */