Add start of "zonefile" virtual table.
FossilOrigin-Name: 0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43
This commit is contained in:
+679
-4
@@ -44,6 +44,25 @@ typedef unsigned long u32;
|
||||
#define ZONEFILE_DEFAULT_COMPRESSION 0
|
||||
|
||||
|
||||
#define ZONEFILE_SCHEMA \
|
||||
"CREATE TABLE z1(" \
|
||||
" k INTEGER PRIMARY KEY," \
|
||||
" v BLOB," \
|
||||
" fileid INTEGER," \
|
||||
" frame INTEGER," \
|
||||
" ofst INTEGER," \
|
||||
" sz INTEGER" \
|
||||
")"
|
||||
|
||||
#define ZONEFILE_FILES_SCHEMA \
|
||||
"CREATE TABLE z2(" \
|
||||
" filename TEXT," \
|
||||
" priority INTEGER," \
|
||||
" ekey BLOB," \
|
||||
" header JSON HIDDEN" \
|
||||
")"
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
@@ -56,6 +75,21 @@ struct ZonefileWrite {
|
||||
int maxAutoFrameSize;
|
||||
};
|
||||
|
||||
typedef struct ZonefileHeader ZonefileHeader;
|
||||
struct ZonefileHeader {
|
||||
u32 magicNumber;
|
||||
u8 compressionTypeIndexData;
|
||||
u8 compressionTypeContent;
|
||||
u32 byteOffsetDictionary;
|
||||
u32 byteOffsetFrames;
|
||||
u32 numFrames;
|
||||
u32 numKeys;
|
||||
u8 encryptionType;
|
||||
u8 encryptionKeyIdx;
|
||||
u8 extendedHeaderVersion;
|
||||
u8 extendedHeaderSize;
|
||||
};
|
||||
|
||||
typedef struct ZonefileBuffer ZonefileBuffer;
|
||||
struct ZonefileBuffer {
|
||||
u8 *a;
|
||||
@@ -83,7 +117,33 @@ static void zonefileTransferError(sqlite3_context *pCtx){
|
||||
sqlite3_result_error(pCtx, zErr, -1);
|
||||
}
|
||||
|
||||
static sqlite3_stmt *zonefilePrepare(
|
||||
static int zonefilePrepare(
|
||||
sqlite3 *db,
|
||||
sqlite3_stmt **ppStmt,
|
||||
char **pzErr,
|
||||
const char *zFmt,
|
||||
...
|
||||
){
|
||||
int rc;
|
||||
va_list ap;
|
||||
char *zSql;
|
||||
va_start(ap, zFmt);
|
||||
zSql = sqlite3_vmprintf(zFmt, ap);
|
||||
*ppStmt = 0;
|
||||
if( zSql ){
|
||||
rc = sqlite3_prepare(db, zSql, -1, ppStmt, 0);
|
||||
if( rc!=SQLITE_OK ){
|
||||
*pzErr = sqlite3_mprintf("%s", sqlite3_errmsg(db));
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
rc = SQLITE_NOMEM;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
static sqlite3_stmt *zonefileCtxPrepare(
|
||||
sqlite3_context *pCtx,
|
||||
const char *zFmt,
|
||||
...
|
||||
@@ -99,6 +159,7 @@ static sqlite3_stmt *zonefilePrepare(
|
||||
if( rc!=SQLITE_OK ){
|
||||
zonefileTransferError(pCtx);
|
||||
}
|
||||
sqlite3_free(zSql);
|
||||
}else{
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}
|
||||
@@ -118,9 +179,9 @@ static int zonefileCompareValue(sqlite3_value *p1, sqlite3_value *p2){
|
||||
if( sqlite3_value_type(p2)!=eType ) return 1;
|
||||
switch( eType ){
|
||||
case SQLITE_INTEGER:
|
||||
return sqlite3_value_int64(p1)==sqlite3_value_int64(p2);
|
||||
return sqlite3_value_int64(p1)!=sqlite3_value_int64(p2);
|
||||
case SQLITE_FLOAT:
|
||||
return sqlite3_value_double(p1)==sqlite3_value_double(p2);
|
||||
return sqlite3_value_double(p1)!=sqlite3_value_double(p2);
|
||||
case SQLITE_TEXT:
|
||||
case SQLITE_BLOB: {
|
||||
int n1 = sqlite3_value_bytes(p1);
|
||||
@@ -192,6 +253,13 @@ static void zonefilePut32(u8 *aBuf, u32 v){
|
||||
aBuf[3] = v & 0xFF;
|
||||
}
|
||||
|
||||
static u32 zonefileGet32(u8 *aBuf){
|
||||
return (((u32)aBuf[0]) << 24)
|
||||
+ (((u32)aBuf[1]) << 16)
|
||||
+ (((u32)aBuf[2]) << 8)
|
||||
+ (((u32)aBuf[3]) << 0);
|
||||
}
|
||||
|
||||
static void zonefileAppend32(ZonefileBuffer *pBuf, u32 v){
|
||||
zonefilePut32(&pBuf->a[pBuf->n], v);
|
||||
pBuf->n += 4;
|
||||
@@ -212,6 +280,15 @@ static int zonefileWrite(FILE *pFd, const u8 *aBuf, int nBuf){
|
||||
return res!=nBuf ? SQLITE_ERROR : SQLITE_OK;
|
||||
}
|
||||
|
||||
static int zonefileRead(FILE *pFd, u8 *aBuf, int nBuf, i64 iOff){
|
||||
int rc = fseek(pFd, iOff, SEEK_SET);
|
||||
if( rc==0 ){
|
||||
rc = fread(aBuf, 1, nBuf, pFd);
|
||||
rc = (rc==nBuf) ? SQLITE_OK : SQLITE_ERROR;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** Function: zonefile_write(F,T[,J])
|
||||
*/
|
||||
@@ -247,7 +324,7 @@ static void zonefileWriteFunc(
|
||||
|
||||
/* Prepare the SQL statement used to read data from the source table. This
|
||||
** also serves to verify the suitability of the source table schema. */
|
||||
pStmt = zonefilePrepare(pCtx,
|
||||
pStmt = zonefileCtxPrepare(pCtx,
|
||||
"SELECT k, frame, v FROM %Q ORDER BY frame, idx, k", zTbl
|
||||
);
|
||||
if( pStmt==0 ) return;
|
||||
@@ -296,6 +373,8 @@ static void zonefileWriteFunc(
|
||||
szFrame += nBlob;
|
||||
nKey++;
|
||||
}
|
||||
sqlite3_value_free(pPrev);
|
||||
pPrev = 0;
|
||||
|
||||
/* Create the zonefile header in the in-memory buffer */
|
||||
zonefilePut32(&aHdr[0], ZONEFILE_MAGIC_NUMBER);
|
||||
@@ -333,10 +412,598 @@ static void zonefileWriteFunc(
|
||||
zonefileBufferFree(&sFrames);
|
||||
}
|
||||
|
||||
typedef struct ZonefileFilesTab ZonefileFilesTab;
|
||||
struct ZonefileFilesTab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
sqlite3 *db;
|
||||
char *zBase; /* Name of this table */
|
||||
char *zDb; /* Database containing this table */
|
||||
sqlite3_stmt *pInsert; /* Insert into the %_shadow_file table */
|
||||
sqlite3_stmt *pDelete; /* Delete by rowid from %_shadow_file table */
|
||||
};
|
||||
|
||||
typedef struct ZonefileFilesCsr ZonefileFilesCsr;
|
||||
struct ZonefileFilesCsr {
|
||||
sqlite3_vtab_cursor base; /* Base class - must be first */
|
||||
sqlite3_stmt *pSelect;
|
||||
};
|
||||
|
||||
/*
|
||||
** This function does the work of xCreate (if bCreate!=0) or xConnect
|
||||
** (if bCreate==0) for the zonefile_files module.
|
||||
*/
|
||||
static int zffCreateConnect(
|
||||
int bCreate,
|
||||
sqlite3 *db,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
ZonefileFilesTab *p;
|
||||
const char *zName = argv[2];
|
||||
const char *zDb = argv[1];
|
||||
int nName = strlen(zName);
|
||||
int nDb = strlen(zDb);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
if( nName<6 || memcmp(&zName[nName-6], "_files", 6)!=0 ){
|
||||
*pzErr = sqlite3_mprintf("do not create zonefile_files tables directly!");
|
||||
*ppVtab = 0;
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
|
||||
p = (ZonefileFilesTab*)sqlite3_malloc(sizeof(ZonefileFilesTab)+nName+1+nDb+1);
|
||||
if( !p ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(p, 0, sizeof(ZonefileFilesTab));
|
||||
p->zBase = (char*)&p[1];
|
||||
memcpy(p->zBase, zName, nName-6);
|
||||
p->zBase[nName-6] = '\0';
|
||||
p->zDb = &p->zBase[nName+1];
|
||||
memcpy(p->zDb, zDb, nDb+1);
|
||||
p->db = db;
|
||||
rc = sqlite3_declare_vtab(db, ZONEFILE_FILES_SCHEMA);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(p);
|
||||
p = 0;
|
||||
}
|
||||
*ppVtab = (sqlite3_vtab*)p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xCreate method.
|
||||
*/
|
||||
static int zffCreate(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
return zffCreateConnect(1, db, argc, argv, ppVtab, pzErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xConnect method.
|
||||
*/
|
||||
static int zffConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
return zffCreateConnect(0, db, argc, argv, ppVtab, pzErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xDisconnect method.
|
||||
*/
|
||||
static int zffDisconnect(sqlite3_vtab *pVtab){
|
||||
ZonefileFilesTab *pTab = (ZonefileFilesTab*)pVtab;
|
||||
sqlite3_finalize(pTab->pInsert);
|
||||
sqlite3_finalize(pTab->pDelete);
|
||||
sqlite3_free(pTab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xBestIndex method.
|
||||
*/
|
||||
static int zffBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xOpen method.
|
||||
*/
|
||||
static int zffOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){
|
||||
ZonefileFilesCsr *pCsr;
|
||||
pCsr = (ZonefileFilesCsr*)sqlite3_malloc(sizeof(ZonefileFilesCsr));
|
||||
if( pCsr==0 ){
|
||||
return SQLITE_NOMEM;
|
||||
}
|
||||
memset(pCsr, 0, sizeof(ZonefileFilesCsr));
|
||||
*ppCursor = (sqlite3_vtab_cursor*)pCsr;
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
static void zffCursorReset(ZonefileFilesCsr *pCsr){
|
||||
sqlite3_finalize(pCsr->pSelect);
|
||||
pCsr->pSelect = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xClose method.
|
||||
*/
|
||||
static int zffClose(sqlite3_vtab_cursor *cur){
|
||||
ZonefileFilesCsr *pCsr = (ZonefileFilesCsr*)cur;
|
||||
zffCursorReset(pCsr);
|
||||
sqlite3_free(pCsr);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xNext method.
|
||||
*/
|
||||
static int zffNext(sqlite3_vtab_cursor *cur){
|
||||
ZonefileFilesCsr *pCsr = (ZonefileFilesCsr*)cur;
|
||||
int rc;
|
||||
if( SQLITE_ROW==sqlite3_step(pCsr->pSelect) ){
|
||||
rc = SQLITE_OK;
|
||||
}else{
|
||||
rc = sqlite3_finalize(pCsr->pSelect);
|
||||
pCsr->pSelect = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xFilter method.
|
||||
*/
|
||||
static int zffFilter(
|
||||
sqlite3_vtab_cursor *cur,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
ZonefileFilesCsr *pCsr = (ZonefileFilesCsr*)cur;
|
||||
ZonefileFilesTab *pTab = (ZonefileFilesTab*)(pCsr->base.pVtab);
|
||||
int rc;
|
||||
zffCursorReset(pCsr);
|
||||
|
||||
rc = zonefilePrepare(pTab->db, &pCsr->pSelect, &pTab->base.zErrMsg,
|
||||
"SELECT filename, fileid FROM %Q.'%q_shadow_file'",
|
||||
pTab->zDb, pTab->zBase
|
||||
);
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = zffNext(cur);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xEof method.
|
||||
*/
|
||||
static int zffEof(sqlite3_vtab_cursor *cur){
|
||||
ZonefileFilesCsr *pCsr = (ZonefileFilesCsr*)cur;
|
||||
return pCsr->pSelect==0;
|
||||
}
|
||||
|
||||
static FILE *zonefileOpenFile(sqlite3_context *pCtx, const char *zFile){
|
||||
FILE *pFd = fopen(zFile, "r");
|
||||
if( pFd==0 ){
|
||||
zonefileCtxError(pCtx, "failed to open file for reading: \"%s\"", zFile);
|
||||
}
|
||||
return pFd;
|
||||
}
|
||||
|
||||
static void zonefileHeaderDeserialize(u8 *aBuf, ZonefileHeader *pHdr){
|
||||
pHdr->magicNumber = zonefileGet32(&aBuf[0]);
|
||||
pHdr->compressionTypeIndexData = aBuf[4];
|
||||
pHdr->compressionTypeContent = aBuf[5];
|
||||
pHdr->byteOffsetDictionary = zonefileGet32(&aBuf[6]);
|
||||
pHdr->byteOffsetFrames = zonefileGet32(&aBuf[10]);
|
||||
pHdr->numFrames = zonefileGet32(&aBuf[14]);
|
||||
pHdr->numKeys = zonefileGet32(&aBuf[18]);
|
||||
pHdr->encryptionType = aBuf[22];
|
||||
pHdr->encryptionKeyIdx = aBuf[23];
|
||||
pHdr->extendedHeaderVersion = aBuf[24];
|
||||
pHdr->extendedHeaderSize = aBuf[25];
|
||||
}
|
||||
|
||||
static void zonefileJsonHeader(sqlite3_context *pCtx, const char *zFile){
|
||||
FILE *pFd = zonefileOpenFile(pCtx, zFile);
|
||||
if( pFd ){
|
||||
int rc;
|
||||
ZonefileHeader hdr;
|
||||
u8 aBuf[ZONEFILE_SZ_HEADER];
|
||||
|
||||
rc = zonefileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0);
|
||||
if( rc==SQLITE_OK ){
|
||||
zonefileHeaderDeserialize(aBuf, &hdr);
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
zonefileCtxError(pCtx, "failed to read header from file: \"%s\"", zFile);
|
||||
}else{
|
||||
char *zJson = sqlite3_mprintf("{"
|
||||
"\"magicNumber\":%u,"
|
||||
"\"compressionTypeIndexData\":%u,"
|
||||
"\"compressionTypeContent\":%u,"
|
||||
"\"byteOffsetDictionary\":%u,"
|
||||
"\"byteOffsetFrames\":%u,"
|
||||
"\"numFrames\":%u,"
|
||||
"\"numKeys\":%u,"
|
||||
"\"encryptionType\":%u,"
|
||||
"\"encryptionKeyIdx\":%u,"
|
||||
"\"extendedHeaderVersion\":%u,"
|
||||
"\"extendedHeaderSize\":%u}",
|
||||
(u32)hdr.magicNumber,
|
||||
(u32)hdr.compressionTypeIndexData,
|
||||
(u32)hdr.compressionTypeContent,
|
||||
(u32)hdr.byteOffsetDictionary,
|
||||
(u32)hdr.byteOffsetFrames,
|
||||
(u32)hdr.numFrames,
|
||||
(u32)hdr.numKeys,
|
||||
(u32)hdr.encryptionType,
|
||||
(u32)hdr.encryptionKeyIdx,
|
||||
(u32)hdr.extendedHeaderVersion,
|
||||
(u32)hdr.extendedHeaderSize
|
||||
);
|
||||
if( zJson ){
|
||||
sqlite3_result_text(pCtx, zJson, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_free(zJson);
|
||||
}else{
|
||||
sqlite3_result_error_nomem(pCtx);
|
||||
}
|
||||
}
|
||||
fclose(pFd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xColumn method.
|
||||
*/
|
||||
static int zffColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
ZonefileFilesCsr *pCsr = (ZonefileFilesCsr*)cur;
|
||||
switch( i ){
|
||||
case 0: /* filename */
|
||||
sqlite3_result_value(ctx, sqlite3_column_value(pCsr->pSelect, 0));
|
||||
break;
|
||||
case 1: /* priority */
|
||||
break;
|
||||
case 2: /* ekey */
|
||||
break;
|
||||
case 3: { /* header */
|
||||
const char *zFile = (const char*)sqlite3_column_text(pCsr->pSelect, 0);
|
||||
zonefileJsonHeader(ctx, zFile);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xRowid method.
|
||||
*/
|
||||
static int zffRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
|
||||
ZonefileFilesCsr *pCsr = (ZonefileFilesCsr*)cur;
|
||||
*pRowid = sqlite3_column_int64(pCsr->pSelect, 1);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile_files virtual table module xUpdate method.
|
||||
**
|
||||
** A delete specifies a single argument - the rowid of the row to remove.
|
||||
**
|
||||
** Update and insert operations pass:
|
||||
**
|
||||
** 1. The "old" rowid, or NULL.
|
||||
** 2. The "new" rowid.
|
||||
** 3. Values for each of the 4 columns: (filename,priority,ekey,header)
|
||||
*/
|
||||
static int zffUpdate(
|
||||
sqlite3_vtab *pVtab,
|
||||
int nVal,
|
||||
sqlite3_value **apVal,
|
||||
sqlite_int64 *pRowid
|
||||
){
|
||||
int rc = SQLITE_OK;
|
||||
ZonefileFilesTab *pTab = (ZonefileFilesTab*)pVtab;
|
||||
|
||||
if( sqlite3_value_type(apVal[0])==SQLITE_INTEGER ){
|
||||
if( pTab->pDelete==0 ){
|
||||
rc = zonefilePrepare(pTab->db, &pTab->pInsert, &pVtab->zErrMsg,
|
||||
"DELETE FROM %Q.'%q_shadow_file WHERE fileid=?",
|
||||
pTab->zDb, pTab->zBase
|
||||
);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
sqlite3_bind_value(pTab->pDelete, 1, apVal[0]);
|
||||
sqlite3_step(pTab->pDelete);
|
||||
rc = sqlite3_reset(pTab->pDelete);
|
||||
}
|
||||
}
|
||||
if( nVal>1 ){
|
||||
if( pTab->pInsert==0 ){
|
||||
rc = zonefilePrepare(pTab->db, &pTab->pInsert, &pVtab->zErrMsg,
|
||||
"INSERT INTO %Q.'%q_shadow_file'(filename) VALUES(?)",
|
||||
pTab->zDb, pTab->zBase
|
||||
);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zFile = (const char*)sqlite3_value_text(apVal[2]);
|
||||
sqlite3_bind_text(pTab->pInsert, 1, zFile, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_step(pTab->pInsert);
|
||||
rc = sqlite3_reset(pTab->pInsert);
|
||||
}
|
||||
}
|
||||
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
typedef struct ZonefileTab ZonefileTab;
|
||||
struct ZonefileTab {
|
||||
sqlite3_vtab base; /* Base class - must be first */
|
||||
sqlite3 *db;
|
||||
char *zName; /* Name of this table */
|
||||
char *zDb; /* Name of db containing this table */
|
||||
};
|
||||
|
||||
/*
|
||||
** This function does the work of xCreate (if bCreate!=0) or xConnect
|
||||
** (if bCreate==0) for the zonefile module.
|
||||
**
|
||||
** argv[0] -> module name ("zonefile")
|
||||
** argv[1] -> database name
|
||||
** argv[2] -> table name
|
||||
*/
|
||||
static int zonefileCreateConnect(
|
||||
int bCreate,
|
||||
sqlite3 *db,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
ZonefileTab *p;
|
||||
const char *zName = argv[2];
|
||||
const char *zDb = argv[1];
|
||||
int nName = strlen(zName);
|
||||
int nDb = strlen(zDb);
|
||||
int rc = SQLITE_OK;
|
||||
|
||||
p = (ZonefileTab*)sqlite3_malloc(sizeof(ZonefileTab) + nName+1 + nDb+1);
|
||||
if( !p ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
memset(p, 0, sizeof(ZonefileTab));
|
||||
p->zName = (char*)&p[1];
|
||||
memcpy(p->zName, zName, nName+1);
|
||||
p->zDb = &p->zName[nName+1];
|
||||
memcpy(p->zDb, zDb, nDb+1);
|
||||
p->db = db;
|
||||
|
||||
if( bCreate ){
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"CREATE TABLE %Q.'%q_shadow_idx'("
|
||||
" k INTEGER PRIMARY KEY,"
|
||||
" fileid INTEGER,"
|
||||
" frame INTEGER,"
|
||||
" ofst INTEGER,"
|
||||
" sz INTEGER"
|
||||
");"
|
||||
"CREATE TABLE %Q.'%q_shadow_file'("
|
||||
" filename TEXT,"
|
||||
" priority INTEGER,"
|
||||
" fileid INTEGER PRIMARY KEY"
|
||||
");"
|
||||
"CREATE VIRTUAL TABLE %Q.'%q_files' USING zonefile_files;",
|
||||
zDb, zName, zDb, zName, zDb, zName
|
||||
);
|
||||
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_exec(db, zSql, 0, 0, pzErr);
|
||||
sqlite3_free(zSql);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_declare_vtab(db, ZONEFILE_SCHEMA);
|
||||
}
|
||||
}
|
||||
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3_free(p);
|
||||
p = 0;
|
||||
}
|
||||
*ppVtab = (sqlite3_vtab*)p;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xCreate method.
|
||||
*/
|
||||
static int zonefileCreate(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
return zonefileCreateConnect(1, db, argc, argv, ppVtab, pzErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xConnect method.
|
||||
*/
|
||||
static int zonefileConnect(
|
||||
sqlite3 *db,
|
||||
void *pAux,
|
||||
int argc, const char *const*argv,
|
||||
sqlite3_vtab **ppVtab,
|
||||
char **pzErr
|
||||
){
|
||||
return zonefileCreateConnect(0, db, argc, argv, ppVtab, pzErr);
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xDisconnect method.
|
||||
*/
|
||||
static int zonefileDisconnect(sqlite3_vtab *pVtab){
|
||||
ZonefileTab *pTab = (ZonefileTab*)pVtab;
|
||||
sqlite3_free(pTab);
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xBestIndex method.
|
||||
*/
|
||||
static int zonefileBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xDestroy method.
|
||||
*/
|
||||
static int zonefileDestroy(sqlite3_vtab *pVtab){
|
||||
ZonefileTab *pTab = (ZonefileTab*)pVtab;
|
||||
int rc = SQLITE_OK;
|
||||
char *zSql = sqlite3_mprintf(
|
||||
"DROP TABLE IF EXISTS %Q.'%q_shadow_idx';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_shadow_file';"
|
||||
"DROP TABLE IF EXISTS %Q.'%q_files';",
|
||||
pTab->zDb, pTab->zName, pTab->zDb, pTab->zName, pTab->zDb, pTab->zName
|
||||
);
|
||||
if( zSql==0 ){
|
||||
rc = SQLITE_NOMEM;
|
||||
}else{
|
||||
rc = sqlite3_exec(pTab->db, zSql, 0, 0, 0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
zonefileDisconnect(pVtab);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xOpen method.
|
||||
*/
|
||||
static int zonefileOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xClose method.
|
||||
*/
|
||||
static int zonefileClose(sqlite3_vtab_cursor *cur){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xFilter method.
|
||||
*/
|
||||
static int zonefileFilter(
|
||||
sqlite3_vtab_cursor *pVtabCursor,
|
||||
int idxNum, const char *idxStr,
|
||||
int argc, sqlite3_value **argv
|
||||
){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xNext method.
|
||||
*/
|
||||
static int zonefileNext(sqlite3_vtab_cursor *pVtabCursor){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xEof method.
|
||||
*/
|
||||
static int zonefileEof(sqlite3_vtab_cursor *cur){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xColumn method.
|
||||
*/
|
||||
static int zonefileColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
** zonefile virtual table module xRowid method.
|
||||
*/
|
||||
static int zonefileRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){
|
||||
return SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Register the "zonefile" extensions.
|
||||
*/
|
||||
static int zonefileRegister(sqlite3 *db){
|
||||
static sqlite3_module filesModule = {
|
||||
0, /* iVersion */
|
||||
zffCreate, /* xCreate - create a table */
|
||||
zffConnect, /* xConnect - connect to an existing table */
|
||||
zffBestIndex, /* xBestIndex - Determine search strategy */
|
||||
zffDisconnect, /* xDisconnect - Disconnect from a table */
|
||||
zffDisconnect, /* xDestroy - Drop a table */
|
||||
zffOpen, /* xOpen - open a cursor */
|
||||
zffClose, /* xClose - close a cursor */
|
||||
zffFilter, /* xFilter - configure scan constraints */
|
||||
zffNext, /* xNext - advance a cursor */
|
||||
zffEof, /* xEof */
|
||||
zffColumn, /* xColumn - read data */
|
||||
zffRowid, /* xRowid - read data */
|
||||
zffUpdate, /* xUpdate - write data */
|
||||
0, /* xBegin - begin transaction */
|
||||
0, /* xSync - sync transaction */
|
||||
0, /* xCommit - commit transaction */
|
||||
0, /* xRollback - rollback transaction */
|
||||
0, /* xFindFunction - function overloading */
|
||||
0, /* xRename - rename the table */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
static sqlite3_module zonefileModule = {
|
||||
0, /* iVersion */
|
||||
zonefileCreate, /* xCreate - create a table */
|
||||
zonefileConnect, /* xConnect - connect to an existing table */
|
||||
zonefileBestIndex, /* xBestIndex - Determine search strategy */
|
||||
zonefileDisconnect, /* xDisconnect - Disconnect from a table */
|
||||
zonefileDestroy, /* xDestroy - Drop a table */
|
||||
zonefileOpen, /* xOpen - open a cursor */
|
||||
zonefileClose, /* xClose - close a cursor */
|
||||
zonefileFilter, /* xFilter - configure scan constraints */
|
||||
zonefileNext, /* xNext - advance a cursor */
|
||||
zonefileEof, /* xEof */
|
||||
zonefileColumn, /* xColumn - read data */
|
||||
zonefileRowid, /* xRowid - read data */
|
||||
0, /* xUpdate - write data */
|
||||
0, /* xBegin - begin transaction */
|
||||
0, /* xSync - sync transaction */
|
||||
0, /* xCommit - commit transaction */
|
||||
0, /* xRollback - rollback transaction */
|
||||
0, /* xFindFunction - function overloading */
|
||||
0, /* xRename - rename the table */
|
||||
0, /* xSavepoint */
|
||||
0, /* xRelease */
|
||||
0 /* xRollbackTo */
|
||||
};
|
||||
|
||||
struct Func {
|
||||
const char *z;
|
||||
int n;
|
||||
@@ -345,6 +1012,7 @@ static int zonefileRegister(sqlite3 *db){
|
||||
{ "zonefile_write", 2, zonefileWriteFunc },
|
||||
{ "zonefile_write", 3, zonefileWriteFunc },
|
||||
};
|
||||
|
||||
int rc = SQLITE_OK;
|
||||
int i;
|
||||
|
||||
@@ -353,6 +1021,13 @@ static int zonefileRegister(sqlite3 *db){
|
||||
rc = sqlite3_create_function(db, p->z, p->n, SQLITE_ANY, 0, p->x, 0, 0);
|
||||
}
|
||||
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_module(db, "zonefile_files", &filesModule, 0);
|
||||
}
|
||||
if( rc==SQLITE_OK ){
|
||||
rc = sqlite3_create_module(db, "zonefile", &zonefileModule, 0);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,6 @@ source [file join $testdir tester.tcl]
|
||||
set testprefix zonefile1
|
||||
load_static_extension db zonefile
|
||||
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE zz(k INTEGER PRIMARY KEY, frame INTEGER, idx INTEGER, v BLOB);
|
||||
INSERT INTO zz VALUES(1, -1, -1, randomblob(100));
|
||||
@@ -27,8 +26,23 @@ do_execsql_test 1.0 {
|
||||
INSERT INTO zz VALUES(3, -1, -1, randomblob(100));
|
||||
}
|
||||
|
||||
|
||||
do_execsql_test 1.1 {
|
||||
SELECT zonefile_write('test.zonefile', 'zz');
|
||||
}
|
||||
} {{}}
|
||||
|
||||
do_execsql_test 2.0 {
|
||||
CREATE VIRTUAL TABLE z1 USING zonefile;
|
||||
SELECT name FROM sqlite_master WHERE name LIKE 'z1%' ORDER BY 1;
|
||||
} {z1 z1_files z1_shadow_file z1_shadow_idx}
|
||||
|
||||
do_execsql_test 2.1 {
|
||||
INSERT INTO z1_files(filename) VALUES('test.zonefile');
|
||||
SELECT filename,
|
||||
json_extract(header, '$.magicNumber'),
|
||||
json_extract(header, '$.numFrames'),
|
||||
json_extract(header, '$.numKeys')
|
||||
FROM z1_files;
|
||||
} {test.zonefile 1179332920 1 3}
|
||||
|
||||
finish_test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
C Add\sthe\sstart\sof\sthe\s"zonefile"\sextension.
|
||||
D 2018-02-10T17:41:01.882
|
||||
C Add\sstart\sof\s"zonefile"\svirtual\stable.
|
||||
D 2018-02-10T21:04:12.610
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F Makefile.in 7a3f714b4fcf793108042b7b0a5c720b0b310ec84314d61ba7f3f49f27e550ea
|
||||
@@ -409,8 +409,8 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
|
||||
F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
|
||||
F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
|
||||
F ext/zonefile/README.md d675dbdffe2cd6d54681b958a13c88433a5022d39ab9ef3d4f487a272603f902
|
||||
F ext/zonefile/zonefile.c da7c63bfc0332e61cff28712ff75b08164c3a5eceef6273cac82f1fe2703b1ce
|
||||
F ext/zonefile/zonefile1.test ba4ca1166bb39a4121e6e7b3ef40a57cdff47a7432c816ab90ca61c02d9648d3
|
||||
F ext/zonefile/zonefile.c 835a05e6c633aa65f986971ccdc90dff8e14e5f31562907907934f32c745489e
|
||||
F ext/zonefile/zonefile1.test b13e8c46b2e48fd262c47ad9dcc648763cc1bf0ab4269d9c2d55e9543e0fd97e
|
||||
F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
|
||||
F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8
|
||||
F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60
|
||||
@@ -1708,10 +1708,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 3aed949a18a251c5795f21f0385c205a127502b7e9cf06bc7f4c763951cd7984
|
||||
R 49b6c60b83f70d70fd5fce453b29eb31
|
||||
T *branch * zonefile
|
||||
T *sym-zonefile *
|
||||
T -sym-trunk *
|
||||
P c125b4c380d1a20c7d71b413e96183eca9987aed3d0ba28395aa79c7c31bb6fd
|
||||
R de1cffc2d7f24bccc433152f51d0cae7
|
||||
U dan
|
||||
Z c26dc1aef1bc29dda740f0f5df0c6eab
|
||||
Z 7e0b32a62a935b3702f0204df537dbab
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
c125b4c380d1a20c7d71b413e96183eca9987aed3d0ba28395aa79c7c31bb6fd
|
||||
0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43
|
||||
Reference in New Issue
Block a user