aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/test1.c28
-rw-r--r--src/vdbe.c141
-rw-r--r--src/vdbeInt.h63
3 files changed, 119 insertions, 113 deletions
diff --git a/src/test1.c b/src/test1.c
index 0d3823c09..e695cce5f 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.57 2004/05/26 10:11:06 danielk1977 Exp $
+** $Id: test1.c,v 1.58 2004/05/26 13:27:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
@@ -696,30 +696,6 @@ static int test_register_func(
}
/*
-** This SQLite callback records the datatype of all columns.
-**
-** The pArg argument is really a pointer to a TCL interpreter. The
-** column names are inserted as the result of this interpreter.
-**
-** This routine returns non-zero which causes the query to abort.
-*/
-static int rememberDataTypes(void *pArg, int nCol, char **argv, char **colv){
- int i;
- Tcl_Interp *interp = (Tcl_Interp*)pArg;
- Tcl_Obj *pList, *pElem;
- if( colv[nCol+1]==0 ){
- return 1;
- }
- pList = Tcl_NewObj();
- for(i=0; i<nCol; i++){
- pElem = Tcl_NewStringObj(colv[i+nCol] ? colv[i+nCol] : "NULL", -1);
- Tcl_ListObjAppendElement(interp, pList, pElem);
- }
- Tcl_SetObjResult(interp, pList);
- return 1;
-}
-
-/*
** Usage: sqlite3_finalize STMT
**
** Finalize a statement handle.
@@ -742,7 +718,7 @@ static int test_finalize(
if( getStmtPointer(interp, Tcl_GetString(objv[1]), &pStmt) ) return TCL_ERROR;
rc = sqlite3_finalize(pStmt);
- Tcl_SetResult(interp, errorName(rc), TCL_STATIC);
+ Tcl_SetResult(interp, (char *)errorName(rc), TCL_STATIC);
if( rc ){
return TCL_ERROR;
}
diff --git a/src/vdbe.c b/src/vdbe.c
index 3b1d5d060..7cc4288b0 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.333 2004/05/26 10:11:06 danielk1977 Exp $
+** $Id: vdbe.c,v 1.334 2004/05/26 13:27:00 danielk1977 Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -95,7 +95,7 @@ int sqlite3_interrupt_count = 0;
#define MemIsNull(p) ((p)->flags&Mem_Null)
#define MemIsBlob(p) ((p)->flags&Mem_Blob)
#define MemIsStr(p) ((p)->flags&(MEM_Int|MEM_Real|MEM_Str))
-#define MemIsInt(p) ((p)->flags&MEM_Int || hardMemIsInt(p))
+#define MemIsInt(p) ((p)->flags&(MEM_Int|MEM_Real) || hardMemIsInt(p))
#define MemIsReal(p) ((p)->flags&(MEM_Int|MEM_Real) || hardMemIsReal(p))
static int hardMemIsInt(Mem *p){
assert( !(p->flags&(MEM_Int|MEM_Real)) );
@@ -127,7 +127,7 @@ static int hardMemIsReal(Mem *p){
** they may cache the integer or real value cast of the value.
*/
#define MemInt(p) (((p)->flags&MEM_Int)?(p)->i:hardMemInt(p))
-#define MemReal(p) (((p)->flags&MEM_Real)?(p)->i:hardMemReal(p))
+#define MemReal(p) (((p)->flags&MEM_Real)?(p)->r:hardMemReal(p))
static i64 hardMemInt(Mem *p){
assert( !(p->flags&MEM_Int) );
if( !MemIsInt(p) ) return 0;
@@ -240,11 +240,23 @@ static int encToFlags(u8 enc){
static int SetEncoding(Mem*, int);
/*
+** Set the MEM_TypeStr, MEM_TypeReal or MEM_TypeInt flags in pMem if
+** required.
+*/
+static void MemSetTypeFlags(Mem *pMem){
+ int f = pMem->flags;
+ if( f&MEM_Int ) pMem->flags |= MEM_TypeInt;
+ else if( f&MEM_Real ) pMem->flags |= MEM_TypeReal;
+ else if( f&MEM_Str ) pMem->flags |= MEM_TypeStr;
+}
+
+
+/*
** Convert the given stack entity into a string if it isn't one
** already. Return non-zero if a malloc() fails.
*/
#define Stringify(P, enc) \
-(!((P)->flags&(MEM_Str|MEM_Blob)) && hardStringify(P, enc))
+if( !((P)->flags&(MEM_Str|MEM_Blob)) ) hardStringify(P, enc);
static int hardStringify(Mem *pStack, u8 enc){
int rc = SQLITE_OK;
int fg = pStack->flags;
@@ -377,7 +389,9 @@ int SetEncoding(Mem *pMem, int flags){
*/
pMem->z = z;
pMem->n = n;
- pMem->flags = (MEM_Str | MEM_Dyn | MEM_Term | flags);
+ pMem->flags &= ~(MEM_Utf8|MEM_Utf16le|MEM_Utf16be);
+ pMem->flags &= ~(MEM_Static|MEM_Short|MEM_Ephem);
+ pMem->flags |= (MEM_Dyn|MEM_Term|flags);
}else{
/* Must be translating between UTF-16le and UTF-16be. */
int i;
@@ -575,44 +589,34 @@ const unsigned char *sqlite3_column_data(sqlite3_stmt *pStmt, int i){
** is returned.
*/
const unsigned char *sqlite3_value_data(sqlite3_value *pVal){
- if( pVal->flags&MEM_Null ){
+ int flags = pVal->flags;
+
+ if( flags&MEM_Null ){
/* For a NULL return a NULL Pointer */
return 0;
}
- if( pVal->flags&MEM_Str ){
+ if( flags&MEM_Str ){
/* If there is already a string representation, make sure it is in
** encoded in UTF-8.
*/
SetEncoding(pVal, MEM_Utf8|MEM_Term);
- }else if( !(pVal->flags&MEM_Blob) ){
- /* Otherwise, unless this is a blob, convert it to a UTF-8 string */
- Stringify(pVal, TEXT_Utf8);
+ }else if( !(flags&MEM_Blob) ){
+ if( flags&MEM_Int ){
+ sqlite3_snprintf(NBFS, pVal->zShort, "%lld", pVal->i);
+ }else{
+ assert( flags&MEM_Real );
+ sqlite3_snprintf(NBFS, pVal->zShort, "%.15g", pVal->r);
+ }
+ pVal->z = pVal->zShort;
+ pVal->n = strlen(pVal->z)+1;
+ pVal->flags |= (MEM_Str|MEM_Short);
}
return pVal->z;
}
/*
-** Return the value of the 'i'th column of the current row of the currently
-** executing statement pStmt.
-*/
-const void *sqlite3_column_data16(sqlite3_stmt *pStmt, int i){
- int vals;
- Vdbe *pVm = (Vdbe *)pStmt;
- Mem *pVal;
-
- vals = sqlite3_data_count(pStmt);
- if( i>=vals || i<0 ){
- sqlite3Error(pVm->db, SQLITE_RANGE, 0);
- return 0;
- }
-
- pVal = &pVm->pTos[(1-vals)+i];
- return sqlite3_value_data16((sqlite3_value *)pVal);
-}
-
-/*
** pVal is a Mem* cast to an sqlite_value* value. Return a pointer to
** the nul terminated UTF-16 string representation if the value is
** not a blob or NULL. If the value is a blob, then just return a pointer
@@ -641,14 +645,33 @@ const void *sqlite3_value_data16(sqlite3_value* pVal){
*/
SetEncoding(pVal, encToFlags(TEXT_Utf16)|MEM_Term);
}else if( !(pVal->flags&MEM_Blob) ){
- /* Otherwise, unless this is a blob, convert it to a UTF-16 string */
- Stringify(pVal, TEXT_Utf16);
+ sqlite3_value_data(pVal);
+ SetEncoding(pVal, encToFlags(TEXT_Utf16)|MEM_Term);
}
return (const void *)(pVal->z);
}
/*
+** Return the value of the 'i'th column of the current row of the currently
+** executing statement pStmt.
+*/
+const void *sqlite3_column_data16(sqlite3_stmt *pStmt, int i){
+ int vals;
+ Vdbe *pVm = (Vdbe *)pStmt;
+ Mem *pVal;
+
+ vals = sqlite3_data_count(pStmt);
+ if( i>=vals || i<0 ){
+ sqlite3Error(pVm->db, SQLITE_RANGE, 0);
+ return 0;
+ }
+
+ pVal = &pVm->pTos[(1-vals)+i];
+ return sqlite3_value_data16((sqlite3_value *)pVal);
+}
+
+/*
** Return the number of bytes of data that will be returned by the
** equivalent sqlite3_value_data() call.
*/
@@ -676,8 +699,7 @@ int sqlite3_value_bytes16(sqlite3_value *pVal){
*/
long long int sqlite3_value_int(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
- Integerify(pMem, flagsToEnc(pMem->flags));
- return pVal->i;
+ return MemInt(pMem);
}
/*
@@ -686,8 +708,7 @@ long long int sqlite3_value_int(sqlite3_value *pVal){
*/
double sqlite3_value_float(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
- Realify(pMem, flagsToEnc(pMem->flags));
- return pMem->r;
+ return MemReal(pMem);
}
/*
@@ -799,13 +820,13 @@ int sqlite3_value_type(sqlite3_value* pVal){
if( f&MEM_Null ){
return SQLITE3_NULL;
}
- if( f&MEM_Int ){
+ if( f&MEM_TypeInt ){
return SQLITE3_INTEGER;
}
- if( f&MEM_Real ){
+ if( f&MEM_TypeReal ){
return SQLITE3_FLOAT;
}
- if( f&MEM_Str ){
+ if( f&MEM_TypeStr ){
return SQLITE3_TEXT;
}
if( f&MEM_Blob ){
@@ -1772,6 +1793,16 @@ case OP_String: {
pTos++;
pTos->flags = 0;
+ if( z ){
+ /* FIX ME: For now the code in expr.c always puts UTF-8 in P3. It
+ ** should transform text to the native encoding before doing so.
+ */
+ MemSetStr(pTos, z, -1, TEXT_Utf8, 0);
+ SetEncoding(pTos, encToFlags(db->enc)|MEM_Term);
+ }else if( op==OP_String ){
+ pTos->flags = MEM_Null;
+ }
+
/* If this is an OP_Real or OP_Integer opcode, set the pTos->r or pTos->i
** values respectively.
*/
@@ -1779,34 +1810,13 @@ case OP_String: {
assert( z );
assert( sqlite3IsNumber(z, 0, TEXT_Utf8) );
pTos->r = sqlite3AtoF(z, 0);
- pTos->flags = MEM_Real;
+ pTos->flags |= MEM_Real;
}else if( op==OP_Integer ){
- pTos->flags = MEM_Int;
pTos->i = pOp->p1;
if( pTos->i==0 && pOp->p3 ){
- sqlite3GetInt64(pOp->p3, &pTos->i);
+ sqlite3GetInt64(z, &pTos->i);
}
- }
-
- if( z ){
- /* FIX ME: For now the code in expr.c always puts UTF-8 in P3. It
- ** should transform text to the native encoding before doing so.
- */
- if( db->enc!=TEXT_Utf8 ){
- rc = sqlite3utfTranslate(z, -1, TEXT_Utf8, (void **)&pTos->z,
- &pTos->n, db->enc);
- if( rc!=SQLITE_OK ){
- assert( !pTos->z );
- goto abort_due_to_error;
- }
- pTos->flags |= MEM_Str | MEM_Dyn | MEM_Term;
- }else{
- pTos->z = z;
- pTos->n = strlen(z) + 1;
- pTos->flags |= MEM_Str | MEM_Static | MEM_Term;
- }
- }else if( op==OP_String ){
- pTos->flags = MEM_Null;
+ pTos->flags |= MEM_Int;
}
break;
@@ -2027,6 +2037,7 @@ case OP_Callback: {
Mem *pVal = &pTos[0-i];
SetEncodingFlags(pVal, db->enc);
MemNulTerminate(pVal);
+ MemSetTypeFlags(pVal);
}
p->resOnStack = 1;
@@ -2277,6 +2288,7 @@ case OP_Function: {
pArg = &pTos[1-n];
for(i=0; i<n; i++, pArg++){
SetEncodingFlags(pArg, db->enc);
+ MemSetTypeFlags(pArg);
apVal[i] = pArg;
}
@@ -5624,8 +5636,9 @@ case OP_AggFunc: {
assert( apVal || n==0 );
for(i=0; i<n; i++, pRec++){
- apVal[i] = pRec;
- SetEncodingFlags(pRec, db->enc);
+ apVal[i] = pRec;
+ SetEncodingFlags(pRec, db->enc);
+ MemSetTypeFlags(pRec);
}
i = pTos->i;
assert( i>=0 && i<p->agg.nMem );
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index e1f5b4e9b..733b333f6 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -144,7 +144,7 @@ typedef struct Mem Mem;
** MemSetNull - Set the value to NULL.
** MemSetInt - Set the value to an integer.
** MemSetReal - Set the value to a real.
-** MemSetStr - Set the value to a string.
+** MemSetStr - Set the value to a string (or blob if enc==0).
*/
#define MemSetNull(p) sqlite3VdbeMemSetNull(p)
#define MemSetInt(p,v) sqlite3VdbeMemSetInt(p,v)
@@ -159,22 +159,21 @@ typedef struct Mem Mem;
**
** Non-zero is returned if a malloc() fails.
*/
-#define MemNulTerminate(p) ( \
- ((p)->flags&MEM_Str) && \
- !((p)->flags&MEM_Term) && \
- sqlite3VdbeMemNulTerminate(p) )
+#define MemNulTerminate(p) \
+if( ((p)->flags&MEM_Str) && !((p)->flags&MEM_Term) ) sqlite3VdbeMemNulTerminate(p);
-/*
-** Allowed values for Mem.flags.
-**
-** The first 5 values determine the data type(s). Null and Blob must
-** occur alone. But Str, Int, and Real can occur together.
+/* One or more of the following flags are set to indicate the valid
+** representations of the value stored in the Mem struct.
**
-** The next 3 utf entries determine the text representation for strings.
-** These values are only meaningful if the type is Str.
+** If the MEM_Null flag is set, then the value is an SQL NULL value.
+** No other flags may be set in this case.
**
-** The last 4 values specify what kind of memory Mem.z points to.
-** These valus are only meaningful if the Str or Blob types are used.
+** If the MEM_Str flag is set then Mem.z points at a string representation.
+** Usually this is encoded in the same unicode encoding as the main
+** database (see below for exceptions). If the MEM_Term flag is also
+** set, then the string is nul terminated. The MEM_Int and MEM_Real
+** flags may coexist with the MEM_Str flag.
+**
*/
#define MEM_Null 0x0001 /* Value is NULL */
#define MEM_Str 0x0002 /* Value is a string */
@@ -182,12 +181,30 @@ typedef struct Mem Mem;
#define MEM_Real 0x0008 /* Value is a real number */
#define MEM_Blob 0x0010 /* Value is a BLOB */
-#define MEM_Term 0x0200 /* String has a nul terminator character */
+#define MEM_Term 0x0100 /* String rep is nul terminated */
+
+/* Values with type NULL or BLOB can have only one representation. But
+** values with a manifest type of REAL, INTEGER or STRING may have one
+** or more representation cached in the Mem struct at any one time. The
+** flags MEM_IntVal, MEM_RealVal and MEM_StrVal are true whenever the real,
+** integer or string representation stored in a Mem struct is valid.
+**
+** When MEM_StrVal is set, then MEM_Term may also be set. This indicates
+** that the string is terminated with a nul-terminator character.
+*/
+#define MEM_TypeInt 0x0020 /* Value type is an integer */
+#define MEM_TypeReal 0x0040 /* Value type is real */
+#define MEM_TypeStr 0x0080 /* Value type is string */
-#define MEM_Dyn 0x0400 /* Need to call sqliteFree() on Mem.z */
-#define MEM_Static 0x0800 /* Mem.z points to a static string */
-#define MEM_Ephem 0x1000 /* Mem.z points to an ephemeral string */
-#define MEM_Short 0x2000 /* Mem.z points to Mem.zShort */
+
+/* Whenever Mem contains a valid string or blob representation, one of
+** the following flags must be set to determine the memory management
+** policy for Mem.z
+*/
+#define MEM_Dyn 0x0200 /* Need to call sqliteFree() on Mem.z */
+#define MEM_Static 0x0400 /* Mem.z points to a static string */
+#define MEM_Ephem 0x0800 /* Mem.z points to an ephemeral string */
+#define MEM_Short 0x1000 /* Mem.z points to Mem.zShort */
/* Internally, all strings manipulated by the VDBE are encoded using the
** native encoding for the main database. Therefore the following three
@@ -214,15 +231,15 @@ typedef struct Mem Mem;
** sqlite3_column_data() or sqlite3_column_data16(). If this occurs, then
** the MEM_Utf* flags are updated accordingly.
*/
-#define MEM_Utf8 0x0040 /* String uses UTF-8 encoding */
-#define MEM_Utf16be 0x0080 /* String uses UTF-16 big-endian */
-#define MEM_Utf16le 0x0100 /* String uses UTF-16 little-endian */
+#define MEM_Utf8 0x2000 /* String uses UTF-8 encoding */
+#define MEM_Utf16be 0x4000 /* String uses UTF-16 big-endian */
+#define MEM_Utf16le 0x8000 /* String uses UTF-16 little-endian */
/* The following MEM_ value appears only in AggElem.aMem.s.flag fields.
** It indicates that the corresponding AggElem.aMem.z points to a
** aggregate function context that needs to be finalized.
*/
-#define MEM_AggCtx 0x4000 /* Mem.z points to an agg function context */
+#define MEM_AggCtx 0x10000 /* Mem.z points to an agg function context */
/*
** The "context" argument for a installable function. A pointer to an