/ Check-in [2dbdfa51]
Login

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

Overview
Comment:Merge in the 3.8.5 release changes and the FTS integrity-check fix.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | apple-osx
Files: files | file ages | folders
SHA1:2dbdfa51703bade30b66730191e4fb286edc500b
User & Date: drh 2014-06-05 12:53:41
Context
2015-04-06
22:05
Detect and suppress an endless loops in clearDatabasePage() that might result from a corrupt database file. This is an edited cherry-pick from [30011ad2f55c] and [395bb3e677a]. Leaf check-in: e5f5ef00 user: drh tags: apple-osx-385
2014-06-30
19:57
Merge the latest trunk changes into the apple-osx branch. check-in: f426876f user: drh tags: apple-osx
2014-06-05
12:53
Merge in the 3.8.5 release changes and the FTS integrity-check fix. check-in: 2dbdfa51 user: drh tags: apple-osx
11:15
Fix a problem that was causing the FTS4 integrity-check command to fail if the table had one or more "notindexed" columns. check-in: 7123bb26 user: dan tags: trunk
2014-05-29
20:36
Merge trunk changes into the apple-osx branch. check-in: b9fad449 user: drh tags: apple-osx
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ext/fts3/fts3_write.c.

5170
5171
5172
5173
5174
5175
5176

5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204

5205
5206
5207
5208
5209
5210
5211

    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
      i64 iDocid = sqlite3_column_int64(pStmt, 0);
      int iLang = langidFromSelect(p, pStmt);
      int iCol;

      for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){

        const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
        int nText = sqlite3_column_bytes(pStmt, iCol+1);
        sqlite3_tokenizer_cursor *pT = 0;

        rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText, &pT);
        while( rc==SQLITE_OK ){
          char const *zToken;       /* Buffer containing token */
          int nToken = 0;           /* Number of bytes in token */
          int iDum1 = 0, iDum2 = 0; /* Dummy variables */
          int iPos = 0;             /* Position of token in zText */

          rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
          if( rc==SQLITE_OK ){
            int i;
            cksum2 = cksum2 ^ fts3ChecksumEntry(
                zToken, nToken, iLang, 0, iDocid, iCol, iPos
            );
            for(i=1; i<p->nIndex; i++){
              if( p->aIndex[i].nPrefix<=nToken ){
                cksum2 = cksum2 ^ fts3ChecksumEntry(
                  zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
                );
              }
            }
          }
        }
        if( pT ) pModule->xClose(pT);
        if( rc==SQLITE_DONE ) rc = SQLITE_OK;

      }
    }

    sqlite3_finalize(pStmt);
  }

  *pbOk = (cksum1==cksum2);







>
|
|
|

|
|
|
|
|
|

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







5170
5171
5172
5173
5174
5175
5176
5177
5178
5179
5180
5181
5182
5183
5184
5185
5186
5187
5188
5189
5190
5191
5192
5193
5194
5195
5196
5197
5198
5199
5200
5201
5202
5203
5204
5205
5206
5207
5208
5209
5210
5211
5212
5213

    while( rc==SQLITE_OK && SQLITE_ROW==sqlite3_step(pStmt) ){
      i64 iDocid = sqlite3_column_int64(pStmt, 0);
      int iLang = langidFromSelect(p, pStmt);
      int iCol;

      for(iCol=0; rc==SQLITE_OK && iCol<p->nColumn; iCol++){
        if( p->abNotindexed[iCol]==0 ){
          const char *zText = (const char *)sqlite3_column_text(pStmt, iCol+1);
          int nText = sqlite3_column_bytes(pStmt, iCol+1);
          sqlite3_tokenizer_cursor *pT = 0;

          rc = sqlite3Fts3OpenTokenizer(p->pTokenizer, iLang, zText, nText,&pT);
          while( rc==SQLITE_OK ){
            char const *zToken;       /* Buffer containing token */
            int nToken = 0;           /* Number of bytes in token */
            int iDum1 = 0, iDum2 = 0; /* Dummy variables */
            int iPos = 0;             /* Position of token in zText */

            rc = pModule->xNext(pT, &zToken, &nToken, &iDum1, &iDum2, &iPos);
            if( rc==SQLITE_OK ){
              int i;
              cksum2 = cksum2 ^ fts3ChecksumEntry(
                  zToken, nToken, iLang, 0, iDocid, iCol, iPos
              );
              for(i=1; i<p->nIndex; i++){
                if( p->aIndex[i].nPrefix<=nToken ){
                  cksum2 = cksum2 ^ fts3ChecksumEntry(
                      zToken, p->aIndex[i].nPrefix, iLang, i, iDocid, iCol, iPos
                  );
                }
              }
            }
          }
          if( pT ) pModule->xClose(pT);
          if( rc==SQLITE_DONE ) rc = SQLITE_OK;
        }
      }
    }

    sqlite3_finalize(pStmt);
  }

  *pbOk = (cksum1==cksum2);

Changes to src/os_win.c.

2920
2921
2922
2923
2924
2925
2926

2927
2928







2929
2930
2931
2932
2933
2934
2935
....
3174
3175
3176
3177
3178
3179
3180











