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:
parent
c023e03ea5
commit
5045789694
30
manifest
30
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
|
||||
|
@ -1 +1 @@
|
||||
aaa84c6202f6e16828bcd6aff2e424f3dba1f82b
|
||||
912f47c72d3597c6d5acff765d94922bd660339a
|
@ -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:
|
||||
|
@ -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
|
||||
|
42
src/main.c
42
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.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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
64
src/test1.c
64
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.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;
|
||||
|
@ -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;
|
||||
|
142
src/vdbe.c
142
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.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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user