From: drh <> Date: Mon, 11 May 2026 12:38:18 +0000 (+0000) Subject: An alternative fix to ALTER TABLE ADD CONSTRAINT. X-Git-Url: http://git.ipfire.org/gitweb/index.cgi?a=commitdiff_plain;h=5f6a6fa6f0c332d31b73b1e35c69de6c4324eb62;p=thirdparty%2Fsqlite.git An alternative fix to ALTER TABLE ADD CONSTRAINT. FossilOrigin-Name: a231fc6d58abb3b76d0e669babdb377e41b5a348d155ab5f2c1fe49eefbbf3a9 --- diff --git a/manifest b/manifest index 7cfd623c6c..b3f2bf41db 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Improve\sdetection\sof\scorrupt\sdatabase\srecords\sin\sfts5. -D 2026-05-11T11:53:07.269 +C An\salternative\sfix\sto\sALTER\sTABLE\sADD\sCONSTRAINT. +D 2026-05-11T12:38:18.187 F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1 F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea @@ -669,7 +669,7 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366 F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398 -F src/alter.c 7d7ddbdc189f0e0c686e32ee170abdddc95c11f2089e40df4ffcee88f5334826 +F src/alter.c 0bd3e9aa311befd1615ce56585039e79764e244c880c12ad0829394d186acac1 F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d F src/attach.c c58278c7d2d954785591c4fde81669ec3e4d52f348c453b028a19ae8adf4f338 F src/auth.c b5ece4e1edccad082c0332fa0087df225473bae0feea9269f824312201377185 @@ -726,7 +726,7 @@ F src/os_win.c 4786b1123beea22a9cd8f8e9d781cc1b4bf4679c56103edbf60a519ce23a2781 F src/os_win.h c06ccc3a090cf54202ea58981c298817f3309d4c9e4d52ad0a02927346493721 F src/pager.c fbec9063ea139dfa5d94ce540671752b89f8e8dc38f8a1f614bab1aa04a2dd40 F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8 -F src/parse.y 1302f85ec4b85a25e47055a35606336b58a9403da04a00b9e4850a079fb49833 +F src/parse.y d5a3c5b0277a441c38b35071c05e2b61ff5fc918a63309c809f4b6706179c320 F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484 F src/pcache.h 092b758d2c5e4dabb30eae46d8dfad77c0f70b16bf3ff1943f7a232b0fe0d4ba F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd @@ -741,7 +741,7 @@ F src/shell.c.in 9ee66535e9da2ca2bd504a5925be1958c0e8f269d80a87109ffdc5ec6e9b416 F src/sqlite.h.in 39d2e09114d2bdb7afd998f4a469c8f8cd065f8093835a7d0422f260fc78fb4f F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479 F src/sqlite3ext.h 9788c301f95370fa30e808861f1d2e6f022a816ddbe2a4f67486784c1b31db2e -F src/sqliteInt.h 5071d64ad787d9922e524d834c3fe7b7a11989d29dc6ea25f7944892a43266f4 +F src/sqliteInt.h 6a4f617776f89a7a36e85a4b14c8c21bc27336f3767e0c3c6f6d9cee886189d6 F src/sqliteLimit.h c70656b67ab5b96741a8f1c812bdd80c81f2b1c1e443d0cc3ea8c33bb1f1a092 F src/status.c 7565d63a79aa2f326339a24a0461a60096d0bd2bce711fefb50b5c89335f3592 F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1 @@ -2204,8 +2204,11 @@ F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee F tool/warnings.sh a554d13f6e5cf3760f041b87939e3d616ec6961859c3245e8ef701d1eafc2ca2 F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f F tool/winmain.c 00c8fb88e365c9017db14c73d3c78af62194d9644feaf60e220ab0f411f3604c -P 4a5ad516ea93926c0d5206b4d72c3675905d2bf666b27a649256b93eb95c671b -R 865af529eea3342e181da8938ef806ff -U dan -Z a39b47d6b7d9419acca90fe50f12d1aa +P 87b653731171a26396f9796b0a5c436593571d39e991d8d040ef4473cf459b67 +R 28b63aaa6a9b1475d2ab92a464126ecf +T *branch * add-constraint-safety-v2 +T *sym-add-constraint-safety-v2 * +T -sym-trunk * +U drh +Z aa8b245cae20725c4cb9b447a6428527 # Remove this line to create a well-formed Fossil manifest. diff --git a/manifest.tags b/manifest.tags index bec971799f..5f8e370af1 100644 --- a/manifest.tags +++ b/manifest.tags @@ -1,2 +1,2 @@ -branch trunk -tag trunk +branch add-constraint-safety-v2 +tag add-constraint-safety-v2 diff --git a/manifest.uuid b/manifest.uuid index 26d8911f63..25be856c27 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -87b653731171a26396f9796b0a5c436593571d39e991d8d040ef4473cf459b67 +a231fc6d58abb3b76d0e669babdb377e41b5a348d155ab5f2c1fe49eefbbf3a9 diff --git a/src/alter.c b/src/alter.c index 10b72526d1..7600b6ab05 100644 --- a/src/alter.c +++ b/src/alter.c @@ -2987,19 +2987,32 @@ void sqlite3AlterAddConstraint( SrcList *pSrc, /* Table to add constraint to */ Token *pFirst, /* First token of new constraint */ Token *pName, /* Name of new constraint. NULL if name omitted. */ - const char *pExpr, /* Text of CHECK expression */ - int nExpr /* Size of pExpr in bytes */ + const char *zExpr, /* Text of CHECK expression */ + int nExpr, /* Size of pExpr in bytes */ + Expr *pExpr /* The parsed CHECK expression */ ){ Table *pTab = 0; /* Table identified by pSrc */ int iDb = 0; /* Which schema does pTab live in */ const char *zDb = 0; /* Name of the schema in which pTab lives */ const char *pCons = 0; /* Text of the constraint */ int nCons; /* Bytes of text to use from pCons[] */ + int rc; /* Result from error checking pExpr */ /* Look up the table being altered. */ assert( pSrc->nSrc==1 ); pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1); - if( !pTab ) return; + if( !pTab ){ + sqlite3ExprDelete(pParse->db, pExpr); + return; + } + + /* Verify that the new CHECK constraint does not contain any + ** internal-use-only function or RAISE() expressions. + ** Forum post 026-05-10T01:11:28Z + */ + rc = sqlite3ResolveSelfReference(pParse, pTab, NC_IsCheck, pExpr, 0); + sqlite3ExprDelete(pParse->db, pExpr); + if( rc ) return; /* If this new constraint has a name, check that it is not a duplicate of ** an existing constraint. It is an error if it is. */ @@ -3020,7 +3033,7 @@ void sqlite3AlterAddConstraint( sqlite3NestedParse(pParse, "SELECT sqlite_fail('constraint failed', %d) " "FROM %Q.%Q WHERE (%.*s) IS NOT TRUE", - SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, pExpr + SQLITE_CONSTRAINT, zDb, pTab->zName, nExpr, zExpr ); /* Edit the SQL for the named table. */ diff --git a/src/parse.y b/src/parse.y index 17a67462d9..93ebf5c9ac 100644 --- a/src/parse.y +++ b/src/parse.y @@ -1912,11 +1912,11 @@ cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) DROP NOT NULL. { cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) SET NOT(Z) NULL onconf. { sqlite3AlterSetNotNull(pParse, X, &Y, &Z); } -cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr RP(B) onconf. { - sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1)); +cmd ::= ALTER TABLE fullname(X) ADD CONSTRAINT(Y) nm(Z) CHECK LP(A) expr(E) RP(B) onconf. { + sqlite3AlterAddConstraint(pParse, X, &Y, &Z, A.z+1, (B.z-A.z-1), E); } -cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr RP(B) onconf. { - sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1)); +cmd ::= ALTER TABLE fullname(X) ADD CHECK(Y) LP(A) expr(E) RP(B) onconf. { + sqlite3AlterAddConstraint(pParse, X, &Y, 0, A.z+1, (B.z-A.z-1), E); } kwcolumn_opt ::= . diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 57474057c1..89ebc878d6 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -5504,7 +5504,15 @@ void sqlite3AlterFunctions(void); void sqlite3AlterRenameTable(Parse*, SrcList*, Token*); void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*); void sqlite3AlterDropConstraint(Parse*,SrcList*,Token*,Token*); -void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int); +void sqlite3AlterAddConstraint( + Parse *pParse, /* Parse context */ + SrcList *pSrc, /* Table to add constraint to */ + Token *pFirst, /* First token of new constraint */ + Token *pName, /* Name of new constraint. NULL if name omitted. */ + const char *zExpr, /* Text of CHECK expression */ + int nExpr, /* Size of pExpr in bytes */ + Expr *pExpr /* The parsed CHECK expression */ +); void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*); i64 sqlite3GetToken(const unsigned char *, int *); void sqlite3NestedParse(Parse*, const char*, ...);