3181
3182
3183
3184
3185
3186
3187
                                         PENDING_BYTE, 0, 1, 0))==0 ){
      /* Try 3 times to get the pending lock.  This is needed to work
      ** around problems caused by indexing and/or anti-virus software on
      ** Windows systems.
      ** If you are using this code as a model for alternative VFSes, do not
      ** copy this retry logic.  It is a hack intended for Windows only.
      */

      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
               pFile->h, cnt, res));







      if( cnt ) sqlite3_win32_sleep(1);
    }
    gotPendingLock = res;
    if( !res ){
      lastErrno = osGetLastError();
    }
  }
................................................................................
        winIoerrRetryDelay = a[1];
      }else{
        a[1] = winIoerrRetryDelay;
      }
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
    }











    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = 0;
      int rc = winGetTempname(pFile->pVfs, &zTFile);
      if( rc==SQLITE_OK ){
        *(char**)pArg = zTFile;
      }
      OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));







>


>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>







2920
2921
2922
2923
2924
2925
2926
2927
2928
2929
2930
2931
2932
2933
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
....
3182
3183
3184
3185
3186
3187
3188
3189
3190
3191
3192
3193
3194
3195
3196
3197
3198
3199
3200
3201
3202
3203
3204
3205
3206
                                         PENDING_BYTE, 0, 1, 0))==0 ){
      /* Try 3 times to get the pending lock.  This is needed to work
      ** around problems caused by indexing and/or anti-virus software on
      ** Windows systems.
      ** If you are using this code as a model for alternative VFSes, do not
      ** copy this retry logic.  It is a hack intended for Windows only.
      */
      lastErrno = osGetLastError();
      OSTRACE(("LOCK-PENDING-FAIL file=%p, count=%d, result=%d\n",
               pFile->h, cnt, res));
      if( lastErrno==ERROR_INVALID_HANDLE ){
        pFile->lastErrno = lastErrno;
        rc = SQLITE_IOERR_LOCK;
        OSTRACE(("LOCK-FAIL file=%p, count=%d, rc=%s\n",
                 pFile->h, cnt, sqlite3ErrName(rc)));
        return rc;
      }
      if( cnt ) sqlite3_win32_sleep(1);
    }
    gotPendingLock = res;
    if( !res ){
      lastErrno = osGetLastError();
    }
  }
................................................................................
        winIoerrRetryDelay = a[1];
      }else{
        a[1] = winIoerrRetryDelay;
      }
      OSTRACE(("FCNTL file=%p, rc=SQLITE_OK\n", pFile->h));
      return SQLITE_OK;
    }
#ifdef SQLITE_TEST
    case SQLITE_FCNTL_WIN32_SET_HANDLE: {
      LPHANDLE phFile = (LPHANDLE)pArg;
      HANDLE hOldFile = pFile->h;
      pFile->h = *phFile;
      *phFile = hOldFile;
      OSTRACE(("FCNTL oldFile=%p, newFile=%p, rc=SQLITE_OK\n",
               hOldFile, pFile->h));
      return SQLITE_OK;
    }
#endif
    case SQLITE_FCNTL_TEMPFILENAME: {
      char *zTFile = 0;
      int rc = winGetTempname(pFile->pVfs, &zTFile);
      if( rc==SQLITE_OK ){
        *(char**)pArg = zTFile;
      }
      OSTRACE(("FCNTL file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));

Changes to src/printf.c.

752
753
754
755
756
757
758

759
760
761
762
763
764
765
    }
    if( p->useMalloc==1 ){
      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
    }else{
      zNew = sqlite3_realloc(zOld, p->nAlloc);
    }
    if( zNew ){

      if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
      p->zText = zNew;
    }else{
      sqlite3StrAccumReset(p);
      setStrAccumError(p, STRACCUM_NOMEM);
      return 0;
    }







>







752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
    }
    if( p->useMalloc==1 ){
      zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
    }else{
      zNew = sqlite3_realloc(zOld, p->nAlloc);
    }
    if( zNew ){
      assert( p->zText!=0 || p->nChar==0 );
      if( zOld==0 && p->nChar>0 ) memcpy(zNew, p->zText, p->nChar);
      p->zText = zNew;
    }else{
      sqlite3StrAccumReset(p);
      setStrAccumError(p, STRACCUM_NOMEM);
      return 0;
    }

Changes to src/select.c.

1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
  }
  if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
  sqlite3VdbeResolveLabel(v, addrBreak);
  if( eDest==SRT_Output || eDest==SRT_Coroutine ){
    sqlite3VdbeAddOp2(v, OP_Close, pseudoTab, 0);
  }
}

/*
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
** Also try to estimate the size of the returned value and return that







<
<
<







1222
1223
1224
1225
1226
1227
1228



1229
1230
1231
1232
1233
1234
1235
  if( pSort->sortFlags & SORTFLAG_UseSorter ){
    sqlite3VdbeAddOp2(v, OP_SorterNext, iTab, addr); VdbeCoverage(v);
  }else{
    sqlite3VdbeAddOp2(v, OP_Next, iTab, addr); VdbeCoverage(v);
  }
  if( pSort->regReturn ) sqlite3VdbeAddOp1(v, OP_Return, pSort->regReturn);
  sqlite3VdbeResolveLabel(v, addrBreak);



}

/*
** Return a pointer to a string containing the 'declaration type' of the
** expression pExpr. The string may be treated as static by the caller.
**
** Also try to estimate the size of the returned value and return that

Changes to src/shell.c.

2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
....
2437
2438
2439
2440
2441
2442
2443


2444
2445
2446
2447
2448
2449
2450
....
2994
2995
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
  }else

  if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
    fprintf(p->out, "%s", zHelp);
  }else

  if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
    char *zTable = azArg[2];    /* Insert data into this table */
    char *zFile = azArg[1];     /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
    int nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->separator[] */
    char *zSql;                 /* An SQL statement */
