diff --git a/manifest b/manifest index 6a016cad96..8b2e0a14f3 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Cache\sthe\slocation\sof\soverflow\spages\sin\scursors\sused\sfor\sincremental\sblob\sIO.\s(CVS\s3899) -D 2007-05-02T16:48:37 +C More\sfixes\sand\simprovements\sto\sthe\szeroblob()\smechanism.\s(CVS\s3900) +D 2007-05-02T16:51:59 F Makefile.in 8cab54f7c9f5af8f22fd97ddf1ecfd1e1860de62 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028 @@ -102,7 +102,7 @@ F src/sqlite3ext.h 7d0d363ea7327e817ef0dfe1b7eee1f171b72890 F src/sqliteInt.h 0b14d0eae083aafca0562d2261a404e5e5abc5f0 F src/table.c 6d0da66dde26ee75614ed8f584a1996467088d06 F src/tclsqlite.c 23082fa8affdf3ae73937ca0755754fc562674bc -F src/test1.c bf70db366aa28b813810f63fc48fec424034502d +F src/test1.c 29a39fdde51f4612082ecf3f5af54dac93766f87 F src/test2.c 24458b17ab2f3c90cbc1c8446bd7ffe69be62f88 F src/test3.c 946ea9d1a8c928656e3c70f0a2fcb8e733a15e86 F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25 @@ -125,7 +125,7 @@ F src/update.c 3359041db390a8f856d67272f299600e2104f350 F src/utf.c e64a48bc21aa973eb622dd47da87d56a4cdcf528 F src/util.c b6344325378e75b9e18175d8b6aed1723d73dad9 F src/vacuum.c 8bd895d29e7074e78d4e80f948e35ddc9cf2beef -F src/vdbe.c bb1baa9a357b14f28ddfd0a896f60c6ef82dfd33 +F src/vdbe.c a4abf744b5376372a9be30f02ab4b231f353cab1 F src/vdbe.h 0025259af1939fb264a545816c69e4b5b8d52691 F src/vdbeInt.h cb02cbbceddf3b40d49012e9f41576f17bcbec97 F src/vdbeapi.c 37d793559390bec8a00c556f651f21b5f9e589af @@ -395,7 +395,7 @@ F test/where.test 1d020f50c77f37b2dbab9766ca959e6e3278ecdb F test/where2.test 3249d426b3fc7a106713d784e1628307fc308d2e F test/where3.test 0a30fe9808b0fa01c46d0fcf4fac0bf6cf75bb30 F test/where4.test b68496500bff496e83e76ae4ffb493b99064eac6 -F test/zeroblob.test 76efa0e1b8116037e009b38a060033ea77526437 +F test/zeroblob.test 547d46fd17a574d4d6f1dcea5fce4c4929e165bc F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b F tool/fragck.tcl 5265a95126abcf6ab357f7efa544787e5963f439 F tool/lemon.c c8c8b25ab1ac8156b3ad83ba4ea1bf00d5e07f5a @@ -471,7 +471,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b F www/whentouse.tcl fc46eae081251c3c181bd79c5faef8195d7991a5 -P 4dbbfff4a7d4be197aac19c80400dafe10dd5e58 -R c0b16184c9579452ff42a74fabe3dca1 -U danielk1977 -Z 7dadee4977fc90359d0189698014dc76 +P 349f1ea7895f06c40affc985a13aa6686dfdea07 +R c40994429188bdd3545336b5231dc204 +U drh +Z 278e5bf758bcf3f514d6f2d4595a443f diff --git a/manifest.uuid b/manifest.uuid index 0ed0535473..ad61868214 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -349f1ea7895f06c40affc985a13aa6686dfdea07 \ No newline at end of file +83ab25014e890b1cc6ea08ca1ebeeee0078da466 \ No newline at end of file diff --git a/src/test1.c b/src/test1.c index 409f4c2124..43e85bb731 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.241 2007/05/02 01:34:31 drh Exp $ +** $Id: test1.c,v 1.242 2007/05/02 16:51:59 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" @@ -4349,6 +4349,7 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite3_open_file_count; extern int sqlite3_sort_count; extern int sqlite3_current_time; + extern int sqlite3_max_blobsize; static struct { char *zName; Tcl_CmdProc *xProc; @@ -4542,6 +4543,8 @@ int Sqlitetest1_Init(Tcl_Interp *interp){ (char*)&sqlite3_search_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_sort_count", (char*)&sqlite3_sort_count, TCL_LINK_INT); + Tcl_LinkVar(interp, "sqlite3_max_blobsize", + (char*)&sqlite3_max_blobsize, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_like_count", (char*)&sqlite3_like_count, TCL_LINK_INT); Tcl_LinkVar(interp, "sqlite_interrupt_count", diff --git a/src/vdbe.c b/src/vdbe.c index 072375ac1c..12aedc51b1 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.604 2007/05/02 13:30:27 drh Exp $ +** $Id: vdbe.c,v 1.605 2007/05/02 16:51:59 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -84,6 +84,17 @@ int sqlite3_interrupt_count = 0; int sqlite3_sort_count = 0; #endif +/* +** The next global variable records the size of the largest MEM_Blob +** or MEM_Str that has appeared on the VDBE stack. The test procedures +** use this information to make sure that the zero-blob functionality +** is working correctly. This variable has no function other than to +** help verify the correct operation of the library. +*/ +#ifdef SQLITE_TEST +int sqlite3_max_blobsize = 0; +#endif + /* ** Release the memory associated with the given stack level. This ** leaves the Mem.flags field in an inconsistent state. @@ -1633,6 +1644,8 @@ case OP_Ge: { /* same as TK_GE, no-push */ } assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 ); + sqlite3VdbeMemExpandBlob(pNos); + sqlite3VdbeMemExpandBlob(pTos); res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3); switch( pOp->opcode ){ case OP_Eq: res = res==0; break; @@ -2223,6 +2236,7 @@ case OP_MakeRecord: { ** out how much space is required for the new record. */ for(pRec=pData0; pRec<=pTos; pRec++){ + int len; if( zAffinity ){ applyAffinity(pRec, zAffinity[pRec-pData0], encoding); } @@ -2230,14 +2244,15 @@ case OP_MakeRecord: { containsNull = 1; } serial_type = sqlite3VdbeSerialType(pRec, file_format); - nData += sqlite3VdbeSerialTypeLen(serial_type); + len = sqlite3VdbeSerialTypeLen(serial_type); + nData += len; nHdr += sqlite3VarintLen(serial_type); if( pRec->flags & MEM_Zero ){ /* Only pure zero-filled BLOBs can be input to this Opcode. ** We do not allow blobs with a prefix and a zero-filled tail. */ assert( pRec->n==0 ); nZero += pRec->u.i; - }else{ + }else if( len ){ nZero = 0; } } @@ -2877,7 +2892,7 @@ case OP_MoveGt: { /* no-push */ pC->rowidIsValid = res==0; }else{ assert( pTos->flags & MEM_Blob ); - /* Stringify(pTos, encoding); */ + sqlite3VdbeMemExpandBlob(pTos); rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); if( rc!=SQLITE_OK ){ goto abort_due_to_error; @@ -2984,6 +2999,7 @@ case OP_Found: { /* no-push */ if( (pC = p->apCsr[i])->pCursor!=0 ){ int res, rx; assert( pC->isTable==0 ); + assert( pTos->flags & MEM_Blob ); Stringify(pTos, encoding); rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res); alreadyExists = rx==SQLITE_OK && res==0; @@ -3051,6 +3067,7 @@ case OP_IsUnique: { /* no-push */ /* Make sure K is a string and make zKey point to K */ + assert( pNos->flags & MEM_Blob ); Stringify(pNos, encoding); zKey = pNos->z; nKey = pNos->n; @@ -3902,9 +3919,9 @@ case OP_IdxGE: { /* no-push */ if( (pC = p->apCsr[i])->pCursor!=0 ){ int res; - assert( pTos->flags & MEM_Blob ); /* Created using OP_Make*Key */ - Stringify(pTos, encoding); + assert( pTos->flags & MEM_Blob ); /* Created using OP_MakeRecord */ assert( pC->deferredMoveto==0 ); + sqlite3VdbeMemExpandBlob(pTos); *pC->pIncrKey = pOp->p3!=0; assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT ); rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res); @@ -4982,6 +4999,16 @@ default: { } #endif +#ifdef SQLITE_TEST + /* Keep track of the size of the largest BLOB or STR that has appeared + ** on the top of the VDBE stack. + */ + if( pTos>=p->aStack && (pTos->flags & (MEM_Blob|MEM_Str))!=0 + && pTos->n>sqlite3_max_blobsize ){ + sqlite3_max_blobsize = pTos->n; + } +#endif + /* The following code adds nothing to the actual functionality ** of the program. It is only here for testing and debugging. ** On the other hand, it does burn CPU cycles every time through @@ -4998,6 +5025,7 @@ default: { } assert( pc>=-1 && pcnOp ); #ifdef SQLITE_DEBUG + /* Code for tracing the vdbe stack. */ if( p->trace && pTos>=p->aStack ){ int i; diff --git a/test/zeroblob.test b/test/zeroblob.test index 07ac0d7b9a..d797f9d899 100644 --- a/test/zeroblob.test +++ b/test/zeroblob.test @@ -13,46 +13,107 @@ # including the sqlite3_bind_zeroblob(), sqlite3_result_zeroblob(), # and the built-in zeroblob() SQL function. # -# $Id: zeroblob.test,v 1.1 2007/05/02 13:30:27 drh Exp $ +# $Id: zeroblob.test,v 1.2 2007/05/02 16:51:59 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl -# Create the database +# When zeroblob() is used for the last field of a column, then the +# content of the zeroblob is never instantiated on the VDBE stack. +# But it does get inserted into the database correctly. # do_test zeroblob-1.1 { execsql { CREATE TABLE t1(a,b,c,d); - INSERT INTO t1 VALUES(1,2,3,zeroblob(10000)); - SELECT count(*) FROM t1; } -} {1} + set ::sqlite3_max_blobsize 0 + execsql { + INSERT INTO t1 VALUES(2,3,4,zeroblob(10000)); + } + set ::sqlite3_max_blobsize +} {10} do_test zeroblob-1.2 { execsql { SELECT length(d) FROM t1 } } {10000} + +# If a non-NULL column follows the zeroblob, then the content of +# the zeroblob must be instantiated. +# do_test zeroblob-1.3 { + set ::sqlite3_max_blobsize 0 execsql { - INSERT INTO t1 VALUES(2,3,zeroblob(10000),4); - SELECT count(*) FROM t1; + INSERT INTO t1 VALUES(3,4,zeroblob(10000),5); } -} {2} + set ::sqlite3_max_blobsize +} {10010} do_test zeroblob-1.4 { execsql { SELECT length(c), length(d) FROM t1 } } {1 10000 10000 1} + +# Multiple zeroblobs can appear at the end of record. No instantiation +# of the blob content occurs on the stack. +# do_test zeroblob-1.5 { + set ::sqlite3_max_blobsize 0 execsql { - INSERT INTO t1 VALUES(3,4,zeroblob(10000),zeroblob(10000)); - SELECT count(*) FROM t1; + INSERT INTO t1 VALUES(4,5,zeroblob(10000),zeroblob(10000)); } -} {3} + set ::sqlite3_max_blobsize +} {11} do_test zeroblob-1.6 { execsql { SELECT length(c), length(d) FROM t1 } } {1 10000 10000 1 10000 10000} +# NULLs can follow the zeroblob() or be intermixed with zeroblobs and +# no instantiation of the zeroblobs occurs on the stack. +# +do_test zeroblob-1.7 { + set ::sqlite3_max_blobsize 0 + execsql { + INSERT INTO t1 VALUES(5,zeroblob(10000),NULL,zeroblob(10000)); + } + set ::sqlite3_max_blobsize +} {10} +do_test zeroblob-1.8 { + execsql { + SELECT length(b), length(d) FROM t1 WHERE a=5 + } +} {10000 10000} + +# Comparisons against zeroblobs work. +# +do_test zeroblob-2.1 { + execsql { + SELECT a FROM t1 WHERE b=zeroblob(10000) + } +} {5} + +# Comparisons against zeroblobs work even when indexed. +# +do_test zeroblob-2.2 { + execsql { + CREATE INDEX i1_1 ON t1(b); + SELECT a FROM t1 WHERE b=zeroblob(10000); + } +} {5} + +# DISTINCT works for zeroblobs +# +do_test zeroblob-3.1 { + execsql { + SELECT count(DISTINCT a) FROM ( + SELECT x'00000000000000000000' AS a + UNION ALL + SELECT zeroblob(10) AS a + ) + } +} {1} + + finish_test