/ Check-in [435b57dc]
Login

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

Overview
Comment:Merge in the latest changes from the trunk.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1:435b57dc2be7b071270a6cddece297758b8153aa
User & Date: drh 2011-04-06 22:33:50
Context
2011-04-06
23:39
Fix VC++ compiler warnings. check-in: 7b7c8d36 user: drh tags: sessions
22:33
Merge in the latest changes from the trunk. check-in: 435b57dc user: drh tags: sessions
22:05
Fix a performance regression: Keep two btree masks in each prepared statement; one for btrees used and another for btrees that require locks. Only try to lock the btrees identified by the second mask. check-in: 614de91a user: drh tags: trunk
2011-04-05
22:13
Merge the latest trunk changes into the sessions branch. check-in: 45f20261 user: drh tags: sessions
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/btmutex.c.

198
199
200
201
202
203
204








205
206
207
208
209
210
211
  Btree *p;
  assert( sqlite3_mutex_held(db->mutex) );
  for(i=0; i<db->nDb; i++){
    p = db->aDb[i].pBt;
    if( p ) sqlite3BtreeLeave(p);
  }
}









#ifndef NDEBUG
/*
** Return true if the current thread holds the database connection
** mutex and all required BtShared mutexes.
**
** This routine is used inside assert() statements only.







>
>
>
>
>
>
>
>







198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
  Btree *p;
  assert( sqlite3_mutex_held(db->mutex) );
  for(i=0; i<db->nDb; i++){
    p = db->aDb[i].pBt;
    if( p ) sqlite3BtreeLeave(p);
  }
}

/*
** Return true if a particular Btree requires a lock.  Return FALSE if
** no lock is ever required since it is not sharable.
*/
int sqlite3BtreeSharable(Btree *p){
  return p->sharable;
}

#ifndef NDEBUG
/*
** Return true if the current thread holds the database connection
** mutex and all required BtShared mutexes.
**
** This routine is used inside assert() statements only.

Changes to src/btree.c.

2123
2124
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
....
2178
2179
2180
2181
2182
2183
2184

2185
2186
2187
2188
2189
2190
2191
  sqlite3BtreeEnter(p);
  assert( pBt && pBt->pPager );
  rc = sqlite3PagerNosync(pBt->pPager);
  sqlite3BtreeLeave(p);
  return rc;
}

#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Change the default pages size and the number of reserved bytes per page.
** Or, if the page size has already been fixed, return SQLITE_READONLY 
** without changing anything.
**
** The page size must be a power of 2 between 512 and 65536.  If the page
** size supplied does not meet this constraint then the page size is not
................................................................................
/*
** Return the currently defined page size
*/
int sqlite3BtreeGetPageSize(Btree *p){
  return p->pBt->pageSize;
}


/*
** Return the number of bytes of space at the end of every page that
** are intentually left unused.  This is the "reserved" space that is
** sometimes used by extensions.
*/
int sqlite3BtreeGetReserve(Btree *p){
  int n;







<







 







>







2123
2124
2125
2126
2127
2128
2129

2130
2131
2132
2133
2134
2135
2136
....
2177
2178
2179
2180
2181
2182
2183
2184
2185
2186
2187
2188
2189
2190
2191
  sqlite3BtreeEnter(p);
  assert( pBt && pBt->pPager );
  rc = sqlite3PagerNosync(pBt->pPager);
  sqlite3BtreeLeave(p);
  return rc;
}


/*
** Change the default pages size and the number of reserved bytes per page.
** Or, if the page size has already been fixed, return SQLITE_READONLY 
** without changing anything.
**
** The page size must be a power of 2 between 512 and 65536.  If the page
** size supplied does not meet this constraint then the page size is not
................................................................................
/*
** Return the currently defined page size
*/
int sqlite3BtreeGetPageSize(Btree *p){
  return p->pBt->pageSize;
}

