Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Correctly handle attempts to add a UNIQUE or PRIMARY KEY column using the ALTER TABLE statement. Ticket #3651. (CVS 6291) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
dd179ff2986bc2a86d70bbe927fd0e12 |
User & Date: | drh 2009-02-13 03:43:32.000 |
Context
2009-02-13
| ||
16:59 | Make sure OOM errors in the ANALYSIS loader get reported back out to high-level layers. Strange behavior can result otherwise. (CVS 6292) (check-in: 88a6355cd6 user: drh tags: trunk) | |
03:43 | Correctly handle attempts to add a UNIQUE or PRIMARY KEY column using the ALTER TABLE statement. Ticket #3651. (CVS 6291) (check-in: dd179ff298 user: drh tags: trunk) | |
2009-02-12
| ||
17:07 | Add additional cross-references from API documentation to other documents. Comment changes only; no changes to code. (CVS 6290) (check-in: 97203a0ad7 user: drh tags: trunk) | |
Changes
Changes to src/alter.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains C code routines that used to generate VDBE code ** that implements the ALTER TABLE command. ** ** $Id: alter.c,v 1.53 2009/02/13 03:43:32 drh Exp $ */ #include "sqliteInt.h" /* ** The code in this file only exists if we are not omitting the ** ALTER TABLE logic from the build. */ |
︙ | ︙ | |||
449 450 451 452 453 454 455 | if( pParse->nErr || db->mallocFailed ) return; pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zName; | | | 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 | if( pParse->nErr || db->mallocFailed ) return; pNew = pParse->pNewTable; assert( pNew ); assert( sqlite3BtreeHoldsAllMutexes(db) ); iDb = sqlite3SchemaToIndex(db, pNew->pSchema); zDb = db->aDb[iDb].zName; zTab = &pNew->zName[16]; /* Skip the "sqlite_altertab_" prefix on the name */ pCol = &pNew->aCol[pNew->nCol-1]; pDflt = pCol->pDflt; pTab = sqlite3FindTable(db, zTab, zDb); assert( pTab ); #ifndef SQLITE_OMIT_AUTHORIZATION /* Invoke the authorization callback. */ |
︙ | ︙ | |||
579 580 581 582 583 584 585 | goto exit_begin_add_column; } assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the | | > > > > | | 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 | goto exit_begin_add_column; } assert( pTab->addColOffset>0 ); iDb = sqlite3SchemaToIndex(db, pTab->pSchema); /* Put a copy of the Table struct in Parse.pNewTable for the ** sqlite3AddColumn() function and friends to modify. But modify ** the name by adding an "sqlite_altertab_" prefix. By adding this ** prefix, we insure that the name will not collide with an existing ** table because user table are not allowed to have the "sqlite_" ** prefix on their name. */ pNew = (Table*)sqlite3DbMallocZero(db, sizeof(Table)); if( !pNew ) goto exit_begin_add_column; pParse->pNewTable = pNew; pNew->nRef = 1; pNew->db = db; pNew->nCol = pTab->nCol; assert( pNew->nCol>0 ); nAlloc = (((pNew->nCol-1)/8)*8)+8; assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 ); pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc); pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName); if( !pNew->aCol || !pNew->zName ){ db->mallocFailed = 1; goto exit_begin_add_column; } memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol); for(i=0; i<pNew->nCol; i++){ Column *pCol = &pNew->aCol[i]; |
︙ | ︙ |
Changes to src/build.c.
︙ | ︙ | |||
18 19 20 21 22 23 24 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** | | | 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | ** CREATE INDEX ** DROP INDEX ** creating ID lists ** BEGIN TRANSACTION ** COMMIT ** ROLLBACK ** ** $Id: build.c,v 1.518 2009/02/13 03:43:32 drh Exp $ */ #include "sqliteInt.h" /* ** This routine is called when a new SQL statement is beginning to ** be parsed. Initialize the pParse structure as needed. */ |
︙ | ︙ | |||
361 362 363 364 365 366 367 | ** Remove the given index from the index hash table, and free ** its memory structures. ** ** The index is removed from the database hash tables but ** it is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ | | | 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 | ** Remove the given index from the index hash table, and free ** its memory structures. ** ** The index is removed from the database hash tables but ** it is not unlinked from the Table that it indexes. ** Unlinking from the Table must be done by the calling function. */ static void sqlite3DeleteIndex(Index *p){ Index *pOld; const char *zName = p->zName; pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, sqlite3Strlen30(zName)+1, 0); assert( pOld==0 || pOld==p ); freeIndex(p); |
︙ | ︙ | |||
521 522 523 524 525 526 527 | assert( pTable->nRef==0 ); /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->pSchema==pTable->pSchema ); | | | 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 | assert( pTable->nRef==0 ); /* Delete all indices associated with this table */ for(pIndex = pTable->pIndex; pIndex; pIndex=pNext){ pNext = pIndex->pNext; assert( pIndex->pSchema==pTable->pSchema ); sqlite3DeleteIndex(pIndex); } #ifndef SQLITE_OMIT_FOREIGN_KEY /* Delete all foreign keys associated with this table. The keys ** should have already been unlinked from the pSchema->aFKey hash table */ for(pFKey=pTable->pFKey; pFKey; pFKey=pNextFKey){ |
︙ | ︙ | |||
2424 2425 2426 2427 2428 2429 2430 | pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; if( pTab==0 || pParse->nErr ) goto exit_create_index; | | > | 2424 2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436 2437 2438 2439 | pTab = pParse->pNewTable; if( !pTab ) goto exit_create_index; iDb = sqlite3SchemaToIndex(db, pTab->pSchema); } pDb = &db->aDb[iDb]; if( pTab==0 || pParse->nErr ) goto exit_create_index; if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 && memcmp(&pTab->zName[7],"altertab_",9)!=0 ){ sqlite3ErrorMsg(pParse, "table %s may not be indexed", pTab->zName); goto exit_create_index; } #ifndef SQLITE_OMIT_VIEW if( pTab->pSelect ){ sqlite3ErrorMsg(pParse, "views may not be indexed"); goto exit_create_index; |
︙ | ︙ |
Changes to test/alter.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2004 November 10 # # 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 script is testing the ALTER TABLE statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2004 November 10 # # 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 script is testing the ALTER TABLE statement. # # $Id: alter.test,v 1.31 2009/02/13 03:43:32 drh Exp $ # set testdir [file dirname $argv0] source $testdir/tester.tcl # If SQLITE_OMIT_ALTERTABLE is defined, omit this file. ifcapable !altertable { |
︙ | ︙ | |||
806 807 808 809 810 811 812 813 814 | } {t3102a_rename t3102b t3102c} do_test alter-13.3 { execsql { ALTER TABLE t3102b RENAME TO t3102b_rename; SELECT name FROM sqlite_master WHERE name LIKE 't3102%' ORDER BY 1; } } {t3102a_rename t3102b_rename t3102c} finish_test | > > > > > > > > > > > > > > | 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | } {t3102a_rename t3102b t3102c} do_test alter-13.3 { execsql { ALTER TABLE t3102b RENAME TO t3102b_rename; SELECT name FROM sqlite_master WHERE name LIKE 't3102%' ORDER BY 1; } } {t3102a_rename t3102b_rename t3102c} # Ticket #3651 do_test alter-14.1 { catchsql { CREATE TABLE t3651(a UNIQUE); ALTER TABLE t3651 ADD COLUMN b UNIQUE; } } {1 {Cannot add a UNIQUE column}} do_test alter-14.2 { catchsql { ALTER TABLE t3651 ADD COLUMN b PRIMARY KEY; } } {1 {Cannot add a PRIMARY KEY column}} finish_test |