/ Check-in [d0935505]
Login

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

Overview
Comment:Update the sessions branch with the latest trunk changes.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | sessions
Files: files | file ages | folders
SHA1: d09355050a74344c1cb6d303af9f601cd41e2368
User & Date: drh 2013-05-15 18:45:14
Context
2013-05-17
10:58
Update the sessions branch to the latest 3.7.17 beta. check-in: af8057ef user: drh tags: sessions
2013-05-15
18:45
Update the sessions branch with the latest trunk changes. check-in: d0935505 user: drh tags: sessions
17:47
The sqlite3ExprCollSeq() function can no longer be called while parse the schema, so remove the code path inside of sqlite3ExprCollSeq() that dealt with that case. check-in: 867b3e3b user: drh tags: trunk
2013-05-09
23:40
Merge trunk changes into the sessions branch. check-in: 512f8a1e user: drh tags: sessions
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Added ext/misc/rot13.c.

            1  +/*
            2  +** 2013-05-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 SQLite extension implements a rot13() function and a rot13
           14  +** collating sequence.
           15  +*/
           16  +#include "sqlite3ext.h"
           17  +SQLITE_EXTENSION_INIT1
           18  +#include <assert.h>
           19  +#include <string.h>
           20  +
           21  +/*
           22  +** Perform rot13 encoding on a single ASCII character.
           23  +*/
           24  +static unsigned char rot13(unsigned char c){
           25  +  if( c>='a' && c<='z' ){
           26  +    c += 13;
           27  +    if( c>'z' ) c -= 26;
           28  +  }else if( c>='A' && c<='Z' ){
           29  +    c += 13;
           30  +    if( c>'Z' ) c -= 26;
           31  +  }
           32  +  return c;
           33  +}
           34  +
           35  +/*
           36  +** Implementation of the rot13() function.
           37  +**
           38  +** Rotate ASCII alphabetic characters by 13 character positions.  
           39  +** Non-ASCII characters are unchanged.  rot13(rot13(X)) should always
           40  +** equal X.
           41  +*/
           42  +static void rot13func(
           43  +  sqlite3_context *context,
           44  +  int argc,
           45  +  sqlite3_value **argv
           46  +){
           47  +  const unsigned char *zIn;
           48  +  int nIn;
           49  +  unsigned char *zOut;
           50  +  char *zToFree = 0;
           51  +  int i;
           52  +  char zTemp[100];
           53  +  assert( argc==1 );
           54  +  if( sqlite3_value_type(argv[0])==SQLITE_NULL ) return;
           55  +  zIn = (const unsigned char*)sqlite3_value_text(argv[0]);
           56  +  nIn = sqlite3_value_bytes(argv[0]);
           57  +  if( nIn<sizeof(zTemp)-1 ){
           58  +    zOut = zTemp;
           59  +  }else{
           60  +    zOut = zToFree = sqlite3_malloc( nIn+1 );
           61  +    if( zOut==0 ){
           62  +      sqlite3_result_error_nomem(context);
           63  +      return;
           64  +    }
           65  +  }
           66  +  for(i=0; i<nIn; i++) zOut[i] = rot13(zIn[i]);
           67  +  zOut[i] = 0;
           68  +  sqlite3_result_text(context, (char*)zOut, i, SQLITE_TRANSIENT);
           69  +  sqlite3_free(zToFree);
           70  +}
           71  +
           72  +/*
           73  +** Implement the rot13 collating sequence so that if
           74  +**
           75  +**      x=y COLLATE rot13
           76  +**
           77  +** Then 
           78  +**
           79  +**      rot13(x)=rot13(y) COLLATE binary
           80  +*/
           81  +static int rot13CollFunc(
           82  +  void *notUsed,
           83  +  int nKey1, const void *pKey1,
           84  +  int nKey2, const void *pKey2
           85  +){
           86  +  const char *zA = (const char*)pKey1;
           87  +  const char *zB = (const char*)pKey2;
           88  +  int i, x;
           89  +  for(i=0; i<nKey1 && i<nKey2; i++){
           90  +    x = (int)rot13(zA[i]) - (int)rot13(zB[i]);
           91  +    if( x!=0 ) return x;
           92  +  }
           93  +  return nKey1 - nKey2;
           94  +}
           95  +
           96  +
           97  +#ifdef _WIN32
           98  +__declspec(dllexport)
           99  +#endif
          100  +int sqlite3_rot_init(
          101  +  sqlite3 *db, 
          102  +  char **pzErrMsg, 
          103  +  const sqlite3_api_routines *pApi
          104  +){
          105  +  int rc = SQLITE_OK;
          106  +  SQLITE_EXTENSION_INIT2(pApi);
          107  +  (void)pzErrMsg;  /* Unused parameter */
          108  +  rc = sqlite3_create_function(db, "rot13", 1, SQLITE_UTF8, 0,
          109  +                               rot13func, 0, 0);
          110  +  if( rc==SQLITE_OK ){
          111  +    rc = sqlite3_create_collation(db, "rot13", SQLITE_UTF8, 0, rot13CollFunc);
          112  +  }
          113  +  return rc;
          114  +}

