aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <Dan Kennedy>2024-09-18 15:02:27 +0000
committerdan <Dan Kennedy>2024-09-18 15:02:27 +0000
commit38b31a93b3ded0cc39eae8a8c07005606d129434 (patch)
tree45fdc23ec34d895db10757f73dc6359a5021fc43 /src
parenteaa50b866075f4c1a19065600e4f1bae059eb505 (diff)
downloadsqlite-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')
-rw-r--r--src/vdbeInt.h1
-rw-r--r--src/vdbeapi.c23
-rw-r--r--src/vdbeaux.c7
3 files changed, 30 insertions, 1 deletions
diff --git a/src/vdbeInt.h b/src/vdbeInt.h
index 2a23c3f28..b26860f3a 100644
--- a/src/vdbeInt.h
+++ b/src/vdbeInt.h
@@ -543,6 +543,7 @@ struct PreUpdate {
Mem *aNew; /* Array of new.* values */
Table *pTab; /* Schema object being updated */
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
+ sqlite3_value **apDflt; /* Array of default values, if required */
};
/*
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 );
diff --git a/src/vdbeaux.c b/src/vdbeaux.c
index f1e0cccdc..a66bdecff 100644
--- a/src/vdbeaux.c
+++ b/src/vdbeaux.c
@@ -5543,5 +5543,12 @@ void sqlite3VdbePreUpdateHook(
}
sqlite3DbNNFreeNN(db, preupdate.aNew);
}
+ if( preupdate.apDflt ){
+ int i;
+ for(i=0; i<pTab->nCol; i++){
+ sqlite3ValueFree(preupdate.apDflt[i]);
+ }
+ sqlite3DbFree(db, preupdate.apDflt);
+ }
}
#endif /* SQLITE_ENABLE_PREUPDATE_HOOK */