The callback-free API is now working, though much more testing is need. (CVS 853)

FossilOrigin-Name: 162b259188e6967fe9c3722da26b81aab5655d83
diff --git a/src/main.c b/src/main.c
index 2be750b..7b5c76e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -14,7 +14,7 @@
 ** other files are for internal use by SQLite and should not be
 ** accessed by users of the library.
 **
-** $Id: main.c,v 1.110 2003/01/28 23:13:12 drh Exp $
+** $Id: main.c,v 1.111 2003/01/29 14:06:08 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -622,8 +622,7 @@
     sqliteSetString(pzErrMsg, "obsolete database file format", 0);
     return SQLITE_ERROR;
   }
-  if( db->recursionDepth==0 ){ db->nChange = 0; }
-  db->recursionDepth++;
+  if( db->pVdbe==0 ){ db->nChange = 0; }
   memset(&sParse, 0, sizeof(sParse));
   sParse.db = db;
   sParse.pBe = db->pBe;
@@ -642,6 +641,7 @@
     db->flags &= ~SQLITE_InTrans;
     sqliteResetInternalSchema(db);
   }
+  if( sParse.rc==SQLITE_DONE ) sParse.rc = SQLITE_OK;
   if( sParse.rc!=SQLITE_OK && pzErrMsg && *pzErrMsg==0 ){
     sqliteSetString(pzErrMsg, sqlite_error_string(sParse.rc), 0);
   }
@@ -649,11 +649,10 @@
   if( sParse.rc==SQLITE_SCHEMA ){
     sqliteResetInternalSchema(db);
   }
-  db->recursionDepth--;
   if( sParse.useCallback==0 ){
     assert( ppVm );
-    *ppVm = sParse.pVdbe;
-    *pzTail = &sParse.sLastToken.z[sParse.sLastToken.n];
+    *ppVm = (sqlite_vm*)sParse.pVdbe;
+    *pzTail = sParse.zTail;
   }
   if( sqliteSafetyOff(db) ) goto exec_misuse;
   return sParse.rc;
diff --git a/src/select.c b/src/select.c
index 29b1f9e..4998a53 100644
--- a/src/select.c
+++ b/src/select.c
@@ -12,7 +12,7 @@
 ** This file contains C code routines that are called by the parser
 ** to handle SELECT statements in SQLite.
 **
-** $Id: select.c,v 1.123 2003/01/19 03:59:47 drh Exp $
+** $Id: select.c,v 1.124 2003/01/29 14:06:09 drh Exp $
 */
 #include "sqliteInt.h"
 
