/ Check-in [007359b7]
Login

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

Overview
Comment:Test that virtual table methods xBestIndex, xOpen, xFilter, xNext, xColumn, xRowid, xUpdate, xSync and xBegin can all return error messages using the sqlite3_vtab.zErrMsg variable. (CVS 5519)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 007359b770f225877880b11f4c5d97bb548e38ca
User & Date: danielk1977 2008-08-01 17:37:41
Context
2008-08-01
17:51
Also test that setting sqlite3_vtab.zErrMsg works from within the xRename method. (CVS 5520) check-in: 4f4a9cca user: danielk1977 tags: trunk
17:37
Test that virtual table methods xBestIndex, xOpen, xFilter, xNext, xColumn, xRowid, xUpdate, xSync and xBegin can all return error messages using the sqlite3_vtab.zErrMsg variable. (CVS 5519) check-in: 007359b7 user: danielk1977 tags: trunk
16:31
Test cases for sqlite3_db_config() and sqlite3_db_status(). (CVS 5518) check-in: 6a6b9430 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/sqliteInt.h.

     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   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.748 2008/07/31 17:35:45 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.749 2008/08/01 17:37:41 danielk1977 Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Include the configuration header output by 'configure' if we're using the
    21     21   ** autoconf-based build
................................................................................
  2263   2263   #  define sqlite3VtabClear(X)
  2264   2264   #  define sqlite3VtabSync(X,Y) (Y)
  2265   2265   #  define sqlite3VtabRollback(X)
  2266   2266   #  define sqlite3VtabCommit(X)
  2267   2267   #  define sqlite3VtabTransferError(A,B,C)
  2268   2268   #else
  2269   2269      void sqlite3VtabClear(Table*);
  2270         -   int sqlite3VtabSync(sqlite3 *db, int rc);
         2270  +   int sqlite3VtabSync(sqlite3 *db, char **);
  2271   2271      int sqlite3VtabRollback(sqlite3 *db);
  2272   2272      int sqlite3VtabCommit(sqlite3 *db);
  2273   2273      void sqlite3VtabTransferError(sqlite3 *db, int, sqlite3_vtab*);
  2274   2274   #endif
  2275   2275   void sqlite3VtabMakeWritable(Parse*,Table*);
  2276   2276   void sqlite3VtabLock(sqlite3_vtab*);
  2277   2277   void sqlite3VtabUnlock(sqlite3*, sqlite3_vtab*);

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.69 2008/07/28 19:34:54 drh Exp $
           16  +** $Id: test8.c,v 1.70 2008/08/01 17:37:41 danielk1977 Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include <stdlib.h>
    21     21   #include <string.h>
    22     22   
    23     23   #ifndef SQLITE_OMIT_VIRTUALTABLE
