Fix authorization callbacks for the new commands on this branch.
FossilOrigin-Name: 0165e2afa8b640c9d7a31414f06144e089844dc13691f06f363a50d14fec62bc
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
C Add\sexperimental\simplementations\sof\sALTER\sTABLE\scommands\sto\sadd\sand\sdrop\sCHECK\sand\sNOT\sNULL\sconstraints.
|
||||
D 2025-09-27T14:59:21.750
|
||||
C Fix\sauthorization\scallbacks\sfor\sthe\snew\scommands\son\sthis\sbranch.
|
||||
D 2025-09-27T16:13:56.339
|
||||
F .fossil-settings/binary-glob 61195414528fb3ea9693577e1980230d78a1f8b0a54c78cf1b9b24d0a409ed6a x
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
@@ -670,7 +670,7 @@ F mptest/multiwrite01.test dab5c5f8f9534971efce679152c5146da265222d
|
||||
F sqlite.pc.in 42b7bf0d02e08b9e77734a47798d1a55a9e0716b
|
||||
F sqlite3.1 1b9c24374a85dfc7eb8fa7c4266ee0db4f9609cceecfc5481cd8307e5af04366
|
||||
F sqlite3.pc.in e6dee284fba59ef500092fdc1843df3be8433323a3733c91da96690a50a5b398
|
||||
F src/alter.c 8eeaacd19f6b5948600c7d567c1e22a906d60777c1de8be0d2caa6b68a058a3a
|
||||
F src/alter.c b126042887cccd2c6476685f634cbcfa7b7f2812ca4dc96bbb6d606fa9ba56e6
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
|
||||
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
|
||||
@@ -726,7 +726,7 @@ F src/os_win.c f81a7cffdfe8c593a840895b3f64290714f0186b06302d2c397012252d830374
|
||||
F src/os_win.h 4c247cdb6d407c75186c94a1e84d5a22cbae4adcec93fcae8d2bc1f956fd1f19
|
||||
F src/pager.c 113f9149092ccff6cf90e97c2611200e5a237f13d26c394bc9fd933377852764
|
||||
F src/pager.h 6137149346e6c8a3ddc1eeb40aee46381e9bc8b0fcc6dda8a1efde993c2275b8
|
||||
F src/parse.y 853bfe037292ab3731b0753a92291d248161e721dd6893affb9d181d65f43702
|
||||
F src/parse.y 834ba749a6a9f34ef49ad4dd30531252739f6f796f1589d0c4ba548385276535
|
||||
F src/pcache.c 588cc3c5ccaaadde689ed35ce5c5c891a1f7b1f4d1f56f6cf0143b74d8ee6484
|
||||
F src/pcache.h 1497ce1b823cf00094bb0cf3bac37b345937e6f910890c626b16512316d3abf5
|
||||
F src/pcache1.c 131ca0daf4e66b4608d2945ae76d6ed90de3f60539afbd5ef9ec65667a5f2fcd
|
||||
@@ -741,7 +741,7 @@ F src/shell.c.in 0ab96b4d875ec03e1b5d0c97aa3f2f68d3b6c926f270488e26f3088d1755481
|
||||
F src/sqlite.h.in 5732519a2acb09066032ceac21f25996eb3f28f807a4468e30633c7c70faae1c
|
||||
F src/sqlite3.rc 015537e6ac1eec6c7050e17b616c2ffe6f70fca241835a84a4f0d5937383c479
|
||||
F src/sqlite3ext.h 3f0c4ed6934e7309a61c6f3c30f70a30a5b869f785bb3d9f721a36c5e4359126
|
||||
F src/sqliteInt.h 9e65623e73c1c6d45e8bba3bad2d86d90cc289b2923ca35a26db5328d9f1ed60
|
||||
F src/sqliteInt.h d555ae8089e7032ae47823a58150f424e2f8715eaadc0eb3071a5c3de028a8a7
|
||||
F src/sqliteLimit.h fe70bd8983e5d317a264f2ea97473b359faf3ebb0827877a76813f5cf0cdc364
|
||||
F src/status.c 0e72e4f6be6ccfde2488eb63210297e75f569f3ce9920f6c3d77590ec6ce5ffd
|
||||
F src/table.c 0f141b58a16de7e2fbe81c308379e7279f4c6b50eb08efeec5892794a0ba30d1
|
||||
@@ -839,7 +839,7 @@ F test/alter4.test 37cafe164067a6590a0ee4cec780bddbbaa33dc50b11542dcfbe0e6562649
|
||||
F test/alterauth.test 63442ba61ceb0c1eeb63aac1f4f5cebfa509d352276059d27106ae256bafc959
|
||||
F test/alterauth2.test 48967abae0494d9a300d1c92473d99fcb66edfcc23579c89322f033f49410adc
|
||||
F test/altercol.test b43fb5725332f4cf8cff0280605202c1672e808281accea60a066d2ccc5129e5
|
||||
F test/altercons.test 2e05836679a139317b8ac18c48c86d814b38011a7f225cbd52880fc8bc22c2f5
|
||||
F test/altercons.test 33fb8117e669b14536a7cf5df694a6027e5773c2e5d12dd2a240c7b2046c9cc5
|
||||
F test/altercorrupt.test 2e1d705342cf9d7de884518ddbb053fd52d7e60d2b8869b7b63b2fda68435c12
|
||||
F test/alterdropcol.test a653a3945f964d26845ec0cd0a8e74189f46de3119a984c5bc45457da392612e
|
||||
F test/alterdropcol2.test 527fce683b200d620f560f666c44ae33e22728e990a10a48a543280dfd4b4d41
|
||||
@@ -2170,11 +2170,8 @@ F tool/version-info.c 3b36468a90faf1bbd59c65fd0eb66522d9f941eedd364fabccd7227350
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh 1ad0169b022b280bcaaf94a7fa231591be96b514230ab5c98fbf15cd7df842dd
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P b44650f907e9cb4ec908bb7525488e309946fac9d84cdac4cdde730527a440a9
|
||||
R 62bf02b8a31c34d045e943408d7ca34a
|
||||
T *branch * alter-table-constraints
|
||||
T *sym-alter-table-constraints *
|
||||
T -sym-trunk *
|
||||
P d939b25d76fe70a3255cfe38097d4489323028cd05e5512a98dce06b48eee445
|
||||
R df87aa2ddd3ec2e579d06904451a2687
|
||||
U dan
|
||||
Z df1bd70c76c4689d412ec3f686f545c6
|
||||
Z afa946c19eec2db0cf6e37984f361e84
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
d939b25d76fe70a3255cfe38097d4489323028cd05e5512a98dce06b48eee445
|
||||
0165e2afa8b640c9d7a31414f06144e089844dc13691f06f363a50d14fec62bc
|
||||
|
||||
+67
-57
@@ -563,7 +563,7 @@ exit_begin_add_column:
|
||||
** Or, if pTab is not a view or virtual table, zero is returned.
|
||||
*/
|
||||
#if !defined(SQLITE_OMIT_VIEW) || !defined(SQLITE_OMIT_VIRTUALTABLE)
|
||||
static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
|
||||
static int isRealTable(Parse *pParse, Table *pTab, int iOp){
|
||||
const char *zType = 0;
|
||||
#ifndef SQLITE_OMIT_VIEW
|
||||
if( IsView(pTab) ){
|
||||
@@ -576,9 +576,12 @@ static int isRealTable(Parse *pParse, Table *pTab, int bDrop){
|
||||
}
|
||||
#endif
|
||||
if( zType ){
|
||||
const char *azMsg[] = {
|
||||
"rename columns of", "drop column from", "edit constraints of"
|
||||
};
|
||||
assert( iOp>=0 && iOp<ArraySize(azMsg) );
|
||||
sqlite3ErrorMsg(pParse, "cannot %s %s \"%s\"",
|
||||
(bDrop ? "drop column from" : "rename columns of"),
|
||||
zType, pTab->zName
|
||||
azMsg[iOp], zType, pTab->zName
|
||||
);
|
||||
return 1;
|
||||
}
|
||||
@@ -2633,11 +2636,64 @@ static int alterFindCol(Parse *pParse, Table *pTab, Token *pCol, int *piCol){
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( rc==SQLITE_OK ){
|
||||
const char *zDb = db->aDb[sqlite3SchemaToIndex(db, pTab->pSchema)].zDbSName;
|
||||
const char *zCol = pTab->aCol[iCol].zCnName;
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, zDb, pTab->zName, zCol) ){
|
||||
pTab = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
sqlite3DbFree(db, zName);
|
||||
*piCol = iCol;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Find the table named by the first entry in source list pSrc. If successful,
|
||||
** return a pointer to the Table structure and set output variable (*pzDb)
|
||||
** to point to the name of the database containin the table (i.e. "main",
|
||||
** "temp" or the name of an attached database).
|
||||
**
|
||||
** If the table cannot be located, return NULL. The value of the two output
|
||||
** parameters is undefined in this case.
|
||||
*/
|
||||
static Table *alterFindTable(
|
||||
Parse *pParse,
|
||||
SrcList *pSrc,
|
||||
int *piDb,
|
||||
const char **pzDb,
|
||||
int bAuth
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
Table *pTab = 0;
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
||||
if( pTab ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
*pzDb = db->aDb[iDb].zDbSName;
|
||||
*piDb = iDb;
|
||||
|
||||
if( SQLITE_OK!=isRealTable(pParse, pTab, 2)
|
||||
|| SQLITE_OK!=isAlterableTable(pParse, pTab)
|
||||
){
|
||||
pTab = 0;
|
||||
}
|
||||
}
|
||||
#ifndef SQLITE_OMIT_AUTHORIZATION
|
||||
if( pTab && bAuth ){
|
||||
if( sqlite3AuthCheck(pParse, SQLITE_ALTER_TABLE, *pzDb, pTab->zName, 0) ){
|
||||
pTab = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
return pTab;
|
||||
}
|
||||
|
||||
void alterDropConstraint(
|
||||
Parse *pParse,
|
||||
SrcList *pSrc,
|
||||
@@ -2650,26 +2706,14 @@ void alterDropConstraint(
|
||||
const char *zDb = 0;
|
||||
char *zArg = 0;
|
||||
|
||||
/* Look up the table being altered. */
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
||||
if( !pTab ) goto exit_drop_cons;
|
||||
|
||||
/* Make sure this is not an attempt to ALTER a view, virtual table or
|
||||
** system table. */
|
||||
if( SQLITE_OK!=isAlterableTable(pParse, pTab) ) goto exit_drop_cons;
|
||||
if( SQLITE_OK!=isRealTable(pParse, pTab, 1) ) goto exit_drop_cons;
|
||||
|
||||
/* Edit the sqlite_schema table */
|
||||
iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
assert( iDb>=0 );
|
||||
zDb = db->aDb[iDb].zDbSName;
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, pCons!=0);
|
||||
if( !pTab ) return;
|
||||
|
||||
if( pCons ){
|
||||
zArg = sqlite3MPrintf(db, "%.*Q", pCons->n, pCons->z);
|
||||
}else{
|
||||
int iCol;
|
||||
if( alterFindCol(pParse, pTab, pCol, &iCol) ) goto exit_drop_cons;
|
||||
if( alterFindCol(pParse, pTab, pCol, &iCol) ) return;
|
||||
zArg = sqlite3MPrintf(db, "%d", iCol);
|
||||
}
|
||||
|
||||
@@ -2684,9 +2728,6 @@ void alterDropConstraint(
|
||||
|
||||
/* Finally, reload the database schema. */
|
||||
renameReloadSchema(pParse, iDb, INITFLAG_AlterDropCons);
|
||||
|
||||
exit_drop_cons:
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
}
|
||||
|
||||
|
||||
@@ -2724,34 +2765,6 @@ static void failConstraintFunc(
|
||||
sqlite3_result_error_code(ctx, err);
|
||||
}
|
||||
|
||||
/*
|
||||
** Find the table named by the first entry in source list pSrc. If successful,
|
||||
** return a pointer to the Table structure and set output variable (*pzDb)
|
||||
** to point to the name of the database containin the table (i.e. "main",
|
||||
** "temp" or the name of an attached database).
|
||||
**
|
||||
** If the table cannot be located, return NULL. The value of the two output
|
||||
** parameters is undefined in this case.
|
||||
*/
|
||||
static Table *alterFindTable(
|
||||
Parse *pParse,
|
||||
SrcList *pSrc,
|
||||
int *piDb,
|
||||
const char **pzDb
|
||||
){
|
||||
sqlite3 *db = pParse->db;
|
||||
Table *pTab = 0;
|
||||
assert( sqlite3BtreeHoldsAllMutexes(db) );
|
||||
pTab = sqlite3LocateTableItem(pParse, 0, &pSrc->a[0]);
|
||||
sqlite3SrcListDelete(db, pSrc);
|
||||
if( pTab ){
|
||||
int iDb = sqlite3SchemaToIndex(db, pTab->pSchema);
|
||||
*pzDb = db->aDb[iDb].zDbSName;
|
||||
*piDb = iDb;
|
||||
}
|
||||
return pTab;
|
||||
}
|
||||
|
||||
/*
|
||||
** Prepare a statement of the form:
|
||||
**
|
||||
@@ -2760,7 +2773,8 @@ static Table *alterFindTable(
|
||||
void sqlite3AlterSetNotNull(
|
||||
Parse *pParse,
|
||||
SrcList *pSrc,
|
||||
Token *pCol
|
||||
Token *pCol,
|
||||
Token *pFirst
|
||||
){
|
||||
Table *pTab = 0;
|
||||
int iCol = 0;
|
||||
@@ -2771,7 +2785,7 @@ void sqlite3AlterSetNotNull(
|
||||
int t = 0;
|
||||
|
||||
/* Look up the table being altered. */
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb);
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 0);
|
||||
if( !pTab ) return;
|
||||
|
||||
/* Find the column being altered. */
|
||||
@@ -2779,12 +2793,8 @@ void sqlite3AlterSetNotNull(
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the start of the constraint definition */
|
||||
pCons = &pCol->z[pCol->n];
|
||||
pCons += getConstraintToken((const u8*)pCons, &t);
|
||||
pCons += getWhitespace((const u8*)pCons);
|
||||
|
||||
/* Find the length in bytes of the constraint definition */
|
||||
pCons = pFirst->z;
|
||||
nCons = pParse->sLastToken.z - pCons;
|
||||
if( pCons[nCons-1]==';' ) nCons--;
|
||||
while( sqlite3Isspace(pCons[nCons-1]) ) nCons--;
|
||||
@@ -2868,7 +2878,7 @@ void sqlite3AlterAddConstraint(
|
||||
int nCons;
|
||||
|
||||
/* Look up the table being altered. */
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb);
|
||||
pTab = alterFindTable(pParse, pSrc, &iDb, &zDb, 1);
|
||||
if( !pTab ) return;
|
||||
|
||||
/* If this new constraint has a name, check that it is not a duplicate of
|
||||
|
||||
+2
-2
@@ -1856,8 +1856,8 @@ cmd ::= ALTER TABLE fullname(X) DROP CONSTRAINT nm(Y). {
|
||||
cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) DROP NOT NULL. {
|
||||
sqlite3AlterDropNotNull(pParse, X, &Y);
|
||||
}
|
||||
cmd ::= ALTER TABLE fullname(X) ALTER kwcolumn_opt nm(Y) SET NOT NULL onconf. {
|
||||
sqlite3AlterSetNotNull(pParse, X, &Y);
|
||||
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. {
|
||||
|
||||
+1
-1
@@ -5451,7 +5451,7 @@ void sqlite3AlterRenameColumn(Parse*, SrcList*, Token*, Token*);
|
||||
void sqlite3AlterDropConstraint(Parse*, SrcList*, Token*);
|
||||
void sqlite3AlterDropNotNull(Parse*, SrcList*, Token*);
|
||||
void sqlite3AlterAddConstraint(Parse*,SrcList*,Token*,Token*,const char*,int);
|
||||
void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*);
|
||||
void sqlite3AlterSetNotNull(Parse*, SrcList*, Token*, Token*);
|
||||
int sqlite3GetToken(const unsigned char *, int *);
|
||||
void sqlite3NestedParse(Parse*, const char*, ...);
|
||||
void sqlite3ExpirePreparedStatements(sqlite3*, int);
|
||||
|
||||
@@ -228,4 +228,46 @@ do_execsql_test 6.4.1 {
|
||||
SELECT sql FROM sqlite_schema WHERE tbl_name='b1'
|
||||
} {{CREATE TABLE b1(a, b, CONSTRAINT abc CHECK (a!=2))}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
# Try attaching a NOT NULL to a generated column.
|
||||
#
|
||||
reset_db
|
||||
do_execsql_test 7.0 {
|
||||
CREATE TABLE x1(a, b AS (a+1));
|
||||
INSERT INTO x1 VALUES(1), (2), (3), (NULL);
|
||||
}
|
||||
|
||||
do_catchsql_test 7.1 {
|
||||
ALTER TABLE x1 ALTER b SET NOT NULL;
|
||||
} {1 {constraint failed}}
|
||||
|
||||
do_catchsql_test 7.2 {
|
||||
DELETE FROM x1 WHERE b IS NULL;
|
||||
ALTER TABLE x1 ALTER b SET NOT NULL;
|
||||
} {0 {}}
|
||||
|
||||
do_execsql_test 7.3 {
|
||||
SELECT b FROM x1
|
||||
} {2 3 4}
|
||||
|
||||
do_catchsql_test 7.4 {
|
||||
ALTER TABLE x1 ALTER rowid SET NOT NULL;
|
||||
} {1 {no such column: rowid}}
|
||||
|
||||
do_execsql_test 7.5 {
|
||||
CREATE VIEW v1 AS SELECT a, b FROM x1;
|
||||
}
|
||||
do_catchsql_test 7.6 {
|
||||
ALTER TABLE v1 RENAME a TO c;
|
||||
} {1 {cannot rename columns of view "v1"}}
|
||||
do_catchsql_test 7.7 {
|
||||
ALTER TABLE v1 ALTER a SET NOT NULL;
|
||||
} {1 {cannot edit constraints of view "v1"}}
|
||||
do_catchsql_test 7.8 {
|
||||
ALTER TABLE sqlite_schema ALTER sql SET NOT NULL;
|
||||
} {1 {table sqlite_master may not be altered}}
|
||||
do_catchsql_test 7.9 {
|
||||
ALTER TABLE v1 ALTER a DROP NOT NULL
|
||||
} {1 {cannot edit constraints of view "v1"}}
|
||||
|
||||
finish_test
|
||||
|
||||
Reference in New Issue
Block a user