Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix vacuum so that it works with blobs. (CVS 1490) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
4feb4b9a71ce7a92924d2358a7ccecb4 |
User & Date: | danielk1977 2004-05-29 10:23:19.000 |
Context
2004-05-29
| ||
10:43 | Ensure vacuum handles table names with spaces in them. (CVS 1491) (check-in: 0a6689be84 user: danielk1977 tags: trunk) | |
10:23 | Fix vacuum so that it works with blobs. (CVS 1490) (check-in: 4feb4b9a71 user: danielk1977 tags: trunk) | |
02:44 | Avoid arithmetic on void pointers. (CVS 1489) (check-in: 3d68703e2e user: danielk1977 tags: trunk) | |
Changes
Changes to src/btree.c.
1 2 3 4 5 6 7 8 9 10 11 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | /* ** 2004 April 6 ** ** 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. ** ************************************************************************* ** $Id: btree.c,v 1.148 2004/05/29 10:23:19 danielk1977 Exp $ ** ** This file implements a external (disk-based) database using BTrees. ** For a detailed discussion of BTrees, refer to ** ** Donald E. Knuth, THE ART OF COMPUTER PROGRAMMING, Volume 3: ** "Sorting And Searching", pages 473-480. Addison-Wesley ** Publishing Company, Reading, Massachusetts. |
︙ | ︙ | |||
4146 4147 4148 4149 4150 4151 4152 | } /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** ** The size of file pBtFrom may be reduced by this operation. | | | 4146 4147 4148 4149 4150 4151 4152 4153 4154 4155 4156 4157 4158 4159 4160 | } /* ** Copy the complete content of pBtFrom into pBtTo. A transaction ** must be active for both files. ** ** The size of file pBtFrom may be reduced by this operation. ** If anything goes wrong, the transaction on pBtTo is rolled back. */ int sqlite3BtreeCopyFile(Btree *pBtTo, Btree *pBtFrom){ int rc = SQLITE_OK; Pgno i, nPage, nToPage; if( !pBtTo->inTrans || !pBtFrom->inTrans ) return SQLITE_ERROR; if( pBtTo->pCursor ) return SQLITE_BUSY; |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
19 20 21 22 23 24 25 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** | | | 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** PRAGMA ** ** $Id: build.c,v 1.199 2004/05/29 10:23:19 danielk1977 Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Check to see if the schema for the database needs |
︙ | ︙ | |||
562 563 564 565 566 567 568 | "the temporary database file"); return; } } } /* Make sure the new table name does not collide with an existing | | | < < < | | | 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 | "the temporary database file"); return; } } } /* Make sure the new table name does not collide with an existing ** index or table name in the same database. Issue an error message if ** it does. */ pTable = sqlite3FindTable(db, zName, db->aDb[iDb].zName); if( pTable ){ sqlite3ErrorMsg(pParse, "table %T already exists", pName); sqliteFree(zName); return; } if( (pIdx = sqlite3FindIndex(db, zName, 0))!=0 && (pIdx->iDb==0 || !db->init.busy) ){ sqlite3ErrorMsg(pParse, "there is already an index named %s", zName); |
︙ | ︙ | |||
1687 1688 1689 1690 1691 1692 1693 | ** own name. */ if( pName && !db->init.busy ){ Index *pISameName; /* Another index with the same name */ Table *pTSameName; /* A table with same name as the index */ zName = sqliteStrNDup(pName->z, pName->n); if( zName==0 ) goto exit_create_index; | | | 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 | ** own name. */ if( pName && !db->init.busy ){ Index *pISameName; /* Another index with the same name */ Table *pTSameName; /* A table with same name as the index */ zName = sqliteStrNDup(pName->z, pName->n); if( zName==0 ) goto exit_create_index; if( (pISameName = sqlite3FindIndex(db, zName, db->aDb[iDb].zName))!=0 ){ sqlite3ErrorMsg(pParse, "index %s already exists", zName); goto exit_create_index; } if( (pTSameName = sqlite3FindTable(db, zName, 0))!=0 ){ sqlite3ErrorMsg(pParse, "there is already a table named %s", zName); goto exit_create_index; } |
︙ | ︙ |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.196 2004/05/29 10:23:19 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> /* ** A pointer to this structure is used to communicate information |
︙ | ︙ | |||
243 244 245 246 247 248 249 | sqlite3BtreeCloseCursor(curMain); return rc; } }else{ memset(meta, 0, sizeof(meta)); } db->aDb[iDb].schema_cookie = meta[0]; | | < < < | | > | | > > > > > > > > > > | > > > > | > | < > > | > > > > | | | | < < < < < < < | < < < < < > | 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 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | sqlite3BtreeCloseCursor(curMain); return rc; } }else{ memset(meta, 0, sizeof(meta)); } db->aDb[iDb].schema_cookie = meta[0]; /* If opening a non-empty database, check the text encoding. For the ** main database, set sqlite3.enc to the encoding of the main database. ** For an attached db, it is an error if the encoding is not the same ** as sqlite3.enc. */ if( meta[4] ){ /* text encoding */ if( iDb==0 ){ /* If opening the main database, set db->enc. */ db->enc = (u8)meta[4]; }else{ /* If opening an attached database, the encoding much match db->enc */ if( meta[4]!=db->enc ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "attached databases must use the same" " text encoding as main database", (char*)0); return SQLITE_ERROR; } } } if( iDb==0 ){ size = meta[2]; if( size==0 ){ size = MAX_PAGES; } db->cache_size = size; db->safety_level = meta[3]; if( meta[5]>0 && meta[5]<=2 && db->temp_store==0 ){ db->temp_store = meta[5]; } if( db->safety_level==0 ) db->safety_level = 2; /* FIX ME: Every struct Db will need a next_cookie */ db->next_cookie = meta[0]; db->file_format = meta[1]; if( db->file_format==0 ){ /* This happens if the database was initially empty */ db->file_format = 1; } } /* ** file_format==1 Version 3.0.0. */ if( meta[1]>1 ){ sqlite3BtreeCloseCursor(curMain); sqlite3SetString(pzErrMsg, "unsupported file format", (char*)0); return SQLITE_ERROR; } sqlite3BtreeSetCacheSize(db->aDb[iDb].pBt, db->cache_size); sqlite3BtreeSetSafetyLevel(db->aDb[iDb].pBt, meta[3]==0 ? 2 : meta[3]); /* Read the schema information out of the schema tables */ assert( db->init.busy ); if( rc==SQLITE_EMPTY ){ /* For an empty database, there is nothing to read */ rc = SQLITE_OK; }else{ sqlite3SafetyOff(db); if( iDb==0 ){ /* This SQL statement tries to read the temp.* schema from the ** sqlite_temp_master table. It might return SQLITE_EMPTY. */ rc = sqlite3_exec(db, init_script1, sqlite3InitCallback, &initData, 0); if( rc==SQLITE_OK || rc==SQLITE_EMPTY ){ rc = sqlite3_exec(db, init_script2, sqlite3InitCallback, &initData, 0); |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.124 2004/05/29 10:23:20 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ |
︙ | ︙ | |||
778 779 780 781 782 783 784 | number(A) ::= INTEGER(X). {A = X;} number(A) ::= FLOAT(X). {A = X;} plus_opt ::= PLUS. plus_opt ::= . //////////////////////////// The CREATE TRIGGER command ///////////////////// | | | > | 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 | number(A) ::= INTEGER(X). {A = X;} number(A) ::= FLOAT(X). {A = X;} plus_opt ::= PLUS. plus_opt ::= . //////////////////////////// The CREATE TRIGGER command ///////////////////// cmd ::= CREATE trigger_decl(A) BEGIN trigger_cmd_list(S) END(Z). { Token all; all.z = A.z; all.n = (Z.z - A.z) + Z.n; sqlite3FinishTrigger(pParse, S, &all); } trigger_decl(A) ::= temp(T) TRIGGER nm(B) dbnm(Z) trigger_time(C) trigger_event(D) ON nm(E) dbnm(DB) foreach_clause(F) when_clause(G). { SrcList *pTab = sqlite3SrcListAppend(0, &E, &DB); sqlite3BeginTrigger(pParse, &B, &Z, C, D.a, D.b, pTab, F, G, T); A = (Z.n==0?B:Z); } %type trigger_time {int} trigger_time(A) ::= BEFORE. { A = TK_BEFORE; } trigger_time(A) ::= AFTER. { A = TK_AFTER; } trigger_time(A) ::= INSTEAD OF. { A = TK_INSTEAD;} trigger_time(A) ::= . { A = TK_BEFORE; } |
︙ | ︙ |
Changes to src/trigger.c.
︙ | ︙ | |||
209 210 211 212 213 214 215 | if( !db->init.busy ){ static VdbeOpList insertTrig[] = { { OP_NewRecno, 0, 0, 0 }, { OP_String, 0, 0, "trigger" }, { OP_String, 0, 0, 0 }, /* 2: trigger name */ { OP_String, 0, 0, 0 }, /* 3: table name */ { OP_Integer, 0, 0, 0 }, | > | > | | 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 | if( !db->init.busy ){ static VdbeOpList insertTrig[] = { { OP_NewRecno, 0, 0, 0 }, { OP_String, 0, 0, "trigger" }, { OP_String, 0, 0, 0 }, /* 2: trigger name */ { OP_String, 0, 0, 0 }, /* 3: table name */ { OP_Integer, 0, 0, 0 }, { OP_String, 0, 0, "CREATE TRIGGER "}, { OP_String, 0, 0, 0 }, /* 6: SQL */ { OP_Concat, 2, 0, 0 }, { OP_MakeRecord, 5, 0, "tttit" }, { OP_PutIntKey, 0, 0, 0 }, }; int addr; Vdbe *v; /* Make an entry in the sqlite_master table */ v = sqlite3GetVdbe(pParse); if( v==0 ) goto triggerfinish_cleanup; sqlite3BeginWriteOperation(pParse, 0, nt->iDb); sqlite3OpenMasterTable(v, nt->iDb); addr = sqlite3VdbeAddOpList(v, ArraySize(insertTrig), insertTrig); sqlite3VdbeChangeP3(v, addr+2, nt->name, 0); sqlite3VdbeChangeP3(v, addr+3, nt->table, 0); sqlite3VdbeChangeP3(v, addr+6, pAll->z, pAll->n); if( nt->iDb==0 ){ sqlite3ChangeCookie(db, v, 0); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); sqlite3EndWriteOperation(pParse); } |
︙ | ︙ |
Changes to src/vacuum.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** | | < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 | ** ************************************************************************* ** This file contains code used to implement the VACUUM command. ** ** Most of the code in this file may be omitted by defining the ** SQLITE_OMIT_VACUUM macro. ** ** $Id: vacuum.c,v 1.17 2004/05/29 10:23:20 danielk1977 Exp $ */ #include "sqliteInt.h" #include "os.h" #if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM /* ** Generate a random name of 20 character in length. */ static void randomName(unsigned char *zBuf){ static const unsigned char zChars[] = "abcdefghijklmnopqrstuvwxyz" "0123456789"; int i; sqlite3Randomness(20, zBuf); for(i=0; i<20; i++){ zBuf[i] = zChars[ zBuf[i]%(sizeof(zChars)-1) ]; } } /* ** Execute zSql on database db. Return an error code. */ static int execSql(sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; if( SQLITE_OK!=sqlite3_prepare(db, zSql, -1, &pStmt, 0) ){ return sqlite3_errcode(db); } while( SQLITE_ROW==sqlite3_step(pStmt) ); return sqlite3_finalize(pStmt); } /* ** Execute zSql on database db. The statement returns exactly ** one column. Execute this as SQL on the same database. */ static int execExecSql(sqlite3 *db, const char *zSql){ sqlite3_stmt *pStmt; int rc; rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0); if( rc!=SQLITE_OK ) return rc; while( SQLITE_ROW==sqlite3_step(pStmt) ){ rc = execSql(db, sqlite3_column_text(pStmt, 0)); if( rc!=SQLITE_OK ){ sqlite3_finalize(pStmt); return rc; } } return sqlite3_finalize(pStmt); } #endif /* ** The non-standard VACUUM command is used to clean up the database, ** collapse free space, etc. It is modelled after the VACUUM command ** in PostgreSQL. ** |
︙ | ︙ | |||
212 213 214 215 216 217 218 219 220 221 222 | return; } /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ int sqlite3RunVacuum(char **pzErrMsg, sqlite *db){ #if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM const char *zFilename; /* full pathname of the database file */ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ | > < < < < < < | < < | < | > < | | | | < | > > > | | | > > | | < < | | | | | | | > > > > > > > > > > > | > > > > | > > > | < < < < | < | | < > > > > > | > > | | > > | | > > > > > > > > | > > > > > > > | > > > > | > > > > | > > > > > > > | | > > > > | > < | < < | | | | > | < | < < < < | | < | 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 113 114 115 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 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 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 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 | return; } /* ** This routine implements the OP_Vacuum opcode of the VDBE. */ int sqlite3RunVacuum(char **pzErrMsg, sqlite *db){ int rc = SQLITE_OK; /* Return code from service routines */ #if !defined(SQLITE_OMIT_VACUUM) || SQLITE_OMIT_VACUUM const char *zFilename; /* full pathname of the database file */ int nFilename; /* number of characters in zFilename[] */ char *zTemp = 0; /* a temporary file in same directory as zFilename */ int i; /* Loop counter */ char *zSql = 0; sqlite3_stmt *pStmt = 0; if( db->flags & SQLITE_InTrans ){ sqlite3SetString(pzErrMsg, "cannot VACUUM from within a transaction", (char*)0); rc = SQLITE_ERROR; goto end_of_vacuum; } /* Get the full pathname of the database file and create a ** temporary filename in the same directory as the original file. */ zFilename = sqlite3BtreeGetFilename(db->aDb[0].pBt); if( zFilename==0 ){ /* The in-memory database. Do nothing. */ goto end_of_vacuum; } nFilename = strlen(zFilename); zTemp = sqliteMalloc( nFilename+100 ); if( zTemp==0 ){ rc = SQLITE_NOMEM; goto end_of_vacuum; } strcpy(zTemp, zFilename); for(i=0; i<10; i++){ zTemp[nFilename] = '-'; randomName((unsigned char*)&zTemp[nFilename+1]); if( !sqlite3OsFileExists(zTemp) ) break; } /* Attach the temporary database as 'vacuum' */ zSql = sqlite3MPrintf("ATTACH '%s' AS vacuum_db;", zTemp); if( !zSql ){ rc = SQLITE_NOMEM; goto end_of_vacuum; } rc = execSql(db, zSql); sqliteFree(zSql); zSql = 0; if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Begin a transaction */ rc = execSql(db, "BEGIN;"); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Query the schema of the main database. Create a mirror schema ** in the temporary database. */ rc = execExecSql(db, "SELECT 'CREATE ' || type || ' vacuum_db.' || " "substr(sql, length(type)+9, 1000000) " "FROM sqlite_master " "WHERE type != 'trigger' AND sql IS NOT NULL " "ORDER BY (type != 'table');" ); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Loop through the tables in the main database. For each, do ** an "INSERT INTO vacuum_db.xxx SELECT * FROM xxx;" to copy ** the contents to the temporary database. */ rc = execExecSql(db, "SELECT 'INSERT INTO vacuum_db.' || name " "|| ' SELECT * FROM ' || name || ';'" "FROM sqlite_master " "WHERE type = 'table';" ); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* Copy the triggers from the main database to the temporary database. ** This was deferred before in case the triggers interfered with copying ** the data. It's possible the indices should be deferred until this ** point also. */ rc = execExecSql(db, "SELECT 'CREATE ' || type || ' vacuum_db.' || " "substr(sql, length(type)+9, 1000000) " "FROM sqlite_master " "WHERE type = 'trigger' AND sql IS NOT NULL;" ); if( rc!=SQLITE_OK ) goto end_of_vacuum; /* At this point, unless the main db was completely empty, there is now a ** transaction open on the vacuum database, but not on the main database. ** Open a btree level transaction on the main database. This allows a ** call to sqlite3BtreeCopyFile(). The main database btree level ** transaction is then committed, so the SQL level never knows it was ** opened for writing. This way, the SQL transaction used to create the ** temporary database never needs to be committed. */ /* FIX ME: The above will be the case shortly. But for now, a transaction ** will have been started on the main database file by the 'BEGIN'. */ /* rc = sqlite3BtreeBeginTrans(db->aDb[0].pBt); if( rc!=SQLITE_OK ) goto end_of_vacuum; */ if( db->aDb[db->nDb-1].inTrans ){ Btree *pTemp = db->aDb[db->nDb-1].pBt; Btree *pMain = db->aDb[0].pBt; u32 meta; /* Copy Btree meta values 3 and 4. These correspond to SQL layer meta ** values 2 and 3, the default values of a couple of pragmas. */ rc = sqlite3BtreeGetMeta(pMain, 3, &meta); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeUpdateMeta(pTemp, 3, meta); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeGetMeta(pMain, 4, &meta); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeUpdateMeta(pTemp, 4, meta); if( rc!=SQLITE_OK ) goto end_of_vacuum; rc = sqlite3BtreeCopyFile(pMain, pTemp); /* FIX ME: Remove the main btree from the transaction so that it is not ** rolled back. This won't be required once the new 'auto-commit' ** model is in place. */ rc = sqlite3BtreeCommit(pMain); db->aDb[0].inTrans = 0; } end_of_vacuum: execSql(db, "DETACH vacuum_db;"); execSql(db, "ROLLBACK;"); if( zTemp ){ sqlite3OsDelete(zTemp); sqliteFree(zTemp); } if( zSql ) sqliteFree( zSql ); if( pStmt ) sqlite3_finalize( pStmt ); #endif return rc; } |
Changes to test/attach.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and related functionality. # # $Id: attach.test,v 1.18 2004/05/29 10:23:20 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl for {set i 2} {$i<=15} {incr i} { file delete -force test$i.db |
︙ | ︙ | |||
68 69 70 71 72 73 74 | SELECT * FROM two.t2; } } {1 {no such table: two.t2}} do_test attach-1.8 { catchsql { ATTACH DATABASE 'test3.db' AS three; } | | | | | 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 | SELECT * FROM two.t2; } } {1 {no such table: two.t2}} do_test attach-1.8 { catchsql { ATTACH DATABASE 'test3.db' AS three; } } {0 {}} do_test attach-1.9 { catchsql { SELECT * FROM three.sqlite_master; } } {0 {}} do_test attach-1.10 { catchsql { DETACH DATABASE three; } } {0 {}} do_test attach-1.11 { execsql { ATTACH 'test.db' AS db2; ATTACH 'test.db' AS db3; ATTACH 'test.db' AS db4; ATTACH 'test.db' AS db5; ATTACH 'test.db' AS db6; |
︙ | ︙ | |||
559 560 561 562 563 564 565 | # Check to make sure we get a sensible error if unable to open # the file that we are trying to attach. # do_test attach-6.1 { catchsql { ATTACH DATABASE 'no-such-file' AS nosuch; } | | | 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 | # Check to make sure we get a sensible error if unable to open # the file that we are trying to attach. # do_test attach-6.1 { catchsql { ATTACH DATABASE 'no-such-file' AS nosuch; } } {0 {}} file delete -force no-such-file if {$tcl_platform(platform)=="unix"} { do_test attach-6.2 { sqlite dbx cannot-read dbx eval {CREATE TABLE t1(a,b,c)} dbx close file attributes cannot-read -permission 0000 |
︙ | ︙ |
Changes to test/attach3.test.
︙ | ︙ | |||
8 9 10 11 12 13 14 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and schema changes to attached databases. # | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this script is testing the ATTACH and DETACH commands # and schema changes to attached databases. # # $Id: attach3.test,v 1.5 2004/05/29 10:23:20 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Create tables t1 and t2 in the main database |
︙ | ︙ | |||
168 169 170 171 172 173 174 | SELECT * FROM t3; } } {10 20 20 40} do_test attach3-5.3 { execsql { SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; } | | | 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | SELECT * FROM t3; } } {10 20 20 40} do_test attach3-5.3 { execsql { SELECT * FROM aux.sqlite_master WHERE name = 'tr1'; } } {trigger tr1 t3 0 {CREATE TRIGGER tr1 AFTER INSERT ON t3 BEGIN INSERT INTO t3 VALUES(new.e*2, new.f*2); END}} # Drop the trigger do_test attach3-8.1 { execsql { DROP TRIGGER aux.tr1; |
︙ | ︙ |
Changes to test/vacuum.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # 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 file is testing the VACUUM statement. # | | | > | > | 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 | # 2001 September 15 # # 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 file is testing the VACUUM statement. # # $Id: vacuum.test,v 1.19 2004/05/29 10:23:20 danielk1977 Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl proc cksum {{db db}} { set sql "SELECT name, type, sql FROM sqlite_master ORDER BY name, type" set txt [$db eval $sql]\n set sql "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name" foreach tbl [$db eval $sql] { append txt [$db eval "SELECT * FROM $tbl"]\n } foreach prag {default_synchronous default_cache_size} { append txt $prag-[$db eval "PRAGMA $prag"]\n } set cksum [string length $txt]-[md5 $txt] # puts $cksum-[file size test.db] |
︙ | ︙ |