................................................................................
    39     39   ** This is used for automated testing of virtual table modules.
    40     40   **
    41     41   ** The ::echo_module_sync_fail variable is set by test scripts and read
    42     42   ** by code in this file. If it is set to the name of a real table in the
    43     43   ** the database, then all xSync operations on echo virtual tables that
    44     44   ** use the named table as a backing store will fail.
    45     45   */
           46  +
           47  +/*
           48  +** Errors can be provoked within the following echo virtual table methods:
           49  +**
           50  +**   xBestIndex   xOpen     xFilter   xNext   
           51  +**   xColumn      xRowid    xUpdate   xSync   
           52  +**   xBegin
           53  +**
           54  +** This is done by setting the global tcl variable:
           55  +**
           56  +**   echo_module_fail($method,$tbl)
           57  +**
           58  +** where $method is set to the name of the virtual table method to fail
           59  +** (i.e. "xBestIndex") and $tbl is the name of the table being echoed (not
           60  +** the name of the virtual table, the name of the underlying real table).
           61  +*/
    46     62   
    47     63   /* 
    48     64   ** An echo virtual-table object.
    49     65   **
    50     66   ** echo.vtab.aIndex is an array of booleans. The nth entry is true if 
    51     67   ** the nth column of the real table is the left-most column of an index
    52     68   ** (implicit or otherwise). In other words, if SQLite can optimize
................................................................................
    71     87   };
    72     88   
    73     89   /* An echo cursor object */
    74     90   struct echo_cursor {
    75     91     sqlite3_vtab_cursor base;
    76     92     sqlite3_stmt *pStmt;
    77     93   };
           94  +
           95  +static int simulateVtabError(echo_vtab *p, const char *zMethod){
           96  +  const char *zErr;
           97  +  char zVarname[128];
           98  +  zVarname[127] = '\0';
           99  +  snprintf(zVarname, 127, "echo_module_fail(%s,%s)", zMethod, p->zTableName);
          100  +  zErr = Tcl_GetVar(p->interp, zVarname, TCL_GLOBAL_ONLY);
          101  +  if( zErr ){
          102  +    p->base.zErrMsg = sqlite3_mprintf("echo-vtab-error: %s", zErr);
          103  +  }
          104  +  return (zErr!=0);
          105  +}
    78    106   
    79    107   /*
    80    108   ** Convert an SQL-style quoted string into a normal string by removing
    81    109   ** the quote characters.  The conversion is done in-place.  If the
    82    110   ** input does not begin with a quote character, then this routine
    83    111   ** is a no-op.
    84    112   **
................................................................................
   520    548   }
   521    549   
   522    550   /* 
   523    551   ** Echo virtual table module xOpen method.
   524    552   */
   525    553   static int echoOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
   526    554     echo_cursor *pCur;
          555  +  if( simulateVtabError((echo_vtab *)pVTab, "xOpen") ){
          556  +    return SQLITE_ERROR;
          557  +  }
   527    558     pCur = sqlite3MallocZero(sizeof(echo_cursor));
   528    559     *ppCursor = (sqlite3_vtab_cursor *)pCur;
   529    560     return (pCur ? SQLITE_OK : SQLITE_NOMEM);
   530    561   }
   531    562   
   532    563   /* 
   533    564   ** Echo virtual table module xClose method.
................................................................................
   552    583   
   553    584   /* 
   554    585   ** Echo virtual table module xNext method.
   555    586   */
   556    587   static int echoNext(sqlite3_vtab_cursor *cur){
   557    588     int rc = SQLITE_OK;
   558    589     echo_cursor *pCur = (echo_cursor *)cur;
          590  +
          591  +  if( simulateVtabError((echo_vtab *)(cur->pVtab), "xNext") ){
          592  +    return SQLITE_ERROR;
          593  +  }
   559    594   
   560    595     if( pCur->pStmt ){
   561    596       rc = sqlite3_step(pCur->pStmt);
   562    597       if( rc==SQLITE_ROW ){
   563    598         rc = SQLITE_OK;
   564    599       }else{
   565    600         rc = sqlite3_finalize(pCur->pStmt);
................................................................................
   572    607   
   573    608   /* 
   574    609   ** Echo virtual table module xColumn method.
   575    610   */
   576    611   static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
   577    612     int iCol = i + 1;
   578    613     sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt;
          614  +
          615  +  if( simulateVtabError((echo_vtab *)(cur->pVtab), "xColumn") ){
          616  +    return SQLITE_ERROR;
          617  +  }
          618  +
   579    619     if( !pStmt ){
   580    620       sqlite3_result_null(ctx);
   581    621     }else{
   582    622       assert( sqlite3_data_count(pStmt)>iCol );
   583    623       sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
   584    624     }
   585    625     return SQLITE_OK;
................................................................................
   586    626   }
   587    627   
   588    628   /* 
   589    629   ** Echo virtual table module xRowid method.
   590    630   */
   591    631   static int echoRowid(sqlite3_vtab_cursor *cur, sqlite_int64 *pRowid){
   592    632     sqlite3_stmt *pStmt = ((echo_cursor *)cur)->pStmt;
          633  +
          634  +  if( simulateVtabError((echo_vtab *)(cur->pVtab), "xRowid") ){
          635  +    return SQLITE_ERROR;
          636  +  }
          637  +
   593    638     *pRowid = sqlite3_column_int64(pStmt, 0);
   594    639     return SQLITE_OK;
   595    640   }
   596    641   
   597    642   /*
   598    643   ** Compute a simple hash of the null terminated string zString.
   599    644   **
................................................................................
   622    667   ){
   623    668     int rc;
   624    669     int i;
   625    670   
   626    671     echo_cursor *pCur = (echo_cursor *)pVtabCursor;
   627    672     echo_vtab *pVtab = (echo_vtab *)pVtabCursor->pVtab;
   628    673     sqlite3 *db = pVtab->db;
          674  +
          675  +  if( simulateVtabError(pVtab, "xFilter") ){
          676  +    return SQLITE_ERROR;
          677  +  }
   629    678   
   630    679     /* Check that idxNum matches idxStr */
   631    680     assert( idxNum==hashString(idxStr) );
   632    681   
   633    682     /* Log arguments to the ::echo_module Tcl variable */
   634    683     appendToEchoModule(pVtab->interp, "xFilter");
   635    684     appendToEchoModule(pVtab->interp, idxStr);
................................................................................
   730    779     Tcl_Interp *interp = pVtab->interp;
   731    780   
   732    781     int nRow;
   733    782     int useIdx = 0;
   734    783     int rc = SQLITE_OK;
   735    784     int useCost = 0;
   736    785     double cost;
   737         -
   738    786     int isIgnoreUsable = 0;
   739    787     if( Tcl_GetVar(interp, "echo_module_ignore_usable", TCL_GLOBAL_ONLY) ){
   740    788       isIgnoreUsable = 1;
   741    789     }
          790  +
          791  +  if( simulateVtabError(pVtab, "xBestIndex") ){
          792  +    return SQLITE_ERROR;
          793  +  }
   742    794   
   743    795     /* Determine the number of rows in the table and store this value in local
   744    796     ** variable nRow. The 'estimated-cost' of the scan will be the number of
   745    797     ** rows in the table for a linear scan, or the log (base 2) of the 
   746    798     ** number of rows if the proposed scan uses an index.  
   747    799     */
   748    800     if( Tcl_GetVar(interp, "echo_module_cost", TCL_GLOBAL_ONLY) ){
................................................................................
   887    939     int i;                     /* Counter variable used by for loops */
   888    940   
   889    941     assert( nData==pVtab->nCol+2 || nData==1 );
   890    942   
   891    943     /* Ticket #3083 - make sure we always start a transaction prior to
   892    944     ** making any changes to a virtual table */
   893    945     assert( pVtab->inTransaction );
          946  +
          947  +  if( simulateVtabError(pVtab, "xUpdate") ){
          948  +    return SQLITE_ERROR;
          949  +  }
   894    950   
   895    951     /* If apData[0] is an integer and nData>1 then do an UPDATE */
   896    952     if( nData>1 && sqlite3_value_type(apData[0])==SQLITE_INTEGER ){
   897    953       char *zSep = " SET";
   898    954       z = sqlite3_mprintf("UPDATE %Q", pVtab->zTableName);
   899    955       if( !z ){
   900    956         rc = SQLITE_NOMEM;
................................................................................
  1014   1070     echo_vtab *pVtab = (echo_vtab *)tab;
  1015   1071     Tcl_Interp *interp = pVtab->interp;
  1016   1072     const char *zVal; 
  1017   1073   
  1018   1074     /* Ticket #3083 - do not start a transaction if we are already in
  1019   1075     ** a transaction */
  1020   1076     assert( !pVtab->inTransaction );
         1077  +
         1078  +  if( simulateVtabError(pVtab, "xBegin") ){
         1079  +    return SQLITE_ERROR;
         1080  +  }
  1021   1081   
  1022   1082     rc = echoTransactionCall(tab, "xBegin");
  1023   1083   
  1024   1084     if( rc==SQLITE_OK ){
  1025   1085       /* Check if the $::echo_module_begin_fail variable is defined. If it is,
  1026   1086       ** and it is set to the name of the real table underlying this virtual
  1027   1087       ** echo module table, then cause this xSync operation to fail.
................................................................................
  1041   1101     echo_vtab *pVtab = (echo_vtab *)tab;
  1042   1102     Tcl_Interp *interp = pVtab->interp;
  1043   1103     const char *zVal; 
  1044   1104   
  1045   1105     /* Ticket #3083 - Only call xSync if we have previously started a
  1046   1106     ** transaction */
  1047   1107     assert( pVtab->inTransaction );
         1108  +
         1109  +  if( simulateVtabError(pVtab, "xSync") ){
         1110  +    return SQLITE_ERROR;
         1111  +  }
  1048   1112   
  1049   1113     rc = echoTransactionCall(tab, "xSync");
  1050   1114   
  1051   1115     if( rc==SQLITE_OK ){
  1052   1116       /* Check if the $::echo_module_sync_fail variable is defined. If it is,
  1053   1117       ** and it is set to the name of the real table underlying this virtual
  1054   1118       ** echo module table, then cause this xSync operation to fail.
................................................................................
  1063   1127   static int echoCommit(sqlite3_vtab *tab){
  1064   1128     echo_vtab *pVtab = (echo_vtab*)tab;
  1065   1129     int rc;
  1066   1130   
  1067   1131     /* Ticket #3083 - Only call xCommit if we have previously started
  1068   1132     ** a transaction */
  1069   1133     assert( pVtab->inTransaction );
         1134  +
         1135  +  if( simulateVtabError(pVtab, "xCommit") ){
         1136  +    return SQLITE_ERROR;
         1137  +  }
  1070   1138   
  1071   1139     sqlite3BeginBenignMalloc();
  1072   1140     rc = echoTransactionCall(tab, "xCommit");
  1073   1141     sqlite3EndBenignMalloc();
  1074   1142     pVtab->inTransaction = 0;
  1075   1143     return rc;
  1076   1144   }

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.769 2008/07/30 13:27:11 drh Exp $
           46  +** $Id: vdbe.c,v 1.770 2008/08/01 17:37:41 danielk1977 Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include <ctype.h>
    50     50   #include "vdbeInt.h"
    51     51   
    52     52   /*
    53     53   ** The following global variable is incremented every time a cursor
................................................................................
  4566   4566     break;
  4567   4567   }
  4568   4568   #endif /* SQLITE_OMIT_SHARED_CACHE */
  4569   4569   
  4570   4570   #ifndef SQLITE_OMIT_VIRTUALTABLE
  4571   4571   /* Opcode: VBegin * * * P4 *
  4572   4572   **
  4573         -** P4 a pointer to an sqlite3_vtab structure. Call the xBegin method 
  4574         -** for that table.
         4573  +** P4 may be a pointer to an sqlite3_vtab structure. If so, call the 
         4574  +** xBegin method for that table.
         4575  +**
         4576  +** Also, whether or not P4 is set, check that this is not being called from
         4577  +** within a callback to a virtual table xSync() method. If it is, set the
         4578  +** error code to SQLITE_LOCKED.
  4575   4579   */
  4576   4580   case OP_VBegin: {
  4577         -  rc = sqlite3VtabBegin(db, pOp->p4.pVtab);
         4581  +  sqlite3_vtab *pVtab = pOp->p4.pVtab;
         4582  +  rc = sqlite3VtabBegin(db, pVtab);
         4583  +  if( pVtab ){
         4584  +    sqlite3DbFree(db, p->zErrMsg);
         4585  +    p->zErrMsg = pVtab->zErrMsg;
         4586  +    pVtab->zErrMsg = 0;
         4587  +  }
  4578   4588     break;
  4579   4589   }
  4580   4590   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  4581   4591   
  4582   4592   #ifndef SQLITE_OMIT_VIRTUALTABLE
  4583   4593   /* Opcode: VCreate P1 * * P4 *
  4584   4594   **
................................................................................
  4695   4705         storeTypeInfo(apArg[i], 0);
  4696   4706       }
  4697   4707   
  4698   4708       if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  4699   4709       p->inVtabMethod = 1;
  4700   4710       rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
  4701   4711       p->inVtabMethod = 0;
         4712  +    sqlite3DbFree(db, p->zErrMsg);
         4713  +    p->zErrMsg = pVtab->zErrMsg;
         4714  +    pVtab->zErrMsg = 0;
  4702   4715       if( rc==SQLITE_OK ){
  4703   4716         res = pModule->xEof(pVtabCursor);
  4704   4717       }
  4705   4718       if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  4706   4719   
  4707   4720       if( res ){
  4708   4721         pc = pOp->p2 - 1;
................................................................................
  4717   4730   #ifndef SQLITE_OMIT_VIRTUALTABLE
  4718   4731   /* Opcode: VRowid P1 P2 * * *
  4719   4732   **
  4720   4733   ** Store into register P2  the rowid of
  4721   4734   ** the virtual-table that the P1 cursor is pointing to.
  4722   4735   */
  4723   4736   case OP_VRowid: {             /* out2-prerelease */
         4737  +  sqlite3_vtab *pVtab;
  4724   4738     const sqlite3_module *pModule;
  4725   4739     sqlite_int64 iRow;
  4726   4740     Cursor *pCur = p->apCsr[pOp->p1];
  4727   4741   
  4728   4742     assert( pCur->pVtabCursor );
  4729   4743     if( pCur->nullRow ){
  4730   4744       break;
  4731   4745     }
  4732         -  pModule = pCur->pVtabCursor->pVtab->pModule;
         4746  +  pVtab = pCur->pVtabCursor->pVtab;
         4747  +  pModule = pVtab->pModule;
  4733   4748     assert( pModule->xRowid );
  4734   4749     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  4735   4750     rc = pModule->xRowid(pCur->pVtabCursor, &iRow);
         4751  +  sqlite3DbFree(db, p->zErrMsg);
         4752  +  p->zErrMsg = pVtab->zErrMsg;
         4753  +  pVtab->zErrMsg = 0;
  4736   4754     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  4737   4755     MemSetTypeFlag(pOut, MEM_Int);
  4738   4756     pOut->u.i = iRow;
  4739   4757     break;
  4740   4758   }
  4741   4759   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  4742   4760   
................................................................................
  4744   4762   /* Opcode: VColumn P1 P2 P3 * *
  4745   4763   **
  4746   4764   ** Store the value of the P2-th column of
  4747   4765   ** the row of the virtual-table that the 
  4748   4766   ** P1 cursor is pointing to into register P3.
  4749   4767   */
  4750   4768   case OP_VColumn: {
         4769  +  sqlite3_vtab *pVtab;
  4751   4770     const sqlite3_module *pModule;
  4752   4771     Mem *pDest;
  4753   4772     sqlite3_context sContext;
  4754   4773   
  4755   4774     Cursor *pCur = p->apCsr[pOp->p1];
  4756   4775     assert( pCur->pVtabCursor );
  4757   4776     assert( pOp->p3>0 && pOp->p3<=p->nMem );
  4758   4777     pDest = &p->aMem[pOp->p3];
  4759   4778     if( pCur->nullRow ){
  4760   4779       sqlite3VdbeMemSetNull(pDest);
  4761   4780       break;
  4762   4781     }
  4763         -  pModule = pCur->pVtabCursor->pVtab->pModule;
         4782  +  pVtab = pCur->pVtabCursor->pVtab;
         4783  +  pModule = pVtab->pModule;
  4764   4784     assert( pModule->xColumn );
  4765   4785     memset(&sContext, 0, sizeof(sContext));
  4766   4786   
  4767   4787     /* The output cell may already have a buffer allocated. Move
  4768   4788     ** the current contents to sContext.s so in case the user-function 
  4769   4789     ** can use the already allocated buffer instead of allocating a 
  4770   4790     ** new one.
  4771   4791     */
  4772   4792     sqlite3VdbeMemMove(&sContext.s, pDest);
  4773   4793     MemSetTypeFlag(&sContext.s, MEM_Null);
  4774   4794   
  4775   4795     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  4776   4796     rc = pModule->xColumn(pCur->pVtabCursor, &sContext, pOp->p2);
         4797  +  sqlite3DbFree(db, p->zErrMsg);
         4798  +  p->zErrMsg = pVtab->zErrMsg;
         4799  +  pVtab->zErrMsg = 0;
  4777   4800   
  4778   4801     /* Copy the result of the function to the P3 register. We
  4779   4802     ** do this regardless of whether or not an error occured to ensure any
  4780   4803     ** dynamic allocation in sContext.s (a Mem struct) is  released.
  4781   4804     */
  4782   4805     sqlite3VdbeChangeEncoding(&sContext.s, encoding);
  4783   4806     REGISTER_TRACE(pOp->p3, pDest);
................................................................................
  4798   4821   /* Opcode: VNext P1 P2 * * *
  4799   4822   **
  4800   4823   ** Advance virtual table P1 to the next row in its result set and
  4801   4824   ** jump to instruction P2.  Or, if the virtual table has reached
  4802   4825   ** the end of its result set, then fall through to the next instruction.
  4803   4826   */
  4804   4827   case OP_VNext: {   /* jump */
         4828  +  sqlite3_vtab *pVtab;
  4805   4829     const sqlite3_module *pModule;
  4806   4830     int res = 0;
  4807   4831   
  4808   4832     Cursor *pCur = p->apCsr[pOp->p1];
  4809   4833     assert( pCur->pVtabCursor );
  4810   4834     if( pCur->nullRow ){
  4811   4835       break;
  4812   4836     }
  4813         -  pModule = pCur->pVtabCursor->pVtab->pModule;
         4837  +  pVtab = pCur->pVtabCursor->pVtab;
         4838  +  pModule = pVtab->pModule;
  4814   4839     assert( pModule->xNext );
  4815   4840   
  4816   4841     /* Invoke the xNext() method of the module. There is no way for the
  4817   4842     ** underlying implementation to return an error if one occurs during
  4818   4843     ** xNext(). Instead, if an error occurs, true is returned (indicating that 
  4819   4844     ** data is available) and the error code returned when xColumn or
  4820   4845     ** some other method is next invoked on the save virtual table cursor.
  4821   4846     */
  4822   4847     if( sqlite3SafetyOff(db) ) goto abort_due_to_misuse;
  4823   4848     p->inVtabMethod = 1;
  4824   4849     rc = pModule->xNext(pCur->pVtabCursor);
  4825   4850     p->inVtabMethod = 0;
         4851  +  sqlite3DbFree(db, p->zErrMsg);
         4852  +  p->zErrMsg = pVtab->zErrMsg;
         4853  +  pVtab->zErrMsg = 0;
  4826   4854     if( rc==SQLITE_OK ){
  4827   4855       res = pModule->xEof(pCur->pVtabCursor);
  4828   4856     }
  4829   4857     if( sqlite3SafetyOn(db) ) goto abort_due_to_misuse;
  4830   4858   
  4831   4859     if( !res ){
  4832   4860       /* If there is data, jump to P2 */

Changes to src/vdbeaux.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used for creating, destroying, and populating
    13     13   ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
    14     14   ** to version 2.8.7, all this code was combined into the vdbe.c source file.
    15     15   ** But that file was getting too big so this subroutines were split out.
    16     16   **
    17         -** $Id: vdbeaux.c,v 1.402 2008/07/31 01:43:14 shane Exp $
           17  +** $Id: vdbeaux.c,v 1.403 2008/08/01 17:37:41 danielk1977 Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include <ctype.h>
    21     21   #include "vdbeInt.h"
    22     22   
    23     23   
    24     24   
................................................................................
  1212   1212   
  1213   1213   /*
  1214   1214   ** A read or write transaction may or may not be active on database handle
  1215   1215   ** db. If a transaction is active, commit it. If there is a
  1216   1216   ** write-transaction spanning more than one database file, this routine
  1217   1217   ** takes care of the master journal trickery.
  1218   1218   */
  1219         -static int vdbeCommit(sqlite3 *db){
         1219  +static int vdbeCommit(sqlite3 *db, Vdbe *p){
  1220   1220     int i;
  1221   1221     int nTrans = 0;  /* Number of databases with an active write-transaction */
  1222   1222     int rc = SQLITE_OK;
  1223   1223     int needXcommit = 0;
  1224   1224   
  1225   1225     /* Before doing anything else, call the xSync() callback for any
  1226   1226     ** virtual module tables written in this transaction. This has to
  1227   1227     ** be done before determining whether a master journal file is 
  1228   1228     ** required, as an xSync() callback may add an attached database
  1229   1229     ** to the transaction.
  1230   1230     */
  1231         -  rc = sqlite3VtabSync(db, rc);
         1231  +  rc = sqlite3VtabSync(db, &p->zErrMsg);
  1232   1232     if( rc!=SQLITE_OK ){
  1233   1233       return rc;
  1234   1234     }
  1235   1235   
  1236   1236     /* This loop determines (a) if the commit hook should be invoked and
  1237   1237     ** (b) how many database files have open write transactions, not 
  1238   1238     ** including the temp database. (b) is important because if more than 
................................................................................
  1588   1588       */
  1589   1589       if( db->autoCommit && db->activeVdbeCnt==1 ){
  1590   1590         if( p->rc==SQLITE_OK || (p->errorAction==OE_Fail && !isSpecialError) ){
  1591   1591           /* The auto-commit flag is true, and the vdbe program was 
  1592   1592           ** successful or hit an 'OR FAIL' constraint. This means a commit 
  1593   1593           ** is required.
  1594   1594           */
  1595         -        int rc = vdbeCommit(db);
         1595  +        int rc = vdbeCommit(db, p);
  1596   1596           if( rc==SQLITE_BUSY ){
  1597   1597             sqlite3BtreeMutexArrayLeave(&p->aMutex);
  1598   1598             return SQLITE_BUSY;
  1599   1599           }else if( rc!=SQLITE_OK ){
  1600   1600             p->rc = rc;
  1601   1601             sqlite3RollbackAll(db);
  1602   1602           }else{

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.72 2008/07/28 19:34:54 drh Exp $
           14  +** $Id: vtab.c,v 1.73 2008/08/01 17:37:41 danielk1977 Exp $
    15     15   */
    16     16   #ifndef SQLITE_OMIT_VIRTUALTABLE
    17     17   #include "sqliteInt.h"
    18     18   
    19     19   static int createModule(
    20     20     sqlite3 *db,                    /* Database in which module is registered */
    21     21     const char *zName,              /* Name assigned to this module */
................................................................................
   636    636       sqlite3DbFree(db, db->aVTrans);
   637    637       db->nVTrans = 0;
   638    638       db->aVTrans = 0;
   639    639     }
   640    640   }
   641    641   
   642    642   /*
   643         -** If argument rc2 is not SQLITE_OK, then return it and do nothing. 
   644         -** Otherwise, invoke the xSync method of all virtual tables in the 
   645         -** sqlite3.aVTrans array. Return the error code for the first error 
   646         -** that occurs, or SQLITE_OK if all xSync operations are successful.
          643  +** Invoke the xSync method of all virtual tables in the sqlite3.aVTrans
          644  +** array. Return the error code for the first error that occurs, or
          645  +** SQLITE_OK if all xSync operations are successful.
          646  +**
          647  +** Set *pzErrmsg to point to a buffer that should be released using 
          648  +** sqlite3DbFree() containing an error message, if one is available.
   647    649   */
   648         -int sqlite3VtabSync(sqlite3 *db, int rc2){
          650  +int sqlite3VtabSync(sqlite3 *db, char **pzErrmsg){
   649    651     int i;
   650    652     int rc = SQLITE_OK;
   651    653     int rcsafety;
   652    654     sqlite3_vtab **aVTrans = db->aVTrans;
   653         -  if( rc2!=SQLITE_OK ) return rc2;
   654    655   
   655    656     rc = sqlite3SafetyOff(db);
   656    657     db->aVTrans = 0;
   657    658     for(i=0; rc==SQLITE_OK && i<db->nVTrans && aVTrans[i]; i++){
   658    659       sqlite3_vtab *pVtab = aVTrans[i];
   659    660       int (*x)(sqlite3_vtab *);
   660    661       x = pVtab->pModule->xSync;
   661    662       if( x ){
   662    663         rc = x(pVtab);
          664  +      sqlite3DbFree(db, *pzErrmsg);
          665  +      *pzErrmsg = pVtab->zErrMsg;
          666  +      pVtab->zErrMsg = 0;
   663    667       }
   664    668     }
   665    669     db->aVTrans = aVTrans;
   666    670     rcsafety = sqlite3SafetyOn(db);
   667    671   
   668    672     if( rc==SQLITE_OK ){
   669    673       rc = rcsafety;
................................................................................
   723    727         if( db->aVTrans[i]==pVtab ){
   724    728           return SQLITE_OK;
   725    729         }
   726    730       }
   727    731   
   728    732       /* Invoke the xBegin method */
   729    733       rc = pModule->xBegin(pVtab);
   730         -    sqlite3VtabTransferError(db, rc, pVtab);
   731         -    if( rc!=SQLITE_OK ){
   732         -      return rc;
          734  +    if( rc==SQLITE_OK ){
          735  +      rc = addToVTrans(db, pVtab);
   733    736       }
   734         -
   735         -    rc = addToVTrans(db, pVtab);
   736    737     }
   737    738     return rc;
   738    739   }
   739    740   
   740    741   /*
   741    742   ** The first parameter (pDef) is a function implementation.  The
   742    743   ** second parameter (pExpr) is the first argument to this function.

Changes to src/where.c.

    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  This module is responsible for
    14     14   ** generating the code that loops through a table looking for applicable
    15     15   ** rows.  Indices are selected and used to speed the search when doing
    16     16   ** so is applicable.  Because this module is responsible for selecting
    17     17   ** indices, you might also think of this module as the "query optimizer".
    18     18   **
    19         -** $Id: where.c,v 1.318 2008/07/28 19:34:54 drh Exp $
           19  +** $Id: where.c,v 1.319 2008/08/01 17:37:41 danielk1977 Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   
    23     23   /*
    24     24   ** The number of bits in a Bitmask.  "BMS" means "BitMask Size".
    25     25   */
    26     26   #define BMS  (sizeof(Bitmask)*8)
................................................................................
  1255   1255     struct SrcList_item *pSrc,     /* The FROM clause term to search */
  1256   1256     Bitmask notReady,              /* Mask of cursors that are not available */
  1257   1257     ExprList *pOrderBy,            /* The order by clause */
  1258   1258     int orderByUsable,             /* True if we can potential sort */
  1259   1259     sqlite3_index_info **ppIdxInfo /* Index information passed to xBestIndex */
  1260   1260   ){
  1261   1261     Table *pTab = pSrc->pTab;
         1262  +  sqlite3_vtab *pVtab = pTab->pVtab;
  1262   1263     sqlite3_index_info *pIdxInfo;
  1263   1264     struct sqlite3_index_constraint *pIdxCons;
  1264   1265     struct sqlite3_index_orderby *pIdxOrderBy;
  1265   1266     struct sqlite3_index_constraint_usage *pUsage;
  1266   1267     WhereTerm *pTerm;
  1267   1268     int i, j;
  1268   1269     int nOrderBy;
................................................................................
  1366   1367     */
  1367   1368   
  1368   1369     /* The module name must be defined. Also, by this point there must
  1369   1370     ** be a pointer to an sqlite3_vtab structure. Otherwise
  1370   1371     ** sqlite3ViewGetColumnNames() would have picked up the error. 
  1371   1372     */
  1372   1373     assert( pTab->azModuleArg && pTab->azModuleArg[0] );
  1373         -  assert( pTab->pVtab );
         1374  +  assert( pVtab );
  1374   1375   #if 0
  1375   1376     if( pTab->pVtab==0 ){
  1376   1377       sqlite3ErrorMsg(pParse, "undefined module %s for table %s",
  1377   1378           pTab->azModuleArg[0], pTab->zName);
  1378   1379       return 0.0;
  1379   1380     }
  1380   1381   #endif
................................................................................
  1419   1420     if( pIdxInfo->nOrderBy && !orderByUsable ){
  1420   1421       *(int*)&pIdxInfo->nOrderBy = 0;
  1421   1422     }
  1422   1423   
  1423   1424     (void)sqlite3SafetyOff(pParse->db);
  1424   1425     WHERETRACE(("xBestIndex for %s\n", pTab->zName));
  1425   1426     TRACE_IDX_INPUTS(pIdxInfo);
  1426         -  rc = pTab->pVtab->pModule->xBestIndex(pTab->pVtab, pIdxInfo);
         1427  +  rc = pVtab->pModule->xBestIndex(pVtab, pIdxInfo);
  1427   1428     TRACE_IDX_OUTPUTS(pIdxInfo);
  1428   1429     (void)sqlite3SafetyOn(pParse->db);
         1430  +
         1431  +  if( rc!=SQLITE_OK ){
         1432  +    if( rc==SQLITE_NOMEM ){
         1433  +      pParse->db->mallocFailed = 1;
         1434  +    }else if( !pVtab->zErrMsg ){
         1435  +      sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
         1436  +    }else{
         1437  +      sqlite3ErrorMsg(pParse, "%s", pVtab->zErrMsg);
         1438  +    }
         1439  +  }
         1440  +  sqlite3DbFree(pParse->db, pVtab->zErrMsg);
         1441  +  pVtab->zErrMsg = 0;
  1429   1442   
  1430   1443     for(i=0; i<pIdxInfo->nConstraint; i++){
  1431   1444       if( !pIdxInfo->aConstraint[i].usable && pUsage[i].argvIndex>0 ){
  1432   1445         sqlite3ErrorMsg(pParse, 
  1433   1446             "table %s: xBestIndex returned an invalid plan", pTab->zName);
  1434   1447         return 0.0;
  1435   1448       }
  1436   1449     }
  1437   1450   
  1438         -  if( rc!=SQLITE_OK ){
  1439         -    if( rc==SQLITE_NOMEM ){
  1440         -      pParse->db->mallocFailed = 1;
  1441         -    }else {
  1442         -      sqlite3ErrorMsg(pParse, "%s", sqlite3ErrStr(rc));
  1443         -    }
  1444         -  }
  1445   1451     *(int*)&pIdxInfo->nOrderBy = nOrderBy;
  1446         -
  1447   1452     return pIdxInfo->estimatedCost;
  1448   1453   }
  1449   1454   #endif /* SQLITE_OMIT_VIRTUALTABLE */
  1450   1455   
  1451   1456   /*
  1452   1457   ** Find the best index for accessing a particular table.  Return a pointer
  1453   1458   ** to the index, flags that describe how the index should be used, the

Changes to test/vtab1.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is creating and dropping virtual tables.
    13     13   #
    14         -# $Id: vtab1.test,v 1.55 2008/07/23 21:07:25 drh Exp $
           14  +# $Id: vtab1.test,v 1.56 2008/08/01 17:37:41 danielk1977 Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   ifcapable !vtab||!schema_pragmas {
    20     20     finish_test
    21     21     return
................................................................................
    48     48   #----------------------------------------------------------------------
    49     49   # Test cases vtab1.1.*
    50     50   #
    51     51   
    52     52   # We cannot create a virtual table if the module has not been registered.
    53     53   #
    54     54   do_test vtab1-1.1 {
           55  +  explain {
           56  +    CREATE VIRTUAL TABLE t1 USING echo;
           57  +  }
    55     58     catchsql {
    56     59       CREATE VIRTUAL TABLE t1 USING echo;
    57     60     }
    58     61   } {1 {no such module: echo}}
    59     62   do_test vtab1-1.2 {
    60     63     execsql {
    61     64       SELECT name FROM sqlite_master ORDER BY 1
................................................................................
  1104   1107   } {45 {} {} {} 46 {} {} {}}
  1105   1108   do_test vtab1-15.4 {
  1106   1109     catchsql {
  1107   1110       INSERT INTO echo_t1(rowid) VALUES('new rowid');
  1108   1111     }
  1109   1112   } {1 {datatype mismatch}}
  1110   1113   
         1114  +# The following tests - vtab1-16.* - are designed to test that setting 
         1115  +# sqlite3_vtab.zErrMsg variable can be used by the vtab interface to 
         1116  +# return an error message to the user.
         1117  +# 
         1118  +do_test vtab1-16.1 {
         1119  +  execsql {
         1120  +    CREATE TABLE t2(a PRIMARY KEY, b, c);
         1121  +    INSERT INTO t2 VALUES(1, 2, 3);
         1122  +    INSERT INTO t2 VALUES(4, 5, 6);
         1123  +    CREATE VIRTUAL TABLE echo_t2 USING echo(t2);
         1124  +  }
         1125  +} {}
         1126  +
         1127  +set tn 2
         1128  +foreach method [list \
         1129  +    xBestIndex       \
         1130  +    xOpen            \
         1131  +    xFilter          \
         1132  +    xNext            \
         1133  +    xColumn          \
         1134  +    xRowid           \
         1135  +] {
         1136  +  do_test vtab1-16.$tn {
         1137  +    set echo_module_fail($method,t2) "the $method method has failed"
         1138  +    catchsql { SELECT rowid, * FROM echo_t2 WHERE a >= 1 }
         1139  +  } "1 {echo-vtab-error: the $method method has failed}"
         1140  +  unset echo_module_fail($method,t2)
         1141  +  incr tn
         1142  +}
         1143  +
         1144  +foreach method [list \
         1145  +  xUpdate            \
         1146  +  xBegin             \
         1147  +  xSync              \
         1148  +] {
         1149  +  do_test vtab1-16.$tn {
         1150  +    set echo_module_fail($method,t2) "the $method method has failed"
         1151  +    catchsql { INSERT INTO echo_t2 VALUES(7, 8, 9) }
         1152  +  } "1 {echo-vtab-error: the $method method has failed}"
         1153  +  unset echo_module_fail($method,t2)
         1154  +  incr tn
         1155  +}
  1111   1156   
  1112   1157   unset -nocomplain echo_module_begin_fail
  1113   1158   finish_test