/ Check-in [83ab2501]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:More fixes and improvements to the zeroblob() mechanism. (CVS 3900)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:83ab25014e890b1cc6ea08ca1ebeeee0078da466
User & Date: drh 2007-05-02 16:51:59
Context
2007-05-02
17:48
Combine the internal btree functions BtreePutData() and getPayload(). (CVS 3901) check-in: a100a530 user: danielk1977 tags: trunk
16:51
More fixes and improvements to the zeroblob() mechanism. (CVS 3900) check-in: 83ab2501 user: drh tags: trunk
16:48
Cache the location of overflow pages in cursors used for incremental blob IO. (CVS 3899) check-in: 349f1ea7 user: danielk1977 tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/test1.c.

     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Code for testing all sorts of SQLite interfaces.  This code
    13     13   ** is not included in the SQLite library.  It is used for automated
    14     14   ** testing of the SQLite library.
    15     15   **
    16         -** $Id: test1.c,v 1.241 2007/05/02 01:34:31 drh Exp $
           16  +** $Id: test1.c,v 1.242 2007/05/02 16:51:59 drh Exp $
    17     17   */
    18     18   #include "sqliteInt.h"
    19     19   #include "tcl.h"
    20     20   #include "os.h"
    21     21   #include <stdlib.h>
    22     22   #include <string.h>
    23     23   
