diff options
author | drh <drh@noemail.net> | 2002-02-19 22:42:05 +0000 |
---|---|---|
committer | drh <drh@noemail.net> | 2002-02-19 22:42:05 +0000 |
commit | 5cf8e8c7fa103aea2f10fc36a77cd4419c56bc5d (patch) | |
tree | 91e87acefabb1bb2d3882cf213e43d19a2303c7d /src | |
parent | 9562b55115c5f708d593d92ca2257e62d6bb425b (diff) | |
download | sqlite-5cf8e8c7fa103aea2f10fc36a77cd4419c56bc5d.tar.gz sqlite-5cf8e8c7fa103aea2f10fc36a77cd4419c56bc5d.zip |
New ROWIDs are numbered sequentially. (CVS 383)
FossilOrigin-Name: 1686196a8aea326f616bc8205df99cd84d955ec4
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 4 | ||||
-rw-r--r-- | src/select.c | 19 | ||||
-rw-r--r-- | src/sqliteInt.h | 4 | ||||
-rw-r--r-- | src/vdbe.c | 67 |
4 files changed, 64 insertions, 30 deletions
diff --git a/src/main.c b/src/main.c index 61450217e..553f74683 100644 --- a/src/main.c +++ b/src/main.c @@ -14,7 +14,7 @@ ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** -** $Id: main.c,v 1.59 2002/02/18 18:30:33 drh Exp $ +** $Id: main.c,v 1.60 2002/02/19 22:42:05 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -275,8 +275,8 @@ sqlite *sqlite_open(const char *zFilename, int mode, char **pzErrMsg){ sqliteHashInit(&db->idxHash, SQLITE_HASH_STRING, 0); sqliteHashInit(&db->tblDrop, SQLITE_HASH_POINTER, 0); sqliteHashInit(&db->idxDrop, SQLITE_HASH_POINTER, 0); - db->nextRowid = sqliteRandomInteger(); db->onError = OE_Default; + db->priorNewRowid = 0; /* Open the backend database driver */ rc = sqliteBtreeOpen(zFilename, mode, MAX_PAGES, &db->pBe); diff --git a/src/select.c b/src/select.c index 036c35ec5..ef6cd216e 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.62 2002/02/19 15:00:08 drh Exp $ +** $Id: select.c,v 1.63 2002/02/19 22:42:05 drh Exp $ */ #include "sqliteInt.h" @@ -783,22 +783,28 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ /* Begin generating code */ - base = pParse->nTab; - eList.nExpr = 1; - memset(&eListItem, 0, sizeof(eListItem)); - eList.a = &eListItem; - eList.a[0].pExpr = pExpr; + if( !pParse->schemaVerified && (pParse->db->flags & SQLITE_InTrans)==0 ){ + sqliteVdbeAddOp(v, OP_VerifyCookie, pParse->db->schema_cookie, 0); + pParse->schemaVerified = 1; + } openOp = pTab->isTemp ? OP_OpenAux : OP_Open; + base = pParse->nTab; sqliteVdbeAddOp(v, openOp, base, pTab->tnum); + sqliteVdbeChangeP3(v, -1, pTab->zName, P3_STATIC); if( pIdx==0 ){ sqliteVdbeAddOp(v, seekOp, base, 0); }else{ sqliteVdbeAddOp(v, openOp, base+1, pIdx->tnum); + sqliteVdbeChangeP3(v, -1, pIdx->zName, P3_STATIC); sqliteVdbeAddOp(v, seekOp, base+1, 0); sqliteVdbeAddOp(v, OP_IdxRecno, base+1, 0); sqliteVdbeAddOp(v, OP_Close, base+1, 0); sqliteVdbeAddOp(v, OP_MoveTo, base, 0); } + eList.nExpr = 1; + memset(&eListItem, 0, sizeof(eListItem)); + eList.a = &eListItem; + eList.a[0].pExpr = pExpr; cont = sqliteVdbeMakeLabel(v); selectInnerLoop(pParse, &eList, base, 1, 0, -1, eDest, iParm, cont, cont); sqliteVdbeResolveLabel(v, cont); @@ -1011,6 +1017,7 @@ int sqliteSelect( ** in the result set. */ if( simpleMinMaxQuery(pParse, p, eDest, iParm) ){ + rc = 0; goto select_end; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 1f3db95bf..302a2b494 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.87 2002/02/18 18:30:33 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.88 2002/02/19 22:42:05 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -182,7 +182,7 @@ struct sqlite { Hash tblDrop; /* Uncommitted DROP TABLEs */ Hash idxDrop; /* Uncommitted DROP INDEXs */ int lastRowid; /* ROWID of most recent insert */ - int nextRowid; /* Next generated rowID */ + int priorNewRowid; /* Last randomly generated ROWID */ int onError; /* Default conflict algorithm */ }; diff --git a/src/vdbe.c b/src/vdbe.c index 788c5a9d2..f9f088504 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.119 2002/02/19 15:00:08 drh Exp $ +** $Id: vdbe.c,v 1.120 2002/02/19 22:42:05 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> @@ -71,6 +71,7 @@ struct Cursor { Bool recnoIsValid; /* True if lastRecno is valid */ Bool keyAsData; /* The OP_Column command works on key instead of data */ Bool atFirst; /* True if pointing to first entry */ + Bool useRandomRowid; /* Generate new record numbers semi-randomly */ Btree *pBt; /* Separate file holding temporary table */ }; typedef struct Cursor Cursor; @@ -2913,10 +2914,18 @@ case OP_NewRecno: { if( VERIFY( i<0 || i>=p->nCursor || ) (pC = &p->aCsr[i])->pCursor==0 ){ v = 0; }else{ - /* A probablistic algorithm is used to locate an unused rowid. - ** We select a rowid at random and see if it exists in the table. - ** If it does not exist, we have succeeded. If the random rowid - ** does exist, we select a new one and try again, up to 1000 times. + /* The next rowid or record number (different terms for the same + ** thing) is obtained in a two-step algorithm. + ** + ** First we attempt to find the largest existing rowid and add one + ** to that. But if the largest existing rowid is already the maximum + ** positive integer, we have to fall through to the second + ** probabilistic algorithm + ** + ** The second algorithm is to select a rowid at random and see if + ** it already exists in the table. If it does not exist, we have + ** succeeded. If the random rowid does exist, we select a new one + ** and try again, up to 1000 times. ** ** For a table with less than 2 billion entries, the probability ** of not finding a unused rowid is about 1.0e-300. This is a @@ -2932,28 +2941,46 @@ case OP_NewRecno: { ** random number generator based on the RC4 algorithm. ** ** To promote locality of reference for repetitive inserts, the - ** first few attempts at chosing a rowid pick values just a little + ** first few attempts at chosing a random rowid pick values just a little ** larger than the previous rowid. This has been shown experimentally ** to double the speed of the COPY operation. */ int res, rx, cnt, x; cnt = 0; - v = db->nextRowid; - do{ - if( cnt>5 ){ - v = sqliteRandomInteger(); + if( !pC->useRandomRowid ){ + rx = sqliteBtreeLast(pC->pCursor, &res); + if( res ){ + v = 1; }else{ - v += sqliteRandomByte() + 1; + sqliteBtreeKey(pC->pCursor, 0, sizeof(v), (void*)&v); + v = keyToInt(v); + if( v==0x7fffffff ){ + pC->useRandomRowid = 1; + }else{ + v++; + } + } + } + if( pC->useRandomRowid ){ + v = db->priorNewRowid; + cnt = 0; + do{ + if( v==0 || cnt>2 ){ + v = sqliteRandomInteger(); + if( cnt<5 ) v &= 0xffffff; + }else{ + v += sqliteRandomByte() + 1; + } + if( v==0 ) continue; + x = intToKey(v); + rx = sqliteBtreeMoveto(pC->pCursor, &x, sizeof(int), &res); + cnt++; + }while( cnt<1000 && rx==SQLITE_OK && res==0 ); + db->priorNewRowid = v; + if( rx==SQLITE_OK && res==0 ){ + rc = SQLITE_FULL; + goto abort_due_to_error; } - if( v==0 ) continue; - x = intToKey(v); - rx = sqliteBtreeMoveto(pC->pCursor, &x, sizeof(int), &res); - cnt++; - }while( cnt<1000 && rx==SQLITE_OK && res==0 ); - db->nextRowid = v; - if( rx==SQLITE_OK && res==0 ){ - rc = SQLITE_FULL; - goto abort_due_to_error; } } VERIFY( NeedStack(p, p->tos+1); ) |