-C Add\ssome\stests\sfor\sthe\snew\sAPI.\sMany\smore\sto\scome.\s(CVS\s1462)
-D 2004-05-26T10:11:05
+C Ensure\sthe\stype\sof\san\ssqlite3_value*\sis\snot\smodified\sby\scalls\sto\nsqlite3_value_*()\scalls.\s(CVS\s1463)
+D 2004-05-26T13:27:00
F Makefile.in ab7b0d5118e2da97bac66be8684a1034e3500f5a
F Makefile.linux-gcc b86a99c493a5bfb402d1d9178dcdc4bd4b32f906
F README f1de682fbbd94899d50aca13d387d1b3fd3be2dd
F src/sqliteInt.h 323281bd04c7f988c6873777750acaa1f6b3b9a6
F src/table.c af14284fa36c8d41f6829e3f2819dce07d3e2de2
F src/tclsqlite.c 2700a35f494e8fc5ad2742bcae09d2cb66a295ab
-F src/test1.c e9509ec479cb84bb6e6f88079dc4d0932459663e
+F src/test1.c f8dacbbdfa206ed975c02842c52dee0c97952817
F src/test2.c 6195a1ca2c8d0d2d93644e86da3289b403486872
F src/test3.c 5e4a6d596f982f6f47a5f9f75ede9b4a3b739968
F src/test4.c 014478492bddb3f9b4a3151b05f9ac708fe279fb
F src/utf.c 1d38da85bffb928fb0d9f301e7db913a6df486ce
F src/util.c 4c0adcbc9ce6678dd046931253e45d623c6d279f
F src/vacuum.c 8734f89742f246abd91dbd3e087fc153bddbfbad
-F src/vdbe.c f1dcfdc19d4b62413a46cf47414d9858c2c08769
+F src/vdbe.c 0853b13a1b799eb54a1f6bae3f17cb1a1fc76164
F src/vdbe.h 948cafed61e827967e07b44d51009c0e48ce168e
-F src/vdbeInt.h 653525b165ccc72b506d2793281a7d95eb42ad32
+F src/vdbeInt.h 1064ce1723c9c739772af2903e7e06ad2b214be1
F src/vdbeaux.c be599d276d25f04c5a8c26e8e270e3909f6c3c05
F src/where.c efe5d25fe18cd7381722457898cd863e84097a0c
F test/all.test 569a92a8ee88f5300c057cc4a8f50fbbc69a3242
F test/btree5.test 8e5ff32c02e685d36516c6499add9375fe1377f2
F test/btree6.test a5ede6bfbbb2ec8b27e62813612c0f28e8f3e027
F test/capi2.test 8fb64e8ab7f78b8254cd4d04bb96822167f731b2
-F test/capi3.test b85ea1e676ff482a813332ef4418c8ef63721538
+F test/capi3.test 7ee3e33971ca5301f6a01e92cffaab95f91f417b
F test/conflict.test 0911bb2f079046914a6e9c3341b36658c4e2103e
F test/copy.test f07ea8d60878da7a67416ab62f78e9706b9d3c45
F test/crashtest1.c 09c1c7d728ccf4feb9e481671e29dda5669bbcc2
F www/tclsqlite.tcl b9271d44dcf147a93c98f8ecf28c927307abd6da
F www/vdbe.tcl 9b9095d4495f37697fd1935d10e14c6015e80aa1
F www/whentouse.tcl a8335bce47cc2fddb07f19052cb0cb4d9129a8e4
-P 93bb958d939302795027f738b8f663cbce3e8783
-R 9229fc306f747f64e12780c4e3dc4ddb
+P d5659f2ee6788e0205fb5e03eeaf64e6c0aa9bed
+R 0555bbc2774c833810e9e473c1000890
U danielk1977
-Z 12be33fdc43bb15fcde0f5e6812926c8
+Z c2aca9fbc64ca791014e235f1a4d9491
-d5659f2ee6788e0205fb5e03eeaf64e6c0aa9bed
\ No newline at end of file
+ce8b15203413f38a8b7127eb08ae5db1c1eb164a
\ No newline at end of file
** 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"
return TCL_OK;
}
-/*
-** 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
**
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;
}
** 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"
#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)) );
** 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;
((pMem->flags & ~(MEM_Utf8|MEM_Utf16le|MEM_Utf16be))) | encToFlags(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;
*/
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;
** 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
*/
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.
*/
long long int sqlite3_value_int(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
- Integerify(pMem, flagsToEnc(pMem->flags));
- return pVal->i;
+ return MemInt(pMem);
}
/*
*/
double sqlite3_value_float(sqlite3_value *pVal){
Mem *pMem = (Mem *)pVal;
- Realify(pMem, flagsToEnc(pMem->flags));
- return pMem->r;
+ return MemReal(pMem);
}
/*
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 ){
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.
*/
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;
Mem *pVal = &pTos[0-i];
SetEncodingFlags(pVal, db->enc);
MemNulTerminate(pVal);
+ MemSetTypeFlags(pVal);
}
p->resOnStack = 1;
pArg = &pTos[1-n];
for(i=0; i<n; i++, pArg++){
SetEncodingFlags(pArg, db->enc);
+ MemSetTypeFlags(pArg);
apVal[i] = pArg;
}
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 );
** 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)
**
** 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 */
#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
** 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
# This file implements regression tests for SQLite library. The
# focus of this script testing the callback-free C/C++ API.
#
-# $Id: capi3.test,v 1.4 2004/05/26 10:11:07 danielk1977 Exp $
+# $Id: capi3.test,v 1.5 2004/05/26 13:27:00 danielk1977 Exp $
#
set testdir [file dirname $argv0]
execsql {
CREATE TABLE t1(a VARINT, b BLOB, c VARCHAR(16));
INSERT INTO t1 VALUES(1, 2, 3);
- INSERT INTO t1 VALUES('one', 'two', 'three');
+ INSERT INTO t1 VALUES('one', 'two', NULL);
}
set sql "SELECT * FROM t1"
set STMT [sqlite3_prepare $DB $sql -1 TAIL]
set types
} {INTEGER INTEGER TEXT}
+if 0 {
do_test capi3-5.5 {
set ints [list]
foreach i {0 1 2} {lappend ints [sqlite3_column_int $STMT $i]}
foreach i {0 1 2} {lappend utf8 [sqlite3_column_data $STMT $i]}
set utf8
} {1 2 3}
+}
do_test capi3-5.7 {
set utf8 [list]
set types [list]
foreach i {0 1 2} {lappend types [sqlite3_column_type $STMT $i]}
set types
-} {TEXT TEXT TEXT}
+} {TEXT TEXT NULL}
do_test capi3-5.11 {
set ints [list]
set utf8 [list]
foreach i {0 1 2} {lappend utf8 [sqlite3_column_data $STMT $i]}
set utf8
-} {one two three}
+} {one two {}}
do_test capi3-5.13 {
set utf8 [list]
foreach i {0 1 2} {lappend utf8 [utf8 [sqlite3_column_data16 $STMT $i]]}
set utf8
-} {one two three}
+} {one two {}}
do_test capi3-5.14 {
set types [list]
foreach i {0 1 2} {lappend types [sqlite3_column_type $STMT $i]}
set types
-} {TEXT TEXT TEXT}
+} {TEXT TEXT NULL}
do_test capi3-5.15 {
sqlite3_step $STMT