mirror of
https://github.com/sqlite/sqlite.git
synced 2026-10-23 21:49:02 +03:00
Fix a problem with ALTER TABLE DROP COLUMN commands where the column being dropped is the rightmost in table and is immediately preceded by a comment containing a "," character.
FossilOrigin-Name: c872bd1ee7b219e055f40e43766e4ed6bc2d2ca8cb92577cd3560f4173b1f257
This commit is contained in:
16
manifest
16
manifest
@@ -1,5 +1,5 @@
|
||||
C Add\sdeveloper\snote\son\show\sto\smeasure\scoverage\sof\sQRF.
|
||||
D 2025-12-02T12:23:24.524
|
||||
C Fix\sa\sproblem\swith\sALTER\sTABLE\sDROP\sCOLUMN\scommands\swhere\sthe\scolumn\sbeing\sdropped\sis\sthe\srightmost\sin\stable\sand\sis\simmediately\spreceded\sby\sa\scomment\scontaining\sa\s","\scharacter.
|
||||
D 2025-12-02T14:43:59.730
|
||||
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 fe6fa35700b968f8f9d2515939455e70f6b6ff2586a6e3ce9827bf44756354f2
|
||||
F src/alter.c 49274beed71d31591c8de17404f31e53ed8798507c8b3016d6f15b8ec478b1e2
|
||||
F src/analyze.c 03bcfc083fc0cccaa9ded93604e1d4244ea245c17285d463ef6a60425fcb247d
|
||||
F src/attach.c 9af61b63b10ee702b1594ecd24fb8cea0839cfdb6addee52fba26fa879f5db9d
|
||||
F src/auth.c 54ab9c6c5803b47c0d45b76ce27eff22a03b4b1f767c5945a3a4eb13aa4c78dc
|
||||
@@ -852,7 +852,7 @@ F test/altermalloc3.test 8040e486368403f2fdd6fc3998258b499bd4cc2f3ddbb5f8f874cd4
|
||||
F test/alterqf.test 8ec03d776de9c391daa0078ea8f838903bdcfb11dfae4ba3576b48436834ccba
|
||||
F test/altertab.test 8a2712f9076da5012a002d0b5cc0a421398a5bf61c25bab41b77c427586a7a27
|
||||
F test/altertab2.test 0889ba0700cc1cdb7bc7d25975aa61fece34f621de963d0886e2395716b38576
|
||||
F test/altertab3.test 471b8898d10bbc6488db9c23dc76811f405de6707d2d342b1b8b6fd1f13cd3c8
|
||||
F test/altertab3.test 575e771e2f02b13eb98798dc92eabacd187d6dbcf596e70f11d699b0b6b5d0b2
|
||||
F test/altertrig.test aacc980b657354fe2d3d4d3a004f07d04ccc1a93e5ef82d68a79088c274ddc6b
|
||||
F test/amatch1.test b5ae7065f042b7f4c1c922933f4700add50cdb9f
|
||||
F test/analyze.test 2fb21d7d64748636384e6cb8998dbf83968caf644c07fcb4f76c18f2e7ede94b
|
||||
@@ -2181,8 +2181,8 @@ F tool/version-info.c 33d0390ef484b3b1cb685d59362be891ea162123cea181cb8e6d2cf6dd
|
||||
F tool/warnings-clang.sh bbf6a1e685e534c92ec2bfba5b1745f34fb6f0bc2a362850723a9ee87c1b31a7
|
||||
F tool/warnings.sh d924598cf2f55a4ecbc2aeb055c10bd5f48114793e7ba25f9585435da29e7e98
|
||||
F tool/win/sqlite.vsix deb315d026cc8400325c5863eef847784a219a2f
|
||||
P 7e99e93cddeba555836206a278c5dcfd8565cc2a486a83cffab64dad168e9464
|
||||
R de758b56921e31817918b1313754b07f
|
||||
U drh
|
||||
Z cc3cfdbf6b5a72385cbc0d52882a934a
|
||||
P 0fdd453c03addb8f5c1e546f7513e3498bccd61266174ce99a61ceebf04e97cf
|
||||
R a05db7d00d43861c033636a6b23ea3b7
|
||||
U dan
|
||||
Z 7c7543e8fa4c87f35bf5869e2e4f8ba1
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
||||
@@ -1 +1 @@
|
||||
0fdd453c03addb8f5c1e546f7513e3498bccd61266174ce99a61ceebf04e97cf
|
||||
c872bd1ee7b219e055f40e43766e4ed6bc2d2ca8cb92577cd3560f4173b1f257
|
||||
|
||||
114
src/alter.c
114
src/alter.c
@@ -2114,6 +2114,57 @@ static void renameTableTest(
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return the number of bytes until the end of the next non-whitespace and
|
||||
** non-comment token. For the purpose of this function, a "(" token includes
|
||||
** all of the bytes through and including the matching ")", or until the
|
||||
** first illegal token, whichever comes first.
|
||||
**
|
||||
** Write the token type into *piToken.
|
||||
**
|
||||
** The value returned is the number of bytes in the token itself plus
|
||||
** the number of bytes of leading whitespace and comments skipped plus
|
||||
** all bytes through the next matching ")" if the token is TK_LP.
|
||||
**
|
||||
** Example: (Note: '.' used in place of '*' in the example z[] text)
|
||||
**
|
||||
** ,--------- *piToken := TK_RP
|
||||
** v
|
||||
** z[] = " /.comment./ --comment\n (two three four) five"
|
||||
** | |
|
||||
** |<-------------------------------------->|
|
||||
** |
|
||||
** `--- return value
|
||||
*/
|
||||
static int getConstraintToken(const u8 *z, int *piToken){
|
||||
int iOff = 0;
|
||||
int t = 0;
|
||||
do {
|
||||
iOff += sqlite3GetToken(&z[iOff], &t);
|
||||
}while( t==TK_SPACE || t==TK_COMMENT );
|
||||
|
||||
*piToken = t;
|
||||
|
||||
if( t==TK_LP ){
|
||||
int nNest = 1;
|
||||
while( nNest>0 ){
|
||||
iOff += sqlite3GetToken(&z[iOff], &t);
|
||||
if( t==TK_LP ){
|
||||
nNest++;
|
||||
}else if( t==TK_RP ){
|
||||
t = TK_LP;
|
||||
nNest--;
|
||||
}else if( t==TK_ILLEGAL ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*piToken = t;
|
||||
return iOff;
|
||||
}
|
||||
|
||||
/*
|
||||
** The implementation of internal UDF sqlite_drop_column().
|
||||
**
|
||||
@@ -2158,15 +2209,24 @@ static void dropColumnFunc(
|
||||
goto drop_column_done;
|
||||
}
|
||||
|
||||
pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
|
||||
if( iCol<pTab->nCol-1 ){
|
||||
RenameToken *pEnd;
|
||||
pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol].zCnName);
|
||||
pEnd = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol+1].zCnName);
|
||||
zEnd = (const char*)pEnd->t.z;
|
||||
}else{
|
||||
int eTok;
|
||||
assert( IsOrdinaryTable(pTab) );
|
||||
assert( iCol!=0 );
|
||||
/* Point pCol->t.z at the "," immediately preceding the definition of
|
||||
** the column being dropped. To do this, start at the name of the
|
||||
** previous column, and tokenize until the next ",". */
|
||||
pCol = renameTokenFind(&sParse, 0, (void*)pTab->aCol[iCol-1].zCnName);
|
||||
do {
|
||||
pCol->t.z += getConstraintToken(pCol->t.z, &eTok);
|
||||
}while( eTok!=TK_COMMA );
|
||||
pCol->t.z--;
|
||||
zEnd = (const char*)&zSql[pTab->u.tab.addColOffset];
|
||||
while( ALWAYS(pCol->t.z[0]!=0) && pCol->t.z[0]!=',' ) pCol->t.z--;
|
||||
}
|
||||
|
||||
zNew = sqlite3MPrintf(db, "%.*s%s", pCol->t.z-zSql, zSql, zEnd);
|
||||
@@ -2350,56 +2410,6 @@ static int getWhitespace(const u8 *z){
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** Return the number of bytes until the end of the next non-whitespace and
|
||||
** non-comment token. For the purpose of this function, a "(" token includes
|
||||
** all of the bytes through and including the matching ")", or until the
|
||||
** first illegal token, whichever comes first.
|
||||
**
|
||||
** Write the token type into *piToken.
|
||||
**
|
||||
** The value returned is the number of bytes in the token itself plus
|
||||
** the number of bytes of leading whitespace and comments skipped plus
|
||||
** all bytes through the next matching ")" if the token is TK_LP.
|
||||
**
|
||||
** Example: (Note: '.' used in place of '*' in the example z[] text)
|
||||
**
|
||||
** ,--------- *piToken := TK_RP
|
||||
** v
|
||||
** z[] = " /.comment./ --comment\n (two three four) five"
|
||||
** | |
|
||||
** |<-------------------------------------->|
|
||||
** |
|
||||
** `--- return value
|
||||
*/
|
||||
static int getConstraintToken(const u8 *z, int *piToken){
|
||||
int iOff = 0;
|
||||
int t = 0;
|
||||
do {
|
||||
iOff += sqlite3GetToken(&z[iOff], &t);
|
||||
}while( t==TK_SPACE || t==TK_COMMENT );
|
||||
|
||||
*piToken = t;
|
||||
|
||||
if( t==TK_LP ){
|
||||
int nNest = 1;
|
||||
while( nNest>0 ){
|
||||
iOff += sqlite3GetToken(&z[iOff], &t);
|
||||
if( t==TK_LP ){
|
||||
nNest++;
|
||||
}else if( t==TK_RP ){
|
||||
t = TK_LP;
|
||||
nNest--;
|
||||
}else if( t==TK_ILLEGAL ){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
*piToken = t;
|
||||
return iOff;
|
||||
}
|
||||
|
||||
/*
|
||||
** Argument z points into the body of a constraint - specifically the
|
||||
** second token of the constraint definition. For a named constraint,
|
||||
|
||||
@@ -778,4 +778,52 @@ do_execsql_test 31.2 {
|
||||
SELECT rr FROM t1 LIMIT 1
|
||||
} {5.0}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 32.1.0 {
|
||||
CREATE TABLE t1(
|
||||
a INT,
|
||||
b INT,
|
||||
-- comment with comma
|
||||
c INT
|
||||
);
|
||||
}
|
||||
do_execsql_test 32.1.1 {
|
||||
ALTER TABLE t1 DROP COLUMN c;
|
||||
}
|
||||
do_execsql_test 32.1.2 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {{CREATE TABLE t1(
|
||||
a INT,
|
||||
b INT)}}
|
||||
|
||||
reset_db
|
||||
do_execsql_test 32.2.0 {
|
||||
CREATE TABLE t1(
|
||||
a INT,
|
||||
b INT,
|
||||
-- comment with, comma
|
||||
c INT
|
||||
);
|
||||
}
|
||||
do_execsql_test 32.2.1 {
|
||||
ALTER TABLE t1 DROP COLUMN c;
|
||||
}
|
||||
do_execsql_test 32.2.2 {
|
||||
SELECT sql FROM sqlite_schema
|
||||
} {{CREATE TABLE t1(
|
||||
a INT,
|
||||
b INT)}}
|
||||
|
||||
#-------------------------------------------------------------------------
|
||||
reset_db
|
||||
do_execsql_test 33.1 {
|
||||
CREATE TABLE x1(a TEXT, b INTEGER, c CHECK(c!=0));
|
||||
}
|
||||
|
||||
do_execsql_test 33.2 {
|
||||
ALTER TABLE x1 DROP COLUMN b;
|
||||
SELECT sql FROM sqlite_schema;
|
||||
} {{CREATE TABLE x1(a TEXT, c CHECK(c!=0))}}
|
||||
|
||||
finish_test
|
||||
|
||||
Reference in New Issue
Block a user