aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordrh <drh@noemail.net>2003-09-06 22:18:07 +0000
committerdrh <drh@noemail.net>2003-09-06 22:18:07 +0000
commit7c972dec5ca539a5f33507a00d5db2ba66373887 (patch)
tree989489c046b5beee09cf1bb010bd8d55603c4c1c /src
parent9a32464b543cda85c698bd14e3561c4ebff22da1 (diff)
downloadsqlite-7c972dec5ca539a5f33507a00d5db2ba66373887.tar.gz
sqlite-7c972dec5ca539a5f33507a00d5db2ba66373887.zip
Update Makefile.in for the new vdbeaux.c file. Remove the experimental
"sqlite_instantiate()" routine and replace it with "sqlite_bind()" which is more like ODBC and JDBC. (CVS 1095) FossilOrigin-Name: 990bb11898a539bb0795a4a216fcd989943a0fb2
Diffstat (limited to 'src')
-rw-r--r--src/build.c7
-rw-r--r--src/expr.c4
-rw-r--r--src/main.c30
-rw-r--r--src/parse.y7
-rw-r--r--src/sqlite.h.in42
-rw-r--r--src/sqliteInt.h7
-rw-r--r--src/test1.c41
-rw-r--r--src/tokenize.c8
-rw-r--r--src/vdbe.c15
-rw-r--r--src/vdbe.h4
-rw-r--r--src/vdbeInt.h6
-rw-r--r--src/vdbeaux.c69
12 files changed, 129 insertions, 111 deletions
diff --git a/src/build.c b/src/build.c
index 560fc305e..0e214676d 100644
--- a/src/build.c
+++ b/src/build.c
@@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
-** $Id: build.c,v 1.159 2003/08/24 16:38:18 drh Exp $
+** $Id: build.c,v 1.160 2003/09/06 22:18:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -51,6 +51,7 @@ void sqliteBeginParse(Parse *pParse, int explainFlag){
DbClearProperty(db, i, DB_Cookie);
}
}
+ pParse->nVar = 0;
}
/*
@@ -86,7 +87,8 @@ void sqliteExec(Parse *pParse){
if( v && pParse->nErr==0 ){
FILE *trace = (db->flags & SQLITE_VdbeTrace)!=0 ? stdout : 0;
sqliteVdbeTrace(v, trace);
- sqliteVdbeMakeReady(v, xCallback, pParse->pArg, pParse->explain);
+ sqliteVdbeMakeReady(v, pParse->nVar, xCallback, pParse->pArg,
+ pParse->explain);
if( pParse->useCallback ){
if( pParse->explain ){
rc = sqliteVdbeList(v);
@@ -110,6 +112,7 @@ void sqliteExec(Parse *pParse){
pParse->nMem = 0;
pParse->nSet = 0;
pParse->nAgg = 0;
+ pParse->nVar = 0;
}
/*
diff --git a/src/expr.c b/src/expr.c
index 46bd04d47..398bf8f62 100644
--- a/src/expr.c
+++ b/src/expr.c
@@ -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.99 2003/09/06 01:10:47 drh Exp $
+** $Id: expr.c,v 1.100 2003/09/06 22:18:08 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -1046,7 +1046,7 @@ void sqliteExprCode(Parse *pParse, Expr *pExpr){
break;
}
case TK_VARIABLE: {
- sqliteVdbeAddOp(v, OP_Variable, atoi(&pExpr->token.z[1]), 0);
+ sqliteVdbeAddOp(v, OP_Variable, pExpr->iTable, 0);
break;
}
case TK_LT:
diff --git a/src/main.c b/src/main.c
index 29a4d2ca0..1b0c692e8 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.141 2003/09/06 01:10:47 drh Exp $
+** $Id: main.c,v 1.142 2003/09/06 22:18:08 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -695,31 +695,6 @@ 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
@@ -753,7 +728,7 @@ int sqlite_reset(
char **pzErrMsg /* OUT: Write error messages here */
){
int rc = sqliteVdbeReset((Vdbe*)pVm, pzErrMsg);
- sqliteVdbeMakeReady((Vdbe*)pVm, 0, 0, 0);
+ sqliteVdbeMakeReady((Vdbe*)pVm, -1, 0, 0, 0);
sqliteStrRealloc(pzErrMsg);
return rc;
}
@@ -790,6 +765,7 @@ const char *sqlite_error_string(int rc){
case SQLITE_NOLFS: z = "kernel lacks large file support"; break;
case SQLITE_AUTH: z = "authorization denied"; break;
case SQLITE_FORMAT: z = "auxiliary database format error"; break;
+ case SQLITE_RANGE: z = "bind index out of range"; break;
default: z = "unknown error"; break;
}
return z;
diff --git a/src/parse.y b/src/parse.y
index 5ea4f410f..21c033b10 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -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.100 2003/09/06 01:10:48 drh Exp $
+** @(#) $Id: parse.y,v 1.101 2003/09/06 22:18:08 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@@ -541,7 +541,10 @@ 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) ::= VARIABLE(X). {
+ A = sqliteExpr(TK_VARIABLE, 0, 0, &X);
+ if( A ) A->iTable = ++pParse->nVar;
+}
expr(A) ::= ID(X) LP exprlist(Y) RP(E). {
A = sqliteExprFunction(Y, &X);
sqliteExprSpan(A,&X,&E);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index bcf8b38a2..3832ee6b9 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.51 2003/09/06 01:10:48 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.52 2003/09/06 22:18:08 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
@@ -166,6 +166,7 @@ int sqlite_exec(
#define SQLITE_NOLFS 22 /* Uses OS features not supported on host */
#define SQLITE_AUTH 23 /* Authorization denied */
#define SQLITE_FORMAT 24 /* Auxiliary database format error */
+#define SQLITE_RANGE 25 /* 2nd parameter to sqlite_bind out of range */
#define SQLITE_ROW 100 /* sqlite_step() has another row ready */
#define SQLITE_DONE 101 /* sqlite_step() has finished executing */
@@ -695,31 +696,38 @@ int sqlite_finalize(sqlite_vm*, char **pzErrMsg);
**
** If sqlite_reset() returns SQLITE_SCHEMA, then *ppVm is set to NULL.
**
+******* THIS IS AN EXPERIMENTAL API AND IS SUBJECT TO CHANGE ******
*/
-int sqlite_reset(sqlite_vm *, char **pzErrMsg);
+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.
+** If the SQL that was handed to sqlite_compile contains variables that
+** are represeted in the SQL text by a question mark ('?'). This routine
+** is used to assign values to those variables.
+**
+** The first parameter is a virtual machine obtained from sqlite_compile().
+** The 2nd "idx" parameter determines which variable in the SQL statement
+** to bind the value to. The left most '?' is 1. The 3rd parameter is
+** the value to assign to that variable. The 4th parameter is the number
+** of bytes in the value, including the terminating \000 for strings.
+** Finally, the 5th "copy" parameter is TRUE if SQLite should make its
+** own private copy of this value, or false if the space that the 3rd
+** parameter points to will be unchanging and can be used directly by
+** SQLite.
+**
+** Unbound variables are treated as having a value of NULL. To explicitly
+** set a variable to NULL, call this routine with the 3rd parameter as a
+** NULL pointer.
+**
+** If the 4th "len" parameter is -1, then strlen() is used to find the
+** length.
**
** 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_instantiate(sqlite_vm*, int, const char**);
-
-
+int sqlite_bind(sqlite_vm*, int idx, const char *value, int len, int copy);
#ifdef __cplusplus
} /* End of the 'extern "C"' block */
diff --git a/src/sqliteInt.h b/src/sqliteInt.h
index 65944bec8..500bcf475 100644
--- a/src/sqliteInt.h
+++ b/src/sqliteInt.h
@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.197 2003/08/23 22:40:54 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.198 2003/09/06 22:18:08 drh Exp $
*/
#include "config.h"
#include "sqlite.h"
@@ -604,7 +604,9 @@ struct Token {
** it can be accessed after all aggregates are computed.
**
** If the expression is a function, the Expr.iTable is an integer code
-** representing which function.
+** representing which function. If the expression is an unbound variable
+** marker (a question mark character '?' in the original SQL) then the
+** Expr.iTable holds the index number for that variable.
**
** The Expr.pSelect field points to a SELECT statement. The SELECT might
** be the right operand of an IN operator. Or, if a scalar SELECT appears
@@ -866,6 +868,7 @@ struct Parse {
int nMem; /* Number of memory cells used so far */
int nSet; /* Number of sets used so far */
int nAgg; /* Number of aggregate expressions */
+ int nVar; /* Number of '?' variables seen in the SQL so far */
AggExpr *aAgg; /* An array of aggregate expressions */
const char *zAuthContext; /* The 6th parameter to db->xAuth callbacks */
Trigger *pNewTrigger; /* Trigger under construct by a CREATE TRIGGER */
diff --git a/src/test1.c b/src/test1.c
index d768d3440..e8af1fc8f 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.27 2003/09/06 01:10:48 drh Exp $
+** $Id: test1.c,v 1.28 2003/09/06 22:18:08 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -806,11 +806,22 @@ static int test_reset(
}
/*
-** Usage: sqlite_instantiate VM ARGS...
+** This is the "static_bind_value" that variables are bound to when
+** the FLAG option of sqlite_bind is "static"
+*/
+static char *sqlite_static_bind_value = 0;
+
+/*
+** Usage: sqlite_bind VM IDX VALUE FLAGS
**
-** Set the values of variables (ex: $1, $2, etc) in the original SQL string.
+** Sets the value of the IDX-th occurance of "?" in the original SQL
+** string. VALUE is the new value. If FLAGS=="null" then VALUE is
+** ignored and the value is set to NULL. If FLAGS=="static" then
+** the value is set to the value of a static variable named
+** "sqlite_static_bind_value". If FLAGS=="normal" then a copy
+** of the VALUE is made.
*/
-static int test_instantiate(
+static int test_bind(
void *NotUsed,
Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
int argc, /* Number of arguments */
@@ -818,13 +829,25 @@ static int test_instantiate(
){
sqlite_vm *vm;
int rc;
- if( argc<2 ){
+ int idx;
+ if( argc!=5 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
- " VM ARGS...\"", 0);
+ " VM IDX VALUE (null|static|normal)\"", 0);
return TCL_ERROR;
}
if( getVmPointer(interp, argv[1], &vm) ) return TCL_ERROR;
- rc = sqlite_instantiate(vm, argc-2, &argv[2]);
+ if( Tcl_GetInt(interp, argv[2], &idx) ) return TCL_ERROR;
+ if( strcmp(argv[4],"null")==0 ){
+ rc = sqlite_bind(vm, idx, 0, 0, 0);
+ }else if( strcmp(argv[4],"static")==0 ){
+ rc = sqlite_bind(vm, idx, sqlite_static_bind_value, -1, 0);
+ }else if( strcmp(argv[4],"normal")==0 ){
+ rc = sqlite_bind(vm, idx, argv[3], -1, 1);
+ }else{
+ Tcl_AppendResult(interp, "4th argument should be "
+ "\"null\" or \"static\" or \"normal\"", 0);
+ return TCL_ERROR;
+ }
if( rc ){
char zBuf[50];
sprintf(zBuf, "(%d) ", rc);
@@ -887,7 +910,7 @@ 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_bind", (Tcl_CmdProc*)test_bind },
{ "sqlite_reset", (Tcl_CmdProc*)test_reset },
{ "breakpoint", (Tcl_CmdProc*)test_breakpoint },
};
@@ -900,5 +923,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){
(char*)&sqlite_search_count, TCL_LINK_INT);
Tcl_LinkVar(interp, "sqlite_open_file_count",
(char*)&sqlite_open_file_count, TCL_LINK_INT);
+ Tcl_LinkVar(interp, "sqlite_static_bind_value",
+ (char*)&sqlite_static_bind_value, TCL_LINK_STRING);
return TCL_OK;
}
diff --git a/src/tokenize.c b/src/tokenize.c
index 7a187186e..24433a07f 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.61 2003/09/06 01:10:48 drh Exp $
+** $Id: tokenize.c,v 1.62 2003/09/06 22:18:08 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -380,11 +380,9 @@ 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++){}
+ case '?': {
*tokenType = TK_VARIABLE;
- return i;
+ return 1;
}
default: {
if( !isIdChar[*z] ){
diff --git a/src/vdbe.c b/src/vdbe.c
index 305168dfc..e1f1154a4 100644
--- a/src/vdbe.c
+++ b/src/vdbe.c
@@ -43,7 +43,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.239 2003/09/06 20:12:01 drh Exp $
+** $Id: vdbe.c,v 1.240 2003/09/06 22:18:08 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -711,14 +711,17 @@ case OP_String: {
**
** 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().
+** Any occurance of the '?' character in the original SQL is considered
+** a variable. Variables in the SQL string are number from left to
+** right beginning with 1. The values of variables are set using the
+** sqlite_bind() API.
*/
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;
+ int j = pOp->p1 - 1;
+ if( j>=0 && j<p->nVar && p->azVar[j]!=0 ){
+ zStack[i] = p->azVar[j];
+ aStack[i].n = p->anVar[j];
aStack[i].flags = STK_Str | STK_Static;
}else{
zStack[i] = 0;
diff --git a/src/vdbe.h b/src/vdbe.h
index 494313dcb..87fea2517 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.67 2003/09/06 01:10:49 drh Exp $
+** $Id: vdbe.h,v 1.68 2003/09/06 22:18:08 drh Exp $
*/
#ifndef _SQLITE_VDBE_H_
#define _SQLITE_VDBE_H_
@@ -84,7 +84,7 @@ int sqliteVdbeFindOp(Vdbe*, int, int);
VdbeOp *sqliteVdbeGetOp(Vdbe*, int);
int sqliteVdbeMakeLabel(Vdbe*);
void sqliteVdbeDelete(Vdbe*);
-void sqliteVdbeMakeReady(Vdbe*,sqlite_callback,void*,int);
+void sqliteVdbeMakeReady(Vdbe*,int,sqlite_callback,void*,int);
int sqliteVdbeExec(Vdbe*);
int sqliteVdbeList(Vdbe*);
int sqliteVdbeFinalize(Vdbe*,char**);
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 20aebdb4f..d168387cd 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -235,8 +235,10 @@ 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 */
+ int nVar; /* Number of entries in azVariable[] */
+ char **azVar; /* Values for the OP_Variable opcode */
+ int *anVar; /* Length of each value in azVariable[] */
+ u8 *abVar; /* TRUE if azVariable[i] needs to be sqliteFree()ed */
char *zLine; /* A single line from the input file */
int nLineAlloc; /* Number of spaces allocated for zLine */
int magic; /* Magic number for sanity checking */
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index 9fedb8dd0..dd6737632 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -568,6 +568,7 @@ int sqliteVdbeList(
*/
void sqliteVdbeMakeReady(
Vdbe *p, /* The VDBE */
+ int nVar, /* Number of '?' see in the SQL statement */
sqlite_callback xCallback, /* Result callback */
void *pCallbackArg, /* 1st argument to xCallback() */
int isExplain /* True if the EXPLAIN keywords is present */
@@ -591,10 +592,17 @@ void sqliteVdbeMakeReady(
**
** Allocation all the stack space we will ever need.
*/
+ p->nVar = nVar>=0 ? nVar : p->nVar;
n = isExplain ? 10 : p->nOp;
- p->aStack = sqliteMalloc( n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) );
+ p->aStack = sqliteMalloc(
+ n*(sizeof(p->aStack[0]) + 2*sizeof(char*)) /* aStack and zStack */
+ + p->nVar*(sizeof(char*)+sizeof(int)+1) /* azVar, anVar, abVar */
+ );
p->zStack = (char**)&p->aStack[n];
p->azColName = (char**)&p->zStack[n];
+ p->azVar = (char**)&p->azColName[n];
+ p->anVar = (int*)&p->azVar[p->nVar];
+ p->abVar = (u8*)&p->anVar[p->nVar];
sqliteHashInit(&p->agg.hash, SQLITE_HASH_BINARY, 0);
p->agg.pSearch = 0;
@@ -740,15 +748,6 @@ static void closeAllCursors(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
@@ -808,7 +807,6 @@ static void Cleanup(Vdbe *p){
}
sqliteFree(p->zErrMsg);
p->zErrMsg = 0;
- ClearVariableArray(p);
}
/*
@@ -927,37 +925,33 @@ int sqliteVdbeFinalize(Vdbe *p, char **pzErrMsg){
**
** 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 ){
+int sqlite_bind(sqlite_vm *pVm, int i, const char *zVal, int len, int copy){
+ Vdbe *p = (Vdbe*)pVm;
+ if( p->magic!=VDBE_MAGIC_RUN || p->pc!=0 ){
return SQLITE_MISUSE;
}
- ClearVariableArray(p);
- if( nValue==0 ){
- p->nVariable = 0;
- p->azVariable = 0;
+ if( i<1 || i>p->nVar ){
+ return SQLITE_RANGE;
}
- for(i=n=0; i<nValue; i++){
- if( azValue[i] ) n += strlen(azValue[i]) + 1;
+ i--;
+ if( p->abVar[i] ){
+ sqliteFree(p->azVar[i]);
}
- p->azVariable = sqliteMalloc( sizeof(p->azVariable[0])*nValue + n );
- if( p->azVariable==0 ){
- p->nVariable = 0;
- return SQLITE_NOMEM;
+ if( zVal==0 ){
+ copy = 0;
+ len = 0;
}
- 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;
- }
+ if( len<0 ){
+ len = strlen(zVal)+1;
+ }
+ if( copy ){
+ p->azVar[i] = sqliteMalloc( len );
+ if( p->azVar[i] ) memcpy(p->azVar[i], zVal, len);
+ }else{
+ p->azVar[i] = zVal;
}
- p->nVariable = nValue;
+ p->abVar[i] = copy;
+ p->anVar[i] = len;
return SQLITE_OK;
}
@@ -988,6 +982,9 @@ void sqliteVdbeDelete(Vdbe *p){
sqliteFree(p->aOp[i].p3);
}
}
+ for(i=0; i<p->nVar; i++){
+ if( p->abVar[i] ) sqliteFree(p->azVar[i]);
+ }
sqliteFree(p->aOp);
sqliteFree(p->aLabel);
sqliteFree(p->aStack);