/ Check-in [e963bed0]
Login
SQLite training in Houston TX on 2019-11-05 (details)
Part of the 2019 Tcl Conference

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

Overview
Comment:Remove the rowhash object from the code. Rowset now fills its role. (CVS 6535)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: e963bed0fe3ce5fa32f04b930e5ed0956dc2aa47
User & Date: drh 2009-04-22 02:15:48
Context
2009-04-22
15:32
Change the OP_Rowid opcode so that a deferred OP_Seek is pending, it simply pulls the rowid from the deferred seek target and does not actually move the cursor or do a seek. Other where.c cleanups. (CVS 6536) check-in: 1c508a99 user: drh tags: trunk
02:15
Remove the rowhash object from the code. Rowset now fills its role. (CVS 6535) check-in: e963bed0 user: drh tags: trunk
00:47
Extend the Rowset object to contain all the capabilities of Rowhash in addition to its legacy capabilities. Use Rowset to replace Rowhash. In addition to requiring less code, This removes the 2^32 result row limitation, uses less memory, and gives better bounds on worst-case performance. The Rowhash implementation has yet to be removed. (CVS 6534) check-in: b101cf70 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to Makefile.in.

   168    168           delete.lo expr.lo fault.lo func.lo global.lo \
   169    169           hash.lo journal.lo insert.lo legacy.lo loadext.lo \
   170    170           main.lo malloc.lo mem0.lo mem1.lo mem2.lo mem3.lo mem5.lo \
   171    171           memjournal.lo \
   172    172           mutex.lo mutex_noop.lo mutex_os2.lo mutex_unix.lo mutex_w32.lo \
   173    173           notify.lo opcodes.lo os.lo os_unix.lo os_win.lo os_os2.lo \
   174    174           pager.lo parse.lo pcache.lo pcache1.lo pragma.lo prepare.lo printf.lo \
   175         -        random.lo resolve.lo rowhash.lo rowset.lo select.lo status.lo \
          175  +        random.lo resolve.lo rowset.lo select.lo status.lo \
   176    176           table.lo tokenize.lo trigger.lo update.lo \
   177    177           util.lo vacuum.lo \
   178    178           vdbe.lo vdbeapi.lo vdbeaux.lo vdbeblob.lo vdbemem.lo \
   179    179           walker.lo where.lo utf.lo vtab.lo
   180    180   
   181    181   # Object files for the amalgamation.
   182    182   #
................................................................................
   245    245     $(TOP)/src/pcache.h \
   246    246     $(TOP)/src/pcache1.c \
   247    247     $(TOP)/src/pragma.c \
   248    248     $(TOP)/src/prepare.c \
   249    249     $(TOP)/src/printf.c \
   250    250     $(TOP)/src/random.c \
   251    251     $(TOP)/src/resolve.c \
   252         -  $(TOP)/src/rowhash.c \
   253    252     $(TOP)/src/rowset.c \
   254    253     $(TOP)/src/select.c \
   255    254     $(TOP)/src/status.c \
   256    255     $(TOP)/src/shell.c \
   257    256     $(TOP)/src/sqlite.h.in \
   258    257     $(TOP)/src/sqlite3ext.h \
   259    258     $(TOP)/src/sqliteInt.h \
................................................................................
   668    667   
   669    668   random.lo:	$(TOP)/src/random.c $(HDR)
   670    669   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/random.c
   671    670   
   672    671   resolve.lo:	$(TOP)/src/resolve.c $(HDR)
   673    672   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/resolve.c
   674    673   
   675         -rowhash.lo:	$(TOP)/src/rowhash.c $(HDR)
   676         -	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/rowhash.c
   677         -
   678    674   rowset.lo:	$(TOP)/src/rowset.c $(HDR)
   679    675   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/rowset.c
   680    676   
   681    677   select.lo:	$(TOP)/src/select.c $(HDR)
   682    678   	$(LTCOMPILE) $(TEMP_STORE) -c $(TOP)/src/select.c
   683    679   
   684    680   status.lo:	$(TOP)/src/status.c $(HDR)

Changes to main.mk.

    57     57            func.o global.o hash.o \
    58     58            icu.o insert.o journal.o legacy.o loadext.o \
    59     59            main.o malloc.o mem0.o mem1.o mem2.o mem3.o mem5.o \
    60     60            memjournal.o \
    61     61            mutex.o mutex_noop.o mutex_os2.o mutex_unix.o mutex_w32.o \
    62     62            notify.o opcodes.o os.o os_os2.o os_unix.o os_win.o \
    63     63            pager.o parse.o pcache.o pcache1.o pragma.o prepare.o printf.o \
    64         -         random.o resolve.o rowhash.o rowset.o rtree.o select.o status.o \
           64  +         random.o resolve.o rowset.o rtree.o select.o status.o \
    65     65            table.o tokenize.o trigger.o \
    66     66            update.o util.o vacuum.o \
    67     67            vdbe.o vdbeapi.o vdbeaux.o vdbeblob.o vdbemem.o \
    68     68            walker.o where.o utf.o vtab.o
    69     69   
    70     70   
    71     71   
................................................................................
   126    126     $(TOP)/src/pcache.h \
   127    127     $(TOP)/src/pcache1.c \
   128    128     $(TOP)/src/pragma.c \
   129    129     $(TOP)/src/prepare.c \
   130    130     $(TOP)/src/printf.c \
   131    131     $(TOP)/src/random.c \
   132    132     $(TOP)/src/resolve.c \
   133         -  $(TOP)/src/rowhash.c \
   134    133     $(TOP)/src/rowset.c \
   135    134     $(TOP)/src/select.c \
   136    135     $(TOP)/src/status.c \
   137    136     $(TOP)/src/shell.c \
   138    137     $(TOP)/src/sqlite.h.in \
   139    138     $(TOP)/src/sqlite3ext.h \
   140    139     $(TOP)/src/sqliteInt.h \