................................................................................
    CSVReader sCsv;             /* Reader context */
    int (*xCloser)(FILE*);      /* Procedure to close th3 connection */

    if( nArg!=3 ){
      fprintf(stderr, "Usage: .import FILE TABLE\n");
      goto meta_command_exit;
    }


    seenInterrupt = 0;
    memset(&sCsv, 0, sizeof(sCsv));
    open_db(p, 0);
    nSep = strlen30(p->separator);
    if( nSep==0 ){
      fprintf(stderr, "Error: non-null separator required for import\n");
      return 1;
................................................................................
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
    system(zCmd);
    sqlite3_free(zCmd);
  }else

  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
    int i;
    if( nArg!=1 ){
      fprintf(stderr, "Usage: .show\n");







|
|







 







>
>







 







|







2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434
2435
2436
....
2437
2438
2439
2440
2441
2442
2443
2444
2445
2446
2447
2448
2449
2450
2451
2452
....
2996
2997
2998
2999
3000
3001
3002
3003
3004
3005
3006
3007
3008
3009
3010
  }else

  if( c=='h' && strncmp(azArg[0], "help", n)==0 ){
    fprintf(p->out, "%s", zHelp);
  }else

  if( c=='i' && strncmp(azArg[0], "import", n)==0 ){
    char *zTable;               /* Insert data into this table */
    char *zFile;                /* Name of file to extra content from */
    sqlite3_stmt *pStmt = NULL; /* A statement */
    int nCol;                   /* Number of columns in the table */
    int nByte;                  /* Number of bytes in an SQL string */
    int i, j;                   /* Loop counters */
    int needCommit;             /* True to COMMIT or ROLLBACK at end */
    int nSep;                   /* Number of bytes in p->separator[] */
    char *zSql;                 /* An SQL statement */
................................................................................
    CSVReader sCsv;             /* Reader context */
    int (*xCloser)(FILE*);      /* Procedure to close th3 connection */

    if( nArg!=3 ){
      fprintf(stderr, "Usage: .import FILE TABLE\n");
      goto meta_command_exit;
    }
    zFile = azArg[1];
    zTable = azArg[2];
    seenInterrupt = 0;
    memset(&sCsv, 0, sizeof(sCsv));
    open_db(p, 0);
    nSep = strlen30(p->separator);
    if( nSep==0 ){
      fprintf(stderr, "Error: non-null separator required for import\n");
      return 1;
................................................................................
      goto meta_command_exit;
    }
    zCmd = sqlite3_mprintf(strchr(azArg[1],' ')==0?"%s":"\"%s\"", azArg[1]);
    for(i=2; i<nArg; i++){
      zCmd = sqlite3_mprintf(strchr(azArg[i],' ')==0?"%z %s":"%z \"%s\"",
                             zCmd, azArg[i]);
    }
    (void)system(zCmd);
    sqlite3_free(zCmd);
  }else

  if( c=='s' && strncmp(azArg[0], "show", n)==0 ){
    int i;
    if( nArg!=1 ){
      fprintf(stderr, "Usage: .show\n");

Changes to src/sqlite.h.in.

939
940
941
942
943
944
945






946
947
948
949
950
951
952
...
962
963
964
965
966
967
968

969
970
971
972
973
974
975
**
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
** pointer to an integer and it writes a boolean into that integer depending
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**






** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
#define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
#define SQLITE_FCNTL_LAST_ERRNO              4
#define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16
#define SQLITE_FCNTL_MMAP_SIZE              18
#define SQLITE_FCNTL_TRACE                  19
#define SQLITE_FCNTL_HAS_MOVED              20
#define SQLITE_FCNTL_SYNC                   21
#define SQLITE_FCNTL_COMMIT_PHASETWO        22

/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO

/*
** CAPI3REF: Mutex Handle







>
>
>
>
>
>







 







>







939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
...
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
**
** <li>[[SQLITE_FCNTL_HAS_MOVED]]
** The [SQLITE_FCNTL_HAS_MOVED] file control interprets its argument as a
** pointer to an integer and it writes a boolean into that integer depending
** on whether or not the file has been renamed, moved, or deleted since it
** was first opened.
**
** <li>[[SQLITE_FCNTL_WIN32_SET_HANDLE]]
** The [SQLITE_FCNTL_WIN32_SET_HANDLE] opcode is used for debugging.  This
** opcode causes the xFileControl method to swap the file handle with the one
** pointed to by the pArg argument.  This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE               1
#define SQLITE_FCNTL_GET_LOCKPROXYFILE       2
#define SQLITE_FCNTL_SET_LOCKPROXYFILE       3
#define SQLITE_FCNTL_LAST_ERRNO              4
#define SQLITE_FCNTL_SIZE_HINT               5
................................................................................
#define SQLITE_FCNTL_BUSYHANDLER            15
#define SQLITE_FCNTL_TEMPFILENAME           16
#define SQLITE_FCNTL_MMAP_SIZE              18
#define SQLITE_FCNTL_TRACE                  19
#define SQLITE_FCNTL_HAS_MOVED              20
#define SQLITE_FCNTL_SYNC                   21
#define SQLITE_FCNTL_COMMIT_PHASETWO        22
#define SQLITE_FCNTL_WIN32_SET_HANDLE       23
/* deprecated names */
#define SQLITE_GET_LOCKPROXYFILE      SQLITE_FCNTL_GET_LOCKPROXYFILE
#define SQLITE_SET_LOCKPROXYFILE      SQLITE_FCNTL_SET_LOCKPROXYFILE
#define SQLITE_LAST_ERRNO             SQLITE_FCNTL_LAST_ERRNO

/*
** CAPI3REF: Mutex Handle

Changes to src/test1.c.

112
113
114
115
116
117
118










119
120
121
122
123
124
125
....
5399
5400
5401
5402
5403
5404
5405

5406
5407
5408
5409
5410
5411
5412
....
5432
5433
5434
5435
5436
5437
5438




































5439
5440
5441
5442
5443
5444
5445
....
6665
6666
6667
6668
6669
6670
6671

6672


6673
6674
6675
6676
6677
6678
6679
    p = (struct SqliteDb*)cmdInfo.objClientData;
    *ppDb = p->db;
  }else{
    *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
  }
  return TCL_OK;
}











extern const char *sqlite3ErrName(int);
#define t1ErrorName sqlite3ErrName

/*
** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
** fact that the sqlite3* is the first field in the Vdbe structure.
................................................................................
#else
  Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); 
#endif
  
  return TCL_OK;  
}


/*
** tclcmd:   file_control_win32_av_retry DB  NRETRY  DELAY
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
*/
static int file_control_win32_av_retry(
................................................................................
  if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
  sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
  Tcl_AppendResult(interp, z, (char*)0);
  return TCL_OK;  
}





































/*
** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_PERSIST_WAL opcode.
*/
static int file_control_persist_wal(
................................................................................
     { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
#ifdef __APPLE__
     { "file_control_truncate_test", file_control_truncate_test,  0   },
     { "file_control_replace_test", file_control_replace_test,  0   },
#endif 
     { "file_control_chunksize_test", file_control_chunksize_test,  0   },
     { "file_control_sizehint_test",  file_control_sizehint_test,   0   },

     { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },


     { "file_control_persist_wal",    file_control_persist_wal,     0   },
     { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
     { "file_control_vfsname",        file_control_vfsname,         0   },
     { "file_control_tempfilename",   file_control_tempfilename,    0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },
     { "sqlite3_create_function_v2", test_create_function_v2, 0 },
     { "path_is_local",              path_is_local,  0   },







>
>
>
>
>
>
>
>
>
>







 







>







 







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







 







>

>
>







112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
....
5409
5410
5411
5412
5413
5414
5415
5416
5417
5418
5419
5420
5421
5422
5423
....
5443
5444
5445
5446
5447
5448
5449
5450
5451
5452
5453
5454
5455
5456
5457
5458
5459
5460
5461
5462
5463
5464
5465
5466
5467
5468
5469
5470
5471
5472
5473
5474
5475
5476
5477
5478
5479
5480
5481
5482
5483
5484
5485
5486
5487
5488
5489
5490
5491
5492
....
6712
6713
6714
6715
6716
6717
6718
6719
6720
6721
6722
6723
6724
6725
6726
6727
6728
6729
    p = (struct SqliteDb*)cmdInfo.objClientData;
    *ppDb = p->db;
  }else{
    *ppDb = (sqlite3*)sqlite3TestTextToPtr(zA);
  }
  return TCL_OK;
}

#if SQLITE_OS_WIN
/*
** Decode a Win32 HANDLE object.
*/
int getWin32Handle(Tcl_Interp *interp, const char *zA, LPHANDLE phFile){
  *phFile = (HANDLE)sqlite3TestTextToPtr(zA);
  return TCL_OK;
}
#endif

extern const char *sqlite3ErrName(int);
#define t1ErrorName sqlite3ErrName

/*
** Convert an sqlite3_stmt* into an sqlite3*.  This depends on the
** fact that the sqlite3* is the first field in the Vdbe structure.
................................................................................
#else
  Tcl_SetObjResult(interp, Tcl_NewIntObj(0)); 
#endif
  
  return TCL_OK;  
}

#if SQLITE_OS_WIN
/*
** tclcmd:   file_control_win32_av_retry DB  NRETRY  DELAY
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_AV_RETRY opcode.
*/
static int file_control_win32_av_retry(
................................................................................
  if( Tcl_GetIntFromObj(interp, objv[3], &a[1]) ) return TCL_ERROR;
  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_AV_RETRY, (void*)a);
  sqlite3_snprintf(sizeof(z), z, "%d %d %d", rc, a[0], a[1]);
  Tcl_AppendResult(interp, z, (char*)0);
  return TCL_OK;  
}

/*
** tclcmd:   file_control_win32_set_handle DB HANDLE
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_WIN32_SET_HANDLE opcode.
*/
static int file_control_win32_set_handle(
  ClientData clientData, /* Pointer to sqlite3_enable_XXX function */
  Tcl_Interp *interp,    /* The TCL interpreter that invoked this command */
  int objc,              /* Number of arguments */
  Tcl_Obj *CONST objv[]  /* Command arguments */
){
  sqlite3 *db;
  int rc;
  HANDLE hFile = NULL;
  char z[100];

  if( objc!=3 ){
    Tcl_AppendResult(interp, "wrong # args: should be \"",
        Tcl_GetStringFromObj(objv[0], 0), " DB HANDLE", 0);
    return TCL_ERROR;
  }
  if( getDbPointer(interp, Tcl_GetString(objv[1]), &db) ){
    return TCL_ERROR;
  }
  if( getWin32Handle(interp, Tcl_GetString(objv[2]), &hFile) ){
    return TCL_ERROR;
  }
  rc = sqlite3_file_control(db, NULL, SQLITE_FCNTL_WIN32_SET_HANDLE,
                            (void*)&hFile);
  sqlite3_snprintf(sizeof(z), z, "%d %p", rc, (void*)hFile);
  Tcl_AppendResult(interp, z, (char*)0);
  return TCL_OK;  
}
#endif

/*
** tclcmd:   file_control_persist_wal DB PERSIST-FLAG
**
** This TCL command runs the sqlite3_file_control interface with
** the SQLITE_FCNTL_PERSIST_WAL opcode.
*/
static int file_control_persist_wal(
................................................................................
     { "file_control_lockproxy_test", file_control_lockproxy_test,  0   },
#ifdef __APPLE__
     { "file_control_truncate_test", file_control_truncate_test,  0   },
     { "file_control_replace_test", file_control_replace_test,  0   },
#endif 
     { "file_control_chunksize_test", file_control_chunksize_test,  0   },
     { "file_control_sizehint_test",  file_control_sizehint_test,   0   },
#if SQLITE_OS_WIN
     { "file_control_win32_av_retry", file_control_win32_av_retry,  0   },
     { "file_control_win32_set_handle", file_control_win32_set_handle, 0  },
#endif
     { "file_control_persist_wal",    file_control_persist_wal,     0   },
     { "file_control_powersafe_overwrite",file_control_powersafe_overwrite,0},
     { "file_control_vfsname",        file_control_vfsname,         0   },
     { "file_control_tempfilename",   file_control_tempfilename,    0   },
     { "sqlite3_vfs_list",           vfs_list,     0   },
     { "sqlite3_create_function_v2", test_create_function_v2, 0 },
     { "path_is_local",              path_is_local,  0   },

Changes to src/where.c.

4282
4283
4284
4285
4286
4287
4288
4289
4290
4291
4292
4293
4294
4295
4296
4297
4298
4299
4300
4301
4302
4303
4304
4305
....
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
5306
5307
....
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335
5336
5337

      assert( pNew->nOut==saved_nOut );
      if( pTerm->truthProb<=0 && iCol>=0 ){
        assert( (eOp & WO_IN) || nIn==0 );
        testcase( eOp & WO_IN );
        pNew->nOut += pTerm->truthProb;
        pNew->nOut -= nIn;
        pNew->wsFlags |= WHERE_LIKELIHOOD;
      }else{
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
        tRowcnt nOut = 0;
        if( nInMul==0 
         && pProbe->nSample 
         && pNew->u.btree.nEq<=pProbe->nSampleCol
         && OptimizationEnabled(db, SQLITE_Stat3) 
         && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))
         && (pNew->wsFlags & WHERE_LIKELIHOOD)==0
        ){
          Expr *pExpr = pTerm->pExpr;
          if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){
            testcase( eOp & WO_EQ );
            testcase( eOp & WO_ISNULL );
            rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
          }else{
................................................................................

  pParse = pWInfo->pParse;
  db = pParse->db;
  nLoop = pWInfo->nLevel;
  /* TUNING: For simple queries, only the best path is tracked.
  ** For 2-way joins, the 5 best paths are followed.
  ** For joins of 3 or more tables, track the 10 best paths */
  mxChoice = (nLoop==1) ? 1 : (nLoop==2 ? 5 : 10);
  assert( nLoop<=pWInfo->pTabList->nSrc );
  WHERETRACE(0x002, ("---- begin solver\n"));

  /* Allocate and initialize space for aTo and aFrom */
  ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
  pSpace = sqlite3DbMallocRaw(db, ii);
  if( pSpace==0 ) return SQLITE_NOMEM;
................................................................................

  /* Precompute the cost of sorting the final result set, if the caller
  ** to sqlite3WhereBegin() was concerned about sorting */
  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
    aFrom[0].isOrdered = 0;
    nOrderBy = 0;
  }else{
    aFrom[0].isOrdered = -1;
    nOrderBy = pWInfo->pOrderBy->nExpr;
  }

  /* Compute successively longer WherePaths using the previous generation
  ** of WherePaths as the basis for the next.  Keep track of the mxChoice
  ** best paths at each generation */
  for(iLoop=0; iLoop<nLoop; iLoop++){







<








<







 







|







 







|







4282
4283
4284
4285
4286
4287
4288

4289
4290
4291
4292
4293
4294
4295
4296

4297
4298
4299
4300
4301
4302
4303
....
5291
5292
5293
5294
5295
5296
5297
5298
5299
5300
5301
5302
5303
5304
5305
....
5321
5322
5323
5324
5325
5326
5327
5328
5329
5330
5331
5332
5333
5334
5335

      assert( pNew->nOut==saved_nOut );
      if( pTerm->truthProb<=0 && iCol>=0 ){
        assert( (eOp & WO_IN) || nIn==0 );
        testcase( eOp & WO_IN );
        pNew->nOut += pTerm->truthProb;
        pNew->nOut -= nIn;

      }else{
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
        tRowcnt nOut = 0;
        if( nInMul==0 
         && pProbe->nSample 
         && pNew->u.btree.nEq<=pProbe->nSampleCol
         && OptimizationEnabled(db, SQLITE_Stat3) 
         && ((eOp & WO_IN)==0 || !ExprHasProperty(pTerm->pExpr, EP_xIsSelect))

        ){
          Expr *pExpr = pTerm->pExpr;
          if( (eOp & (WO_EQ|WO_ISNULL))!=0 ){
            testcase( eOp & WO_EQ );
            testcase( eOp & WO_ISNULL );
            rc = whereEqualScanEst(pParse, pBuilder, pExpr->pRight, &nOut);
          }else{
................................................................................

  pParse = pWInfo->pParse;
  db = pParse->db;
  nLoop = pWInfo->nLevel;
  /* TUNING: For simple queries, only the best path is tracked.
  ** For 2-way joins, the 5 best paths are followed.
  ** For joins of 3 or more tables, track the 10 best paths */
  mxChoice = (nLoop<=1) ? 1 : (nLoop==2 ? 5 : 10);
  assert( nLoop<=pWInfo->pTabList->nSrc );
  WHERETRACE(0x002, ("---- begin solver\n"));

  /* Allocate and initialize space for aTo and aFrom */
  ii = (sizeof(WherePath)+sizeof(WhereLoop*)*nLoop)*mxChoice*2;
  pSpace = sqlite3DbMallocRaw(db, ii);
  if( pSpace==0 ) return SQLITE_NOMEM;
................................................................................

  /* Precompute the cost of sorting the final result set, if the caller
  ** to sqlite3WhereBegin() was concerned about sorting */
  if( pWInfo->pOrderBy==0 || nRowEst==0 ){
    aFrom[0].isOrdered = 0;
    nOrderBy = 0;
  }else{
    aFrom[0].isOrdered = nLoop>0 ? -1 : 1;
    nOrderBy = pWInfo->pOrderBy->nExpr;
  }

  /* Compute successively longer WherePaths using the previous generation
  ** of WherePaths as the basis for the next.  Keep track of the mxChoice
  ** best paths at each generation */
  for(iLoop=0; iLoop<nLoop; iLoop++){

Changes to src/whereInt.h.

454
455
456
457
458
459
460
461
#define WHERE_VIRTUALTABLE 0x00000400  /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE      0x00000800  /* Able to support an IN operator */
#define WHERE_ONEROW       0x00001000  /* Selects no more than one row */
#define WHERE_MULTI_OR     0x00002000  /* OR using multiple indices */
#define WHERE_AUTO_INDEX   0x00004000  /* Uses an ephemeral index */
#define WHERE_SKIPSCAN     0x00008000  /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED   0x00010000  /* WHERE_ONEROW would have been helpful*/
#define WHERE_LIKELIHOOD   0x00020000  /* A likelihood() is affecting nOut */







<
454
455
456
457
458
459
460

#define WHERE_VIRTUALTABLE 0x00000400  /* WhereLoop.u.vtab is valid */
#define WHERE_IN_ABLE      0x00000800  /* Able to support an IN operator */
#define WHERE_ONEROW       0x00001000  /* Selects no more than one row */
#define WHERE_MULTI_OR     0x00002000  /* OR using multiple indices */
#define WHERE_AUTO_INDEX   0x00004000  /* Uses an ephemeral index */
#define WHERE_SKIPSCAN     0x00008000  /* Uses the skip-scan algorithm */
#define WHERE_UNQ_WANTED   0x00010000  /* WHERE_ONEROW would have been helpful*/

Changes to test/cost.test.

240
241
242
243
244
245
246

247








































248
249
250
251
  set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w"

  do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/}
  do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/}
}












































finish_test










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




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
287
288
289
290
291
292
  set sql2 "SELECT * FROM t1 WHERE likelihood(k=?, $p2) AND $w"

  do_eqp_test 9.3.$tn.1 $sql1 {/INDEX i1/}
  do_eqp_test 9.3.$tn.2 $sql2 {/INDEX i2/}
}


#-------------------------------------------------------------------------
#

ifcapable stat4 {
  do_execsql_test 10.1 {
    CREATE TABLE t6(a, b, c);
    CREATE INDEX t6i1 ON t6(a, b);
    CREATE INDEX t6i2 ON t6(c);
  }
  
  do_test 10.2 {
    for {set i 0} {$i < 16} {incr i} {
      execsql { INSERT INTO t6 VALUES($i%4, 'xyz', $i%8) }
    }
    execsql ANALYZE
  } {}

  do_eqp_test 10.3 {
    SELECT rowid FROM t6 WHERE a=0 AND c=0
  } {
    0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
  }

  do_eqp_test 10.4 {
    SELECT rowid FROM t6 WHERE a=0 AND b='xyz' AND c=0
  } {
    0 0 0 {SEARCH TABLE t6 USING INDEX t6i2 (c=?)}
  }

  do_eqp_test 10.5 {
    SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND c=0
  } {
    0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=?)}
  }

  do_eqp_test 10.6 {
    SELECT rowid FROM t6 WHERE likelihood(a=0, 0.1) AND b='xyz' AND c=0
  } {
    0 0 0 {SEARCH TABLE t6 USING INDEX t6i1 (a=? AND b=?)}
  }
}

finish_test



Changes to test/e_insert.test.

170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
} {
    1    "INSERT INTO a2 VALUES(1)"         {a2 3 1}
    2    "INSERT INTO a2 VALUES(1,2)"       {a2 3 2}
    3    "INSERT INTO a2 VALUES(1,2,3,4)"   {a2 3 4}
    4    "INSERT INTO a2 VALUES(1,2,3,4,5)" {a2 3 5}
}

