]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
The beginnings of changes to support pre-compiled SQL. Mostly untested,
authordrh <drh@noemail.net>
Sat, 6 Sep 2003 01:10:47 +0000 (01:10 +0000)
committerdrh <drh@noemail.net>
Sat, 6 Sep 2003 01:10:47 +0000 (01:10 +0000)
though all regression tests to pass. (CVS 1093)

FossilOrigin-Name: 912f47c72d3597c6d5acff765d94922bd660339a

12 files changed:
manifest
manifest.uuid
src/expr.c
src/func.c
src/main.c
src/pager.c
src/parse.y
src/sqlite.h.in
src/test1.c
src/tokenize.c
src/vdbe.c
src/vdbe.h

index 55c6497347f10ba22d9cde36e9bc4279c4bb5115..b041b4fb831d37a3e5f799426e1b53cfe8c24f9c 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Add\sa\slogo\sfrom\sRasmus\sSchultz.\s(CVS\s1092)
-D 2003-09-02T15:26:33
+C The\sbeginnings\sof\schanges\sto\ssupport\spre-compiled\sSQL.\s\sMostly\suntested,\nthough\sall\sregression\stests\sto\spass.\s(CVS\s1093)
+D 2003-09-06T01:10:47
 F Makefile.in f7e916ae863393827fa6a4cb292e3398096edcf1
 F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
 F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
@@ -30,39 +30,39 @@ F src/build.c 7cdc95266496f53673a66202477b137d514898cf
 F src/copy.c 9e47975ea96751c658bcf1a0c4f0bb7c6ee61e73
 F src/delete.c 0f81e6799c089487615d38e042a2de4d2d6192bc
 F src/encode.c 25ea901a9cefb3d93774afa4a06b57cb58acf544
-F src/expr.c 03c321ac66c1e998c2e0faf22184b5a808b559ca
-F src/func.c be22d719450ffa4c2e04adec96d9116a4c0cdb62
+F src/expr.c 0c10a35c15756e90940d946cdec1e5c7d860ddc9
+F src/func.c 377ea94127351de27892a62a63f931e0fbaa33d4
 F src/hash.c 058f077c1f36f266581aa16f907a3903abf64aa3
 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8
 F src/insert.c dc200ae04a36bd36e575272a069e20c528b7fbdf
-F src/main.c 2500392bad5629b6d70b06ac5a076958acb49b92
+F src/main.c e472b0c86b811a76b6a17760c945acfabd8ba935
 F src/md5.c fe4f9c9c6f71dfc26af8da63e4d04489b1430565
 F src/os.c 97df440bc71f65e22df5d3d920ce39551c0a5f5a
 F src/os.h 729395fefcca4b81ae056aa9ff67b72bb40dd9e0
-F src/pager.c 77e1a7de50197e5fc87353c36006a304756b0747
+F src/pager.c 62702dff51d50694d039bc210f31990d1fbba2dd
 F src/pager.h 5da62c83443f26b1792cfd72c96c422f91aadd31
-F src/parse.y 16aed0e3ed05445fa7f6a4209cc054208c7083c0
+F src/parse.y 5cd707f0e5444b1dd168e414dd2c055fb158db5c
 F src/pragma.c cee60f17679210e8acd30d5bdee855716d0c898c
 F src/printf.c 12e45d482ac8abcc6f786fc99e5bed7dd9a51af0
 F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
 F src/select.c 2fa83d6c972d3e3f379faee32e3621411490dedb
 F src/shell.c c2ba26c850874964f5ec1ebf6c43406f28e44c4a
 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in dafa83571810b6932f089b589c783355ef7a54b5
+F src/sqlite.h.in 72c07cf3b70c42a0e829270527f7b40a55d4a2d6
 F src/sqliteInt.h e68eb1eeba806905acc9ed491f4c5b96587020df
 F src/table.c 4301926464d88d2c2c7cd21c3360aa75bf068b95
 F src/tclsqlite.c ec9e5b796bf9ec1483927e986828a205d4a7422a
-F src/test1.c b12b585bfb4763df3262975ed8d3f4f274b5eaed
+F src/test1.c 751e11106c637d8ee64ecf95597b0133c544ab9f
 F src/test2.c 5014337d8576b731cce5b5a14bec4f0daf432700
 F src/test3.c 30985ebdfaf3ee1462a9b0652d3efbdc8d9798f5
 F src/threadtest.c d641a5219e718e18a1a80a50eb9bb549f451f42e
