Fix harmless compiler warnings.
[sqlite.git] / src / dbpage.c
blob75e4c42e67243fbe8e5505ca2d3d116b2637e704
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.
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
18 ** retrieved.
20 ** Usage example:
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
27 ** "main".
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;
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 */
51 struct DbpageTable {
52 sqlite3_vtab base; /* Base class. Must be first */
53 sqlite3 *db; /* The database */
56 /* Columns */
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(
67 sqlite3 *db,
68 void *pAux,
69 int argc, const char *const*argv,
70 sqlite3_vtab **ppVtab,
71 char **pzErr
73 DbpageTable *pTab = 0;
74 int rc = SQLITE_OK;
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;
83 assert( rc==SQLITE_OK || pTab==0 );
84 if( rc==SQLITE_OK ){
85 memset(pTab, 0, sizeof(DbpageTable));
86 pTab->db = db;
89 *ppVtab = (sqlite3_vtab*)pTab;
90 return rc;
94 ** Disconnect from or destroy a dbpagevfs virtual table.
96 static int dbpageDisconnect(sqlite3_vtab *pVtab){
97 sqlite3_free(pVtab);
98 return SQLITE_OK;
102 ** idxNum:
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){
110 int i;
111 int iPlan = 0;
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
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. Use the default SQLITE_BIG_DBL cost */
123 pIdxInfo->estimatedRows = 0x7fffffff;
124 return SQLITE_OK;
126 iPlan = 2;
127 pIdxInfo->aConstraintUsage[i].argvIndex = 1;
128 pIdxInfo->aConstraintUsage[i].omit = 1;
129 break;
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;
147 iPlan |= 1;
148 break;
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 return SQLITE_OK;
163 ** Open a new dbpagevfs cursor.
165 static int dbpageOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
166 DbpageCursor *pCsr;
168 pCsr = (DbpageCursor *)sqlite3_malloc64(sizeof(DbpageCursor));
169 if( pCsr==0 ){
170 return SQLITE_NOMEM_BKPT;
171 }else{
172 memset(pCsr, 0, sizeof(DbpageCursor));
173 pCsr->base.pVtab = pVTab;
174 pCsr->pgno = -1;
177 *ppCursor = (sqlite3_vtab_cursor *)pCsr;
178 return SQLITE_OK;
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);
187 sqlite3_free(pCsr);
188 return SQLITE_OK;
192 ** Move a dbpagevfs cursor to the next entry in the file.
194 static int dbpageNext(sqlite3_vtab_cursor *pCursor){
195 int rc = SQLITE_OK;
196 DbpageCursor *pCsr = (DbpageCursor *)pCursor;
197 pCsr->pgno++;
198 return rc;
201 static int dbpageEof(sqlite3_vtab_cursor *pCursor){
202 DbpageCursor *pCsr = (DbpageCursor *)pCursor;
203 return pCsr->pgno > pCsr->mxPgno;
207 ** idxNum:
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;
223 int rc;
224 sqlite3 *db = pTab->db;
225 Btree *pBt;
227 /* Default setting is no rows of result */
228 pCsr->pgno = 1;
229 pCsr->mxPgno = 0;
231 if( idxNum & 2 ){
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;
237 }else{
238 pCsr->iDb = 0;
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);
245 if( idxNum & 1 ){
246 assert( argc>(idxNum>>1) );
247 pCsr->pgno = sqlite3_value_int(argv[idxNum>>1]);
248 if( pCsr->pgno<1 || pCsr->pgno>pCsr->mxPgno ){
249 pCsr->pgno = 1;
250 pCsr->mxPgno = 0;
251 }else{
252 pCsr->mxPgno = pCsr->pgno;
254 }else{
255 assert( pCsr->pgno==1 );
257 if( pCsr->pPage1 ) sqlite3PagerUnrefPageOne(pCsr->pPage1);
258 rc = sqlite3PagerGet(pCsr->pPager, 1, &pCsr->pPage1, 0);
259 return rc;
262 static int dbpageColumn(
263 sqlite3_vtab_cursor *pCursor,
264 sqlite3_context *ctx,
265 int i
267 DbpageCursor *pCsr = (DbpageCursor *)pCursor;
268 int rc = SQLITE_OK;
269 switch( i ){
270 case 0: { /* pgno */
271 sqlite3_result_int(ctx, pCsr->pgno);
272 break;
274 case 1: { /* data */
275 DbPage *pDbPage = 0;
276 rc = sqlite3PagerGet(pCsr->pPager, pCsr->pgno, (DbPage**)&pDbPage, 0);
277 if( rc==SQLITE_OK ){
278 sqlite3_result_blob(ctx, sqlite3PagerGetData(pDbPage), pCsr->szPage,
279 SQLITE_TRANSIENT);
281 sqlite3PagerUnref(pDbPage);
282 break;
284 default: { /* schema */
285 sqlite3 *db = sqlite3_context_db_handle(ctx);
286 sqlite3_result_text(ctx, db->aDb[pCsr->iDb].zDbSName, -1, SQLITE_STATIC);
287 break;
290 return SQLITE_OK;
293 static int dbpageRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
294 DbpageCursor *pCsr = (DbpageCursor *)pCursor;
295 *pRowid = pCsr->pgno;
296 return SQLITE_OK;
299 static int dbpageUpdate(
300 sqlite3_vtab *pVtab,
301 int argc,
302 sqlite3_value **argv,
303 sqlite_int64 *pRowid
305 DbpageTable *pTab = (DbpageTable *)pVtab;
306 int 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;
316 if( argc==1 ){
317 zErr = "cannot delete";
318 goto update_fail;
320 pgno = sqlite3_value_int(argv[0]);
321 if( sqlite3_value_int(argv[1])!=pgno ){
322 zErr = "cannot insert";
323 goto update_fail;
325 zSchema = (const char*)sqlite3_value_text(argv[4]);
326 iDb = zSchema ? sqlite3FindDbName(pTab->db, zSchema) : -1;
327 if( iDb<0 ){
328 zErr = "no such schema";
329 goto update_fail;
331 pBt = pTab->db->aDb[iDb].pBt;
332 if( pgno<1 || pBt==0 || pgno>(int)sqlite3BtreeLastPage(pBt) ){
333 zErr = "bad page number";
334 goto update_fail;
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";
341 goto update_fail;
343 pPager = sqlite3BtreePager(pBt);
344 rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0);
345 if( rc==SQLITE_OK ){
346 rc = sqlite3PagerWrite(pDbPage);
347 if( rc==SQLITE_OK ){
348 memcpy(sqlite3PagerGetData(pDbPage),
349 sqlite3_value_blob(argv[3]),
350 szPage);
353 sqlite3PagerUnref(pDbPage);
354 return rc;
356 update_fail:
357 sqlite3_free(pVtab->zErrMsg);
358 pVtab->zErrMsg = sqlite3_mprintf("%s", zErr);
359 return SQLITE_ERROR;
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.
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++){
371 Btree *pBt = db->aDb[i].pBt;
372 if( pBt ) sqlite3BtreeBeginTrans(pBt, 1);
374 return SQLITE_OK;
379 ** Invoke this routine to register the "dbpage" virtual table module
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 */
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 */