# EVIDENCE-OF: R-34231-22576 In this case the result of evaluating the
# left-most expression in each term of the VALUES list is inserted into
# the left-most column of the each new row, and forth for each
# subsequent expression.
#
delete_all_data
do_insert_tests e_insert-1.3 {
    1a   "INSERT INTO a2 VALUES(1, 2, 3)"    {}
    1b   "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {1 2 3}








|
|
|







170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
} {
    1    "INSERT INTO a2 VALUES(1)"         {a2 3 1}
    2    "INSERT INTO a2 VALUES(1,2)"       {a2 3 2}
    3    "INSERT INTO a2 VALUES(1,2,3,4)"   {a2 3 4}
    4    "INSERT INTO a2 VALUES(1,2,3,4,5)" {a2 3 5}
}

# EVIDENCE-OF: R-29730-42609 In this case the result of evaluating the
# left-most expression from each term of the VALUES list is inserted
# into the left-most column of each new row, and so forth for each
# subsequent expression.
#
delete_all_data
do_insert_tests e_insert-1.3 {
    1a   "INSERT INTO a2 VALUES(1, 2, 3)"    {}
    1b   "SELECT * FROM a2 WHERE oid=last_insert_rowid()" {1 2 3}

Changes to test/fts4check.test.

147
148
149
150
151
152
153
154



























155

} {
  do_execsql_test  3.2.1.$tn "BEGIN; $disruption"
  do_catchsql_test 3.2.2.$tn {
    INSERT INTO t3 (t3) VALUES('integrity-check')
  } {1 {database disk image is malformed}}
  do_execsql_test  3.2.3.$tn "ROLLBACK"
}




























