mirror of
https://github.com/sqlite/sqlite.git
synced 2025-08-05 15:55:57 +03:00
Avoid loading the entire record into memory for an sqlite3_preupdate_old() call that retrieves an IPK value.
FossilOrigin-Name: 7f4de43733200beeb3ff0a70d51bbc68f5331895698ea95a82741cfd7bb66834
This commit is contained in:
102
src/vdbeapi.c
102
src/vdbeapi.c
@@ -2197,60 +2197,64 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){
|
||||
goto preupdate_old_out;
|
||||
}
|
||||
|
||||
/* If the old.* record has not yet been loaded into memory, do so now. */
|
||||
if( p->pUnpacked==0 ){
|
||||
u32 nRec;
|
||||
u8 *aRec;
|
||||
|
||||
assert( p->pCsr->eCurType==CURTYPE_BTREE );
|
||||
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
|
||||
aRec = sqlite3DbMallocRaw(db, nRec);
|
||||
if( !aRec ) goto preupdate_old_out;
|
||||
rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
|
||||
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3DbFree(db, aRec);
|
||||
goto preupdate_old_out;
|
||||
}
|
||||
p->aRecord = aRec;
|
||||
}
|
||||
|
||||
pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
|
||||
if( iIdx==p->pTab->iPKey ){
|
||||
*ppValue = pMem = &p->oldipk;
|
||||
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
|
||||
}else if( iIdx>=p->pUnpacked->nField ){
|
||||
/* This occurs when the table has been extended using ALTER TABLE
|
||||
** ADD COLUMN. The value to return is the default value of the column. */
|
||||
Column *pCol = &p->pTab->aCol[iIdx];
|
||||
if( pCol->iDflt>0 ){
|
||||
if( p->apDflt==0 ){
|
||||
int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
|
||||
p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
|
||||
if( p->apDflt==0 ) goto preupdate_old_out;
|
||||
}else{
|
||||
|
||||
/* If the old.* record has not yet been loaded into memory, do so now. */
|
||||
if( p->pUnpacked==0 ){
|
||||
u32 nRec;
|
||||
u8 *aRec;
|
||||
|
||||
assert( p->pCsr->eCurType==CURTYPE_BTREE );
|
||||
nRec = sqlite3BtreePayloadSize(p->pCsr->uc.pCursor);
|
||||
aRec = sqlite3DbMallocRaw(db, nRec);
|
||||
if( !aRec ) goto preupdate_old_out;
|
||||
rc = sqlite3BtreePayload(p->pCsr->uc.pCursor, 0, nRec, aRec);
|
||||
if( rc==SQLITE_OK ){
|
||||
p->pUnpacked = vdbeUnpackRecord(&p->keyinfo, nRec, aRec);
|
||||
if( !p->pUnpacked ) rc = SQLITE_NOMEM;
|
||||
}
|
||||
if( p->apDflt[iIdx]==0 ){
|
||||
sqlite3_value *pVal = 0;
|
||||
Expr *pDflt;
|
||||
assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
|
||||
pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
|
||||
rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
|
||||
if( rc==SQLITE_OK && pVal==0 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
p->apDflt[iIdx] = pVal;
|
||||
if( rc!=SQLITE_OK ){
|
||||
sqlite3DbFree(db, aRec);
|
||||
goto preupdate_old_out;
|
||||
}
|
||||
*ppValue = p->apDflt[iIdx];
|
||||
}else{
|
||||
*ppValue = (sqlite3_value *)columnNullValue();
|
||||
p->aRecord = aRec;
|
||||
}
|
||||
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
|
||||
if( pMem->flags & (MEM_Int|MEM_IntReal) ){
|
||||
testcase( pMem->flags & MEM_Int );
|
||||
testcase( pMem->flags & MEM_IntReal );
|
||||
sqlite3VdbeMemRealify(pMem);
|
||||
|
||||
pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
|
||||
if( iIdx>=p->pUnpacked->nField ){
|
||||
/* This occurs when the table has been extended using ALTER TABLE
|
||||
** ADD COLUMN. The value to return is the default value of the column. */
|
||||
Column *pCol = &p->pTab->aCol[iIdx];
|
||||
if( pCol->iDflt>0 ){
|
||||
if( p->apDflt==0 ){
|
||||
int nByte = sizeof(sqlite3_value*)*p->pTab->nCol;
|
||||
p->apDflt = (sqlite3_value**)sqlite3DbMallocZero(db, nByte);
|
||||
if( p->apDflt==0 ) goto preupdate_old_out;
|
||||
}
|
||||
if( p->apDflt[iIdx]==0 ){
|
||||
sqlite3_value *pVal = 0;
|
||||
Expr *pDflt;
|
||||
assert( p->pTab!=0 && IsOrdinaryTable(p->pTab) );
|
||||
pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr;
|
||||
rc = sqlite3ValueFromExpr(db, pDflt, ENC(db), pCol->affinity, &pVal);
|
||||
if( rc==SQLITE_OK && pVal==0 ){
|
||||
rc = SQLITE_CORRUPT_BKPT;
|
||||
}
|
||||
p->apDflt[iIdx] = pVal;
|
||||
}
|
||||
*ppValue = p->apDflt[iIdx];
|
||||
}else{
|
||||
*ppValue = (sqlite3_value *)columnNullValue();
|
||||
}
|
||||
}else if( p->pTab->aCol[iIdx].affinity==SQLITE_AFF_REAL ){
|
||||
if( pMem->flags & (MEM_Int|MEM_IntReal) ){
|
||||
testcase( pMem->flags & MEM_Int );
|
||||
testcase( pMem->flags & MEM_IntReal );
|
||||
sqlite3VdbeMemRealify(pMem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user