Changes to main.mk.

   293    293     $(TOP)/src/btree.c \
   294    294     $(TOP)/src/build.c \
   295    295     $(TOP)/src/date.c \
   296    296     $(TOP)/src/expr.c \
   297    297     $(TOP)/src/func.c \
   298    298     $(TOP)/src/insert.c \
   299    299     $(TOP)/src/wal.c \
          300  +  $(TOP)/src/main.c \
   300    301     $(TOP)/src/mem5.c \
   301    302     $(TOP)/src/os.c \
   302    303     $(TOP)/src/os_unix.c \
   303    304     $(TOP)/src/os_win.c \
   304    305     $(TOP)/src/pager.c \
   305    306     $(TOP)/src/pragma.c \
   306    307     $(TOP)/src/prepare.c \

Changes to src/btree.c.

  2513   2513   
  2514   2514   page1_init_failed:
  2515   2515     releasePage(pPage1);
  2516   2516     pBt->pPage1 = 0;
  2517   2517     return rc;
  2518   2518   }
  2519   2519   
         2520  +#ifndef NDEBUG
         2521  +/*
         2522  +** Return the number of cursors open on pBt. This is for use
         2523  +** in assert() expressions, so it is only compiled if NDEBUG is not
         2524  +** defined.
         2525  +**
         2526  +** Only write cursors are counted if wrOnly is true.  If wrOnly is
         2527  +** false then all cursors are counted.
         2528  +**
         2529  +** For the purposes of this routine, a cursor is any cursor that
         2530  +** is capable of reading or writing to the databse.  Cursors that
         2531  +** have been tripped into the CURSOR_FAULT state are not counted.
         2532  +*/
         2533  +static int countValidCursors(BtShared *pBt, int wrOnly){
         2534  +  BtCursor *pCur;
         2535  +  int r = 0;
         2536  +  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
         2537  +    if( (wrOnly==0 || pCur->wrFlag) && pCur->eState!=CURSOR_FAULT ) r++; 
         2538  +  }
         2539  +  return r;
         2540  +}
         2541  +#endif
         2542  +
  2520   2543   /*
  2521   2544   ** If there are no outstanding cursors and we are not in the middle
  2522   2545   ** of a transaction but there is a read lock on the database, then
  2523   2546   ** this routine unrefs the first page of the database file which 
  2524   2547   ** has the effect of releasing the read lock.
  2525   2548   **
  2526   2549   ** If there is a transaction in progress, this routine is a no-op.
  2527   2550   */
  2528   2551   static void unlockBtreeIfUnused(BtShared *pBt){
  2529   2552     assert( sqlite3_mutex_held(pBt->mutex) );
  2530         -  assert( pBt->pCursor==0 || pBt->inTransaction>TRANS_NONE );
         2553  +  assert( countValidCursors(pBt,0)==0 || pBt->inTransaction>TRANS_NONE );
  2531   2554     if( pBt->inTransaction==TRANS_NONE && pBt->pPage1!=0 ){
  2532   2555       assert( pBt->pPage1->aData );
  2533   2556       assert( sqlite3PagerRefcount(pBt->pPager)==1 );
  2534   2557       assert( pBt->pPage1->aData );
  2535   2558       releasePage(pBt->pPage1);
  2536   2559       pBt->pPage1 = 0;
  2537   2560     }
................................................................................
  3251   3274   static void btreeEndTransaction(Btree *p){
  3252   3275     BtShared *pBt = p->pBt;
  3253   3276     assert( sqlite3BtreeHoldsMutex(p) );
  3254   3277   
  3255   3278   #ifndef SQLITE_OMIT_AUTOVACUUM
  3256   3279     pBt->bDoTruncate = 0;
  3257   3280   #endif
  3258         -  btreeClearHasContent(pBt);
  3259   3281     if( p->inTrans>TRANS_NONE && p->db->activeVdbeCnt>1 ){
  3260   3282       /* If there are other active statements that belong to this database
  3261   3283       ** handle, downgrade to a read-only transaction. The other statements
  3262   3284       ** may still be reading from the database.  */
  3263   3285       downgradeAllSharedCacheTableLocks(p);
  3264   3286       p->inTrans = TRANS_READ;
  3265   3287     }else{
................................................................................
  3326   3348       assert( pBt->nTransaction>0 );
  3327   3349       rc = sqlite3PagerCommitPhaseTwo(pBt->pPager);
  3328   3350       if( rc!=SQLITE_OK && bCleanup==0 ){
  3329   3351         sqlite3BtreeLeave(p);
  3330   3352         return rc;
  3331   3353       }
  3332   3354       pBt->inTransaction = TRANS_READ;
         3355  +    btreeClearHasContent(pBt);
  3333   3356     }
  3334   3357   
  3335   3358     btreeEndTransaction(p);
  3336   3359     sqlite3BtreeLeave(p);
  3337   3360     return SQLITE_OK;
  3338   3361   }
  3339   3362   
................................................................................
  3347   3370     if( rc==SQLITE_OK ){
  3348   3371       rc = sqlite3BtreeCommitPhaseTwo(p, 0);
  3349   3372     }
  3350   3373     sqlite3BtreeLeave(p);
  3351   3374     return rc;
  3352   3375   }
  3353   3376   
  3354         -#ifndef NDEBUG
  3355         -/*
  3356         -** Return the number of write-cursors open on this handle. This is for use
  3357         -** in assert() expressions, so it is only compiled if NDEBUG is not
  3358         -** defined.
  3359         -**
  3360         -** For the purposes of this routine, a write-cursor is any cursor that
  3361         -** is capable of writing to the databse.  That means the cursor was
  3362         -** originally opened for writing and the cursor has not be disabled
  3363         -** by having its state changed to CURSOR_FAULT.
  3364         -*/
  3365         -static int countWriteCursors(BtShared *pBt){
  3366         -  BtCursor *pCur;
  3367         -  int r = 0;
  3368         -  for(pCur=pBt->pCursor; pCur; pCur=pCur->pNext){
  3369         -    if( pCur->wrFlag && pCur->eState!=CURSOR_FAULT ) r++; 
  3370         -  }
  3371         -  return r;
  3372         -}
  3373         -#endif
  3374         -
  3375   3377   /*
  3376   3378   ** This routine sets the state to CURSOR_FAULT and the error
  3377   3379   ** code to errCode for every cursor on BtShared that pBtree
  3378   3380   ** references.
  3379   3381   **
  3380   3382   ** Every cursor is tripped, including cursors that belong
  3381   3383   ** to other database connections that happen to be sharing
................................................................................
  3447   3449         int nPage = get4byte(28+(u8*)pPage1->aData);
  3448   3450         testcase( nPage==0 );
  3449   3451         if( nPage==0 ) sqlite3PagerPagecount(pBt->pPager, &nPage);
  3450   3452         testcase( pBt->nPage!=nPage );
  3451   3453         pBt->nPage = nPage;
  3452   3454         releasePage(pPage1);
  3453   3455       }
  3454         -    assert( countWriteCursors(pBt)==0 );
         3456  +    assert( countValidCursors(pBt, 1)==0 );
  3455   3457       pBt->inTransaction = TRANS_READ;
         3458  +    btreeClearHasContent(pBt);
  3456   3459     }
  3457   3460   
  3458   3461     btreeEndTransaction(p);
  3459   3462     sqlite3BtreeLeave(p);
  3460   3463     return rc;
  3461   3464   }
  3462   3465   

Changes to src/build.c.

  2655   2655   
  2656   2656     /* Figure out how many bytes of space are required to store explicitly
  2657   2657     ** specified collation sequence names.
  2658   2658     */
  2659   2659     for(i=0; i<pList->nExpr; i++){
  2660   2660       Expr *pExpr = pList->a[i].pExpr;
  2661   2661       if( pExpr ){
  2662         -      CollSeq *pColl = sqlite3ExprCollSeq(pParse, pExpr);
  2663         -      if( pColl ){
  2664         -        nExtra += (1 + sqlite3Strlen30(pColl->zName));
  2665         -      }
         2662  +      assert( pExpr->op==TK_COLLATE );
         2663  +      nExtra += (1 + sqlite3Strlen30(pExpr->u.zToken));
  2666   2664       }
  2667   2665     }
  2668   2666   
  2669   2667     /* 
  2670   2668     ** Allocate the index structure. 
  2671   2669     */
  2672   2670     nName = sqlite3Strlen30(zName);
