Improve ALTER TABLE DROP CONSTRAINT so that it is better able to deal

with some corner case in the constraint syntax.
Bugs [bugs:/info/2026-10-22T16:25:18Z|2026-10-22T16:25:18Z] and
[bugs:/info/2026-10-22T16:30:48Z|2026-10-22T16:30:48Z].

FossilOrigin-Name: 14d924c33ff11babef13e68f178c715bb8744a0134ee580715486b601d5738d8
This commit is contained in:
drh committed 2026-10-22 19:55:10 +00:00
1 parent bc766d966a
commit 7c2cb02205
5 files changed
+67 -17

No files matched your search

+8 -8
View File
@@ -1,5 +1,5 @@
C Merge\sbranch-3.54\sfixes\sinto\strunk
D 2026-10-22T11:41:16.140
C Improve\sALTER\sTABLE\sDROP\sCONSTRAINT\sso\sthat\sit\sis\sbetter\sable\sto\sdeal\nwith\ssome\scorner\scase\sin\sthe\sconstraint\ssyntax.\nBugs\s[bugs:/info/2026-10-22T16:25:18Z|2026-10-22T16:25:18Z]\sand\n[bugs:/info/2026-10-22T16:30:48Z|2026-10-22T16:30:48Z].
D 2026-10-22T19:55:10.157
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
@@ -740,7 +740,7 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
F src/alter.c 2dd9daa84c9395da33e92944af6bbc596dd46c01037f8fd613724ebf384e52dc
F src/alter.c d4d05d515b945309c1cc541bf343c37465329d5ed7a6f93231ca84622d747986
F src/analyze.c 73162482c656187823217f4c00758c9ee13a420c8745bc542129e0279b792287
F src/attach.c 40a83de1c720dfb3552458ebf6c9dac7ed6b2fcde4e073658fd9a38d90cb329e
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
@@ -910,9 +910,9 @@ F test/alter4.test f1b495928c12d818e96ef323162fc3a346b48b62f341764be61ad25fa017e
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
F test/altercons.test 575693a87b96e49eac2b8085cef71a95c7a94aab742d2334c66ca954d00aa9ce
F test/altercons.test 9a03043274fbe350db68a3a35c9236ce1eefc8be929ace2b210267580a3e6567
F test/altercons2.test 264c1cc31c16b319de423af9565eb7129d7e9f55b21bb4eda6fdae02841265ae
F test/altercons3.test d0bd7dde66a4a4f0b432b3ae3520e989b52b9bdfadddb9bd80be94554fecf803
F test/altercons3.test e95c18aba7050a48db97842e805edc267366b9bf9dc0db49c0e2b5c9a84bfe48
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
@@ -2297,8 +2297,8 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
P 03f699544e6b2040eda17e2f4b48813b10513fc05891a3dd4000867316413103 12285a3f4efdf41210fa3020127670b0d1fd8d740a5ac43db0c6641fec3e5142
R 7e43ea42358511ef205f08b515ae9978
P fdf339d965aba5e35feaf3ef613e2e2ce0795338591f261998141a6d080bb0da
R 4cf4f7463265cefb4651b6bc760f0580
U drh
Z 58fd7612be0ec62affd861745171369a
Z 29402b27137f74b18959508a58afc75f
# Remove this line to create a well-formed Fossil manifest.
+1 -1
View File
@@ -1 +1 @@
fdf339d965aba5e35feaf3ef613e2e2ce0795338591f261998141a6d080bb0da
14d924c33ff11babef13e68f178c715bb8744a0134ee580715486b601d5738d8
+40 -7
View File
@@ -2444,15 +2444,19 @@ static int getWhitespace(const u8 *z){
** keyword.
**
** Argument eTok may be the token value of the first token of the constraint
** (e.g. TK_CHECK or TK_REFERENCES) or zero. If it is either TK_REFERENCES
** or TK_FOREIGN, special parsing is enabled to find the end of the foreign-key
** constraint definition.
** (e.g. TK_CHECK or TK_REFERENCES or TK_NOT) or zero. If it is either
** TK_REFERENCES or TK_FOREIGN, special parsing is enabled to find the
** end of the foreign-key constraint definition. If eTok is TK_NOT then
** special processing is enabled to find the end of a NOT NULL constraint
** including its optional ON CONFLICT clause.
**
** Return the number of bytes until the end of the constraint.
*/
static int getConstraint(const u8 *z, int eTok){
int iOff = 0;
int t = 0;
int t2 = 0;
int prev = 0;
#ifndef SQLITE_OMIT_FOREIGN_KEY
if( eTok==TK_FOREIGN ){
@@ -2468,6 +2472,14 @@ static int getConstraint(const u8 *z, int eTok){
/* REFERENCES is followed by a table name. Gobble this up here in
** case the table name is a fallback token like TK_GENERATED. */
iOff += getConstraintToken(&z[iOff], &t);
/* If the table names is followed by a parenthesized list of columns,
** also skip that, lest the close ")" end the constraint in the
** while loop below. */
iOff += getWhitespace(&z[iOff]);
if( z[iOff]=='(' ){
iOff += getConstraintToken(&z[iOff], &t);
}
}
#endif
@@ -2478,17 +2490,34 @@ static int getConstraint(const u8 *z, int eTok){
** COLLATE, REFERENCES, FOREIGN, GENERATED, AS, RP, or COMMA
**
** Also exit the loop if ILLEGAL turns up.
**
** Exceptions:
**
** * For NOT NULL constraints, also terminate at DEFERRABLE
**
** * Do not terminate at DEFAULT if the previous token was SET
*/
while( 1 ){
int n = getConstraintToken(&z[iOff], &t);
if( t==TK_CONSTRAINT || t==TK_PRIMARY || t==TK_NOT || t==TK_UNIQUE
|| t==TK_CHECK || t==TK_DEFAULT || t==TK_COLLATE || t==TK_REFERENCES
if( t==TK_CONSTRAINT || t==TK_PRIMARY || t==TK_UNIQUE
|| t==TK_CHECK || t==TK_COLLATE || t==TK_REFERENCES
|| (t==TK_DEFAULT && prev!=TK_SET)
|| t==TK_FOREIGN || t==TK_RP || t==TK_COMMA || t==TK_ILLEGAL
|| t==TK_AS || t==TK_GENERATED
|| (eTok==TK_NOT && t==TK_DEFERRABLE)
){
break;
}
if( t==TK_NOT
&& (eTok!=TK_REFERENCES
|| (getConstraintToken(&z[iOff+n],&t2), t2!=TK_DEFERRABLE))
){
/* NOT ends the constraint unless eTok is TK_REFERENCES and the next
** token is DEFERRABLE */
break;
}
iOff += n;
prev = t;
}
return iOff;
@@ -2655,8 +2684,12 @@ static void dropConstraintFunc(
}
}else if( t==TK_NOT && iNotNull==ii ){
iEnd = iOff + getConstraint(&zSql[iOff], 0);
break;
int t2;
(void)getConstraintToken(zSql+iOff, &t2);
if( t2==TK_NULL ){
iEnd = iOff + getConstraint(zSql+iOff, TK_NOT);
break;
}
}else if( t==TK_RP || t==TK_ILLEGAL ){
iEnd = -1;
break;
+9
View File
@@ -156,6 +156,15 @@ foreach {tn col before after} {
11 b { CREATE TABLE t1(a, b NOT NULL GENERATED ALWAYS AS (a+1)) }
{ CREATE TABLE t1(a, b GENERATED ALWAYS AS (a+1)) }
12 b { CREATE TABLE t1(a, b REFERENCES t1(a) NOT DEFERRABLE NOT NULL) }
{ CREATE TABLE t1(a, b REFERENCES t1(a) NOT DEFERRABLE) }
13 b { CREATE TABLE t1(a, b REFERENCES t1(a) NOT NULL DEFERRABLE) }
{ CREATE TABLE t1(a, b REFERENCES t1(a) DEFERRABLE) }
14 b { CREATE TABLE t1(a, b REFERENCES t1(a) NOT NULL ON CONFLICT IGNORE DEFERRABLE) }
{ CREATE TABLE t1(a, b REFERENCES t1(a) DEFERRABLE) }
} {
reset_db
+9 -1
View File
@@ -72,6 +72,15 @@ foreach {tn before after} {
5 "CREATE TABLE c1(b, generated CONSTRAINT fk REFERENCES x1)"
"CREATE TABLE c1(b, generated)"
6 "CREATE TABLE c1(x CONSTRAINT fk REFERENCES p(a) ON DELETE SET DEFAULT\
ON UPDATE CASCADE, y)"
"CREATE TABLE c1(x, y)"
7 "CREATE TABLE c1(w REFERENCES p DEFERRABLE INITIALLY DEFERRED,\
x CONSTRAINT fk REFERENCES p NOT DEFERRABLE)"
"CREATE TABLE c1(w REFERENCES p DEFERRABLE INITIALLY DEFERRED, x)"
} {
do_execsql_test 4.$tn.1 { DROP TABLE IF EXISTS c1 }
do_execsql_test 4.$tn.2 $before
@@ -98,4 +107,3 @@ do_execsql_test 5.2 {
} {{CREATE TABLE x1(a, b }}
finish_test