@@ -697,7 +697,9 @@
 ){
   Vdbe *v = pParse->pVdbe;
   int i;
-  if( (pParse->db->flags & SQLITE_ReportTypes)==0 ) return;
+  if( pParse->useCallback && (pParse->db->flags & SQLITE_ReportTypes)==0 ){
+    return;
+  }
   for(i=0; i<pEList->nExpr; i++){
     Expr *p = pEList->a[i].pExpr;
     char *zType = 0;
@@ -1456,7 +1458,9 @@
 
   /* Issue a null callback if that is what the user wants.
   */
-  if( (pParse->db->flags & SQLITE_NullCallback)!=0 && eDest==SRT_Callback ){
+  if( eDest==SRT_Callback &&
+    (pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0)
+  ){
     sqliteVdbeAddOp(v, OP_NullCallback, p->pEList->nExpr, 0);
   }
   return 0;
@@ -2306,7 +2310,9 @@
 
   /* Issue a null callback if that is what the user wants.
   */
-  if( (pParse->db->flags & SQLITE_NullCallback)!=0 && eDest==SRT_Callback ){
+  if( eDest==SRT_Callback &&
+    (pParse->useCallback==0 || (pParse->db->flags & SQLITE_NullCallback)!=0)
+  ){
     sqliteVdbeAddOp(v, OP_NullCallback, pEList->nExpr, 0);
   }
 
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 1b1c528..1590453 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the SQLite library
 ** presents to client programs.
 **
-** @(#) $Id: sqlite.h.in,v 1.40 2003/01/28 23:13:12 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.41 2003/01/29 14:06:09 drh Exp $
 */
 #ifndef _SQLITE_H_
 #define _SQLITE_H_
@@ -588,6 +588,8 @@
 **
 ** *ppVm is left pointing to a "virtual machine" that can be used to execute
 ** the compiled statement.  Or if there is an error, *ppVm may be set to NULL.
+** If the input text contained no SQL (if the input is and empty string or
+** a comment) then *ppVm is set to NULL.
 **
 ** If any errors are detected during compilation, an error message is written
 ** into space obtained from malloc() and *pzErrMsg is made to point to that
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 734eadd..19cf999 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
 *************************************************************************
 ** Internal interface definitions for SQLite.
 **
-** @(#) $Id: sqliteInt.h,v 1.157 2003/01/28 23:13:12 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.158 2003/01/29 14:06:09 drh Exp $
 */
 #include "config.h"
 #include "sqlite.h"
@@ -224,7 +224,7 @@
   int onError;                  /* Default conflict algorithm */
   int magic;                    /* Magic number for detect library misuse */
   int nChange;                  /* Number of rows changed */
-  int recursionDepth;           /* Number of nested calls to sqlite_exec() */
+  struct Vdbe *pVdbe;           /* List of active virtual machines */
 #ifndef SQLITE_OMIT_TRACE
   void (*xTrace)(void*,const char*);     /* Trace function */
   void *pTraceArg;                       /* Argument to the trace function */
@@ -737,6 +737,7 @@
   Token sErrToken;     /* The token at which the error occurred */
   Token sFirstToken;   /* The first token parsed */
   Token sLastToken;    /* The last token parsed */
+  const char *zTail;   /* All SQL text past the last semicolon parsed */
   Table *pNewTable;    /* A table being constructed by CREATE TABLE */
   Vdbe *pVdbe;         /* An engine for executing database bytecode */
   u8 colNamesSet;      /* TRUE after OP_ColumnName has been issued to pVdbe */
diff --git a/src/test1.c b/src/test1.c
index 434662a..09d6c19 100644
--- a/src/test1.c
+++ b/src/test1.c
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test1.c,v 1.17 2003/01/28 23:13:12 drh Exp $
+** $Id: test1.c,v 1.18 2003/01/29 14:06:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -733,8 +733,10 @@
     sqlite_freemem(zErr);
     return TCL_ERROR;
   }
-  sprintf(zBuf, "%p", vm);
-  Tcl_AppendResult(interp, zBuf, 0);
+  if( vm ){
+    sprintf(zBuf, "%p", vm);
+    Tcl_AppendResult(interp, zBuf, 0);
+  }
   Tcl_SetVar(interp, argv[3], zTail, 0);
   return TCL_OK;
 }
@@ -765,7 +767,7 @@
   }
   if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
   rc = sqlite_step(vm, &N, &azValue, &azColName);
-  if( rc==SQLITE_DONE || SQLITE_ROW ){
+  if( rc==SQLITE_DONE || rc==SQLITE_ROW ){
     sprintf(zBuf, "%d", N);
     Tcl_SetVar(interp, argv[2], zBuf, 0);
     Tcl_SetVar(interp, argv[3], "", 0);
@@ -777,15 +779,15 @@
     }
     Tcl_SetVar(interp, argv[4], "", 0);
     for(i=0; i<N*2; i++){
-      Tcl_SetVar(interp, argv[4], azValue[i] ? azValue[i] : "",
+      Tcl_SetVar(interp, argv[4], azColName[i] ? azColName[i] : "",
           TCL_APPEND_VALUE | TCL_LIST_ELEMENT);
     }
   }
   switch( rc ){
     case SQLITE_DONE:   zRc = "SQLITE_DONE";    break;
-    case SQLITE_BUSY:   zRc = "SQLITE_DONE";    break;
-    case SQLITE_ROW:    zRc = "SQLITE_DONE";    break;
-    case SQLITE_ERROR:  zRc = "SQLITE_DONE";    break;
+    case SQLITE_BUSY:   zRc = "SQLITE_BUSY";    break;
+    case SQLITE_ROW:    zRc = "SQLITE_ROW";     break;
+    case SQLITE_ERROR:  zRc = "SQLITE_ERROR";   break;
     case SQLITE_MISUSE: zRc = "SQLITE_MISUSE";  break;
     default:            zRc = "unknown";        break;
   }
@@ -809,7 +811,7 @@
   char *zErrMsg = 0;
   if( argc!=2 ){
     Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
-       " VM NVAR VALUEVAR COLNAMEVAR", 0);
+       " VM\"", 0);
     return TCL_ERROR;
   }
   if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
diff --git a/src/tokenize.c b/src/tokenize.c
index df27fa7..7dd49b2 100644
--- a/src/tokenize.c
+++ b/src/tokenize.c
@@ -15,7 +15,7 @@
 ** individual tokens and sends those tokens one-by-one over to the
 ** parser for analysis.
 **
-** $Id: tokenize.c,v 1.54 2003/01/28 23:13:12 drh Exp $
+** $Id: tokenize.c,v 1.55 2003/01/29 14:06:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -422,6 +422,7 @@
     return 1;
   }
   pParse->sLastToken.dyn = 0;
+  pParse->zTail = zSql;
   while( sqlite_malloc_failed==0 && zSql[i]!=0 ){
     
     assert( i>=0 );
@@ -445,6 +446,10 @@
         nErr++;
         goto abort_parse;
       }
+      case TK_SEMI: {
+        pParse->zTail = &zSql[i];
+        /* Fall thru into the default case */
+      }
       default: {
         sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse);
         lastTokenParsed = tokenType;
@@ -459,6 +464,7 @@
   if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
     if( lastTokenParsed!=TK_SEMI ){
       sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
+      pParse->zTail = &zSql[i];
     }
     sqliteParser(pEngine, 0, pParse->sLastToken, pParse);
   }
