mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-08 14:02:16 +03:00
Detect when a UNIQUE or PRIMARY KEY on a WITHOUT ROWID table would need
to use more than SQLITE_LIMIT_COLUMN columns and raise an error. Also include some unrelated compiler warning fixes. FossilOrigin-Name: d7729dbbf231d57cbcaaa5004d0a9c4957f112dd6520052995b232aa521c0ca3
This commit is contained in:
34
src/alter.c
34
src/alter.c
@@ -531,13 +531,13 @@ void sqlite3AlterBeginAddColumn(Parse *pParse, SrcList *pSrc){
|
||||
assert( pNew->nCol>0 );
|
||||
nAlloc = (((pNew->nCol-1)/8)*8)+8;
|
||||
assert( nAlloc>=pNew->nCol && nAlloc%8==0 && nAlloc-pNew->nCol<8 );
|
||||
pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*nAlloc);
|
||||
pNew->aCol = (Column*)sqlite3DbMallocZero(db, sizeof(Column)*(u32)nAlloc);
|
||||
pNew->zName = sqlite3MPrintf(db, "sqlite_altertab_%s", pTab->zName);
|
||||
if( !pNew->aCol || !pNew->zName ){
|
||||
assert( db->mallocFailed );
|
||||
goto exit_begin_add_column;
|
||||
}
|
||||
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*pNew->nCol);
|
||||
memcpy(pNew->aCol, pTab->aCol, sizeof(Column)*(size_t)pNew->nCol);
|
||||
for(i=0; i<pNew->nCol; i++){
|
||||
Column *pCol = &pNew->aCol[i];
|
||||
pCol->zCnName = sqlite3DbStrDup(db, pCol->zCnName);
|
||||
@@ -1144,7 +1144,13 @@ static int renameParseSql(
|
||||
if( sqlite3StrNICmp(zSql,"CREATE ",7)!=0 ){
|
||||
return SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
db->init.iDb = bTemp ? 1 : sqlite3FindDbName(db, zDb);
|
||||
if( bTemp ){
|
||||
db->init.iDb = 1;
|
||||
}else{
|
||||
int iDb = sqlite3FindDbName(db, zDb);
|
||||
assert( iDb>=0 && iDb<=0xff );
|
||||
db->init.iDb = (u8)iDb;
|
||||
}
|
||||
p->eParseMode = PARSE_MODE_RENAME;
|
||||
p->db = db;
|
||||
p->nQueryLoop = 1;
|
||||
@@ -1211,10 +1217,11 @@ static int renameEditSql(
|
||||
nQuot = sqlite3Strlen30(zQuot)-1;
|
||||
}
|
||||
|
||||
assert( nQuot>=nNew );
|
||||
zOut = sqlite3DbMallocZero(db, nSql + pRename->nList*nQuot + 1);
|
||||
assert( nQuot>=nNew && nSql>0 && nNew>0 );
|
||||
zOut = sqlite3DbMallocZero(db, (u64)(nSql + pRename->nList*nQuot + 1));
|
||||
}else{
|
||||
zOut = (char*)sqlite3DbMallocZero(db, (nSql*2+1) * 3);
|
||||
assert( nSql>0 );
|
||||
zOut = (char*)sqlite3DbMallocZero(db, (u64)(nSql*2+1) * 3);
|
||||
if( zOut ){
|
||||
zBuf1 = &zOut[nSql*2+1];
|
||||
zBuf2 = &zOut[nSql*4+2];
|
||||
@@ -1226,16 +1233,17 @@ static int renameEditSql(
|
||||
** with the new column name, or with single-quoted versions of themselves.
|
||||
** All that remains is to construct and return the edited SQL string. */
|
||||
if( zOut ){
|
||||
int nOut = nSql;
|
||||
memcpy(zOut, zSql, nSql);
|
||||
i64 nOut = nSql;
|
||||
assert( nSql>0 );
|
||||
memcpy(zOut, zSql, (size_t)nSql);
|
||||
while( pRename->pList ){
|
||||
int iOff; /* Offset of token to replace in zOut */
|
||||
u32 nReplace;
|
||||
i64 nReplace;
|
||||
const char *zReplace;
|
||||
RenameToken *pBest = renameColumnTokenNext(pRename);
|
||||
|
||||
if( zNew ){
|
||||
if( bQuote==0 && sqlite3IsIdChar(*pBest->t.z) ){
|
||||
if( bQuote==0 && sqlite3IsIdChar(*(u8*)pBest->t.z) ){
|
||||
nReplace = nNew;
|
||||
zReplace = zNew;
|
||||
}else{
|
||||
@@ -1547,7 +1555,7 @@ static void renameColumnFunc(
|
||||
if( sParse.pNewTable ){
|
||||
if( IsView(sParse.pNewTable) ){
|
||||
Select *pSelect = sParse.pNewTable->u.view.pSelect;
|
||||
pSelect->selFlags &= ~SF_View;
|
||||
pSelect->selFlags &= ~(u32)SF_View;
|
||||
sParse.rc = SQLITE_OK;
|
||||
sqlite3SelectPrep(&sParse, pSelect, 0);
|
||||
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
|
||||
@@ -1765,7 +1773,7 @@ static void renameTableFunc(
|
||||
sNC.pParse = &sParse;
|
||||
|
||||
assert( pSelect->selFlags & SF_View );
|
||||
pSelect->selFlags &= ~SF_View;
|
||||
pSelect->selFlags &= ~(u32)SF_View;
|
||||
sqlite3SelectPrep(&sParse, pTab->u.view.pSelect, &sNC);
|
||||
if( sParse.nErr ){
|
||||
rc = sParse.rc;
|
||||
@@ -1938,7 +1946,7 @@ static void renameQuotefixFunc(
|
||||
if( sParse.pNewTable ){
|
||||
if( IsView(sParse.pNewTable) ){
|
||||
Select *pSelect = sParse.pNewTable->u.view.pSelect;
|
||||
pSelect->selFlags &= ~SF_View;
|
||||
pSelect->selFlags &= ~(u32)SF_View;
|
||||
sParse.rc = SQLITE_OK;
|
||||
sqlite3SelectPrep(&sParse, pSelect, 0);
|
||||
rc = (db->mallocFailed ? SQLITE_NOMEM : sParse.rc);
|
||||
|
22
src/build.c
22
src/build.c
@@ -1067,10 +1067,16 @@ Index *sqlite3PrimaryKeyIndex(Table *pTab){
|
||||
** find the (first) offset of that column in index pIdx. Or return -1
|
||||
** if column iCol is not used in index pIdx.
|
||||
*/
|
||||
i16 sqlite3TableColumnToIndex(Index *pIdx, i16 iCol){
|
||||
i16 sqlite3TableColumnToIndex(Index *pIdx, int iCol){
|
||||
int i;
|
||||
i16 iCol16;
|
||||
assert( iCol>=(-1) && iCol<=SQLITE_MAX_COLUMN );
|
||||
assert( pIdx->nColumn<=SQLITE_MAX_COLUMN );
|
||||
iCol16 = iCol;
|
||||
for(i=0; i<pIdx->nColumn; i++){
|
||||
if( iCol==pIdx->aiColumn[i] ) return i;
|
||||
if( iCol16==pIdx->aiColumn[i] ){
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -2167,10 +2173,16 @@ static char *createTableStmt(sqlite3 *db, Table *p){
|
||||
** Resize an Index object to hold N columns total. Return SQLITE_OK
|
||||
** on success and SQLITE_NOMEM on an OOM error.
|
||||
*/
|
||||
static int resizeIndexObject(sqlite3 *db, Index *pIdx, int N){
|
||||
static int resizeIndexObject(Parse *pParse, Index *pIdx, int N){
|
||||
char *zExtra;
|
||||
int nByte;
|
||||
sqlite3 *db;
|
||||
if( pIdx->nColumn>=N ) return SQLITE_OK;
|
||||
db = pParse->db;
|
||||
if( N>db->aLimit[SQLITE_LIMIT_COLUMN] ){
|
||||
sqlite3ErrorMsg(pParse, "too many columns on %s", pIdx->zName);
|
||||
return SQLITE_ERROR;
|
||||
}
|
||||
assert( pIdx->isResized==0 );
|
||||
nByte = (sizeof(char*) + sizeof(LogEst) + sizeof(i16) + 1)*N;
|
||||
zExtra = sqlite3DbMallocZero(db, nByte);
|
||||
@@ -2440,7 +2452,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
pIdx->nColumn = pIdx->nKeyCol;
|
||||
continue;
|
||||
}
|
||||
if( resizeIndexObject(db, pIdx, pIdx->nKeyCol+n) ) return;
|
||||
if( resizeIndexObject(pParse, pIdx, pIdx->nKeyCol+n) ) return;
|
||||
for(i=0, j=pIdx->nKeyCol; i<nPk; i++){
|
||||
if( !isDupColumn(pIdx, pIdx->nKeyCol, pPk, i) ){
|
||||
testcase( hasColumn(pIdx->aiColumn, pIdx->nKeyCol, pPk->aiColumn[i]) );
|
||||
@@ -2464,7 +2476,7 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
|
||||
if( !hasColumn(pPk->aiColumn, nPk, i)
|
||||
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0 ) nExtra++;
|
||||
}
|
||||
if( resizeIndexObject(db, pPk, nPk+nExtra) ) return;
|
||||
if( resizeIndexObject(pParse, pPk, nPk+nExtra) ) return;
|
||||
for(i=0, j=nPk; i<pTab->nCol; i++){
|
||||
if( !hasColumn(pPk->aiColumn, j, i)
|
||||
&& (pTab->aCol[i].colFlags & COLFLAG_VIRTUAL)==0
|
||||
|
@@ -1963,7 +1963,7 @@ Select *sqlite3SelectDup(sqlite3 *db, const Select *pDup, int flags){
|
||||
pNew->pLimit = sqlite3ExprDup(db, p->pLimit, flags);
|
||||
pNew->iLimit = 0;
|
||||
pNew->iOffset = 0;
|
||||
pNew->selFlags = p->selFlags & ~SF_UsesEphemeral;
|
||||
pNew->selFlags = p->selFlags & ~(u32)SF_UsesEphemeral;
|
||||
pNew->addrOpenEphm[0] = -1;
|
||||
pNew->addrOpenEphm[1] = -1;
|
||||
pNew->nSelectRow = p->nSelectRow;
|
||||
|
@@ -693,7 +693,7 @@ Select *sqlite3MultiValues(Parse *pParse, Select *pLeft, ExprList *pRow){
|
||||
f = (f & pLeft->selFlags);
|
||||
}
|
||||
pSelect = sqlite3SelectNew(pParse, pRow, 0, 0, 0, 0, 0, f, 0);
|
||||
pLeft->selFlags &= ~SF_MultiValue;
|
||||
pLeft->selFlags &= ~(u32)SF_MultiValue;
|
||||
if( pSelect ){
|
||||
pSelect->op = TK_ALL;
|
||||
pSelect->pPrior = pLeft;
|
||||
|
@@ -617,8 +617,8 @@ selectnowith(A) ::= selectnowith(A) multiselect_op(Y) oneselect(Z). {
|
||||
if( pRhs ){
|
||||
pRhs->op = (u8)Y;
|
||||
pRhs->pPrior = pLhs;
|
||||
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~SF_MultiValue;
|
||||
pRhs->selFlags &= ~SF_MultiValue;
|
||||
if( ALWAYS(pLhs) ) pLhs->selFlags &= ~(u32)SF_MultiValue;
|
||||
pRhs->selFlags &= ~(u32)SF_MultiValue;
|
||||
if( Y!=TK_ALL ) pParse->hasCompound = 1;
|
||||
}else{
|
||||
sqlite3SelectDelete(pParse->db, pLhs);
|
||||
|
12
src/select.c
12
src/select.c
@@ -5646,7 +5646,7 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
|
||||
#ifndef SQLITE_OMIT_WINDOWFUNC
|
||||
p->pWinDefn = 0;
|
||||
#endif
|
||||
p->selFlags &= ~SF_Compound;
|
||||
p->selFlags &= ~(u32)SF_Compound;
|
||||
assert( (p->selFlags & SF_Converted)==0 );
|
||||
p->selFlags |= SF_Converted;
|
||||
assert( pNew->pPrior!=0 );
|
||||
@@ -7252,7 +7252,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
|
||||
pSub->pPrior = 0;
|
||||
pSub->pNext = 0;
|
||||
pSub->selFlags |= SF_Aggregate;
|
||||
pSub->selFlags &= ~SF_Compound;
|
||||
pSub->selFlags &= ~(u32)SF_Compound;
|
||||
pSub->nSelectRow = 0;
|
||||
sqlite3ParserAddCleanup(pParse, sqlite3ExprListDeleteGeneric, pSub->pEList);
|
||||
pTerm = pPrior ? sqlite3ExprDup(db, pCount, 0) : pCount;
|
||||
@@ -7267,7 +7267,7 @@ static int countOfViewOptimization(Parse *pParse, Select *p){
|
||||
pSub = pPrior;
|
||||
}
|
||||
p->pEList->a[0].pExpr = pExpr;
|
||||
p->selFlags &= ~SF_Aggregate;
|
||||
p->selFlags &= ~(u32)SF_Aggregate;
|
||||
|
||||
#if TREETRACE_ENABLED
|
||||
if( sqlite3TreeTrace & 0x200 ){
|
||||
@@ -7474,7 +7474,7 @@ int sqlite3Select(
|
||||
testcase( pParse->earlyCleanup );
|
||||
p->pOrderBy = 0;
|
||||
}
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
p->selFlags &= ~(u32)SF_Distinct;
|
||||
p->selFlags |= SF_NoopOrderBy;
|
||||
}
|
||||
sqlite3SelectPrep(pParse, p, 0);
|
||||
@@ -7513,7 +7513,7 @@ int sqlite3Select(
|
||||
** and leaving this flag set can cause errors if a compound sub-query
|
||||
** in p->pSrc is flattened into this query and this function called
|
||||
** again as part of compound SELECT processing. */
|
||||
p->selFlags &= ~SF_UFSrcCheck;
|
||||
p->selFlags &= ~(u32)SF_UFSrcCheck;
|
||||
}
|
||||
|
||||
if( pDest->eDest==SRT_Output ){
|
||||
@@ -8002,7 +8002,7 @@ int sqlite3Select(
|
||||
&& p->pWin==0
|
||||
#endif
|
||||
){
|
||||
p->selFlags &= ~SF_Distinct;
|
||||
p->selFlags &= ~(u32)SF_Distinct;
|
||||
pGroupBy = p->pGroupBy = sqlite3ExprListDup(db, pEList, 0);
|
||||
if( pGroupBy ){
|
||||
for(i=0; i<pGroupBy->nExpr; i++){
|
||||
|
@@ -3097,10 +3097,10 @@ struct Expr {
|
||||
/* Macros can be used to test, set, or clear bits in the
|
||||
** Expr.flags field.
|
||||
*/
|
||||
#define ExprHasProperty(E,P) (((E)->flags&(P))!=0)
|
||||
#define ExprHasAllProperty(E,P) (((E)->flags&(P))==(P))
|
||||
#define ExprSetProperty(E,P) (E)->flags|=(P)
|
||||
#define ExprClearProperty(E,P) (E)->flags&=~(P)
|
||||
#define ExprHasProperty(E,P) (((E)->flags&(u32)(P))!=0)
|
||||
#define ExprHasAllProperty(E,P) (((E)->flags&(u32)(P))==(u32)(P))
|
||||
#define ExprSetProperty(E,P) (E)->flags|=(u32)(P)
|
||||
#define ExprClearProperty(E,P) (E)->flags&=~(u32)(P)
|
||||
#define ExprAlwaysTrue(E) (((E)->flags&(EP_OuterON|EP_IsTrue))==EP_IsTrue)
|
||||
#define ExprAlwaysFalse(E) (((E)->flags&(EP_OuterON|EP_IsFalse))==EP_IsFalse)
|
||||
#define ExprIsFullSize(E) (((E)->flags&(EP_Reduced|EP_TokenOnly))==0)
|
||||
@@ -4908,7 +4908,7 @@ void sqlite3SubqueryColumnTypes(Parse*,Table*,Select*,char);
|
||||
Table *sqlite3ResultSetOfSelect(Parse*,Select*,char);
|
||||
void sqlite3OpenSchemaTable(Parse *, int);
|
||||
Index *sqlite3PrimaryKeyIndex(Table*);
|
||||
i16 sqlite3TableColumnToIndex(Index*, i16);
|
||||
i16 sqlite3TableColumnToIndex(Index*, int);
|
||||
#ifdef SQLITE_OMIT_GENERATED_COLUMNS
|
||||
# define sqlite3TableColumnToStorage(T,X) (X) /* No-op pass-through */
|
||||
# define sqlite3StorageColumnToTable(T,X) (X) /* No-op pass-through */
|
||||
|
@@ -36,14 +36,16 @@
|
||||
** * Terms in the GROUP BY or ORDER BY clauses of a SELECT statement.
|
||||
** * Terms in the VALUES clause of an INSERT statement
|
||||
**
|
||||
** The hard upper limit here is 32676. Most database people will
|
||||
** The hard upper limit here is 32767. Most database people will
|
||||
** tell you that in a well-normalized database, you usually should
|
||||
** not have more than a dozen or so columns in any table. And if
|
||||
** that is the case, there is no point in having more than a few
|
||||
** dozen values in any of the other situations described above.
|
||||
*/
|
||||
#ifndef SQLITE_MAX_COLUMN
|
||||
#if !defined(SQLITE_MAX_COLUMN)
|
||||
# define SQLITE_MAX_COLUMN 2000
|
||||
#elif SQLITE_MAX_COLUMN>32767
|
||||
# error SQLITE_MAX_COLUMN may not exceed 32767
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
@@ -192,8 +192,9 @@ int sqlite3LookasideUsed(sqlite3 *db, int *pHighwater){
|
||||
nInit += countLookasideSlots(db->lookaside.pSmallInit);
|
||||
nFree += countLookasideSlots(db->lookaside.pSmallFree);
|
||||
#endif /* SQLITE_OMIT_TWOSIZE_LOOKASIDE */
|
||||
if( pHighwater ) *pHighwater = db->lookaside.nSlot - nInit;
|
||||
return db->lookaside.nSlot - (nInit+nFree);
|
||||
assert( db->lookaside.nSlot >= nInit+nFree );
|
||||
if( pHighwater ) *pHighwater = (int)(db->lookaside.nSlot - nInit);
|
||||
return (int)(db->lookaside.nSlot - (nInit+nFree));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -246,7 +247,7 @@ int sqlite3_db_status(
|
||||
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)>=0 );
|
||||
assert( (op-SQLITE_DBSTATUS_LOOKASIDE_HIT)<3 );
|
||||
*pCurrent = 0;
|
||||
*pHighwater = db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT];
|
||||
*pHighwater = (int)db->lookaside.anStat[op-SQLITE_DBSTATUS_LOOKASIDE_HIT];
|
||||
if( resetFlag ){
|
||||
db->lookaside.anStat[op - SQLITE_DBSTATUS_LOOKASIDE_HIT] = 0;
|
||||
}
|
||||
|
@@ -995,7 +995,7 @@ int sqlite3WindowRewrite(Parse *pParse, Select *p){
|
||||
p->pWhere = 0;
|
||||
p->pGroupBy = 0;
|
||||
p->pHaving = 0;
|
||||
p->selFlags &= ~SF_Aggregate;
|
||||
p->selFlags &= ~(u32)SF_Aggregate;
|
||||
p->selFlags |= SF_WinRewrite;
|
||||
|
||||
/* Create the ORDER BY clause for the sub-select. This is the concatenation
|
||||
|
Reference in New Issue
Block a user