diff --git a/manifest b/manifest
index 1d670ad187..53517d7138 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\stypos\sthe\ssource\sto\swebpages\shtml\sfiles.\s(CVS\s703)
-D 2002-08-06T12:05:00
+C Fix\sfor\sticket\s#9:\sAdd\sthe\sability\sto\sread\slittle-endian\sdatabase\sfiles\nfrom\sa\sbig-endian\smachine\sand\svice\sversa.\s(CVS\s704)
+D 2002-08-11T20:10:47
F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c
F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
@@ -18,8 +18,8 @@ F publish.sh 29f86624db9253353ae159a9e015f81e16f9dd5b
F spec.template 238f7db425a78dc1bb7682e56e3834c7270a3f5e
F sqlite.1 83f4a9d37bdf2b7ef079a82d54eaf2e3509ee6ea
F src/TODO af7f3cab0228e34149cf98e073aa83d45878e7e6
-F src/btree.c f014b682e184876aba5df14a68f96594e0b7ae00
-F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3
+F src/btree.c c7669b179d452999dc39bf8a931e29a5d7151f96
+F src/btree.h 0ca6c2631338df62e4f7894252d9347ae234eda9
F src/build.c 0d661e653e02ce8037917c35403d9f0ff4418e6e
F src/delete.c c9f59ee217e062eb9de7b64b76b5cfff42b2f028
F src/encode.c 346b12b46148506c32038524b95c4631ab46d760
@@ -34,7 +34,7 @@ F src/os.c 9665974085ebe1d40d56d1145045b3d64f12cbce
F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10
F src/pager.c b8415b02a2a5c4e9d8bfd45311a5f15e785c7f1f
F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e
-F src/parse.y 5307e1a7b26241991934d4b50ae70980f3f2aca9
+F src/parse.y 66e7da55b34b57f81ca07e50d1dcc430b1c1bf74
F src/printf.c 06f4c8725063e0faf0e34824ab70feace7146bf7
F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe
F src/select.c f504cc542229f472b3f15cefe5d6782494ee8d92
@@ -46,7 +46,7 @@ F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63
F src/tclsqlite.c c502819c209011659e1bbb428cbac5670cce7f79
F src/test1.c 456cb080db85056be723e770435d9509afc3a83a
F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730
-F src/test3.c fda085b4cdd5a2d7f65786ce679036e955f4bfa2
+F src/test3.c b99d5ab68ee672f1fbb00520723b5c21bac35822
F src/threadtest.c 72bce0a284647314847bbea44616ceb056bfb77f
F src/tokenize.c b5500e193a82b5b9888fbf947efd90d3b4858178
F src/trigger.c d88ab4d68d68955c217b38fb6717e090fbbf54a4
@@ -55,7 +55,7 @@ F src/util.c 7a99e754c44dd220e881122e30581c08b6d6adef
F src/vdbe.c aa647946d08e54b71bfff9049ad31135b7af4a8e
F src/vdbe.h a9292f2b5fcecef924fa255fb74609e9cbc776c2
F src/where.c 0fde349514717a55ff6a27ed2c6e914ce98a1512
-F test/all.test f296d27fff6aca72348af15092154f879d1fc7d4
+F test/all.test 9a6eb262393f74cb7fb09b17156491a34b941fe3
F test/bigrow.test 8ab252dba108f12ad64e337b0f2ff31a807ac578
F test/btree.test bf326f546a666617367a7033fa2c07451bd4f8e1
F test/btree2.test e3b81ec33dc2f89b3e6087436dfe605b870c9080
@@ -108,7 +108,7 @@ F test/trigger4.test 9a5c1406344d743020c2753ae8d6dfe6eb75f818
F test/unique.test 572aa791327c1e8d797932263e9d67f176cfdb44
F test/update.test 7ffb062d580a972e7870d0f51d5af3ab9bfeae08
F test/vacuum.test 059871b312eb910bbe49dafde1d01490cc2c6bbe
-F test/version.test 946589ce15d214443b8377b69d176551e6b32b34
+F test/version.test f6a264303faba43a865714072d49f8d44c69e274
F test/view.test 3afca084dab44c7a5772d3c6a326adf93ad52050
F test/where.test 1f87bec674bf85d74ac1cc5b2cd3d89be1e87b1d
F tool/diffdb.c 7524b1b5df217c20cd0431f6789851a4e0cb191b
@@ -133,17 +133,17 @@ F www/conflict.tcl 81dd21f9a679e60aae049e9dd8ab53d59570cda2
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
F www/download.tcl 29aa6679ca29621d10613f60ebbbda18f4b91c49
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
-F www/faq.tcl fbe9f4a5468a9630e723f0a9cc5abe3402eda39b
+F www/faq.tcl 5e3f71ced26a6dc863bd8d7afd711bf16c99acf6
F www/formatchng.tcl 502847353450adaf76d187d87374bce20dd07e0e
-F www/index.tcl 17384c30e0ddccaac4cd775be4e3b18fa8a248eb
+F www/index.tcl 72684d0dbad02f58edd27e71ccf11a797c4bd6e9
F www/lang.tcl 8c3d0bda030f110c754b5edbad75eddf5dbe2ed1
F www/mingw.tcl f1c7c0a7f53387dd9bb4f8c7e8571b7561510ebc
-F www/opcode.tcl bdec8ef9f100dbd87bbef8976c54b88e43fd8ccc
+F www/opcode.tcl 33c5f2061a05c5d227c72b84c080b3bf74c74f8b
F www/speed.tcl 7fc83f1b018e1ecc451838449542c3079ed12425
F www/sqlite.tcl ae3dcfb077e53833b59d4fcc94d8a12c50a44098
F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P 18745c67acdf7ebec378f5538174117970e9f5cc
-R 758cf5a969dba907709ff2017be34dc3
+P 61bb3af7405aa7b54f3e5519537ea483879eed39
+R c9670f7561402c0ee88efdafe6f79692
U drh
-Z 49ea59ad7dbd18b80f8590758e88954f
+Z 718b1cc10029822de3a6f0da6b7466de
diff --git a/manifest.uuid b/manifest.uuid
index 01e5be5f8b..472ad48ee1 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-61bb3af7405aa7b54f3e5519537ea483879eed39
\ No newline at end of file
+ce4b943bf68c160445a58ffccfbabbbd30d9829b
\ No newline at end of file
diff --git a/src/btree.c b/src/btree.c
index ee7fd5f130..935e527662 100644
--- a/src/btree.c
+++ b/src/btree.c
@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
-** $Id: btree.c,v 1.68 2002/07/18 11:01:48 drh Exp $
+** $Id: btree.c,v 1.69 2002/08/11 20:10:47 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -54,6 +54,30 @@
#include "btree.h"
#include
+/*
+** Macros used for byteswapping. B is a pointer to the Btree
+** structure. This is needed to access the Btree.needSwab boolean
+** in order to tell if byte swapping is needed or not.
+** X is an unsigned integer. SWAB16 byte swaps a 16-bit integer.
+** SWAB32 byteswaps a 32-bit integer.
+*/
+#define SWAB16(B,X) ((B)->needSwab? swab16(X) : (X))
+#define SWAB32(B,X) ((B)->needSwab? swab32(X) : (X))
+#define SWAB_ADD(B,X,A) \
+ if((B)->needSwab){ X=swab32(swab32(X)+A); }else{ X += (A); }
+
+/*
+** The following global variable - available only if SQLITE_TEST is
+** defined - is used to determine whether new databases are created in
+** native byte order or in non-native byte order. Non-native byte order
+** databases are created for testing purposes only. Under normal operation,
+** only native byte-order databases should be created, but we should be
+** able to read or write existing databases regardless of the byteorder.
+*/
+#ifdef SQLITE_TEST
+int btree_native_byte_order = 1;
+#endif
+
/*
** Forward declarations of structures used only in this file.
*/
@@ -167,8 +191,8 @@ struct CellHdr {
** space. The following macros reassembly a key or data size back
** into an integer.
*/
-#define NKEY(h) (h.nKey + h.nKeyHi*65536)
-#define NDATA(h) (h.nData + h.nDataHi*65536)
+#define NKEY(b,h) (SWAB16(b,h.nKey) + h.nKeyHi*65536)
+#define NDATA(b,h) (SWAB16(b,h.nData) + h.nDataHi*65536)
/*
** The minimum size of a complete Cell. The Cell must contain a header
@@ -318,6 +342,7 @@ struct Btree {
u8 inTrans; /* True if a transaction is in progress */
u8 inCkpt; /* True if there is a checkpoint on the transaction */
u8 readOnly; /* True if the underlying file is readonly */
+ u8 needSwab; /* Need to byte-swapping */
Hash locks; /* Key: root page number. Data: lock count */
};
typedef Btree Bt;
@@ -338,6 +363,17 @@ struct BtCursor {
u8 iMatch; /* compare result from last sqliteBtreeMoveto() */
};
+/*
+** Routines for byte swapping.
+*/
+u16 swab16(u16 x){
+ return ((x & 0xff)<<8) | ((x>>8)&0xff);
+}
+u32 swab32(u32 x){
+ return ((x & 0xff)<<24) | ((x & 0xff00)<<8) |
+ ((x>>8) & 0xff00) | ((x>>24)&0xff);
+}
+
/*
** Compute the total number of bytes that a Cell needs on the main
** database page. The number returned includes the Cell header,
@@ -345,8 +381,8 @@ struct BtCursor {
** applicable). Additional space allocated on overflow pages
** is NOT included in the value returned from this routine.
*/
-static int cellSize(Cell *pCell){
- int n = NKEY(pCell->h) + NDATA(pCell->h);
+static int cellSize(Btree *pBt, Cell *pCell){
+ int n = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
if( n>MX_LOCAL_PAYLOAD ){
n = MX_LOCAL_PAYLOAD + sizeof(Pgno);
}else{
@@ -361,7 +397,7 @@ static int cellSize(Cell *pCell){
** beginning of the page and all free space is collected
** into one big FreeBlk at the end of the page.
*/
-static void defragmentPage(MemPage *pPage){
+static void defragmentPage(Btree *pBt, MemPage *pPage){
int pc, i, n;
FreeBlk *pFBlk;
char newPage[SQLITE_PAGE_SIZE];
@@ -369,7 +405,7 @@ static void defragmentPage(MemPage *pPage){
assert( sqlitepager_iswriteable(pPage) );
assert( pPage->isInit );
pc = sizeof(PageHdr);
- pPage->u.hdr.firstCell = pc;
+ pPage->u.hdr.firstCell = SWAB16(pBt, pc);
memcpy(newPage, pPage->u.aDisk, pc);
for(i=0; inCell; i++){
Cell *pCell = pPage->apCell[i];
@@ -379,8 +415,8 @@ static void defragmentPage(MemPage *pPage){
assert( Addr(pCell) > Addr(pPage) );
assert( Addr(pCell) < Addr(pPage) + SQLITE_PAGE_SIZE );
- n = cellSize(pCell);
- pCell->h.iNext = pc + n;
+ n = cellSize(pBt, pCell);
+ pCell->h.iNext = SWAB16(pBt, pc + n);
memcpy(&newPage[pc], pCell, n);
pPage->apCell[i] = (Cell*)&pPage->u.aDisk[pc];
pc += n;
@@ -391,9 +427,9 @@ static void defragmentPage(MemPage *pPage){
pPage->apCell[pPage->nCell-1]->h.iNext = 0;
}
pFBlk = (FreeBlk*)&pPage->u.aDisk[pc];
- pFBlk->iSize = SQLITE_PAGE_SIZE - pc;
+ pFBlk->iSize = SWAB16(pBt, SQLITE_PAGE_SIZE - pc);
pFBlk->iNext = 0;
- pPage->u.hdr.firstFree = pc;
+ pPage->u.hdr.firstFree = SWAB16(pBt, pc);
memset(&pFBlk[1], 0, SQLITE_PAGE_SIZE - pc - sizeof(FreeBlk));
}
@@ -410,38 +446,39 @@ static void defragmentPage(MemPage *pPage){
** calls defragementPage() to consolidate all free space before
** allocating the new chunk.
*/
-static int allocateSpace(MemPage *pPage, int nByte){
+static int allocateSpace(Btree *pBt, MemPage *pPage, int nByte){
FreeBlk *p;
u16 *pIdx;
int start;
int cnt = 0;
+ int iSize;
assert( sqlitepager_iswriteable(pPage) );
assert( nByte==ROUNDUP(nByte) );
assert( pPage->isInit );
if( pPage->nFreeisOverfull ) return 0;
pIdx = &pPage->u.hdr.firstFree;
- p = (FreeBlk*)&pPage->u.aDisk[*pIdx];
- while( p->iSizeu.aDisk[SWAB16(pBt, *pIdx)];
+ while( (iSize = SWAB16(pBt, p->iSize))iNext==0 ){
- defragmentPage(pPage);
+ defragmentPage(pBt, pPage);
pIdx = &pPage->u.hdr.firstFree;
}else{
pIdx = &p->iNext;
}
- p = (FreeBlk*)&pPage->u.aDisk[*pIdx];
+ p = (FreeBlk*)&pPage->u.aDisk[SWAB16(pBt, *pIdx)];
}
- if( p->iSize==nByte ){
- start = *pIdx;
+ if( iSize==nByte ){
+ start = SWAB16(pBt, *pIdx);
*pIdx = p->iNext;
}else{
FreeBlk *pNew;
- start = *pIdx;
+ start = SWAB16(pBt, *pIdx);
pNew = (FreeBlk*)&pPage->u.aDisk[start + nByte];
pNew->iNext = p->iNext;
- pNew->iSize = p->iSize - nByte;
- *pIdx = start + nByte;
+ pNew->iSize = SWAB16(pBt, iSize - nByte);
+ *pIdx = SWAB16(pBt, start + nByte);
}
pPage->nFree -= nByte;
return start;
@@ -456,44 +493,50 @@ static int allocateSpace(MemPage *pPage, int nByte){
** Most of the effort here is involved in coalesing adjacent
** free blocks into a single big free block.
*/
-static void freeSpace(MemPage *pPage, int start, int size){
+static void freeSpace(Btree *pBt, MemPage *pPage, int start, int size){
int end = start + size;
u16 *pIdx, idx;
FreeBlk *pFBlk;
FreeBlk *pNew;
FreeBlk *pNext;
+ int iSize;
assert( sqlitepager_iswriteable(pPage) );
assert( size == ROUNDUP(size) );
assert( start == ROUNDUP(start) );
assert( pPage->isInit );
pIdx = &pPage->u.hdr.firstFree;
- idx = *pIdx;
+ idx = SWAB16(pBt, *pIdx);
while( idx!=0 && idxu.aDisk[idx];
- if( idx + pFBlk->iSize == start ){
- pFBlk->iSize += size;
- if( idx + pFBlk->iSize == pFBlk->iNext ){
- pNext = (FreeBlk*)&pPage->u.aDisk[pFBlk->iNext];
- pFBlk->iSize += pNext->iSize;
+ iSize = SWAB16(pBt, pFBlk->iSize);
+ if( idx + iSize == start ){
+ pFBlk->iSize = SWAB16(pBt, iSize + size);
+ if( idx + iSize + size == SWAB16(pBt, pFBlk->iNext) ){
+ pNext = (FreeBlk*)&pPage->u.aDisk[idx + iSize + size];
+ if( pBt->needSwab ){
+ pFBlk->iSize = swab16(swab16(pNext->iSize)+iSize+size);
+ }else{
+ pFBlk->iSize += pNext->iSize;
+ }
pFBlk->iNext = pNext->iNext;
}
pPage->nFree += size;
return;
}
pIdx = &pFBlk->iNext;
- idx = *pIdx;
+ idx = SWAB16(pBt, *pIdx);
}
pNew = (FreeBlk*)&pPage->u.aDisk[start];
if( idx != end ){
- pNew->iSize = size;
- pNew->iNext = idx;
+ pNew->iSize = SWAB16(pBt, size);
+ pNew->iNext = SWAB16(pBt, idx);
}else{
pNext = (FreeBlk*)&pPage->u.aDisk[idx];
- pNew->iSize = size + pNext->iSize;
+ pNew->iSize = SWAB16(pBt, size + SWAB16(pBt, pNext->iSize));
pNew->iNext = pNext->iNext;
}
- *pIdx = start;
+ *pIdx = SWAB16(pBt, start);
pPage->nFree += size;
}
@@ -511,7 +554,7 @@ static void freeSpace(MemPage *pPage, int start, int size){
** guarantee that the page is well-formed. It only shows that
** we failed to detect any corruption.
*/
-static int initPage(MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
+static int initPage(Bt *pBt, MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
int idx; /* An index into pPage->u.aDisk[] */
Cell *pCell; /* A pointer to a Cell in pPage->u.aDisk[] */
FreeBlk *pFBlk; /* A pointer to a free block in pPage->u.aDisk[] */
@@ -530,27 +573,29 @@ static int initPage(MemPage *pPage, Pgno pgnoThis, MemPage *pParent){
pPage->isInit = 1;
pPage->nCell = 0;
freeSpace = USABLE_SPACE;
- idx = pPage->u.hdr.firstCell;
+ idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx!=0 ){
if( idx>SQLITE_PAGE_SIZE-MIN_CELL_SIZE ) goto page_format_error;
if( idxu.aDisk[idx];
- sz = cellSize(pCell);
+ sz = cellSize(pBt, pCell);
if( idx+sz > SQLITE_PAGE_SIZE ) goto page_format_error;
freeSpace -= sz;
pPage->apCell[pPage->nCell++] = pCell;
- idx = pCell->h.iNext;
+ idx = SWAB16(pBt, pCell->h.iNext);
}
pPage->nFree = 0;
- idx = pPage->u.hdr.firstFree;
+ idx = SWAB16(pBt, pPage->u.hdr.firstFree);
while( idx!=0 ){
+ int iNext;
if( idx>SQLITE_PAGE_SIZE-sizeof(FreeBlk) ) goto page_format_error;
if( idxu.aDisk[idx];
- pPage->nFree += pFBlk->iSize;
- if( pFBlk->iNext>0 && pFBlk->iNext <= idx ) goto page_format_error;
- idx = pFBlk->iNext;
+ pPage->nFree += SWAB16(pBt, pFBlk->iSize);
+ iNext = SWAB16(pBt, pFBlk->iNext);
+ if( iNext>0 && iNext <= idx ) goto page_format_error;
+ idx = iNext;
}
if( pPage->nCell==0 && pPage->nFree==0 ){
/* As a special case, an uninitialized root page appears to be
@@ -568,18 +613,18 @@ page_format_error:
** Set up a raw page so that it looks like a database page holding
** no entries.
*/
-static void zeroPage(MemPage *pPage){
+static void zeroPage(Btree *pBt, MemPage *pPage){
PageHdr *pHdr;
FreeBlk *pFBlk;
assert( sqlitepager_iswriteable(pPage) );
memset(pPage, 0, SQLITE_PAGE_SIZE);
pHdr = &pPage->u.hdr;
pHdr->firstCell = 0;
- pHdr->firstFree = sizeof(*pHdr);
+ pHdr->firstFree = SWAB16(pBt, sizeof(*pHdr));
pFBlk = (FreeBlk*)&pHdr[1];
pFBlk->iNext = 0;
- pFBlk->iSize = SQLITE_PAGE_SIZE - sizeof(*pHdr);
- pPage->nFree = pFBlk->iSize;
+ pPage->nFree = SQLITE_PAGE_SIZE - sizeof(*pHdr);
+ pFBlk->iSize = SWAB16(pBt, pPage->nFree);
pPage->nCell = 0;
pPage->isOverfull = 0;
}
@@ -694,10 +739,12 @@ static int lockBtree(Btree *pBt){
*/
if( sqlitepager_pagecount(pBt->pPager)>0 ){
PageOne *pP1 = pBt->page1;
- if( strcmp(pP1->zMagic,zMagicHeader)!=0 || pP1->iMagic!=MAGIC ){
+ if( strcmp(pP1->zMagic,zMagicHeader)!=0 ||
+ (pP1->iMagic!=MAGIC && swab32(pP1->iMagic)!=MAGIC) ){
rc = SQLITE_CORRUPT;
goto page1_init_failed;
}
+ pBt->needSwab = pP1->iMagic!=MAGIC;
}
return rc;
@@ -746,8 +793,19 @@ static int newDatabase(Btree *pBt){
return rc;
}
strcpy(pP1->zMagic, zMagicHeader);
+#ifdef SQLITE_TEST
+ if( btree_native_byte_order ){
+ pP1->iMagic = MAGIC;
+ pBt->needSwab = 0;
+ }else{
+ pP1->iMagic = swab32(MAGIC);
+ pBt->needSwab = 1;
+ }
+#else
pP1->iMagic = MAGIC;
- zeroPage(pRoot);
+ pBt->needSwab = 0;
+#endif
+ zeroPage(pBt, pRoot);
sqlitepager_unref(pRoot);
return SQLITE_OK;
}
@@ -936,7 +994,7 @@ int sqliteBtreeCursor(Btree *pBt, int iTable, int wrFlag, BtCursor **ppCur){
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
- rc = initPage(pCur->pPage, pCur->pgnoRoot, 0);
+ rc = initPage(pBt, pCur->pPage, pCur->pgnoRoot, 0);
if( rc!=SQLITE_OK ){
goto create_cursor_exception;
}
@@ -1035,7 +1093,7 @@ int sqliteBtreeKeySize(BtCursor *pCur, int *pSize){
*pSize = 0;
}else{
pCell = pPage->apCell[pCur->idx];
- *pSize = NKEY(pCell->h);
+ *pSize = NKEY(pCur->pBt, pCell->h);
}
return SQLITE_OK;
}
@@ -1052,6 +1110,7 @@ static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
char *aPayload;
Pgno nextPage;
int rc;
+ Btree *pBt = pCur->pBt;
assert( pCur!=0 && pCur->pPage!=0 );
assert( pCur->idx>=0 && pCur->idxpPage->nCell );
aPayload = pCur->pPage->apCell[pCur->idx]->aPayload;
@@ -1071,15 +1130,15 @@ static int getPayload(BtCursor *pCur, int offset, int amt, char *zBuf){
offset -= MX_LOCAL_PAYLOAD;
}
if( amt>0 ){
- nextPage = pCur->pPage->apCell[pCur->idx]->ovfl;
+ nextPage = SWAB32(pBt, pCur->pPage->apCell[pCur->idx]->ovfl);
}
while( amt>0 && nextPage ){
OverflowPage *pOvfl;
- rc = sqlitepager_get(pCur->pBt->pPager, nextPage, (void**)&pOvfl);
+ rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
if( rc!=0 ){
return rc;
}
- nextPage = pOvfl->iNext;
+ nextPage = SWAB32(pBt, pOvfl->iNext);
if( offset OVERFLOW_SIZE ){
@@ -1121,8 +1180,8 @@ int sqliteBtreeKey(BtCursor *pCur, int offset, int amt, char *zBuf){
return 0;
}
pCell = pPage->apCell[pCur->idx];
- if( amt+offset > NKEY(pCell->h) ){
- amt = NKEY(pCell->h) - offset;
+ if( amt+offset > NKEY(pCur->pBt, pCell->h) ){
+ amt = NKEY(pCur->pBt, pCell->h) - offset;
if( amt<=0 ){
return 0;
}
@@ -1147,7 +1206,7 @@ int sqliteBtreeDataSize(BtCursor *pCur, int *pSize){
*pSize = 0;
}else{
pCell = pPage->apCell[pCur->idx];
- *pSize = NDATA(pCell->h);
+ *pSize = NDATA(pCur->pBt, pCell->h);
}
return SQLITE_OK;
}
@@ -1163,6 +1222,7 @@ int sqliteBtreeDataSize(BtCursor *pCur, int *pSize){
int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
Cell *pCell;
MemPage *pPage;
+ int nData;
if( amt<0 ) return 0;
if( offset<0 ) return 0;
@@ -1172,13 +1232,14 @@ int sqliteBtreeData(BtCursor *pCur, int offset, int amt, char *zBuf){
return 0;
}
pCell = pPage->apCell[pCur->idx];
- if( amt+offset > NDATA(pCell->h) ){
- amt = NDATA(pCell->h) - offset;
+ nData = NDATA(pCur->pBt, pCell->h);
+ if( amt+offset > nData ){
+ amt = nData - offset;
if( amt<=0 ){
return 0;
}
}
- getPayload(pCur, offset + NKEY(pCell->h), amt, zBuf);
+ getPayload(pCur, offset + NKEY(pCur->pBt, pCell->h), amt, zBuf);
return amt;
}
@@ -1213,12 +1274,13 @@ int sqliteBtreeKeyCompare(
Pgno nextPage;
int n, c, rc, nLocal;
Cell *pCell;
+ Btree *pBt = pCur->pBt;
const char *zKey = (const char*)pKey;
assert( pCur->pPage );
assert( pCur->idx>=0 && pCur->idxpPage->nCell );
pCell = pCur->pPage->apCell[pCur->idx];
- nLocal = NKEY(pCell->h) - nIgnore;
+ nLocal = NKEY(pBt, pCell->h) - nIgnore;
if( nLocal<0 ) nLocal = 0;
n = nKeyMX_LOCAL_PAYLOAD ){
@@ -1232,17 +1294,17 @@ int sqliteBtreeKeyCompare(
zKey += n;
nKey -= n;
nLocal -= n;
- nextPage = pCell->ovfl;
+ nextPage = SWAB32(pBt, pCell->ovfl);
while( nKey>0 && nLocal>0 ){
OverflowPage *pOvfl;
if( nextPage==0 ){
return SQLITE_CORRUPT;
}
- rc = sqlitepager_get(pCur->pBt->pPager, nextPage, (void**)&pOvfl);
+ rc = sqlitepager_get(pBt->pPager, nextPage, (void**)&pOvfl);
if( rc ){
return rc;
}
- nextPage = pOvfl->iNext;
+ nextPage = SWAB32(pBt, pOvfl->iNext);
n = nKeyOVERFLOW_SIZE ){
n = OVERFLOW_SIZE;
@@ -1270,10 +1332,11 @@ int sqliteBtreeKeyCompare(
static int moveToChild(BtCursor *pCur, int newPgno){
int rc;
MemPage *pNewPage;
+ Btree *pBt = pCur->pBt;
- rc = sqlitepager_get(pCur->pBt->pPager, newPgno, (void**)&pNewPage);
+ rc = sqlitepager_get(pBt->pPager, newPgno, (void**)&pNewPage);
if( rc ) return rc;
- rc = initPage(pNewPage, newPgno, pCur->pPage);
+ rc = initPage(pBt, pNewPage, newPgno, pCur->pPage);
if( rc ) return rc;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNewPage;
@@ -1300,6 +1363,7 @@ static int moveToParent(BtCursor *pCur){
sqlitepager_unref(pCur->pPage);
pCur->pPage = pParent;
pCur->idx = pParent->nCell;
+ oldPgno = SWAB32(pCur->pBt, oldPgno);
for(i=0; inCell; i++){
if( pParent->apCell[i]->h.leftChild==oldPgno ){
pCur->idx = i;
@@ -1315,10 +1379,11 @@ static int moveToParent(BtCursor *pCur){
static int moveToRoot(BtCursor *pCur){
MemPage *pNew;
int rc;
+ Btree *pBt = pCur->pBt;
- rc = sqlitepager_get(pCur->pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
+ rc = sqlitepager_get(pBt->pPager, pCur->pgnoRoot, (void**)&pNew);
if( rc ) return rc;
- rc = initPage(pNew, pCur->pgnoRoot, 0);
+ rc = initPage(pBt, pNew, pCur->pgnoRoot, 0);
if( rc ) return rc;
sqlitepager_unref(pCur->pPage);
pCur->pPage = pNew;
@@ -1335,7 +1400,7 @@ static int moveToLeftmost(BtCursor *pCur){
int rc;
while( (pgno = pCur->pPage->apCell[pCur->idx]->h.leftChild)!=0 ){
- rc = moveToChild(pCur, pgno);
+ rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno));
if( rc ) return rc;
}
return SQLITE_OK;
@@ -1377,7 +1442,7 @@ int sqliteBtreeLast(BtCursor *pCur, int *pRes){
}
*pRes = 0;
while( (pgno = pCur->pPage->u.hdr.rightChild)!=0 ){
- rc = moveToChild(pCur, pgno);
+ rc = moveToChild(pCur, SWAB32(pCur->pBt, pgno));
if( rc ) return rc;
}
pCur->idx = pCur->pPage->nCell-1;
@@ -1447,7 +1512,7 @@ int sqliteBtreeMoveto(BtCursor *pCur, const void *pKey, int nKey, int *pRes){
if( pRes ) *pRes = c;
return SQLITE_OK;
}
- rc = moveToChild(pCur, chldPg);
+ rc = moveToChild(pCur, SWAB32(pCur->pBt, chldPg));
if( rc ) return rc;
}
/* NOT REACHED */
@@ -1474,7 +1539,7 @@ int sqliteBtreeNext(BtCursor *pCur, int *pRes){
pCur->idx++;
if( pCur->idx>=pCur->pPage->nCell ){
if( pCur->pPage->u.hdr.rightChild ){
- rc = moveToChild(pCur, pCur->pPage->u.hdr.rightChild);
+ rc = moveToChild(pCur, SWAB32(pCur->pBt, pCur->pPage->u.hdr.rightChild));
if( rc ) return rc;
rc = moveToLeftmost(pCur);
if( rc ) return rc;
@@ -1524,8 +1589,9 @@ static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
rc = sqlitepager_write(pPage1);
if( rc ) return rc;
- pPage1->nFree--;
- rc = sqlitepager_get(pBt->pPager, pPage1->freeList, (void**)&pOvfl);
+ SWAB_ADD(pBt, pPage1->nFree, -1);
+ rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
+ (void**)&pOvfl);
if( rc ) return rc;
rc = sqlitepager_write(pOvfl);
if( rc ){
@@ -1534,27 +1600,28 @@ static int allocatePage(Btree *pBt, MemPage **ppPage, Pgno *pPgno, Pgno nearby){
}
pInfo = (FreelistInfo*)pOvfl->aPayload;
if( pInfo->nFree==0 ){
- *pPgno = pPage1->freeList;
+ *pPgno = SWAB32(pBt, pPage1->freeList);
pPage1->freeList = pOvfl->iNext;
*ppPage = (MemPage*)pOvfl;
}else{
- int closest;
- if( pInfo->nFree>1 && nearby>0 ){
+ int closest, n;
+ n = SWAB32(pBt, pInfo->nFree);
+ if( n>1 && nearby>0 ){
int i, dist;
closest = 0;
- dist = pInfo->aFree[0] - nearby;
+ dist = SWAB32(pBt, pInfo->aFree[0]) - nearby;
if( dist<0 ) dist = -dist;
- for(i=1; inFree; i++){
- int d2 = pInfo->aFree[i] - nearby;
+ for(i=1; iaFree[i]) - nearby;
if( d2<0 ) d2 = -d2;
if( d2nFree--;
- *pPgno = pInfo->aFree[closest];
- pInfo->aFree[closest] = pInfo->aFree[pInfo->nFree];
+ SWAB_ADD(pBt, pInfo->nFree, -1);
+ *pPgno = SWAB32(pBt, pInfo->aFree[closest]);
+ pInfo->aFree[closest] = pInfo->aFree[n-1];
rc = sqlitepager_get(pBt->pPager, *pPgno, (void**)ppPage);
sqlitepager_unref(pOvfl);
if( rc==SQLITE_OK ){
@@ -1599,17 +1666,19 @@ static int freePage(Btree *pBt, void *pPage, Pgno pgno){
if( rc ){
return rc;
}
- pPage1->nFree++;
- if( pPage1->nFree>0 && pPage1->freeList ){
+ SWAB_ADD(pBt, pPage1->nFree, 1);
+ if( pPage1->nFree!=0 && pPage1->freeList!=0 ){
OverflowPage *pFreeIdx;
- rc = sqlitepager_get(pBt->pPager, pPage1->freeList, (void**)&pFreeIdx);
+ rc = sqlitepager_get(pBt->pPager, SWAB32(pBt, pPage1->freeList),
+ (void**)&pFreeIdx);
if( rc==SQLITE_OK ){
FreelistInfo *pInfo = (FreelistInfo*)pFreeIdx->aPayload;
- if( pInfo->nFree<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
+ int n = SWAB32(pBt, pInfo->nFree);
+ if( n<(sizeof(pInfo->aFree)/sizeof(pInfo->aFree[0])) ){
rc = sqlitepager_write(pFreeIdx);
if( rc==SQLITE_OK ){
- pInfo->aFree[pInfo->nFree] = pgno;
- pInfo->nFree++;
+ pInfo->aFree[n] = SWAB32(pBt, pgno);
+ SWAB_ADD(pBt, pInfo->nFree, 1);
sqlitepager_unref(pFreeIdx);
sqlitepager_dont_write(pBt->pPager, pgno);
return rc;
@@ -1630,7 +1699,7 @@ static int freePage(Btree *pBt, void *pPage, Pgno pgno){
return rc;
}
pOvfl->iNext = pPage1->freeList;
- pPage1->freeList = pgno;
+ pPage1->freeList = SWAB32(pBt, pgno);
memset(pOvfl->aPayload, 0, OVERFLOW_SIZE);
if( needUnref ) rc = sqlitepager_unref(pOvfl);
return rc;
@@ -1646,15 +1715,15 @@ static int clearCell(Btree *pBt, Cell *pCell){
Pgno ovfl, nextOvfl;
int rc;
- if( NKEY(pCell->h) + NDATA(pCell->h) <= MX_LOCAL_PAYLOAD ){
+ if( NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h) <= MX_LOCAL_PAYLOAD ){
return SQLITE_OK;
}
- ovfl = pCell->ovfl;
+ ovfl = SWAB32(pBt, pCell->ovfl);
pCell->ovfl = 0;
while( ovfl ){
rc = sqlitepager_get(pPager, ovfl, (void**)&pOvfl);
if( rc ) return rc;
- nextOvfl = pOvfl->iNext;
+ nextOvfl = SWAB32(pBt, pOvfl->iNext);
rc = freePage(pBt, pOvfl, ovfl);
if( rc ) return rc;
sqlitepager_unref(pOvfl);
@@ -1683,9 +1752,9 @@ static int fillInCell(
Pgno nearby = 0;
pCell->h.leftChild = 0;
- pCell->h.nKey = nKey & 0xffff;
+ pCell->h.nKey = SWAB16(pBt, nKey & 0xffff);
pCell->h.nKeyHi = nKey >> 16;
- pCell->h.nData = nData & 0xffff;
+ pCell->h.nData = SWAB16(pBt, nData & 0xffff);
pCell->h.nDataHi = nData >> 16;
pCell->h.iNext = 0;
@@ -1709,6 +1778,7 @@ static int fillInCell(
clearCell(pBt, pCell);
return rc;
}
+ if( pBt->needSwab ) *pNext = swab32(*pNext);
pPrior = pOvfl;
spaceLeft = OVERFLOW_SIZE;
pSpace = pOvfl->aPayload;
@@ -1764,12 +1834,13 @@ static void reparentPage(Pager *pPager, Pgno pgno, MemPage *pNewParent){
** This routine gets called after you memcpy() one page into
** another.
*/
-static void reparentChildPages(Pager *pPager, MemPage *pPage){
+static void reparentChildPages(Btree *pBt, MemPage *pPage){
int i;
+ Pager *pPager = pBt->pPager;
for(i=0; inCell; i++){
- reparentPage(pPager, pPage->apCell[i]->h.leftChild, pPage);
+ reparentPage(pPager, SWAB32(pBt, pPage->apCell[i]->h.leftChild), pPage);
}
- reparentPage(pPager, pPage->u.hdr.rightChild, pPage);
+ reparentPage(pPager, SWAB32(pBt, pPage->u.hdr.rightChild), pPage);
}
/*
@@ -1785,12 +1856,12 @@ static void reparentChildPages(Pager *pPager, MemPage *pPage){
** routine will be called soon after this routine in order to rebuild
** the linked list.
*/
-static void dropCell(MemPage *pPage, int idx, int sz){
+static void dropCell(Btree *pBt, MemPage *pPage, int idx, int sz){
int j;
assert( idx>=0 && idxnCell );
- assert( sz==cellSize(pPage->apCell[idx]) );
+ assert( sz==cellSize(pBt, pPage->apCell[idx]) );
assert( sqlitepager_iswriteable(pPage) );
- freeSpace(pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
+ freeSpace(pBt, pPage, Addr(pPage->apCell[idx]) - Addr(pPage), sz);
for(j=idx; jnCell-1; j++){
pPage->apCell[j] = pPage->apCell[j+1];
}
@@ -1810,12 +1881,12 @@ static void dropCell(MemPage *pPage, int idx, int sz){
** routine will be called soon after this routine in order to rebuild
** the linked list.
*/
-static void insertCell(MemPage *pPage, int i, Cell *pCell, int sz){
+static void insertCell(Btree *pBt, MemPage *pPage, int i, Cell *pCell, int sz){
int idx, j;
assert( i>=0 && i<=pPage->nCell );
- assert( sz==cellSize(pCell) );
+ assert( sz==cellSize(pBt, pCell) );
assert( sqlitepager_iswriteable(pPage) );
- idx = allocateSpace(pPage, sz);
+ idx = allocateSpace(pBt, pPage, sz);
for(j=pPage->nCell; j>i; j--){
pPage->apCell[j] = pPage->apCell[j-1];
}
@@ -1835,7 +1906,7 @@ static void insertCell(MemPage *pPage, int i, Cell *pCell, int sz){
** Invoke this routine once to repair damage after one or more
** invocations of either insertCell() or dropCell().
*/
-static void relinkCellList(MemPage *pPage){
+static void relinkCellList(Btree *pBt, MemPage *pPage){
int i;
u16 *pIdx;
assert( sqlitepager_iswriteable(pPage) );
@@ -1843,7 +1914,7 @@ static void relinkCellList(MemPage *pPage){
for(i=0; inCell; i++){
int idx = Addr(pPage->apCell[i]) - Addr(pPage);
assert( idx>0 && idxapCell[i]->h.iNext;
}
*pIdx = 0;
@@ -1939,7 +2010,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
int cntNew[4]; /* Index in apCell[] of cell after i-th page */
int szNew[4]; /* Combined size of cells place on i-th page */
MemPage *extraUnref = 0; /* A page that needs to be unref-ed */
- Pgno pgno; /* Page number */
+ Pgno pgno, swabPgno; /* Page number */
Cell *apCell[MX_CELL*3+5]; /* All cells from pages being balanceed */
int szCell[MX_CELL*3+5]; /* Local size of all cells */
Cell aTemp[2]; /* Temporary holding area for apDiv[] */
@@ -1952,7 +2023,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
assert( sqlitepager_iswriteable(pPage) );
if( !pPage->isOverfull && pPage->nFreenCell>=2){
- relinkCellList(pPage);
+ relinkCellList(pBt, pPage);
return SQLITE_OK;
}
@@ -1973,14 +2044,14 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
** into the root page and return. This reduces the depth
** of the BTree by one.
*/
- pgnoChild = pPage->u.hdr.rightChild;
+ pgnoChild = SWAB32(pBt, pPage->u.hdr.rightChild);
rc = sqlitepager_get(pBt->pPager, pgnoChild, (void**)&pChild);
if( rc ) return rc;
memcpy(pPage, pChild, SQLITE_PAGE_SIZE);
pPage->isInit = 0;
- rc = initPage(pPage, sqlitepager_pagenumber(pPage), 0);
+ rc = initPage(pBt, pPage, sqlitepager_pagenumber(pPage), 0);
assert( rc==SQLITE_OK );
- reparentChildPages(pBt->pPager, pPage);
+ reparentChildPages(pBt, pPage);
if( pCur && pCur->pPage==pChild ){
sqlitepager_unref(pChild);
pCur->pPage = pPage;
@@ -1989,14 +2060,14 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
freePage(pBt, pChild, pgnoChild);
sqlitepager_unref(pChild);
}else{
- relinkCellList(pPage);
+ relinkCellList(pBt, pPage);
}
return SQLITE_OK;
}
if( !pPage->isOverfull ){
/* It is OK for the root page to be less than half full.
*/
- relinkCellList(pPage);
+ relinkCellList(pBt, pPage);
return SQLITE_OK;
}
/*
@@ -2022,8 +2093,8 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
}else{
extraUnref = pChild;
}
- zeroPage(pPage);
- pPage->u.hdr.rightChild = pgnoChild;
+ zeroPage(pBt, pPage);
+ pPage->u.hdr.rightChild = SWAB32(pBt, pgnoChild);
pParent = pPage;
pPage = pChild;
}
@@ -2038,13 +2109,14 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
*/
idx = -1;
pgno = sqlitepager_pagenumber(pPage);
+ swabPgno = SWAB32(pBt, pgno);
for(i=0; inCell; i++){
- if( pParent->apCell[i]->h.leftChild==pgno ){
+ if( pParent->apCell[i]->h.leftChild==swabPgno ){
idx = i;
break;
}
}
- if( idx<0 && pParent->u.hdr.rightChild==pgno ){
+ if( idx<0 && pParent->u.hdr.rightChild==swabPgno ){
idx = pParent->nCell;
}
if( idx<0 ){
@@ -2077,15 +2149,15 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
idxDiv[i] = k;
apDiv[i] = pParent->apCell[k];
nDiv++;
- pgnoOld[i] = apDiv[i]->h.leftChild;
+ pgnoOld[i] = SWAB32(pBt, apDiv[i]->h.leftChild);
}else if( k==pParent->nCell ){
- pgnoOld[i] = pParent->u.hdr.rightChild;
+ pgnoOld[i] = SWAB32(pBt, pParent->u.hdr.rightChild);
}else{
break;
}
rc = sqlitepager_get(pBt->pPager, pgnoOld[i], (void**)&apOld[i]);
if( rc ) goto balance_cleanup;
- rc = initPage(apOld[i], pgnoOld[i], pParent);
+ rc = initPage(pBt, apOld[i], pgnoOld[i], pParent);
if( rc ) goto balance_cleanup;
nOld++;
}
@@ -2134,15 +2206,15 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
MemPage *pOld = &aOld[i];
for(j=0; jnCell; j++){
apCell[nCell] = pOld->apCell[j];
- szCell[nCell] = cellSize(apCell[nCell]);
+ szCell[nCell] = cellSize(pBt, apCell[nCell]);
nCell++;
}
if( ih.leftChild==pgnoOld[i] );
+ dropCell(pBt, pParent, nxDiv, szCell[nCell]);
+ assert( SWAB32(pBt, apCell[nCell]->h.leftChild)==pgnoOld[i] );
apCell[nCell]->h.leftChild = pOld->u.hdr.rightChild;
nCell++;
}
@@ -2198,7 +2270,7 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
if( rc ) goto balance_cleanup;
}
nNew++;
- zeroPage(apNew[i]);
+ zeroPage(pBt, apNew[i]);
apNew[i]->isInit = 1;
}
@@ -2256,17 +2328,17 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
while( jnFree>=szCell[j] );
if( pCur && iCur==j ){ pCur->pPage = pNew; pCur->idx = pNew->nCell; }
- insertCell(pNew, pNew->nCell, apCell[j], szCell[j]);
+ insertCell(pBt, pNew, pNew->nCell, apCell[j], szCell[j]);
j++;
}
assert( pNew->nCell>0 );
assert( !pNew->isOverfull );
- relinkCellList(pNew);
+ relinkCellList(pBt, pNew);
if( iu.hdr.rightChild = apCell[j]->h.leftChild;
- apCell[j]->h.leftChild = pgnoNew[i];
+ apCell[j]->h.leftChild = SWAB32(pBt, pgnoNew[i]);
if( pCur && iCur==j ){ pCur->pPage = pParent; pCur->idx = nxDiv; }
- insertCell(pParent, nxDiv, apCell[j], szCell[j]);
+ insertCell(pBt, pParent, nxDiv, apCell[j], szCell[j]);
j++;
nxDiv++;
}
@@ -2274,9 +2346,9 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
assert( j==nCell );
apNew[nNew-1]->u.hdr.rightChild = aOld[nOld-1].u.hdr.rightChild;
if( nxDiv==pParent->nCell ){
- pParent->u.hdr.rightChild = pgnoNew[nNew-1];
+ pParent->u.hdr.rightChild = SWAB32(pBt, pgnoNew[nNew-1]);
}else{
- pParent->apCell[nxDiv]->h.leftChild = pgnoNew[nNew-1];
+ pParent->apCell[nxDiv]->h.leftChild = SWAB32(pBt, pgnoNew[nNew-1]);
}
if( pCur ){
if( j<=iCur && pCur->pPage==pParent && pCur->idx>idxDiv[nOld-1] ){
@@ -2293,9 +2365,9 @@ static int balance(Btree *pBt, MemPage *pPage, BtCursor *pCur){
** Reparent children of all cells.
*/
for(i=0; ipPager, apNew[i]);
+ reparentChildPages(pBt, apNew[i]);
}
- reparentChildPages(pBt->pPager, pParent);
+ reparentChildPages(pBt, pParent);
/*
** balance the parent page.
@@ -2359,19 +2431,19 @@ int sqliteBtreeInsert(
if( rc ) return rc;
rc = fillInCell(pBt, &newCell, pKey, nKey, pData, nData);
if( rc ) return rc;
- szNew = cellSize(&newCell);
+ szNew = cellSize(pBt, &newCell);
if( loc==0 ){
newCell.h.leftChild = pPage->apCell[pCur->idx]->h.leftChild;
rc = clearCell(pBt, pPage->apCell[pCur->idx]);
if( rc ) return rc;
- dropCell(pPage, pCur->idx, cellSize(pPage->apCell[pCur->idx]));
+ dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pPage->apCell[pCur->idx]));
}else if( loc<0 && pPage->nCell>0 ){
assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
pCur->idx++;
}else{
assert( pPage->u.hdr.rightChild==0 ); /* Must be a leaf page */
}
- insertCell(pPage, pCur->idx, &newCell, szNew);
+ insertCell(pBt, pPage, pCur->idx, &newCell, szNew);
rc = balance(pCur->pBt, pPage, pCur);
/* sqliteBtreePageDump(pCur->pBt, pCur->pgnoRoot, 1); */
/* fflush(stdout); */
@@ -2393,6 +2465,7 @@ int sqliteBtreeDelete(BtCursor *pCur){
Cell *pCell;
int rc;
Pgno pgnoChild;
+ Btree *pBt = pCur->pBt;
assert( pPage->isInit );
if( pCur->pPage==0 ){
@@ -2410,8 +2483,8 @@ int sqliteBtreeDelete(BtCursor *pCur){
rc = sqlitepager_write(pPage);
if( rc ) return rc;
pCell = pPage->apCell[pCur->idx];
- pgnoChild = pCell->h.leftChild;
- clearCell(pCur->pBt, pCell);
+ pgnoChild = SWAB32(pBt, pCell->h.leftChild);
+ clearCell(pBt, pCell);
if( pgnoChild ){
/*
** The entry we are about to delete is not a leaf so if we do not
@@ -2430,19 +2503,19 @@ int sqliteBtreeDelete(BtCursor *pCur){
}
rc = sqlitepager_write(leafCur.pPage);
if( rc ) return rc;
- dropCell(pPage, pCur->idx, cellSize(pCell));
+ dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
pNext = leafCur.pPage->apCell[leafCur.idx];
- szNext = cellSize(pNext);
- pNext->h.leftChild = pgnoChild;
- insertCell(pPage, pCur->idx, pNext, szNext);
- rc = balance(pCur->pBt, pPage, pCur);
+ szNext = cellSize(pBt, pNext);
+ pNext->h.leftChild = SWAB32(pBt, pgnoChild);
+ insertCell(pBt, pPage, pCur->idx, pNext, szNext);
+ rc = balance(pBt, pPage, pCur);
if( rc ) return rc;
pCur->bSkipNext = 1;
- dropCell(leafCur.pPage, leafCur.idx, szNext);
- rc = balance(pCur->pBt, leafCur.pPage, pCur);
+ dropCell(pBt, leafCur.pPage, leafCur.idx, szNext);
+ rc = balance(pBt, leafCur.pPage, pCur);
releaseTempCursor(&leafCur);
}else{
- dropCell(pPage, pCur->idx, cellSize(pCell));
+ dropCell(pBt, pPage, pCur->idx, cellSize(pBt, pCell));
if( pCur->idx>=pPage->nCell ){
pCur->idx = pPage->nCell-1;
if( pCur->idx<0 ){
@@ -2454,7 +2527,7 @@ int sqliteBtreeDelete(BtCursor *pCur){
}else{
pCur->bSkipNext = 1;
}
- rc = balance(pCur->pBt, pPage, pCur);
+ rc = balance(pBt, pPage, pCur);
}
return rc;
}
@@ -2481,7 +2554,7 @@ int sqliteBtreeCreateTable(Btree *pBt, int *piTable){
rc = allocatePage(pBt, &pRoot, &pgnoRoot, 0);
if( rc ) return rc;
assert( sqlitepager_iswriteable(pRoot) );
- zeroPage(pRoot);
+ zeroPage(pBt, pRoot);
sqlitepager_unref(pRoot);
*piTable = (int)pgnoRoot;
return SQLITE_OK;
@@ -2514,27 +2587,27 @@ static int clearDatabasePage(Btree *pBt, Pgno pgno, int freePageFlag){
if( rc ) return rc;
rc = sqlitepager_write(pPage);
if( rc ) return rc;
- rc = initPage(pPage, pgno, 0);
+ rc = initPage(pBt, pPage, pgno, 0);
if( rc ) return rc;
- idx = pPage->u.hdr.firstCell;
+ idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 ){
pCell = (Cell*)&pPage->u.aDisk[idx];
- idx = pCell->h.iNext;
+ idx = SWAB16(pBt, pCell->h.iNext);
if( pCell->h.leftChild ){
- rc = clearDatabasePage(pBt, pCell->h.leftChild, 1);
+ rc = clearDatabasePage(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
if( rc ) return rc;
}
rc = clearCell(pBt, pCell);
if( rc ) return rc;
}
if( pPage->u.hdr.rightChild ){
- rc = clearDatabasePage(pBt, pPage->u.hdr.rightChild, 1);
+ rc = clearDatabasePage(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
if( rc ) return rc;
}
if( freePageFlag ){
rc = freePage(pBt, pPage, pgno);
}else{
- zeroPage(pPage);
+ zeroPage(pBt, pPage);
}
sqlitepager_unref(pPage);
return rc;
@@ -2584,7 +2657,7 @@ int sqliteBtreeDropTable(Btree *pBt, int iTable){
if( iTable>2 ){
rc = freePage(pBt, pPage, iTable);
}else{
- zeroPage(pPage);
+ zeroPage(pBt, pPage);
}
sqlitepager_unref(pPage);
return rc;
@@ -2596,11 +2669,14 @@ int sqliteBtreeDropTable(Btree *pBt, int iTable){
int sqliteBtreeGetMeta(Btree *pBt, int *aMeta){
PageOne *pP1;
int rc;
+ int i;
rc = sqlitepager_get(pBt->pPager, 1, (void**)&pP1);
if( rc ) return rc;
- aMeta[0] = pP1->nFree;
- memcpy(&aMeta[1], pP1->aMeta, sizeof(pP1->aMeta));
+ aMeta[0] = SWAB32(pBt, pP1->nFree);
+ for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){
+ aMeta[i+1] = SWAB32(pBt, pP1->aMeta[i]);
+ }
sqlitepager_unref(pP1);
return SQLITE_OK;
}
@@ -2610,7 +2686,7 @@ int sqliteBtreeGetMeta(Btree *pBt, int *aMeta){
*/
int sqliteBtreeUpdateMeta(Btree *pBt, int *aMeta){
PageOne *pP1;
- int rc;
+ int rc, i;
if( !pBt->inTrans ){
return SQLITE_ERROR; /* Must start a transaction first */
}
@@ -2620,7 +2696,9 @@ int sqliteBtreeUpdateMeta(Btree *pBt, int *aMeta){
pP1 = pBt->page1;
rc = sqlitepager_write(pP1);
if( rc ) return rc;
- memcpy(pP1->aMeta, &aMeta[1], sizeof(pP1->aMeta));
+ for(i=0; iaMeta)/sizeof(pP1->aMeta[0]); i++){
+ pP1->aMeta[i] = SWAB32(pBt, aMeta[i+1]);
+ }
return SQLITE_OK;
}
@@ -2649,12 +2727,12 @@ int sqliteBtreePageDump(Btree *pBt, int pgno, int recursive){
}
if( recursive ) printf("PAGE %d:\n", pgno);
i = 0;
- idx = pPage->u.hdr.firstCell;
+ idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 && idx<=SQLITE_PAGE_SIZE-MIN_CELL_SIZE ){
Cell *pCell = (Cell*)&pPage->u.aDisk[idx];
- int sz = cellSize(pCell);
+ int sz = cellSize(pBt, pCell);
sprintf(range,"%d..%d", idx, idx+sz-1);
- sz = NKEY(pCell->h) + NDATA(pCell->h);
+ sz = NKEY(pBt, pCell->h) + NDATA(pBt, pCell->h);
if( sz>sizeof(payload)-1 ) sz = sizeof(payload)-1;
memcpy(payload, pCell->aPayload, sz);
for(j=0; jh.leftChild, NKEY(pCell->h), NDATA(pCell->h),
+ i, range, (int)pCell->h.leftChild,
+ NKEY(pBt, pCell->h), NDATA(pBt, pCell->h),
payload
);
if( pPage->isInit && pPage->apCell[i]!=pCell ){
printf("**** apCell[%d] does not match on prior entry ****\n", i);
}
i++;
- idx = pCell->h.iNext;
+ idx = SWAB16(pBt, pCell->h.iNext);
}
if( idx!=0 ){
printf("ERROR: next cell index out of range: %d\n", idx);
}
- printf("right_child: %d\n", pPage->u.hdr.rightChild);
+ printf("right_child: %d\n", SWAB32(pBt, pPage->u.hdr.rightChild));
nFree = 0;
i = 0;
- idx = pPage->u.hdr.firstFree;
+ idx = SWAB16(pBt, pPage->u.hdr.firstFree);
while( idx>0 && idxu.aDisk[idx];
sprintf(range,"%d..%d", idx, idx+p->iSize-1);
- nFree += p->iSize;
+ nFree += SWAB16(pBt, p->iSize);
printf("freeblock %2d: i=%-10s size=%-4d total=%d\n",
- i, range, p->iSize, nFree);
- idx = p->iNext;
+ i, range, SWAB16(pBt, p->iSize), nFree);
+ idx = SWAB16(pBt, p->iNext);
i++;
}
if( idx!=0 ){
printf("ERROR: next freeblock index out of range: %d\n", idx);
}
if( recursive && pPage->u.hdr.rightChild!=0 ){
- idx = pPage->u.hdr.firstCell;
+ idx = SWAB16(pBt, pPage->u.hdr.firstCell);
while( idx>0 && idxu.aDisk[idx];
- sqliteBtreePageDump(pBt, pCell->h.leftChild, 1);
- idx = pCell->h.iNext;
+ sqliteBtreePageDump(pBt, SWAB32(pBt, pCell->h.leftChild), 1);
+ idx = SWAB16(pBt, pCell->h.iNext);
}
- sqliteBtreePageDump(pBt, pPage->u.hdr.rightChild, 1);
+ sqliteBtreePageDump(pBt, SWAB32(pBt, pPage->u.hdr.rightChild), 1);
}
sqlitepager_unref(pPage);
return SQLITE_OK;
@@ -2724,25 +2803,26 @@ int sqliteBtreePageDump(Btree *pBt, int pgno, int recursive){
int sqliteBtreeCursorDump(BtCursor *pCur, int *aResult){
int cnt, idx;
MemPage *pPage = pCur->pPage;
+ Btree *pBt = pCur->pBt;
aResult[0] = sqlitepager_pagenumber(pPage);
aResult[1] = pCur->idx;
aResult[2] = pPage->nCell;
if( pCur->idx>=0 && pCur->idxnCell ){
- aResult[3] = cellSize(pPage->apCell[pCur->idx]);
- aResult[6] = pPage->apCell[pCur->idx]->h.leftChild;
+ aResult[3] = cellSize(pBt, pPage->apCell[pCur->idx]);
+ aResult[6] = SWAB32(pBt, pPage->apCell[pCur->idx]->h.leftChild);
}else{
aResult[3] = 0;
aResult[6] = 0;
}
aResult[4] = pPage->nFree;
cnt = 0;
- idx = pPage->u.hdr.firstFree;
+ idx = SWAB16(pBt, pPage->u.hdr.firstFree);
while( idx>0 && idxu.aDisk[idx])->iNext;
+ idx = SWAB16(pBt, ((FreeBlk*)&pPage->u.aDisk[idx])->iNext);
}
aResult[5] = cnt;
- aResult[7] = pPage->u.hdr.rightChild;
+ aResult[7] = SWAB32(pBt, pPage->u.hdr.rightChild);
return SQLITE_OK;
}
#endif
@@ -2839,12 +2919,13 @@ static void checkList(
}
if( isFreeList ){
FreelistInfo *pInfo = (FreelistInfo*)pOvfl->aPayload;
- for(i=0; inFree; i++){
- checkRef(pCheck, pInfo->aFree[i], zMsg);
+ int n = SWAB32(pCheck->pBt, pInfo->nFree);
+ for(i=0; ipBt, pInfo->aFree[i]), zMsg);
}
- N -= pInfo->nFree;
+ N -= n;
}
- iPage = (int)pOvfl->iNext;
+ iPage = SWAB32(pCheck->pBt, pOvfl->iNext);
sqlitepager_unref(pOvfl);
}
}
@@ -2899,12 +2980,14 @@ static int checkTreePage(
char *zKey1, *zKey2;
int nKey1, nKey2;
BtCursor cur;
+ Btree *pBt;
char zMsg[100];
char zContext[100];
char hit[SQLITE_PAGE_SIZE];
/* Check that the page exists
*/
+ cur.pBt = pBt = pCheck->pBt;
if( iPage==0 ) return 0;
if( checkRef(pCheck, iPage, zParentContext) ) return 0;
sprintf(zContext, "On tree page %d: ", iPage);
@@ -2913,7 +2996,7 @@ static int checkTreePage(
checkAppendMsg(pCheck, zContext, zMsg);
return 0;
}
- if( (rc = initPage(pPage, (Pgno)iPage, pParent))!=0 ){
+ if( (rc = initPage(pBt, pPage, (Pgno)iPage, pParent))!=0 ){
sprintf(zMsg, "initPage() returns error code %d", rc);
checkAppendMsg(pCheck, zContext, zMsg);
sqlitepager_unref(pPage);
@@ -2932,19 +3015,18 @@ static int checkTreePage(
}
nKey1 = nLower;
cur.pPage = pPage;
- cur.pBt = pCheck->pBt;
for(i=0; inCell; i++){
Cell *pCell = pPage->apCell[i];
int sz;
/* Check payload overflow pages
*/
- nKey2 = NKEY(pCell->h);
- sz = nKey2 + NDATA(pCell->h);
+ nKey2 = NKEY(pBt, pCell->h);
+ sz = nKey2 + NDATA(pBt, pCell->h);
sprintf(zContext, "On page %d cell %d: ", iPage, i);
if( sz>MX_LOCAL_PAYLOAD ){
int nPage = (sz - MX_LOCAL_PAYLOAD + OVERFLOW_SIZE - 1)/OVERFLOW_SIZE;
- checkList(pCheck, 0, pCell->ovfl, nPage, zContext);
+ checkList(pCheck, 0, SWAB32(pBt, pCell->ovfl), nPage, zContext);
}
/* Check that keys are in the right order
@@ -2958,7 +3040,7 @@ static int checkTreePage(
/* Check sanity of left child page.
*/
- pgno = (int)pCell->h.leftChild;
+ pgno = SWAB32(pBt, pCell->h.leftChild);
d2 = checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zKey2,nKey2);
if( i>0 && d2!=depth ){
checkAppendMsg(pCheck, zContext, "Child page depth differs");
@@ -2968,7 +3050,7 @@ static int checkTreePage(
zKey1 = zKey2;
nKey1 = nKey2;
}
- pgno = pPage->u.hdr.rightChild;
+ pgno = SWAB32(pBt, pPage->u.hdr.rightChild);
sprintf(zContext, "On page %d at right child: ", iPage);
checkTreePage(pCheck, pgno, pPage, zContext, zKey1,nKey1,zUpperBound,nUpper);
sqliteFree(zKey1);
@@ -2977,17 +3059,17 @@ static int checkTreePage(
*/
memset(hit, 0, sizeof(hit));
memset(hit, 1, sizeof(PageHdr));
- for(i=pPage->u.hdr.firstCell; i>0 && iu.hdr.firstCell); i>0 && iu.aDisk[i];
int j;
- for(j=i+cellSize(pCell)-1; j>=i; j--) hit[j]++;
- i = pCell->h.iNext;
+ for(j=i+cellSize(pBt, pCell)-1; j>=i; j--) hit[j]++;
+ i = SWAB16(pBt, pCell->h.iNext);
}
- for(i=pPage->u.hdr.firstFree; i>0 && iu.hdr.firstFree); i>0 && iu.aDisk[i];
int j;
- for(j=i+pFBlk->iSize-1; j>=i; j--) hit[j]++;
- i = pFBlk->iNext;
+ for(j=i+SWAB16(pBt,pFBlk->iSize)-1; j>=i; j--) hit[j]++;
+ i = SWAB16(pBt,pFBlk->iNext);
}
for(i=0; ipage1->freeList, pBt->page1->nFree,
- "Main freelist: ");
+ checkList(&sCheck, 1, SWAB32(pBt, pBt->page1->freeList),
+ SWAB32(pBt, pBt->page1->nFree), "Main freelist: ");
/* Check all the tables.
*/
diff --git a/src/btree.h b/src/btree.h
index 351aa28ecb..ec4d68f8a9 100644
--- a/src/btree.h
+++ b/src/btree.h
@@ -13,7 +13,7 @@
** subsystem. See comments in the source code for a detailed description
** of what each interface routine does.
**
-** @(#) $Id: btree.h,v 1.24 2002/02/19 15:00:08 drh Exp $
+** @(#) $Id: btree.h,v 1.25 2002/08/11 20:10:48 drh Exp $
*/
#ifndef _BTREE_H_
#define _BTREE_H_
@@ -63,6 +63,7 @@ char *sqliteBtreeIntegrityCheck(Btree*, int*, int);
int sqliteBtreePageDump(Btree*, int, int);
int sqliteBtreeCursorDump(BtCursor*, int*);
struct Pager *sqliteBtreePager(Btree*);
+int btree_native_byte_order;
#endif
#endif /* _BTREE_H_ */
diff --git a/src/parse.y b/src/parse.y
index f986d81ec7..b70a365103 100644
--- a/src/parse.y
+++ b/src/parse.y
@@ -14,7 +14,7 @@
** the parser. Lemon will also generate a header file containing
** numeric codes for all of the tokens.
**
-** @(#) $Id: parse.y,v 1.79 2002/07/15 18:55:25 drh Exp $
+** @(#) $Id: parse.y,v 1.80 2002/08/11 20:10:48 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@@ -164,6 +164,7 @@ carg ::= DEFAULT NULL.
// In addition to the type name, we also care about the primary key and
// UNIQUE constraints.
//
+ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R). {sqliteAddNotNull(pParse, R);}
ccons ::= PRIMARY KEY sortorder onconf(R). {sqliteAddPrimaryKey(pParse,0,R);}
ccons ::= UNIQUE onconf(R). {sqliteCreateIndex(pParse,0,0,0,R,0,0);}
diff --git a/src/test3.c b/src/test3.c
index ff447078bd..9402a01b25 100644
--- a/src/test3.c
+++ b/src/test3.c
@@ -13,7 +13,7 @@
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test3.c,v 1.17 2002/07/07 17:12:36 drh Exp $
+** $Id: test3.c,v 1.18 2002/08/11 20:10:48 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
@@ -496,7 +496,7 @@ static int btree_integrity_check(
zResult = sqliteBtreeIntegrityCheck(pBt, aRoot, nRoot);
if( zResult ){
Tcl_AppendResult(interp, zResult, 0);
- free(zResult);
+ sqliteFree(zResult);
}
return TCL_OK;
}
@@ -906,5 +906,7 @@ int Sqlitetest3_Init(Tcl_Interp *interp){
Tcl_CreateCommand(interp, "btree_integrity_check", btree_integrity_check,0,0);
Tcl_LinkVar(interp, "pager_refinfo_enable", (char*)&pager_refinfo_enable,
TCL_LINK_INT);
+ Tcl_LinkVar(interp, "btree_native_byte_order",(char*)&btree_native_byte_order,
+ TCL_LINK_INT);
return TCL_OK;
}
diff --git a/test/all.test b/test/all.test
index e77fde8df8..60ed369d58 100644
--- a/test/all.test
+++ b/test/all.test
@@ -10,7 +10,7 @@
#***********************************************************************
# This file runs all tests.
#
-# $Id: all.test,v 1.15 2002/07/07 16:52:47 drh Exp $
+# $Id: all.test,v 1.16 2002/08/11 20:10:49 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -20,7 +20,7 @@ proc finish_test {} {memleak_check}
if {[file exists ./sqlite_test_count]} {
set COUNT [exec cat ./sqlite_test_count]
} else {
- set COUNT 3
+ set COUNT 4
}
# LeakList will hold a list of the number of unfreed mallocs after
@@ -38,6 +38,7 @@ set EXCLUDE {
# btree2.test
for {set Counter 0} {$Counter<$COUNT && $nErr==0} {incr Counter} {
+ set btree_native_byte_order [expr {($Counter>>1)&0x1}]
if {$Counter%2} {
set ::SETUP_SQL {PRAGMA default_synchronous=off;}
} else {
diff --git a/test/version.test b/test/version.test
index f545521db5..30a39cc138 100644
--- a/test/version.test
+++ b/test/version.test
@@ -12,7 +12,7 @@
# focus of this file is testing the ability of the library to detect
# past or future file format version numbers and respond appropriately.
#
-# $Id: version.test,v 1.4 2002/07/19 18:52:41 drh Exp $
+# $Id: version.test,v 1.5 2002/08/11 20:10:49 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -38,7 +38,9 @@ do_test version-1.1 {
do_test version-1.2 {
db close
set ::bt [btree_open test.db]
+ btree_begin_transaction $::bt
set ::meta [btree_get_meta $::bt]
+ btree_rollback $::bt
lindex $::meta 2
} $VX
diff --git a/www/faq.tcl b/www/faq.tcl
index 54c356a2eb..84fa83160a 100644
--- a/www/faq.tcl
+++ b/www/faq.tcl
@@ -1,7 +1,7 @@
#
# Run this script to generated a faq.html output file
#
-set rcsid {$Id: faq.tcl,v 1.13 2002/08/02 10:36:10 drh Exp $}
+set rcsid {$Id: faq.tcl,v 1.14 2002/08/11 20:10:49 drh Exp $}
puts {
@@ -153,26 +153,15 @@ faq {
My linux box is not able to read an SQLite database that was created
on my SparcStation.
} {
+ You need to upgrade your SQLite library to version 2.6.3 or later.
+
The x86 processor on your linux box is little-endian (meaning that
the least significant byte of integers comes first) but the Sparc is
big-endian (the most significant bytes comes first). SQLite databases
- created on a little-endian architecture cannot be used on a big-endian
- machine and vice versa.
-
- If you need to move the database from one machine to another, you'll
- have to do an ASCII dump of the database on the source machine and then
- reconstruct the database at the destination machine. The following is
- a typical command for transferring an SQLite databases between two
- machines:
-
-echo .dump | sqlite from.db | ssh sparc sqlite to.db
-
- The command above assumes the name of the destination machine is
- sparc and that you have SSH running on both the source and
- destination. An alternative approach is to save the output of the first
- sqlite command in a temporary file, move the temporary file
- to the destination machine, then run the second sqlite command
- while redirecting input from the temporary file.
+ created on a little-endian architecture cannot be on a big-endian
+ machine by version 2.6.2 or earlier of SQLite. Beginning with
+ version 2.6.3, SQLite should be able to read and write database files
+ regardless of byte order of the machine on which the file was created.
}
faq {
diff --git a/www/index.tcl b/www/index.tcl
index 4caa8ea603..aad5d6ff79 100644
--- a/www/index.tcl
+++ b/www/index.tcl
@@ -1,7 +1,7 @@
#
# Run this TCL script to generate HTML for the index.html file.
#
-set rcsid {$Id: index.tcl,v 1.60 2002/07/18 02:07:08 drh Exp $}
+set rcsid {$Id: index.tcl,v 1.61 2002/08/11 20:10:49 drh Exp $}
puts {
SQLite: An SQL Database Engine In A C Library
@@ -49,7 +49,7 @@ puts {Features