finish_test









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

>
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
172
173
174
175
176
177
178
179
180
181
182
183
} {
  do_execsql_test  3.2.1.$tn "BEGIN; $disruption"
  do_catchsql_test 3.2.2.$tn {
    INSERT INTO t3 (t3) VALUES('integrity-check')
  } {1 {database disk image is malformed}}
  do_execsql_test  3.2.3.$tn "ROLLBACK"
}

#--------------------------------------------------------------------------
# Test case 4.*
#
# Test that the integrity-check works if there are "notindexed" columns.
#
do_execsql_test 4.0 {
  CREATE VIRTUAL TABLE t4 USING fts4(a, b, c, notindexed=b);
  INSERT INTO t4 VALUES('text one', 'text two', 'text three');
  INSERT INTO t4(t4) VALUES('integrity-check');
}

do_execsql_test 4.1 {
  PRAGMA writable_schema = 1;
  UPDATE sqlite_master 
    SET sql = 'CREATE VIRTUAL TABLE t4 USING fts4(a, b, c)' 
    WHERE name = 't4';
}

do_test 4.2 {
  db close
  sqlite3 db test.db
  catchsql {
    INSERT INTO t4(t4) VALUES('integrity-check');
  }
} {1 {database disk image is malformed}}
reset_db

finish_test

