/ Check-in [c1f43a77]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initial implementation of eponymous virtual table instances.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | table-valued-functions
Files: files | file ages | folders
SHA1: c1f43a7799a9298abea01b2f8531fc7cdadc4594
User & Date: drh 2015-08-19 02:32:25
Context
2015-08-19
12:52
Merge changes from trunk. check-in: dddd792d user: drh tags: table-valued-functions
02:32
Initial implementation of eponymous virtual table instances. check-in: c1f43a77 user: drh tags: table-valued-functions
2015-08-18
16:32
Fix harmless compiler warning in FTS5. check-in: 02448a9f user: mistachkin tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

   351    351     ** and code in pParse and return NULL. */
   352    352     if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
   353    353       return 0;
   354    354     }
   355    355   
   356    356     p = sqlite3FindTable(pParse->db, zName, zDbase);
   357    357     if( p==0 ){
          358  +#ifndef SQLITE_OMIT_VIRTUAL_TABLE
          359  +    /* If zName is the not the name of a table in the schema created using
          360  +    ** CREATE, then check to see if it is the name of an virtual table that
          361  +    ** can be an eponymous virtual table. */
          362  +    Module *pMod = (Module*)sqlite3HashFind(&pParse->db->aModule, zName);
          363  +    if( pMod && sqlite3VtabEponymousTableInit(pParse, pMod) ){
          364  +      return pMod->pEpoTab;
          365  +    }
          366  +#endif
   358    367       const char *zMsg = isView ? "no such view" : "no such table";
   359    368       if( zDbase ){
   360    369         sqlite3ErrorMsg(pParse, "%s: %s.%s", zMsg, zDbase, zName);
   361    370       }else{
   362    371         sqlite3ErrorMsg(pParse, "%s: %s", zMsg, zName);
   363    372       }
   364    373       pParse->checkSchema = 1;
................................................................................
   556    565     db->flags &= ~SQLITE_InternChanges;
   557    566   }
   558    567   
   559    568   /*
   560    569   ** Delete memory allocated for the column names of a table or view (the
   561    570   ** Table.aCol[] array).
   562    571   */
   563         -static void sqliteDeleteColumnNames(sqlite3 *db, Table *pTable){
          572  +void sqlite3DeleteColumnNames(sqlite3 *db, Table *pTable){
   564    573     int i;
   565    574     Column *pCol;
   566    575     assert( pTable!=0 );
   567    576     if( (pCol = pTable->aCol)!=0 ){
   568    577       for(i=0; i<pTable->nCol; i++, pCol++){
   569    578         sqlite3DbFree(db, pCol->zName);
   570    579         sqlite3ExprDelete(db, pCol->pDflt);
................................................................................
   623    632     }
   624    633   
   625    634     /* Delete any foreign keys attached to this table. */
   626    635     sqlite3FkDelete(db, pTable);
   627    636   
   628    637     /* Delete the Table structure itself.
   629    638     */
   630         -  sqliteDeleteColumnNames(db, pTable);
          639  +  sqlite3DeleteColumnNames(db, pTable);
   631    640     sqlite3DbFree(db, pTable->zName);
   632    641     sqlite3DbFree(db, pTable->zColAff);
   633    642     sqlite3SelectDelete(db, pTable->pSelect);
   634    643   #ifndef SQLITE_OMIT_CHECK
   635    644     sqlite3ExprListDelete(db, pTable->pCheck);
   636    645   #endif
   637    646   #ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
  2214   2223   static void sqliteViewResetAll(sqlite3 *db, int idx){
  2215   2224     HashElem *i;
  2216   2225     assert( sqlite3SchemaMutexHeld(db, idx, 0) );
  2217   2226     if( !DbHasProperty(db, idx, DB_UnresetViews) ) return;
  2218   2227     for(i=sqliteHashFirst(&db->aDb[idx].pSchema->tblHash); i;i=sqliteHashNext(i)){
  2219   2228       Table *pTab = sqliteHashData(i);
  2220   2229       if( pTab->pSelect ){
  2221         -      sqliteDeleteColumnNames(db, pTab);
         2230  +      sqlite3DeleteColumnNames(db, pTab);
  2222   2231         pTab->aCol = 0;
  2223   2232         pTab->nCol = 0;
  2224   2233       }
  2225   2234     }
  2226   2235     DbClearProperty(db, idx, DB_UnresetViews);
  2227   2236   }
  2228   2237   #else

Changes to src/main.c.

   928    928   /*
   929    929   ** Disconnect all sqlite3_vtab objects that belong to database connection
   930    930   ** db. This is called when db is being closed.
   931    931   */
   932    932   static void disconnectAllVtab(sqlite3 *db){
   933    933   #ifndef SQLITE_OMIT_VIRTUALTABLE
   934    934     int i;
          935  +  HashElem *p;
   935    936     sqlite3BtreeEnterAll(db);
   936    937     for(i=0; i<db->nDb; i++){
   937    938       Schema *pSchema = db->aDb[i].pSchema;
   938    939       if( db->aDb[i].pSchema ){
   939         -      HashElem *p;
   940    940         for(p=sqliteHashFirst(&pSchema->tblHash); p; p=sqliteHashNext(p)){
   941    941           Table *pTab = (Table *)sqliteHashData(p);
   942    942           if( IsVirtual(pTab) ) sqlite3VtabDisconnect(db, pTab);
   943    943         }
   944    944       }
          945  +  }
          946  +  for(p=sqliteHashFirst(&db->aModule); p; p=sqliteHashNext(p)){
          947  +    Module *pMod = (Module *)sqliteHashData(p);
          948  +    if( pMod->pEpoTab ){
          949  +      sqlite3VtabDisconnect(db, pMod->pEpoTab);
          950  +    }
   945    951     }
   946    952     sqlite3VtabUnlockList(db);
   947    953     sqlite3BtreeLeaveAll(db);
   948    954   #else
   949    955     UNUSED_PARAMETER(db);
   950    956   #endif
   951    957   }
................................................................................
  1116   1122     sqlite3HashClear(&db->aCollSeq);
  1117   1123   #ifndef SQLITE_OMIT_VIRTUALTABLE
  1118   1124     for(i=sqliteHashFirst(&db->aModule); i; i=sqliteHashNext(i)){
  1119   1125       Module *pMod = (Module *)sqliteHashData(i);
  1120   1126       if( pMod->xDestroy ){
  1121   1127         pMod->xDestroy(pMod->pAux);
  1122   1128       }
         1129  +    sqlite3VtabEponymousTableClear(db, pMod);
  1123   1130       sqlite3DbFree(db, pMod);
  1124   1131     }
  1125   1132     sqlite3HashClear(&db->aModule);
  1126   1133   #endif
  1127   1134   
  1128   1135     sqlite3Error(db, SQLITE_OK); /* Deallocates any cached error strings. */
  1129   1136     sqlite3ValueFree(db->pErr);

Changes to src/sqliteInt.h.

  1475   1475   ** hash table.
  1476   1476   */
  1477   1477   struct Module {
  1478   1478     const sqlite3_module *pModule;       /* Callback pointers */
  1479   1479     const char *zName;                   /* Name passed to create_module() */
  1480   1480     void *pAux;                          /* pAux passed to create_module() */
  1481   1481     void (*xDestroy)(void *);            /* Module destructor function */
         1482  +  Table *pEpoTab;                      /* Eponymous table for this module */
  1482   1483   };
  1483   1484   
  1484   1485   /*
  1485   1486   ** information about each column of an SQL table is held in an instance
  1486   1487   ** of this structure.
  1487   1488   */
  1488   1489   struct Column {
................................................................................
  3244   3245   int sqlite3InitCallback(void*, int, char**, char**);
  3245   3246   void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
  3246   3247   void sqlite3ResetAllSchemasOfConnection(sqlite3*);
  3247   3248   void sqlite3ResetOneSchema(sqlite3*,int);
  3248   3249   void sqlite3CollapseDatabaseArray(sqlite3*);
  3249   3250   void sqlite3BeginParse(Parse*,int);
  3250   3251   void sqlite3CommitInternalChanges(sqlite3*);
         3252  +void sqlite3DeleteColumnNames(sqlite3*,Table*);
  3251   3253   Table *sqlite3ResultSetOfSelect(Parse*,Select*);
  3252   3254   void sqlite3OpenMasterTable(Parse *, int);
  3253   3255   Index *sqlite3PrimaryKeyIndex(Table*);
  3254   3256   i16 sqlite3ColumnOfIndex(Index*, i16);
  3255   3257   void sqlite3StartTable(Parse*,Token*,Token*,int,int,int,int);
  3256   3258   void sqlite3AddColumn(Parse*,Token*);
  3257   3259   void sqlite3AddNotNull(Parse*, int);
................................................................................
  3714   3716      void sqlite3VtabUnlock(VTable *);
  3715   3717      void sqlite3VtabUnlockList(sqlite3*);
  3716   3718      int sqlite3VtabSavepoint(sqlite3 *, int, int);
  3717   3719      void sqlite3VtabImportErrmsg(Vdbe*, sqlite3_vtab*);
  3718   3720      VTable *sqlite3GetVTable(sqlite3*, Table*);
  3719   3721   #  define sqlite3VtabInSync(db) ((db)->nVTrans>0 && (db)->aVTrans==0)
  3720   3722   #endif
         3723  +int sqlite3VtabEponymousTableInit(Parse*,Module*);
         3724  +void sqlite3VtabEponymousTableClear(sqlite3*,Module*);
  3721   3725   void sqlite3VtabMakeWritable(Parse*,Table*);
  3722   3726   void sqlite3VtabBeginParse(Parse*, Token*, Token*, Token*, int);
  3723   3727   void sqlite3VtabFinishParse(Parse*, Token*);
  3724   3728   void sqlite3VtabArgInit(Parse*);
  3725   3729   void sqlite3VtabArgExtend(Parse*, Token*);
  3726   3730   int sqlite3VtabCallCreate(sqlite3*, int, const char *, char **);
  3727   3731   int sqlite3VtabCallConnect(Parse*, Table*);

Changes to src/vtab.c.

    54     54         Module *pDel;
    55     55         char *zCopy = (char *)(&pMod[1]);
    56     56         memcpy(zCopy, zName, nName+1);
    57     57         pMod->zName = zCopy;
    58     58         pMod->pModule = pModule;
    59     59         pMod->pAux = pAux;
    60     60         pMod->xDestroy = xDestroy;
           61  +      pMod->pEpoTab = 0;
    61     62         pDel = (Module *)sqlite3HashInsert(&db->aModule,zCopy,(void*)pMod);
    62     63         assert( pDel==0 || pDel==pMod );
    63     64         if( pDel ){
    64     65           db->mallocFailed = 1;
    65     66           sqlite3DbFree(db, pDel);
    66     67         }
    67     68       }
................................................................................
   271    272     if( !db || db->pnBytesFreed==0 ) vtabDisconnectAll(0, p);
   272    273     if( p->azModuleArg ){
   273    274       int i;
   274    275       for(i=0; i<p->nModuleArg; i++){
   275    276         if( i!=1 ) sqlite3DbFree(db, p->azModuleArg[i]);
   276    277       }
   277    278       sqlite3DbFree(db, p->azModuleArg);
          279  +    p->azModuleArg = 0;
   278    280     }
   279    281   }
   280    282   
   281    283   /*
   282    284   ** Add a new module argument to pTable->azModuleArg[].
   283    285   ** The string is not copied - the pointer is stored.  The
   284    286   ** string will be freed automatically when the table is
................................................................................
  1087   1089     if( apVtabLock ){
  1088   1090       pToplevel->apVtabLock = apVtabLock;
  1089   1091       pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
  1090   1092     }else{
  1091   1093       pToplevel->db->mallocFailed = 1;
  1092   1094     }
  1093   1095   }
         1096  +
         1097  +/*
         1098  +** Check to see if virtual tale module pMod can be have an eponymous
         1099  +** virtual table instance.  If it can, create one if one does not already
         1100  +** exist. Return non-zero if the eponymous virtual table instance exists
         1101  +** when this routine returns, and return zero if it does not exist.
         1102  +**
         1103  +** An eponymous virtual table instance is one that is named after its
         1104  +** module, and more importantly, does not require a CREATE VIRTUAL TABLE
         1105  +** statement in order to come into existance.  Eponymous virtual table
         1106  +** instances always exist.  They cannot be DROP-ed.
         1107  +**
         1108  +** Any virtual table module for which xConnect and xCreate are the same
         1109  +** method can have an eponymous virtual table instance.
         1110  +*/
         1111  +int sqlite3VtabEponymousTableInit(Parse *pParse, Module *pMod){
         1112  +  const sqlite3_module *pModule = pMod->pModule;
         1113  +  Table *pTab;
         1114  +  char *zErr = 0;
         1115  +  int nName;
         1116  +  int rc;
         1117  +  sqlite3 *db = pParse->db;
         1118  +  if( pMod->pEpoTab ) return 1;
         1119  +  if( pModule->xCreate!=pModule->xConnect ) return 0;
         1120  +  nName = sqlite3Strlen30(pMod->zName) + 1;
         1121  +  pTab = sqlite3DbMallocZero(db, sizeof(Table) + nName);
         1122  +  if( pTab==0 ) return 0;
         1123  +  pMod->pEpoTab = pTab;
         1124  +  pTab->zName = (char*)&pTab[1];
         1125  +  memcpy(pTab->zName, pMod->zName, nName);
         1126  +  pTab->nRef = 1;
         1127  +  pTab->pSchema = db->aDb[0].pSchema;
         1128  +  pTab->tabFlags |= TF_Virtual;
         1129  +  pTab->nModuleArg = 0;
         1130  +  addModuleArgument(db, pTab, pTab->zName);
         1131  +  addModuleArgument(db, pTab, 0);
         1132  +  addModuleArgument(db, pTab, pTab->zName);
         1133  +  rc = vtabCallConstructor(db, pTab, pMod, pModule->xConnect, &zErr);
         1134  +  if( rc ){
         1135  +    sqlite3ErrorMsg(pParse, "%s", zErr);
         1136  +    sqlite3DbFree(db, zErr);
         1137  +    sqlite3VtabEponymousTableClear(db, pMod);
         1138  +    return 0;
         1139  +  }
         1140  +  return 1;
         1141  +}
         1142  +
         1143  +/*
         1144  +** Erase the eponymous virtual table instance associated with
         1145  +** virtual table module pMod, if it exists.
         1146  +*/
         1147  +void sqlite3VtabEponymousTableClear(sqlite3 *db, Module *pMod){
         1148  +  Table *pTab = pMod->pEpoTab;
         1149  +  if( (pTab = pMod->pEpoTab)!=0 ){
         1150  +    sqlite3DeleteColumnNames(db, pTab);
         1151  +    sqlite3DbFree(db, pTab->azModuleArg);
         1152  +    sqlite3DbFree(db, pTab);
         1153  +    pMod->pEpoTab = 0;
         1154  +  }
         1155  +}
  1094   1156   
  1095   1157   /*
  1096   1158   ** Return the ON CONFLICT resolution mode in effect for the virtual
  1097   1159   ** table update operation currently in progress.
  1098   1160   **
  1099   1161   ** The results of this routine are undefined unless it is called from
  1100   1162   ** within an xUpdate method.