The beginnings of changes to support pre-compiled SQL. Mostly untested,

though all regression tests to pass. (CVS 1093)

FossilOrigin-Name: 912f47c72d3597c6d5acff765d94922bd660339a
This commit is contained in:
drh 2003-09-06 01:10:47 +00:00
parent c023e03ea5
commit 5045789694
12 changed files with 291 additions and 50 deletions

View File

@ -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

View File

@ -1 +1 @@
aaa84c6202f6e16828bcd6aff2e424f3dba1f82b
912f47c72d3597c6d5acff765d94922bd660339a

View 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:

View 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

View 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;
}

View 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;

View 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);

View 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 */

View 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;

View 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;

View 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

View 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