Changes to test/orderby1.test.

448
449
450
451
452
453
454

455









456


















457
    INSERT INTO t41 VALUES(1,1),(3,1);
    INSERT INTO t42 VALUES(1,13),(1,15),(3,14),(3,16);
    
    SELECT b, y FROM t41 CROSS JOIN t42 ON x=a ORDER BY b, y;
  }
} {1 13 1 14 1 15 1 16}































finish_test







>
|
>
>
>
>
>
>
>
>
>

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

448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
    INSERT INTO t41 VALUES(1,1),(3,1);
    INSERT INTO t42 VALUES(1,13),(1,15),(3,14),(3,16);
    
    SELECT b, y FROM t41 CROSS JOIN t42 ON x=a ORDER BY b, y;
  }
} {1 13 1 14 1 15 1 16}

# No sorting of queries that omit the FROM clause.
#
do_execsql_test 5.0 {
  EXPLAIN QUERY PLAN SELECT 5 ORDER BY 1
} {}
do_execsql_test 5.1 {
  EXPLAIN QUERY PLAN SELECT 5 UNION ALL SELECT 3 ORDER BY 1
} {~/B-TREE/}
do_execsql_test 5.2 {
  SELECT 5 UNION ALL SELECT 3 ORDER BY 1
} {3 5}

