From: dan Date: Sat, 10 Feb 2018 21:04:12 +0000 (+0000) Subject: Add start of "zonefile" virtual table. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b3f58b8b30532903e6b569b8a0c1605604a45986;p=thirdparty%2Fsqlite.git Add start of "zonefile" virtual table. FossilOrigin-Name: 0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43 --- diff --git a/ext/zonefile/zonefile.c b/ext/zonefile/zonefile.c index a52b4cf626..cdde4c13da 100644 --- a/ext/zonefile/zonefile.c +++ b/ext/zonefile/zonefile.c @@ -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 #include #include @@ -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; } diff --git a/ext/zonefile/zonefile1.test b/ext/zonefile/zonefile1.test index 9aae50c2ee..3f4da1e374 100644 --- a/ext/zonefile/zonefile1.test +++ b/ext/zonefile/zonefile1.test @@ -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 diff --git a/manifest b/manifest index 2f28794302..ba8da4f500 100644 --- a/manifest +++ b/manifest @@ -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 diff --git a/manifest.uuid b/manifest.uuid index 0991015f78..c633bfac10 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -c125b4c380d1a20c7d71b413e96183eca9987aed3d0ba28395aa79c7c31bb6fd \ No newline at end of file +0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43 \ No newline at end of file