-F src/tokenize.c 2ba93fe10d5f57f0cc20b07417c3244a30c324b3
+F src/tokenize.c ea4e89b37db050fb99ae4c916bd7671375845aaf
 F src/trigger.c 474581eaab388233df01bb019e558af2965decbf
 F src/update.c 24260b4fda00c9726d27699a0561d53c0dccc397
 F src/util.c f16efa2d60bfd4e31ae06b07ed149557e828d294
 F src/vacuum.c e4724eade07e4cf8897060a8cf632dbd92408eeb
-F src/vdbe.c 306f59011785428e2d19578ca1fcd7a1304f57f7
-F src/vdbe.h d853ed6cc4727fa9e8ace6187c55afcf817041dd
+F src/vdbe.c b6a2b0a8eeca95cc29a9e07fb7d2cc3c1eaec468
+F src/vdbe.h 3c51cb382316dbf3860e4ece72e658b4bf014501
 F src/where.c 83b2a2d26d5c3bea33457a83e541bb1dcf7b1248
 F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
 F test/attach.test c26848402e7ac829e043e1fa5e0eb87032e5d81d
@@ -170,7 +170,7 @@ F www/speed.tcl 2f6b1155b99d39adb185f900456d1d592c4832b3
 F www/sqlite.tcl 3c83b08cf9f18aa2d69453ff441a36c40e431604
 F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
 F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
-P 522c2efeb5bdccadf3306234d458425b94cdbbe3
-R 5b61a815079f1971babe212bb4f8b793
+P aaa84c6202f6e16828bcd6aff2e424f3dba1f82b
+R 0bb0019009c0a448d322679ad1dd5f73
 U drh
-Z f92c2044c3f4c2f842d2611b3febcf40
+Z 42cb329fb1ec590b60ca4f6b47463c49
index 0d4d8c2e03ca304b70c754efc5a75ada04f3f9c6..b0c5bbb28cc1200fdd89eccb482df1cf0ebb8e95 100644 (file)
@@ -1 +1 @@
-aaa84c6202f6e16828bcd6aff2e424f3dba1f82b
\ No newline at end of file
+912f47c72d3597c6d5acff765d94922bd660339a
\ No newline at end of file
index 804e751b798ec2c57d68267d73e9aff9622f12fe..46bd04d4711035247c4fe723ac6273b2a647634a 100644 (file)
@@ -12,7 +12,7 @@
 ** This file contains routines used for analyzing expressions and
 ** for generating VDBE code that evaluates expressions in SQLite.
 **
-** $Id: expr.c,v 1.98 2003/07/30 12:34:12 drh Exp $
+** $Id: expr.c,v 1.99 2003/09/06 01:10:47 drh Exp $
 */
 #include "sqliteInt.h"
 #include <ctype.h>