................................................................................
  2719   2717     ** same column more than once cannot be an error because that would 
  2720   2718     ** break backwards compatibility - it needs to be a warning.
  2721   2719     */
  2722   2720     for(i=0, pListItem=pList->a; i<pList->nExpr; i++, pListItem++){
  2723   2721       const char *zColName = pListItem->zName;
  2724   2722       Column *pTabCol;
  2725   2723       int requestedSortOrder;
  2726         -    CollSeq *pColl;                /* Collating sequence */
  2727   2724       char *zColl;                   /* Collation sequence name */
  2728   2725   
  2729   2726       for(j=0, pTabCol=pTab->aCol; j<pTab->nCol; j++, pTabCol++){
  2730   2727         if( sqlite3StrICmp(zColName, pTabCol->zName)==0 ) break;
  2731   2728       }
  2732   2729       if( j>=pTab->nCol ){
  2733   2730         sqlite3ErrorMsg(pParse, "table %s has no column named %s",
  2734   2731           pTab->zName, zColName);
  2735   2732         pParse->checkSchema = 1;
  2736   2733         goto exit_create_index;
  2737   2734       }
  2738   2735       pIndex->aiColumn[i] = j;
  2739         -    if( pListItem->pExpr
  2740         -     && (pColl = sqlite3ExprCollSeq(pParse, pListItem->pExpr))!=0
  2741         -    ){
         2736  +    if( pListItem->pExpr ){
  2742   2737         int nColl;
  2743         -      zColl = pColl->zName;
         2738  +      assert( pListItem->pExpr->op==TK_COLLATE );
         2739  +      zColl = pListItem->pExpr->u.zToken;
  2744   2740         nColl = sqlite3Strlen30(zColl) + 1;
  2745   2741         assert( nExtra>=nColl );
  2746   2742         memcpy(zExtra, zColl, nColl);
  2747   2743         zColl = zExtra;
  2748   2744         zExtra += nColl;
  2749   2745         nExtra -= nColl;
  2750   2746       }else{
  2751   2747         zColl = pTab->aCol[j].zColl;
  2752         -      if( !zColl ){
  2753         -        zColl = "BINARY";
  2754         -      }
         2748  +      if( !zColl ) zColl = "BINARY";
  2755   2749       }
  2756   2750       if( !db->init.busy && !sqlite3LocateCollSeq(pParse, zColl) ){
  2757   2751         goto exit_create_index;
  2758   2752       }
  2759   2753       pIndex->azColl[i] = zColl;
  2760   2754       requestedSortOrder = pListItem->sortOrder & sortOrderMask;
  2761   2755       pIndex->aSortOrder[i] = (u8)requestedSortOrder;

Changes to src/expr.c.

   112    112       int op = p->op;
   113    113       if( op==TK_CAST || op==TK_UPLUS ){
   114    114         p = p->pLeft;
   115    115         continue;
   116    116       }
   117    117       assert( op!=TK_REGISTER || p->op2!=TK_COLLATE );
   118    118       if( op==TK_COLLATE ){
   119         -      if( db->init.busy ){
   120         -        /* Do not report errors when parsing while the schema */
   121         -        pColl = sqlite3FindCollSeq(db, ENC(db), p->u.zToken, 0);
   122         -      }else{
   123         -        pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
   124         -      }
          119  +      pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
   125    120         break;
   126    121       }
   127    122       if( p->pTab!=0
   128    123        && (op==TK_AGG_COLUMN || op==TK_COLUMN
   129    124             || op==TK_REGISTER || op==TK_TRIGGER)
   130    125       ){
   131    126         /* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally

Changes to src/main.c.

   844    844     if( !forceZombie && connectionIsBusy(db) ){
   845    845       sqlite3Error(db, SQLITE_BUSY, "unable to close due to unfinalized "
   846    846          "statements or unfinished backups");
   847    847       sqlite3_mutex_leave(db->mutex);
   848    848       return SQLITE_BUSY;
   849    849     }
   850    850   
          851  +  /* If a transaction is open, roll it back. This also ensures that if
          852  +  ** any database schemas have been modified by the current transaction
          853  +  ** they are reset. And that the required b-tree mutex is held to make
          854  +  ** the the pager rollback and schema reset an atomic operation. */
          855  +  sqlite3RollbackAll(db, SQLITE_OK);
          856  +
   851    857   #ifdef SQLITE_ENABLE_SQLLOG
   852    858     if( sqlite3GlobalConfig.xSqllog ){
   853    859       /* Closing the handle. Fourth parameter is passed the value 2. */
   854    860       sqlite3GlobalConfig.xSqllog(sqlite3GlobalConfig.pSqllogArg, db, 0, 2);
   855    861     }
   856    862   #endif
   857    863   
................................................................................
   998   1004   ** attempts to use that cursor.
   999   1005   */
  1000   1006   void sqlite3RollbackAll(sqlite3 *db, int tripCode){
  1001   1007     int i;
  1002   1008     int inTrans = 0;
  1003   1009     assert( sqlite3_mutex_held(db->mutex) );
  1004   1010     sqlite3BeginBenignMalloc();
         1011  +  sqlite3BtreeEnterAll(db);
  1005   1012     for(i=0; i<db->nDb; i++){
  1006   1013       Btree *p = db->aDb[i].pBt;
  1007   1014       if( p ){
  1008   1015         if( sqlite3BtreeIsInTrans(p) ){
  1009   1016           inTrans = 1;
  1010   1017         }
  1011   1018         sqlite3BtreeRollback(p, tripCode);
................................................................................
  1015   1022     sqlite3VtabRollback(db);
  1016   1023     sqlite3EndBenignMalloc();
  1017   1024   
  1018   1025     if( (db->flags&SQLITE_InternChanges)!=0 && db->init.busy==0 ){
  1019   1026       sqlite3ExpirePreparedStatements(db);
  1020   1027       sqlite3ResetAllSchemasOfConnection(db);
  1021   1028     }
         1029  +  sqlite3BtreeLeaveAll(db);
  1022   1030   
  1023   1031     /* Any deferred constraint violations have now been resolved. */
  1024   1032     db->nDeferredCons = 0;
  1025   1033   
  1026   1034     /* If one has been configured, invoke the rollback-hook callback */
  1027   1035     if( db->xRollbackCallback && (inTrans || !db->autoCommit) ){
  1028   1036       db->xRollbackCallback(db->pRollbackArg);

Changes to test/collate3.test.

    50     50       CREATE INDEX collate3i1 ON collate3t1(c1 COLLATE garbage);
    51     51     }
    52     52   } {1 {no such collation sequence: garbage}}
    53     53   
    54     54   execsql {
    55     55     DROP TABLE collate3t1;
    56     56   }
           57  +
           58  +proc caseless {a b} { string compare -nocase $a $b }
           59  +do_test collate3-1.4 {
           60  +  db collate caseless caseless
           61  +  execsql { 
           62  +    CREATE TABLE t1(a COLLATE caseless); 
           63  +    INSERT INTO t1 VALUES('Abc2');
           64  +    INSERT INTO t1 VALUES('abc1');
           65  +    INSERT INTO t1 VALUES('aBc3');
           66  +  }
           67  +  execsql { SELECT * FROM t1 ORDER BY a }
           68  +} {abc1 Abc2 aBc3}
           69  +
           70  +do_test collate3-1.5 {
           71  +  db close
           72  +  sqlite3 db test.db
           73  +  catchsql { SELECT * FROM t1 ORDER BY a }
           74  +} {1 {no such collation sequence: caseless}}
           75  +
           76  +do_test collate3-1.6.1 {
           77  +  db collate caseless caseless
           78  +  execsql { CREATE INDEX i1 ON t1(a) }
           79  +  execsql { SELECT * FROM t1 ORDER BY a }
           80  +} {abc1 Abc2 aBc3}
           81  +
           82  +do_test collate3-1.6.2 {
           83  +  db close
           84  +  sqlite3 db test.db
           85  +  catchsql { SELECT * FROM t1 ORDER BY a }
           86  +} {1 {no such collation sequence: caseless}}
           87  +
           88  +do_test collate3-1.6.3 {
           89  +  db close
           90  +  sqlite3 db test.db
           91  +  catchsql { PRAGMA integrity_check }
           92  +} {1 {no such collation sequence: caseless}}
           93  +
           94  +do_test collate3-1.6.4 {
           95  +  db close
           96  +  sqlite3 db test.db
           97  +  catchsql { REINDEX }
           98  +} {1 {no such collation sequence: caseless}}
           99  +
          100  +do_test collate3-1.7.1 {
          101  +  db collate caseless caseless
          102  +  execsql {
          103  +    DROP TABLE t1;
          104  +    CREATE TABLE t1(a);
          105  +    CREATE INDEX i1 ON t1(a COLLATE caseless);
          106  +    INSERT INTO t1 VALUES('Abc2');
          107  +    INSERT INTO t1 VALUES('abc1');
          108  +    INSERT INTO t1 VALUES('aBc3');
          109  +    SELECT * FROM t1 ORDER BY a COLLATE caseless;
          110  +  }
          111  +} {abc1 Abc2 aBc3}
          112  +
          113  +do_test collate3-1.7.2 {
          114  +  db close
          115  +  sqlite3 db test.db
          116  +  catchsql { SELECT * FROM t1 ORDER BY a COLLATE caseless}
          117  +} {1 {no such collation sequence: caseless}}
          118  +
          119  +do_test collate3-1.7.4 {
          120  +  db close
          121  +  sqlite3 db test.db
          122  +  catchsql { REINDEX }
          123  +} {1 {no such collation sequence: caseless}}
          124  +
          125  +do_test collate3-1.7.3 {
          126  +  db close
          127  +  sqlite3 db test.db
          128  +  catchsql { PRAGMA integrity_check }
          129  +} {1 {no such collation sequence: caseless}}
          130  +
          131  +do_test collate3-1.7.4 {
          132  +  db close
          133  +  sqlite3 db test.db
          134  +  catchsql { REINDEX }
          135  +} {1 {no such collation sequence: caseless}}
          136  +
          137  +do_test collate3-1.7.5 {
          138  +  db close
          139  +  sqlite3 db test.db
          140  +  db collate caseless caseless
          141  +  catchsql { PRAGMA integrity_check }
          142  +} {0 ok}
          143  +
          144  +proc needed {nm} { db collate caseless caseless }
          145  +do_test collate3-1.7.6 {
          146  +  db close
          147  +  sqlite3 db test.db
          148  +  db collation_needed needed
          149  +  catchsql { PRAGMA integrity_check }
          150  +} {0 ok}
          151  +
          152  +do_test collate3-1.8 {
          153  +  execsql { DROP TABLE t1 }
          154  +} {}
    57    155   
    58    156   #
    59    157   # Create a table with a default collation sequence, then close
    60    158   # and re-open the database without re-registering the collation
    61    159   # sequence. Then make sure the library stops us from using
    62    160   # the collation sequence in:
    63    161   # * an explicitly collated ORDER BY

Added test/sharedA.test.

            1  +# 2013 May 14
            2  +#
            3  +# The author disclaims copyright to this source code.  In place of
            4  +# a legal notice, here is a blessing:
            5  +#
            6  +#    May you do good and not evil.
            7  +#    May you find forgiveness for yourself and forgive others.
            8  +#    May you share freely, never taking more than you give.
            9  +#
           10  +#***********************************************************************
           11  +#
           12  +# Test some specific circumstances to do with shared cache mode.
           13  +#
           14  +
           15  +
           16  +set testdir [file dirname $argv0]
           17  +source $testdir/tester.tcl
           18  +if {[run_thread_tests]==0} { finish_test ; return }
           19  +db close
           20  +set ::testprefix sharedA
           21  +
           22  +set ::enable_shared_cache [sqlite3_enable_shared_cache 1]
           23  +
           24  +#-------------------------------------------------------------------------
           25  +#
           26  +do_test 0.1 {
           27  +  sqlite3 db1 test.db
           28  +  sqlite3 db2 test.db
           29  +
           30  +  db1 eval {
           31  +    CREATE TABLE t1(x);
           32  +    INSERT INTO t1 VALUES(randomblob(100));
           33  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           34  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           35  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           36  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           37  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           38  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           39  +    CREATE INDEX i1 ON t1(x);
           40  +  }
           41  +
           42  +  db1 eval {
           43  +    BEGIN;
           44  +    DROP INDEX i1;
           45  +  }
           46  +
           47  +  db2 close
           48  +
           49  +  db1 eval {
           50  +    INSERT INTO t1 SELECT randomblob(100) FROM t1;
           51  +    ROLLBACK;
           52  +    PRAGMA integrity_check;
           53  +  }
           54  +} {ok}
           55  +
           56  +db1 close
           57  +forcedelete test.db
           58  +
           59  +
           60  +#-------------------------------------------------------------------------
           61  +#
           62  +do_test 1.1 {
           63  +  sqlite3 db1 test.db
           64  +  sqlite3 db2 test.db
           65  +  db2 eval {
           66  +    CREATE TABLE t1(x);
           67  +    INSERT INTO t1 VALUES(123);
           68  +  }
           69  +  db1 eval { 
           70  +    SELECT * FROM t1;
           71  +    CREATE INDEX i1 ON t1(x);
           72  +  }
           73  +} {123}
           74  +
           75  +do_test 1.2 {
           76  +  db2 eval { SELECT * FROM t1 ORDER BY x; }
           77  +
           78  +  db1 eval {
           79  +    BEGIN; DROP INDEX i1;
           80  +  }
           81  +  db1 close
           82  +
           83  +  db2 eval { SELECT * FROM t1 ORDER BY x; }
           84  +} {123}
           85  +
           86  +do_test 1.3 {
           87  +  db2 close
           88  +} {}
           89  +
           90  +#-------------------------------------------------------------------------
           91  +#
           92  +# sqlite3RollbackAll() loops through all attached b-trees and rolls
           93  +# back each one separately.  Then if the SQLITE_InternChanges flag is
           94  +# set, it resets the schema.  Both of the above steps must be done
           95  +# while holding a mutex, otherwise another thread might slip in and
           96  +# try to use the new schema with the old data.
           97  +#
           98  +# The following sequence of tests attempt to verify that the actions
           99  +# taken by sqlite3RollbackAll() are thread-atomic (that they cannot be
          100  +# interrupted by a separate thread.)  
          101  +#
          102  +# Note that a TCL interpreter can only be used within the thread in which
          103  +# it was originally created (because it uses thread-local-storage).  
          104  +# The tvfs callbacks must therefore only run on the main thread.  
          105  +# There is some trickery in the read_callback procedure to ensure that
          106  +# this is the case.
          107  +#
          108  +testvfs tvfs
          109  +
          110  +# Set up two databases and two database connections.
          111  +#
          112  +#   db1:  main(test.db), two(test2.db)
          113  +#   db2:  main(test.db)
          114  +#
          115  +# The cache for test.db is shared between db1 and db2.
          116  +#
          117  +do_test 2.1 {
          118  +  forcedelete test.db test.db2
          119  +  sqlite3 db1 test.db -vfs tvfs
          120  +  db1 eval { ATTACH 'test.db2' AS two }
          121  +
          122  +  db1 eval {
          123  +    CREATE TABLE t1(x);
          124  +    INSERT INTO t1 VALUES(1);
          125  +    INSERT INTO t1 VALUES(2);
          126  +    INSERT INTO t1 VALUES(3);
          127  +    CREATE TABLE two.t2(x);
          128  +    INSERT INTO t2 SELECT * FROM t1;
          129  +  }
          130  +
          131  +  sqlite3 db2 test.db -vfs tvfs
          132  +  db2 eval { SELECT * FROM t1 }
          133  +} {1 2 3}
          134  +
          135  +# Create a prepared statement on db2 that will attempt a schema change
          136  +# in test.db.  Meanwhile, start a transaction on db1 that changes
          137  +# the schema of test.db and that creates a rollback journal on test2.db
          138  +#
          139  +do_test 2.2 {
          140  +  set ::STMT [sqlite3_prepare db2 "CREATE INDEX i1 ON t1(x)" -1 tail]
          141  +  db1 eval {
          142  +    BEGIN;
          143  +      CREATE INDEX i1 ON t1(x);
          144  +      INSERT INTO t2 VALUES('value!');
          145  +  }
          146  +} {}
          147  +
          148  +# Set up a callback that will cause db2 to try to execute its
          149  +# schema change when db1 accesses the journal file of test2.db.
          150  +#
          151  +# This callback will be invoked after the content of test.db has
          152  +# be rolled back but before the schema has been reset.  If the
          153  +# sqlite3RollbackAll() operation is not thread-atomic, then the
          154  +# db2 statement in the callback will see old content with the newer
          155  +# schema, which is wrong.
          156  +#
          157  +tvfs filter xRead
          158  +tvfs script read_callback
          159  +unset -nocomplain ::some_time_laster
          160  +unset -nocomplain ::thread_result
          161  +proc read_callback {call file args} { 
          162  +  if {[string match *test.db2-journal $file]} {
          163  +    tvfs filter {}   ;# Ensure that tvfs callbacks to do run on the
          164  +                      # child thread
          165  +    sqlthread spawn ::thread_result [subst -nocommands {
          166  +      sqlite3_step $::STMT
          167  +      set rc [sqlite3_finalize $::STMT]
          168  +    }]
          169  +    after 1000 { set ::some_time_later 1 }
          170  +    vwait ::some_time_later
          171  +  }
          172  +}
          173  +do_test 2.3 { db1 eval ROLLBACK } {}
          174  +
          175  +# Verify that the db2 statement invoked by the callback detected the
          176  +# schema change.
          177  +#
          178  +if {[info exists ::thread_result]==0} { vwait ::thread_result }
          179  +do_test 2.4 { 
          180  +  list $::thread_result [sqlite3_errmsg db2] 
          181  +} {SQLITE_SCHEMA {database schema has changed}}
          182  +
          183  +db1 close
          184  +db2 close
          185  +tvfs delete
          186  +
          187  +sqlite3_enable_shared_cache $::enable_shared_cache
          188  +finish_test