Deleted src/rowhash.c.

     1         -/*
     2         -** 2009 April 15
     3         -**
     4         -** The author disclaims copyright to this source code.  In place of
     5         -** a legal notice, here is a blessing:
     6         -**
     7         -**    May you do good and not evil.
     8         -**    May you find forgiveness for yourself and forgive others.
     9         -**    May you share freely, never taking more than you give.
    10         -**
    11         -*************************************************************************
    12         -**
    13         -** This file contains the implementation of the RowHash data structure.
    14         -** A RowHash has the following properties:
    15         -**
    16         -**   *  A RowHash stores an unordered "bag" of 64-bit integer rowids.
    17         -**      There is no other content.
    18         -**
    19         -**   *  Primative operations are CREATE, INSERT, TEST, and DESTROY.
    20         -**      There is no way to remove individual elements from the RowHash
    21         -**      once they are inserted.
    22         -**
    23         -**   *  INSERT operations are batched.  TEST operation will ignore
    24         -**      elements in the current INSERT batch.  Only elements inserted
    25         -**      in prior batches will be seen by a TEST.
    26         -**
    27         -** The insert batch number is a parameter to the TEST primitive.  The
    28         -** hash table is rebuilt whenever the batch number increases.  TEST
    29         -** operations only look for INSERTs that occurred in prior batches.
    30         -**
    31         -** The caller is responsible for insuring that there are no duplicate
    32         -** INSERTs.
    33         -**
    34         -** $Id: rowhash.c,v 1.5 2009/04/22 00:47:01 drh Exp $
    35         -*/
    36         -#include "sqliteInt.h"
    37         -
    38         -/*
    39         -** An upper bound on the size of heap allocations made by this module.
    40         -** Limiting the size of allocations helps to avoid memory fragmentation.
    41         -*/
    42         -#define ROWHASH_ALLOCATION 1024
    43         -
    44         -/*
    45         -** If there are less than this number of elements in the RowHash, do not
    46         -** bother building a hash-table. Just do a linear search.
    47         -*/
    48         -#define ROWHASH_LINEAR_SEARCH_LIMIT 10
    49         -
    50         -/*
    51         -** This value is what we want the average length of the collision hash
    52         -** chain to be.
    53         -*/
    54         -#define ROWHASH_COLLISION_LENGTH 3
    55         -
    56         -
    57         -/* Forward references to data structures. */
    58         -typedef struct RowHashElem RowHashElem;
    59         -typedef struct RowHashBlock RowHashBlock;
    60         -typedef union RowHashPtr RowHashPtr;
    61         -typedef struct RowHashPage RowHashPage;
    62         -
    63         -/*
    64         -** Number of elements in the RowHashBlock.aElem[] array. This array is
    65         -** sized to make RowHashBlock very close to (without exceeding)
    66         -** ROWHASH_ALLOCATION bytes in size.
    67         -*/
    68         -#define ROWHASH_ELEM_PER_BLOCK (                                            \
    69         -    (ROWHASH_ALLOCATION - ROUND8(sizeof(struct RowHashBlockData))) /        \
    70         -    sizeof(RowHashElem)                                                     \
    71         -)
    72         -
    73         -/*
    74         -** Number of pointers that fit into a single allocation of 
    75         -** ROWHASH_ALLOCATION bytes.
    76         -*/
    77         -#define ROWHASH_POINTER_PER_PAGE (ROWHASH_ALLOCATION/sizeof(RowHashPtr))
    78         -
    79         -/*
    80         -** A page of pointers used to construct a hash table.
    81         -**
    82         -** The hash table is actually a tree composed of instances of this
    83         -** object.  Leaves of the tree use the a[].pElem pointer to point
    84         -** to RowHashElem entries.  Interior nodes of the tree use the
    85         -** a[].pPage element to point to subpages.
    86         -**
    87         -** The hash table is split into a tree in order to avoid having
    88         -** to make large memory allocations, since large allocations can
    89         -** result in unwanted memory fragmentation.
    90         -*/
    91         -struct RowHashPage {
    92         -  union RowHashPtr {
    93         -    RowHashPage *pPage;   /* Used by interior nodes.  Pointer to subtree. */
    94         -    RowHashElem *pElem;   /* Used by leaves.  Pointer to hash entry. */
    95         -  } a[ROWHASH_POINTER_PER_PAGE];
    96         -};
    97         -
    98         -/*
    99         -** Each 64-bit integer in a RowHash is stored as an instance of
   100         -** this object.  
   101         -**
   102         -** Instances of this object are not allocated separately.  They are
   103         -** allocated in large blocks using the RowHashBlock object as a container.
   104         -*/
   105         -struct RowHashElem {
   106         -  i64 iVal;              /* The value being stored.  A rowid. */
   107         -  RowHashElem *pNext;    /* Next element with the same hash */
   108         -};
   109         -
   110         -/*
   111         -** In order to avoid many small allocations of RowHashElem objects,
   112         -** multiple RowHashElem objects are allocated at once, as an instance
   113         -** of this object, and then used as needed.
   114         -**
   115         -** A single RowHash object will allocate one or more of these RowHashBlock
   116         -** objects.  As many are allocated as are needed to store all of the
   117         -** content.  All RowHashBlocks are kept on a linked list formed using
   118         -** RowHashBlock.data.pNext so that they can be freed when the RowHash
   119         -** is destroyed.
   120         -**
   121         -** The linked list of RowHashBlock objects also provides a way to sequentially
   122         -** scan all elements in the RowHash.  This sequential scan is used when
   123         -** rebuilding the hash table.  The hash table is rebuilt after every 
   124         -** batch of inserts.
   125         -*/
   126         -struct RowHashBlock {
   127         -  struct RowHashBlockData {
   128         -    RowHashBlock *pNext;      /* Next RowHashBlock object in list of them all */
   129         -  } data;
   130         -  RowHashElem aElem[ROWHASH_ELEM_PER_BLOCK]; /* Available RowHashElem objects */
   131         -};
   132         -
   133         -/*
   134         -** RowHash structure. References to a structure of this type are passed
   135         -** around and used as opaque handles by code in other modules.
   136         -*/
   137         -struct RowHash {
   138         -  unsigned int nEntry;    /* Number of used entries over all RowHashBlocks */
   139         -  int iBatch;             /* The current insert batch number */
   140         -  u16 nUsed;              /* Number of used entries in first RowHashBlock */
   141         -  u8 nHeight;             /* Height of tree of hash pages */
   142         -  u8 nLinearLimit;        /* Linear search limit (used if pHash==0) */
   143         -  int nBucket;            /* Number of buckets in hash table */
   144         -  RowHashPage *pHash;     /* Pointer to root of hash table tree */
   145         -  RowHashBlock *pBlock;   /* Linked list of RowHashBlocks */
   146         -  sqlite3 *db;            /* Associated database connection */
   147         -};
   148         -
   149         -
   150         -/*
   151         -** Allocate a hash table tree of height nHeight with *pnLeaf leaf pages. 
   152         -** Set *pp to point to the root of the tree.  If the maximum number of leaf 
   153         -** pages in a tree of height nHeight is less than *pnLeaf, allocate only
   154         -** that part of the tree that is necessary to account for all leaves.
   155         -**
   156         -** Before returning, subtract the number of leaves in the tree allocated
   157         -** from *pnLeaf.
   158         -**
   159         -** This routine returns SQLITE_NOMEM if a malloc() fails, or SQLITE_OK
   160         -** otherwise.
   161         -*/
   162         -static int allocHashTable(RowHashPage **pp, int nHeight, int *pnLeaf){
   163         -  RowHashPage *p = (RowHashPage *)sqlite3MallocZero(sizeof(*p));
   164         -  if( !p ){
   165         -    return SQLITE_NOMEM;
   166         -  }
   167         -  *pp = p;
   168         -  if( nHeight==0 ){
   169         -    (*pnLeaf)--;
   170         -  }else{
   171         -    int ii;
   172         -    for(ii=0; ii<ROWHASH_POINTER_PER_PAGE && *pnLeaf>0; ii++){
   173         -      if( allocHashTable(&p->a[ii].pPage, nHeight-1, pnLeaf) ){
   174         -        return SQLITE_NOMEM;
   175         -      }
   176         -    }
   177         -  }
   178         -  return SQLITE_OK;
   179         -}
   180         -
   181         -/*
   182         -** Delete the hash table tree of height nHeight passed as the first argument.
   183         -*/
   184         -static void deleteHashTable(RowHashPage *p, int nHeight){
   185         -  if( p ){
   186         -    if( nHeight>0 ){
   187         -      int ii;
   188         -      for(ii=0; ii<ROWHASH_POINTER_PER_PAGE; ii++){
   189         -        deleteHashTable(p->a[ii].pPage, nHeight-1);
   190         -      }
   191         -    }
   192         -    sqlite3_free(p);
   193         -  }
   194         -}
   195         -
   196         -/*
   197         -** Find the hash-bucket associated with value iVal. Return a pointer to it.
   198         -**
   199         -** By "hash-bucket", we mean the RowHashPage.a[].pElem pointer that
   200         -** corresponds to a particular hash entry.
   201         -*/
   202         -static RowHashElem **findHashBucket(RowHash *pRowHash, i64 iVal){
   203         -  int aOffset[16];
   204         -  int n;
   205         -  RowHashPage *pPage = pRowHash->pHash;
   206         -  int h = (((u64)iVal) % pRowHash->nBucket);
   207         -
   208         -  assert( pRowHash->nHeight < sizeof(aOffset)/sizeof(aOffset[0]) );
   209         -  for(n=0; n<pRowHash->nHeight; n++){
   210         -    int h1 = h / ROWHASH_POINTER_PER_PAGE;
   211         -    aOffset[n] = h - (h1 * ROWHASH_POINTER_PER_PAGE);
   212         -    h = h1;
   213         -  }
   214         -  aOffset[n] = h;
   215         -  for(n=pRowHash->nHeight; n>0; n--){
   216         -    pPage = pPage->a[aOffset[n]].pPage;
   217         -  }
   218         -  return &pPage->a[aOffset[0]].pElem;
   219         -}
   220         -
   221         -/*
   222         -** Build a new hash table tree in p->pHash.  The new hash table should
   223         -** contain all p->nEntry entries in the p->pBlock list.  If there
   224         -** existed a prior tree, delete the old tree first before constructing
   225         -** the new one.
   226         -**
   227         -** If the number of entries (p->nEntry) is less than
   228         -** ROWHASH_LINEAR_SEARCH_LIMIT, then we are guessing that a linear
   229         -** search is going to be faster than a lookup, so do not bother
   230         -** building the hash table.
   231         -*/
   232         -static int makeHashTable(RowHash *p, int iBatch){
   233         -  RowHashBlock *pBlock;
   234         -  int nBucket;
   235         -  int nLeaf, n;
   236         -  
   237         -  /* Delete the old hash table. */
   238         -  deleteHashTable(p->pHash, p->nHeight);
   239         -  assert( p->iBatch!=iBatch );
   240         -  p->iBatch = iBatch;
   241         -
   242         -  /* Skip building the hash table if the number of elements is small */
   243         -  if( p->nEntry<ROWHASH_LINEAR_SEARCH_LIMIT ){
   244         -    p->nLinearLimit = p->nEntry;
   245         -    p->pHash = 0;
   246         -    return SQLITE_OK;
   247         -  }
   248         -
   249         -  /* Determine how many leaves the hash-table will comprise. */
   250         -  nLeaf = 1 + (p->nEntry / (ROWHASH_POINTER_PER_PAGE*ROWHASH_COLLISION_LENGTH));
   251         -  p->nBucket = nBucket = nLeaf*ROWHASH_POINTER_PER_PAGE;
   252         -
   253         -  /* Set nHeight to the height of the tree that contains the leaf pages. If
   254         -  ** RowHash.nHeight is zero, then the whole hash-table fits on a single
   255         -  ** leaf. If RowHash.nHeight is 1, then RowHash.pHash points to an array
   256         -  ** of pointers to leaf pages. If 2, pHash points to an array of pointers
   257         -  ** to arrays of pointers to leaf pages. And so on.
   258         -  */
   259         -  p->nHeight = 0;
   260         -  n = nLeaf;
   261         -  while( n>1 ){
   262         -    n = (n+ROWHASH_POINTER_PER_PAGE-1) / ROWHASH_POINTER_PER_PAGE;
   263         -    p->nHeight++;
   264         -  }
   265         -
   266         -  /* Allocate the hash-table. */
   267         -  if( allocHashTable(&p->pHash, p->nHeight, &nLeaf) ){
   268         -    return SQLITE_NOMEM;
   269         -  }
   270         -
   271         -  /* Insert all values into the hash-table. */
   272         -  for(pBlock=p->pBlock; pBlock; pBlock=pBlock->data.pNext){
   273         -    RowHashElem * const pEnd = &pBlock->aElem[
   274         -      pBlock==p->pBlock?p->nUsed:ROWHASH_ELEM_PER_BLOCK
   275         -    ];
   276         -    RowHashElem *pIter;
   277         -    for(pIter=pBlock->aElem; pIter<pEnd; pIter++){
   278         -      RowHashElem **ppElem = findHashBucket(p, pIter->iVal);
   279         -      pIter->pNext = *ppElem;
   280         -      *ppElem = pIter;
   281         -    }
   282         -  }
   283         -
   284         -  return SQLITE_OK;
   285         -}
   286         -
   287         -/*
   288         -** Check to see if iVal has been inserted into the hash table "p"
   289         -** in some batch prior to iBatch.  If so, set *pExists to 1.
   290         -** If not, set *pExists to 0.
   291         -**
   292         -** The hash table is rebuilt whenever iBatch changes.  A hash table
   293         -** rebuild might encounter an out-of-memory condition.  If that happens,
   294         -** return SQLITE_NOMEM.  If there are no problems, return SQLITE_OK.
   295         -**
   296         -** The initial "batch" is 0.  So, if there were prior calls to
   297         -** sqlite3RowhashInsert() and then this routine is invoked with iBatch==0,
   298         -** because all prior inserts where in the same batch, none of the prior
   299         -** inserts will be visible and this routine will indicate not found.
   300         -** Hence, the first invocation of this routine should probably use
   301         -** a batch number of 1.
   302         -*/
   303         -int sqlite3RowhashTest(
   304         -  RowHash *p,     /* The RowHash to search in */
   305         -  int iBatch,     /* Look for values inserted in batches prior to this batch */
   306         -  i64 iVal,       /* The rowid value we are looking for */
   307         -  int *pExists    /* Store 0 or 1 hear to indicate not-found or found */
   308         -){
   309         -  *pExists = 0;
   310         -  if( p ){
   311         -    assert( p->pBlock );
   312         -    if( iBatch!=p->iBatch && makeHashTable(p, iBatch) ){
   313         -      return SQLITE_NOMEM;
   314         -    }
   315         -    if( p->pHash ){
   316         -      RowHashElem *pElem = *findHashBucket(p, iVal);
   317         -      for(; pElem; pElem=pElem->pNext){
   318         -        if( pElem->iVal==iVal ){
   319         -          *pExists = 1;
   320         -          break;
   321         -        }
   322         -      }
   323         -    }else{
   324         -      int ii;
   325         -      RowHashElem *aElem = p->pBlock->aElem;
   326         -      for(ii=0; ii<p->nLinearLimit; ii++){
   327         -        if( aElem[ii].iVal==iVal ){
   328         -          *pExists = 1;
   329         -          break;
   330         -        }
   331         -      }
   332         -    }
   333         -  }
   334         -  return SQLITE_OK;
   335         -}
   336         -
   337         -/*
   338         -** Insert value iVal into the RowHash object.  Allocate a new RowHash
   339         -** object if necessary.
   340         -**
   341         -** Return SQLITE_OK if all goes as planned. If a malloc() fails, return
   342         -** SQLITE_NOMEM.
   343         -*/
   344         -int sqlite3RowhashInsert(sqlite3 *db, RowHash **pp, i64 iVal){
   345         -  RowHash *p = *pp;
   346         -  
   347         -  /* If the RowHash structure has not been allocated, allocate it now. */
   348         -  if( !p ){
   349         -    p = (RowHash*)sqlite3DbMallocZero(db, sizeof(RowHash));
   350         -    if( !p ){
   351         -      return SQLITE_NOMEM;
   352         -    }
   353         -    p->db = db;
   354         -    *pp = p;
   355         -  }
   356         -
   357         -  /* If the current RowHashBlock is full, or if the first RowHashBlock has
   358         -  ** not yet been allocated, allocate one now. */ 
   359         -  if( !p->pBlock || p->nUsed==ROWHASH_ELEM_PER_BLOCK ){
   360         -    RowHashBlock *pBlock = (RowHashBlock*)sqlite3Malloc(sizeof(RowHashBlock));
   361         -    if( !pBlock ){
   362         -      return SQLITE_NOMEM;
   363         -    }
   364         -    pBlock->data.pNext = p->pBlock;
   365         -    p->pBlock = pBlock;
   366         -    p->nUsed = 0;
   367         -  }
   368         -  assert( p->nUsed==(p->nEntry % ROWHASH_ELEM_PER_BLOCK) );
   369         -
   370         -  /* Add iVal to the current RowHashBlock. */
   371         -  p->pBlock->aElem[p->nUsed].iVal = iVal;
   372         -  p->nUsed++;
   373         -  p->nEntry++;
   374         -  return SQLITE_OK;
   375         -}
   376         -
   377         -/*
   378         -** Destroy the RowHash object passed as the first argument.
   379         -*/
   380         -void sqlite3RowhashDestroy(RowHash *p){
   381         -  if( p ){
   382         -    RowHashBlock *pBlock, *pNext;
   383         -    deleteHashTable(p->pHash, p->nHeight);
   384         -    for(pBlock=p->pBlock; pBlock; pBlock=pNext){
   385         -      pNext = pBlock->data.pNext;
   386         -      sqlite3_free(pBlock);
   387         -    }
   388         -    sqlite3DbFree(p->db, p);
   389         -  }
   390         -}

