-C For\sdisplay\smodes\sin\sthe\sCLI\sfor\swhich\scolumn\sheaders\sare\senabled,\nmake\sthe\smode\s"always"\sinstead\sof\s"on.\s\sImproved\scomments\sand\stest\ncases.
-D 2026-07-08T15:43:42.959
+C Allow\s"ALTER\sTABLE\s...\sDROP\sCONSTRAINT"\sto\sdrop\sforeign\skey\sconstraints.
+D 2026-07-08T17:40:04.496
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
-F src/alter.c da59ac700b52ba5d0e4dd099fb1818975cf8a79a546594da586b4e1eba3ae405
+F src/alter.c 0c6e7f9d2ddd1ee55e5e9dd903ea00a13ba728b7be2fbbaa2e83725dafdadbd9
F src/analyze.c 73162482c656187823217f4c00758c9ee13a420c8745bc542129e0279b792287
F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338
F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185
F test/alterauth2.test 4b74fa8f184f4736497317feb587b65759eb87d87acfe3a8ef433d4d18bb002b
F test/altercol.test 3661c432aacb42bc2198dd4611bbb9c3b09fc73251b59edda046109103b8ac00
F test/altercons.test 9b036a956268eccd64761a6af3ab6f7b313c738392c7460b747d8aacd32589a2
-F test/altercons2.test 4933eadb035fc0ccfc34ed879f69a09051c53907f9dae9c3d36d25f93519ccc7
+F test/altercons2.test 264c1cc31c16b319de423af9565eb7129d7e9f55b21bb4eda6fdae02841265ae
+F test/altercons3.test d0bd7dde66a4a4f0b432b3ae3520e989b52b9bdfadddb9bd80be94554fecf803
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c
-P 4edba31af4ef18350cb415079fb92cae0c53767fc0e74d63d404296974e75e5c f94259fc07cd7856e9c6f81a46689f4f96bbf464fda7f1d11b51a308c296aca0
-R 688db872c29fb684e76bc6c6acf8cc9b
-T +closed f94259fc07cd7856e9c6f81a46689f4f96bbf464fda7f1d11b51a308c296aca0
-U drh
-Z aa42c4c981256f3d4f6c42fc99d72364
+P c8aa208bf5b00f3ab93c5edd510dfd0d7edd271c064f159616ee409b308f7eb9
+R 4bd3a46fbadb8b3a12b89cadb35de70a
+T *branch * drop-constraint-fk
+T *sym-drop-constraint-fk *
+T -sym-trunk *
+U dan
+Z 7b2661190251d9be0a0996978db71a70
# Remove this line to create a well-formed Fossil manifest.
-branch trunk
-tag trunk
+branch drop-constraint-fk
+tag drop-constraint-fk
-c8aa208bf5b00f3ab93c5edd510dfd0d7edd271c064f159616ee409b308f7eb9
+17c08963812d6458783720c511806727aeae263a243a11d49b463d2c7867cd54
/*
** Argument z points into the body of a constraint - specifically the
** second token of the constraint definition. For a named constraint,
-** z points to the first token past the CONSTRAINT keyword. For an
-** unnamed NOT NULL constraint, z points to the first byte past the NOT
+** z points to the second token of the constraint definition. For an
+** unnamed NOT NULL constraint, z points to the first byte past the NOT
** 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.
+**
** Return the number of bytes until the end of the constraint.
*/
-static int getConstraint(const u8 *z){
+static int getConstraint(const u8 *z, int eTok){
int iOff = 0;
int t = 0;
+#ifndef SQLITE_OMIT_FOREIGN_KEY
+ if( eTok==TK_FOREIGN ){
+ /* For a FOREIGN KEY constraint, use getConstraint() to parse everything
+ ** up to the REFERENCES keyword. Then getConstraintToken() to consume
+ ** the TK_REFERENCES token itself. Then fall through to the special
+ ** handling for TK_REFERENCES below. */
+ iOff = getConstraint(z, 0);
+ iOff += getConstraintToken(&z[iOff], &eTok);
+ }
+
+ if( eTok==TK_REFERENCES ){
+ /* 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);
+ }
+#endif
+
/* Now, the current constraint proceeds until the next occurence of one
** of the following tokens:
**
t = TK_CHECK;
}else{
iOff += nTok;
- iOff += getConstraint(&zSql[iOff]);
+ iOff += getConstraint(&zSql[iOff], t);
}
if( cmp==0 || (iNotNull>=0 && t==TK_NOT) ){
- if( t!=TK_NOT && t!=TK_CHECK ){
+ if( t!=TK_NOT && t!=TK_CHECK && t!=TK_REFERENCES && t!=TK_FOREIGN ){
errorMPrintf(ctx, "constraint may not be dropped: %s", zCons);
return;
}
}
}else if( t==TK_NOT && iNotNull==ii ){
- iEnd = iOff + getConstraint(&zSql[iOff]);
+ iEnd = iOff + getConstraint(&zSql[iOff], 0);
break;
}else if( t==TK_RP || t==TK_ILLEGAL ){
iEnd = -1;
}
do_catchsql_test 8.1 {
ALTER TABLE abc DROP CONSTRAINT one
-} {1 {constraint may not be dropped: one}}
+} {0 {}}
+do_execsql_test 8.2 {
+ SELECT sql FROM sqlite_schema
+} {{CREATE TABLE abc(a, b, c)}}
#-------------------------------------------------------------------------
reset_db
--- /dev/null
+# 2026 July 8
+#
+# 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 altercons3
+
+# If SQLITE_OMIT_ALTERTABLE is defined, omit this file.
+ifcapable !altertable {
+ finish_test
+ return
+}
+
+#-------------------------------------------------------------------------
+do_execsql_test 1.0 {
+ CREATE TABLE p1(a PRIMARY KEY);
+ CREATE TABLE c1(b CONSTRAINT fk REFERENCES p1(a));
+}
+do_execsql_test 1.1 {
+ ALTER TABLE c1 DROP CONSTRAINT fk;
+ SELECT sql FROM sqlite_schema WHERE name='c1';
+} {{CREATE TABLE c1(b)}}
+
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 2.0 {
+ CREATE TABLE p1(a PRIMARY KEY);
+ CREATE TABLE c1(b, CONSTRAINT fk FOREIGN KEY (b) REFERENCES p1(a));
+}
+do_execsql_test 2.1 {
+ ALTER TABLE c1 DROP CONSTRAINT fk;
+ SELECT sql FROM sqlite_schema WHERE name='c1';
+} {{CREATE TABLE c1(b)}}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 3.0 {
+ CREATE TABLE generated(a PRIMARY KEY);
+ CREATE TABLE c1(b CONSTRAINT fk REFERENCES generated(a));
+}
+do_execsql_test 3.1 {
+ ALTER TABLE c1 DROP CONSTRAINT fk;
+ SELECT sql FROM sqlite_schema WHERE name='c1';
+} {{CREATE TABLE c1(b)}}
+
+#--------------------------------------------------------------------------
+reset_db
+
+foreach {tn before after} {
+ 1 "CREATE TABLE c1(b CONSTRAINT fk REFERENCES p1(a))"
+ "CREATE TABLE c1(b)"
+
+ 2 "CREATE TABLE c1(b, c, CONSTRAINT fk FOREIGN key (c, b) REFERENCES p1(o,t))"
+ "CREATE TABLE c1(b, c)"
+
+ 3 "CREATE TABLE c1(b, generated,
+ CONSTRAINT fk FOREIGN key (generated) REFERENCES p1(o))"
+ "CREATE TABLE c1(b, generated)"
+
+ 4 "CREATE TABLE c1(b, generated CONSTRAINT fk REFERENCES p1(o) NOT NULL)"
+ "CREATE TABLE c1(b, generated NOT NULL)"
+
+ 5 "CREATE TABLE c1(b, generated CONSTRAINT fk REFERENCES x1)"
+ "CREATE TABLE c1(b, generated)"
+} {
+ do_execsql_test 4.$tn.1 { DROP TABLE IF EXISTS c1 }
+ do_execsql_test 4.$tn.2 $before
+ do_execsql_test 4.$tn.3 { ALTER TABLE c1 DROP CONSTRAINT fk }
+ do_execsql_test 4.$tn.4 {
+ SELECT sql FROM sqlite_schema WHERE name='c1'
+ } [list $after]
+}
+
+#-------------------------------------------------------------------------
+reset_db
+do_execsql_test 5.0 {
+ CREATE TABLE x1(a, b CONSTRAINT ott REFERENCES x2);
+ PRAGMA writable_schema = 1;
+ UPDATE sqlite_schema SET sql='CREATE TABLE x1(a, b CONSTRAINT ott REFERENCES';
+}
+
+do_execsql_test 5.1 {
+ ALTER TABLE x1 DROP CONSTRAINT ott;
+}
+
+do_execsql_test 5.2 {
+ SELECT sql FROM sqlite_schema
+} {{CREATE TABLE x1(a, b }}
+
+finish_test
+