diff --git a/src/util.c b/src/util.c
index f71950c..26e7afc 100644
--- a/src/util.c
+++ b/src/util.c
@@ -14,7 +14,7 @@
 ** This file contains functions for allocating memory, comparing
 ** strings, and stuff like that.
 **
-** $Id: util.c,v 1.56 2003/01/14 00:44:09 drh Exp $
+** $Id: util.c,v 1.57 2003/01/29 14:06:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include <stdarg.h>
@@ -1196,7 +1196,7 @@
 ** at the wrong time or in the wrong sequence.
 */
 int sqliteSafetyCheck(sqlite *db){
-  if( db->recursionDepth ){
+  if( db->pVdbe!=0 ){
     db->magic = SQLITE_MAGIC_ERROR;
     return 1;
   }
diff --git a/src/vdbe.c b/src/vdbe.c
index 0839b30..c0ec8ac 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -36,7 +36,7 @@
 ** in this file for details.  If in doubt, do not deviate from existing
 ** commenting and indentation practices when changing or adding code.
 **
-** $Id: vdbe.c,v 1.200 2003/01/28 23:13:12 drh Exp $
+** $Id: vdbe.c,v 1.201 2003/01/29 14:06:09 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -242,6 +242,7 @@
 */
 struct Vdbe {
   sqlite *db;         /* The whole database */
+  Vdbe *pPrev,*pNext; /* Linked list of VDBEs with the same Vdbe.db */
   Btree *pBt;         /* Opaque context structure used by DB backend */
   FILE *trace;        /* Write an execution trace here, if not NULL */
   int nOp;            /* Number of instructions in the program */
@@ -316,6 +317,12 @@
   if( p==0 ) return 0;
   p->pBt = db->pBe;
   p->db = db;
+  if( db->pVdbe ){
+    db->pVdbe->pPrev = p;
+  }
+  p->pNext = db->pVdbe;
+  p->pPrev = 0;
+  db->pVdbe = p;
   p->magic = VDBE_MAGIC_INIT;
   return p;
 }
@@ -763,17 +770,22 @@
   const char ***pazColName     /* OUT: Column names and datatypes */
 ){
   Vdbe *p = (Vdbe*)pVm;
+  sqlite *db;
   int rc;
 
   if( p->magic!=VDBE_MAGIC_RUN ){
     return SQLITE_MISUSE;
   }
+  db = p->db;
+  if( sqliteSafetyOn(db) ){
+    return SQLITE_MISUSE;
+  }
   if( p->explain ){
     rc = sqliteVdbeList(p);
   }else{
     rc = sqliteVdbeExec(p);
   }
-  if( rc!=SQLITE_DONE ){
+  if( rc==SQLITE_DONE || rc==SQLITE_ROW ){
     *pazColName = (const char**)p->azColName;
     *pN = p->nResColumn;
   }else{
@@ -785,6 +797,9 @@
   }else{
     *pazValue = 0;
   }
+  if( sqliteSafetyOff(db) ){
+    return SQLITE_MISUSE;
+  }
   return rc;
 }
 
@@ -1191,6 +1206,16 @@
   int i;
   if( p==0 ) return;
   Cleanup(p);
+  if( p->pPrev ){
+    p->pPrev->pNext = p->pNext;
+  }else{
+    assert( p->db->pVdbe==p );
+    p->db->pVdbe = p->pNext;
+  }
+  if( p->pNext ){
+    p->pNext->pPrev = p->pPrev;
+  }
+  p->pPrev = p->pNext = 0;
   if( p->nOpAlloc==0 ){
     p->aOp = 0;
     p->nOp = 0;
@@ -1255,7 +1280,7 @@
       p->pc = i+1;
       p->azResColumn = p->zStack;
       p->nResColumn = 5;
-      return SQLITE_CALLBACK;
+      return SQLITE_ROW;
     }
     if( sqliteSafetyOff(db) ){
       p->rc = SQLITE_MISUSE;
@@ -1453,7 +1478,7 @@
 **
 ** The behavior of sqliteVdbeExec() is influenced by the parameters to
 ** this routine.  If xCallback is NULL, then sqliteVdbeExec() will return
-** with SQLITE_CALLBACK whenever there is a row of the result set ready
+** with SQLITE_ROW whenever there is a row of the result set ready
 ** to be delivered.  p->azResColumn will point to the row and 
 ** p->nResColumn gives the number of columns in the row.  If xCallback
 ** is not NULL, then the xCallback() routine is invoked to process each
@@ -1523,7 +1548,7 @@
 **
 ** Whenever a row or result data is available, this routine will either
 ** invoke the result callback (if there is one) or return with
-** SQLITE_CALLBACK.
+** SQLITE_ROW.
 **
 ** If an attempt is made to open a locked database, then this routine
 ** will either invoke the busy callback (if there is one) or it will
@@ -1887,7 +1912,7 @@
     p->nResColumn = pOp->p1;
     p->popStack = pOp->p1;
     p->pc = pc + 1;
-    return SQLITE_CALLBACK;
+    return SQLITE_ROW;
   }
   if( sqliteSafetyOff(db) ) goto abort_due_to_misuse; 
   if( p->xCallback(p->pCbArg, pOp->p1, &zStack[i], p->azColName)!=0 ){
@@ -1926,6 +1951,7 @@
     p->nCallback++;
     if( sqlite_malloc_failed ) goto no_mem;
   }
+  p->nResColumn = pOp->p1;
   break;
 }
 
@@ -4843,7 +4869,7 @@
     p->azResColumn = (char**)zStack[i];
     p->nResColumn = pOp->p1;
     p->popStack = 1;
-    return SQLITE_CALLBACK;
+    return SQLITE_ROW;
   }else{
     if( sqliteSafetyOff(db) ) goto abort_due_to_misuse;
     if( p->xCallback(p->pCbArg, pOp->p1, (char**)zStack[i], p->azColName)!=0 ){
diff --git a/src/vdbe.h b/src/vdbe.h
index 535b1e7..6a8e191 100644
--- a/src/vdbe.h
+++ b/src/vdbe.h
@@ -15,7 +15,7 @@
 ** or VDBE.  The VDBE implements an abstract machine that runs a
 ** simple program to access and modify the underlying database.
 **
-** $Id: vdbe.h,v 1.62 2003/01/28 23:13:13 drh Exp $
+** $Id: vdbe.h,v 1.63 2003/01/29 14:06:10 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -63,13 +63,6 @@
 #define ADDR(X)  (-1-(X))
 
 /*
-** The sqliteVdbeExec() routine can return any of the normal SQLite return
-** codes defined in sqlite.h.  But it can also return the following
-** additional values:
-*/
-#define SQLITE_CALLBACK    100    /* sqliteVdbeExec() hit an OP_Callback */
-
-/*
 ** The makefile scans the vdbe.c source file and creates the "opcodes.h"
 ** header file that defines a number for each opcode used by the VDBE.
 */