/ Check-in [f44b8bae]
Login

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

Overview
Comment:Add pzErr parameters to the xConnect and xCreate methods of virtual tables in order to provide better error reporting. This is an interface change for virtual tables. Prior virtual table implementations will need to be modified and recompiled. (CVS 3402)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: f44b8bae97b6872524580009c96d07391578c388
User & Date: drh 2006-09-10 17:31:59
Context
2006-09-11
00:34
Add a rudimentary tokenizer and parser to FTS1 for parsing the module arguments during initialization. Recognized arguments include a tokenizer selector and a list of virtual table columns. (CVS 3403) check-in: 227dc3fe user: drh tags: trunk
2006-09-10
17:31
Add pzErr parameters to the xConnect and xCreate methods of virtual tables in order to provide better error reporting. This is an interface change for virtual tables. Prior virtual table implementations will need to be modified and recompiled. (CVS 3402) check-in: f44b8bae user: drh tags: trunk
17:08
Add a new zErrMsg field to the sqlite3_vtab structure to support returning error messages from virtual table constructors. This change means that virtual table implementations compiled as loadable extensions for version 3.3.7 will need to be recompile for version 3.3.8 and will not be usable by both versions at one. The virtual table mechanism is still considered experimental so we feel justified in breaking backwards compatibility in this way. Additional interface changes might occurs in the future. (CVS 3401) check-in: 36693a5c user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to ext/fts1/fts1.c.

  1105   1105   ** argv[0] - module name
  1106   1106   ** argv[1] - database name
  1107   1107   ** argv[2] - table name
  1108   1108   ** argv[3] - tokenizer name (optional, a sensible default is provided)
  1109   1109   ** argv[4..] - passed to tokenizer (optional based on tokenizer)
  1110   1110   **/
  1111   1111   static int fulltextConnect(sqlite3 *db, void *pAux, int argc, char **argv,
  1112         -                           sqlite3_vtab **ppVTab){
         1112  +                           sqlite3_vtab **ppVTab, char **pzErr){
  1113   1113     int rc;
  1114   1114     fulltext_vtab *v;
  1115   1115     const sqlite3_tokenizer_module *m = NULL;
  1116   1116   
  1117   1117     assert( argc>=3 );
  1118   1118     v = (fulltext_vtab *) malloc(sizeof(fulltext_vtab));
  1119         -  /* sqlite will initialize v->base */
         1119  +  memset(v, 0, sizeof(*v));
  1120   1120     v->db = db;
  1121   1121     v->zName = string_dup(argv[2]);
  1122   1122     v->pTokenizer = NULL;
  1123   1123   
  1124   1124     if( argc==3 ){
  1125   1125       sqlite3Fts1SimpleTokenizerModule(&m);
  1126   1126     } else {
  1127   1127       /* TODO(shess) For now, add new tokenizers as else if clauses. */
  1128   1128       if( !strcmp(argv[3], "simple") ){
  1129   1129         sqlite3Fts1SimpleTokenizerModule(&m);
  1130   1130       } else {
         1131  +      *pzErr = sqlite3_mprintf("unknown tokenizer: %s", argv[3]);
  1131   1132         assert( "unrecognized tokenizer"==NULL );
  1132   1133       }
  1133   1134     }
  1134   1135   
  1135   1136     /* TODO(shess) Since tokenization impacts the index, the parameters
  1136   1137     ** to the tokenizer need to be identical when a persistent virtual
  1137   1138     ** table is re-created.  One solution would be a meta-table to track
................................................................................
  1152   1153   
  1153   1154     *ppVTab = &v->base;
  1154   1155     TRACE(("FTS1 Connect %p\n", v));
  1155   1156     return SQLITE_OK;
  1156   1157   }
  1157   1158   
  1158   1159   static int fulltextCreate(sqlite3 *db, void *pAux, int argc, char **argv,
  1159         -                          sqlite3_vtab **ppVTab){
         1160  +                          sqlite3_vtab **ppVTab, char **pzErr){
  1160   1161     int rc;
  1161   1162     assert( argc>=3 );
  1162   1163     TRACE(("FTS1 Create\n"));
  1163   1164   
  1164   1165     /* The %_content table holds the text of each full-text item, with
  1165   1166     ** the rowid used as the docid.
  1166   1167     **
................................................................................
  1198   1199     */
  1199   1200     rc = sql_exec(db, argv[2],
  1200   1201       "create table %_content(content text);"
  1201   1202       "create table %_term(term text, segment integer, doclist blob, "
  1202   1203                           "primary key(term, segment));");
  1203   1204     if( rc!=SQLITE_OK ) return rc;
  1204   1205   
  1205         -  return fulltextConnect(db, pAux, argc, argv, ppVTab);
         1206  +  return fulltextConnect(db, pAux, argc, argv, ppVTab, pzErr);
  1206   1207   }
  1207   1208   
  1208   1209   /* Decide how to handle an SQL query.
  1209   1210    * At the moment, MATCH queries can include implicit boolean ANDs; we
  1210   1211    * haven't implemented phrase searches or OR yet. */
  1211   1212   static int fulltextBestIndex(sqlite3_vtab *pVTab, sqlite3_index_info *pInfo){
  1212   1213     int i;

Changes to src/sqlite.h.in.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This header file defines the interface that the SQLite library
    13     13   ** presents to client programs.
    14     14   **
    15         -** @(#) $Id: sqlite.h.in,v 1.190 2006/09/10 17:08:30 drh Exp $
           15  +** @(#) $Id: sqlite.h.in,v 1.191 2006/09/10 17:31:59 drh Exp $
    16     16   */
    17     17   #ifndef _SQLITE3_H_
    18     18   #define _SQLITE3_H_
    19     19   #include <stdarg.h>     /* Needed for the definition of va_list */
    20     20   
    21     21   /*
    22     22   ** Make sure we can call this stuff from C++.
................................................................................
  1578   1578   ** by an instance of the following structure.  This structure consists
  1579   1579   ** mostly of methods for the module.
  1580   1580   */
  1581   1581   struct sqlite3_module {
  1582   1582     int iVersion;
  1583   1583     int (*xCreate)(sqlite3*, void *pAux,
  1584   1584                  int argc, char **argv,
  1585         -               sqlite3_vtab **ppVTab);
         1585  +               sqlite3_vtab **ppVTab, char**);
  1586   1586     int (*xConnect)(sqlite3*, void *pAux,
  1587   1587                  int argc, char **argv,
  1588         -               sqlite3_vtab **ppVTab);
         1588  +               sqlite3_vtab **ppVTab, char**);
  1589   1589     int (*xBestIndex)(sqlite3_vtab *pVTab, sqlite3_index_info*);
  1590   1590     int (*xDisconnect)(sqlite3_vtab *pVTab);
  1591   1591     int (*xDestroy)(sqlite3_vtab *pVTab);
  1592   1592     int (*xOpen)(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor);
  1593   1593     int (*xClose)(sqlite3_vtab_cursor*);
  1594   1594     int (*xFilter)(sqlite3_vtab_cursor*, int idxNum, const char *idxStr,
  1595   1595                   int argc, sqlite3_value **argv);
................................................................................
  1715   1715   ** that sqlite3_mprintf() and sqlite3_free() are used on the zErrMsg field
  1716   1716   ** since virtual tables are commonly implemented in loadable extensions which
  1717   1717   ** do not have access to sqlite3MPrintf() or sqlite3Free().
  1718   1718   */
  1719   1719   struct sqlite3_vtab {
  1720   1720     const sqlite3_module *pModule;  /* The module for this virtual table */
  1721   1721     int nRef;                       /* Used internally */
  1722         -  char *zErrMsg;                  /* Error message text */
         1722  +  char *zErrMsg;                  /* Error message from sqlite3_mprintf() */
  1723   1723     /* Virtual table implementations will typically add additional fields */
  1724   1724   };
  1725   1725   
  1726   1726   /* Every module implementation uses a subclass of the following structure
  1727   1727   ** to describe cursors that point into the virtual table and are used
  1728   1728   ** to loop through the virtual table.  Cursors are created using the
  1729   1729   ** xOpen method of the module.  Each module implementation will define

Changes to src/test8.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing the virtual table interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test8.c,v 1.40 2006/07/08 18:09:15 drh Exp $
           16  +** $Id: test8.c,v 1.41 2006/09/10 17:32:00 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include "os.h"
    21     21   #include <stdlib.h>
    22     22   #include <string.h>
    23     23   
................................................................................
   308    308   ** to allocate the required in-memory structures for a newly connected
   309    309   ** virtual table.
   310    310   */
   311    311   static int echoConstructor(
   312    312     sqlite3 *db,
   313    313     void *pAux,
   314    314     int argc, char **argv,
   315         -  sqlite3_vtab **ppVtab
          315  +  sqlite3_vtab **ppVtab,
          316  +  char **pzErr
   316    317   ){
   317    318     int i;
   318    319     echo_vtab *pVtab;
   319    320   
   320    321     /* Allocate the sqlite3_vtab/echo_vtab structure itself */
   321    322     pVtab = sqliteMalloc( sizeof(*pVtab) );
   322    323     if( !pVtab ){
................................................................................
   354    355   /* 
   355    356   ** Echo virtual table module xCreate method.
   356    357   */
   357    358   static int echoCreate(
   358    359     sqlite3 *db,
   359    360     void *pAux,
   360    361     int argc, char **argv,
   361         -  sqlite3_vtab **ppVtab
          362  +  sqlite3_vtab **ppVtab,
          363  +  char **pzErr
   362    364   ){
   363    365     int rc = SQLITE_OK;
   364    366     appendToEchoModule((Tcl_Interp *)(pAux), "xCreate");
   365         -  rc = echoConstructor(db, pAux, argc, argv, ppVtab);
          367  +  rc = echoConstructor(db, pAux, argc, argv, ppVtab, pzErr);
   366    368   
   367    369     /* If there were two arguments passed to the module at the SQL level 
   368    370     ** (i.e. "CREATE VIRTUAL TABLE tbl USING echo(arg1, arg2)"), then 
   369    371     ** the second argument is used as a table name. Attempt to create
   370    372     ** such a table with a single column, "logmsg". This table will
   371    373     ** be used to log calls to the xUpdate method. It will be deleted
   372    374     ** when the virtual table is DROPed.
................................................................................
   389    391   /* 
   390    392   ** Echo virtual table module xConnect method.
   391    393   */
   392    394   static int echoConnect(
   393    395     sqlite3 *db,
   394    396     void *pAux,
   395    397     int argc, char **argv,
   396         -  sqlite3_vtab **ppVtab
          398  +  sqlite3_vtab **ppVtab,
          399  +  char **pzErr
   397    400   ){
   398    401     appendToEchoModule((Tcl_Interp *)(pAux), "xConnect");
   399         -  return echoConstructor(db, pAux, argc, argv, ppVtab);
          402  +  return echoConstructor(db, pAux, argc, argv, ppVtab, pzErr);
   400    403   }
   401    404   
   402    405   /* 
   403    406   ** Echo virtual table module xDisconnect method.
   404    407   */
   405    408   static int echoDisconnect(sqlite3_vtab *pVtab){
   406    409     appendToEchoModule(((echo_vtab *)pVtab)->interp, "xDisconnect");

Changes to src/test_schema.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing the virtual table interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test_schema.c,v 1.9 2006/07/08 17:06:44 drh Exp $
           16  +** $Id: test_schema.c,v 1.10 2006/09/10 17:32:00 drh Exp $
    17     17   */
    18     18   
    19     19   /* The code in this file defines a sqlite3 virtual-table module that
    20     20   ** provides a read-only view of the current database schema. There is one
    21     21   ** row in the schema table for each column in the database schema.
    22     22   */
    23     23   #define SCHEMA \
................................................................................
    81     81   /*
    82     82   ** Table constructor for the schema module.
    83     83   */
    84     84   static int schemaCreate(
    85     85     sqlite3 *db,
    86     86     void *pAux,
    87     87     int argc, char **argv,
    88         -  sqlite3_vtab **ppVtab
           88  +  sqlite3_vtab **ppVtab,
           89  +  char **pzErr
    89     90   ){
    90     91     int rc = SQLITE_NOMEM;
    91     92     schema_vtab *pVtab = MALLOC(sizeof(schema_vtab));
    92     93     if( pVtab ){
    93     94       memset(pVtab, 0, sizeof(schema_vtab));
    94     95       pVtab->db = db;
    95     96   #ifndef SQLITE_OMIT_VIRTUALTABLE

Changes to src/test_tclvar.c.

    12     12   ** Code for testing the virtual table interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16     16   ** The emphasis of this file is a virtual table that provides
    17     17   ** access to TCL variables.
    18     18   **
    19         -** $Id: test_tclvar.c,v 1.8 2006/08/15 14:21:16 drh Exp $
           19  +** $Id: test_tclvar.c,v 1.9 2006/09/10 17:32:00 drh Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   #include "tcl.h"
    23     23   #include "os.h"
    24     24   #include <stdlib.h>
    25     25   #include <string.h>
    26     26   
................................................................................
    48     48   };
    49     49   
    50     50   /* Methods for the tclvar module */
    51     51   static int tclvarConnect(
    52     52     sqlite3 *db,
    53     53     void *pAux,
    54     54     int argc, char **argv,
    55         -  sqlite3_vtab **ppVtab
           55  +  sqlite3_vtab **ppVtab,
           56  +  char **pzErr
    56     57   ){
    57     58     tclvar_vtab *pVtab;
    58     59     static const char zSchema[] = 
    59     60        "CREATE TABLE whatever(name TEXT, arrayname TEXT, value TEXT)";
    60     61     pVtab = sqliteMalloc( sizeof(*pVtab) );
    61     62     if( pVtab==0 ) return SQLITE_NOMEM;
    62     63     *ppVtab = &pVtab->base;

Changes to src/vtab.c.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used to help implement virtual tables.
    13     13   **
    14         -** $Id: vtab.c,v 1.32 2006/09/10 17:08:30 drh Exp $
           14  +** $Id: vtab.c,v 1.33 2006/09/10 17:32:00 drh Exp $
    15     15   */
    16     16   #ifndef SQLITE_OMIT_VIRTUALTABLE
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   /*
    20     20   ** External API function used to create a new virtual-table module.
    21     21   */
................................................................................
    55     55   /*
    56     56   ** Unlock a virtual table.  When the last lock is removed,
    57     57   ** disconnect the virtual table.
    58     58   */
    59     59   void sqlite3VtabUnlock(sqlite3_vtab *pVtab){
    60     60     pVtab->nRef--;
    61     61     if( pVtab->nRef==0 ){
    62         -    sqlite3_free(pVtab->zErrMsg);
    63         -    pVtab->zErrMsg = 0;
    64     62       pVtab->pModule->xDisconnect(pVtab);
    65     63     }
    66     64   }
    67     65   
    68     66   /*
    69     67   ** Clear any and all virtual-table information from the Table record.
    70     68   ** This routine is called, for example, just before deleting the Table
................................................................................
   284    282   ** pointer to the function to invoke is passed as the fourth parameter
   285    283   ** to this procedure.
   286    284   */
   287    285   static int vtabCallConstructor(
   288    286     sqlite3 *db, 
   289    287     Table *pTab,
   290    288     Module *pMod,
   291         -  int (*xConstruct)(sqlite3*, void *, int, char **, sqlite3_vtab **),
          289  +  int (*xConstruct)(sqlite3*,void*,int,char**,sqlite3_vtab**,char**),
   292    290     char **pzErr
   293    291   ){
   294    292     int rc;
   295    293     int rc2;
   296    294     sqlite3_vtab *pVtab;
   297    295     char **azArg = pTab->azModuleArg;
   298    296     int nArg = pTab->nModuleArg;
   299         -  char *zErr = sqlite3MPrintf("vtable constructor failed: %s", pTab->zName);
          297  +  char *zErr = 0;
   300    298   
   301    299     assert( !db->pVTab );
   302    300     assert( xConstruct );
   303    301   
   304    302     db->pVTab = pTab;
   305    303     rc = sqlite3SafetyOff(db);
   306    304     assert( rc==SQLITE_OK );
   307         -  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab);
          305  +  rc = xConstruct(db, pMod->pAux, nArg, azArg, &pTab->pVtab, &zErr);
   308    306     rc2 = sqlite3SafetyOn(db);
   309    307     pVtab = pTab->pVtab;
   310    308     if( rc==SQLITE_OK && pVtab ){
   311    309       pVtab->pModule = pMod->pModule;
   312    310       pVtab->nRef = 1;
   313    311     }
   314    312   
   315    313     if( SQLITE_OK!=rc ){
   316         -    if( pVtab && pVtab->zErrMsg ){
   317         -      *pzErr = sqlite3MPrintf("%s", pVtab->zErrMsg);
   318         -      sqlite3_free(pVtab->zErrMsg);
   319         -      pVtab->zErrMsg = 0;
   320         -    }else{
   321         -      *pzErr = zErr;
   322         -      zErr = 0;
          314  +    if( zErr==0 ){
          315  +      *pzErr = sqlite3MPrintf("vtable constructor failed: %s", pTab->zName);
          316  +    }else {
          317  +      *pzErr = sqlite3_mprintf("%s", zErr);
          318  +      sqlite3_free(zErr);
   323    319       }
   324    320     }else if( db->pVTab ){
   325    321       const char *zFormat = "vtable constructor did not declare schema: %s";
   326    322       *pzErr = sqlite3MPrintf(zFormat, pTab->zName);
   327    323       rc = SQLITE_ERROR;
   328    324     } 
   329    325     if( rc==SQLITE_OK ){
   330    326       rc = rc2;
   331    327     }
   332    328     db->pVTab = 0;
   333         -  sqliteFree(zErr);
   334    329     return rc;
   335    330   }
   336    331   
   337    332   /*
   338    333   ** This function is invoked by the parser to call the xConnect() method
   339    334   ** of the virtual table pTab. If an error occurs, an error code is returned 
   340    335   ** and an error left in pParse.