/ Check-in [e431131d]
Login

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

Overview
Comment:More work toward getting sqlite3_interrupt() to work from separate threads. Ticket #1897. (CVS 3336)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:e431131d47481f9fc64c498e8934b10a96b0a931
User & Date: drh 2006-07-26 13:43:31
Context
2006-07-26
14:49
Add a test case to trigger an assertion fault when running sqlite3_prepare16() with a predefined string size. (CVS 3337) check-in: 93878e6e user: drh tags: trunk
13:43
More work toward getting sqlite3_interrupt() to work from separate threads. Ticket #1897. (CVS 3336) check-in: e431131d user: drh tags: trunk
01:39
Initial attempt at making sqlite3_interrupt() work even when called from a separate thread. (CVS 3335) check-in: 35fd67d7 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/prepare.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains the implementation of the sqlite3_prepare()
    13     13   ** interface, and routines that contribute to loading the database schema
    14     14   ** from disk.
    15     15   **
    16         -** $Id: prepare.c,v 1.36 2006/06/26 12:50:09 drh Exp $
           16  +** $Id: prepare.c,v 1.37 2006/07/26 13:43:31 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "os.h"
    20     20   #include <ctype.h>
    21     21   
    22     22   /*
    23     23   ** Fill the InitData structure with an error message that indicates
................................................................................
    24     24   ** that the database is corrupt.
    25     25   */
    26     26   static void corruptSchema(InitData *pData, const char *zExtra){
    27     27     if( !sqlite3MallocFailed() ){
    28     28       sqlite3SetString(pData->pzErrMsg, "malformed database schema",
    29     29          zExtra!=0 && zExtra[0]!=0 ? " - " : (char*)0, zExtra, (char*)0);
    30     30     }
           31  +  pData->rc = SQLITE_CORRUPT;
    31     32   }
    32     33   
    33     34   /*
    34     35   ** This is the callback routine for the code that initializes the
    35     36   ** database.  See sqlite3Init() below for additional information.
    36     37   ** This routine is also called from the OP_ParseSchema opcode of the VDBE.
    37     38   **
................................................................................
    45     46   **
    46     47   */
    47     48   int sqlite3InitCallback(void *pInit, int argc, char **argv, char **azColName){
    48     49     InitData *pData = (InitData*)pInit;
    49     50     sqlite3 *db = pData->db;
    50     51     int iDb;
    51     52   
           53  +  pData->rc = SQLITE_OK;
    52     54     if( sqlite3MallocFailed() ){
    53     55       return SQLITE_NOMEM;
    54     56     }
    55     57   
    56     58     assert( argc==4 );
    57     59     if( argv==0 ) return 0;   /* Might happen if EMPTY_RESULT_CALLBACKS are on */
    58     60     if( argv[1]==0 || argv[3]==0 ){
................................................................................
    72     74       assert( db->init.busy );
    73     75       db->init.iDb = iDb;
    74     76       db->init.newTnum = atoi(argv[1]);
    75     77       rc = sqlite3_exec(db, argv[2], 0, 0, &zErr);
    76     78       db->init.iDb = 0;
    77     79       assert( rc!=SQLITE_OK || zErr==0 );
    78     80       if( SQLITE_OK!=rc ){
           81  +      pData->rc = rc;
    79     82         if( rc==SQLITE_NOMEM ){
    80     83           sqlite3FailedMalloc();
    81         -      }else{
           84  +      }else if( rc!=SQLITE_INTERRUPT ){
    82     85           corruptSchema(pData, zErr);
    83     86         }
    84     87         sqlite3_free(zErr);
    85         -      return rc;
           88  +      return 1;
    86     89       }
    87     90     }else{
    88     91       /* If the SQL column is blank it means this is an index that
    89     92       ** was created to be the PRIMARY KEY or to fulfill a UNIQUE
    90     93       ** constraint for a CREATE TABLE.  The index should have already
    91     94       ** been created when we processed the CREATE TABLE.  All we have
    92     95       ** to do here is record the root page number for that index.
................................................................................
   175    178     azArg[2] = zMasterSchema;
   176    179     sprintf(zDbNum, "%d", iDb);
   177    180     azArg[3] = zDbNum;
   178    181     azArg[4] = 0;
   179    182     initData.db = db;
   180    183     initData.pzErrMsg = pzErrMsg;
   181    184     rc = sqlite3InitCallback(&initData, 4, (char **)azArg, 0);
   182         -  if( rc!=SQLITE_OK ){
          185  +  if( rc ){
   183    186       sqlite3SafetyOn(db);
   184         -    return rc;
          187  +    return initData.rc;
   185    188     }
   186    189     pTab = sqlite3FindTable(db, zMasterName, db->aDb[iDb].zName);
   187    190     if( pTab ){
   188    191       pTab->readOnly = 1;
   189    192     }
   190    193     sqlite3SafetyOn(db);
   191    194   
................................................................................
   291    294     }else{
   292    295       char *zSql;
   293    296       zSql = sqlite3MPrintf(
   294    297           "SELECT name, rootpage, sql, '%s' FROM '%q'.%s",
   295    298           zDbNum, db->aDb[iDb].zName, zMasterName);
   296    299       sqlite3SafetyOff(db);
   297    300       rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
          301  +    if( rc==SQLITE_ABORT ) rc = initData.rc;
   298    302       sqlite3SafetyOn(db);
   299    303       sqliteFree(zSql);
   300    304   #ifndef SQLITE_OMIT_ANALYZE
   301    305       if( rc==SQLITE_OK ){
   302    306         sqlite3AnalysisLoad(db, iDb);
   303    307       }
   304    308   #endif

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.522 2006/07/26 01:39:30 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.523 2006/07/26 13:43:31 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Extra interface definitions for those who need them
    21     21   */
................................................................................
  1509   1509   /*
  1510   1510   ** A pointer to this structure is used to communicate information
  1511   1511   ** from sqlite3Init and OP_ParseSchema into the sqlite3InitCallback.
  1512   1512   */
  1513   1513   typedef struct {
  1514   1514     sqlite3 *db;        /* The database being initialized */
  1515   1515     char **pzErrMsg;    /* Error message stored here */
         1516  +  int rc;             /* Result code stored here */
  1516   1517   } InitData;
  1517   1518   
  1518   1519   /*
  1519   1520    * This global flag is set for performance testing of triggers. When it is set
  1520   1521    * SQLite will perform the overhead of building new and old trigger references 
  1521   1522    * even when no triggers exist
  1522   1523    */

Changes to src/tokenize.c.

    11     11   *************************************************************************
    12     12   ** An tokenizer for SQL
    13     13   **
    14     14   ** This file contains C code that splits an SQL input string up into
    15     15   ** individual tokens and sends those tokens one-by-one over to the
    16     16   ** parser for analysis.
    17     17   **
    18         -** $Id: tokenize.c,v 1.122 2006/07/26 01:39:30 drh Exp $
           18  +** $Id: tokenize.c,v 1.123 2006/07/26 13:43:31 drh Exp $
    19     19   */
    20     20   #include "sqliteInt.h"
    21     21   #include "os.h"
    22     22   #include <ctype.h>
    23     23   #include <stdlib.h>
    24     24   
    25     25   /*
................................................................................
   390    390     int tokenType;
   391    391     int lastTokenParsed = -1;
   392    392     sqlite3 *db = pParse->db;
   393    393     extern void *sqlite3ParserAlloc(void*(*)(int));
   394    394     extern void sqlite3ParserFree(void*, void(*)(void*));
   395    395     extern int sqlite3Parser(void*, int, Token, Parse*);
   396    396   
   397         -  db->u1.isInterrupted = 0;
          397  +  if( db->activeVdbeCnt==0 ){
          398  +    db->u1.isInterrupted = 0;
          399  +  }
   398    400     pParse->rc = SQLITE_OK;
   399    401     i = 0;
   400    402     pEngine = sqlite3ParserAlloc((void*(*)(int))sqlite3MallocX);
   401    403     if( pEngine==0 ){
   402    404       return SQLITE_NOMEM;
   403    405     }
   404    406     assert( pParse->sLastToken.dyn==0 );

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.571 2006/07/26 01:39:30 drh Exp $
           46  +** $Id: vdbe.c,v 1.572 2006/07/26 13:43:31 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
  4044   4044        pOp->p1, db->aDb[iDb].zName, zMaster, pOp->p3);
  4045   4045     if( zSql==0 ) goto no_mem;
  4046   4046     sqlite3SafetyOff(db);
  4047   4047     assert( db->init.busy==0 );
  4048   4048     db->init.busy = 1;
  4049   4049     assert( !sqlite3MallocFailed() );
  4050   4050     rc = sqlite3_exec(db, zSql, sqlite3InitCallback, &initData, 0);
         4051  +  if( rc==SQLITE_ABORT ) rc = initData.rc;
  4051   4052     sqliteFree(zSql);
  4052   4053     db->init.busy = 0;
  4053   4054     sqlite3SafetyOn(db);
  4054   4055     if( rc==SQLITE_NOMEM ){
  4055   4056       sqlite3FailedMalloc();
  4056   4057       goto no_mem;
  4057   4058     }
................................................................................
  4967   4968     goto vdbe_halt;
  4968   4969   
  4969   4970     /* Jump to here if the sqlite3_interrupt() API sets the interrupt
  4970   4971     ** flag.
  4971   4972     */
  4972   4973   abort_due_to_interrupt:
  4973   4974     assert( db->u1.isInterrupted );
  4974         -  db->u1.isInterrupted = 0;
  4975   4975     if( db->magic!=SQLITE_MAGIC_BUSY ){
  4976   4976       rc = SQLITE_MISUSE;
  4977   4977     }else{
  4978   4978       rc = SQLITE_INTERRUPT;
  4979   4979     }
  4980   4980     p->rc = rc;
  4981   4981     sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(rc), (char*)0);
  4982   4982     goto vdbe_halt;
  4983   4983   }