................................................................................
  4345   4345   */
  4346   4346   int Sqlitetest1_Init(Tcl_Interp *interp){
  4347   4347     extern int sqlite3_search_count;
  4348   4348     extern int sqlite3_interrupt_count;
  4349   4349     extern int sqlite3_open_file_count;
  4350   4350     extern int sqlite3_sort_count;
  4351   4351     extern int sqlite3_current_time;
         4352  +  extern int sqlite3_max_blobsize;
  4352   4353     static struct {
  4353   4354        char *zName;
  4354   4355        Tcl_CmdProc *xProc;
  4355   4356     } aCmd[] = {
  4356   4357        { "sqlite3_mprintf_int",           (Tcl_CmdProc*)sqlite3_mprintf_int    },
  4357   4358        { "sqlite3_mprintf_int64",         (Tcl_CmdProc*)sqlite3_mprintf_int64  },
  4358   4359        { "sqlite3_mprintf_str",           (Tcl_CmdProc*)sqlite3_mprintf_str    },
................................................................................
  4538   4539       Tcl_CreateObjCommand(interp, aObjCmd[i].zName, 
  4539   4540           aObjCmd[i].xProc, aObjCmd[i].clientData, 0);
  4540   4541     }
  4541   4542     Tcl_LinkVar(interp, "sqlite_search_count", 
  4542   4543         (char*)&sqlite3_search_count, TCL_LINK_INT);
  4543   4544     Tcl_LinkVar(interp, "sqlite_sort_count", 
  4544   4545         (char*)&sqlite3_sort_count, TCL_LINK_INT);
         4546  +  Tcl_LinkVar(interp, "sqlite3_max_blobsize", 
         4547  +      (char*)&sqlite3_max_blobsize, TCL_LINK_INT);
  4545   4548     Tcl_LinkVar(interp, "sqlite_like_count", 
  4546   4549         (char*)&sqlite3_like_count, TCL_LINK_INT);
  4547   4550     Tcl_LinkVar(interp, "sqlite_interrupt_count", 
  4548   4551         (char*)&sqlite3_interrupt_count, TCL_LINK_INT);
  4549   4552     Tcl_LinkVar(interp, "sqlite_open_file_count", 
  4550   4553         (char*)&sqlite3_open_file_count, TCL_LINK_INT);
  4551   4554     Tcl_LinkVar(interp, "sqlite_current_time", 

Changes to src/vdbe.c.

    39     39   **
    40     40   ** Various scripts scan this source file in order to generate HTML
    41     41   ** documentation, headers files, or other derived files.  The formatting
    42     42   ** of the code in this file is, therefore, important.  See other comments
    43     43   ** in this file for details.  If in doubt, do not deviate from existing
    44     44   ** commenting and indentation practices when changing or adding code.
    45     45   **
    46         -** $Id: vdbe.c,v 1.604 2007/05/02 13:30:27 drh Exp $
           46  +** $Id: vdbe.c,v 1.605 2007/05/02 16:51:59 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "os.h"
    50     50   #include <ctype.h>
    51     51   #include "vdbeInt.h"
    52     52   
    53     53   /*
................................................................................
    80     80   ** has no function other than to help verify the correct operation of the
    81     81   ** library.
    82     82   */
    83     83   #ifdef SQLITE_TEST
    84     84   int sqlite3_sort_count = 0;
    85     85   #endif
    86     86   
           87  +/*
           88  +** The next global variable records the size of the largest MEM_Blob
           89  +** or MEM_Str that has appeared on the VDBE stack.  The test procedures
           90  +** use this information to make sure that the zero-blob functionality
           91  +** is working correctly.   This variable has no function other than to
           92  +** help verify the correct operation of the library.
           93  +*/
           94  +#ifdef SQLITE_TEST
           95  +int sqlite3_max_blobsize = 0;
           96  +#endif
           97  +
    87     98   /*
    88     99   ** Release the memory associated with the given stack level.  This
    89    100   ** leaves the Mem.flags field in an inconsistent state.
    90    101   */
    91    102   #define Release(P) if((P)->flags&MEM_Dyn){ sqlite3VdbeMemRelease(P); }
    92    103   
    93    104   /*
................................................................................
  1629   1640     affinity = pOp->p1 & 0xFF;
  1630   1641     if( affinity ){
  1631   1642       applyAffinity(pNos, affinity, encoding);
  1632   1643       applyAffinity(pTos, affinity, encoding);
  1633   1644     }
  1634   1645   
  1635   1646     assert( pOp->p3type==P3_COLLSEQ || pOp->p3==0 );
         1647  +  sqlite3VdbeMemExpandBlob(pNos);
         1648  +  sqlite3VdbeMemExpandBlob(pTos);
  1636   1649     res = sqlite3MemCompare(pNos, pTos, (CollSeq*)pOp->p3);
  1637   1650     switch( pOp->opcode ){
  1638   1651       case OP_Eq:    res = res==0;     break;
  1639   1652       case OP_Ne:    res = res!=0;     break;
  1640   1653       case OP_Lt:    res = res<0;      break;
  1641   1654       case OP_Le:    res = res<=0;     break;
  1642   1655       case OP_Gt:    res = res>0;      break;
................................................................................
  2219   2232     containsNull = 0;
  2220   2233     file_format = p->minWriteFileFormat;
  2221   2234   
  2222   2235     /* Loop through the elements that will make up the record to figure
  2223   2236     ** out how much space is required for the new record.
  2224   2237     */
  2225   2238     for(pRec=pData0; pRec<=pTos; pRec++){
         2239  +    int len;
  2226   2240       if( zAffinity ){
  2227   2241         applyAffinity(pRec, zAffinity[pRec-pData0], encoding);
  2228   2242       }
  2229   2243       if( pRec->flags&MEM_Null ){
  2230   2244         containsNull = 1;
  2231   2245       }
  2232   2246       serial_type = sqlite3VdbeSerialType(pRec, file_format);
  2233         -    nData += sqlite3VdbeSerialTypeLen(serial_type);
         2247  +    len = sqlite3VdbeSerialTypeLen(serial_type);
         2248  +    nData += len;
  2234   2249       nHdr += sqlite3VarintLen(serial_type);
  2235   2250       if( pRec->flags & MEM_Zero ){
  2236   2251         /* Only pure zero-filled BLOBs can be input to this Opcode.
  2237   2252         ** We do not allow blobs with a prefix and a zero-filled tail. */
  2238   2253         assert( pRec->n==0 );
  2239   2254         nZero += pRec->u.i;
  2240         -    }else{
         2255  +    }else if( len ){
  2241   2256         nZero = 0;
  2242   2257       }
  2243   2258     }
  2244   2259   
  2245   2260     /* If we have to append a varint rowid to this record, set pRowid
  2246   2261     ** to the value of the rowid and increase nByte by the amount of space
  2247   2262     ** required to store it.
................................................................................
  2873   2888         if( rc!=SQLITE_OK ){
  2874   2889           goto abort_due_to_error;
  2875   2890         }
  2876   2891         pC->lastRowid = pTos->u.i;
  2877   2892         pC->rowidIsValid = res==0;
  2878   2893       }else{
  2879   2894         assert( pTos->flags & MEM_Blob );
  2880         -      /* Stringify(pTos, encoding); */
         2895  +      sqlite3VdbeMemExpandBlob(pTos);
  2881   2896         rc = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
  2882   2897         if( rc!=SQLITE_OK ){
  2883   2898           goto abort_due_to_error;
  2884   2899         }
  2885   2900         pC->rowidIsValid = 0;
  2886   2901       }
  2887   2902       pC->deferredMoveto = 0;
................................................................................
  2980   2995     Cursor *pC;
  2981   2996     assert( pTos>=p->aStack );
  2982   2997     assert( i>=0 && i<p->nCursor );
  2983   2998     assert( p->apCsr[i]!=0 );
  2984   2999     if( (pC = p->apCsr[i])->pCursor!=0 ){
  2985   3000       int res, rx;
  2986   3001       assert( pC->isTable==0 );
         3002  +    assert( pTos->flags & MEM_Blob );
  2987   3003       Stringify(pTos, encoding);
  2988   3004       rx = sqlite3BtreeMoveto(pC->pCursor, pTos->z, pTos->n, 0, &res);
  2989   3005       alreadyExists = rx==SQLITE_OK && res==0;
  2990   3006       pC->deferredMoveto = 0;
  2991   3007       pC->cacheStatus = CACHE_STALE;
  2992   3008     }
  2993   3009     if( pOp->opcode==OP_Found ){
................................................................................
  3047   3063       char *zKey;    /* The value of K */
  3048   3064       int nKey;      /* Number of bytes in K */
  3049   3065       int len;       /* Number of bytes in K without the rowid at the end */
  3050   3066       int szRowid;   /* Size of the rowid column at the end of zKey */
  3051   3067   
  3052   3068       /* Make sure K is a string and make zKey point to K
  3053   3069       */
         3070  +    assert( pNos->flags & MEM_Blob );
  3054   3071       Stringify(pNos, encoding);
  3055   3072       zKey = pNos->z;
  3056   3073       nKey = pNos->n;
  3057   3074   
  3058   3075       szRowid = sqlite3VdbeIdxRowidLen((u8*)zKey);
  3059   3076       len = nKey-szRowid;
  3060   3077   
................................................................................
  3898   3915   
  3899   3916     assert( i>=0 && i<p->nCursor );
  3900   3917     assert( p->apCsr[i]!=0 );
  3901   3918     assert( pTos>=p->aStack );
  3902   3919     if( (pC = p->apCsr[i])->pCursor!=0 ){
  3903   3920       int res;
  3904   3921    
  3905         -    assert( pTos->flags & MEM_Blob );  /* Created using OP_Make*Key */
  3906         -    Stringify(pTos, encoding);
         3922  +    assert( pTos->flags & MEM_Blob );  /* Created using OP_MakeRecord */
  3907   3923       assert( pC->deferredMoveto==0 );
         3924  +    sqlite3VdbeMemExpandBlob(pTos);
  3908   3925       *pC->pIncrKey = pOp->p3!=0;
  3909   3926       assert( pOp->p3==0 || pOp->opcode!=OP_IdxGT );
  3910   3927       rc = sqlite3VdbeIdxKeyCompare(pC, pTos->n, (u8*)pTos->z, &res);
  3911   3928       *pC->pIncrKey = 0;
  3912   3929       if( rc!=SQLITE_OK ){
  3913   3930         break;
  3914   3931       }
................................................................................
  4977   4994         pOp->cnt++;
  4978   4995   #if 0
  4979   4996           fprintf(stdout, "%10lld ", elapse);
  4980   4997           sqlite3VdbePrintOp(stdout, origPc, &p->aOp[origPc]);
  4981   4998   #endif
  4982   4999       }
  4983   5000   #endif
         5001  +
         5002  +#ifdef SQLITE_TEST
         5003  +    /* Keep track of the size of the largest BLOB or STR that has appeared
         5004  +    ** on the top of the VDBE stack.
         5005  +    */
         5006  +    if( pTos>=p->aStack && (pTos->flags & (MEM_Blob|MEM_Str))!=0
         5007  +         && pTos->n>sqlite3_max_blobsize ){
         5008  +      sqlite3_max_blobsize = pTos->n;
         5009  +    }
         5010  +#endif
  4984   5011   
  4985   5012       /* The following code adds nothing to the actual functionality
  4986   5013       ** of the program.  It is only here for testing and debugging.
  4987   5014       ** On the other hand, it does burn CPU cycles every time through
  4988   5015       ** the evaluator loop.  So we can leave it out when NDEBUG is defined.
  4989   5016       */
  4990   5017   #ifndef NDEBUG
................................................................................
  4994   5021       ** cell, so avoid calling MemSanity() in this case.
  4995   5022       */
  4996   5023       if( pTos>=p->aStack && pTos->flags ){
  4997   5024         sqlite3VdbeMemSanity(pTos);
  4998   5025       }
  4999   5026       assert( pc>=-1 && pc<p->nOp );
  5000   5027   #ifdef SQLITE_DEBUG
         5028  +
  5001   5029       /* Code for tracing the vdbe stack. */
  5002   5030       if( p->trace && pTos>=p->aStack ){
  5003   5031         int i;
  5004   5032         fprintf(p->trace, "Stack:");
  5005   5033         for(i=0; i>-5 && &pTos[i]>=p->aStack; i--){
  5006   5034           if( pTos[i].flags & MEM_Null ){
  5007   5035             fprintf(p->trace, " NULL");

Changes to test/zeroblob.test.

     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing of the zero-filled blob functionality
    13     13   # including the sqlite3_bind_zeroblob(), sqlite3_result_zeroblob(),
    14     14   # and the built-in zeroblob() SQL function.
    15     15   #
    16         -# $Id: zeroblob.test,v 1.1 2007/05/02 13:30:27 drh Exp $
           16  +# $Id: zeroblob.test,v 1.2 2007/05/02 16:51:59 drh Exp $
    17     17   
    18     18   set testdir [file dirname $argv0]
    19     19   source $testdir/tester.tcl
    20     20   
    21         -# Create the database
           21  +# When zeroblob() is used for the last field of a column, then the
           22  +# content of the zeroblob is never instantiated on the VDBE stack.
           23  +# But it does get inserted into the database correctly.
    22     24   #
    23     25   do_test zeroblob-1.1 {
    24     26     execsql {
    25     27       CREATE TABLE t1(a,b,c,d);
    26         -    INSERT INTO t1 VALUES(1,2,3,zeroblob(10000));
    27         -    SELECT count(*) FROM t1;
           28  +  }
           29  +  set ::sqlite3_max_blobsize 0
           30  +  execsql {
           31  +    INSERT INTO t1 VALUES(2,3,4,zeroblob(10000));
    28     32     }
    29         -} {1}
           33  +  set ::sqlite3_max_blobsize
           34  +} {10}
    30     35   do_test zeroblob-1.2 {
    31     36     execsql {
    32     37       SELECT length(d) FROM t1
    33     38     }
    34     39   } {10000}
           40  +
           41  +# If a non-NULL column follows the zeroblob, then the content of
           42  +# the zeroblob must be instantiated.
           43  +#
    35     44   do_test zeroblob-1.3 {
           45  +  set ::sqlite3_max_blobsize 0
    36     46     execsql {
    37         -    INSERT INTO t1 VALUES(2,3,zeroblob(10000),4);
    38         -    SELECT count(*) FROM t1;
           47  +    INSERT INTO t1 VALUES(3,4,zeroblob(10000),5);
    39     48     }
    40         -} {2}
           49  +  set ::sqlite3_max_blobsize
           50  +} {10010}
    41     51   do_test zeroblob-1.4 {
    42     52     execsql {
    43     53       SELECT length(c), length(d) FROM t1
    44     54     }
    45     55   } {1 10000 10000 1}
           56  +
           57  +# Multiple zeroblobs can appear at the end of record.  No instantiation
           58  +# of the blob content occurs on the stack.
           59  +#
    46     60   do_test zeroblob-1.5 {
           61  +  set ::sqlite3_max_blobsize 0
    47     62     execsql {
    48         -    INSERT INTO t1 VALUES(3,4,zeroblob(10000),zeroblob(10000));
    49         -    SELECT count(*) FROM t1;
           63  +    INSERT INTO t1 VALUES(4,5,zeroblob(10000),zeroblob(10000));
    50     64     }
    51         -} {3}
           65  +  set ::sqlite3_max_blobsize
           66  +} {11}
    52     67   do_test zeroblob-1.6 {
    53     68     execsql {
    54     69       SELECT length(c), length(d) FROM t1
    55     70     }
    56     71   } {1 10000 10000 1 10000 10000}
           72  +
           73  +# NULLs can follow the zeroblob() or be intermixed with zeroblobs and
           74  +# no instantiation of the zeroblobs occurs on the stack.
           75  +#
           76  +do_test zeroblob-1.7 {
           77  +  set ::sqlite3_max_blobsize 0
           78  +  execsql {
           79  +    INSERT INTO t1 VALUES(5,zeroblob(10000),NULL,zeroblob(10000));
           80  +  }
           81  +  set ::sqlite3_max_blobsize
           82  +} {10}
           83  +do_test zeroblob-1.8 {
           84  +  execsql {
           85  +    SELECT length(b), length(d) FROM t1 WHERE a=5
           86  +  }
           87  +} {10000 10000}
           88  +
           89  +# Comparisons against zeroblobs work.
           90  +#
           91  +do_test zeroblob-2.1 {
           92  +  execsql {
           93  +    SELECT a FROM t1 WHERE b=zeroblob(10000)
           94  +  }
           95  +} {5}
           96  +
           97  +# Comparisons against zeroblobs work even when indexed.
           98  +#
           99  +do_test zeroblob-2.2 {
          100  +  execsql {
          101  +    CREATE INDEX i1_1 ON t1(b);
          102  +    SELECT a FROM t1 WHERE b=zeroblob(10000);
          103  +  }
          104  +} {5}
          105  +
          106  +# DISTINCT works for zeroblobs
          107  +#
          108  +do_test zeroblob-3.1 {
          109  +  execsql {
          110  +    SELECT count(DISTINCT a) FROM (
          111  +      SELECT x'00000000000000000000' AS a
          112  +      UNION ALL
          113  +      SELECT zeroblob(10) AS a
          114  +    )
          115  +  }
          116  +} {1}
          117  +  
    57    118   
    58    119   finish_test