@@ -310,6 +310,7 @@ int sqliteExprIsConstant(Expr *p){
     case TK_STRING:
     case TK_INTEGER:
     case TK_FLOAT:
+    case TK_VARIABLE:
       return 1;
     default: {
       if( p->pLeft && !sqliteExprIsConstant(p->pLeft) ) return 0;
@@ -914,6 +915,7 @@ int sqliteExprType(Expr *p){
     case TK_STRING:
     case TK_NULL:
     case TK_CONCAT:
+    case TK_VARIABLE:
       return SQLITE_SO_TEXT;
 
     case TK_LT:
@@ -1043,6 +1045,10 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
       sqliteVdbeAddOp(v, OP_String, 0, 0);
       break;
     }
+    case TK_VARIABLE: {
+      sqliteVdbeAddOp(v, OP_Variable, atoi(&pExpr->token.z[1]), 0);
+      break;
+    }
     case TK_LT:
     case TK_LE:
     case TK_GT:
index c7d2eb51e6d5e1113e1259a57a864c1dd240708a..2e3c20728e27c609a8b7c5d166ebf8207575fe66 100644 (file)
@@ -16,7 +16,7 @@
 ** sqliteRegisterBuildinFunctions() found at the bottom of the file.
 ** All other code has file scope.
 **
-** $Id: func.c,v 1.30 2003/08/26 11:41:27 drh Exp $
+** $Id: func.c,v 1.31 2003/09/06 01:10:47 drh Exp $
 */
 #include <ctype.h>
 #include <math.h>
@@ -542,6 +542,9 @@ static void minMaxFinalize(sqlite_func *context){
 /****************************************************************************
 ** Time and date functions.
 **
+** 1970-01-01 00:00:00 is JD 2440587.5.
+** 2000-01-01 00:00:00 is JD 2451544.5
+**
 ** SQLite processes all times and dates as Julian Day numbers.  The
 ** dates and times are stored as the number of days since noon
 ** in Greenwich on November 24, 4714 B.C. according to the Gregorian
index 27c2ec92b2d938871c85f28ada13cf62573e1c70..29a4d2ca0d76143f74374e35dfd0489577555180 100644 (file)
@@ -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.140 2003/07/27 17:26:23 drh Exp $
+** $Id: main.c,v 1.141 2003/09/06 01:10:47 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -695,6 +695,32 @@ int sqlite_compile(
   return sqliteMain(db, zSql, 0, 0, pzTail, ppVm, pzErrMsg);
 }
 
+/*
+** If the SQL that was handed to sqlite_compile contains variables of
+** the form $1, $2, $3, etc. then this routine assigns values to those
+** variables.  azValue[0] is assigned to $1.  azValue[1] is assigned
+** to $2.  And so forth.  The value of variable $0 will always be NULL.
+** The values of any variable $N where N>nValue will be NULL.  If any
+** azValue[] is a NULL pointer, then the corresponding variable will be
+** NULL.
+**
+** This routine can only be called immediately after sqlite_compile()
+** or sqlite_reset() and before any calls to sqlite_step().
+**
+** This routine makes copies of all strings in azValue[] so the values
+** passed in can be changed or deleted immediately after this call.  The
+** copies are deallocated when sqlite_finalize() or sqlite_reset() is
+** invoked.
+*/
+int sqlite_instantiate(
+  sqlite_vm *pVm,
+  int nValue,
+  const char **azValue
+){
+  return sqliteVdbeSetVariables((Vdbe*)pVm, nValue, azValue);
+}
+
+
 /*
 ** The following routine destroys a virtual machine that is created by
 ** the sqlite_compile() routine.
@@ -716,16 +742,18 @@ int sqlite_finalize(
 }
 
 /*
-** Destroy a virtual machine in the same manner as sqlite_finalize(). If 
-** possible, leave *ppVm pointing at a new virtual machine which may be
-** used to re-execute the query.
+** Terminate the current execution of a virtual machine then
+** reset the virtual machine back to its starting state so that it
+** can be reused.  Any error message resulting from the prior execution
+** is written into *pzErrMsg.  A success code from the prior execution
+** is returned.
 */
 int sqlite_reset(
   sqlite_vm *pVm,            /* The virtual machine to be destroyed */
-  char **pzErrMsg,           /* OUT: Write error messages here */
-  sqlite_vm **ppVm           /* OUT: The new virtual machine */
+  char **pzErrMsg            /* OUT: Write error messages here */
 ){
-  int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg, (Vdbe **)ppVm);
+  int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg);
+  sqliteVdbeMakeReady((Vdbe*)pVm, 0, 0, 0);
   sqliteStrRealloc(pzErrMsg);
   return rc;
 }
index 5a58e6d6864bbe6346cd4d39ca361622eda59994..c3fff42ac2ae69014308dc8363f08258681af84c 100644 (file)
@@ -18,7 +18,7 @@
 ** file simultaneously, or one process from reading the database while
 ** another is writing.
 **
-** @(#) $Id: pager.c,v 1.89 2003/08/26 11:41:27 drh Exp $
+** @(#) $Id: pager.c,v 1.90 2003/09/06 01:10:47 drh Exp $
 */
 #include "os.h"         /* Must be first to enable large file support */
 #include "sqliteInt.h"
@@ -426,6 +426,10 @@ static void pager_reset(Pager *pPager){
 ** a write lock on the database.  This routine releases the database
 ** write lock and acquires a read lock in its place.  The journal file
 ** is deleted and closed.
+**
+** TODO: Consider keeping the journal file open for temporary databases.
+** This might give a performance improvement on windows where opening
+** a file is an expensive operation.
 */
 static int pager_unwritelock(Pager *pPager){
   int rc;
index 4efb90ed761fe3ee4cc67d4963e3a5c07e2e4d33..5ea4f410f37c984dca93e6c24198b5f514fe41ee 100644 (file)
@@ -14,7 +14,7 @@
 ** the parser.  Lemon will also generate a header file containing
 ** numeric codes for all of the tokens.
 **
-** @(#) $Id: parse.y,v 1.99 2003/07/16 02:19:38 drh Exp $
+** @(#) $Id: parse.y,v 1.100 2003/09/06 01:10:48 drh Exp $
 */
 %token_prefix TK_
 %token_type {Token}
@@ -541,6 +541,7 @@ expr(A) ::= expr(B) ORACLE_OUTER_JOIN.
 expr(A) ::= INTEGER(X).      {A = sqliteExpr(TK_INTEGER, 0, 0, &X);}
 expr(A) ::= FLOAT(X).        {A = sqliteExpr(TK_FLOAT, 0, 0, &X);}
 expr(A) ::= STRING(X).       {A = sqliteExpr(TK_STRING, 0, 0, &X);}
+expr(A) ::= VARIABLE(X).     {A = sqliteExpr(TK_VARIABLE, 0, 0, &X);}
 expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
   A = sqliteExprFunction(Y, &X);
   sqliteExprSpan(A,&X,&E);
index 2980f817e7fb92570a62c1b119ec64c39576b32b..bcf8b38a2bddf777897bf9930ab1966f8e2dfd80 100644 (file)
@@ -12,7 +12,7 @@
 ** This header file defines the interface that the SQLite library
 ** presents to client programs.
 **
-** @(#) $Id: sqlite.h.in,v 1.50 2003/07/22 09:24:44 danielk1977 Exp $
+** @(#) $Id: sqlite.h.in,v 1.51 2003/09/06 01:10:48 drh Exp $
 */
 #ifndef _SQLITE_H_
 #define _SQLITE_H_
@@ -695,9 +695,31 @@ int sqlite_finalize(sqlite_vm*, char **pzErrMsg);
 **
 ** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL.
 **
+*/
+int sqlite_reset(sqlite_vm *, char **pzErrMsg);
+
+/*
+** If the SQL that was handed to sqlite_compile contains variables of
+** the form $1, $2, $3, etc. then this routine assigns values to those
+** variables.  azValue[0] is assigned to $1.  azValue[1] is assigned
+** to $2.  And so forth.  The value of variable $0 will always be NULL.
+** The values of any variable $N where N>nValue will be NULL.  If any
+** azValue[] is a NULL pointer, then the corresponding variable will be
+** NULL.
+**
+** This routine can only be called immediately after sqlite_compile()
+** or sqlite_reset() and before any calls to sqlite_step().
+**
+** This routine makes copies of all strings in azValue[] so the values
+** passed in can be changed or deleted immediately after this call.  The
+** copies are deallocated when sqlite_finalize() or sqlite_reset() is
+** invoked.
+**
 ******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
 */
-int sqlite_reset(sqlite_vm *, char **pzErrMsg, sqlite_vm **ppVm);
+int sqlite_instantiate(sqlite_vm*, int, const char**);
+
+
 
 #ifdef __cplusplus
 }  /* End of the 'extern "C"' block */
index 3ec97d7e7fe296b2d5fa6f694271ec846529ae2c..d768d3440cf39172238036cfab9f76b8701781da 100644 (file)
@@ -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.26 2003/07/09 00:28:15 drh Exp $
+** $Id: test1.c,v 1.27 2003/09/06 01:10:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -774,6 +774,66 @@ static int test_finalize(
   return TCL_OK;
 }
 
+/*
+** Usage:  sqlite_reset   VM 
+**
+** Reset a virtual machine and prepare it to be run again.
+*/
+static int test_reset(
+  void *NotUsed,
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int argc,              /* Number of arguments */
+  char **argv            /* Text of each argument */
+){
+  sqlite_vm *vm;
+  int rc;
+  char *zErrMsg = 0;
+  if( argc!=2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
+       " VM\"", 0);
+    return TCL_ERROR;
+  }
+  if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
+  rc = sqlite_reset(vm, &zErrMsg);
+  if( rc ){
+    char zBuf[50];
+    sprintf(zBuf, "(%d) ", rc);
+    Tcl_AppendResult(interp, zBuf, zErrMsg, 0);
+    sqlite_freemem(zErrMsg);
+    return TCL_ERROR;
+  }
+  return TCL_OK;
+}
+
+/*
+** Usage:  sqlite_instantiate  VM  ARGS...
+**
+** Set the values of variables (ex: $1, $2, etc) in the original SQL string.
+*/
+static int test_instantiate(
+  void *NotUsed,
+  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
+  int argc,              /* Number of arguments */
+  char **argv            /* Text of each argument */
+){
+  sqlite_vm *vm;
+  int rc;
+  if( argc<2 ){
+    Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], 
+       " VM ARGS...\"", 0);
+    return TCL_ERROR;
+  }
+  if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
+  rc = sqlite_instantiate(vm, argc-2, &argv[2]);
+  if( rc ){
+    char zBuf[50];
+    sprintf(zBuf, "(%d) ", rc);
+    Tcl_AppendResult(interp, zBuf, sqlite_error_string(rc), 0);
+    return TCL_ERROR;
+  }
+  return TCL_OK;
+}
+
 /*
 ** Usage:    breakpoint
 **
@@ -827,6 +887,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
      { "sqlite_compile",                 (Tcl_CmdProc*)test_compile          },
      { "sqlite_step",                    (Tcl_CmdProc*)test_step             },
      { "sqlite_finalize",                (Tcl_CmdProc*)test_finalize         },
+     { "sqlite_instantiate",             (Tcl_CmdProc*)test_instantiate      },
+     { "sqlite_reset",                   (Tcl_CmdProc*)test_reset            },
      { "breakpoint",                     (Tcl_CmdProc*)test_breakpoint       },
   };
   int i;
index 66ecae06c232b4e232695961d38c3676675c96cb..7a187186e6abea44db0b2de6d49ae2c67fa2ecc9 100644 (file)
@@ -15,7 +15,7 @@
 ** individual tokens and sends those tokens one-by-one over to the
 ** parser for analysis.
 **
-** $Id: tokenize.c,v 1.60 2003/05/04 18:30:59 drh Exp $
+** $Id: tokenize.c,v 1.61 2003/09/06 01:10:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -380,6 +380,12 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
       *tokenType = TK_ID;
       return i;
     }
+    case '$': {
+      if( !isdigit(z[1]) ) break;
+      for(i=1; z[i] && isdigit(z[i]); i++){}
+      *tokenType = TK_VARIABLE;
+      return i;
+    }
     default: {
       if( !isIdChar[*z] ){
         break;
index 1df38bf2006db303358b32e0e1fb8a323491c8fb..de33d162d7e1c2a5d59bfa87bfbf575e450e1a78 100644 (file)
@@ -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.237 2003/08/26 11:35:00 drh Exp $
+** $Id: vdbe.c,v 1.238 2003/09/06 01:10:48 drh Exp $
 */
 #include "sqliteInt.h"
 #include "os.h"
@@ -270,9 +270,11 @@ struct Vdbe {
   FILE *pFile;        /* At most one open file handler */
   int nField;         /* Number of file fields */
   char **azField;     /* Data for each file field */
+  int nVariable;          /* Number of entries in azVariable[] */
+  char **azVariable;      /* Values for the OP_Variable opcode */
   char *zLine;            /* A single line from the input file */
-  int magic;              /* Magic number for sanity checking */
   int nLineAlloc;         /* Number of spaces allocated for zLine */
+  int magic;              /* Magic number for sanity checking */
   int nMem;               /* Number of memory locations currently allocated */
   Mem *aMem;              /* The memory locations */
   Agg agg;                /* Aggregate information */
@@ -1147,11 +1149,21 @@ static void SorterReset(Vdbe *p){
   }
 }
 
+/*
+** Delete the variables in p->azVariable[]
+*/
+static void ClearVariableArray(Vdbe *p){
+  sqliteFree(p->azVariable);
+  p->nVariable = 0;
+  p->azVariable = 0;
+}
+
 /*
 ** Clean up the VM after execution.
 **
 ** This routine will automatically close any cursors, lists, and/or
-** sorters that were left open.
+** sorters that were left open.  It also deletes the values of
+** variables in the azVariable[] array.
 */
 static void Cleanup(Vdbe *p){
   int i;
@@ -1206,7 +1218,7 @@ static void Cleanup(Vdbe *p){
   }
   sqliteFree(p->zErrMsg);
   p->zErrMsg = 0;
-  p->magic = VDBE_MAGIC_DEAD;
+  ClearVariableArray(p);
 }
 
 /*
@@ -1238,6 +1250,7 @@ void sqliteVdbeDelete(Vdbe *p){
   sqliteFree(p->aOp);
   sqliteFree(p->aLabel);
   sqliteFree(p->aStack);
+  p->magic = VDBE_MAGIC_DEAD;
   sqliteFree(p);
 }
 
@@ -1508,7 +1521,9 @@ void sqliteVdbeMakeReady(
 
   /* Add a HALT instruction to the very end of the program.
   */
-  sqliteVdbeAddOp(p, OP_Halt, 0, 0);
+  if( p->nOp==0 || (p->aOp && p->aOp[p->nOp-1].opcode!=OP_Halt) ){
+    sqliteVdbeAddOp(p, OP_Halt, 0, 0);
+  }
 
   /* No instruction ever pushes more than a single element onto the
   ** stack.  And the stack never grows on successive executions of the
@@ -1539,7 +1554,7 @@ void sqliteVdbeMakeReady(
   p->xCallback = xCallback;
   p->pCbArg = pCallbackArg;
   p->popStack =  0;
-  p->explain = isExplain;
+  p->explain |= isExplain;
   p->magic = VDBE_MAGIC_RUN;
 #ifdef VDBE_PROFILE
   for(i=0; i<p->nOp; i++){
@@ -1772,6 +1787,27 @@ case OP_String: {
   break;
 }
 
+/* Opcode: Variable P1 * *
+**
+** Push the value of variable P1 onto the stack.  A variable is
+** an unknown in the original SQL string as handed to sqlite_compile().
+** The first variable is $1, the second is $2, and so forth.  The
+** value of the variables is determined by sqlite_instantiate().
+*/
+case OP_Variable: {
+  int i = ++p->tos;
+  if( pOp->p1>0 && pOp->p1<=p->nVariable && p->azVariable[pOp->p1-1]!=0 ){
+    zStack[i] = p->azVariable[pOp->p1-1];
+    aStack[i].n = strlen(zStack[i]) + 1;
+    aStack[i].flags = STK_Str | STK_Static;
+  }else{
+    zStack[i] = 0;
+    aStack[i].n = 0;
+    aStack[i].flags = STK_Null;
+  }
+  break;
+}
+
 /* Opcode: Pop P1 * *
 **
 ** P1 elements are popped off of the top of stack and discarded.
@@ -3025,9 +3061,17 @@ case OP_MakeRecord: {
 ** back in its place.
 **
 ** P3 is a string that is P1 characters long.  Each character is either
-** an 'n' or a 't' to indicates if the argument should be numeric or
-** text.  The first character corresponds to the lowest element on the
-** stack.  If P3 is NULL then all arguments are assumed to be numeric.
+** an 'n' or a 't' to indicates if the argument should be intepreted as
+** numeric or text type.  The first character of P3 corresponds to the
+** lowest element on the stack.  If P3 is NULL then all arguments are
+** assumed to be of the numeric type.
+**
+** The type makes a difference in that text-type fields may not be 
+** introduced by 'b' (as described in the next paragraph).  The
+** first character of a text-type field must be either 'a' (if it is NULL)
+** or 'c'.  Numeric fields will be introduced by 'b' if their content
+** looks like a well-formed number.  Otherwise the 'a' or 'c' will be
+** used.
 **
 ** The key is a concatenation of fields.  Each field is terminated by
 ** a single 0x00 character.  A NULL field is introduced by an 'a' and
@@ -3039,7 +3083,7 @@ case OP_MakeRecord: {
 ** sqliteRealToSortable() function.  A text field is introduced by a
 ** 'c' character and is followed by the exact text of the field.  The
 ** use of an 'a', 'b', or 'c' character at the beginning of each field
-** guarantees that NULL sort before numbers and that numbers sort
+** guarantees that NULLs sort before numbers and that numbers sort
 ** before text.  0x00 characters do not occur except as separators
 ** between fields.
 **
@@ -5816,12 +5860,15 @@ bad_instruction:
 
 
 /*
-** Clean up the VDBE after execution.  Return an integer which is the
-** result code.
+** Clean up a VDBE after execution but do not delete the VDBE just yet.
+** Write any error messages into *pzErrMsg.  Return the result code.
+**
+** After this routine is run, the VDBE should be ready to be executed
+** again.
 */
-int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
+int sqliteVdbeReset(Vdbe *p, char **pzErrMsg){
   sqlite *db = p->db;
-  int i, rc;
+  int i;
 
   if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
     sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), 0);
@@ -5895,7 +5942,24 @@ int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
     }
   }
 #endif
-  rc = p->rc;
+  p->magic = VDBE_MAGIC_INIT;
+  return p->rc;
+}
+
+/*
+** Clean up and delete a VDBE after execution.  Return an integer which is
+** the result code.  Write any error message text into *pzErrMsg.
+*/
+int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
+  int rc;
+  sqlite *db;
+
+  if( p->magic!=VDBE_MAGIC_RUN && p->magic!=VDBE_MAGIC_HALT ){
+    sqliteSetString(pzErrMsg, sqlite_error_string(SQLITE_MISUSE), 0);
+    return SQLITE_MISUSE;
+  }
+  db = p->db;
+  rc = sqliteVdbeReset(p, pzErrMsg);
   sqliteVdbeDelete(p);
   if( db->want_to_close && db->pVdbe==0 ){
     sqlite_close(db);
@@ -5903,12 +5967,55 @@ int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
   return rc;
 }
 
+/*
+** Set the values of all variables.  Variable $1 in the original SQL will
+** be the string azValue[0].  $2 will have the value azValue[1].  And
+** so forth.  If a value is out of range (for example $3 when nValue==2)
+** then its value will be NULL.
+**
+** This routine overrides any prior call.
+*/
+int sqliteVdbeSetVariables(Vdbe *p, int nValue, const char **azValue){
+  int i, n;
+  char *z;
+  if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 || p->nVariable!=0 ){
+    return SQLITE_MISUSE;
+  }
+  ClearVariableArray(p);
+  if( nValue==0 ){
+    p->nVariable = 0;
+    p->azVariable = 0;
+  }
+  for(i=n=0; i<nValue; i++){
+    if( azValue[i] ) n += strlen(azValue[i]) + 1;
+  }
+  p->azVariable = sqliteMalloc( sizeof(p->azVariable[0])*nValue + n );
+  if( p->azVariable==0 ){
+    p->nVariable = 0;
+    return SQLITE_NOMEM;
+  }
+  z = (char*)&p->azVariable[nValue];
+  for(i=0; i<nValue; i++){
+    if( azValue[i]==0 ){
+      p->azVariable[i] = 0;
+    }else{
+      p->azVariable[i] = z;
+      n = strlen(azValue[i]);
+      memcpy(z, azValue[i], n+1);
+      z += n+1;
+    }
+  }
+  p->nVariable = nValue;
+  return SQLITE_OK;
+}
+
+
+#if 0
 /*
 ** Create a new Vdbe in *pOut and populate it with the program from p. Then
 ** pass p to sqliteVdbeFinalize().
 */