# The following test (originally derived from a single test within fuzz.test)
# verifies that a PseudoTable cursor is not closed prematurely in a deeply
# nested query.  This test caused a segfault on 3.8.5 beta.
#
do_execsql_test 6.0 {
  CREATE TABLE abc(a, b, c);
  INSERT INTO abc VALUES(1, 2, 3);
  INSERT INTO abc VALUES(4, 5, 6);
  INSERT INTO abc VALUES(7, 8, 9);
  SELECT (
    SELECT 'hardware' FROM ( 
      SELECT 'software' ORDER BY 'firmware' ASC, 'sportswear' DESC 
    ) GROUP BY 1 HAVING length(b)
  )
  FROM abc;
} {hardware hardware hardware}


finish_test

Changes to test/permutations.test.

153
154
155
156
157
158
159






















160
161
162
163
164
165
166
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
] -initialize {
  set ::G(valgrind) 1
} -shutdown {
  unset -nocomplain ::G(valgrind)
}























test_suite "quick" -prefix "" -description {
  Quick test suite. Runs in around 10 minutes on a workstation.
} -files [
  test_set $allquicktests
]








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







153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
] -initialize {
  set ::G(valgrind) 1
} -shutdown {
  unset -nocomplain ::G(valgrind)
}

test_suite "valgrind-nolookaside" -prefix "" -description {
  Run the "veryquick" test suite with a couple of multi-process tests (that
  fail under valgrind) omitted.
} -files [
  test_set $allquicktests -exclude *malloc* *ioerr* *fault* wal.test atof1.test
] -initialize {
  set ::G(valgrind) 1
  catch {db close}
  sqlite3_shutdown
  sqlite3_config_lookaside 0 0
  sqlite3_initialize
  autoinstall_test_functions
} -shutdown {
  catch {db close}
  sqlite3_shutdown
  sqlite3_config_lookaside 100 500
  sqlite3_initialize
  autoinstall_test_functions
  unset -nocomplain ::G(valgrind)
}