Changes to src/vdbeapi.c.

   176    176     }
   177    177     db = p->db;
   178    178     if( sqlite3SafetyOn(db) ){
   179    179       p->rc = SQLITE_MISUSE;
   180    180       return SQLITE_MISUSE;
   181    181     }
   182    182     if( p->pc<0 ){
          183  +    /* If there are no other statements currently running, then
          184  +    ** reset the interrupt flag.  This prevents a call to sqlite3_interrupt
          185  +    ** from interrupting a statement that has not yet started.
          186  +    */
          187  +    if( db->activeVdbeCnt==0 ){
          188  +      db->u1.isInterrupted = 0;
          189  +    }
          190  +
   183    191   #ifndef SQLITE_OMIT_TRACE
   184    192       /* Invoke the trace callback if there is one
   185    193       */
   186    194       if( db->xTrace && !db->init.busy ){
   187    195         assert( p->nOp>0 );
   188    196         assert( p->aOp[p->nOp-1].opcode==OP_Noop );
   189    197         assert( p->aOp[p->nOp-1].p3!=0 );

Changes to src/vdbeaux.c.

   667    667     do{
   668    668       i = p->pc++;
   669    669     }while( i<p->nOp && p->explain==2 && p->aOp[i].opcode!=OP_Explain );
   670    670     if( i>=p->nOp ){
   671    671       p->rc = SQLITE_OK;
   672    672       rc = SQLITE_DONE;
   673    673     }else if( db->u1.isInterrupted ){
   674         -    db->u1.isInterrupted = 0;
   675    674       p->rc = SQLITE_INTERRUPT;
   676    675       rc = SQLITE_ERROR;
   677    676       sqlite3SetString(&p->zErrMsg, sqlite3ErrStr(p->rc), (char*)0);
   678    677     }else{
   679    678       Op *pOp = &p->aOp[i];
   680    679       Mem *pMem = p->aStack;
   681    680       pMem->flags = MEM_Int;