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 rc
= sqlite3_declare_vtab(db
,
77 "CREATE TABLE x(pgno INTEGER PRIMARY KEY, data BLOB, schema HIDDEN)");
79 pTab
= (DbpageTable
*)sqlite3_malloc64(sizeof(DbpageTable
));
80 if( pTab
==0 ) rc
= SQLITE_NOMEM_BKPT
;
83 assert( rc
==SQLITE_OK
|| pTab
==0 );
85 memset(pTab
, 0, sizeof(DbpageTable
));
89 *ppVtab
= (sqlite3_vtab
*)pTab
;
94 ** Disconnect from or destroy a dbpagevfs virtual table.
96 static int dbpageDisconnect(sqlite3_vtab
*pVtab
){
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
109 static int dbpageBestIndex(sqlite3_vtab
*tab
, sqlite3_index_info
*pIdxInfo
){
113 /* If there is a schema= constraint, it must be honored. Report a
114 ** ridiculously large estimated cost if the schema= constraint is
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;
122 /* No solution. Use the default SQLITE_BIG_DBL cost */
123 pIdxInfo
->estimatedRows
= 0x7fffffff;
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;
163 ** Open a new dbpagevfs cursor.
165 static int dbpageOpen(sqlite3_vtab
*pVTab
, sqlite3_vtab_cursor
**ppCursor
){
168 pCsr
= (DbpageCursor
*)sqlite3_malloc64(sizeof(DbpageCursor
));
170 return SQLITE_NOMEM_BKPT
;
172 memset(pCsr
, 0, sizeof(DbpageCursor
));
173 pCsr
->base
.pVtab
= pVTab
;
177 *ppCursor
= (sqlite3_vtab_cursor
*)pCsr
;
182 ** Close a dbpagevfs cursor.
184 static int dbpageClose(sqlite3_vtab_cursor
*pCursor
){
185 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
186 if( pCsr
->pPage1
) sqlite3PagerUnrefPageOne(pCsr
->pPage1
);
192 ** Move a dbpagevfs cursor to the next entry in the file.
194 static int dbpageNext(sqlite3_vtab_cursor
*pCursor
){
196 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
201 static int dbpageEof(sqlite3_vtab_cursor
*pCursor
){
202 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
203 return pCsr
->pgno
> pCsr
->mxPgno
;
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
214 ** idxStr is not used
216 static int dbpageFilter(
217 sqlite3_vtab_cursor
*pCursor
,
218 int idxNum
, const char *idxStr
,
219 int argc
, sqlite3_value
**argv
221 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
222 DbpageTable
*pTab
= (DbpageTable
*)pCursor
->pVtab
;
224 sqlite3
*db
= pTab
->db
;
227 /* Default setting is no rows of result */
234 zSchema
= (const char*)sqlite3_value_text(argv
[0]);
235 pCsr
->iDb
= sqlite3FindDbName(db
, zSchema
);
236 if( pCsr
->iDb
<0 ) return SQLITE_OK
;
240 pBt
= db
->aDb
[pCsr
->iDb
].pBt
;
241 if( pBt
==0 ) return SQLITE_OK
;
242 pCsr
->pPager
= sqlite3BtreePager(pBt
);
243 pCsr
->szPage
= sqlite3BtreeGetPageSize(pBt
);
244 pCsr
->mxPgno
= sqlite3BtreeLastPage(pBt
);
246 assert( argc
>(idxNum
>>1) );
247 pCsr
->pgno
= sqlite3_value_int(argv
[idxNum
>>1]);
248 if( pCsr
->pgno
<1 || pCsr
->pgno
>pCsr
->mxPgno
){
252 pCsr
->mxPgno
= pCsr
->pgno
;
255 assert( pCsr
->pgno
==1 );
257 if( pCsr
->pPage1
) sqlite3PagerUnrefPageOne(pCsr
->pPage1
);
258 rc
= sqlite3PagerGet(pCsr
->pPager
, 1, &pCsr
->pPage1
, 0);
262 static int dbpageColumn(
263 sqlite3_vtab_cursor
*pCursor
,
264 sqlite3_context
*ctx
,
267 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
271 sqlite3_result_int(ctx
, pCsr
->pgno
);
276 rc
= sqlite3PagerGet(pCsr
->pPager
, pCsr
->pgno
, (DbPage
**)&pDbPage
, 0);
278 sqlite3_result_blob(ctx
, sqlite3PagerGetData(pDbPage
), pCsr
->szPage
,
281 sqlite3PagerUnref(pDbPage
);
284 default: { /* schema */
285 sqlite3
*db
= sqlite3_context_db_handle(ctx
);
286 sqlite3_result_text(ctx
, db
->aDb
[pCsr
->iDb
].zDbSName
, -1, SQLITE_STATIC
);
293 static int dbpageRowid(sqlite3_vtab_cursor
*pCursor
, sqlite_int64
*pRowid
){
294 DbpageCursor
*pCsr
= (DbpageCursor
*)pCursor
;
295 *pRowid
= pCsr
->pgno
;
299 static int dbpageUpdate(
302 sqlite3_value
**argv
,
305 DbpageTable
*pTab
= (DbpageTable
*)pVtab
;
317 zErr
= "cannot delete";
320 pgno
= sqlite3_value_int(argv
[0]);
321 if( sqlite3_value_int(argv
[1])!=pgno
){
322 zErr
= "cannot insert";
325 zSchema
= (const char*)sqlite3_value_text(argv
[4]);
326 iDb
= zSchema
? sqlite3FindDbName(pTab
->db
, zSchema
) : -1;
328 zErr
= "no such schema";
331 pBt
= pTab
->db
->aDb
[iDb
].pBt
;
332 if( pgno
<1 || pBt
==0 || pgno
>(int)sqlite3BtreeLastPage(pBt
) ){
333 zErr
= "bad page number";
336 szPage
= sqlite3BtreeGetPageSize(pBt
);
337 if( sqlite3_value_type(argv
[3])!=SQLITE_BLOB
338 || sqlite3_value_bytes(argv
[3])!=szPage
340 zErr
= "bad page value";
343 pPager
= sqlite3BtreePager(pBt
);
344 rc
= sqlite3PagerGet(pPager
, pgno
, (DbPage
**)&pDbPage
, 0);
346 rc
= sqlite3PagerWrite(pDbPage
);
348 memcpy(sqlite3PagerGetData(pDbPage
),
349 sqlite3_value_blob(argv
[3]),
353 sqlite3PagerUnref(pDbPage
);
357 sqlite3_free(pVtab
->zErrMsg
);
358 pVtab
->zErrMsg
= sqlite3_mprintf("%s", zErr
);
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
366 static int dbpageBegin(sqlite3_vtab
*pVtab
){
367 DbpageTable
*pTab
= (DbpageTable
*)pVtab
;
368 sqlite3
*db
= pTab
->db
;
370 for(i
=0; i
<db
->nDb
; i
++){
371 Btree
*pBt
= db
->aDb
[i
].pBt
;
372 if( pBt
) sqlite3BtreeBeginTrans(pBt
, 1);
379 ** Invoke this routine to register the "dbpage" virtual table module
381 int sqlite3DbpageRegister(sqlite3
*db
){
382 static sqlite3_module dbpage_module
= {
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 */
407 return sqlite3_create_module(db
, "sqlite_dbpage", &dbpage_module
, 0);
409 #elif defined(SQLITE_ENABLE_DBPAGE_VTAB)
410 int sqlite3DbpageRegister(sqlite3
*db
){ return SQLITE_OK
; }
411 #endif /* SQLITE_ENABLE_DBSTAT_VTAB */