test_suite "quick" -prefix "" -description {
  Quick test suite. Runs in around 10 minutes on a workstation.
} -files [
  test_set $allquicktests
]

Changes to test/win32lock.test.

20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
123
124
125
126
127
128
129
130














































131
132
133
134

set testprefix win32lock

db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  lappend ::log $msg 
}
sqlite3 db test.db
db eval {PRAGMA mmap_size=0}

do_test win32lock-1.1 {
  db eval {
    PRAGMA cache_size=10;
................................................................................
    break
  }
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
db close














































sqlite3_shutdown
test_sqlite3_log 
sqlite3_initialize
finish_test







|







 








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

|


20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
...
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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180

set testprefix win32lock

db close
sqlite3_shutdown
test_sqlite3_log xLog
proc xLog {error_code msg} {
  lappend ::log $msg
}
sqlite3 db test.db
db eval {PRAGMA mmap_size=0}

do_test win32lock-1.1 {
  db eval {
    PRAGMA cache_size=10;
................................................................................
    break
  }
  sqlite3_sleep 10
}

file_control_win32_av_retry db 10 25
sqlite3_test_control_pending_byte $old_pending_byte
db close
forcedelete test.db

sqlite3 db test.db
sqlite3 db2 test.db

do_test win32lock-3.0 {
  db eval {
    CREATE TABLE t1(x);
    INSERT INTO t1 VALUES(1);
    INSERT INTO t1 VALUES(2);
    INSERT INTO t1 VALUES(3);
  }
} {}

do_test win32lock-3.1 {
  db eval {
    BEGIN EXCLUSIVE;
    INSERT INTO t1 VALUES(4);
  }
} {}

do_test win32lock-3.2 {
  catchsql {
    BEGIN EXCLUSIVE;
    INSERT INTO t1 VALUES(5);
    COMMIT;
  } db2
} {1 {database is locked}}

do_test win32lock-3.3 {
  db eval {
    COMMIT;
  }
} {}

do_test win32lock-3.4 {
  set handle [lindex [file_control_win32_set_handle db 0] end]
  list [catchsql {
    BEGIN EXCLUSIVE;
    INSERT INTO t1 VALUES(6);
    COMMIT;
  }] [file_control_win32_set_handle db $handle] [sqlite3_extended_errcode db]
} {{1 {disk I/O error}} {0 0} SQLITE_IOERR_LOCK}

db2 close
db close
sqlite3_shutdown
test_sqlite3_log
sqlite3_initialize
finish_test

Changes to tool/mkkeywordhash.c.

366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  nKeyword = j;

  /* Fill in the lengths of strings and hashes for all entries. */
  for(i=0; i<nKeyword; i++){
    Keyword *p = &aKeywordTable[i];
    p->len = (int)strlen(p->zName);
    assert( p->len<sizeof(p->zOrigName) );
    strcpy(p->zOrigName, p->zName);
    totalLen += p->len;
    p->hash = (UpperToLower[(int)p->zName[0]]*4) ^
              (UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len;
    p->id = i+1;
  }

  /* Sort the table from shortest to longest keyword */







|







366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
  nKeyword = j;

  /* Fill in the lengths of strings and hashes for all entries. */
  for(i=0; i<nKeyword; i++){
    Keyword *p = &aKeywordTable[i];
    p->len = (int)strlen(p->zName);
    assert( p->len<sizeof(p->zOrigName) );
    memcpy(p->zOrigName, p->zName, p->len+1);
    totalLen += p->len;
    p->hash = (UpperToLower[(int)p->zName[0]]*4) ^
              (UpperToLower[(int)p->zName[p->len-1]]*3) ^ p->len;
    p->id = i+1;
  }

  /* Sort the table from shortest to longest keyword */