#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Return the number of bytes of space at the end of every page that
** are intentually left unused.  This is the "reserved" space that is
** sometimes used by extensions.
*/
int sqlite3BtreeGetReserve(Btree *p){
  int n;

Changes to src/btree.h.

208
209
210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226

227
228
229
230
231
232
233
234
235
236
237
238
  void sqlite3BtreeEnterAll(sqlite3*);
#else
# define sqlite3BtreeEnter(X) 
# define sqlite3BtreeEnterAll(X)
#endif

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE

  void sqlite3BtreeLeave(Btree*);
  void sqlite3BtreeEnterCursor(BtCursor*);
  void sqlite3BtreeLeaveCursor(BtCursor*);
  void sqlite3BtreeLeaveAll(sqlite3*);
#ifndef NDEBUG
  /* These routines are used inside assert() statements only. */
  int sqlite3BtreeHoldsMutex(Btree*);
  int sqlite3BtreeHoldsAllMutexes(sqlite3*);
  int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
#endif
#else


# define sqlite3BtreeLeave(X)
# define sqlite3BtreeEnterCursor(X)
# define sqlite3BtreeLeaveCursor(X)
# define sqlite3BtreeLeaveAll(X)

# define sqlite3BtreeHoldsMutex(X) 1
# define sqlite3BtreeHoldsAllMutexes(X) 1
# define sqlite3SchemaMutexHeld(X,Y,Z) 1
#endif


#endif /* _BTREE_H_ */







>












>












208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
  void sqlite3BtreeEnterAll(sqlite3*);
#else
# define sqlite3BtreeEnter(X) 
# define sqlite3BtreeEnterAll(X)
#endif

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE
  int sqlite3BtreeSharable(Btree*);
  void sqlite3BtreeLeave(Btree*);
  void sqlite3BtreeEnterCursor(BtCursor*);
  void sqlite3BtreeLeaveCursor(BtCursor*);
  void sqlite3BtreeLeaveAll(sqlite3*);
#ifndef NDEBUG
  /* These routines are used inside assert() statements only. */
  int sqlite3BtreeHoldsMutex(Btree*);
  int sqlite3BtreeHoldsAllMutexes(sqlite3*);
  int sqlite3SchemaMutexHeld(sqlite3*,int,Schema*);
#endif
#else

# define sqlite3BtreeSharable(X) 0
# define sqlite3BtreeLeave(X)
# define sqlite3BtreeEnterCursor(X)
# define sqlite3BtreeLeaveCursor(X)
# define sqlite3BtreeLeaveAll(X)

# define sqlite3BtreeHoldsMutex(X) 1
# define sqlite3BtreeHoldsAllMutexes(X) 1
# define sqlite3SchemaMutexHeld(X,Y,Z) 1
#endif


#endif /* _BTREE_H_ */

Changes to src/loadext.c.

66
67
68
69
70
71
72





73
74
75
76
77
78
79
# define sqlite3_column_origin_name16   0
#endif

#ifdef SQLITE_OMIT_COMPLETE
# define sqlite3_complete 0
# define sqlite3_complete16 0
#endif






#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
# define sqlite3_progress_handler 0
#endif

#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3_create_module 0







>
>
>
>
>







66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# define sqlite3_column_origin_name16   0
#endif

#ifdef SQLITE_OMIT_COMPLETE
# define sqlite3_complete 0
# define sqlite3_complete16 0
#endif

#ifdef SQLITE_OMIT_DECLTYPE
# define sqlite3_column_decltype16      0
# define sqlite3_column_decltype        0
#endif

#ifdef SQLITE_OMIT_PROGRESS_CALLBACK
# define sqlite3_progress_handler 0
#endif

#ifdef SQLITE_OMIT_VIRTUALTABLE
# define sqlite3_create_module 0

Changes to src/os_unix.c.

3394
3395
3396
3397
3398
3399
3400
3401
3402
3403
3404
3405
3406
3407
3408
3409
3410
3411
3412


3413
3414
3415
3416
3417
3418
3419
      ** ftruncate() to set the file size, then write a single byte to
      ** the last byte in each block within the extended region. This
      ** is the same technique used by glibc to implement posix_fallocate()
      ** on systems that do not have a real fallocate() system call.
      */
      int nBlk = buf.st_blksize;  /* File-system block size */
      i64 iWrite;                 /* Next offset to write to */
      int nWrite;                 /* Return value from seekAndWrite() */

      if( robust_ftruncate(pFile->h, nSize) ){
        pFile->lastErrno = errno;
        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
      }
      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
      do {
        nWrite = seekAndWrite(pFile, iWrite, "", 1);
        iWrite += nBlk;
      } while( nWrite==1 && iWrite<nSize );
      if( nWrite!=1 ) return SQLITE_IOERR_WRITE;


#endif
    }
  }

  return SQLITE_OK;
}








<






|
|
<
<
|
>
>







3394
3395
3396
3397
3398
3399
3400

3401
3402
3403
3404
3405
3406
3407
3408


3409
3410
3411
3412
3413
3414
3415
3416
3417
3418
      ** ftruncate() to set the file size, then write a single byte to
      ** the last byte in each block within the extended region. This
      ** is the same technique used by glibc to implement posix_fallocate()
      ** on systems that do not have a real fallocate() system call.
      */
      int nBlk = buf.st_blksize;  /* File-system block size */
      i64 iWrite;                 /* Next offset to write to */


      if( robust_ftruncate(pFile->h, nSize) ){
        pFile->lastErrno = errno;
        return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
      }
      iWrite = ((buf.st_size + 2*nBlk - 1)/nBlk)*nBlk-1;
      while( iWrite<nSize ){
        int nWrite = seekAndWrite(pFile, iWrite, "", 1);


        if( nWrite!=1 ) return SQLITE_IOERR_WRITE;
        iWrite += nBlk;
      }
