aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authordan <dan@noemail.net>2011-10-08 14:57:07 +0000
committerdan <dan@noemail.net>2011-10-08 14:57:07 +0000
commitf4ba1093568851a1320a84ce195b1dc08e8964c1 (patch)
treeb5f9d8ead01e28d393e847dafef0559911847c01 /src
parent08ccfaa1b183a7b365f0576d1aac0a5d8f66d755 (diff)
downloadsqlite-f4ba1093568851a1320a84ce195b1dc08e8964c1.tar.gz
sqlite-f4ba1093568851a1320a84ce195b1dc08e8964c1.zip
Add the SQLITE_DIRECT_OVERFLOW_READ compile time option.
FossilOrigin-Name: 2ab14a846727857175eac7961b7338c4d3b417ca
Diffstat (limited to 'src')
-rw-r--r--src/btree.c58
-rw-r--r--src/test_config.c6
2 files changed, 52 insertions, 12 deletions
diff --git a/src/btree.c b/src/btree.c
index 7e6e02f14..72d61cc26 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -3938,21 +3938,55 @@ static int accessPayload(
/* Need to read this page properly. It contains some of the
** range of data that is being read (eOp==0) or written (eOp!=0).
*/
- DbPage *pDbPage;
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ sqlite3_file *fd;
+#endif
int a = amt;
- rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
- if( rc==SQLITE_OK ){
- aPayload = sqlite3PagerGetData(pDbPage);
- nextPage = get4byte(aPayload);
- if( a + offset > ovflSize ){
- a = ovflSize - offset;
+ if( a + offset > ovflSize ){
+ a = ovflSize - offset;
+ }
+
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ /* If all the following are true:
+ **
+ ** 1) this is a read operation, and
+ ** 2) data is required from the start of this overflow page, and
+ ** 3) the database is file-backed, and
+ ** 4) there is no open write-transaction, and
+ ** 5) the database is not a WAL database,
+ **
+ ** then data can be read directly from the database file into the
+ ** output buffer, bypassing the page-cache altogether. This speeds
+ ** up loading large records that span many overflow pages.
+ */
+ if( eOp==0 /* (1) */
+ && offset==0 /* (2) */
+ && pBt->inTransaction==TRANS_READ /* (4) */
+ && (fd = sqlite3PagerFile(pBt->pPager))->pMethods /* (3) */
+ && pBt->pPage1->aData[19]==0x01 /* (5) */
+ ){
+ u8 aSave[4];
+ u8 *aWrite = &pBuf[-4];
+ memcpy(aSave, aWrite, 4);
+ rc = sqlite3OsRead(fd, aWrite, a+4, pBt->pageSize * (nextPage-1));
+ nextPage = get4byte(aWrite);
+ memcpy(aWrite, aSave, 4);
+ }else
+#endif
+
+ {
+ DbPage *pDbPage;
+ rc = sqlite3PagerGet(pBt->pPager, nextPage, &pDbPage);
+ if( rc==SQLITE_OK ){
+ aPayload = sqlite3PagerGetData(pDbPage);
+ nextPage = get4byte(aPayload);
+ rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
+ sqlite3PagerUnref(pDbPage);
+ offset = 0;
}
- rc = copyPayload(&aPayload[offset+4], pBuf, a, eOp, pDbPage);
- sqlite3PagerUnref(pDbPage);
- offset = 0;
- amt -= a;
- pBuf += a;
}
+ amt -= a;
+ pBuf += a;
}
}
}
diff --git a/src/test_config.c b/src/test_config.c
index 4c4dfa3d8..b0efe2324 100644
--- a/src/test_config.c
+++ b/src/test_config.c
@@ -55,6 +55,12 @@ static void set_options(Tcl_Interp *interp){
Tcl_SetVar2(interp, "sqlite_options", "debug", "0", TCL_GLOBAL_ONLY);
#endif
+#ifdef SQLITE_DIRECT_OVERFLOW_READ
+ Tcl_SetVar2(interp, "sqlite_options", "direct_read", "1", TCL_GLOBAL_ONLY);
+#else
+ Tcl_SetVar2(interp, "sqlite_options", "direct_read", "0", TCL_GLOBAL_ONLY);
+#endif
+
#ifdef SQLITE_DISABLE_DIRSYNC
Tcl_SetVar2(interp, "sqlite_options", "dirsync", "0", TCL_GLOBAL_ONLY);
#else