]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
More fixes and improvements to the zeroblob() mechanism. (CVS 3900)
authordrh <drh@noemail.net>
Wed, 2 May 2007 16:51:59 +0000 (16:51 +0000)
committerdrh <drh@noemail.net>
Wed, 2 May 2007 16:51:59 +0000 (16:51 +0000)
FossilOrigin-Name: 83ab25014e890b1cc6ea08ca1ebeeee0078da466

manifest
manifest.uuid
src/test1.c
src/vdbe.c
test/zeroblob.test

index 6a016cad960104da4b6ff9e934c98530905163be..8b2e0a14f3461b12a0c268555964b2f6d4d58809 100644 (file)
--- 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
index 0ed05354738643d9a28c0e545552123be4c0f07f..ad618682141934d92772c37e1d7de64f75b2b4af 100644 (file)
@@ -1 +1 @@
-349f1ea7895f06c40affc985a13aa6686dfdea07
\ No newline at end of file
+83ab25014e890b1cc6ea08ca1ebeeee0078da466
\ No newline at end of file
index 409f4c212445b544c556d69501db9f137e7137c1..43e85bb73193de10d38b3eacfd482c4c0fe98640 100644 (file)
@@ -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", 
index 072375ac1c9d1ef7345ee063f7cd067345618cc6..12aedc51b1e831d2a95dacd2db757488f14d27fa 100644 (file)
@@ -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 && pc<p->nOp );
 #ifdef SQLITE_DEBUG
+
     /* Code for tracing the vdbe stack. */
     if( p->trace && pTos>=p->aStack ){
       int i;
index 07ac0d7b9aa7dbf94302d1eec5ed095055839e5c..d797f9d899549c249b24ca6b043009fa1449f05b 100644 (file)
 # 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