#endif
    }
  }

  return SQLITE_OK;
}

Changes to src/select.c.

802
803
804
805
806
807
808
















809
810
811
812
813
814
815
...
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
  if( pParse->explain==2 ){
    Vdbe *v = pParse->pVdbe;
    char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
}

















/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of one of the two forms:
**
**   "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
**   "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
................................................................................
    char *zMsg = sqlite3MPrintf(
        pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
        bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
    );
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
}

/*
** Assign expression b to lvalue a. A second, no-op, version of this macro
** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
** in sqlite3Select() to assign values to structure member variables that
** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
** code with #ifndef directives.
*/
# define explainSetInteger(a, b) a = b

#else
/* No-op versions of the explainXXX() functions and macros. */
# define explainTempTable(y,z)
# define explainComposite(v,w,x,y,z)
# define explainSetInteger(y,z)
#endif

/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







<
<
<
<
<
<
<
<
<
<


<

<







802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
...
849
850
851
852
853
854
855










856
857

858

859
860
861
862
863
864
865
  if( pParse->explain==2 ){
    Vdbe *v = pParse->pVdbe;
    char *zMsg = sqlite3MPrintf(pParse->db, "USE TEMP B-TREE FOR %s", zUsage);
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
}

/*
** Assign expression b to lvalue a. A second, no-op, version of this macro
** is provided when SQLITE_OMIT_EXPLAIN is defined. This allows the code
** in sqlite3Select() to assign values to structure member variables that
** only exist if SQLITE_OMIT_EXPLAIN is not defined without polluting the
** code with #ifndef directives.
*/
# define explainSetInteger(a, b) a = b

#else
/* No-op versions of the explainXXX() functions and macros. */
# define explainTempTable(y,z)
# define explainSetInteger(y,z)
#endif

#if !defined(SQLITE_OMIT_EXPLAIN) && !defined(SQLITE_OMIT_COMPOUND_SELECT)
/*
** Unless an "EXPLAIN QUERY PLAN" command is being processed, this function
** is a no-op. Otherwise, it adds a single row of output to the EQP result,
** where the caption is of one of the two forms:
**
**   "COMPOSITE SUBQUERIES iSub1 and iSub2 (op)"
**   "COMPOSITE SUBQUERIES iSub1 and iSub2 USING TEMP B-TREE (op)"
................................................................................
    char *zMsg = sqlite3MPrintf(
        pParse->db, "COMPOUND SUBQUERIES %d AND %d %s(%s)", iSub1, iSub2,
        bUseTmp?"USING TEMP B-TREE ":"", selectOpName(op)
    );
    sqlite3VdbeAddOp4(v, OP_Explain, pParse->iSelectId, 0, 0, zMsg, P4_DYNAMIC);
  }
}










#else
/* No-op versions of the explainXXX() functions and macros. */

# define explainComposite(v,w,x,y,z)

#endif

/*
** If the inner loop was generated using a non-null pOrderBy argument,
** then the results were placed in a sorter.  After the loop is terminated
** we need to run the sorter and output the results.  The following
** routine generates the code needed to do that.

Changes to src/sqliteLimit.h.

114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
*/
#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT  1000
#endif

/*
** The maximum number of attached databases.  This must be between 0
** and 30.  The upper bound on 30 is because a 32-bit integer bitmap
** is used internally to track attached databases.
*/
#ifndef SQLITE_MAX_ATTACHED
# define SQLITE_MAX_ATTACHED 10
#endif









|







114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
*/
#ifndef SQLITE_DEFAULT_WAL_AUTOCHECKPOINT
# define SQLITE_DEFAULT_WAL_AUTOCHECKPOINT  1000
#endif

/*
** The maximum number of attached databases.  This must be between 0
** and 62.  The upper bound on 62 is because a 64-bit integer bitmap
** is used internally to track attached databases.
*/
#ifndef SQLITE_MAX_ATTACHED
# define SQLITE_MAX_ATTACHED 10
#endif


Changes to src/test_server.c.

449
450
451
452
453
454
455
456
457
458
459
460
461
462
463

    /* Signal the client that the message has been processed.
    */
    pMsg->op = MSG_Done;
    pthread_mutex_unlock(&pMsg->clientMutex);
    pthread_cond_signal(&pMsg->clientWakeup);
  }
  sqlite3_thread_cleanup();
  pthread_mutex_unlock(&g.serverMutex);
  return 0;
}

