aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main.c4
-rw-r--r--src/select.c19
-rw-r--r--src/sqliteInt.h4
-rw-r--r--src/vdbe.c67
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); )