/ Check-in [b7489f94]
Login

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

Overview
Comment:Fix a bug in the threadtest4.c program. Remove the keyinfo cache as it provides minimal performance improvements, and then only at SQL preparation time, not at runtime, and it has problems with data races in shared-cache mode. We might later add the keyinfo cache back but only enable it when shared-cache mode is off.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | threadtest4
Files: files | file ages | folders
SHA1: b7489f9451628c68f1dfc1d457fc161a0921c631
User & Date: drh 2014-12-12 00:20:37
Context
2014-12-12
00:26
Merge the cell overflow page number cache thread race fix from trunk. check-in: cefad47e user: drh tags: threadtest4
00:20
Fix a bug in the threadtest4.c program. Remove the keyinfo cache as it provides minimal performance improvements, and then only at SQL preparation time, not at runtime, and it has problems with data races in shared-cache mode. We might later add the keyinfo cache back but only enable it when shared-cache mode is off. check-in: b7489f94 user: drh tags: threadtest4
2014-12-11
19:29
Add the threadtest4.c test program. Not yet working. check-in: ec3a7446 user: drh tags: threadtest4
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/build.c.

   431    431   /*
   432    432   ** Reclaim the memory used by an index
   433    433   */
   434    434   static void freeIndex(sqlite3 *db, Index *p){
   435    435   #ifndef SQLITE_OMIT_ANALYZE
   436    436     sqlite3DeleteIndexSamples(db, p);
   437    437   #endif
   438         -  if( db==0 || db->pnBytesFreed==0 ) sqlite3KeyInfoUnref(p->pKeyInfo);
   439    438     sqlite3ExprDelete(db, p->pPartIdxWhere);
   440    439     sqlite3DbFree(db, p->zColAff);
   441    440     if( p->isResized ) sqlite3DbFree(db, p->azColl);
   442    441   #ifdef SQLITE_ENABLE_STAT3_OR_STAT4
   443    442     sqlite3_free(p->aiRowEst);
   444    443   #endif
   445    444     sqlite3DbFree(db, p);
................................................................................
  4186   4185   ** So there might be multiple references to the returned pointer.  The
  4187   4186   ** caller should not try to modify the KeyInfo object.
  4188   4187   **
  4189   4188   ** The caller should invoke sqlite3KeyInfoUnref() on the returned object
  4190   4189   ** when it has finished using it.
  4191   4190   */
  4192   4191   KeyInfo *sqlite3KeyInfoOfIndex(Parse *pParse, Index *pIdx){
         4192  +  int i;
         4193  +  int nCol = pIdx->nColumn;
         4194  +  int nKey = pIdx->nKeyCol;
         4195  +  KeyInfo *pKey;
  4193   4196     if( pParse->nErr ) return 0;
  4194         -#ifndef SQLITE_OMIT_SHARED_CACHE
  4195         -  if( pIdx->pKeyInfo && pIdx->pKeyInfo->db!=pParse->db ){
  4196         -    sqlite3KeyInfoUnref(pIdx->pKeyInfo);
  4197         -    pIdx->pKeyInfo = 0;
         4197  +  if( pIdx->uniqNotNull ){
         4198  +    pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
         4199  +  }else{
         4200  +    pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
  4198   4201     }
  4199         -#endif
  4200         -  if( pIdx->pKeyInfo==0 ){
  4201         -    int i;
  4202         -    int nCol = pIdx->nColumn;
  4203         -    int nKey = pIdx->nKeyCol;
  4204         -    KeyInfo *pKey;
  4205         -    if( pIdx->uniqNotNull ){
  4206         -      pKey = sqlite3KeyInfoAlloc(pParse->db, nKey, nCol-nKey);
  4207         -    }else{
  4208         -      pKey = sqlite3KeyInfoAlloc(pParse->db, nCol, 0);
         4202  +  if( pKey ){
         4203  +    assert( sqlite3KeyInfoIsWriteable(pKey) );
         4204  +    for(i=0; i<nCol; i++){
         4205  +      char *zColl = pIdx->azColl[i];
         4206  +      assert( zColl!=0 );
         4207  +      pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
         4208  +                        sqlite3LocateCollSeq(pParse, zColl);
         4209  +      pKey->aSortOrder[i] = pIdx->aSortOrder[i];
  4209   4210       }
  4210         -    if( pKey ){
  4211         -      assert( sqlite3KeyInfoIsWriteable(pKey) );
  4212         -      for(i=0; i<nCol; i++){
  4213         -        char *zColl = pIdx->azColl[i];
  4214         -        assert( zColl!=0 );
  4215         -        pKey->aColl[i] = strcmp(zColl,"BINARY")==0 ? 0 :
  4216         -                          sqlite3LocateCollSeq(pParse, zColl);
  4217         -        pKey->aSortOrder[i] = pIdx->aSortOrder[i];
  4218         -      }
  4219         -      if( pParse->nErr ){
  4220         -        sqlite3KeyInfoUnref(pKey);
  4221         -      }else{
  4222         -        pIdx->pKeyInfo = pKey;
  4223         -      }
         4211  +    if( pParse->nErr ){
         4212  +      sqlite3KeyInfoUnref(pKey);
         4213  +      pKey = 0;
  4224   4214       }
  4225   4215     }
  4226         -  return sqlite3KeyInfoRef(pIdx->pKeyInfo);
         4216  +  return pKey;
  4227   4217   }
  4228   4218   
  4229   4219   #ifndef SQLITE_OMIT_CTE
  4230   4220   /* 
  4231   4221   ** This routine is invoked once per CTE by the parser while parsing a 
  4232   4222   ** WITH clause. 
  4233   4223   */

Changes to src/main.c.

  1028   1028     /* Free any outstanding Savepoint structures. */
  1029   1029     sqlite3CloseSavepoints(db);
  1030   1030   
  1031   1031     /* Close all database connections */
  1032   1032     for(j=0; j<db->nDb; j++){
  1033   1033       struct Db *pDb = &db->aDb[j];
  1034   1034       if( pDb->pBt ){
  1035         -      if( pDb->pSchema ){
  1036         -        /* Must clear the KeyInfo cache.  See ticket [e4a18565a36884b00edf] */
  1037         -        sqlite3BtreeEnter(pDb->pBt);
  1038         -        for(i=sqliteHashFirst(&pDb->pSchema->idxHash); i; i=sqliteHashNext(i)){
  1039         -          Index *pIdx = sqliteHashData(i);
  1040         -          sqlite3KeyInfoUnref(pIdx->pKeyInfo);
  1041         -          pIdx->pKeyInfo = 0;
  1042         -        }
  1043         -        sqlite3BtreeLeave(pDb->pBt);
  1044         -      }
  1045   1035         sqlite3BtreeClose(pDb->pBt);
  1046   1036         pDb->pBt = 0;
  1047   1037         if( j!=1 ){
  1048   1038           pDb->pSchema = 0;
  1049   1039         }
  1050   1040       }
  1051   1041     }
................................................................................
  2165   2155   ** argument.  For now, this simply calls the internal sqlite3ErrStr()
  2166   2156   ** function.
  2167   2157   */
  2168   2158   const char *sqlite3_errstr(int rc){
  2169   2159     return sqlite3ErrStr(rc);
  2170   2160   }
  2171   2161   
  2172         -/*
  2173         -** Invalidate all cached KeyInfo objects for database connection "db"
  2174         -*/
  2175         -static void invalidateCachedKeyInfo(sqlite3 *db){
  2176         -  Db *pDb;                    /* A single database */
  2177         -  int iDb;                    /* The database index number */
  2178         -  HashElem *k;                /* For looping over tables in pDb */
  2179         -  Table *pTab;                /* A table in the database */
  2180         -  Index *pIdx;                /* Each index */
  2181         -
  2182         -  for(iDb=0, pDb=db->aDb; iDb<db->nDb; iDb++, pDb++){
  2183         -    if( pDb->pBt==0 ) continue;
  2184         -    sqlite3BtreeEnter(pDb->pBt);
  2185         -    for(k=sqliteHashFirst(&pDb->pSchema->tblHash);  k; k=sqliteHashNext(k)){
  2186         -      pTab = (Table*)sqliteHashData(k);
  2187         -      for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
  2188         -        if( pIdx->pKeyInfo && pIdx->pKeyInfo->db==db ){
  2189         -          sqlite3KeyInfoUnref(pIdx->pKeyInfo);
  2190         -          pIdx->pKeyInfo = 0;
  2191         -        }
  2192         -      }
  2193         -    }
  2194         -    sqlite3BtreeLeave(pDb->pBt);
  2195         -  }
  2196         -}
  2197         -
  2198   2162   /*
  2199   2163   ** Create a new collating function for database "db".  The name is zName
  2200   2164   ** and the encoding is enc.
  2201   2165   */
  2202   2166   static int createCollation(
  2203   2167     sqlite3* db,
  2204   2168     const char *zName, 
................................................................................
  2234   2198     if( pColl && pColl->xCmp ){
  2235   2199       if( db->nVdbeActive ){
  2236   2200         sqlite3ErrorWithMsg(db, SQLITE_BUSY, 
  2237   2201           "unable to delete/modify collation sequence due to active statements");
  2238   2202         return SQLITE_BUSY;
  2239   2203       }
  2240   2204       sqlite3ExpirePreparedStatements(db);
  2241         -    invalidateCachedKeyInfo(db);
  2242   2205   
  2243   2206       /* If collation sequence pColl was created directly by a call to
  2244   2207       ** sqlite3_create_collation, and not generated by synthCollSeq(),
  2245   2208       ** then any copies made by synthCollSeq() need to be invalidated.
  2246   2209       ** Also, collation destructor - CollSeq.xDel() - function may need
  2247   2210       ** to be called.
  2248   2211       */ 

Changes to src/sqliteInt.h.

  1780   1780     Table *pTable;           /* The SQL table being indexed */
  1781   1781     char *zColAff;           /* String defining the affinity of each column */
  1782   1782     Index *pNext;            /* The next index associated with the same table */
  1783   1783     Schema *pSchema;         /* Schema containing this index */
  1784   1784     u8 *aSortOrder;          /* for each column: True==DESC, False==ASC */
  1785   1785     char **azColl;           /* Array of collation sequence names for index */
  1786   1786     Expr *pPartIdxWhere;     /* WHERE clause for partial indices */
  1787         -  KeyInfo *pKeyInfo;       /* A KeyInfo object suitable for this index */
  1788   1787     int tnum;                /* DB Page containing root of this index */
  1789   1788     LogEst szIdxRow;         /* Estimated average row size in bytes */
  1790   1789     u16 nKeyCol;             /* Number of columns forming the key */
  1791   1790     u16 nColumn;             /* Number of columns stored in the index */
  1792   1791     u8 onError;              /* OE_Abort, OE_Ignore, OE_Replace, or OE_None */
  1793   1792     unsigned idxType:2;      /* 1==UNIQUE, 2==PRIMARY KEY, 0==CREATE INDEX */
  1794   1793     unsigned bUnordered:1;   /* Use this index for == or IN queries only */

Changes to src/where.c.

  3937   3937     if( p->wsFlags & (WHERE_VIRTUALTABLE|WHERE_AUTO_INDEX) ){
  3938   3938       if( (p->wsFlags & WHERE_VIRTUALTABLE)!=0 && p->u.vtab.needFree ){
  3939   3939         sqlite3_free(p->u.vtab.idxStr);
  3940   3940         p->u.vtab.needFree = 0;
  3941   3941         p->u.vtab.idxStr = 0;
  3942   3942       }else if( (p->wsFlags & WHERE_AUTO_INDEX)!=0 && p->u.btree.pIndex!=0 ){
  3943   3943         sqlite3DbFree(db, p->u.btree.pIndex->zColAff);
  3944         -      sqlite3KeyInfoUnref(p->u.btree.pIndex->pKeyInfo);
  3945   3944         sqlite3DbFree(db, p->u.btree.pIndex);
  3946   3945         p->u.btree.pIndex = 0;
  3947   3946       }
  3948   3947     }
  3949   3948   }
  3950   3949   
  3951   3950   /*

Changes to test/threadtest4.c.

   297    297       rc = sqlite3_step(pStmt);
   298    298       if( rc!=SQLITE_ROW ){
   299    299         worker_error(p, "Failed to step: %s", sqlite3_sql(pStmt));
   300    300       }else if( sqlite3_column_int(pStmt, 0)!=400 ){
   301    301         worker_error(p, "Wrong result: %d", sqlite3_column_int(pStmt,0));
   302    302       }
   303    303       if( p->nErr ) break;
          304  +    sqlite3_finalize(pStmt);
   304    305   
   305    306       worker_delete_all_content(p, (p->tid+iOuter)%2);
   306    307       worker_close_connection(p);
   307    308       p->db = 0;
   308    309     }
   309    310     worker_close_connection(p);
   310    311     printf("worker %d finished\n", p->tid); fflush(stdout);