/*
** Start a server thread if one is not already running.  If there
** is aleady a server thread running, the new thread will quickly







<







449
450
451
452
453
454
455

456
457
458
459
460
461
462

    /* Signal the client that the message has been processed.
    */
    pMsg->op = MSG_Done;
    pthread_mutex_unlock(&pMsg->clientMutex);
    pthread_cond_signal(&pMsg->clientWakeup);
  }

  pthread_mutex_unlock(&g.serverMutex);
  return 0;
}

/*
** Start a server thread if one is not already running.  If there
** is aleady a server thread running, the new thread will quickly

Changes to src/vdbe.c.

4693
4694
4695
4696
4697
4698
4699
4700
4701
4702
4703
4704
4705
4706
4707
4708
  ** sqlite3InitCallback().
  */
#ifdef SQLITE_DEBUG
  for(iDb=0; iDb<db->nDb; iDb++){
    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  }
#endif
  assert( p->btreeMask == ~(yDbMask)0 );


  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;







<
<







4693
4694
4695
4696
4697
4698
4699


4700
4701
4702
4703
4704
4705
4706
  ** sqlite3InitCallback().
  */
#ifdef SQLITE_DEBUG
  for(iDb=0; iDb<db->nDb; iDb++){
    assert( iDb==1 || sqlite3BtreeHoldsMutex(db->aDb[iDb].pBt) );
  }
