mirror of
https://github.com/sqlite/sqlite.git
synced 2024-11-23 23:57:41 +01:00
Avoid loading the entire record into memory for an sqlite3_preupdate_old() call that retrieves an IPK value.
FossilOrigin-Name: f9a90a0d2cd04e44dcc53e8bd270447f5acf9b4d679e23b67810875b6ee95ca7
This commit is contained in:
parent
c251e9edb2
commit
d770c86b82
55
ext/session/sessionblob.test
Normal file
55
ext/session/sessionblob.test
Normal file
@ -0,0 +1,55 @@
|
||||
# 2024 November 04
|
||||
#
|
||||
# The author disclaims copyright to this source code. In place of
|
||||
# a legal notice, here is a blessing:
|
||||
#
|
||||
# May you do good and not evil.
|
||||
# May you find forgiveness for yourself and forgive others.
|
||||
# May you share freely, never taking more than you give.
|
||||
#
|
||||
#***********************************************************************
|
||||
#
|
||||
|
||||
if {![info exists testdir]} {
|
||||
set testdir [file join [file dirname [info script]] .. .. test]
|
||||
}
|
||||
source [file join [file dirname [info script]] session_common.tcl]
|
||||
source $testdir/tester.tcl
|
||||
ifcapable !session {finish_test; return}
|
||||
|
||||
if {$::tcl_platform(pointerSize)<8} {
|
||||
finish_test
|
||||
return
|
||||
}
|
||||
|
||||
set testprefix sessionblob
|
||||
|
||||
forcedelete test.db2
|
||||
sqlite3 db2 test.db2
|
||||
|
||||
set NBLOB 2000000
|
||||
|
||||
do_execsql_test 1.0 {
|
||||
CREATE TABLE t1(a INTEGER PRIMARY KEY, b);
|
||||
INSERT INTO t1 VALUES(123, zeroblob($NBLOB));
|
||||
}
|
||||
|
||||
do_test 1.1 {
|
||||
sqlite3session S db main
|
||||
S attach t1
|
||||
} {}
|
||||
|
||||
set b2 [string repeat x 1000]
|
||||
do_test 1.2 {
|
||||
set ::blob [db incrblob t1 b 123]
|
||||
for {set ii 0} {$ii < $NBLOB} {incr ii [string length $b2]} {
|
||||
seek $::blob $ii
|
||||
puts -nonewline $::blob $b2
|
||||
}
|
||||
close $::blob
|
||||
} {}
|
||||
|
||||
S delete
|
||||
|
||||
finish_test
|
||||
|
22
manifest
22
manifest
@ -1,5 +1,5 @@
|
||||
C Fix\sthe\sOPFS\sVFS's\sxOpen()\sto\shonor\sthe\sread-only\sflag.\sFix\sthe\sOPFS\sSAHPool\sVFS\sto\senable\sre-installation\sof\sthe\sVFS\safter\scalling\sOpfsSAHPoolUtil.removeVfs().
|
||||
D 2024-10-17T12:17:18.240
|
||||
C Avoid\sloading\sthe\sentire\srecord\sinto\smemory\sfor\san\ssqlite3_preupdate_old()\scall\sthat\sretrieves\san\sIPK\svalue.
|
||||
D 2024-11-04T17:33:26.757
|
||||
F .fossil-settings/empty-dirs dbb81e8fc0401ac46a1491ab34a7f2c7c0452f2f06b54ebb845d024ca8283ef1
|
||||
F .fossil-settings/ignore-glob 35175cdfcf539b2318cb04a9901442804be81cd677d8b889fcc9149c21f239ea
|
||||
F LICENSE.md df5091916dbb40e6e9686186587125e1b2ff51f022cc334e886c19a0e9982724
|
||||
@ -568,6 +568,7 @@ F ext/session/session_speed_test.c dcf0ef58d76b70c8fbd9eab3be77cf9deb8bc1638fed8
|
||||
F ext/session/sessionalter.test 460bdac2832a550519f6bc32e5db2c0cee94f335870aaf25a3a403a81ab20e17
|
||||
F ext/session/sessionat.test 00c8badb35e43a2f12a716d2734a44d614ff62361979b6b85419035bc04b45ee
|
||||
F ext/session/sessionbig.test 47c381e7acfabeef17d98519a3080d69151723354d220afa2053852182ca7adf
|
||||
F ext/session/sessionblob.test 87faf667870b72f08e91969abd9f52a383ab7b514506ee194d64a39d8faff00a
|
||||
F ext/session/sessionchange.test 77c4702050f24270b58070e2cf01c95c3d232a3ef164b70f31974b386ce69903
|
||||
F ext/session/sessionconflict.test 8b8cbd98548e2e636ddc17d0986276f60e833fb865617dd4f88ea5bbe3a16b96
|
||||
F ext/session/sessiondiff.test ad13dd65664bae26744e1f18eb3cbd5588349b7e9118851d8f9364248d67bcec
|
||||
@ -826,9 +827,9 @@ F src/util.c 4d6d7ebfe6772a1b950c97bbb1d1a72ad4874617ec498ab8aa73b7f5a43e44bb
|
||||
F src/vacuum.c 604fcdaebe76f3497c855afcbf91b8fa5046b32de3045bab89cc008d68e40104
|
||||
F src/vdbe.c 3b1793c5d2235ae89b01ef051a33d7d2ad3704c71799653b112686735ad401ff
|
||||
F src/vdbe.h c2d78d15112c3fc5ab87f5e8e0b75d2db1c624409de2e858c3d1aafb1650bb4f
|
||||
F src/vdbeInt.h 949669dfd8a41550d27dcb905b494f2ccde9a2e6c1b0b04daa1227e2e74c2b2c
|
||||
F src/vdbeapi.c 80235ac380e9467fec1cb0883354d841f2a771976e766995f7e0c77f845406df
|
||||
F src/vdbeaux.c 6e37cb918506c28fe7657454fcbc2e01e66bfba4164f306c2f075fd5c5fef609
|
||||
F src/vdbeInt.h dc5a717607385857dd65e8661fc967aeee77b3c0bcbfb7c7acb1ea99e9007578
|
||||
F src/vdbeapi.c 1e6880bbc1b5930752ed1b67fbfcc751d4782e59763859249db699fb3e75a986
|
||||
F src/vdbeaux.c dd58f3dd2c0fee9b1a497201269511af633b67ce9ddfc0719c9b5b2b48a15d1e
|
||||
F src/vdbeblob.c 13f9287b55b6356b4b1845410382d6bede203ceb29ef69388a4a3d007ffacbe5
|
||||
F src/vdbemem.c 831a244831eaa45335f9ae276b50a7a82ee10d8c46c2c72492d4eb8c98d94d89
|
||||
F src/vdbesort.c 237840ca1947511fa59bd4e18b9eeae93f2af2468c34d2427b059f896230a547
|
||||
@ -2192,10 +2193,9 @@ F vsixtest/vsixtest.tcl 6a9a6ab600c25a91a7acc6293828957a386a8a93
|
||||
F vsixtest/vsixtest.vcxproj.data 2ed517e100c66dc455b492e1a33350c1b20fbcdc
|
||||
F vsixtest/vsixtest.vcxproj.filters 37e51ffedcdb064aad6ff33b6148725226cd608e
|
||||
F vsixtest/vsixtest_TemporaryKey.pfx e5b1b036facdb453873e7084e1cae9102ccc67a0
|
||||
P 242cb4bbee0707f470833d9f47efcfb5631f2302b9d48cffdbba63e64984827c
|
||||
Q +0a32624015f16fd881a4ecbb56b7833391028d327a95f4c899eee864ed7fe00d
|
||||
Q +b7f7a5deeae61920dbfec7606cf9014de711f959a285b29e12673abfd2f88646
|
||||
R 35167de4f82ff4a760245cc11df277ba
|
||||
U stephan
|
||||
Z 23bdd4bd7373bf8ed99c8093853b8c62
|
||||
P 63ee3584201fe3a126991e278bd4d7bf2d4ae5c4937d97e311686a69fd1cf69b
|
||||
Q +7f4de43733200beeb3ff0a70d51bbc68f5331895698ea95a82741cfd7bb66834
|
||||
R 1925f50d4d915494bbec6d09eb751f2d
|
||||
U dan
|
||||
Z bfb0012b12d420c95f9f9c70ce345eb0
|
||||
# Remove this line to create a well-formed Fossil manifest.
|
||||
|
@ -1 +1 @@
|
||||
63ee3584201fe3a126991e278bd4d7bf2d4ae5c4937d97e311686a69fd1cf69b
|
||||
f9a90a0d2cd04e44dcc53e8bd270447f5acf9b4d679e23b67810875b6ee95ca7
|
||||
|
@ -540,6 +540,7 @@ struct PreUpdate {
|
||||
int iBlobWrite; /* Value returned by preupdate_blobwrite() */
|
||||
i64 iKey1; /* First key value passed to hook */
|
||||
i64 iKey2; /* Second key value passed to hook */
|
||||
Mem oldipk; /* Memory cell holding "old" IPK value */
|
||||
Mem *aNew; /* Array of new.* values */
|
||||
Table *pTab; /* Schema object being updated */
|
||||
Index *pPk; /* PK index if pTab is WITHOUT ROWID */
|
||||
|
@ -2180,37 +2180,40 @@ 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 ){
|
||||
pMem = *ppValue = &p->oldipk;
|
||||
sqlite3VdbeMemSetInt64(pMem, p->iKey1);
|
||||
}else if( iIdx>=p->pUnpacked->nField ){
|
||||
*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);
|
||||
}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( rc!=SQLITE_OK ){
|
||||
sqlite3DbFree(db, aRec);
|
||||
goto preupdate_old_out;
|
||||
}
|
||||
p->aRecord = aRec;
|
||||
}
|
||||
|
||||
pMem = *ppValue = &p->pUnpacked->aMem[iIdx];
|
||||
if( iIdx>=p->pUnpacked->nField ){
|
||||
*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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -5525,6 +5525,7 @@ void sqlite3VdbePreUpdateHook(
|
||||
sqlite3DbFree(db, preupdate.aRecord);
|
||||
vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pUnpacked);
|
||||
vdbeFreeUnpacked(db, preupdate.keyinfo.nKeyField+1, preupdate.pNewUnpacked);
|
||||
sqlite3VdbeMemRelease(&preupdate.oldipk);
|
||||
if( preupdate.aNew ){
|
||||
int i;
|
||||
for(i=0; i<pCsr->nField; i++){
|
||||
|
Loading…
Reference in New Issue
Block a user