Add experimental implementation of ALTER TABLE DROP COLUMN. Only some cases work so far.
FossilOrigin-Name: f0217937d7306fb595727e61e871e8b03d8c881d339a0865bfd0117d90d42e4e
This commit is contained in:
parent
33941691a5
commit
6e6d9833cc
24
manifest
24
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\san\sissue\swith\sthe\sLIKE\soperator\swhen\sit\sincludes\sthe\s"ESCAPE\s'_'"\sclause.\nTicket\s[c0aeea67d58ae0fd].
|
||||
D 2021-02-15T17:02:01.949
|
||||
C Add\sexperimental\simplementation\sof\sALTER\sTABLE\sDROP\sCOLUMN.\sOnly\ssome\scases\swork\sso\sfar.
|
||||
D 2021-02-16T20:43:36.239
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -475,7 +475,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786
|
||||
F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a
|
||||
F src/alter.c c4a973d7fc68f81fbc5d1d028a88ddb2cb212faef8c6f63433175b8d5ecd83dc
|
||||
F src/alter.c e912280eed81e2df936cc03af00a59abfcbfc24a27c3e5db8e8bd96022e2bf79
|
||||
F src/analyze.c 01c6c6765cb4d40b473b71d85535093730770bb186f2f473abac25f07fcdee5c
|
||||
F src/attach.c e80162a47411f296bea550ed8fafd730481f4aa71e89ece23ba9c957eed15d4a
|
||||
F src/auth.c 08954fdc4cc2da5264ba5b75cfd90b67a6fc7d1710a02ccf917c38eadec77853
|
||||
@ -530,7 +530,7 @@ F src/os_win.c 77d39873836f1831a9b0b91894fec45ab0e9ca8e067dc8c549e1d1eca1566fe9
|
||||
F src/os_win.h 7b073010f1451abe501be30d12f6bc599824944a
|
||||
F src/pager.c c49952ac5e9cc536778eff528091d79d38b3e45cbeeed4695dc05e207dc6547d
|
||||
F src/pager.h 4bf9b3213a4b2bebbced5eaa8b219cf25d4a82f385d093cd64b7e93e5285f66f
|
||||
F src/parse.y 67ba503780de64b967ae195b7e14c33531329228e1bc0b83d63324beb733680b
|
||||
F src/parse.y 8170885f22f4815c2adba3430ac7c990a39b60e04a0bcc4d02cce54e33475975
|
||||
F src/pcache.c 385ff064bca69789d199a98e2169445dc16e4291fa807babd61d4890c3b34177
|
||||
F src/pcache.h 4f87acd914cef5016fae3030343540d75f5b85a1877eed1a2a19b9f284248586
|
||||
F src/pcache1.c 6596e10baf3d8f84cc1585d226cf1ab26564a5f5caf85a15757a281ff977d51a
|
||||
@ -541,12 +541,12 @@ F src/printf.c 30e92b638fac71dcd85cdea1d12ecfae354c9adee2c71e8e1ae4727cde7c91ed
|
||||
F src/random.c 80f5d666f23feb3e6665a6ce04c7197212a88384
|
||||
F src/resolve.c 89e4faf6171e179edf279905e8e45c4f9dd108777dc60716396729fbd7cb045e
|
||||
F src/rowset.c ba9515a922af32abe1f7d39406b9d35730ed65efab9443dc5702693b60854c92
|
||||
F src/select.c 9b4c84fd2703ee3c8b5d4b189387482a84c26acf2c38ca4835db5b48c68a09d4
|
||||
F src/select.c 4bd3b7d21d0d58dfdb4134f71d0330915e962a036ae1e1c8cde2f7f8b45de7e9
|
||||
F src/shell.c.in 9ebc74e4f05cfbd0f4a36060fdaeff1da4e9af4458358722bc08c5a1ab9a0879
|
||||
F src/sqlite.h.in 8855a19f37ade8dad189a9e48233a2ebe1b46faf469c7eb0906a654e252dcc57
|
||||
F src/sqlite3.rc 5121c9e10c3964d5755191c80dd1180c122fc3a8
|
||||
F src/sqlite3ext.h 61b38c073d5e1e96a3d45271b257aef27d0d13da2bea5347692ae579475cd95e
|
||||
F src/sqliteInt.h 4cb469678a0dbf814e4efbde4488a0161a5398e9a63141830d9f676b4e9fb0cc
|
||||
F src/sqliteInt.h 514b41619e2c6b49188571df50249db2600ec33e4bfd1a6efb21f7e1c352f400
|
||||
F src/sqliteLimit.h d7323ffea5208c6af2734574bae933ca8ed2ab728083caa117c9738581a31657
|
||||
F src/status.c 4b8bc2a6905163a38b739854a35b826c737333fab5b1f8e03fa7eb9a4799c4c1
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@ -647,6 +647,7 @@ F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f0
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499
|
||||
F test/altercol.test 1d6a6fe698b81e626baea4881f5717f9bc53d7d07f1cd23ee7ad1b931f117ddf
|
||||
F test/alterdropcol.test 77539861deb0f1a04fb938f33984d7ccac8618337492611ac41dffea4b316863
|
||||
F test/alterlegacy.test 82022721ce0de29cedc9a7af63bc9fcc078b0ee000f8283b4b6ea9c3eab2f44b
|
||||
F test/altermalloc.test 167a47de41b5c638f5f5c6efb59784002b196fff70f98d9b4ed3cd74a3fb80c9
|
||||
F test/altermalloc2.test fa7b1c1139ea39b8dec407cf1feb032ca8e0076bd429574969b619175ad0174b
|
||||
@ -1900,7 +1901,10 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 7cc65ae57183b3c16f1102fca5603a36acda432e5d45e22a2996e5ebe069fc6a
|
||||
R 3ed1929e1ca13bbf9ff7ef7c6dc85f4d
|
||||
U drh
|
||||
Z b9fb1ccb5459387ee6a14bca5dee2b45
|
||||
P 27d4117980d125975b5e70eeea58a6ab07bcf066e71b5fcb81b822e05afdbab0
|
||||
R af9ecd1afb3809621548f4fa239dc0d6
|
||||
T *branch * alter-table-drop-column
|
||||
T *sym-alter-table-drop-column *
|
||||
T -sym-trunk *
|
||||
U dan
|
||||
Z e426edd9d98bb43cdac675b225a7f76a
|
||||
|
@ -1 +1 @@
|
||||
27d4117980d125975b5e70eeea58a6ab07bcf066e71b5fcb81b822e05afdbab0
|
||||
f0217937d7306fb595727e61e871e8b03d8c881d339a0865bfd0117d90d42e4e
|
207
src/alter.c
207
src/alter.c
@ -870,23 +870,33 @@ static void renameTokenFree(sqlite3 *db, RenameToken *pToken){
|
||||
|
||||
/*
|
||||
** Search the Parse object passed as the first argument for a RenameToken
|
||||
** object associated with parse tree element pPtr. If found, remove it
|
||||
** from the Parse object and add it to the list maintained by the
|
||||
** RenameCtx object passed as the second argument.
|
||||
** object associated with parse tree element pPtr. If found, return a pointer
|
||||
** to it. Otherwise, return NULL.
|
||||
**
|
||||
** If the second argument passed to this function is not NULL and a matching
|
||||
** RenameToken object is found, remove it from the Parse object and add it to
|
||||
** the list maintained by the RenameCtx object.
|
||||
*/
|
||||
static void renameTokenFind(Parse *pParse, struct RenameCtx *pCtx, void *pPtr){
|
||||
static RenameToken *renameTokenFind(
|
||||
Parse *pParse,
|
||||
struct RenameCtx *pCtx,
|
||||
void *pPtr
|
||||
){
|
||||
RenameToken **pp;
|
||||
assert( pPtr!=0 );
|
||||
for(pp=&pParse->pRename; (*pp); pp=&(*pp)->pNext){
|
||||
if( (*pp)->p==pPtr ){
|
||||
RenameToken *pToken = *pp;
|
||||
*pp = pToken->pNext;
|
||||
pToken->pNext = pCtx->pList;
|
||||
pCtx->pList = pToken;
|
||||
pCtx->nList++;
|
||||
break;
|
||||
if( pCtx ){
|
||||
*pp = pToken->pNext;
|
||||
pToken->pNext = pCtx->pList;
|
||||
pCtx->pList = pToken;
|
||||
pCtx->nList++;
|
||||
}
|
||||
return pToken;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1751,14 +1761,187 @@ static void renameTableTest(
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
** Arguments:
|
||||
**
|
||||
** argv[0]: An integer - the index of the schema containing the table
|
||||
** argv[1]: CREATE TABLE statement to modify.
|
||||
** argv[2]: An integer - the index of the column to remove.
|
||||
** argv[3]: Byte offset of first byte after last column definition in argv[1]
|
||||
*/
|
||||
static void dropColumnFunc(
|
||||
sqlite3_context *context,
|
||||
int NotUsed,
|
||||
sqlite3_value **argv
|
||||
){
|
||||
sqlite3 *db = sqlite3_context_db_handle(context);
|
||||
int iSchema = sqlite3_value_int(argv[0]);
|
||||
const char *zSql = (const char*)sqlite3_value_text(argv[1]);
|
||||
int iCol = sqlite3_value_int(argv[2]);
|
||||
int iAddColOffset = sqlite3_value_int(argv[3]);
|
||||
const char *zDb = db->aDb[iSchema].zDbSName;
|
||||
int rc;
|
||||
Parse sParse;
|
||||
RenameToken *pCol;
|
||||
Table *pTab;
|
||||
const char *zEnd;
|
||||
char *zNew = 0;
|
||||
|
||||
rc = renameParseSql(&sParse, zDb, db, zSql, iSchema==1);
|
||||
if( rc!=SQLITE_OK ) goto drop_column_done;
|
||||
pTab = sParse.pNewTable;
|
||||
|
||||
pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zName);
|
||||
if( iCol<pTab->nCol-1 ){
|
||||
RenameToken *pEnd;
|
||||
pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zName);
|
||||
zEnd = (const char*)pEnd->t.z;
|
||||
}else{
|
||||
zEnd = (const char*)&zSql[iAddColOffset];
|
||||
while( pCol->t.z[0]!=',' && pCol->t.z[1]!='(' ) pCol->t.z--;
|
||||
}
|
||||
|
||||
zNew = sqlite3_mprintf("%.*s%s", pCol->t.z-zSql, zSql, zEnd);
|
||||
sqlite3_result_text(context, zNew, -1, SQLITE_TRANSIENT);
|
||||
sqlite3_free(zNew);
|
||||
|
||||
drop_column_done:
|
||||
renameParseCleanup(&sParse);
|
||||
}
|
||||
|
||||
void sqlite3AlterDropColumn(Parse *pParse, SrcList *pSrc, Token *pName){
|
||||
Table *pTab;
|
||||
int i;
|
||||
int iSchema = 0;
|
||||
const char *zDb = 0;
|
||||
sqlite3 *db = pParse->db;
|
||||
char *zCol = 0;
|
||||
int iCol = 0;
|
||||
Vdbe *v;
|
||||
int iCur;
|
||||
int addr;
|
||||
int reg;
|
||||
int regRec;
|
||||
Index *pIdx;
|
||||
Index *pPk = 0;
|
||||
|
||||
/* Look up the table being altered. */
|
||||
assert( pParse->pNewTable==0 );
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
if( db->mallocFailed ) goto exit_drop_column;
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
||||
if( !pTab ) goto exit_drop_column;
|
||||
|
||||
/* Which schema holds the table to be altered */
|
||||
iSchema = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iSchema>=0 );
|
||||
zDb = db->aDb[iSchema].zDbSName;
|
||||
|
||||
#ifndef SQLITE_OMIT_VIRTUALTABLE
|
||||
if( IsVirtual(pTab) ){
|
||||
sqlite3ErrorMsg(pParse, "virtual tables may not be altered");
|
||||
goto exit_drop_column;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Make sure this is not an attempt to ALTER a view. */
|
||||
if( pTab->pSelect ){
|
||||
sqlite3ErrorMsg(pParse, "cannot drop a column from a view");
|
||||
goto exit_drop_column;
|
||||
}
|
||||
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ){
|
||||
goto exit_drop_column;
|
||||
}
|
||||
|
||||
/* Find the index of the column being dropped. */
|
||||
zCol = sqlite3NameFromToken(db, pName);
|
||||
if( zCol==0 ){
|
||||
assert( db->mallocFailed );
|
||||
goto exit_drop_column;
|
||||
}
|
||||
iCol = sqlite3ColumnIndex(pTab, zCol);
|
||||
if( iCol<0 ){
|
||||
sqlite3ErrorMsg(pParse, "no such column: \"%s\"", zCol);
|
||||
goto exit_drop_column;
|
||||
}
|
||||
|
||||
/* Do not allow the user to drop a PRIMARY KEY column or a column
|
||||
** constrained by a UNIQUE constraint. */
|
||||
if( pTab->iPKey==iCol ){
|
||||
sqlite3ErrorMsg(pParse, "cannot drop PRIMARY KEY column: \"%s\"", zCol);
|
||||
goto exit_drop_column;
|
||||
}
|
||||
for(pIdx=pTab->pIndex; pIdx; pIdx=pIdx->pNext){
|
||||
int ii;
|
||||
for(ii=0; ii<pIdx->nKeyCol; ii++){
|
||||
if( iCol==pIdx->aiColumn[ii]
|
||||
&& sqlite3_strnicmp("sqlite_", pIdx->zName, 7)==0
|
||||
){
|
||||
sqlite3ErrorMsg(pParse, "cannot drop %s column: \"%s\"",
|
||||
pIdx->idxType==2 ? "PRIMARY KEY" : "UNIQUE", zCol
|
||||
);
|
||||
goto exit_drop_column;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sqlite3NestedParse(pParse,
|
||||
"UPDATE \"%w\"." DFLT_SCHEMA_TABLE " SET "
|
||||
"sql = sqlite_drop_column(%d, sql, %d, %d) "
|
||||
"WHERE (type=='table' AND tbl_name=%Q COLLATE nocase)"
|
||||
, zDb, iSchema, iCol, pTab->addColOffset, pTab->zName
|
||||
);
|
||||
|
||||
/* Drop and reload the database schema. */
|
||||
renameReloadSchema(pParse, iSchema);
|
||||
renameTestSchema(pParse, zDb, iSchema==1);
|
||||
|
||||
/* Edit rows of table on disk */
|
||||
v = sqlite3GetVdbe(pParse);
|
||||
iCur = pParse->nTab++;
|
||||
sqlite3OpenTable(pParse, iCur, iSchema, pTab, OP_OpenWrite);
|
||||
addr = sqlite3VdbeAddOp1(v, OP_Rewind, iCur);
|
||||
reg = ++pParse->nMem;
|
||||
pParse->nMem += pTab->nCol;
|
||||
if( HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp2(v, OP_Rowid, iCur, reg);
|
||||
}else{
|
||||
pPk = sqlite3PrimaryKeyIndex(pTab);
|
||||
}
|
||||
for(i=0; i<pTab->nCol; i++){
|
||||
if( i!=iCol ){
|
||||
int iPos = (pPk ? sqlite3TableColumnToIndex(pPk, i) : i);
|
||||
int iColPos = (pPk ? sqlite3TableColumnToIndex(pPk, iCol) : iCol);
|
||||
int regOut = reg+1+iPos-(iPos>iColPos);
|
||||
sqlite3ExprCodeGetColumnOfTable(v, pTab, iCur, i, regOut);
|
||||
}
|
||||
}
|
||||
regRec = reg + pTab->nCol;
|
||||
sqlite3VdbeAddOp3(v, OP_MakeRecord, reg+1, pTab->nCol-1, regRec);
|
||||
if( HasRowid(pTab) ){
|
||||
sqlite3VdbeAddOp3(v, OP_Insert, iCur, regRec, reg);
|
||||
}else{
|
||||
sqlite3VdbeAddOp4Int(v, OP_IdxInsert, iCur, regRec, reg+1, pPk->nKeyCol);
|
||||
}
|
||||
|
||||
sqlite3VdbeAddOp2(v, OP_Next, iCur, addr+1);
|
||||
sqlite3VdbeJumpHere(v, addr);
|
||||
|
||||
exit_drop_column:
|
||||
sqlite3DbFree(db, zCol);
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
** Register built-in functions used to help implement ALTER TABLE
|
||||
*/
|
||||
void sqlite3AlterFunctions(void){
|
||||
static FuncDef aAlterTableFuncs[] = {
|
||||
INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
|
||||
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
|
||||
INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
|
||||
INTERNAL_FUNCTION(sqlite_rename_column, 9, renameColumnFunc),
|
||||
INTERNAL_FUNCTION(sqlite_rename_table, 7, renameTableFunc),
|
||||
INTERNAL_FUNCTION(sqlite_rename_test, 5, renameTableTest),
|
||||
INTERNAL_FUNCTION(sqlite_drop_column, 4, dropColumnFunc),
|
||||
};
|
||||
sqlite3InsertBuiltinFuncs(aAlterTableFuncs, ArraySize(aAlterTableFuncs));
|
||||
}
|
||||
|
@ -1621,6 +1621,10 @@ cmd ::= ALTER TABLE add_column_fullname
|
||||
Y.n = (int)(pParse->sLastToken.z-Y.z) + pParse->sLastToken.n;
|
||||
sqlite3AlterFinishAddColumn(pParse, &Y);
|
||||
}
|
||||
cmd ::= ALTER TABLE fullname(X) DROP COLUMNKW nm(Y). {
|
||||
sqlite3AlterDropColumn(pParse, X, &Y);
|
||||
}
|
||||
|
||||
add_column_fullname ::= fullname(X). {
|
||||
disableLookaside(pParse);
|
||||
sqlite3AlterBeginAddColumn(pParse, X);
|
||||
|
@ -262,7 +262,7 @@ int sqlite3JoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){
|
||||
** Return the index of a column in a table. Return -1 if the column
|
||||
** is not contained in the table.
|
||||
*/
|
||||
static int columnIndex(Table *pTab, const char *zCol){
|
||||
int sqlite3ColumnIndex(Table *pTab, const char *zCol){
|
||||
int i;
|
||||
u8 h = sqlite3StrIHash(zCol);
|
||||
Column *pCol;
|
||||
@ -294,7 +294,7 @@ static int tableAndColumnIndex(
|
||||
|
||||
assert( (piTab==0)==(piCol==0) ); /* Both or neither are NULL */
|
||||
for(i=0; i<N; i++){
|
||||
iCol = columnIndex(pSrc->a[i].pTab, zCol);
|
||||
iCol = sqlite3ColumnIndex(pSrc->a[i].pTab, zCol);
|
||||
if( iCol>=0
|
||||
&& (bIgnoreHidden==0 || IsHiddenColumn(&pSrc->a[i].pTab->aCol[iCol])==0)
|
||||
){
|
||||
@ -504,7 +504,7 @@ static int sqliteProcessJoin(Parse *pParse, Select *p){
|
||||
int iRightCol; /* Column number of matching column on the right */
|
||||
|
||||
zName = pList->a[j].zName;
|
||||
iRightCol = columnIndex(pRightTab, zName);
|
||||
iRightCol = sqlite3ColumnIndex(pRightTab, zName);
|
||||
if( iRightCol<0
|
||||
|| !tableAndColumnIndex(pSrc, i+1, zName, &iLeft, &iLeftCol, 0)
|
||||
){
|
||||
|
@ -4531,6 +4531,7 @@ void sqlite3MaterializeView(Parse*, Table*, Expr*, ExprList*,Expr*,int);
|
||||
#endif
|
||||
|
||||
int sqlite3JoinType(Parse*, Token*, Token*, Token*);
|
||||
int sqlite3ColumnIndex(Table *pTab, const char *zCol);
|
||||
void sqlite3SetJoinExpr(Expr*,int);
|
||||
void sqlite3CreateForeignKey(Parse*, ExprList*, Token*, ExprList*, int);
|
||||
void sqlite3DeferForeignKey(Parse*, int);
|
||||
@ -4715,6 +4716,7 @@ int sqlite3ResolveOrderGroupBy(Parse*, Select*, ExprList*, const char*);
|
||||
void sqlite3ColumnDefault(Vdbe *, Table *, int, int);
|
||||
void sqlite3AlterFinishAddColumn(Parse *, Token *);
|
||||
void sqlite3AlterBeginAddColumn(Parse *, SrcList *);
|
||||
void sqlite3AlterDropColumn(Parse*, SrcList*, Token*);
|
||||
void *sqlite3RenameTokenMap(Parse*, void*, Token*);
|
||||
void sqlite3RenameTokenRemap(Parse*, void *pTo, void *pFrom);
|
||||
void sqlite3RenameExprUnmap(Parse*, Expr*);
|
||||
|
113
test/alterdropcol.test
Normal file
113
test/alterdropcol.test
Normal file
@ -0,0 +1,113 @@
|
||||
# 2021 February 16
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
#*************************************************************************
|
||||
#
|
||||
|
||||
set testdir [file dirname $argv0]
|
||||
source $testdir/tester.tcl
|
||||
set testprefix alterdropcol
|
||||
|
||||
# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
|
||||
ifcapable !altertable {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a, b, c);
|
||||
CREATE VIEW v1 AS SELECT * FROM t1;
|
||||
|
||||
CREATE TABLE t2(x INTEGER PRIMARY KEY, y, z UNIQUE);
|
||||
CREATE INDEX t2y ON t2(y);
|
||||
}
|
||||
|
||||
do_catchsql_test 1.1 {
|
||||
ALTER TABLE nosuch DROP COLUMN z;
|
||||
} {1 {no such table: nosuch}}
|
||||
|
||||
do_catchsql_test 1.2 {
|
||||
ALTER TABLE v1 DROP COLUMN c;
|
||||
} {1 {cannot drop a column from a view}}
|
||||
|
||||
ifcapable fts5 {
|
||||
do_execsql_test 1.3.1 {
|
||||
CREATE VIRTUAL TABLE ft1 USING fts5(one, two);
|
||||
}
|
||||
do_catchsql_test 1.3.2 {
|
||||
ALTER TABLE ft1 DROP COLUMN two;
|
||||
} {1 {virtual tables may not be altered}}
|
||||
}
|
||||
|
||||
do_catchsql_test 1.4 {
|
||||
ALTER TABLE sqlite_schema DROP COLUMN sql;
|
||||
} {1 {table sqlite_master may not be altered}}
|
||||
|
||||
do_catchsql_test 1.5 {
|
||||
ALTER TABLE t1 DROP COLUMN d;
|
||||
} {1 {no such column: "d"}}
|
||||
|
||||
do_execsql_test 1.6.1 {
|
||||
ALTER TABLE t1 DROP COLUMN b;
|
||||
}
|
||||
do_execsql_test 1.6.2 {
|
||||
SELECT sql FROM sqlite_schema WHERE name = 't1'
|
||||
} {{CREATE TABLE t1(a, c)}}
|
||||
|
||||
do_execsql_test 1.7.1 {
|
||||
ALTER TABLE t1 DROP COLUMN c;
|
||||
}
|
||||
do_execsql_test 1.7.2 {
|
||||
SELECT sql FROM sqlite_schema WHERE name = 't1'
|
||||
} {{CREATE TABLE t1(a)}}
|
||||
|
||||
|
||||
do_catchsql_test 1.8 {
|
||||
ALTER TABLE t2 DROP COLUMN z
|
||||
} {1 {cannot drop UNIQUE column: "z"}}
|
||||
|
||||
do_catchsql_test 1.9 {
|
||||
ALTER TABLE t2 DROP COLUMN x
|
||||
} {1 {cannot drop PRIMARY KEY column: "x"}}
|
||||
|
||||
do_catchsql_test 1.10 {
|
||||
ALTER TABLE t2 DROP COLUMN y
|
||||
} {1 {cannot drop indexed column: "y"}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
|
||||
foreach {tn wo} {
|
||||
1 {}
|
||||
2 {WITHOUT ROWID}
|
||||
} { eval [string map [list %TN% $tn %WO% $wo] {
|
||||
|
||||
reset_db
|
||||
do_execsql_test 2.%TN%.0 {
|
||||
CREATE TABLE t1(x, y INTEGER PRIMARY KEY, z) %WO% ;
|
||||
INSERT INTO t1 VALUES(1, 2, 3);
|
||||
INSERT INTO t1 VALUES(4, 5, 6);
|
||||
INSERT INTO t1 VALUES(7, 8, 9);
|
||||
}
|
||||
|
||||
do_execsql_test 2.%TN%.1 {
|
||||
ALTER TABLE t1 DROP COLUMN x;
|
||||
SELECT * FROM t1;
|
||||
} {
|
||||
2 3 5 6 8 9
|
||||
}
|
||||
do_execsql_test 2.%TN%.2 {
|
||||
ALTER TABLE t1 DROP COLUMN z;
|
||||
SELECT * FROM t1;
|
||||
} {
|
||||
2 5 8
|
||||
}
|
||||
}]}
|
||||
|
||||
finish_test
|
||||
|
Loading…
x
Reference in New Issue
Block a user