#endif



  iDb = pOp->p1;
  assert( iDb>=0 && iDb<db->nDb );
  assert( DbHasProperty(db, iDb, DB_SchemaLoaded) );
  /* Used to be a conditional */ {
    zMaster = SCHEMA_TABLE(iDb);
    initData.db = db;

Changes to src/vdbeInt.h.

299
300
301
302
303
304
305

306
307
308
309
310
311
312
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  u8 inVtabMethod;        /* See comments above */
  u8 usesStmtJournal;     /* True if uses a statement journal */
  u8 readOnly;            /* True for read-only statements */
  u8 isPrepareV2;         /* True if prepared with prepare_v2() */
  int nChange;            /* Number of db changes made since last reset */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */

  int iStatement;         /* Statement number (or 0 if has not opened stmt) */
  int aCounter[3];        /* Counters used by sqlite3_stmt_status() */
#ifndef SQLITE_OMIT_TRACE
  i64 startTime;          /* Time when query started - used for profiling */
#endif
  i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
  i64 nStmtDefCons;       /* Number of def. constraints when stmt started */







>







299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
  u8 minWriteFileFormat;  /* Minimum file format for writable database files */
  u8 inVtabMethod;        /* See comments above */
  u8 usesStmtJournal;     /* True if uses a statement journal */
  u8 readOnly;            /* True for read-only statements */
  u8 isPrepareV2;         /* True if prepared with prepare_v2() */
  int nChange;            /* Number of db changes made since last reset */
  yDbMask btreeMask;      /* Bitmask of db->aDb[] entries referenced */
  yDbMask lockMask;       /* Subset of btreeMask that requires a lock */
  int iStatement;         /* Statement number (or 0 if has not opened stmt) */
  int aCounter[3];        /* Counters used by sqlite3_stmt_status() */
#ifndef SQLITE_OMIT_TRACE
  i64 startTime;          /* Time when query started - used for profiling */
#endif
  i64 nFkConstraint;      /* Number of imm. FK constraints this VM */
  i64 nStmtDefCons;       /* Number of def. constraints when stmt started */

Changes to src/vdbeaux.c.

157
158
159
160
161
162
163
164

165
166
167
168
169
170
171
...
955
956
957
958
959
960
961



962
963
964
965
966
967
968
...
982
983
984
985
986
987
988




989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006




1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
  p->expired = 0;
  if( op==OP_ParseSchema ){
    /* Any program that uses the OP_ParseSchema opcode needs to lock
    ** all btrees. */
    p->btreeMask = ~(yDbMask)0;

  }
#ifdef SQLITE_DEBUG
  pOp->zComment = 0;
  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
#endif
#ifdef VDBE_PROFILE
  pOp->cycles = 0;
................................................................................
** attached databases that they will be using.  A mask of these databases
** is maintained in p->btreeMask and is used for locking and other purposes.
*/
void sqlite3VdbeUsesBtree(Vdbe *p, int i){
  assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
  assert( i<(int)sizeof(p->btreeMask)*8 );
  p->btreeMask |= ((yDbMask)1)<<i;



}

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
/*
** If SQLite is compiled to support shared-cache mode and to be threadsafe,
** this routine obtains the mutex associated with each BtShared structure
** that may be accessed by the VM passed as an argument. In doing so it also
................................................................................
** corresponding to btrees that use shared cache.  Then the runtime of
** this routine is N*N.  But as N is rarely more than 1, this should not
** be a problem.
*/
void sqlite3VdbeEnter(Vdbe *p){
  int i;
  yDbMask mask;




  sqlite3 *db = p->db;
  Db *aDb = db->aDb;
  int nDb = db->nDb;
  for(i=0, mask=1; i<nDb; i++, mask += mask){
    if( i!=1 && (mask & p->btreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
      sqlite3BtreeEnter(aDb[i].pBt);
    }
  }
}
#endif

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
/*
** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
*/
void sqlite3VdbeLeave(Vdbe *p){
  int i;
  yDbMask mask;




  sqlite3 *db = p->db;
  Db *aDb = db->aDb;
  int nDb = db->nDb;

  for(i=0, mask=1; i<nDb; i++, mask += mask){
    if( i!=1 && (mask & p->btreeMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
      sqlite3BtreeLeave(aDb[i].pBt);
    }
  }
}
#endif

#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)







|
>







 







>
>
>







 







>
>
>
>
|
|
|

|













>
>
>
>
|
|
|
<

|







157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
...
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
...
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021

1022
1023
1024
1025
1026
1027
1028
1029
1030
  pOp->p3 = p3;
  pOp->p4.p = 0;
  pOp->p4type = P4_NOTUSED;
  p->expired = 0;
  if( op==OP_ParseSchema ){
    /* Any program that uses the OP_ParseSchema opcode needs to lock
    ** all btrees. */
    int j;
    for(j=0; j<p->db->nDb; j++) sqlite3VdbeUsesBtree(p, j);
  }
#ifdef SQLITE_DEBUG
  pOp->zComment = 0;
  if( sqlite3VdbeAddopTrace ) sqlite3VdbePrintOp(0, i, &p->aOp[i]);
#endif
#ifdef VDBE_PROFILE
  pOp->cycles = 0;
................................................................................
** attached databases that they will be using.  A mask of these databases
** is maintained in p->btreeMask and is used for locking and other purposes.
*/
void sqlite3VdbeUsesBtree(Vdbe *p, int i){
  assert( i>=0 && i<p->db->nDb && i<(int)sizeof(yDbMask)*8 );
  assert( i<(int)sizeof(p->btreeMask)*8 );
  p->btreeMask |= ((yDbMask)1)<<i;
  if( i!=1 && sqlite3BtreeSharable(p->db->aDb[i].pBt) ){
    p->lockMask |= ((yDbMask)1)<<i;
  }
}

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
/*
** If SQLite is compiled to support shared-cache mode and to be threadsafe,
** this routine obtains the mutex associated with each BtShared structure
** that may be accessed by the VM passed as an argument. In doing so it also
................................................................................
** corresponding to btrees that use shared cache.  Then the runtime of
** this routine is N*N.  But as N is rarely more than 1, this should not
** be a problem.
*/
void sqlite3VdbeEnter(Vdbe *p){
  int i;
  yDbMask mask;
  sqlite3 *db;
  Db *aDb;
  int nDb;
  if( p->lockMask==0 ) return;  /* The common case */
  db = p->db;
  aDb = db->aDb;
  nDb = db->nDb;
  for(i=0, mask=1; i<nDb; i++, mask += mask){
    if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
      sqlite3BtreeEnter(aDb[i].pBt);
    }
  }
}
#endif

#if !defined(SQLITE_OMIT_SHARED_CACHE) && SQLITE_THREADSAFE>0
/*
** Unlock all of the btrees previously locked by a call to sqlite3VdbeEnter().
*/
void sqlite3VdbeLeave(Vdbe *p){
  int i;
  yDbMask mask;
  sqlite3 *db;
  Db *aDb;
  int nDb;
  if( p->lockMask==0 ) return;  /* The common case */
  db = p->db;
  aDb = db->aDb;
  nDb = db->nDb;

  for(i=0, mask=1; i<nDb; i++, mask += mask){
    if( i!=1 && (mask & p->lockMask)!=0 && ALWAYS(aDb[i].pBt!=0) ){
      sqlite3BtreeLeave(aDb[i].pBt);
    }
  }
}
#endif

#if defined(VDBE_PROFILE) || defined(SQLITE_DEBUG)

Added test/attach4.test.

































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# 200 July 1
#
# The author disclaims copyright to this source code.  In place of
# a legal notice, here is a blessing:
#
#    May you do good and not evil.
#    May you find forgiveness for yourself and forgive others.
#    May you share freely, never taking more than you give.
#
#***********************************************************************
# This file implements regression tests for SQLite library.  The
# focus of this script is attaching many database files to a single
# connection.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl

set testprefix attach4

ifcapable !attach {
  finish_test
  return
}

puts "Testing with SQLITE_MAX_ATTACHED=$SQLITE_MAX_ATTACHED"

set files {main test.db}
for {set ii 0} {$ii < $SQLITE_MAX_ATTACHED} {incr ii} {
  lappend files aux$ii "test.db$ii"
}

do_test 1.1 {
  sqlite3_limit db SQLITE_LIMIT_ATTACHED -1
} $SQLITE_MAX_ATTACHED

do_test 1.2.1 {
  db close
  foreach {name f} $files { forcedelete $f }
  sqlite3 db test.db
  
  foreach {name f} $files {
    if {$name == "main"} continue
    execsql "ATTACH '$f' AS $name"
  }

  db eval {PRAGMA database_list} {
    lappend L $name [file tail $file]
  }
  set L
} $files

do_catchsql_test 1.2.2 {
  ATTACH 'x.db' AS next;
} [list 1 "too many attached databases - max $SQLITE_MAX_ATTACHED"]

do_test 1.3 {
  execsql BEGIN;
  foreach {name f} $files {
    execsql "CREATE TABLE $name.tbl(x)"
    execsql "INSERT INTO $name.tbl VALUES('$f')"
  }
  execsql COMMIT;
} {}

do_test 1.4 {
  set L [list]
  foreach {name f} $files {
    lappend L $name [execsql "SELECT x FROM $name.tbl"]
  }
  set L
} $files

set L [list]
set S ""
foreach {name f} $files {
  lappend L wal
  append S "
    PRAGMA $name.journal_mode = WAL;
    UPDATE $name.tbl SET x = '$name';
  "
}
do_execsql_test 1.5 $S $L

do_test 1.6 {
  set L [list]
  foreach {name f} $files {
    lappend L [execsql "SELECT x FROM $name.tbl"] $f
  }
  set L
} $files

do_test 1.7 {
  execsql BEGIN;
  foreach {name f} $files {
    execsql "UPDATE $name.tbl SET x = '$f'"
  }
  execsql COMMIT;
} {}

do_test 1.8 {
  set L [list]
  foreach {name f} $files {
    lappend L $name [execsql "SELECT x FROM $name.tbl"]
  }
  set L
} $files

db close
foreach {name f} $files { forcedelete $f }

finish_test

Changes to test/releasetest.tcl.

56
57
58
59
60
61
62





63
64
65
66
67
68
69
...
140
141
142
143
144
145
146

147
148
149
150
151
152
153
154
155
156
157

158
159
160
161
162
163
164
  ########################################################
}

array set ::Configs {
  "Default" {
    -O2
  }





  "Unlock-Notify" {
    -O2
    -DSQLITE_ENABLE_UNLOCK_NOTIFY
    -DSQLITE_THREADSAFE
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "Secure-Delete" {
................................................................................
    -DSQLITE_MAX_LENGTH=2147483645
    -DSQLITE_MAX_VARIABLE_NUMBER=500000
    -DSQLITE_DEBUG=1 
    -DSQLITE_PREFER_PROXY_LOCKING=1
  }
  "Extra-Robustness" {
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1

  }
}

array set ::Platforms {
  Linux-x86_64 {
    "Secure-Delete"           test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Update-Delete-Limit"     test
    "Debug-One"               test
    "Extra-Robustness"        test
    "Device-Two"              test

    "Default"                 "threadtest test"
    "Device-One"              fulltest
  }
  Linux-i686 {
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Device-One"              test
    "Device-Two"              test







>
>
>
>
>







 







>











>







56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
...
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
  ########################################################
}

array set ::Configs {
  "Default" {
    -O2
  }
  "Ftrapv" {
    -O2 -ftrapv
    -DSQLITE_MAX_ATTACHED=55
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "Unlock-Notify" {
    -O2
    -DSQLITE_ENABLE_UNLOCK_NOTIFY
    -DSQLITE_THREADSAFE
    -DSQLITE_TCL_DEFAULT_FULLMUTEX=1
  }
  "Secure-Delete" {
................................................................................
    -DSQLITE_MAX_LENGTH=2147483645
    -DSQLITE_MAX_VARIABLE_NUMBER=500000
    -DSQLITE_DEBUG=1 
    -DSQLITE_PREFER_PROXY_LOCKING=1
  }
  "Extra-Robustness" {
    -DSQLITE_ENABLE_OVERSIZE_CELL_CHECK=1
    -DSQLITE_MAX_ATTACHED=62
  }
}

array set ::Platforms {
  Linux-x86_64 {
    "Secure-Delete"           test
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Update-Delete-Limit"     test
    "Debug-One"               test
    "Extra-Robustness"        test
    "Device-Two"              test
    "Ftrapv"                  test
    "Default"                 "threadtest test"
    "Device-One"              fulltest
  }
  Linux-i686 {
    "Unlock-Notify"           "QUICKTEST_INCLUDE=notify2.test test"
    "Device-One"              test
    "Device-Two"              test

Changes to test/syscall.test.

235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250




















251
252
253
254
255
256
257
forcedelete test.db test.db2

do_test 8.1 {
  sqlite3 db test.db
  file_control_chunksize_test db main 4096
  file size test.db
} {0}

foreach {tn hint size} {
  1  1000    4096 
  2  1000    4096 
  3  3000    4096 
  4  4096    4096 
  5  4197    8192 
} {
  do_test 8.2.$tn {




















    file_control_sizehint_test db main $hint
    file size test.db
  } $size
}

test_syscall reset
finish_test







<








>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







235
236
237
238
239
240
241

242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
forcedelete test.db test.db2

do_test 8.1 {
  sqlite3 db test.db
  file_control_chunksize_test db main 4096
  file size test.db
} {0}

foreach {tn hint size} {
  1  1000    4096 
  2  1000    4096 
  3  3000    4096 
  4  4096    4096 
  5  4197    8192 
} {
  do_test 8.2.$tn {
    file_control_sizehint_test db main $hint
    file size test.db
  } $size
}

do_test 8.3 {
  db close
  forcedelete test.db test.db2
  sqlite3 db test.db
  file_control_chunksize_test db main 16
  file size test.db
} {0}
foreach {tn hint size} {
  1  5       16 
  2  13      16 
  3  45      48 
  4  48      48 
  5  49      64 
} {
  do_test 8.4.$tn {
    file_control_sizehint_test db main $hint
    file size test.db
  } $size
}

test_syscall reset
finish_test

Changes to test/wal.test.

1526
1527
1528
1529
1530
1531
1532
1533

1534
1535
1536
1537

1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randomblob(5000));
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
  } {wal}
  do_execsql_test 24.2 { 

    DELETE FROM t1;
    PRAGMA wal_checkpoint;
  } {0 109 109}
  do_test 24.3 {

    db close
    sqlite3 db test.db
    file exists test.db-wal
  } 0
  do_test 24.4 {
    file size test.db
  } [expr 84 * 1024]
  do_test 24.5 {
    execsql { 
      PRAGMA incremental_vacuum;
      PRAGMA wal_checkpoint;
    }
    file size test.db
  } [expr 3 * 1024]
  do_test 24.6 {
    file size test.db-wal
  } 2128
}

db close
sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize

finish_test







|
>
|
|
<
<
>




|


|






|










1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536


1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
1551
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(randomblob(5000));
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
    INSERT INTO t1 SELECT * FROM t1;
  } {wal}
  do_test 24.2 { 
    execsql {
      DELETE FROM t1;
      PRAGMA wal_checkpoint;


    }
    db close
    sqlite3 db test.db
    file exists test.db-wal
  } 0
  do_test 24.3 {
    file size test.db
  } [expr 84 * 1024]
  do_test 24.4 {
    execsql { 
      PRAGMA incremental_vacuum;
      PRAGMA wal_checkpoint;
    }
    file size test.db
  } [expr 3 * 1024]
  do_test 24.5 {
    file size test.db-wal
  } 2128
}

db close
sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize

finish_test

Changes to tool/omittest.tcl.

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141

142
143


144
145
146
147
148
149
150
...
237
238
239
240
241
242
243











244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271

272
# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly.
set ::USAGE_MESSAGE {
This Tcl script is used to test the various compile time options 
available for omitting code (the SQLITE_OMIT_xxx options). It
should be invoked as follows:

    <script> ?-makefile PATH-TO-MAKEFILE? ?-skip_run?

The default value for ::MAKEFILE is "../Makefile.linux.gcc".

If -skip_run option is given then only the compile part is attempted.

This script builds the testfixture program and runs the SQLite test suite
once with each SQLITE_OMIT_ option defined and then once with all options
................................................................................
# This proc processes the command line options passed to this script.
# Currently the only option supported is "-makefile", default
# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
# option.
#
proc process_options {argv} {
  if {$::tcl_platform(platform)=="windows" || $::tcl_platform(platform)=="os2"} {
      set ::MAKEFILE ./Makefile                         ;# Default value
  } else {
      set ::MAKEFILE ./Makefile.linux-gcc               ;# Default value
  }
  set ::SKIP_RUN 0                                      ;# Default to attempt test

  for {set i 0} {$i < [llength $argv]} {incr i} {
    switch -- [lindex $argv $i] {
      -makefile {
        incr i
        set ::MAKEFILE [lindex $argv $i]
      }
  
      -skip_run {
        incr i
        set ::SKIP_RUN 1
      }

      default {

        puts stderr [string trim $::USAGE_MESSAGE]
        exit -1


      }
    }
    set ::MAKEFILE [file normalize $::MAKEFILE]
  }
}

# Main routine.
................................................................................
    SQLITE_ENABLE_UNLOCK_NOTIFY \
    SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
  ]

  # Process any command line options.
  process_options $argv












  # First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT 
  # and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
  # and the latter is currently incompatible with the test suite (this should
  # be fixed, but it will be a lot of work).
  set allsyms [list]
  foreach s $::OMIT_SYMBOLS {
    if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
      lappend allsyms $s
    }
  }
  run_quick_test test_OMIT_EVERYTHING $allsyms

  # Now try one quick.test with each of the OMIT symbols defined. Included
  # are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we
  # know they will fail. It's good to be reminded of this from time to time.
  foreach sym $::OMIT_SYMBOLS {
    set dirname "test_[string range $sym 7 end]"
    run_quick_test $dirname $sym
  }

  # Try the ENABLE/DISABLE symbols one at a time.  
  # We don't do them all at once since some are conflicting.
  foreach sym $::ENABLE_SYMBOLS {
    set dirname "test_[string range $sym 7 end]"
    run_quick_test $dirname $sym
  }
}


