]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Modifications to the zonefile module to make it easier to add a cache of
authordan <dan@noemail.net>
Wed, 21 Feb 2018 21:15:45 +0000 (21:15 +0000)
committerdan <dan@noemail.net>
Wed, 21 Feb 2018 21:15:45 +0000 (21:15 +0000)
uncompressed frame content.

FossilOrigin-Name: d9d5cc62f11058f9ba560381367ff4765dbbde08184e55abdb50ae1b6bf4a016

ext/zonefile/zonefile.c
manifest
manifest.uuid

index 2bd73f5c3da065a8c1b7b8acee614c4fe0c58dee..fbf4ca846bfaf06b4d363399bf0e6bda1c961749 100644 (file)
@@ -16,9 +16,64 @@ SQLITE_EXTENSION_INIT1
 #ifndef SQLITE_OMIT_VIRTUALTABLE
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <string.h>
 #include <assert.h>
 
+/*
+** Default values for various zonefile_write() parameters.
+*/
+#define ZONEFILE_DEFAULT_MAXAUTOFRAMESIZE (64*1024)
+#define ZONEFILE_DEFAULT_ENCRYPTION       1
+#define ZONEFILE_DEFAULT_COMPRESSION      0
+#define ZONEFILE_DEFAULT_DICTSIZE         (64*1024)
+
+/* 
+** Value to use for the first 4 bytes of a zonefile file header.
+*/
+#define ZONEFILE_MAGIC_NUMBER 0x464B3138
+
+/*
+** Size of a zonefile header. And of each entry in the 
+** ZonefileIndex.keyOffsets array.
+*/
+#define ZONEFILE_SZ_HEADER           32
+#define ZONEFILE_SZ_KEYOFFSETS_ENTRY 20
+
+/*
+** Constants for supported compression types. These are copied from the
+** published file format spec.
+*/
+#define ZONEFILE_COMPRESSION_NONE             0
+#define ZONEFILE_COMPRESSION_ZSTD             1
+#define ZONEFILE_COMPRESSION_ZSTD_GLOBAL_DICT 2
+#define ZONEFILE_COMPRESSION_ZLIB             3
+#define ZONEFILE_COMPRESSION_BROTLI           4
+#define ZONEFILE_COMPRESSION_LZ4              5
+#define ZONEFILE_COMPRESSION_LZ4HC            6
+
+/*
+** Schema for "zonefile" virtual table.
+*/
+#define ZONEFILE_SCHEMA          \
+  "CREATE TABLE z1("             \
+  "  k INTEGER PRIMARY KEY,"     \
+  "  v BLOB,"                    \
+  "  fileid INTEGER,"            \
+  "  sz INTEGER"                 \
+  ")"
+
+/*
+** Schema for "zonefile_files" virtual table.
+*/
+#define ZONEFILE_FILES_SCHEMA    \
+  "CREATE TABLE z2("             \
+  "  filename TEXT,"             \
+  "  ekey BLOB,"                 \
+  "  header JSON HIDDEN"         \
+  ")"
+
+
 #ifndef SQLITE_AMALGAMATION
 typedef sqlite3_int64 i64;
 typedef sqlite3_uint64 u64;
@@ -39,6 +94,23 @@ typedef unsigned long u32;
 #endif
 #endif   /* SQLITE_AMALGAMATION */
 
+/*
+** Forward declarations for encryption/decryption functions.
+**
+** If this module is not compiled with SQLITE_HAVE_ZONEFILE_CODEC, then
+** implementations of the following type and functions that support the
+** mock encryption method "xor" only are provided. Alternatively, the
+** application may append a more functional implementation of the following 
+** type and functions to this file before compiling it with
+** SQLITE_HAVE_ZONEFILE_CODEC defined.
+*/
+typedef struct ZonefileCodec ZonefileCodec;
+static int zonefileCodecCreate(int,unsigned char*,int,ZonefileCodec**,char**);
+static int zonefileCodecNonceSize(ZonefileCodec*);
+static void zonefileCodecEncode(ZonefileCodec*, unsigned char*, int);
+static void zonefileCodecDecode(ZonefileCodec*, unsigned char*, int);
+static void zonefileCodecDestroy(ZonefileCodec*);
+
 #ifndef SQLITE_HAVE_ZONEFILE_CODEC
 typedef struct ZonefileCodec ZonefileCodec;
 
