From: drh Date: Fri, 8 May 2020 19:02:21 +0000 (+0000) Subject: Release some restrictions on columns added by ALTER TABLE so that they X-Git-Tag: version-3.32.0~33 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9e5fdc41c1f46f92776ede52359900b41b2e3a82;p=thirdparty%2Fsqlite.git Release some restrictions on columns added by ALTER TABLE so that they only apply if the table contains one or more rows. FossilOrigin-Name: 3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff --- diff --git a/manifest b/manifest index f775a4fca0..07b0207e1c 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Fix\sthe\scount-optimization\sso\sthat\sit\shonors\sthe\sNOT\sINDEXED\sclause. -D 2020-05-08T18:22:00.148 +C Release\ssome\srestrictions\son\scolumns\sadded\sby\sALTER\sTABLE\sso\sthat\sthey\nonly\sapply\sif\sthe\stable\scontains\sone\sor\smore\srows. +D 2020-05-08T19:02:21.347 F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724 @@ -467,7 +467,7 @@ F spec.template 86a4a43b99ebb3e75e6b9a735d5fd293a24e90ca F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 fc7ad8990fc8409983309bb80de8c811a7506786 F sqlite3.pc.in 48fed132e7cb71ab676105d2a4dc77127d8c1f3a -F src/alter.c fa2c3be9b0ebecfafb7062072a0ae6eda126d3e5a9fd51b2eded5acd95dc783c +F src/alter.c 8d8e0b512a684596b3cf7026a92328575be5cefc7d0163e27a1fd179ad484512 F src/analyze.c 953a6c43870ccaf080597244e1eeb4dc2ff6cb84f9501b24e46323de36970b61 F src/attach.c ff2daea0fe62080192e3f262670e4f61f5a86c1e7bea9cec34e960fe79852aa1 F src/auth.c a3d5bfdba83d25abed1013a8c7a5f204e2e29b0c25242a56bc02bb0c07bf1e06 @@ -477,7 +477,7 @@ F src/btmutex.c 8acc2f464ee76324bf13310df5692a262b801808984c1b79defb2503bbafadb6 F src/btree.c f14e415fcfd0b52b4e4ebd193ba5fadac5e8252c30f023389af682813af44025 F src/btree.h 989ef3c33413549e3e148f3dcb46c030f317dac130dc86809ba6b9aa4b16c72a F src/btreeInt.h 5c8b8749805787313ecf49eb5be3ced1e94bbf8ef54bb01470ce6bd0d5185c67 -F src/build.c 5566b570435d3511a0fd57388c124491b1f74e59561f0c1679fabe74c4c54b7a +F src/build.c 5d19ef52be003d02e072dfc2892d7e107d20caf9ca49506937563de5c8d91141 F src/callback.c d0b853dd413255d2e337b34545e54d888ea02f20da5ad0e63585b389624c4a6c F src/complete.c a3634ab1e687055cd002e11b8f43eb75c17da23e F src/ctime.c e98518d2d3d4029a13c805e07313fb60c877be56db76e90dd5f3af73085d0ce6 @@ -485,7 +485,7 @@ F src/date.c b29b349d277e3d579dcc295b24c0a2caed83fd8f090a9f7cbe6070c0fd662384 F src/dbpage.c 8a01e865bf8bc6d7b1844b4314443a6436c07c3efe1d488ed89e81719047833a F src/dbstat.c 793deaf88a0904f88285d93d6713c636d55ede0ffd9f08d10f4ea825531d367f F src/delete.c 88047c8e59878c920fce14582bc1dde4d81157d1ca5ffdf36c2907e6d41996c4 -F src/expr.c d1e1d42cbdec08bb867a1ab43a59b401d82ff2bc88bdcb4af20e479a5facb6d8 +F src/expr.c 2918cac044a96d534d2f51bd121e913afda57314b8c5b00eb6bc1cf8999a7dea F src/fault.c 460f3e55994363812d9d60844b2a6de88826e007 F src/fkey.c 4b575423b0a5d4898b1a7868ce985cf1a8ad91c741c9abbb108ff02536d20f41 F src/func.c f3dcdc0e95509864767c1f0991b19360f969e44177f4e058fd51da9a6154f47e @@ -632,10 +632,10 @@ F test/aggerror.test a867e273ef9e3d7919f03ef4f0e8c0d2767944f2 F test/aggnested.test 12106f0748e8e9bfc1a8e6840e203e051eae06a26ed13fc9fd5db108a8d6db54 F test/alias.test 4529fbc152f190268a15f9384a5651bbbabc9d87 F test/all.test 2ecb8bbd52416642e41c9081182a8df05d42c75637afd4488aace78cc4b69e13 -F test/alter.test 77f0092d137dd9470fc683b64ed92868e188462e713e52f48deae8902ea60b96 +F test/alter.test 25e109787dc5e631e117eb6e1c57f96a572bb51228db3b4f8b5f41d665e2ccaa F test/alter2.test a966ccfcddf9ce0a4e0e6ff1aca9e6e7948e0e242cd7e43fc091948521807687 -F test/alter3.test 9351a9f0c59ff9dddecccaaa2f777ffee5369870c63d30d3a74add815254ec0f -F test/alter4.test 74b22251c5e9c48093cfc4921ed9c11b59df84634aeeb00e501773320beb8424 +F test/alter3.test e487958dec7932453e0b83baf21d6b1e71d5e7d9a55bc20eadfa62a51ddffc29 +F test/alter4.test dfd6086faf461b27ca2d2999848dcd207edf23352fc1592d0005c0844f3f08cf F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959 F test/alterauth2.test c0a1ddf5b93d93cb0d15ba7acaf0c5c6fb515bbe861ede75b2d3fabad33b6499 F test/altercol.test 1d6a6fe698b81e626baea4881f5717f9bc53d7d07f1cd23ee7ad1b931f117ddf @@ -875,7 +875,7 @@ F test/filter2.tcl 44e525497ce07382915f01bd29ffd0fa49dab3adb87253b5e5103ba8f9339 F test/filter2.test 485cf95d1f6d6ceee5632201ca52a71868599836f430cdee42e5f7f14666e30a F test/filterfault.test c08fb491d698e8df6c122c98f7db1c65ffcfcad2c1ab0e07fa8a5be1b34eaa8b F test/fkey1.test d11dbb8a93ead9b5c46ae5d02da016d61245d47662fb2d844c99214f6163f768 -F test/fkey2.test 65c86b11127c11f80c0f450b3480321e0f087edea3031b9daa1978e3c020c91b +F test/fkey2.test b1b6a8c5556dc0ccf31291b1fed8aa57e404b38f3236110e19ab4dc6aa93edf2 F test/fkey3.test 76d475c80b84ee7a5d062e56ccb6ea68882e2b49 F test/fkey4.test 86446017011273aad8f9a99c1a65019e7bd9ca9d F test/fkey5.test 24dd28eb3d9f1b5a174f47e9899ace5facb08373a4223593c8c631e6cf9f7d5a @@ -1751,7 +1751,7 @@ F test/with4.test 257be66c0c67fee1defbbac0f685c3465e2cad037f21ce65f23f86084f1982 F test/withM.test 693b61765f2b387b5e3e24a4536e2e82de15ff64 F test/without_rowid1.test 9cfb83705c506e3849fa7efc88a3c9a15f9a50bf9b1516b41757a7cef9bba8c3 F test/without_rowid2.test af260339f79d13cb220288b67cd287fbcf81ad99 -F test/without_rowid3.test 392e6e12f275d11d931a8bc4580e573342f391639c87ffb631010a7b3cedfdc0 +F test/without_rowid3.test f8e6b9f7cb32a3570bab743dd4f28d2000e2107808d57585e776f5c3eb076241 F test/without_rowid4.test 4e08bcbaee0399f35d58b5581881e7a6243d458a F test/without_rowid5.test 89b1c587bd92a0590e440da33e7666bf4891572a F test/without_rowid6.test 8463b20098e9f75a501a9f17dfb42fffc79068eac0b2775fe56ef2281d2df45e @@ -1864,7 +1864,7 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93 F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0 -P 3fce9711a47329811cd333ae2f1d1384a96d73b9a5d6f9d08454a57a3fd24fc8 -R 8578e4a65d9ea9285aa73605ccc6eef5 +P 0d23a0b209900f4d7c6c13f75d4364f19afc23db72f9cfdb11e05b81502e8040 +R b78535f970f25edde428ed2df290db8d U drh -Z e8a05b1abf68598bded8ccc3e45f3579 +Z 5bccd85159fe501fed38247765ad943e diff --git a/manifest.uuid b/manifest.uuid index 12e9064883..b26a0cf61a 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -0d23a0b209900f4d7c6c13f75d4364f19afc23db72f9cfdb11e05b81502e8040 \ No newline at end of file +3a16c0ce4d8851f79f670d94786032c8007619154ece44647dc9cc5b1f9654ff \ No newline at end of file diff --git a/src/alter.c b/src/alter.c index c357f22074..e5bac436a8 100644 --- a/src/alter.c +++ b/src/alter.c @@ -255,6 +255,22 @@ exit_rename_table: db->mDbFlags = savedDbFlags; } +/* +** Write code that will raise an error if the table described by +** zDb and zTab is not empty. +*/ +static void sqlite3ErrorIfNotEmpty( + Parse *pParse, /* Parsing context */ + const char *zDb, /* Schema holding the table */ + const char *zTab, /* Table to check for empty */ + const char *zErr /* Error message text */ +){ + sqlite3NestedParse(pParse, + "SELECT raise(ABORT,%Q) FROM \"%w\".\"%w\"", + zErr, zDb, zTab + ); +} + /* ** This function is called after an "ALTER TABLE ... ADD" statement ** has been parsed. Argument pColDef contains the text of the new @@ -307,7 +323,8 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ return; } if( pNew->pIndex ){ - sqlite3ErrorMsg(pParse, "Cannot add a UNIQUE column"); + sqlite3ErrorMsg(pParse, + "Cannot add a UNIQUE column"); return; } if( (pCol->colFlags & COLFLAG_GENERATED)==0 ){ @@ -320,16 +337,15 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ pDflt = 0; } if( (db->flags&SQLITE_ForeignKeys) && pNew->pFKey && pDflt ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "Cannot add a REFERENCES column with non-NULL default value"); - return; } if( pCol->notNull && !pDflt ){ - sqlite3ErrorMsg(pParse, + sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "Cannot add a NOT NULL column with default value NULL"); - return; } + /* Ensure the default expression is something that sqlite3ValueFromExpr() ** can handle (i.e. not CURRENT_TIME etc.) */ @@ -343,14 +359,13 @@ void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){ return; } if( !pVal ){ - sqlite3ErrorMsg(pParse,"Cannot add a column with non-constant default"); - return; + sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, + "Cannot add a column with non-constant default"); } sqlite3ValueFree(pVal); } }else if( pCol->colFlags & COLFLAG_STORED ){ - sqlite3ErrorMsg(pParse, "cannot add a STORED column"); - return; + sqlite3ErrorIfNotEmpty(pParse, zDb, zTab, "cannot add a STORED column"); } diff --git a/src/build.c b/src/build.c index 0b47e8e774..571d2652e0 100644 --- a/src/build.c +++ b/src/build.c @@ -4741,7 +4741,7 @@ void sqlite3HaltConstraint( u8 p5Errmsg /* P5_ErrMsg type */ ){ Vdbe *v = sqlite3GetVdbe(pParse); - assert( (errCode&0xff)==SQLITE_CONSTRAINT ); + assert( (errCode&0xff)==SQLITE_CONSTRAINT || pParse->nested ); if( onError==OE_Abort ){ sqlite3MayAbort(pParse); } diff --git a/src/expr.c b/src/expr.c index 23e00db2ee..528377c5d6 100644 --- a/src/expr.c +++ b/src/expr.c @@ -4482,7 +4482,7 @@ expr_code_doover: || pExpr->affExpr==OE_Fail || pExpr->affExpr==OE_Ignore ); - if( !pParse->pTriggerTab ){ + if( !pParse->pTriggerTab && !pParse->nested ){ sqlite3ErrorMsg(pParse, "RAISE() may only be used within a trigger-program"); return 0; @@ -4496,8 +4496,9 @@ expr_code_doover: v, OP_Halt, SQLITE_OK, OE_Ignore, 0, pExpr->u.zToken,0); VdbeCoverage(v); }else{ - sqlite3HaltConstraint(pParse, SQLITE_CONSTRAINT_TRIGGER, - pExpr->affExpr, pExpr->u.zToken, 0, 0); + sqlite3HaltConstraint(pParse, + pParse->pTriggerTab ? SQLITE_CONSTRAINT_TRIGGER : SQLITE_ERROR, + pExpr->affExpr, pExpr->u.zToken, 0, 0); } break; diff --git a/test/alter.test b/test/alter.test index 0ec485ef81..43d2a6d5ae 100644 --- a/test/alter.test +++ b/test/alter.test @@ -840,6 +840,7 @@ do_test alter-13.3 { do_test alter-14.1 { catchsql { CREATE TABLE t3651(a UNIQUE); + INSERT INTO t3651 VALUES(5); ALTER TABLE t3651 ADD COLUMN b UNIQUE; } } {1 {Cannot add a UNIQUE column}} diff --git a/test/alter3.test b/test/alter3.test index b16a7f305b..30bc1cbba2 100644 --- a/test/alter3.test +++ b/test/alter3.test @@ -116,6 +116,7 @@ do_test alter3-1.99 { do_test alter3-2.1 { execsql { CREATE TABLE t1(a, b); + INSERT INTO t1 VALUES(1,2); } catchsql { ALTER TABLE t1 ADD c PRIMARY KEY; diff --git a/test/alter4.test b/test/alter4.test index 92f33e7a36..3aca7df338 100644 --- a/test/alter4.test +++ b/test/alter4.test @@ -123,6 +123,7 @@ do_test alter4-1.99 { do_test alter4-2.1 { execsql { CREATE TABLE temp.t1(a, b); + INSERT INTO t1 VALUES(1,2); } catchsql { ALTER TABLE t1 ADD c PRIMARY KEY; @@ -397,6 +398,7 @@ do_test alter4-10.1 { reset_db do_execsql_test alter4-11.0 { CREATE TABLE t1(c INTEGER PRIMARY KEY, d); + INSERT INTO t1(c,d) VALUES(1,2); PRAGMA foreign_keys = on; ALTER TABLE t1 ADD COLUMN e; } diff --git a/test/fkey2.test b/test/fkey2.test index e7fa7b6457..015c43cbd3 100644 --- a/test/fkey2.test +++ b/test/fkey2.test @@ -955,6 +955,7 @@ ifcapable altertable { execsql { CREATE TABLE t1(a PRIMARY KEY); CREATE TABLE t2(a, b); + INSERT INTO t2 VALUES(1,2); } catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } } {0 {}} @@ -1046,6 +1047,7 @@ ifcapable altertable { execsql { CREATE TEMP TABLE t1(a PRIMARY KEY); CREATE TEMP TABLE t2(a, b); + INSERT INTO temp.t2 VALUES(1,2); } catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } } {0 {}} @@ -1130,6 +1132,7 @@ ifcapable altertable { ATTACH ':memory:' AS aux; CREATE TABLE aux.t1(a PRIMARY KEY); CREATE TABLE aux.t2(a, b); + INSERT INTO aux.t2(a,b) VALUES(1,2); } catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } } {0 {}} diff --git a/test/without_rowid3.test b/test/without_rowid3.test index 24ef2304de..a9839e147e 100644 --- a/test/without_rowid3.test +++ b/test/without_rowid3.test @@ -921,6 +921,7 @@ ifcapable altertable { execsql { CREATE TABLE t1(a PRIMARY KEY) WITHOUT rowid; CREATE TABLE t2(a, b); + INSERT INTO t2(a,b) VALUES(1,2); } catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } } {0 {}} @@ -1015,6 +1016,7 @@ ifcapable altertable { execsql { CREATE TEMP TABLE t1(a PRIMARY KEY) WITHOUT rowid; CREATE TEMP TABLE t2(a, b); + INSERT INTO temp.t2(a,b) VALUES(1,2); } catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } } {0 {}} @@ -1102,6 +1104,7 @@ ifcapable altertable { ATTACH ':memory:' AS aux; CREATE TABLE aux.t1(a PRIMARY KEY) WITHOUT rowid; CREATE TABLE aux.t2(a, b); + INSERT INTO aux.t2(a,b) VALUES(1,2); } catchsql { ALTER TABLE t2 ADD COLUMN c REFERENCES t1 } } {0 {}}