Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Allow DROP TABLE and DROP INDEX on attached databases. (CVS 1484) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
2fb3708e10a06660ad1974ef8e9742b7 |
User & Date: | danielk1977 2004-05-28 12:11:21.000 |
Context
2004-05-28
| ||
12:33 | Allow CREATE and DROP VIEW on attached databases. (CVS 1485) (check-in: ad879a957d user: danielk1977 tags: trunk) | |
12:11 | Allow DROP TABLE and DROP INDEX on attached databases. (CVS 1484) (check-in: 2fb3708e10 user: danielk1977 tags: trunk) | |
11:37 | Allow CREATE TABLE and CREATE INDEX on attached databases. (CVS 1483) (check-in: 4984a130cc user: danielk1977 tags: trunk) | |
Changes
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.195 2004/05/28 12:11:21 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 |
︙ | ︙ | |||
1324 1325 1326 1327 1328 1329 1330 | return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ | | | | > > | | | | | | | | | | | | | | | | | | | | 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 | return pTab; } /* ** This routine is called to do the work of a DROP TABLE statement. ** pName is the name of the table to be dropped. */ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){ Table *pTab; Vdbe *v; int base; sqlite *db = pParse->db; int iDb; if( pParse->nErr || sqlite3_malloc_failed ) goto exit_drop_table; assert( pName->nSrc==1 ); pTab = sqlite3LocateTable(pParse, pName->a[0].zName, pName->a[0].zDatabase); if( pTab==0 ) goto exit_drop_table; iDb = pTab->iDb; assert( iDb>=0 && iDb<db->nDb ); #ifndef SQLITE_OMIT_AUTHORIZATION { int code; const char *zTab = SCHEMA_TABLE(pTab->iDb); const char *zDb = db->aDb[pTab->iDb].zName; if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb)){ goto exit_drop_table; } if( isView ){ if( iDb==1 ){ code = SQLITE_DROP_TEMP_VIEW; }else{ code = SQLITE_DROP_VIEW; } }else{ if( iDb==1 ){ code = SQLITE_DROP_TEMP_TABLE; }else{ code = SQLITE_DROP_TABLE; } } if( sqlite3AuthCheck(pParse, code, pTab->zName, 0, zDb) ){ goto exit_drop_table; } if( sqlite3AuthCheck(pParse, SQLITE_DELETE, pTab->zName, 0, zDb) ){ goto exit_drop_table; } } #endif if( pTab->readOnly ){ sqlite3ErrorMsg(pParse, "table %s may not be dropped", pTab->zName); pParse->nErr++; goto exit_drop_table; } if( isView && pTab->pSelect==0 ){ sqlite3ErrorMsg(pParse, "use DROP TABLE to delete table %s", pTab->zName); goto exit_drop_table; } if( !isView && pTab->pSelect ){ sqlite3ErrorMsg(pParse, "use DROP VIEW to delete view %s", pTab->zName); goto exit_drop_table; } /* Generate code to remove the table from the master table ** on disk. */ v = sqlite3GetVdbe(pParse); if( v ){ |
︙ | ︙ | |||
1398 1399 1400 1401 1402 1403 1404 | { OP_Delete, 0, 0, 0}, { OP_Rewind, 0, ADDR(10), 0}, { OP_Goto, 0, ADDR(3), 0}, { OP_Next, 0, ADDR(3), 0}, /* 9 */ }; Index *pIdx; Trigger *pTrigger; | | | | | | | | | | | | | | > > > | 1400 1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 | { OP_Delete, 0, 0, 0}, { OP_Rewind, 0, ADDR(10), 0}, { OP_Goto, 0, ADDR(3), 0}, { OP_Next, 0, ADDR(3), 0}, /* 9 */ }; Index *pIdx; Trigger *pTrigger; sqlite3BeginWriteOperation(pParse, 0, pTab->iDb); /* Drop all triggers associated with the table being dropped */ pTrigger = pTab->pTrigger; while( pTrigger ){ assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 ); sqlite3DropTriggerPtr(pParse, pTrigger, 1); if( pParse->explain ){ pTrigger = pTrigger->pNext; }else{ pTrigger = pTab->pTrigger; } } /* Drop all SQLITE_MASTER entries that refer to the table */ sqlite3OpenMasterTable(v, pTab->iDb); base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable); sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0); /* Drop all SQLITE_TEMP_MASTER entries that refer to the table */ if( pTab->iDb!=1 ){ sqlite3OpenMasterTable(v, 1); base = sqlite3VdbeAddOpList(v, ArraySize(dropTable), dropTable); sqlite3VdbeChangeP3(v, base+1, pTab->zName, 0); } if( pTab->iDb!=1 ){ /* Temp database has no schema cookie */ sqlite3ChangeCookie(db, v, pTab->iDb); } sqlite3VdbeAddOp(v, OP_Close, 0, 0); if( !isView ){ sqlite3VdbeAddOp(v, OP_Destroy, pTab->tnum, pTab->iDb); for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){ sqlite3VdbeAddOp(v, OP_Destroy, pIdx->tnum, pIdx->iDb); } } sqlite3EndWriteOperation(pParse); } /* Delete the in-memory description of the table. ** ** Exception: if the SQL statement began with the EXPLAIN keyword, ** then no changes should be made. */ if( !pParse->explain ){ sqliteUnlinkAndDeleteTable(db, pTab); db->flags |= SQLITE_InternChanges; } sqliteViewResetAll(db, iDb); exit_drop_table: sqlite3SrcListDelete(pName); } /* ** This routine is called to create a new foreign key on the table ** currently under construction. pFromCol determines which columns ** in the current table point to the foreign key. If pFromCol==0 then ** connect the key to the last column inserted. pTo is the name of |
︙ | ︙ | |||
1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 | goto exit_drop_index; } if( pIndex->autoIndex ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } if( pIndex->iDb>1 ){ sqlite3ErrorMsg(pParse, "cannot alter schema of attached " "databases", 0); goto exit_drop_index; } #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[pIndex->iDb].zName; const char *zTab = SCHEMA_TABLE(pIndex->iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ | > > | 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 | goto exit_drop_index; } if( pIndex->autoIndex ){ sqlite3ErrorMsg(pParse, "index associated with UNIQUE " "or PRIMARY KEY constraint cannot be dropped", 0); goto exit_drop_index; } /* if( pIndex->iDb>1 ){ sqlite3ErrorMsg(pParse, "cannot alter schema of attached " "databases", 0); goto exit_drop_index; } */ #ifndef SQLITE_OMIT_AUTHORIZATION { int code = SQLITE_DROP_INDEX; Table *pTab = pIndex->pTable; const char *zDb = db->aDb[pIndex->iDb].zName; const char *zTab = SCHEMA_TABLE(pIndex->iDb); if( sqlite3AuthCheck(pParse, SQLITE_DELETE, zTab, 0, zDb) ){ |
︙ | ︙ |
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.121 2004/05/28 12:11:21 danielk1977 Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { if( pParse->zErrMsg==0 ){ |
︙ | ︙ | |||
258 259 260 261 262 263 264 | resolvetype(A) ::= ABORT. { A = OE_Abort; } resolvetype(A) ::= FAIL. { A = OE_Fail; } resolvetype(A) ::= IGNORE. { A = OE_Ignore; } resolvetype(A) ::= REPLACE. { A = OE_Replace; } ////////////////////////// The DROP TABLE ///////////////////////////////////// // | | > > | 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 | resolvetype(A) ::= ABORT. { A = OE_Abort; } resolvetype(A) ::= FAIL. { A = OE_Fail; } resolvetype(A) ::= IGNORE. { A = OE_Ignore; } resolvetype(A) ::= REPLACE. { A = OE_Replace; } ////////////////////////// The DROP TABLE ///////////////////////////////////// // cmd ::= DROP TABLE nm(X) dbnm(Y). { sqlite3DropTable(pParse, sqlite3SrcListAppend(0,&X,&Y), 0); } ///////////////////// The CREATE VIEW statement ///////////////////////////// // cmd ::= CREATE(X) temp(T) VIEW nm(Y) AS select(S). { sqlite3CreateView(pParse, &X, &Y, S, T); } cmd ::= DROP VIEW nm(X). { |
︙ | ︙ |
Changes to src/sqliteInt.h.
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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 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. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.258 2004/05/28 12:11:21 danielk1977 Exp $ */ #include "config.h" #include "sqlite.h" #include "hash.h" #include "parse.h" #include <stdio.h> #include <stdlib.h> |
︙ | ︙ | |||
1207 1208 1209 1210 1211 1212 1213 | void sqlite3AddDefaultValue(Parse*,Token*,int); void sqlite3AddCollateType(Parse*, const char*, int); CollSeq *sqlite3ChangeCollatingFunction(sqlite*,const char*,int, void*, int(*)(void*,int,const void*,int,const void*)); void sqlite3EndTable(Parse*,Token*,Select*); void sqlite3CreateView(Parse*,Token*,Token*,Select*,int); int sqlite3ViewGetColumnNames(Parse*,Table*); | | | 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 | void sqlite3AddDefaultValue(Parse*,Token*,int); void sqlite3AddCollateType(Parse*, const char*, int); CollSeq *sqlite3ChangeCollatingFunction(sqlite*,const char*,int, void*, int(*)(void*,int,const void*,int,const void*)); void sqlite3EndTable(Parse*,Token*,Select*); void sqlite3CreateView(Parse*,Token*,Token*,Select*,int); int sqlite3ViewGetColumnNames(Parse*,Table*); void sqlite3DropTable(Parse*, SrcList*, int); void sqlite3DeleteTable(sqlite*, Table*); void sqlite3Insert(Parse*, SrcList*, ExprList*, Select*, IdList*, int); IdList *sqlite3IdListAppend(IdList*, Token*); int sqlite3IdListIndex(IdList*,const char*); SrcList *sqlite3SrcListAppend(SrcList*, Token*, Token*); void sqlite3SrcListAddAlias(SrcList*, Token*); void sqlite3SrcListAssignCursors(Parse*, SrcList*); |
︙ | ︙ |
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.2 2004/05/28 12:11:21 danielk1977 Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # Create tables t1 and t2 in the main database |
︙ | ︙ | |||
31 32 33 34 35 36 37 | execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } db2 db2 close # Create a table in the auxilary database. | | | | | | | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 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 78 79 80 81 82 83 84 85 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 | execsql { CREATE TABLE t1(a, b); CREATE TABLE t2(c, d); } db2 db2 close # Create a table in the auxilary database. do_test attach3-1.1 { execsql { ATTACH 'test2.db' AS aux; } } {} do_test attach3-1.2 { execsql { CREATE TABLE aux.t3(e, f); } } {} do_test attach3-1.3 { execsql { SELECT * FROM sqlite_master WHERE name = 't3'; } } {} do_test attach3-1.4 { execsql { SELECT * FROM aux.sqlite_master WHERE name = 't3'; } } {table t3 t3 4 {CREATE TABLE t3(e, f)}} do_test attach3-1.5 { execsql { INSERT INTO t3 VALUES(1, 2); SELECT * FROM t3; } } {1 2} # Create an index on the auxilary database table. do_test attach4-2.1 { execsql { CREATE INDEX aux.i1 on t3(e); } } {} execsql { pragma vdbe_trace = off; } do_test attach4-2.2 { execsql { SELECT * FROM sqlite_master WHERE name = 'i1'; } } {} do_test attach4-2.3 { execsql { SELECT * FROM aux.sqlite_master WHERE name = 'i1'; } } {index i1 t3 5 {CREATE INDEX i1 on t3(e)}} # Drop the index on the aux database table. do_test attach4-3.1 { execsql { DROP INDEX aux.i1; SELECT * FROM aux.sqlite_master WHERE name = 'i1'; } } {} do_test attach4-3.2 { execsql { CREATE INDEX aux.i1 on t3(e); SELECT * FROM aux.sqlite_master WHERE name = 'i1'; } } {index i1 t3 5 {CREATE INDEX i1 on t3(e)}} do_test attach4-3.3 { execsql { DROP INDEX i1; SELECT * FROM aux.sqlite_master WHERE name = 'i1'; } } {} # Drop the tables in the auxilary database. do_test attach4-4.1 { execsql { DROP TABLE aux.t1; SELECT name FROM aux.sqlite_master; } } {t2 t3} do_test attach4-4.2 { # This will drop main.t2 execsql { DROP TABLE t2; SELECT name FROM aux.sqlite_master; } } {t2 t3} do_test attach4-4.3 { execsql { DROP TABLE t2; SELECT name FROM aux.sqlite_master; } } {t3} do_test attach4-4.4 { execsql { DROP TABLE aux.t3; SELECT * FROM aux.sqlite_master; } } {} finish_test |