@@ -157,6 +229,9 @@ struct ZonefileKey {
   ZonefileKey *pHashNext;         /* Next colliding key in hash table */
 };
 
+/*
+** Return a 32-bit hash value for the three arguments.
+*/
 static u32 zonefileKeyHash(
   const char *zDb,
   const char *zTab,
@@ -302,33 +377,19 @@ static void zonefileKeyDestroy(void *p){
   sqlite3_free(pGlobal);
 }
 
-
-#define ZONEFILE_DEFAULT_MAXAUTOFRAMESIZE (64*1024)
-#define ZONEFILE_DEFAULT_ENCRYPTION       1
-#define ZONEFILE_DEFAULT_COMPRESSION      0
-#define ZONEFILE_DEFAULT_DICTSIZE         (64*1024)
-
-#define ZONEFILE_MAGIC_NUMBER 0x464B3138
-
-#define ZONEFILE_SZ_HEADER           32
-#define ZONEFILE_SZ_KEYOFFSETS_ENTRY 20
-
-
-#define ZONEFILE_COMPRESSION_NONE             0
-#define ZONEFILE_COMPRESSION_ZSTD             1
-#define ZONEFILE_COMPRESSION_ZSTD_GLOBAL_DICT 2
-#define ZONEFILE_COMPRESSION_ZLIB             3
-#define ZONEFILE_COMPRESSION_BROTLI           4
-#define ZONEFILE_COMPRESSION_LZ4              5
-#define ZONEFILE_COMPRESSION_LZ4HC            6
-
-
+/*
+** Write value v to buffer aBuf as an unsigned 32-bit big-endian integer.
+*/
 static void zonefilePut32(u8 *aBuf, u32 v){
   aBuf[0] = (v >> 24) & 0xFF;
   aBuf[1] = (v >> 16) & 0xFF;
   aBuf[2] = (v >>  8) & 0xFF;
   aBuf[3] = v & 0xFF;
 }
+
+/*
+** Read and return an unsigned 32-bit big-endian integer from buffer aBuf.
+*/
 static u32 zonefileGet32(const u8 *aBuf){
   return (((u32)aBuf[0]) << 24)
        + (((u32)aBuf[1]) << 16)
@@ -336,6 +397,10 @@ static u32 zonefileGet32(const u8 *aBuf){
        + (((u32)aBuf[3]) <<  0);
 }
 
+/*
+** Generic xOpen, xClose and xUncompressSize methods used by a few
+** different compression method bindings.
+*/
 static int zfGenericOpen(void **pp, u8 *aDict, int nDict){
   *pp = 0;
   return SQLITE_OK;
@@ -652,27 +717,11 @@ static ZonefileCompress *zonefileCompressByValue(int eType){
 **************************************************************************/
 
 
-
-#define ZONEFILE_SCHEMA          \
-  "CREATE TABLE z1("             \
-  "  k INTEGER PRIMARY KEY,"     \
-  "  v BLOB,"                    \
-  "  fileid INTEGER,"            \
-  "  sz INTEGER"                 \
-  ")"
-
-#define ZONEFILE_FILES_SCHEMA    \
-  "CREATE TABLE z2("             \
-  "  filename TEXT,"             \
-  "  ekey BLOB,"                 \
-  "  header JSON HIDDEN"         \
-  ")"
-
-
-
 /*
 ** A structure to store the parameters for a single zonefile_write()
-** invocation. 
+** invocation. An instance of this structure is populated based on
+** the json parameters passed to zonefile_write() by function
+** zonefileGetParams();
 */
 typedef struct ZonefileParam ZonefileParam;
 struct ZonefileParam {
@@ -703,7 +752,7 @@ struct ZonefileHeader {
 };
 
 /*
-** Buffer structure used by the zonefile_write() implementation.
+** Resizable buffer structure used by the zonefile_write() implementation.
 */
 typedef struct ZonefileBuffer ZonefileBuffer;
 struct ZonefileBuffer {
@@ -757,30 +806,6 @@ static int zonefilePrepare(
   return rc;
 }
 
-
-static sqlite3_stmt *zonefileCtxPrepare(
-  sqlite3_context *pCtx,
-  const char *zFmt,
-  ...
-){
-  sqlite3_stmt *pRet = 0;
-  va_list ap;
-  char *zSql;
-  va_start(ap, zFmt);
-  zSql = sqlite3_vmprintf(zFmt, ap);
-  if( zSql ){
-    sqlite3 *db = sqlite3_context_db_handle(pCtx);
-    int rc = sqlite3_prepare(db, zSql, -1, &pRet, 0);
-    if( rc!=SQLITE_OK ){
-      zonefileTransferError(pCtx);
-    }
-    sqlite3_free(zSql);
-  }else{
-    sqlite3_result_error_nomem(pCtx);
-  }
-  return pRet;
-}
-
 /*
 ** Return zero if the two SQL values passed as arguments are equal, or
 ** non-zero otherwise. Values with different types are considered unequal,
@@ -1134,13 +1159,14 @@ 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 = zonefileCtxPrepare(pCtx, 
+  rc = zonefilePrepare(sqlite3_context_db_handle(pCtx), &pStmt, &zErr,
       "SELECT k, frame, v FROM %Q ORDER BY frame, idx, k", zTbl
   );
-  if( pStmt==0 ) goto zone_write_out;
 
   /* Open the file-handle used to write out the zonefile */ 
-  pFd = zonefileFileOpen(zFile, 1, &zErr);
+  if( rc==SQLITE_OK ){
+    pFd = zonefileFileOpen(zFile, 1, &zErr);
+  }
   if( pFd==0 ){
     sqlite3_result_error(pCtx, zErr, -1);
     sqlite3_free(zErr);
@@ -1893,6 +1919,7 @@ struct ZonefileTab {
   ZonefileGlobal *pGlobal;
   char *zName;               /* Name of this table */
   char *zDb;                 /* Name of db containing this table */
+  int nCacheSize;
 };
 
 typedef struct ZonefileCsr ZonefileCsr;
@@ -1901,6 +1928,81 @@ struct ZonefileCsr {
   sqlite3_stmt *pSelect;     /* SELECT on %_shadow_idx table */
 };
 
+typedef struct ZonefileFrame ZonefileFrame;
+struct ZonefileFrame {
+  i64 iFileid;               /* Fileid for this frame */
+  i64 iFrameOff;             /* Offset of frame in file */
+  int nBuf;                  /* Size of aBuf[] in bytes */
+  u8 *aBuf;                  /* Buffer containing uncompressed frame data */
+};
+
+/*
+** Attempt to interpret the contents of string z as an integer. If
+** successful, set (*piVal) to the integer value and return SQLITE_OK.
+** Otherwise, return SQLITE_ERROR.
+*/
+static int zonefileParseInteger(const char *z, int *piVal){
+  *piVal = atoi(z);
+  return SQLITE_OK;
+}
+
+/*
+** Return true character i is considered to be whitespace.
+*/
+static int zonefile_isspace(char i){
+  return (i==' ');
+}
+
+/*
+** This function is called as part of constructing zonefile virtual table
+** pTab. Argument zOption is the full text of a parameter (column name)
+** specified as part of the CREATE VIRTUAL TABLE statement. This function
+** attempts to interpret the parameter and update structure pTab 
+** accordingly. If successful, SQLITE_OK is returned. Otherwise, an
+** SQLite error code is returned and (*pzErr) is left pointing to
+** a buffer containing an English language error message. It is the
+** responsibility of the caller to eventually free this buffer using
+** sqlite3_free().
+*/
+static int zonefileParseOption(
+  ZonefileTab *pTab,              /* Zonefile vtab under construction */
+  const char *zOption,            /* Text of option (column name) */
+  char **pzErr                    /* OUT: Error message */
+){
+  const char *z = zOption;
+  const char *zOpt;
+  int nOpt;
+  const char *zVal;
+  int rc = SQLITE_OK;
+
+  /* Skip leading whitespace */
+  while( zonefile_isspace(*z) ) z++;
+  zOpt = z;
+
+  /* Skip until EOF, whitespace or "=" */
+  while( *z && !zonefile_isspace(*z) && *z!='=' ) z++;
+  nOpt = z-zOpt;
+
+  /* Skip whitespace. Then check there is an "=". */
+  while( zonefile_isspace(*z) ) z++;
+  if( *z!='=' ) goto parse_error;
+  z++;
+  while( zonefile_isspace(*z) ) z++;
+  zVal = z;
+
+  if( nOpt==9 && sqlite3_strnicmp(zOpt, "cachesize", 9)==0 ){
+    rc = zonefileParseInteger(zVal, &pTab->nCacheSize);
+  }else{
+    goto parse_error;
+  }
+
+  return rc;
+
+ parse_error:
+  *pzErr = sqlite3_mprintf("parse error in option: %s", zOption);
+  return SQLITE_ERROR;
+}
+
 /*
 ** This function does the work of xCreate (if bCreate!=0) or xConnect
 ** (if bCreate==0) for the zonefile module.
@@ -1928,6 +2030,7 @@ static int zonefileCreateConnect(
   if( !p ){
     rc = SQLITE_NOMEM;
   }else{
+    int i;
     memset(p, 0, sizeof(ZonefileTab));
     p->zName = (char*)&p[1];
     memcpy(p->zName, zName, nName+1);
@@ -1965,6 +2068,10 @@ static int zonefileCreateConnect(
     if( rc==SQLITE_OK ){
       rc = sqlite3_declare_vtab(db, ZONEFILE_SCHEMA);
     }
+
+    for(i=3; i<argc && rc==SQLITE_OK; i++){
+      zonefileParseOption(p, argv[i], pzErr);
+    }
   }
 
   if( rc!=SQLITE_OK ){
@@ -2276,119 +2383,194 @@ static void zonefileReleaseFile(ZonefileCsr *pCsr){
   sqlite3_reset(pTab->pIdToName);
 }
 
-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;
-  ZonefileHeader hdr;
-  ZonefileCompress *pCmpMethod = 0;
-  ZonefileCodec *pCodec = 0;
-  void *pCmp = 0;
+static int zonefileValueReadDirect(sqlite3_context *pCtx, ZonefileCsr *pCsr){
+  i64 iOff = sqlite3_column_int64(pCsr->pSelect, 2);
+  int sz = sqlite3_column_int(pCsr->pSelect, 3);
 
-  /* Open the file to read the blob from */
-  rc = zonefileGetFile(pCtx, pCsr, &zFile);
-  if( rc==SQLITE_OK ){
-    pFd = zonefileFileOpen(zFile, 0, &zErr);
-    if( pFd==0 ) rc = SQLITE_ERROR;
-  }
+  FILE *pFd = 0;                  /* File handle open on zonefile */
+  u8 *aBuf;                       /* Buffer to read blob into */
+  int rc;                         /* Return code */
 
-  /* Read the zonefile header */
-  if( rc==SQLITE_OK ){
-    rc = zonefileReadHeader(pFd, zFile, &hdr, &zErr);
+  aBuf = sqlite3_malloc(sz);
+  if( aBuf==0 ){
+    rc = SQLITE_NOMEM;
+  }else{
+    const char *zFile = 0;
+    /* Open the file to read the blob from */
+    rc = zonefileGetFile(pCtx, pCsr, &zFile);
+    if( rc==SQLITE_OK ){
+      char *zErr = 0;
+      pFd = zonefileFileOpen(zFile, 0, &zErr);
+      if( pFd==0 ){ 
+        sqlite3_result_error(pCtx, zErr, -1);
+        sqlite3_free(zErr);
+        rc = SQLITE_ERROR;
+      }
+      zonefileReleaseFile(pCsr);
+    }
   }
 
-  /* Find the compression method and open the compressor handle. */
   if( rc==SQLITE_OK ){
-    rc = zfFindCompress(hdr.compressionTypeContent, &pCmpMethod, &zErr);
+    rc = zonefileFileRead(pFd, aBuf, sz, iOff);
+    if( rc==SQLITE_OK ){
+      sqlite3_result_blob(pCtx, aBuf, sz, zonefileFree);
+      aBuf = 0;
+    }
   }
-  if( pCmpMethod ){
-    int nDict = 0;
-    u8 *aDict = 0;
-    assert( rc==SQLITE_OK );
-    if( hdr.byteOffsetDictionary ){
-      nDict = hdr.byteOffsetFrames - hdr.byteOffsetDictionary;
-      aDict = sqlite3_malloc(nDict);
-      if( aDict==0 ){
-        rc = SQLITE_NOMEM;
+
+  zonefileFileClose(pFd);
+  sqlite3_free(aBuf);
+  return rc;
+}
+
+static ZonefileFrame *zonefileCacheFind(
+  ZonefileTab *pTab, 
+  i64 iFile, 
+  i64 iFrameOff
+){
+  return 0;
+}
+
+static void zonefileCacheStore(
+  ZonefileTab *pTab,
+  ZonefileFrame *pFrame
+){
+}
+
+static int zonefileValueReadCache(sqlite3_context *pCtx, ZonefileCsr *pCsr){
+  int rc = SQLITE_OK;
+  ZonefileTab *pTab = (ZonefileTab*)pCsr->base.pVtab;
+  ZonefileFrame *pFrame = 0;
+  i64 iFile = sqlite3_column_int64(pCsr->pSelect, 1);
+  i64 iFrameOff = sqlite3_column_int64(pCsr->pSelect, 2);
+  i64 iKeyOff = sqlite3_column_int64(pCsr->pSelect, 4);
+  int nKeySz = sqlite3_column_int64(pCsr->pSelect, 5);
+
+  /* Check if this frame is already in the cache. If not, read it from 
+  ** the file.  */
+  pFrame = zonefileCacheFind(pTab, iFile, iFrameOff);
+  if( pFrame==0 ){
+    const char *zFile = 0;
+    char *zErr = 0;
+    FILE *pFd = 0;
+    ZonefileHeader hdr;
+    ZonefileCompress *pCmpMethod = 0;
+    ZonefileCodec *pCodec = 0;
+    void *pCmp = 0;
+
+    /* Open the file to read the blob from */
+    rc = zonefileGetFile(pCtx, pCsr, &zFile);
+    if( rc==SQLITE_OK ){
+      pFd = zonefileFileOpen(zFile, 0, &zErr);
+      if( pFd==0 ) rc = SQLITE_ERROR;
+    }
+
+    /* Read the zonefile header */
+    if( rc==SQLITE_OK ){
+      rc = zonefileReadHeader(pFd, zFile, &hdr, &zErr);
+    }
+
+    /* Find the compression method and open the compressor handle. */
+    if( rc==SQLITE_OK ){
+      rc = zfFindCompress(hdr.compressionTypeContent, &pCmpMethod, &zErr);
+    }
+    if( pCmpMethod ){
+      int nDict = 0;
+      u8 *aDict = 0;
+      assert( rc==SQLITE_OK );
+      if( hdr.byteOffsetDictionary ){
+        nDict = hdr.byteOffsetFrames - hdr.byteOffsetDictionary;
+        aDict = sqlite3_malloc(nDict);
+        if( aDict==0 ){
+          rc = SQLITE_NOMEM;
+        }else{
+          rc = zonefileFileRead(pFd, aDict, nDict, hdr.byteOffsetDictionary);
+        }
+      }
+      if( rc==SQLITE_OK ){
+        rc = pCmpMethod->xOpen(&pCmp, aDict, nDict);
+      }
+      sqlite3_free(aDict);
+    }
+
+    /* Find the encryption method and key. */
+    if( hdr.encryptionType ){
+      const char *z = 0;
+      int n = zonefileKeyFind(pTab->pGlobal, pTab->zDb, pTab->zName, iFile, &z);
+      if( n==0 ){
+        zErr = sqlite3_mprintf("missing encryption key for file \"%s\"", zFile);
+        rc = SQLITE_ERROR;
       }else{
-        rc = zonefileFileRead(pFd, aDict, nDict, hdr.byteOffsetDictionary);
+        rc = zonefileCodecCreate(hdr.encryptionType, (u8*)z, n, &pCodec, &zErr);
       }
     }
+
+    /* Read some data into memory. */
     if( rc==SQLITE_OK ){
-      rc = pCmpMethod->xOpen(&pCmp, aDict, nDict);
+      int szFrame = sqlite3_column_int(pCsr->pSelect, 3);
+
+      pFrame = (ZonefileFrame*)sqlite3_malloc(szFrame + sizeof(ZonefileFrame));
+      if( pFrame==0 ){
+        rc = SQLITE_NOMEM;
+      }else{
+        memset(pFrame, 0, sizeof(ZonefileFrame));
+        pFrame->aBuf = (u8*)&pFrame[1];
+        pFrame->nBuf = szFrame;
+        pFrame->iFrameOff = iFrameOff;
+        pFrame->iFileid = iFile;
+        rc = zonefileFileRead(pFd, pFrame->aBuf, szFrame, iFrameOff);
+      }
     }
-    sqlite3_free(aDict);
-  }
 
-  /* Find the encryption method and key. */
-  if( hdr.encryptionType ){
-    i64 iFileid = sqlite3_column_int64(pCsr->pSelect, 1);
-    const char *z = 0;
-    int n = zonefileKeyFind(pTab->pGlobal, pTab->zDb, pTab->zName, iFileid, &z);
-    if( n==0 ){
-      zErr = sqlite3_mprintf("missing encryption key for file \"%s\"", zFile);
-      rc = SQLITE_ERROR;
-    }else{
-      rc = zonefileCodecCreate(hdr.encryptionType, (u8*)z, n, &pCodec, &zErr);
+    /* Decrypt data if necessary */
+    if( rc==SQLITE_OK && pCodec ){
+      zonefileCodecDecode(pCodec, pFrame->aBuf, pFrame->nBuf);
+      pFrame->nBuf -= zonefileCodecNonceSize(pCodec);
     }
-  }
 
-  /* Read some data into memory. If the data is uncompressed, then just
-  ** the required record is read. Otherwise, the entire frame is read
-  ** into memory.  */
-  if( rc==SQLITE_OK ){
-    i64 iFrameOff = sqlite3_column_int64(pCsr->pSelect, 2);
-    int szFrame = sqlite3_column_int(pCsr->pSelect, 3);
-    u8 *aBuf = sqlite3_malloc(szFrame);
+    /* Uncompress data if required */
+    if( rc==SQLITE_OK && pCmpMethod ){
+      ZonefileFrame *p = 0;
+      int nOut = pCmpMethod->xUncompressSize(pCmp, pFrame->aBuf, pFrame->nBuf);
 
-    if( aBuf==0 ){
-      rc = SQLITE_NOMEM;
-    }else{
-      rc = zonefileFileRead(pFd, aBuf, szFrame, iFrameOff);
-      if( rc!=SQLITE_OK ){
-        zErr = sqlite3_mprintf(
-            "failed to read %d bytes at offset %d from file \"%s\"", 
-            szFrame, iFrameOff, zFile
+      p = (ZonefileFrame*)sqlite3_malloc(nOut + sizeof(ZonefileFrame));
+      if( p==0 ){
+        rc = SQLITE_NOMEM;
+      }else{
+        p->aBuf = (u8*)&p[1];
+        p->nBuf = nOut;
+        p->iFrameOff = iFrameOff;
+        p->iFileid = iFile;
+        rc = pCmpMethod->xUncompress(
+            pCmp, p->aBuf, p->nBuf, pFrame->aBuf, pFrame->nBuf
         );
+        sqlite3_free(pFrame);
+        pFrame = p;
       }
     }
 
-    if( rc==SQLITE_OK ){
-      if( pCodec==0 && pCmpMethod==0 ){
-        sqlite3_result_blob(pCtx, aBuf, szFrame, zonefileFree);
-        aBuf = 0;
-      }else{
-        i64 iOff = sqlite3_column_int64(pCsr->pSelect, 4);
-        int sz = sqlite3_column_int(pCsr->pSelect, 5);
+    if( rc!=SQLITE_OK ){
+      sqlite3_free(pFrame);
+      pFrame = 0;
+    }
+    zonefileReleaseFile(pCsr);
+    zonefileFileClose(pFd);
+    zonefileCodecDestroy(pCodec);
+    if( pCmpMethod ) pCmpMethod->xClose(pCmp);
 
-        /* Decrypt the data if necessary */
-        if( pCodec ){
-          zonefileCodecDecode(pCodec, aBuf, szFrame);
-          szFrame -= zonefileCodecNonceSize(pCodec);
-        }
-        if( pCmpMethod ){
-          rc = zonefileCtxUncompress(
-              pCtx, pCmpMethod, pCmp, aBuf, szFrame, iOff, sz
-          );
-        }else{
-          sqlite3_result_blob(pCtx, &aBuf[iOff], sz, SQLITE_TRANSIENT);
-        }
-      }
+    if( zErr ){
+      assert( rc!=SQLITE_OK );
+      sqlite3_result_error(pCtx, zErr, -1);
+      sqlite3_free(zErr);
     }
-    sqlite3_free(aBuf);
   }
 
-  zonefileReleaseFile(pCsr);
-  if( zErr ){
-    assert( rc!=SQLITE_OK );
-    sqlite3_result_error(pCtx, zErr, -1);
-    sqlite3_free(zErr);
+  if( pFrame ){
+    assert( rc==SQLITE_OK );
+    sqlite3_result_blob(pCtx, &pFrame->aBuf[iKeyOff], nKeySz, SQLITE_TRANSIENT);
+    sqlite3_free(pFrame);
   }
-  zonefileFileClose(pFd);
-  zonefileCodecDestroy(pCodec);
-  if( pCmpMethod ) pCmpMethod->xClose(pCmp);
+
   return rc;
 }
 
@@ -2407,7 +2589,11 @@ static int zonefileColumn(
       sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 0));
       break;
     case 1: /* v */
-      rc = zonefileGetValue(pCtx, pCsr);
+      if( sqlite3_column_type(pCsr->pSelect, 5)==SQLITE_NULL ){
+        rc = zonefileValueReadDirect(pCtx, pCsr);
+      }else{
+        rc = zonefileValueReadCache(pCtx, pCsr);
+      }
       break;
     case 2: /* fileid */
       sqlite3_result_value(pCtx, sqlite3_column_value(pCsr->pSelect, 1));
index d667fb70b02ddeae638fff38ad89e7abf11e9863..46437ab12ace58bd34a4f5fe1cf6fc3e08f447e3 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Have\szonefile\sstore\sencryption\skeys\sin\sa\shash-table\sinstead\sof\sa\slinked\slist.\nAdd\sextra\stests\sfor\skey\smanagement.
-D 2018-02-21T16:36:08.835
+C Modifications\sto\sthe\szonefile\smodule\sto\smake\sit\seasier\sto\sadd\sa\scache\sof\nuncompressed\sframe\scontent.
+D 2018-02-21T21:15:45.427
 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
 F Makefile.in 7a3f714b4fcf793108042b7b0a5c720b0b310ec84314d61ba7f3f49f27e550ea
@@ -409,7 +409,7 @@ F ext/userauth/sqlite3userauth.h 7f3ea8c4686db8e40b0a0e7a8e0b00fac13aa7a3
 F ext/userauth/user-auth.txt e6641021a9210364665fe625d067617d03f27b04
 F ext/userauth/userauth.c 3410be31283abba70255d71fd24734e017a4497f
 F ext/zonefile/README.md df86ef5b4f9aa8b07e1c8124b3f2dcea616927385aad59d525b784f0a06d446c
-F ext/zonefile/zonefile.c cd19e711853a13c16c0926b61f670b041c3a19926493e2b872c8ef1fa97991f4
+F ext/zonefile/zonefile.c 55bd8e0ff63f899903ee07936e32f54cb28045916ffba58d97a8bf2cb8f55e53
 F ext/zonefile/zonefile1.test 4cd9fa8d333c195f59792c4d5c1e8387e778e46354580fbef0b84efc932c6a47
 F ext/zonefile/zonefileenc.test 5cc89a1e716b127a5220f03162ced3bd9d7df8819fe04a87f2d962315e8ebdc1
 F install-sh 9d4de14ab9fb0facae2f48780b874848cbf2f895 x
@@ -1709,7 +1709,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 38d23888cf5a7117c51bd9211bd93ec52a30360f7eb2bc83a13910c5d85fe739
-R 60f734b7b910cc2f794eaa1390ac35ea
+P 3a63ea652546a4c63eccd72665becff38a97a0e39d2f11703cb6899451570fd4
+R 436b9d8cf180e93dddc41915bda96996
 U dan
-Z 89722e52aeff8e71e402a249ff14e24d
+Z 5dfc0a85444f2182f7082352bc1286fe
index 4d8d6ebee58016c4c1a07fa473dd39b9316096c8..111cf7153373fa9c13ec24da02abb7474f6632e8 100644 (file)
@@ -1 +1 @@
-3a63ea652546a4c63eccd72665becff38a97a0e39d2f11703cb6899451570fd4
\ No newline at end of file
+d9d5cc62f11058f9ba560381367ff4765dbbde08184e55abdb50ae1b6bf4a016
\ No newline at end of file