mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Fix for ticket #107: Fix a design defect in indices that was causing queries
to fail when using an index on a column containing an empty string. This fix is an incompatible file-format change. (CVS 681) FossilOrigin-Name: 20d152fcddb4fa53556a9c93c7a869600a7c5183
This commit is contained in:
74
src/main.c
74
src/main.c
@@ -14,7 +14,7 @@
|
||||
** other files are for internal use by SQLite and should not be
|
||||
** accessed by users of the library.
|
||||
**
|
||||
** $Id: main.c,v 1.86 2002/07/13 17:23:21 drh Exp $
|
||||
** $Id: main.c,v 1.87 2002/07/18 00:34:12 drh Exp $
|
||||
*/
|
||||
#include "sqliteInt.h"
|
||||
#include "os.h"
|
||||
@@ -89,6 +89,31 @@ int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){
|
||||
return nErr;
|
||||
}
|
||||
|
||||
/*
|
||||
** This is a callback procedure used to reconstruct a table. The
|
||||
** name of the table to be reconstructed is passed in as argv[0].
|
||||
**
|
||||
** This routine is used to automatically upgrade a database from
|
||||
** format version 1 or 2 to version 3. The correct operation of
|
||||
** this routine relys on the fact that no indices are used when
|
||||
** copying a table out to a temporary file.
|
||||
*/
|
||||
static int
|
||||
upgrade_3_callback(void *pDb, int argc, char **argv, char **NotUsed){
|
||||
sqlite *db = (sqlite*)pDb;
|
||||
int rc;
|
||||
|
||||
rc = sqlite_exec_printf(db,
|
||||
"CREATE TEMP TABLE sqlite_x AS SELECT * FROM '%q'; "
|
||||
"DELETE FROM '%q'; "
|
||||
"INSERT INTO '%q' SELECT * FROM sqlite_x; "
|
||||
"DROP TABLE sqlite_x;",
|
||||
0, 0, 0, argv[0], argv[0], argv[0]);
|
||||
return rc!=SQLITE_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Attempt to read the database schema and initialize internal
|
||||
** data structures. Return one of the SQLITE_ error codes to
|
||||
@@ -206,12 +231,14 @@ int sqliteInit(sqlite *db, char **pzErrMsg){
|
||||
/*
|
||||
** file_format==1 Version 2.1.0.
|
||||
** file_format==2 Version 2.2.0. Add support for INTEGER PRIMARY KEY.
|
||||
** file_format==3 Version 2.6.0. Add support for separate numeric and
|
||||
** file_format==3 Version 2.6.0. Fix empty-string index bug.
|
||||
** file_format==4 Version 2.7.0. Add support for separate numeric and
|
||||
** text datatypes.
|
||||
*/
|
||||
if( db->file_format==0 ){
|
||||
db->file_format = 2;
|
||||
}else if( db->file_format>2 ){
|
||||
/* This happens if the database was initially empty */
|
||||
db->file_format = 3;
|
||||
}else if( db->file_format>3 ){
|
||||
sqliteBtreeCloseCursor(curMain);
|
||||
sqliteSetString(pzErrMsg, "unsupported file format", 0);
|
||||
rc = SQLITE_ERROR;
|
||||
@@ -313,6 +340,40 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){
|
||||
sqliteFree(*pzErrMsg);
|
||||
*pzErrMsg = 0;
|
||||
}
|
||||
|
||||
/* If the database is in formats 1 or 2, then upgrade it to
|
||||
** version 3. This will reconstruct all indices. If the
|
||||
** upgrade fails for any reason (ex: out of disk space, database
|
||||
** is read only, interrupt receive, etc.) then refuse to open.
|
||||
*/
|
||||
if( db->file_format<3 ){
|
||||
char *zErr;
|
||||
int meta[SQLITE_N_BTREE_META];
|
||||
|
||||
db->file_format = 3;
|
||||
rc = sqlite_exec(db,
|
||||
"BEGIN; SELECT name FROM sqlite_master WHERE type='table';",
|
||||
upgrade_3_callback,
|
||||
db,
|
||||
&zErr);
|
||||
if( rc==SQLITE_OK ){
|
||||
sqliteBtreeGetMeta(db->pBe, meta);
|
||||
meta[2] = 3;
|
||||
sqliteBtreeUpdateMeta(db->pBe, meta);
|
||||
sqlite_exec(db, "COMMIT", 0, 0, 0);
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqliteSetString(pzErrMsg,
|
||||
"unable to upgrade database to the version 2.6 format",
|
||||
zErr ? ": " : 0, zErr, 0);
|
||||
sqliteFree(zErr);
|
||||
sqliteStrRealloc(pzErrMsg);
|
||||
sqlite_close(db);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a pointer to the newly opened database structure */
|
||||
return db;
|
||||
|
||||
no_mem_on_open:
|
||||
@@ -502,6 +563,11 @@ int sqlite_exec(
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
if( db->file_format<3 ){
|
||||
sqliteSafetyOff(db);
|
||||
sqliteSetString(pzErrMsg, "obsolete database file format", 0);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
if( db->recursionDepth==0 ){ db->nChange = 0; }
|
||||
db->recursionDepth++;
|
||||
memset(&sParse, 0, sizeof(sParse));
|
||||
|
Reference in New Issue
Block a user