diff options
author | dan <Dan Kennedy> | 2024-09-18 15:02:27 +0000 |
---|---|---|
committer | dan <Dan Kennedy> | 2024-09-18 15:02:27 +0000 |
commit | 38b31a93b3ded0cc39eae8a8c07005606d129434 (patch) | |
tree | 45fdc23ec34d895db10757f73dc6359a5021fc43 /src/vdbeapi.c | |
parent | eaa50b866075f4c1a19065600e4f1bae059eb505 (diff) | |
download | sqlite-38b31a93b3ded0cc39eae8a8c07005606d129434.tar.gz sqlite-38b31a93b3ded0cc39eae8a8c07005606d129434.zip |
Fix the preupdate hook so that it works when the "old.*" row has a column with a non-NULL default value that was added by ALTER TABLE ADD COLUMN after the current record was created.
FossilOrigin-Name: 00a398cf900179aa5a8aab09fe4a671d99e7a31583282848ef39390f2ef246eb
Diffstat (limited to 'src/vdbeapi.c')
-rw-r--r-- | src/vdbeapi.c | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/src/vdbeapi.c b/src/vdbeapi.c index bf185dd3a..c129b9465 100644 --- a/src/vdbeapi.c +++ b/src/vdbeapi.c @@ -2222,7 +2222,28 @@ int sqlite3_preupdate_old(sqlite3 *db, int iIdx, sqlite3_value **ppValue){ if( iIdx==p->pTab->iPKey ){ sqlite3VdbeMemSetInt64(pMem, p->iKey1); }else if( iIdx>=p->pUnpacked->nField ){ - *ppValue = (sqlite3_value *)columnNullValue(); + /* 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 ){ + Expr *pDflt = p->pTab->u.tab.pDfltList->a[pCol->iDflt-1].pExpr; + sqlite3_value *pVal = 0; + 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 ); |