From: dan Date: Mon, 12 Feb 2018 20:04:22 +0000 (+0000) Subject: Add support for reading simple (no compression, no encryption) zonefile files. X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=764d56b564f3d8a5d1dc2ac7de915a1fe6a45dcf;p=thirdparty%2Fsqlite.git Add support for reading simple (no compression, no encryption) zonefile files. FossilOrigin-Name: dba42f0e1efae7bad4579d23ad98e2c06e38053abe55f5cb277d7eecea42c56c --- diff --git a/ext/zonefile/zonefile.c b/ext/zonefile/zonefile.c index cdde4c13da..a28c0ff77f 100644 --- a/ext/zonefile/zonefile.c +++ b/ext/zonefile/zonefile.c @@ -37,7 +37,8 @@ typedef unsigned long u32; #define ZONEFILE_MAGIC_NUMBER 0x464B3138 -#define ZONEFILE_SZ_HEADER 26 +#define ZONEFILE_SZ_HEADER 26 +#define ZONEFILE_SZ_KEYOFFSETS_ENTRY 20 #define ZONEFILE_DEFAULT_MAXAUTOFRAMESIZE (64*1024) #define ZONEFILE_DEFAULT_ENCRYPTION 0 @@ -260,6 +261,17 @@ static u32 zonefileGet32(u8 *aBuf){ + (((u32)aBuf[3]) << 0); } +static u64 zonefileGet64(u8 *aBuf){ + return (((u64)aBuf[0]) << 56) + + (((u64)aBuf[1]) << 48) + + (((u64)aBuf[2]) << 40) + + (((u64)aBuf[3]) << 32) + + (((u64)aBuf[4]) << 24) + + (((u64)aBuf[5]) << 16) + + (((u64)aBuf[6]) << 8) + + (((u64)aBuf[7]) << 0); +} + static void zonefileAppend32(ZonefileBuffer *pBuf, u32 v){ zonefilePut32(&pBuf->a[pBuf->n], v); pBuf->n += 4; @@ -275,12 +287,12 @@ static void zonefileAppendBlob(ZonefileBuffer *pBuf, const u8 *p, int n){ pBuf->n += n; } -static int zonefileWrite(FILE *pFd, const u8 *aBuf, int nBuf){ +static int zonefileFileWrite(FILE *pFd, const u8 *aBuf, int nBuf){ size_t res = fwrite(aBuf, 1, nBuf, pFd); return res!=nBuf ? SQLITE_ERROR : SQLITE_OK; } -static int zonefileRead(FILE *pFd, u8 *aBuf, int nBuf, i64 iOff){ +static int zonefileFileRead(FILE *pFd, u8 *aBuf, int nBuf, i64 iOff){ int rc = fseek(pFd, iOff, SEEK_SET); if( rc==0 ){ rc = fread(aBuf, 1, nBuf, pFd); @@ -289,6 +301,20 @@ static int zonefileRead(FILE *pFd, u8 *aBuf, int nBuf, i64 iOff){ return rc; } +static FILE *zonefileFileOpen(const char *zFile, int bWrite, char **pzErr){ + FILE *pFd = fopen(zFile, bWrite ? "w" : "r"); + if( pFd==0 ){ + *pzErr = sqlite3_mprintf("failed to open file \"%s\" for %s", + zFile, bWrite ? "writing" : "reading" + ); + } + return pFd; +} + +static void zonefileFileClose(FILE *pFd){ + if( pFd ) fclose(pFd); +} + /* ** Function: zonefile_write(F,T[,J]) */ @@ -361,7 +387,9 @@ static void zonefileWriteFunc( } /* Add new entry to sKeyIdx */ - if( zonefileBufferGrow(pCtx, &sKeyIdx, 20) ) goto zone_write_out; + if( zonefileBufferGrow(pCtx, &sKeyIdx, ZONEFILE_SZ_KEYOFFSETS_ENTRY) ){ + goto zone_write_out; + } zonefileAppend64(&sKeyIdx, k); zonefileAppend32(&sKeyIdx, nFrame-1); zonefileAppend32(&sKeyIdx, szFrame); @@ -390,10 +418,10 @@ static void zonefileWriteFunc( aHdr[25] = 0; /* extended header size */ assert( ZONEFILE_SZ_HEADER==26 ); - rc = zonefileWrite(pFd, aHdr, ZONEFILE_SZ_HEADER); - if( rc==SQLITE_OK ) rc = zonefileWrite(pFd, sFrameIdx.a, sFrameIdx.n); - if( rc==SQLITE_OK ) rc = zonefileWrite(pFd, sKeyIdx.a, sKeyIdx.n); - if( rc==SQLITE_OK ) rc = zonefileWrite(pFd, sFrames.a, sFrames.n); + rc = zonefileFileWrite(pFd, aHdr, ZONEFILE_SZ_HEADER); + if( rc==SQLITE_OK ) rc = zonefileFileWrite(pFd, sFrameIdx.a, sFrameIdx.n); + if( rc==SQLITE_OK ) rc = zonefileFileWrite(pFd, sKeyIdx.a, sKeyIdx.n); + if( rc==SQLITE_OK ) rc = zonefileFileWrite(pFd, sFrames.a, sFrames.n); if( rc ){ zonefileCtxError(pCtx, "error writing file \"%s\" (fwrite())", zFile); goto zone_write_out; @@ -419,6 +447,8 @@ struct ZonefileFilesTab { char *zBase; /* Name of this table */ char *zDb; /* Database containing this table */ sqlite3_stmt *pInsert; /* Insert into the %_shadow_file table */ + sqlite3_stmt *pInsertIdx; /* Insert into the %_shadow_idx table */ + sqlite3_stmt *pDeleteIdx; /* Delete by fileid from %_shadow_idx table */ sqlite3_stmt *pDelete; /* Delete by rowid from %_shadow_file table */ }; @@ -507,6 +537,8 @@ static int zffDisconnect(sqlite3_vtab *pVtab){ ZonefileFilesTab *pTab = (ZonefileFilesTab*)pVtab; sqlite3_finalize(pTab->pInsert); sqlite3_finalize(pTab->pDelete); + sqlite3_finalize(pTab->pInsertIdx); + sqlite3_finalize(pTab->pDeleteIdx); sqlite3_free(pTab); return SQLITE_OK; } @@ -514,7 +546,7 @@ static int zffDisconnect(sqlite3_vtab *pVtab){ /* ** zonefile_files virtual table module xBestIndex method. */ -static int zffBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ +static int zffBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pInfo){ return SQLITE_OK; } @@ -532,6 +564,10 @@ static int zffOpen(sqlite3_vtab *pVtab, sqlite3_vtab_cursor **ppCursor){ return SQLITE_OK; } +/* +** Reset a ZonefileFilesCsr object to the state it is in immediately after +** it is allocated by zffOpen(). +*/ static void zffCursorReset(ZonefileFilesCsr *pCsr){ sqlite3_finalize(pCsr->pSelect); pCsr->pSelect = 0; @@ -622,7 +658,7 @@ static void zonefileJsonHeader(sqlite3_context *pCtx, const char *zFile){ ZonefileHeader hdr; u8 aBuf[ZONEFILE_SZ_HEADER]; - rc = zonefileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0); + rc = zonefileFileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0); if( rc==SQLITE_OK ){ zonefileHeaderDeserialize(aBuf, &hdr); } @@ -696,6 +732,102 @@ static int zffRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ return SQLITE_OK; } +/* +** Read and decode a Zonefile header from the start of the file opened +** by file-handle pFd. If successful, populate object (*pHdr) before +** returning SQLITE_OK. Otherwise, if an error occurs, set output +** parameter (*pzErr) to point to an English language error message and +** return an SQLite error code. +** +** It is the responsibility of the caller to eventually free any error +** message returned via (*pzErr) using sqlite3_free(). +*/ +static int zonefileReadHeader( + FILE *pFd, /* File to read from */ + const char *zFile, /* Name of file opened by pFd */ + ZonefileHeader *pHdr, /* Populate this object before returning */ + char **pzErr /* OUT: Error message */ +){ + u8 aBuf[ZONEFILE_SZ_HEADER]; + int rc = zonefileFileRead(pFd, aBuf, ZONEFILE_SZ_HEADER, 0); + if( rc==SQLITE_OK ){ + zonefileHeaderDeserialize(aBuf, pHdr); + if( pHdr->magicNumber!=ZONEFILE_MAGIC_NUMBER ){ + rc = SQLITE_ERROR; + } + } + + if( rc!=SQLITE_OK ){ + *pzErr = sqlite3_mprintf( + "failed to read zonefile header from file \"%s\"", zFile + ); + } + + return rc; +} + +static int zonefilePopulateIndex( + ZonefileFilesTab *pTab, + const char *zFile, + i64 iFileid +){ + ZonefileHeader hdr; + int rc; + FILE *pFd = zonefileFileOpen(zFile, 0, &pTab->base.zErrMsg); + + if( pFd==0 ){ + rc = SQLITE_ERROR; + }else{ + rc = zonefileReadHeader(pFd, zFile, &hdr, &pTab->base.zErrMsg); + } + + if( rc==SQLITE_OK && hdr.numKeys>0 ){ + /* TODO: Deal with encrypted and compressed ZonefileIndex objects */ + i64 iOff; /* Offset of keyOffsets array */ + u8 *aKey; /* Entire KeyOffsets array */ + int nKey; /* Size of buffer aKey[] in bytes */ + int i; + assert( hdr.encryptionType==0 && hdr.compressionTypeIndexData==0 ); + + iOff = ZONEFILE_SZ_HEADER + (hdr.numFrames * 4); + nKey = ZONEFILE_SZ_KEYOFFSETS_ENTRY * hdr.numKeys; + aKey = (u8*)sqlite3_malloc(nKey); + if( aKey==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = zonefileFileRead(pFd, aKey, nKey, iOff); + } + + if( rc==SQLITE_OK && pTab->pInsertIdx==0 ){ + rc = zonefilePrepare(pTab->db, &pTab->pInsertIdx, &pTab->base.zErrMsg, + "INSERT INTO %Q.'%q_shadow_idx'(k, fileid, frame, ofst, sz)" + "VALUES(?,?,?,?,?)", + pTab->zDb, pTab->zBase + ); + } + + for(i=0; ipInsertIdx, 1, (i64)zonefileGet64(&aEntry[0])); + sqlite3_bind_int64(pTab->pInsertIdx, 2, iFileid); + sqlite3_bind_int64(pTab->pInsertIdx, 3, (i64)zonefileGet32(&aEntry[8])); + sqlite3_bind_int64(pTab->pInsertIdx, 4, (i64)zonefileGet32(&aEntry[12])); + sqlite3_bind_int64(pTab->pInsertIdx, 5, (i64)zonefileGet32(&aEntry[16])); + + sqlite3_step(pTab->pInsertIdx); + rc = sqlite3_reset(pTab->pInsertIdx); + if( rc!=SQLITE_OK ){ + pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); + } + } + sqlite3_free(aKey); + } + + zonefileFileClose(pFd); + return rc; +} + /* ** zonefile_files virtual table module xUpdate method. ** @@ -718,18 +850,32 @@ static int zffUpdate( 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=?", + rc = zonefilePrepare(pTab->db, &pTab->pDelete, &pVtab->zErrMsg, + "DELETE FROM %Q.'%q_shadow_file' WHERE fileid=?", pTab->zDb, pTab->zBase ); } + if( rc==SQLITE_OK && pTab->pDeleteIdx==0 ){ + rc = zonefilePrepare(pTab->db, &pTab->pDeleteIdx, &pVtab->zErrMsg, + "DELETE FROM %Q.'%q_shadow_idx' 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( rc==SQLITE_OK ){ + sqlite3_bind_value(pTab->pDeleteIdx, 1, apVal[0]); + sqlite3_step(pTab->pDeleteIdx); + rc = sqlite3_reset(pTab->pDeleteIdx); + } } if( nVal>1 ){ + const char *zFile = (const char*)sqlite3_value_text(apVal[2]); + if( pTab->pInsert==0 ){ rc = zonefilePrepare(pTab->db, &pTab->pInsert, &pVtab->zErrMsg, "INSERT INTO %Q.'%q_shadow_file'(filename) VALUES(?)", @@ -737,25 +883,39 @@ static int zffUpdate( ); } + /* Add the new entry to the %_shadow_file table. */ 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); } + + /* Populate the %_shadow_idx table with entries for all keys in + ** the zonefile just added to %_shadow_file. */ + if( rc==SQLITE_OK ){ + i64 iFileid = sqlite3_last_insert_rowid(pTab->db); + rc = zonefilePopulateIndex(pTab, zFile, iFileid); + } } - return SQLITE_OK; + return rc; } typedef struct ZonefileTab ZonefileTab; struct ZonefileTab { sqlite3_vtab base; /* Base class - must be first */ sqlite3 *db; + sqlite3_stmt *pIdToName; /* Translate fileid to filename */ char *zName; /* Name of this table */ char *zDb; /* Name of db containing this table */ }; +typedef struct ZonefileCsr ZonefileCsr; +struct ZonefileCsr { + sqlite3_vtab_cursor base; /* Base class - must be first */ + sqlite3_stmt *pSelect; /* SELECT on %_shadow_idx table */ +}; + /* ** This function does the work of xCreate (if bCreate!=0) or xConnect ** (if bCreate==0) for the zonefile module. @@ -859,14 +1019,81 @@ static int zonefileConnect( */ static int zonefileDisconnect(sqlite3_vtab *pVtab){ ZonefileTab *pTab = (ZonefileTab*)pVtab; + sqlite3_finalize(pTab->pIdToName); sqlite3_free(pTab); return SQLITE_OK; } /* -** zonefile virtual table module xBestIndex method. +** Zonefile virtual table module xBestIndex method. +** +** Equality and range constraints on either the rowid or column "k" (which +** are the same thing) are processed. Bits in the idxNum parameter are +** set to indicate the constraints present: +** +** 0x01: k == ? +** 0x02: k < ? +** 0x04: k <= ? +** 0x08: k > ? +** 0x10: k >= ? +** +** Only some combinations are valid: +** +** * If an == constraint is found, no other bits are set. +** * If a < constraint is present, any <= is ignored. +** * If a > constraint is present, any >= is ignored. */ -static int zonefileBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){ +static int zonefileBestIndex(sqlite3_vtab *pVtab, sqlite3_index_info *pInfo){ + int iEq = -1; + int iLt = -1; + int iLe = -1; + int iGt = -1; + int iGe = -1; + int i; + int idxNum = 0; + double cost = 1000000000.0; + + for(i=0; inConstraint; i++){ + struct sqlite3_index_constraint *p = &pInfo->aConstraint[i]; + if( p->usable && p->iColumn<=0 ){ + switch( p->op ){ + case SQLITE_INDEX_CONSTRAINT_EQ: iEq = i; break; + case SQLITE_INDEX_CONSTRAINT_LT: iLt = i; break; + case SQLITE_INDEX_CONSTRAINT_LE: iLe = i; break; + case SQLITE_INDEX_CONSTRAINT_GT: iGt = i; break; + case SQLITE_INDEX_CONSTRAINT_GE: iGe = i; break; + } + } + } + + if( iEq>=0 ){ + cost = 10.0; + idxNum = 0x01; + pInfo->aConstraintUsage[iEq].argvIndex = 1; + }else{ + int iIdx = 1; + if( iLt>=0 ){ + pInfo->aConstraintUsage[iLt].argvIndex = iIdx++; + idxNum |= 0x02; + }else if( iLe>=0 ){ + pInfo->aConstraintUsage[iLe].argvIndex = iIdx++; + idxNum |= 0x04; + } + if( iGt>=0 ){ + pInfo->aConstraintUsage[iGt].argvIndex = iIdx++; + idxNum |= 0x08; + }else if( iGe>=0 ){ + pInfo->aConstraintUsage[iGe].argvIndex = iIdx++; + idxNum |= 0x10; + } + + if( iIdx==2 ) cost = 10000.0; + if( iIdx==3 ) cost = 100.0; + } + + pInfo->idxNum = idxNum; + pInfo->estimatedCost = cost; + return SQLITE_OK; } @@ -886,6 +1113,7 @@ static int zonefileDestroy(sqlite3_vtab *pVtab){ rc = SQLITE_NOMEM; }else{ rc = sqlite3_exec(pTab->db, zSql, 0, 0, 0); + sqlite3_free(zSql); } if( rc==SQLITE_OK ){ @@ -898,56 +1126,226 @@ static int zonefileDestroy(sqlite3_vtab *pVtab){ ** zonefile virtual table module xOpen method. */ static int zonefileOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){ + ZonefileCsr *pCsr; + pCsr = (ZonefileCsr*)sqlite3_malloc(sizeof(ZonefileCsr)); + if( pCsr==0 ){ + return SQLITE_NOMEM; + } + memset(pCsr, 0, sizeof(ZonefileCsr)); + *ppCursor = (sqlite3_vtab_cursor*)pCsr; return SQLITE_OK; } +/* +** Reset a ZonefileCsr object to the state it is in immediately after +** it is allocated by zffOpen(). +*/ +static void zonefileCursorReset(ZonefileCsr *pCsr){ + sqlite3_finalize(pCsr->pSelect); + pCsr->pSelect = 0; +} + /* ** zonefile virtual table module xClose method. */ static int zonefileClose(sqlite3_vtab_cursor *cur){ + ZonefileCsr *pCsr = (ZonefileCsr*)cur; + zonefileCursorReset(pCsr); + sqlite3_free(pCsr); return SQLITE_OK; } +/* +** zonefile virtual table module xNext method. +*/ +static int zonefileNext(sqlite3_vtab_cursor *cur){ + ZonefileCsr *pCsr = (ZonefileCsr*)cur; + int rc = SQLITE_OK; + if( SQLITE_ROW!=sqlite3_step(pCsr->pSelect) ){ + rc = sqlite3_finalize(pCsr->pSelect); + if( rc!=SQLITE_OK ){ + ZonefileTab *pTab = (ZonefileTab*)pCsr->base.pVtab; + pTab->base.zErrMsg = sqlite3_mprintf("%s", sqlite3_errmsg(pTab->db)); + } + pCsr->pSelect = 0; + } + return rc; +} + /* ** zonefile virtual table module xFilter method. */ static int zonefileFilter( - sqlite3_vtab_cursor *pVtabCursor, + sqlite3_vtab_cursor *cur, int idxNum, const char *idxStr, int argc, sqlite3_value **argv ){ - return SQLITE_OK; -} + ZonefileCsr *pCsr = (ZonefileCsr*)cur; + ZonefileTab *pTab = (ZonefileTab*)pCsr->base.pVtab; + int rc; -/* -** zonefile virtual table module xNext method. -*/ -static int zonefileNext(sqlite3_vtab_cursor *pVtabCursor){ - return SQLITE_OK; + const char *z1 = 0; + const char *z2 = 0; + + if( idxNum & 0x01 ){ + z1 = "k = ?"; + }else{ + if( idxNum & 0x02 ) { z1 = "k < ?"; } + if( idxNum & 0x04 ) { z1 = "k <= ?"; } + if( idxNum & 0x08 ) { if( z1 ) z2 = "k > ?"; else z1 = "k > ?"; } + if( idxNum & 0x10 ) { if( z1 ) z2 = "k <= ?"; else z1 = "k <= ?"; } + } + + rc = zonefilePrepare(pTab->db, &pCsr->pSelect, &pTab->base.zErrMsg, + "SELECT k, fileid, frame, ofst, sz FROM %Q.'%q_shadow_idx'%s%s%s%s", + pTab->zDb, pTab->zName, + z1 ? " WHERE " : "", z1, + z2 ? " AND " : "", z2 + ); + + if( z1 ) sqlite3_bind_value(pCsr->pSelect, 1, argv[0]); + if( z2 ) sqlite3_bind_value(pCsr->pSelect, 2, argv[1]); + + if( rc==SQLITE_OK ){ + rc = zonefileNext(cur); + } + + return rc; } /* ** zonefile virtual table module xEof method. */ static int zonefileEof(sqlite3_vtab_cursor *cur){ - return SQLITE_OK; + ZonefileCsr *pCsr = (ZonefileCsr*)cur; + return (pCsr->pSelect==0); +} + +static void zonefileFree(void *p){ + sqlite3_free(p); +} + +static int zonefileGetValue(sqlite3_context *pCtx, ZonefileCsr *pCsr){ + ZonefileTab *pTab = (ZonefileTab*)pCsr->base.pVtab; + const char *zFile = 0; + char *zErr = 0; + FILE *pFd = 0; + int rc = SQLITE_OK; + u32 iOff = 0; /* Offset of frame in file */ + ZonefileHeader hdr; + + if( pTab->pIdToName==0 ){ + rc = zonefilePrepare(pTab->db, &pTab->pIdToName, &pTab->base.zErrMsg, + "SELECT filename FROM %Q.'%q_shadow_file' WHERE fileid=?", + pTab->zDb, pTab->zName + ); + if( rc!=SQLITE_OK ){ + zonefileTransferError(pCtx); + return SQLITE_ERROR; + } + } + + /* Open the file to read the blob from */ + sqlite3_bind_int64(pTab->pIdToName, 1, sqlite3_column_int64(pCsr->pSelect,1)); + if( SQLITE_ROW==sqlite3_step(pTab->pIdToName) ){ + zFile = (const char*)sqlite3_column_text(pTab->pIdToName, 0); + pFd = zonefileFileOpen(zFile, 0, &zErr); + } + if( zFile==0 ){ + rc = sqlite3_reset(pTab->pIdToName); + if( rc!=SQLITE_OK ){ + zonefileTransferError(pCtx); + }else{ + rc = SQLITE_CORRUPT_VTAB; + } + }else if( pFd==0 ){ + rc = SQLITE_ERROR; + } + + /* Read the zonefile header */ + if( rc==SQLITE_OK ){ + rc = zonefileReadHeader(pFd, zFile, &hdr, &zErr); + } + + /* Calculate the offset of the frame to read the blob from */ + if( rc==SQLITE_OK ){ + u8 aOff[4] = {0,0,0,0}; + int iFrame = sqlite3_column_int(pCsr->pSelect, 2); + rc = zonefileFileRead(pFd, aOff, 4, ZONEFILE_SZ_HEADER + 4 * iFrame); + iOff = zonefileGet32(aOff); + } + + /* Read the blob */ + if( rc==SQLITE_OK ){ + int sz = sqlite3_column_int(pCsr->pSelect, 4); + int ofst = sqlite3_column_int(pCsr->pSelect, 3); + u8 *aBuf = sqlite3_malloc(sz); + if( aBuf==0 ){ + rc = SQLITE_NOMEM; + }else{ + rc = zonefileFileRead(pFd, aBuf, sz, hdr.byteOffsetFrames + iOff + ofst); + if( rc==SQLITE_OK ){ + sqlite3_result_blob(pCtx, aBuf, sz, zonefileFree); + }else{ + zErr = sqlite3_mprintf( + "failed to read %d bytes from file \"%s\"", sz, zFile + ); + } + } + } + + sqlite3_reset(pTab->pIdToName); + if( zErr ){ + assert( rc!=SQLITE_OK ); + sqlite3_result_error(pCtx, zErr, -1); + sqlite3_free(zErr); + } + zonefileFileClose(pFd); + return rc; } /* ** zonefile virtual table module xColumn method. */ -static int zonefileColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){ - return SQLITE_OK; +static int zonefileColumn( + sqlite3_vtab_cursor *cur, + sqlite3_context *pCtx, + int i +){ + ZonefileCsr *pCsr = (ZonefileCsr*)cur; + int rc = SQLITE_OK; + switch( i ){ + case 0: /* k */ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 0)); + break; + case 1: /* v */ + rc = zonefileGetValue(pCtx, pCsr); + break; + case 2: /* fileid */ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 1)); + break; + case 3: /* frame */ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 2)); + break; + case 4: /* ofst */ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 3)); + break; + default: /* sz */ + sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 4)); + break; + } + return rc; } /* ** zonefile virtual table module xRowid method. */ -static int zonefileRowid(sqlite3_vtab_cursor *pVtabCursor, sqlite_int64 *pRowid){ +static int zonefileRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){ + ZonefileCsr *pCsr = (ZonefileCsr*)cur; + *pRowid = sqlite3_column_int64(pCsr->pSelect, 0); return SQLITE_OK; } - /* ** Register the "zonefile" extensions. */ @@ -977,7 +1375,6 @@ static int zonefileRegister(sqlite3 *db){ 0, /* xRelease */ 0 /* xRollbackTo */ }; - static sqlite3_module zonefileModule = { 0, /* iVersion */ zonefileCreate, /* xCreate - create a table */ diff --git a/ext/zonefile/zonefile1.test b/ext/zonefile/zonefile1.test index 3f4da1e374..067a1f2088 100644 --- a/ext/zonefile/zonefile1.test +++ b/ext/zonefile/zonefile1.test @@ -26,17 +26,16 @@ 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 { +do_execsql_test 1.2 { 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 { +do_execsql_test 1.3 { INSERT INTO z1_files(filename) VALUES('test.zonefile'); SELECT filename, json_extract(header, '$.magicNumber'), @@ -45,4 +44,25 @@ do_execsql_test 2.1 { FROM z1_files; } {test.zonefile 1179332920 1 3} +do_execsql_test 1.4 { SELECT count(*) FROM z1_shadow_idx } 3 + +do_execsql_test 1.5.1 { SELECT k FROM z1 } {1 2 3} +do_execsql_test 1.5.2 { SELECT fileid FROM z1 } {1 1 1} +do_execsql_test 1.5.3 { SELECT frame FROM z1 } {0 0 0} +do_execsql_test 1.5.4 { SELECT sz FROM z1 } {100 100 100} + +do_execsql_test 1.5.5 { + SELECT zz.v==z1.v FROM zz, z1 WHERE zz.k=z1.k +} {1 1 1} + +do_execsql_test 1.5 { + DELETE FROM z1_files; + SELECT * FROM z1_files; +} {} + +do_execsql_test 1.6 { SELECT count(*) FROM z1_shadow_idx } 0 + +do_execsql_test 1.7 { DROP TABLE z1 } + finish_test + diff --git a/manifest b/manifest index ba8da4f500..97500789e1 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Add\sstart\sof\s"zonefile"\svirtual\stable. -D 2018-02-10T21:04:12.610 +C Add\ssupport\sfor\sreading\ssimple\s(no\scompression,\sno\sencryption)\szonefile\sfiles. +D 2018-02-12T20:04:22.636 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 835a05e6c633aa65f986971ccdc90dff8e14e5f31562907907934f32c745489e -F ext/zonefile/zonefile1.test b13e8c46b2e48fd262c47ad9dcc648763cc1bf0ab4269d9c2d55e9543e0fd97e +F ext/zonefile/zonefile.c 31a8627c6fb619f4b87993abb22f2e38f14eb2bdf53130c425ba711d17eedb91 +F ext/zonefile/zonefile1.test 8904658bd8332dc0d0c77c0c74c9c83dce4123a442bb971d5baf00170f6d0afe F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x F ltmain.sh 3ff0879076df340d2e23ae905484d8c15d5fdea8 F magic.txt 8273bf49ba3b0c8559cb2774495390c31fd61c60 @@ -1708,7 +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 c125b4c380d1a20c7d71b413e96183eca9987aed3d0ba28395aa79c7c31bb6fd -R de1cffc2d7f24bccc433152f51d0cae7 +P 0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43 +R 33d1fa645c0dd3199e4abbacb34944f8 U dan -Z 7e0b32a62a935b3702f0204df537dbab +Z de15678e60eb47332eda44ee08650662 diff --git a/manifest.uuid b/manifest.uuid index c633bfac10..4b45f80910 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43 \ No newline at end of file +dba42f0e1efae7bad4579d23ad98e2c06e38053abe55f5cb277d7eecea42c56c \ No newline at end of file