-int sqliteVdbeReset(Vdbe *p, char ** pErrMsg, Vdbe** pOut)
-{
+int sqliteVdbeReset(Vdbe *p, char ** pErrMsg, Vdbe** pOut){
   if( pOut && p->rc != SQLITE_SCHEMA ){
 
     /* Create a new VDBE and populate it with the program used by the old
@@ -5928,3 +6035,4 @@ int sqliteVdbeReset(Vdbe *p, char ** pErrMsg, Vdbe** pOut)
   }
   return sqliteVdbeFinalize(p, pErrMsg);
 }
+#endif
index 9d77ac5695274c12c6397387d122fa89373714bc..494313dcb4f5231594762b40c9fde6260adbaf56 100644 (file)
@@ -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.66 2003/07/22 09:24:44 danielk1977 Exp $
+** $Id: vdbe.h,v 1.67 2003/09/06 01:10:49 drh Exp $
 */
 #ifndef _SQLITE_VDBE_H_
 #define _SQLITE_VDBE_H_
@@ -92,6 +92,7 @@ void sqliteVdbeResolveLabel(Vdbe*, int);
 int sqliteVdbeCurrentAddr(Vdbe*);
 void sqliteVdbeTrace(Vdbe*,FILE*);
 void sqliteVdbeCompressSpace(Vdbe*,int);
-int sqliteVdbeReset(Vdbe*,char **,Vdbe**);
+int sqliteVdbeReset(Vdbe*,char **);
+int sqliteVdbeSetVariables(Vdbe*,int,const char**);
 
 #endif