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 /ext/session | |
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 'ext/session')
-rw-r--r-- | ext/session/sessionfault3.test | 24 | ||||
-rw-r--r-- | ext/session/sqlite3session.c | 16 |
2 files changed, 33 insertions, 7 deletions
diff --git a/ext/session/sessionfault3.test b/ext/session/sessionfault3.test index af5a4cdb4..5af9c9ed7 100644 --- a/ext/session/sessionfault3.test +++ b/ext/session/sessionfault3.test @@ -56,4 +56,28 @@ do_faultsim_test 1 -faults oom* -prep { faultsim_test_result {0 {}} {1 SQLITE_NOMEM} } +#------------------------------------------------------------------------- +reset_db +do_execsql_test 2.0 { + CREATE TABLE t1(a INTEGER PRIMARY KEY, b); + INSERT INTO t1 VALUES(1, 'one'); + INSERT INTO t1 VALUES(2, 'two'); + ALTER TABLE t1 ADD COLUMN c DEFAULT 'abcdefghijklmnopqrstuvwxyz'; +} +faultsim_save_and_close + +do_faultsim_test 2 -faults oom-t* -prep { + faultsim_restore_and_reopen + db eval {SELECT * FROM sqlite_schema} +} -body { + sqlite3session S db main + S attach * + execsql { + DELETE FROM t1 WHERE a = 1; + } +} -test { + faultsim_test_result {0 {}} {1 SQLITE_NOMEM} + catch { S delete } +} + finish_test diff --git a/ext/session/sqlite3session.c b/ext/session/sqlite3session.c index 7a8132bfa..72f424923 100644 --- a/ext/session/sqlite3session.c +++ b/ext/session/sqlite3session.c @@ -48,8 +48,7 @@ struct sqlite3_session { int bEnable; /* True if currently recording */ int bIndirect; /* True if all changes are indirect */ int bAutoAttach; /* True to auto-attach tables */ - int bImplicitPK; /* True to handle tables with implicit PK */ - int rc; /* Non-zero if an error has occurred */ + int bImplicitPK; /* True to handle tables with implicit PK */ int rc; /* Non-zero if an error has occurred */ void *pFilterCtx; /* First argument to pass to xTableFilter */ int (*xTableFilter)(void *pCtx, const char *zTab); i64 nMalloc; /* Number of bytes of data allocated */ @@ -1757,16 +1756,19 @@ static void sessionPreupdateOneChange( for(i=0; i<(pTab->nCol-pTab->bRowid); i++){ sqlite3_value *p = 0; if( op!=SQLITE_INSERT ){ - TESTONLY(int trc = ) pSession->hook.xOld(pSession->hook.pCtx, i, &p); - assert( trc==SQLITE_OK ); + /* This may fail if the column has a non-NULL default and was added + ** using ALTER TABLE ADD COLUMN after this record was created. */ + rc = pSession->hook.xOld(pSession->hook.pCtx, i, &p); }else if( pTab->abPK[i] ){ TESTONLY(int trc = ) pSession->hook.xNew(pSession->hook.pCtx, i, &p); assert( trc==SQLITE_OK ); } - /* This may fail if SQLite value p contains a utf-16 string that must - ** be converted to utf-8 and an OOM error occurs while doing so. */ - rc = sessionSerializeValue(0, p, &nByte); + if( rc==SQLITE_OK ){ + /* This may fail if SQLite value p contains a utf-16 string that must + ** be converted to utf-8 and an OOM error occurs while doing so. */ + rc = sessionSerializeValue(0, p, &nByte); + } if( rc!=SQLITE_OK ) goto error_out; } if( pTab->bRowid ){ |