From c231172f3fe2d5c8c409337a20f002395263763f Mon Sep 17 00:00:00 2001 From: drh Date: Fri, 19 Jul 2002 17:46:38 +0000 Subject: [PATCH] Better detection and reporting of errors when initializing from the sqlite_master table. (CVS 688) FossilOrigin-Name: c8a7b725b7cec792d2148455a4cecbce9dfebe80 --- manifest | 16 ++++++------- manifest.uuid | 2 +- src/main.c | 59 ++++++++++++++++++++++++++++++++--------------- src/sqliteInt.h | 3 +-- test/version.test | 4 ++-- 5 files changed, 53 insertions(+), 31 deletions(-) diff --git a/manifest b/manifest index b157d55bef..7cd98a4c2a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Version\s2.6.0\sRelease\s2\s(CVS\s687) -D 2002-07-18T11:10:30 +C Better\sdetection\sand\sreporting\sof\serrors\swhen\sinitializing\sfrom\sthe\nsqlite_master\stable.\s(CVS\s688) +D 2002-07-19T17:46:39 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -28,7 +28,7 @@ F src/func.c e45cd908b9b723d9b91473d09e12c23f786b3fc2 F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72 F src/hash.h cd0433998bc1a3759d244e1637fe5a3c13b53bf8 F src/insert.c 9bc794863ea2988a7b8667ef010b3c46b26dba38 -F src/main.c e22729b9780f2f3a2c69715f53d67666072a63d5 +F src/main.c ac96008489c086295c2e252f70e725eefd02131c F src/md5.c 0ae1f3e2cac92d06fc6246d1b4b8f61a2fe66d3b F src/os.c edb22daad525f49681f41c76683a16c1d39755c7 F src/os.h 5b9a69875c880d1665ae040cbca1f7b9c82198ab @@ -41,7 +41,7 @@ F src/select.c a43eabfc2e3e4d67660027f016889935f706deab F src/shell.c 37a8405aec5740726c4ee18826c1ff5fd2c29b96 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in 75c5bbb066d0faf34424b7d1babf8b44d5b31af2 -F src/sqliteInt.h 0d0b7b7b2b6829eb5c2f63489b11c44ba966fc75 +F src/sqliteInt.h a7a088cd9e69e9dbefe0fdfe411bb6387b50f384 F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c c502819c209011659e1bbb428cbac5670cce7f79 F src/test1.c 456cb080db85056be723e770435d9509afc3a83a @@ -107,7 +107,7 @@ F test/trigger3.test 7dfe798d7e72c13720394685fe353112e3f31adf F test/unique.test 572aa791327c1e8d797932263e9d67f176cfdb44 F test/update.test 7ffb062d580a972e7870d0f51d5af3ab9bfeae08 F test/vacuum.test 059871b312eb910bbe49dafde1d01490cc2c6bbe -F test/version.test 7b3084bb0b225304d4f5eb8215973e6daf439bcb +F test/version.test 3a4d507ad9a7d4f7e2ce829b7896e399c8372ef1 F test/view.test 3afca084dab44c7a5772d3c6a326adf93ad52050 F test/where.test 1f87bec674bf85d74ac1cc5b2cd3d89be1e87b1d F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b @@ -142,7 +142,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P ee8c2758a222251fed0197d2a364346d05728240 -R 76ddeede69cbf2bb4e711ae5b4e30b2a +P cc4f824b155138326f1a62066a99c65d0f32fb8b +R c16b27894d2d4cede767f11c98c478c7 U drh -Z 599b54bc5f40ea342f28053ffae009fb +Z c2aea7accc0c02c595db5c858e306720 diff --git a/manifest.uuid b/manifest.uuid index 766bd15a1e..fcdc386021 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cc4f824b155138326f1a62066a99c65d0f32fb8b \ No newline at end of file +c8a7b725b7cec792d2148455a4cecbce9dfebe80 \ No newline at end of file diff --git a/src/main.c b/src/main.c index 5012dafc76..6e5e5771a7 100644 --- a/src/main.c +++ b/src/main.c @@ -14,12 +14,22 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.88 2002/07/18 01:27:18 drh Exp $ +** $Id: main.c,v 1.89 2002/07/19 17:46:39 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include +/* +** A pointer to this structure is used to communicate information +** from sqliteInit into the sqliteInitCallback. +*/ +typedef struct { + sqlite *db; /* The database being initialized */ + char **pzErrMsg; /* Error message stored here */ +} InitData; + + /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. @@ -33,8 +43,9 @@ ** argv[4] = "1" for temporary files, "0" for main database ** */ -int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){ - sqlite *db = (sqlite*)pDb; +static +int sqliteInitCallback(void *pInit, int argc, char **argv, char **azColName){ + InitData *pData = (InitData*)pInit; Parse sParse; int nErr = 0; @@ -54,11 +65,11 @@ int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){ ** structures that describe the table, index, or view. */ memset(&sParse, 0, sizeof(sParse)); - sParse.db = db; + sParse.db = pData->db; sParse.initFlag = 1; sParse.isTemp = argv[4][0] - '0'; sParse.newTnum = atoi(argv[2]); - sqliteRunParser(&sParse, argv[3], 0); + sqliteRunParser(&sParse, argv[3], pData->pzErrMsg); }else{ /* If the SQL column is blank it means this is an index that ** was created to be the PRIMARY KEY or to fulfill a UNIQUE @@ -66,7 +77,7 @@ int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){ ** been created when we processed the CREATE TABLE. All we have ** to do here is record the root page number for that index. */ - Index *pIndex = sqliteFindIndex(db, argv[1]); + Index *pIndex = sqliteFindIndex(pData->db, argv[1]); if( pIndex==0 || pIndex->tnum!=0 ){ /* This can occur if there exists an index on a TEMP table which ** has the same name as another index on a permanent index. Since @@ -98,24 +109,29 @@ int sqliteInitCallback(void *pDb, int argc, char **argv, char **azColName){ ** 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; +static +int upgrade_3_callback(void *pInit, int argc, char **argv, char **NotUsed){ + InitData *pData = (InitData*)pInit; int rc; Table *pTab; Trigger *pTrig; + char *zErr; - pTab = sqliteFindTable(db, argv[0]); + pTab = sqliteFindTable(pData->db, argv[0]); if( pTab ){ pTrig = pTab->pTrigger; pTab->pTrigger = 0; /* Disable all triggers before rebuilding the table */ } - rc = sqlite_exec_printf(db, + rc = sqlite_exec_printf(pData->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]); + 0, 0, &zErr, argv[0], argv[0], argv[0]); + if( zErr ){ + sqliteSetString(pData->pzErrMsg, zErr, 0); + sqlite_freemem(zErr); + } if( pTab ) pTab->pTrigger = pTrig; /* Re-enable triggers */ return rc!=SQLITE_OK; } @@ -142,6 +158,7 @@ int sqliteInit(sqlite *db, char **pzErrMsg){ char *azArg[6]; int meta[SQLITE_N_BTREE_META]; Parse sParse; + InitData initData; /* ** The master database table has a structure like this @@ -201,7 +218,9 @@ int sqliteInit(sqlite *db, char **pzErrMsg){ azArg[3] = master_schema; azArg[4] = "0"; azArg[5] = 0; - sqliteInitCallback(db, 5, azArg, 0); + initData.db = db; + initData.pzErrMsg = pzErrMsg; + sqliteInitCallback(&initData, 5, azArg, 0); pTab = sqliteFindTable(db, MASTER_NAME); if( pTab ){ pTab->readOnly = 1; @@ -209,7 +228,7 @@ int sqliteInit(sqlite *db, char **pzErrMsg){ azArg[1] = TEMP_MASTER_NAME; azArg[3] = temp_master_schema; azArg[4] = "1"; - sqliteInitCallback(db, 5, azArg, 0); + sqliteInitCallback(&initData, 5, azArg, 0); pTab = sqliteFindTable(db, TEMP_MASTER_NAME); if( pTab ){ pTab->readOnly = 1; @@ -258,7 +277,7 @@ int sqliteInit(sqlite *db, char **pzErrMsg){ sParse.db = db; sParse.pBe = db->pBe; sParse.xCallback = sqliteInitCallback; - sParse.pArg = (void*)db; + sParse.pArg = (void*)&initData; sParse.initFlag = 1; sqliteRunParser(&sParse, db->file_format>=2 ? init_script : older_init_script, @@ -355,14 +374,17 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ ** is read only, interrupt receive, etc.) then refuse to open. */ if( db->file_format<3 ){ - char *zErr; + char *zErr = 0; + InitData initData; int meta[SQLITE_N_BTREE_META]; + initData.db = db; + initData.pzErrMsg = &zErr; db->file_format = 3; rc = sqlite_exec(db, "BEGIN; SELECT name FROM sqlite_master WHERE type='table';", upgrade_3_callback, - db, + &initData, &zErr); if( rc==SQLITE_OK ){ sqliteBtreeGetMeta(db->pBe, meta); @@ -374,11 +396,12 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ sqliteSetString(pzErrMsg, "unable to upgrade database to the version 2.6 format", zErr ? ": " : 0, zErr, 0); - sqliteFree(zErr); + sqlite_freemem(zErr); sqliteStrRealloc(pzErrMsg); sqlite_close(db); return 0; } + sqlite_freemem(zErr); } /* Return a pointer to the newly opened database structure */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 4b48ecc529..d7683a1c01 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.139 2002/07/18 00:34:12 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.140 2002/07/19 17:46:39 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -949,4 +949,3 @@ TriggerStep *sqliteTriggerUpdateStep(Token*, ExprList*, Expr*, int); TriggerStep *sqliteTriggerDeleteStep(Token*, Expr*); void sqliteDeleteTrigger(Trigger*); int sqliteJoinType(Parse*, Token*, Token*, Token*); -int sqliteInitCallback(void*,int,char**,char**); diff --git a/test/version.test b/test/version.test index 623c4a37d1..33aa049fb8 100644 --- a/test/version.test +++ b/test/version.test @@ -12,7 +12,7 @@ # focus of this file is testing the ability of the library to detect # past or future file format version numbers and respond appropriately. # -# $Id: version.test,v 1.2 2002/07/18 02:07:08 drh Exp $ +# $Id: version.test,v 1.3 2002/07/19 17:46:41 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -177,6 +177,6 @@ do_test version-2.1 { catch {file attributes test.db -readonly 1} set rc [catch {sqlite db test.db} msg] lappend rc $msg -} {1 {unable to upgrade database to the version 2.6 format}} +} {1 {unable to upgrade database to the version 2.6 format: attempt to write a readonly database}} finish_test