Changes to src/sqliteInt.h.

     7      7   **    May you do good and not evil.
     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** Internal interface definitions for SQLite.
    13     13   **
    14         -** @(#) $Id: sqliteInt.h,v 1.857 2009/04/22 00:47:01 drh Exp $
           14  +** @(#) $Id: sqliteInt.h,v 1.858 2009/04/22 02:15:48 drh Exp $
    15     15   */
    16     16   #ifndef _SQLITEINT_H_
    17     17   #define _SQLITEINT_H_
    18     18   
    19     19   /*
    20     20   ** Include the configuration header output by 'configure' if we're using the
    21     21   ** autoconf-based build
................................................................................
   553    553   
   554    554   /*
   555    555   ** Forward references to structures
   556    556   */
   557    557   typedef struct AggInfo AggInfo;
   558    558   typedef struct AuthContext AuthContext;
   559    559   typedef struct Bitvec Bitvec;
   560         -typedef struct RowHash RowHash;
   561    560   typedef struct RowSet RowSet;
   562    561   typedef struct CollSeq CollSeq;
   563    562   typedef struct Column Column;
   564    563   typedef struct Db Db;
   565    564   typedef struct Schema Schema;
   566    565   typedef struct Expr Expr;
   567    566   typedef struct ExprList ExprList;
................................................................................
  1748   1747   #define WHERE_ORDERBY_NORMAL   0x0000 /* No-op */
  1749   1748   #define WHERE_ORDERBY_MIN      0x0001 /* ORDER BY processing for min() func */
  1750   1749   #define WHERE_ORDERBY_MAX      0x0002 /* ORDER BY processing for max() func */
  1751   1750   #define WHERE_ONEPASS_DESIRED  0x0004 /* Want to do one-pass UPDATE/DELETE */
  1752   1751   #define WHERE_FILL_ROWSET      0x0008  /* Save results in a RowSet object */
  1753   1752   #define WHERE_OMIT_OPEN        0x0010  /* Table cursor are already open */
  1754   1753   #define WHERE_OMIT_CLOSE       0x0020  /* Omit close of table & index cursors */
  1755         -#define WHERE_FILL_ROWHASH     0x0040  /* Save results in a RowHash object */
         1754  +#define WHERE_FILL_ROWTEST     0x0040  /* Save results using OP_RowSetTest */
  1756   1755   
  1757   1756   /*
  1758   1757   ** The WHERE clause processing routine has two halves.  The
  1759   1758   ** first part does the start of the WHERE loop and the second
  1760   1759   ** half does the tail of the WHERE loop.  An instance of
  1761   1760   ** this structure is returned by the first half and passed
  1762   1761   ** into the second half to give some continuity.
  1763   1762   */
  1764   1763   struct WhereInfo {
  1765   1764     Parse *pParse;       /* Parsing and code generating context */
  1766   1765     u16 wctrlFlags;      /* Flags originally passed to sqlite3WhereBegin() */
  1767   1766     u8 okOnePass;        /* Ok to use one-pass algorithm for UPDATE or DELETE */
  1768         -  int regRowSet;                 /* Store rowids in this rowset/rowhash */
  1769         -  int iRowidHandler;             /* Address of OP_RowSet or OP_RowHash */
         1767  +  int regRowSet;                 /* Store rowids in this rowset */
         1768  +  int iRowidHandler;             /* Address of OP_RowSet or OP_RowSetTest */
  1770   1769     SrcList *pTabList;             /* List of tables in the join */
  1771   1770     int iTop;                      /* The very beginning of the WHERE loop */
  1772   1771     int iContinue;                 /* Jump here to continue with next record */
  1773   1772     int iBreak;                    /* Jump here to break out of the loop */
  1774   1773     int nLevel;                    /* Number of nested loop */
  1775   1774     struct WhereClause *pWC;       /* Decomposition of the WHERE clause */
  1776   1775     WhereLevel a[1];               /* Information about each nest loop in WHERE */
................................................................................
  2399   2398   
  2400   2399   RowSet *sqlite3RowSetInit(sqlite3*, void*, unsigned int);
  2401   2400   void sqlite3RowSetClear(RowSet*);
  2402   2401   void sqlite3RowSetInsert(RowSet*, i64);
  2403   2402   int sqlite3RowSetTest(RowSet*, u8 iBatch, i64);
  2404   2403   int sqlite3RowSetNext(RowSet*, i64*);
  2405   2404   
  2406         -int sqlite3RowhashInsert(sqlite3*, RowHash **pp, i64 iVal);
  2407         -int sqlite3RowhashTest(RowHash *p, int iSet, i64 iVal, int *pExists);
  2408         -void sqlite3RowhashDestroy(RowHash *p);
  2409         -
  2410   2405   void sqlite3CreateView(Parse*,Token*,Token*,Token*,Select*,int,int);
  2411   2406   
  2412   2407   #if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
  2413   2408     int sqlite3ViewGetColumnNames(Parse*,Table*);
  2414   2409   #else
  2415   2410   # define sqlite3ViewGetColumnNames(A,B) 0
  2416   2411   #endif

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.836 2009/04/22 00:47:01 drh Exp $
           46  +** $Id: vdbe.c,v 1.837 2009/04/22 02:15:48 drh Exp $
    47     47   */
    48     48   #include "sqliteInt.h"
    49     49   #include "vdbeInt.h"
    50     50   
    51     51   /*
    52     52   ** The following global variable is incremented every time a cursor
    53     53   ** moves, either by the OP_SeekXX, OP_Next, or OP_Prev opcodes.  The test
................................................................................
  4600   4600       /* A value was pulled from the index */
  4601   4601       assert( pOp->p3>0 && pOp->p3<=p->nMem );
  4602   4602       sqlite3VdbeMemSetInt64(pOut, val);
  4603   4603     }
  4604   4604     break;
  4605   4605   }
  4606   4606   
  4607         -/* Opcode: RowHash P1 P2 P3 P4
         4607  +/* Opcode: RowSetTest P1 P2 P3 P4
  4608   4608   **
  4609   4609   ** Register P3 is assumed to hold a 64-bit integer value. If register P1
  4610         -** contains a rowid-hash object and the rowid-hash object contains
         4610  +** contains a RowSet object and that RowSet object contains
  4611   4611   ** the value held in P3, jump to register P2. Otherwise, insert the
  4612         -** integer in P3 into the rowid-hash container and continue on to the
         4612  +** integer in P3 into the RowSet and continue on to the
  4613   4613   ** next opcode.
  4614   4614   **
  4615         -** The rowid-hash is optimized for the case where successive sets
         4615  +** The RowSet object is optimized for the case where successive sets
  4616   4616   ** of integers, where each set contains no duplicates. Each set
  4617   4617   ** of values is identified by a unique P4 value. The first set
  4618         -** must have P4==0, the final set P4=-1.
         4618  +** must have P4==0, the final set P4=-1.  P4 must be either -1 or
         4619  +** non-negative.  For non-negative values of P4 only the lower 4
         4620  +** bits are significant.
  4619   4621   **
  4620   4622   ** This allows optimizations: (a) when P4==0 there is no need to test
  4621         -** the row-hash object for P3, as it is guaranteed not to contain it,
         4623  +** the rowset object for P3, as it is guaranteed not to contain it,
  4622   4624   ** (b) when P4==-1 there is no need to insert the value, as it will
  4623   4625   ** never be tested for, and (c) when a value that is part of set X is
  4624   4626   ** inserted, there is no need to search to see if the same value was
  4625   4627   ** previously inserted as part of set X (only if it was previously
  4626   4628   ** inserted as part of some other set).
  4627   4629   */
  4628         -case OP_RowHash: {                     /* jump, in1, in3 */
         4630  +case OP_RowSetTest: {                     /* jump, in1, in3 */
  4629   4631     int iSet = pOp->p4.i;
  4630   4632     assert( pIn3->flags&MEM_Int );
  4631   4633   
  4632         -  /* If there is anything other than a row-hash object in memory cell P1,
  4633         -  ** delete it now and initialize P1 with an empty row-hash (a null pointer
  4634         -  ** is an acceptable representation of an empty row-hash).
         4634  +  /* If there is anything other than a rowset object in memory cell P1,
         4635  +  ** delete it now and initialize P1 with an empty rowset
  4635   4636     */
  4636   4637     if( (pIn1->flags & MEM_RowSet)==0 ){
  4637   4638       sqlite3VdbeMemSetRowSet(pIn1);
  4638   4639       if( (pIn1->flags & MEM_RowSet)==0 ) goto no_mem;
  4639   4640     }
  4640   4641   
  4641   4642     assert( pOp->p4type==P4_INT32 );
         4643  +  assert( iSet==-1 || iSet>=0 );
  4642   4644     if( iSet ){
  4643   4645       int exists;
  4644   4646       exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet>=0 ? iSet & 0xf : 0xff,
  4645   4647                                  pIn3->u.i);
  4646   4648       if( exists ){
  4647   4649         pc = pOp->p2 - 1;
  4648   4650         break;

Changes to src/vdbeInt.h.

    11     11   *************************************************************************
    12     12   ** This is the header file for information that is private to the
    13     13   ** VDBE.  This information used to all be at the top of the single
    14     14   ** source code file "vdbe.c".  When that file became too big (over
    15     15   ** 6000 lines long) it was split up into several smaller files and
    16     16   ** this header information was factored out.
    17     17   **
    18         -** $Id: vdbeInt.h,v 1.168 2009/04/21 09:02:47 danielk1977 Exp $
           18  +** $Id: vdbeInt.h,v 1.169 2009/04/22 02:15:48 drh Exp $
    19     19   */
    20     20   #ifndef _VDBEINT_H_
    21     21   #define _VDBEINT_H_
    22     22   
    23     23   /*
    24     24   ** intToKey() and keyToInt() used to transform the rowid.  But with
    25     25   ** the latest versions of the design they are no-ops.
................................................................................
   111    111   */
   112    112   struct Mem {
   113    113     union {
   114    114       i64 i;              /* Integer value. */
   115    115       int nZero;          /* Used when bit MEM_Zero is set in flags */
   116    116       FuncDef *pDef;      /* Used only when flags==MEM_Agg */
   117    117       RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
   118         -    RowHash *pRowHash;  /* Used only when flags==MEM_RowHash */
   119    118     } u;
   120    119     double r;           /* Real value */
   121    120     sqlite3 *db;        /* The associated database connection */
   122    121     char *z;            /* String or BLOB value */
   123    122     int n;              /* Number of characters in string value, excluding '\0' */
   124    123     u16 flags;          /* Some combination of MEM_Null, MEM_Str, MEM_Dyn, etc. */
   125    124     u8  type;           /* One of SQLITE_NULL, SQLITE_TEXT, SQLITE_INTEGER, etc */
................................................................................
   145    144   */
   146    145   #define MEM_Null      0x0001   /* Value is NULL */
   147    146   #define MEM_Str       0x0002   /* Value is a string */
   148    147   #define MEM_Int       0x0004   /* Value is an integer */
   149    148   #define MEM_Real      0x0008   /* Value is a real number */
   150    149   #define MEM_Blob      0x0010   /* Value is a BLOB */
   151    150   #define MEM_RowSet    0x0020   /* Value is a RowSet object */
   152         -#define MEM_RowHash   0x0040   /* Value is a RowHash object */
   153    151   #define MEM_TypeMask  0x00ff   /* Mask of type bits */
   154    152   
   155    153   /* Whenever Mem contains a valid string or blob representation, one of
   156    154   ** the following flags must be set to determine the memory management
   157    155   ** policy for Mem.z.  The MEM_Term flag tells us whether or not the
   158    156   ** string is \000 or \u0000 terminated
   159    157   */

Changes to src/vdbeaux.c.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains code used for creating, destroying, and populating
    13     13   ** a VDBE (or an "sqlite3_stmt" as it is known to the outside world.)  Prior
    14     14   ** to version 2.8.7, all this code was combined into the vdbe.c source file.
    15     15   ** But that file was getting too big so this subroutines were split out.
    16     16   **
    17         -** $Id: vdbeaux.c,v 1.452 2009/04/21 09:02:47 danielk1977 Exp $
           17  +** $Id: vdbeaux.c,v 1.453 2009/04/22 02:15:48 drh Exp $
    18     18   */
    19     19   #include "sqliteInt.h"
    20     20   #include "vdbeInt.h"
    21     21   
    22     22   
    23     23   
    24     24   /*
................................................................................
  1220   1220     sqlite3 *db = p->db;
  1221   1221     Mem *pMem;
  1222   1222     closeAllCursorsExceptActiveVtabs(p);
  1223   1223     for(pMem=&p->aMem[1], i=1; i<=p->nMem; i++, pMem++){
  1224   1224       if( pMem->flags & MEM_RowSet ){
  1225   1225         sqlite3RowSetClear(pMem->u.pRowSet);
  1226   1226       }
  1227         -    if( pMem->flags & MEM_RowHash ){
  1228         -      sqlite3RowhashDestroy(pMem->u.pRowHash);
  1229         -    }
  1230   1227       MemSetTypeFlag(pMem, MEM_Null);
  1231   1228     }
  1232   1229     releaseMemArray(&p->aMem[1], p->nMem);
  1233   1230     if( p->contextStack ){
  1234   1231       sqlite3DbFree(db, p->contextStack);
  1235   1232     }
  1236   1233     p->contextStack = 0;

Changes to src/vdbemem.c.

    11     11   *************************************************************************
    12     12   **
    13     13   ** This file contains code use to manipulate "Mem" structure.  A "Mem"
    14     14   ** stores a single value in the VDBE.  Mem is an opaque structure visible
    15     15   ** only within the VDBE.  Interface routines refer to a Mem using the
    16     16   ** name sqlite_value
    17     17   **
    18         -** $Id: vdbemem.c,v 1.141 2009/04/21 09:02:47 danielk1977 Exp $
           18  +** $Id: vdbemem.c,v 1.142 2009/04/22 02:15:49 drh Exp $
    19     19   */
    20     20   #include "sqliteInt.h"
    21     21   #include "vdbeInt.h"
    22     22   
    23     23   /*
    24     24   ** Call sqlite3VdbeMemExpandBlob() on the supplied value (type Mem*)
    25     25   ** P if required.
................................................................................
   266    266   /*
   267    267   ** If the memory cell contains a string value that must be freed by
   268    268   ** invoking an external callback, free it now. Calling this function
   269    269   ** does not free any Mem.zMalloc buffer.
   270    270   */
   271    271   void sqlite3VdbeMemReleaseExternal(Mem *p){
   272    272     assert( p->db==0 || sqlite3_mutex_held(p->db->mutex) );
   273         -  if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet|MEM_RowHash) ){
          273  +  if( p->flags&(MEM_Agg|MEM_Dyn|MEM_RowSet) ){
   274    274       if( p->flags&MEM_Agg ){
   275    275         sqlite3VdbeMemFinalize(p, p->u.pDef);
   276    276         assert( (p->flags & MEM_Agg)==0 );
   277    277         sqlite3VdbeMemRelease(p);
   278    278       }else if( p->flags&MEM_Dyn && p->xDel ){
   279    279         assert( (p->flags&MEM_RowSet)==0 );
   280    280         p->xDel((void *)p->z);
   281    281         p->xDel = 0;
   282    282       }else if( p->flags&MEM_RowSet ){
   283    283         sqlite3RowSetClear(p->u.pRowSet);
   284         -    }else if( p->flags&MEM_RowHash ){
   285         -      sqlite3RowhashDestroy(p->u.pRowHash);
   286         -      p->u.pRowHash = 0;
   287    284       }
   288    285     }
   289    286   }
   290    287   
   291    288   /*
   292    289   ** Release any memory held by the Mem. This may leave the Mem in an
   293    290   ** inconsistent state, for example with (Mem.z==0) and

Changes to src/where.c.

    12     12   ** This module contains C code that generates VDBE code used to process
    13     13   ** the WHERE clause of SQL statements.  This module is responsible for
    14     14   ** generating the code that loops through a table looking for applicable
    15     15   ** rows.  Indices are selected and used to speed the search when doing
    16     16   ** so is applicable.  Because this module is responsible for selecting
    17     17   ** indices, you might also think of this module as the "query optimizer".
    18     18   **
    19         -** $Id: where.c,v 1.384 2009/04/21 17:23:05 danielk1977 Exp $
           19  +** $Id: where.c,v 1.385 2009/04/22 02:15:49 drh Exp $
    20     20   */
    21     21   #include "sqliteInt.h"
    22     22   
    23     23   /*
    24     24   ** Trace output macros
    25     25   */
    26     26   #if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
................................................................................
  2410   2410   
  2411   2411     /* Sometimes, this function is required to generate code to do 
  2412   2412     ** something with the rowid of each row scanned. Specifically:
  2413   2413     **
  2414   2414     **   1) If pWInfo->regRowSet is non-zero, then the rowid must be inserted
  2415   2415     **      into the RowSet object stored in register pWInfo->regRowSet.
  2416   2416     **
  2417         -  **   2) If pWInfo->regRowHash is non-zero, then the rowid must be inserted
  2418         -  **      into the RowHash object stored in register pWInfo->regRowHash.
  2419         -  **
  2420   2417     ** Extracting a rowid value from a VDBE cursor is not always a cheap
  2421   2418     ** operation, especially if the rowid is being extracted from an index
  2422   2419     ** cursor. If the rowid value is available as a by-product of the code
  2423   2420     ** generated to create the top of the scan loop, then it can be reused
  2424         -  ** for either of the two purposes enumerated above without extracting
         2421  +  ** without extracting
  2425   2422     ** it from a cursor. The following two variables are used to communicate
  2426   2423     ** the availability of the rowid value to the C-code at the end of this
  2427   2424     ** function that generates the rowid-handling VDBE code.
  2428   2425     */
  2429   2426     int iRowidReg = 0;              /* Rowid is stored in this register */
  2430   2427     int iReleaseReg = 0;            /* Temp register to free before returning */
  2431   2428   
................................................................................
  2433   2430     v = pParse->pVdbe;
  2434   2431     pWC = pWInfo->pWC;
  2435   2432     pLevel = &pWInfo->a[iLevel];
  2436   2433     pTabItem = &pWInfo->pTabList->a[pLevel->iFrom];
  2437   2434     iCur = pTabItem->iCursor;
  2438   2435     bRev = (pLevel->plan.wsFlags & WHERE_REVERSE)!=0;
  2439   2436     omitTable = (pLevel->plan.wsFlags & WHERE_IDX_ONLY)!=0 
  2440         -           && (wctrlFlags & WHERE_FILL_ROWHASH)==0;
         2437  +           && (wctrlFlags & WHERE_FILL_ROWTEST)==0;
  2441   2438     regRowSet = pWInfo->regRowSet;
  2442   2439     codeRowSetEarly = 0;
  2443   2440   
  2444   2441     /* Create labels for the "break" and "continue" instructions
  2445   2442     ** for the current loop.  Jump to addrBrk to break out of a loop.
  2446   2443     ** Jump to cont to go immediately to the next iteration of the
  2447   2444     ** loop.
................................................................................
  2813   2810       **   CREATE INDEX i3 ON t1(c);
  2814   2811       **
  2815   2812       **   SELECT * FROM t1 WHERE a=5 OR b=7 OR (c=11 AND d=13)
  2816   2813       **
  2817   2814       ** In the example, there are three indexed terms connected by OR.
  2818   2815       ** The top of the loop looks like this:
  2819   2816       **
  2820         -    **          Null       1                # Zero the row-hash in reg 1
         2817  +    **          Null       1                # Zero the rowset in reg 1
  2821   2818       **
  2822   2819       ** Then, for each indexed term, the following. The arguments to
  2823         -    ** RowHash are such that the rowid of the current row is inserted
  2824         -    ** into the row-hash. If it is already present, control skips the
         2820  +    ** RowSetTest are such that the rowid of the current row is inserted
         2821  +    ** into the RowSet. If it is already present, control skips the
  2825   2822       ** Gosub opcode and jumps straight to the code generated by WhereEnd().
  2826   2823       **
  2827   2824       **        sqlite3WhereBegin(<term>)
  2828         -    **          RowHash                     # Insert rowid into rowhash
         2825  +    **          RowSetTest                  # Insert rowid into rowset
  2829   2826       **          Gosub      2 A
  2830   2827       **        sqlite3WhereEnd()
  2831   2828       **
  2832   2829       ** Following the above, code to terminate the loop. Label A, the target
  2833   2830       ** of the Gosub above, jumps to the instruction right after the Goto.
  2834   2831       **
  2835         -    **          Null       1                # Zero the row-hash in reg 1
         2832  +    **          Null       1                # Zero the rowset in reg 1
  2836   2833       **          Goto       B                # The loop is finished.
  2837   2834       **
  2838   2835       **       A: <loop body>                 # Return data, whatever.
  2839   2836       **
  2840   2837       **          Return     2                # Jump back to the Gosub
  2841   2838       **
  2842   2839       **       B: <after the loop>
  2843   2840       **
  2844   2841       */
  2845         -    const int f = WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FILL_ROWHASH;
         2842  +    const int f = WHERE_OMIT_OPEN | WHERE_OMIT_CLOSE | WHERE_FILL_ROWTEST;
  2846   2843   
  2847   2844       WhereClause *pOrWc;    /* The OR-clause broken out into subterms */
  2848   2845       WhereTerm *pFinal;     /* Final subterm within the OR-clause. */
  2849   2846       SrcList oneTab;        /* Shortened table list */
  2850   2847   
  2851   2848       int regReturn = ++pParse->nMem;           /* Register used with OP_Gosub */
  2852         -    int regRowhash = ++pParse->nMem;          /* Register for RowHash object */
         2849  +    int regRowset = ++pParse->nMem;           /* Register for RowSet object */
  2853   2850       int iLoopBody = sqlite3VdbeMakeLabel(v);  /* Start of loop body */
  2854   2851       int iRetInit;                             /* Address of regReturn init */
  2855   2852       int ii;
  2856   2853      
  2857   2854       pTerm = pLevel->plan.u.pTerm;
  2858   2855       assert( pTerm!=0 );
  2859   2856       assert( pTerm->eOperator==WO_OR );
................................................................................
  2862   2859       pFinal = &pOrWc->a[pOrWc->nTerm-1];
  2863   2860   
  2864   2861       /* Set up a SrcList containing just the table being scanned by this loop. */
  2865   2862       oneTab.nSrc = 1;
  2866   2863       oneTab.nAlloc = 1;
  2867   2864       oneTab.a[0] = *pTabItem;
  2868   2865   
  2869         -    /* Initialize the row-hash register to contain NULL. An SQL NULL is 
  2870         -    ** equivalent to an empty row-hash. 
         2866  +    /* Initialize the rowset register to contain NULL. An SQL NULL is 
         2867  +    ** equivalent to an empty rowset.
  2871   2868       **
  2872   2869       ** Also initialize regReturn to contain the address of the instruction 
  2873   2870       ** immediately following the OP_Return at the bottom of the loop. This
  2874   2871       ** is required in a few obscure LEFT JOIN cases where control jumps
  2875   2872       ** over the top of the loop into the body of it. In this case the 
  2876   2873       ** correct response for the end-of-loop code (the OP_Return) is to 
  2877   2874       ** fall through to the next instruction, just as an OP_Next does if
  2878   2875       ** called on an uninitialized cursor.
  2879   2876       */
  2880         -    sqlite3VdbeAddOp2(v, OP_Null, 0, regRowhash);
         2877  +    sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
  2881   2878       iRetInit = sqlite3VdbeAddOp2(v, OP_Integer, 0, regReturn);
  2882   2879   
  2883   2880       /* iReleaseReg = iRowidReg = sqlite3GetTempReg(pParse); */
  2884   2881       for(ii=0; ii<pOrWc->nTerm; ii++){
  2885   2882         WhereTerm *pOrTerm = &pOrWc->a[ii];
  2886   2883         if( pOrTerm->leftCursor==iCur || pOrTerm->eOperator==WO_AND ){
  2887   2884           WhereInfo *pSubWInfo;          /* Info for single OR-term scan */
  2888   2885   
  2889   2886           /* Loop through table entries that match term pOrTerm. */
  2890   2887           pSubWInfo = sqlite3WhereBegin(
  2891         -            pParse, &oneTab, pOrTerm->pExpr, 0, f, regRowhash);
         2888  +            pParse, &oneTab, pOrTerm->pExpr, 0, f, regRowset);
  2892   2889           if( pSubWInfo ){
  2893   2890             int iSet = ((ii==pOrWc->nTerm-1)?-1:ii);
  2894         -          /* The call to sqlite3WhereBegin has coded an OP_RowHash 
  2895         -          ** at instruction iRowHash. Set P2 (the jump target) of this
         2891  +          /* The call to sqlite3WhereBegin has coded an OP_RowSetTest
         2892  +          ** at instruction iRowSet. Set P2 (the jump target) of this
  2896   2893             ** instruction to jump past the OP_Gosub coded below. This way,
  2897   2894             ** if the rowid is already in the hash-table, the body of the
  2898   2895             ** loop is not executed.
  2899   2896             */
  2900         -          int iRowHash = pSubWInfo->iRowidHandler;
  2901         -          sqlite3VdbeChangeP2(v, iRowHash, sqlite3VdbeCurrentAddr(v) + 1);
  2902         -          sqlite3VdbeChangeP4(v, iRowHash, (char *)iSet, P4_INT32);
         2897  +          int iRowSet = pSubWInfo->iRowidHandler;
         2898  +          sqlite3VdbeChangeP2(v, iRowSet, sqlite3VdbeCurrentAddr(v) + 1);
         2899  +          sqlite3VdbeChangeP4(v, iRowSet, (char *)iSet, P4_INT32);
  2903   2900             sqlite3VdbeAddOp2(v, OP_Gosub, regReturn, iLoopBody);
  2904   2901   
  2905   2902             /* Finish the loop through table entries that match term pOrTerm. */
  2906   2903             sqlite3WhereEnd(pSubWInfo);
  2907   2904           }
  2908   2905         }
  2909   2906       }
  2910   2907       sqlite3VdbeChangeP1(v, iRetInit, sqlite3VdbeCurrentAddr(v));
  2911         -    sqlite3VdbeAddOp2(v, OP_Null, 0, regRowhash);
         2908  +    sqlite3VdbeAddOp2(v, OP_Null, 0, regRowset);
  2912   2909       sqlite3VdbeAddOp2(v, OP_Goto, 0, pLevel->addrBrk);
  2913   2910       sqlite3VdbeResolveLabel(v, iLoopBody);
  2914   2911   
  2915   2912       pLevel->op = OP_Return;
  2916   2913       pLevel->p1 = regReturn;
  2917   2914       disableTerm(pLevel, pTerm);
  2918   2915     }else
................................................................................
  2994   2991         }
  2995   2992       }
  2996   2993       
  2997   2994       pWInfo->iRowidHandler = sqlite3VdbeCurrentAddr(v);
  2998   2995       if( pWInfo->wctrlFlags&WHERE_FILL_ROWSET ){
  2999   2996         sqlite3VdbeAddOp2(v, OP_RowSetAdd, regRowSet, iRowidReg);
  3000   2997       }else{
  3001         -      assert( pWInfo->wctrlFlags&WHERE_FILL_ROWHASH );
  3002         -      sqlite3VdbeAddOp3(v, OP_RowHash, regRowSet, 0, iRowidReg);
         2998  +      assert( pWInfo->wctrlFlags&WHERE_FILL_ROWTEST );
         2999  +      sqlite3VdbeAddOp3(v, OP_RowSetTest, regRowSet, 0, iRowidReg);
  3003   3000       }
  3004   3001     }
  3005   3002     sqlite3ReleaseTempReg(pParse, iReleaseReg);
  3006   3003   
  3007   3004     return notReady;
  3008   3005   }
  3009   3006   
