Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch dbpage Excluding Merge-Ins
This is equivalent to a diff from fe0d67e72d to 6aa9c8e79b
2024-09-13
| ||
23:41 | Merge sqlite_dbpage fixes into the sqlite3-rsync branch. (check-in: dff76b7a34 user: drh tags: sqlite3-rsync) | |
21:47 | Bug fix in the enhanced sqlite_dbpage for when truncating two or more ATTACH-ed databases within the same transaction. (Leaf check-in: 6aa9c8e79b user: drh tags: dbpage) | |
2024-09-10
| ||
12:09 | Add the ability for sqlite_dbpage to truncate the database file by writing a NULL page. Experimental. (check-in: eb3c89ee2e user: drh tags: dbpage) | |
2024-09-09
| ||
19:12 | Fix an OOM-handling problem affecting locale=1 fts5 tables. (check-in: d8103684f6 user: dan tags: trunk) | |
18:45 | Generalize the sqlite3_dbpage virtual table so that it is able to write new pages onto the end of the database file using INSERT. (check-in: fe0d67e72d user: drh tags: trunk) | |
15:39 | Move the vfstrace extension out of src/ and into ext/misc/. Make it a standard part of the CLI. Improve its output. Also fix some unrelated comment typos. (check-in: 123cb1f579 user: drh tags: trunk) | |
Changes to src/dbpage.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** This is an eponymous virtual table so it does not need to be created before ** use. The optional argument to the sqlite_dbpage() table name is the ** schema for the database file that is to be read. The default schema is ** "main". ** ** The data field of sqlite_dbpage table can be updated. The new ** value must be a BLOB which is the correct page size, otherwise the | > > > > | > > | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | ** This is an eponymous virtual table so it does not need to be created before ** use. The optional argument to the sqlite_dbpage() table name is the ** schema for the database file that is to be read. The default schema is ** "main". ** ** The data field of sqlite_dbpage table can be updated. The new ** value must be a BLOB which is the correct page size, otherwise the ** update fails. INSERT operations also work, and operate as if they ** where REPLACE. The size of the database can be extended by INSERT-ing ** new pages on the end. ** ** Rows may not be deleted. However, doing an INSERT to page number N ** with NULL page data causes the N-th page and all subsequent pages to be ** deleted and the database to be truncated. */ #include "sqliteInt.h" /* Requires access to internal data structures */ #if (defined(SQLITE_ENABLE_DBPAGE_VTAB) || defined(SQLITE_TEST)) \ && !defined(SQLITE_OMIT_VIRTUALTABLE) typedef struct DbpageTable DbpageTable; |
︙ | ︙ | |||
47 48 49 50 51 52 53 54 55 56 57 58 59 | int iDb; /* Index of database to analyze */ int szPage; /* Size of each page in bytes */ }; struct DbpageTable { sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* The database */ }; /* Columns */ #define DBPAGE_COLUMN_PGNO 0 #define DBPAGE_COLUMN_DATA 1 #define DBPAGE_COLUMN_SCHEMA 2 | > > < | 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 | int iDb; /* Index of database to analyze */ int szPage; /* Size of each page in bytes */ }; struct DbpageTable { sqlite3_vtab base; /* Base class. Must be first */ sqlite3 *db; /* The database */ int nTrunc; /* Entries in aTrunc[] */ Pgno *aTrunc; /* Truncation size for each database */ }; /* Columns */ #define DBPAGE_COLUMN_PGNO 0 #define DBPAGE_COLUMN_DATA 1 #define DBPAGE_COLUMN_SCHEMA 2 /* ** Connect to or create a dbpagevfs virtual table. */ static int dbpageConnect( sqlite3 *db, |
︙ | ︙ | |||
96 97 98 99 100 101 102 103 104 105 106 107 108 109 | return rc; } /* ** Disconnect from or destroy a dbpagevfs virtual table. */ static int dbpageDisconnect(sqlite3_vtab *pVtab){ sqlite3_free(pVtab); return SQLITE_OK; } /* ** idxNum: ** | > > | 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 | return rc; } /* ** Disconnect from or destroy a dbpagevfs virtual table. */ static int dbpageDisconnect(sqlite3_vtab *pVtab){ DbpageTable *pTab = (DbpageTable *)pVtab; sqlite3_free(pTab->aTrunc); sqlite3_free(pVtab); return SQLITE_OK; } /* ** idxNum: ** |
︙ | ︙ | |||
321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 | DbPage *pDbPage = 0; int rc = SQLITE_OK; char *zErr = 0; int iDb; Btree *pBt; Pager *pPager; int szPage; (void)pRowid; if( pTab->db->flags & SQLITE_Defensive ){ zErr = "read-only"; goto update_fail; } if( argc==1 ){ zErr = "cannot delete"; goto update_fail; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ pgno = (Pgno)sqlite3_value_int(argv[2]); }else{ pgno = sqlite3_value_int(argv[0]); if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ zErr = "cannot insert"; goto update_fail; } } if( sqlite3_value_type(argv[4])==SQLITE_NULL ){ iDb = 0; }else{ const char *zSchema = (const char*)sqlite3_value_text(argv[4]); | > > > | > > > > > > > > > > > > > > | | > < < | < | > | 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 | DbPage *pDbPage = 0; int rc = SQLITE_OK; char *zErr = 0; int iDb; Btree *pBt; Pager *pPager; int szPage; int isInsert; (void)pRowid; if( pTab->db->flags & SQLITE_Defensive ){ zErr = "read-only"; goto update_fail; } if( argc==1 ){ zErr = "cannot delete"; goto update_fail; } if( sqlite3_value_type(argv[0])==SQLITE_NULL ){ pgno = (Pgno)sqlite3_value_int(argv[2]); isInsert = 1; }else{ pgno = sqlite3_value_int(argv[0]); if( (Pgno)sqlite3_value_int(argv[1])!=pgno ){ zErr = "cannot insert"; goto update_fail; } isInsert = 0; } if( sqlite3_value_type(argv[4])==SQLITE_NULL ){ iDb = 0; }else{ const char *zSchema = (const char*)sqlite3_value_text(argv[4]); iDb = sqlite3FindDbName(pTab->db, zSchema); if( iDb<0 ){ zErr = "no such schema"; goto update_fail; } } pBt = pTab->db->aDb[iDb].pBt; if( pgno<1 || NEVER(pBt==0) ){ zErr = "bad page number"; goto update_fail; } szPage = sqlite3BtreeGetPageSize(pBt); if( sqlite3_value_type(argv[3])!=SQLITE_BLOB || sqlite3_value_bytes(argv[3])!=szPage ){ if( sqlite3_value_type(argv[3])==SQLITE_NULL && isInsert ){ if( iDb>=pTab->nTrunc ){ testcase( pTab->aTrunc!=0 ); pTab->aTrunc = sqlite3_realloc(pTab->aTrunc, (iDb+1)*sizeof(Pgno)); if( pTab->aTrunc ){ int j; for(j=pTab->nTrunc; j<iDb; j++) pTab->aTrunc[j] = 0; pTab->nTrunc = iDb+1; }else{ return SQLITE_NOMEM; } } pTab->aTrunc[iDb] = pgno; }else{ zErr = "bad page value"; goto update_fail; } } pPager = sqlite3BtreePager(pBt); rc = sqlite3PagerGet(pPager, pgno, (DbPage**)&pDbPage, 0); if( rc==SQLITE_OK ){ const void *pData = sqlite3_value_blob(argv[3]); if( (rc = sqlite3PagerWrite(pDbPage))==SQLITE_OK && pData ){ unsigned char *aPage = sqlite3PagerGetData(pDbPage); memcpy(aPage, pData, szPage); } } sqlite3PagerUnref(pDbPage); return rc; update_fail: sqlite3_free(pVtab->zErrMsg); |
︙ | ︙ | |||
393 394 395 396 397 398 399 400 401 402 403 404 405 406 | static int dbpageBegin(sqlite3_vtab *pVtab){ DbpageTable *pTab = (DbpageTable *)pVtab; sqlite3 *db = pTab->db; int i; for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0); } return SQLITE_OK; } /* ** Invoke this routine to register the "dbpage" virtual table module | > > > > > > > > > > > > > > > > > > > > | 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 | static int dbpageBegin(sqlite3_vtab *pVtab){ DbpageTable *pTab = (DbpageTable *)pVtab; sqlite3 *db = pTab->db; int i; for(i=0; i<db->nDb; i++){ Btree *pBt = db->aDb[i].pBt; if( pBt ) (void)sqlite3BtreeBeginTrans(pBt, 1, 0); } if( pTab->nTrunc>0 ){ memset(pTab->aTrunc, 0, sizeof(pTab->aTrunc[0])*pTab->nTrunc); } return SQLITE_OK; } /* Invoke sqlite3PagerTruncate() as necessary, just prior to COMMIT */ static int dbpageSync(sqlite3_vtab *pVtab){ int iDb; DbpageTable *pTab = (DbpageTable *)pVtab; for(iDb=0; iDb<pTab->nTrunc; iDb++){ if( pTab->aTrunc[iDb]>0 ){ Btree *pBt = pTab->db->aDb[iDb].pBt; Pager *pPager = sqlite3BtreePager(pBt); sqlite3PagerTruncateImage(pPager, pTab->aTrunc[iDb]); pTab->aTrunc[iDb] = 0; } } return SQLITE_OK; } /* ** Invoke this routine to register the "dbpage" virtual table module |
︙ | ︙ | |||
418 419 420 421 422 423 424 | dbpageFilter, /* xFilter - configure scan constraints */ dbpageNext, /* xNext - advance a cursor */ dbpageEof, /* xEof - check for end of scan */ dbpageColumn, /* xColumn - read data */ dbpageRowid, /* xRowid - read data */ dbpageUpdate, /* xUpdate */ dbpageBegin, /* xBegin */ | | | 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 | dbpageFilter, /* xFilter - configure scan constraints */ dbpageNext, /* xNext - advance a cursor */ dbpageEof, /* xEof - check for end of scan */ dbpageColumn, /* xColumn - read data */ dbpageRowid, /* xRowid - read data */ dbpageUpdate, /* xUpdate */ dbpageBegin, /* xBegin */ dbpageSync, /* xSync */ 0, /* xCommit */ 0, /* xRollback */ 0, /* xFindMethod */ 0, /* xRename */ 0, /* xSavepoint */ 0, /* xRelease */ 0, /* xRollbackTo */ |
︙ | ︙ |