Skip to content

Commit 0e52527

Browse files
committed
Add import for existing databases.
1 parent 575637d commit 0e52527

File tree

2 files changed

+93
-14
lines changed

2 files changed

+93
-14
lines changed

ceshim.c

Lines changed: 86 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "pager.h"
1010
#include "btreeInt.h"
1111
#endif
12+
#include <sys/stat.h>
1213
#include <zlib.h>
1314
#include "ceshim.h"
1415

@@ -104,21 +105,17 @@ struct __attribute__ ((__packed__)) ceshim_map_entry {
104105
** An instance of this structure is attached to each ceshim VFS to
105106
** provide auxiliary non-persisted information.
106107
*/
108+
typedef struct ceshim_file ceshim_file;
107109
typedef struct ceshim_info ceshim_info;
108110
struct ceshim_info {
109-
sqlite3_vfs *pRootVfs; /* The underlying real VFS */
110-
111-
// Pointers to custom compress functions implemented by the user
112-
int (*xCompressBound)(void *pCtx, int nSrc);
113-
int (*xCompress)(void *pCtx, char *aDest, int *pnDest, char *aSrc, int nSrc);
114-
int (*xUncompress)(void *pCtx, char *aDest, int *pnDest, char *aSrc, int nSrc);
115-
116-
const char *zVfsName; /* Name of this VFS */
117-
char *zUppJournalPath; /* Path to redirect upper journal */
118-
sqlite3_vfs *pCeshimVfs; /* Pointer back to the ceshim VFS */
119-
unsigned char zDbHeader[100]; /* Sqlite3 DB header */
120-
ceshim_header ceshimHeader; /* Ceshim header with page mapping data */
121-
CeshimMemPage *pPage1; /* Page 1 of the pager */
111+
sqlite3_vfs *pRootVfs; // The underlying real VFS
112+
const char *zVfsName; // Name of this VFS
113+
char *zUppJournalPath; // Path to redirect upper journal
114+
sqlite3_vfs *pCeshimVfs; // Pointer back to the ceshim VFS
115+
ceshim_file *pFile; // Pointer back to the ceshim_file representing the dest. db.
116+
unsigned char zDbHeader[100]; // Sqlite3 DB header
117+
ceshim_header ceshimHeader; // Ceshim header with page mapping data
118+
CeshimMemPage *pPage1; // Page 1 of the pager
122119
Pgno lwrPageFile; // max pgno in lower pager, used to update pager header
123120
CeshimMMTblEntry *mmTbl; // The master mapping table
124121
u16 mmTblCurrIx; // Index of the current page map in mmTbl
@@ -134,12 +131,16 @@ struct ceshim_info {
134131
// bools
135132
u8 bPgMapDirty:1; // Curr page map needs to be persisted
136133
u8 bReadOnly:1; // True when db was open for read-only
134+
135+
// Pointers to custom compress functions implemented by the user
136+
int (*xCompressBound)(void *pCtx, int nSrc);
137+
int (*xCompress)(void *pCtx, char *aDest, int *pnDest, char *aSrc, int nSrc);
138+
int (*xUncompress)(void *pCtx, char *aDest, int *pnDest, char *aSrc, int nSrc);
137139
};
138140

139141
/*
140142
** The sqlite3_file object for the shim.
141143
*/
142-
typedef struct ceshim_file ceshim_file;
143144
struct ceshim_file {
144145
sqlite3_file base; /* Base class. Must be first */
145146
ceshim_info *pInfo; /* Custom info for this file */
@@ -1419,6 +1420,9 @@ static int ceshimOpen(
14191420
p->zFName = zName ? fileTail(zName) : "<temp>";
14201421
p->pReal = (sqlite3_file *)&p[1];
14211422
p->pPager = NULL;
1423+
1424+
// We need this for import
1425+
pInfo->pFile = p;
14221426

14231427
// Process URI parameters
14241428
if( flags & SQLITE_OPEN_URI){
@@ -1812,3 +1816,71 @@ SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod(
18121816
){
18131817
_ceshim_register("ceshim-cli", NULL, NULL, ceshimDefaultCompressBound, ceshimDefaultCompress, ceshimDefaultUncompress, 1);
18141818
}
1819+
1820+
int ceshimBuild(const char *srcDbPath, const char *destUri){
1821+
int rc = SQLITE_ERROR;
1822+
unsigned char zDbHeader[100];
1823+
1824+
// _ceshim_register must be done early enough to avoid SQLITE_MISUSE error
1825+
if( (rc = _ceshim_register("ceshim-build", NULL, NULL, ceshimDefaultCompressBound, ceshimDefaultCompress, ceshimDefaultUncompress, 0))==SQLITE_OK ){
1826+
sqlite3_vfs *pVfs = sqlite3_vfs_find(NULL);
1827+
if( pVfs ){
1828+
Pager *pPager;
1829+
int vfsFlags = SQLITE_OPEN_READONLY | SQLITE_OPEN_MAIN_DB | SQLITE_OPEN_URI;
1830+
if( (rc = sqlite3PagerOpen(pVfs, &pPager, srcDbPath, EXTRA_SIZE, 0, vfsFlags, ceshimPageReinit))==SQLITE_OK ){
1831+
sqlite3PagerSetJournalMode(pPager, PAGER_JOURNALMODE_OFF);
1832+
if( (rc = sqlite3PagerReadFileheader(pPager,sizeof(zDbHeader),zDbHeader)) == SQLITE_OK ){
1833+
u32 pageSize = (zDbHeader[16]<<8) | (zDbHeader[17]<<16);
1834+
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE // validate range
1835+
&& ((pageSize-1)&pageSize)==0 ){ // validate page size is a power of 2
1836+
u8 nReserve = zDbHeader[20];
1837+
if( (rc = sqlite3PagerSetPagesize(pPager, &pageSize, nReserve)) == SQLITE_OK ){
1838+
u32 fileChangeCounter = sqlite3Get4byte(zDbHeader+24);
1839+
u32 pageCount = sqlite3Get4byte(zDbHeader+28);
1840+
u32 schemaFormat = sqlite3Get4byte(zDbHeader+44);
1841+
u32 versionValidForNumber = sqlite3Get4byte(zDbHeader+92);
1842+
1843+
// If we didn't get page count, figure it out from the file size
1844+
if( !(pageCount>0 && fileChangeCounter==versionValidForNumber) ){
1845+
struct stat st;
1846+
if( stat(srcDbPath, &st)==0 ){
1847+
off_t size = st.st_size;
1848+
pageCount = st.st_size/pageSize;
1849+
}
1850+
}
1851+
1852+
// lock pager, prepare to read
1853+
if( rc==SQLITE_OK && (rc = sqlite3PagerSharedLock(pPager))==SQLITE_OK ){
1854+
// get destination ready to receive data
1855+
sqlite3 *pDb;
1856+
if( (rc = sqlite3_open_v2(destUri, &pDb, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, "ceshim-build"))==SQLITE_OK ){
1857+
sqlite3_vfs *pVfs = sqlite3_vfs_find("ceshim-build");
1858+
ceshim_info *pInfo = (ceshim_info *)pVfs->pAppData;
1859+
// import all pages
1860+
for(Pgno i=0; i<pageCount; i++){
1861+
// read source page
1862+
DbPage *pPage;
1863+
rc = sqlite3PagerGet(pPager, i+1, &pPage, 0);
1864+
if( rc==SQLITE_OK ){
1865+
// write destination page
1866+
void *pData = sqlite3PagerGetData(pPage);
1867+
rc = ceshimWrite((sqlite3_file *)pInfo->pFile, pData, pageSize, pageSize*i);
1868+
if (i>1) sqlite3PagerUnref(pPage);
1869+
if( rc != SQLITE_OK ) break;
1870+
}else{
1871+
break;
1872+
}
1873+
}
1874+
rc = sqlite3_close(pDb);
1875+
}
1876+
}
1877+
}
1878+
}
1879+
}else{
1880+
rc = SQLITE_CORRUPT;
1881+
}
1882+
}
1883+
}
1884+
}
1885+
return rc;
1886+
}

ceshim.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,11 @@ int ceshim_register(
2525

2626
int ceshim_unregister(const char *zName);
2727

28+
/*!
29+
\brief Create new compresses/encrypted database from existing database.
30+
\param srcDbPath Standard path to existing uncompressed, unencrypted SQLite database file.
31+
\param destUri URI of non-existing destination database file with optional parameters (block_size, key)
32+
*/
33+
int ceshimBuild(const char *srcDbPath, const char *destUri);
34+
2835
#endif /* ceshim_h */

0 commit comments

Comments
 (0)