................................................................................
  3185   3182     pWInfo->pParse = pParse;
  3186   3183     pWInfo->pTabList = pTabList;
  3187   3184     pWInfo->iBreak = sqlite3VdbeMakeLabel(v);
  3188   3185     pWInfo->regRowSet = regRowSet;
  3189   3186     pWInfo->pWC = pWC = (WhereClause *)&((u8 *)pWInfo)[nByteWInfo];
  3190   3187     pWInfo->wctrlFlags = wctrlFlags;
  3191   3188     pMaskSet = (WhereMaskSet*)&pWC[1];
  3192         -  assert( regRowSet==0 || (wctrlFlags&(WHERE_FILL_ROWSET|WHERE_FILL_ROWHASH)) );
         3189  +  assert( regRowSet==0 || (wctrlFlags&(WHERE_FILL_ROWSET|WHERE_FILL_ROWTEST)) );
  3193   3190   
  3194   3191     /* Split the WHERE clause into separate subexpressions where each
  3195   3192     ** subexpression is separated by an AND operator.
  3196   3193     */
  3197   3194     initMaskSet(pMaskSet);
  3198   3195     whereClauseInit(pWC, pParse, pMaskSet);
  3199   3196     sqlite3ExprCodeConstants(pParse, pWhere);

Changes to tool/mksqlite3c.tcl.

   235    235      hash.c
   236    236      opcodes.c
   237    237   
   238    238      os_os2.c
   239    239      os_unix.c
   240    240      os_win.c
   241    241   
   242         -   rowhash.c
   243    242      bitvec.c
   244    243      pcache.c
   245    244      pcache1.c
   246    245      rowset.c
   247    246      pager.c
   248    247   
   249    248      btmutex.c