main $argv







|







 







|

|

|









<




>
|
|
>
>







 







>
>
>
>
>
>
>
>
>
>
>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136

137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
# Documentation for this script. This may be output to stderr
# if the script is invoked incorrectly.
set ::USAGE_MESSAGE {
This Tcl script is used to test the various compile time options 
available for omitting code (the SQLITE_OMIT_xxx options). It
should be invoked as follows:

    <script> ?test-symbol? ?-makefile PATH-TO-MAKEFILE? ?-skip_run?

The default value for ::MAKEFILE is "../Makefile.linux.gcc".

If -skip_run option is given then only the compile part is attempted.

This script builds the testfixture program and runs the SQLite test suite
once with each SQLITE_OMIT_ option defined and then once with all options
................................................................................
# This proc processes the command line options passed to this script.
# Currently the only option supported is "-makefile", default
# "../Makefile.linux-gcc". Set the ::MAKEFILE variable to the value of this
# option.
#
proc process_options {argv} {
  if {$::tcl_platform(platform)=="windows" || $::tcl_platform(platform)=="os2"} {
    set ::MAKEFILE ./Makefile               ;# Default value
  } else {
    set ::MAKEFILE ./Makefile.linux-gcc     ;# Default value
  }
  set ::SKIP_RUN 0                          ;# Default to attempt test

  for {set i 0} {$i < [llength $argv]} {incr i} {
    switch -- [lindex $argv $i] {
      -makefile {
        incr i
        set ::MAKEFILE [lindex $argv $i]
      }
  
      -skip_run {

        set ::SKIP_RUN 1
      }

      default {
        if {[info exists ::SYMBOL]} {
          puts stderr [string trim $::USAGE_MESSAGE]
          exit -1
        }
        set ::SYMBOL [lindex $argv $i]
      }
    }
    set ::MAKEFILE [file normalize $::MAKEFILE]
  }
}

# Main routine.
................................................................................
    SQLITE_ENABLE_UNLOCK_NOTIFY \
    SQLITE_ENABLE_UPDATE_DELETE_LIMIT \
  ]

  # Process any command line options.
  process_options $argv

  if {[info exists ::SYMBOL] } {
    set sym $::SYMBOL

    if {[lsearch $::OMIT_SYMBOLS $sym]<0 && [lsearch $::ENABLE_SYMBOLS $sym]<0} {
      puts stderr "No such symbol: $sym"
      exit -1
    }

    set dirname "test_[string range $sym 7 end]"
    run_quick_test $dirname $sym
  } else {
    # First try a test with all OMIT symbols except SQLITE_OMIT_FLOATING_POINT 
    # and SQLITE_OMIT_PRAGMA defined. The former doesn't work (causes segfaults)
    # and the latter is currently incompatible with the test suite (this should
    # be fixed, but it will be a lot of work).
    set allsyms [list]
    foreach s $::OMIT_SYMBOLS {
      if {$s!="SQLITE_OMIT_FLOATING_POINT" && $s!="SQLITE_OMIT_PRAGMA"} {
        lappend allsyms $s
      }
    }
    run_quick_test test_OMIT_EVERYTHING $allsyms
  
    # Now try one quick.test with each of the OMIT symbols defined. Included
    # are the OMIT_FLOATING_POINT and OMIT_PRAGMA symbols, even though we
    # know they will fail. It's good to be reminded of this from time to time.
    foreach sym $::OMIT_SYMBOLS {
      set dirname "test_[string range $sym 7 end]"
      run_quick_test $dirname $sym
    }
  
    # Try the ENABLE/DISABLE symbols one at a time.  
    # We don't do them all at once since some are conflicting.
    foreach sym $::ENABLE_SYMBOLS {
      set dirname "test_[string range $sym 7 end]"
      run_quick_test $dirname $sym
    }
  }
}

main $argv