]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Add start of "zonefile" virtual table.
authordan <dan@noemail.net>
Sat, 10 Feb 2018 21:04:12 +0000 (21:04 +0000)
committerdan <dan@noemail.net>
Sat, 10 Feb 2018 21:04:12 +0000 (21:04 +0000)
FossilOrigin-Name: 0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43

ext/zonefile/zonefile.c
ext/zonefile/zonefile1.test
manifest
manifest.uuid

index a52b4cf6264924d330f9e4c302bc7ad6a90f3f7c..cdde4c13da765d3381688ed25ac1b6b0e245ad6a 100644 (file)
@@ -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;
 }
 
index 9aae50c2eedee23cf237ed92300d3b2e5a82c5ae..3f4da1e3745484b4056f9c050d76281378b17db8 100644 (file)
@@ -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
index 2f28794302ddab27df2c07588c425ba48dd88257..ba8da4f50066db52be94a879368f5a11bb36a165 100644 (file)
--- 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
index 0991015f78dca167eaf104c84b16495d3b0d6c2d..c633bfac10a6b25fe1a44370375a8b3d965498f3 100644 (file)
@@ -1 +1 @@
-c125b4c380d1a20c7d71b413e96183eca9987aed3d0ba28395aa79c7c31bb6fd
\ No newline at end of file
+0b7bd1694bf50a5afed22ed3026cefe53c5e7ec334167244e2caa9c56185ff43
\ No newline at end of file