1
0
mirror of https://github.com/sqlite/sqlite.git synced 2025-08-05 15:55:57 +03:00

Incremental check-in of changes that will ultimately lead to a

working autoincrement. (CVS 2056)

FossilOrigin-Name: 10c3d88305e404b9e4cc4eef0b8e5dc7864a5937
This commit is contained in:
drh
2004-11-05 00:43:11 +00:00
parent 40e016e492
commit 205f48e635
9 changed files with 154 additions and 32 deletions

View File

@@ -1,5 +1,5 @@
C All\stests\spass\swhen\sSQLITE_OMIT_INTEGRITY_CHECK\sis\sdefined.\s(CVS\s2055)
D 2004-11-04T14:47:12
C Incremental\scheck-in\sof\schanges\sthat\swill\sultimately\slead\sto\sa\nworking\sautoincrement.\s(CVS\s2056)
D 2004-11-05T00:43:12
F Makefile.in c4d2416860f472a1e3393714d0372074197565df
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@@ -29,11 +29,11 @@ F sqlite3.def dbaeb20c153e1d366e8f421b55a573f5dfc00863
F sqlite3.pc.in 985b9bf34192a549d7d370e0f0b6b34a4f61369a
F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
F src/btree.c a3e45d54eb1a81698f609693c22df382dfbf9151
F src/btree.c 1b172b9d58608eeba1022e858fedce351c7090f5
F src/btree.h 3166388fa58c5594d8064d38b43440d79da38fb6
F src/build.c 1bf89a574108cbb03aed722f0ce97cf54469717d
F src/build.c e72d6f76373998063cd85d592e7a402b8e24b721
F src/date.c 34bdb0082db7ec2a83ef00063f7b44e61ee19dad
F src/delete.c 52980e594e69e80374fb928fe611d5f75ca4e390
F src/delete.c 832adc6fe1c07b7e28e1b4c1038d2b06f7397dd4
F src/expr.c 3a43e508a3dc213703808bbcbb17633b88b57d17
F src/func.c 600e506bccf7648df8ad03efb417560d0f7ad4c1
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
@@ -54,19 +54,19 @@ F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c a43e2a392be51966129e9afb18b81551c9f222b8
F src/pager.h cbe4ba356d9dd3f30260f322b3dc77408164df14
F src/parse.y 4a27450611ed2b8c359078e04daf93c50b1d22dd
F src/parse.y e7f4e87a2ad14ccf5b8adcf1019fb8a355964579
F src/pragma.c 44e192eb5928157bdb015926f858a7c6e3ef6c98
F src/printf.c 7a92adc00b758cd5ce087dae80181a8bbdb70ed2
F src/random.c eff68e3f257e05e81eae6c4d50a51eb88beb4ff3
F src/select.c 156990c636102bb6b8de85e7ff3396a62568476b
F src/shell.c 55adda3cf3c1cc2f6c1919aac17b2318f9c2a96f
F src/sqlite.h.in 4f97b5907acfd2a5068cb0cec9d5178816734db7
F src/sqliteInt.h 8b93c9d7b7343b9013ffb73cbd2cb6ea4f546c62
F src/sqliteInt.h 126ec1947a91438a388112f3d282f625f7f73a0a
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008
F src/test1.c df1d1ca2c40cafefb9a29860f072c4d0fee1a7b5
F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8
F src/test3.c fdae1ed48add4b5df60f59a7c22e9d0b34265b55
F src/test3.c de9edf178c02707cd37fd80b54e4c2ea77251cc0
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
F src/tokenize.c bf9de9689b3bb813d65784bf54472804bf9595e6
@@ -75,7 +75,7 @@ F src/update.c 7b17b281d600bf3e220b3c5718e0883442dee722
F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed
F src/util.c 005fdf2d008f3429d081766ad6098fdd86d8d8e6
F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60
F src/vdbe.c cf7eb35b5a649c11345c5f85ad7b1511253431cc
F src/vdbe.c b324acdaff3b1f21cd369bbb0df30e1c3fa828f4
F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b
F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006
@@ -252,7 +252,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 59288db1ac5c0616296b26dce071c36cb611dfe9
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
P 1da361fae82d420be63c53f8e3efaccac24f348a
R 91d65eb4622d90500501298966d2317c
P 158a2d16a8630e3b5892120f6ea68f2b0dc47eb3
R 7e671e2bcee0e6583c9f1a1b858bd032
U drh
Z aa82f4ff31655559fe92ab11f9dd6086
Z 257ce5d18cf67227ffb08447220e1214

View File

@@ -1 +1 @@
158a2d16a8630e3b5892120f6ea68f2b0dc47eb3
10c3d88305e404b9e4cc4eef0b8e5dc7864a5937

View File

@@ -9,7 +9,7 @@
** May you share freely, never taking more than you give.
**
*************************************************************************
** $Id: btree.c,v 1.204 2004/11/04 14:30:05 danielk1977 Exp $
** $Id: btree.c,v 1.205 2004/11/05 00:43:12 drh Exp $
**
** This file implements a external (disk-based) database using BTrees.
** For a detailed discussion of BTrees, refer to
@@ -4412,6 +4412,18 @@ int sqlite3BtreeClearTable(Btree *pBt, int iTable){
**
** This routine will fail with SQLITE_LOCKED if there are any open
** cursors on the table.
**
** If AUTOVACUUM is enabled and the page at iTable is not the last
** root page in the database file, then the last root page
** in the database file is moved into the slot formerly occupied by
** iTable and that last slot formerly occupied by the last root page
** is added to the freelist instead of iTable. In this say, all
** root pages are kept at the beginning of the database file, which
** is necessary for AUTOVACUUM to work right. *piMoved is set to the
** page number that used to be the last root page in the file before
** the move. If no page gets moved, *piMoved is set to 0.
** The last root page is recorded in meta[3] and the value of
** meta[3] is updated by this procedure.
*/
int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){
int rc;
@@ -4434,7 +4446,7 @@ int sqlite3BtreeDropTable(Btree *pBt, int iTable, int *piMoved){
rc = sqlite3BtreeClearTable(pBt, iTable);
if( rc ) return rc;
if( piMoved ) *piMoved = 0;
*piMoved = 0;
if( iTable>1 ){
#ifdef SQLITE_OMIT_AUTOVACUUM
@@ -4521,8 +4533,9 @@ int sqlite3BtreeGetMeta(Btree *pBt, int idx, u32 *pMeta){
*pMeta = get4byte(&pP1[36 + idx*4]);
sqlite3pager_unref(pP1);
/* The current implementation is unable to handle writes to an autovacuumed
** database. So make such a database readonly. */
/* If autovacuumed is disabled in the implementation but we are
** trying to access an autovacuumed database, then make the
** database readonly. */
#ifdef SQLITE_OMIT_AUTOVACUUM
if( idx==4 && *pMeta>0 ) pBt->readOnly = 1;
#endif

View File

@@ -23,7 +23,7 @@
** ROLLBACK
** PRAGMA
**
** $Id: build.c,v 1.260 2004/11/04 14:47:12 drh Exp $
** $Id: build.c,v 1.261 2004/11/05 00:43:12 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@@ -54,6 +54,7 @@ void sqlite3FinishCoding(Parse *pParse){
Vdbe *v;
if( sqlite3_malloc_failed ) return;
if( pParse->nested ) return;
/* Begin by generating some termination code at the end of the
** vdbe program
@@ -112,6 +113,35 @@ void sqlite3FinishCoding(Parse *pParse){
pParse->cookieGoto = 0;
}
/*
** Run the parser and code generator recursively in order to generate
** code for the SQL statement given onto the end of the pParse context
** currently under construction. When the parser is run recursively
** this way, the final OP_Halt is not appended and other initialization
** and finalization steps are omitted because those are handling by the
** outermost parser.
**
** Not everything is nestable. This facility is designed to permit
** INSERT, UPDATE, and DELETE operations against SQLITE_MASTER. Use
** care if you decide to try to use this routine for some other purpose.
*/
void sqlite3NestedParse(Parse *pParse, const char *zFormat, ...){
va_list ap;
char *zSql;
int rc;
Parse savedState;
if( pParse->nErr ) return;
assert( pParse->nested<10 ); /* Nesting should only be of limited depth */
va_start(ap, zFormat);
zSql = sqlite3VMPrintf(zFormat, ap);
va_end(ap);
pParse->nested++;
savedState = *pParse;
rc = sqlite3RunParser(pParse, zSql, 0);
sqliteFree(zSql);
pParse->nested--;
}
/*
** Locate the in-memory structure that describes a particular database
** table given the name of that table and (optionally) the name of the
@@ -836,7 +866,12 @@ void sqlite3AddDefaultValue(Parse *pParse, Token *pVal, int minusFlag){
** If the key is not an INTEGER PRIMARY KEY, then create a unique
** index for the key. No index is created for INTEGER PRIMARY KEYs.
*/
void sqlite3AddPrimaryKey(Parse *pParse, ExprList *pList, int onError){
void sqlite3AddPrimaryKey(
Parse *pParse, /* Parsing context */
ExprList *pList, /* List of field names to be indexed */
int onError, /* What to do with a uniqueness conflict */
int autoInc /* True if the AUTOINCREMENT keyword is present */
){
Table *pTab = pParse->pNewTable;
char *zType = 0;
int iCol = -1, i;
@@ -867,6 +902,10 @@ void sqlite3AddPrimaryKey(Parse *pParse, ExprList *pList, int onError){
if( zType && sqlite3StrICmp(zType, "INTEGER")==0 ){
pTab->iPKey = iCol;
pTab->keyConf = onError;
pTab->autoInc = autoInc;
}else if( autoInc ){
sqlite3ErrorMsg(pParse, "AUTOINCREMENT is only allowed on an "
"INTEGER PRIMARY KEY");
}else{
sqlite3CreateIndex(pParse, 0, 0, 0, pList, onError, 0, 0);
pList = 0;

View File

@@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle DELETE FROM statements.
**
** $Id: delete.c,v 1.85 2004/11/04 04:42:28 drh Exp $
** $Id: delete.c,v 1.86 2004/11/05 00:43:12 drh Exp $
*/
#include "sqliteInt.h"
@@ -38,7 +38,8 @@ Table *sqlite3SrcListLookup(Parse *pParse, SrcList *pSrc){
** writable return 0;
*/
int sqlite3IsReadOnly(Parse *pParse, Table *pTab, int viewOk){
if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0 ){
if( pTab->readOnly && (pParse->db->flags & SQLITE_WriteSchema)==0
&& pParse->nested==0 ){
sqlite3ErrorMsg(pParse, "table %s may not be modified", pTab->zName);
return 1;
}

View File

@@ -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.147 2004/11/03 13:59:05 drh Exp $
** @(#) $Id: parse.y,v 1.148 2004/11/05 00:43:12 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@@ -213,7 +213,8 @@ carg ::= DEFAULT NULL.
//
ccons ::= NULL onconf.
ccons ::= NOT NULL onconf(R). {sqlite3AddNotNull(pParse, R);}
ccons ::= PRIMARY KEY sortorder onconf(R). {sqlite3AddPrimaryKey(pParse,0,R);}
ccons ::= PRIMARY KEY sortorder onconf(R) autoinc(I).
{sqlite3AddPrimaryKey(pParse,0,R,I);}
ccons ::= UNIQUE onconf(R). {sqlite3CreateIndex(pParse,0,0,0,0,R,0,0);}
ccons ::= CHECK LP expr RP onconf.
ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
@@ -221,6 +222,11 @@ ccons ::= REFERENCES nm(T) idxlist_opt(TA) refargs(R).
ccons ::= defer_subclause(D). {sqlite3DeferForeignKey(pParse,D);}
ccons ::= COLLATE id(C). {sqlite3AddCollateType(pParse, C.z, C.n);}
// The optional AUTOINCREMENT keyword
%type autoinc {int}
autoinc(X) ::= . {X = 0;}
autoinc(X) ::= AUTOINC. {X = 1;}
// The next group of rules parses the arguments to a REFERENCES clause
// that determine if the referential integrity checking is deferred or
// or immediate and which determine what action to take if a ref-integ
@@ -256,8 +262,8 @@ conslist ::= conslist COMMA tcons.
conslist ::= conslist tcons.
conslist ::= tcons.
tcons ::= CONSTRAINT nm.
tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
{sqlite3AddPrimaryKey(pParse,X,R);}
tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R) autoinc(I).
{sqlite3AddPrimaryKey(pParse,X,R,I);}
tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
{sqlite3CreateIndex(pParse,0,0,0,X,R,0,0);}
tcons ::= CHECK expr onconf.

View File

@@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.330 2004/11/04 14:30:05 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.331 2004/11/05 00:43:12 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@@ -573,6 +573,7 @@ struct Table {
u8 isTransient; /* True if automatically deleted when VDBE finishes */
u8 hasPrimKey; /* True if there exists a primary key */
u8 keyConf; /* What to do in case of uniqueness conflict on iPKey */
u8 autoInc; /* True if the integer primary key is autoincrement */
Trigger *pTrigger; /* List of SQL triggers on this table */
FKey *pFKey; /* Linked list of all foreign keys in this table */
char *zColAff; /* String defining the affinity of each column */
@@ -1010,6 +1011,7 @@ struct Parse {
u8 useAgg; /* If true, extract field values from the aggregator
** while generating expressions. Normally false */
u8 checkSchema; /* Causes schema cookie check after an error */
u8 nested; /* Number of nested calls to the parser/code generator */
int nErr; /* Number of errors seen */
int nTab; /* Number of previously allocated VDBE cursors */
int nMem; /* Number of memory cells used so far */
@@ -1254,7 +1256,7 @@ void sqlite3OpenMasterTable(Vdbe *v, int);
void sqlite3StartTable(Parse*,Token*,Token*,Token*,int,int);
void sqlite3AddColumn(Parse*,Token*);
void sqlite3AddNotNull(Parse*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int);
void sqlite3AddPrimaryKey(Parse*, ExprList*, int, int);
void sqlite3AddColumnType(Parse*,Token*,Token*);
void sqlite3AddDefaultValue(Parse*,Token*,int);
void sqlite3AddCollateType(Parse*, const char*, int);
@@ -1298,6 +1300,7 @@ void sqlite3ExprCode(Parse*, Expr*);
int sqlite3ExprCodeExprList(Parse*, ExprList*);
void sqlite3ExprIfTrue(Parse*, Expr*, int, int);
void sqlite3ExprIfFalse(Parse*, Expr*, int, int);
void sqlite3NextedParse(Parse*, const char*, ...);
Table *sqlite3FindTable(sqlite3*,const char*, const char*);
Table *sqlite3LocateTable(Parse*,const char*, const char*);
Index *sqlite3FindIndex(sqlite3*,const char*, const char*);

View File

@@ -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.55 2004/11/04 14:47:12 drh Exp $
** $Id: test3.c,v 1.56 2004/11/05 00:43:12 drh Exp $
*/
#include "sqliteInt.h"
#include "pager.h"
@@ -315,6 +315,7 @@ static int btree_drop_table(
Btree *pBt;
int iTable;
int rc;
int notUsed1;
if( argc!=3 ){
Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0],
" ID TABLENUM\"", 0);
@@ -322,7 +323,7 @@ static int btree_drop_table(
}
pBt = sqlite3TextToPtr(argv[1]);
if( Tcl_GetInt(interp, argv[2], &iTable) ) return TCL_ERROR;
rc = sqlite3BtreeDropTable(pBt, iTable, 0);
rc = sqlite3BtreeDropTable(pBt, iTable, &notUsed1);
if( rc!=SQLITE_OK ){
Tcl_AppendResult(interp, errorName(rc), 0);
return TCL_ERROR;

View File

@@ -43,7 +43,7 @@
** in this file for details. If in doubt, do not deviate from existing
** commenting and indentation practices when changing or adding code.
**
** $Id: vdbe.c,v 1.423 2004/11/04 14:30:06 danielk1977 Exp $
** $Id: vdbe.c,v 1.424 2004/11/05 00:43:12 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@@ -2813,12 +2813,19 @@ case OP_NotExists: {
break;
}
/* Opcode: NewRecno P1 * *
/* Opcode: NewRecno P1 P2 *
**
** Get a new integer record number used as the key to a table.
** The record number is not previously used as a key in the database
** table that cursor P1 points to. The new record number is pushed
** onto the stack.
**
** If P2>0 then P2 is a memory cell that holds the largest previously
** generated record number. No new record numbers are allowed to be less
** than this value. When this value reaches 0x7fffffff, a SQLITE_FULL
** error is generated. The P2 memory cell is updated with the generated
** record number. This P2 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
case OP_NewRecno: {
int i = pOp->p1;
@@ -2882,6 +2889,24 @@ case OP_NewRecno: {
}
}
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pOp->p2 ){
Mem *pMem;
assert( pOp->p2>0 && pOp->p2<p->nMem ); /* P2 is a valid memory cell */
pMem = &p->aMem[pOp->p2];
assert( (pMem->flags & MEM_Int)!=0 ); /* mem(P2) holds an integer */
if( pMem->i==0x7fffffffffffffff || pC->useRandomRowid ){
rc = SQLITE_FULL;
goto abort_due_to_error;
}
if( v<pMem->i+1 ){
v = pMem->i + 1;
}
pMem->i = v;
}
#endif
if( v<0x7fffffffffffffff ){
pC->nextRowidValid = 1;
pC->nextRowid = v+1;
@@ -2890,6 +2915,7 @@ case OP_NewRecno: {
}
}
if( pC->useRandomRowid ){
assert( pOp->p2==0 ); /* SQLITE_FULL must have occurred prior to this */
v = db->priorNewRowid;
cnt = 0;
do{
@@ -3607,15 +3633,24 @@ case OP_IdxIsNull: {
** P2==1 then the table to be clear is in the auxiliary database file
** that is used to store tables create using CREATE TEMPORARY TABLE.
**
** If AUTOVACUUM is enabled then it is possible that another root page
** might be moved into the newly deleted root page in order to keep all
** root pages contiguous at the beginning of the database. The former
** value of the root page that moved - its value before the move occurred -
** is pushed onto the stack. If no page movement was required (because
** the table being dropped was already the last one in the database) then
** a zero is pushed onto the stack. If AUTOVACUUM is disabled at
** then a zero is pushed onto the stack.
**
** See also: Clear
*/
case OP_Destroy: {
int iMoved;
rc = sqlite3BtreeDropTable(db->aDb[pOp->p2].pBt, pOp->p1, &iMoved);
#ifndef SQLITE_OMIT_AUTOVACUUM
pTos++;
pTos->flags = MEM_Int;
pTos->i = iMoved;
#ifndef SQLITE_OMIT_AUTOVACUUM
if( iMoved!=0 ){
sqlite3RootPageMoved(&db->aDb[pOp->p2], iMoved, pOp->p1);
}
@@ -4071,6 +4106,30 @@ case OP_MemLoad: {
break;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Opcode: MemMax P1 * *
**
** Set the value of memory cell P1 to the maximum of its current value
** and the value on the top of the stack. The stack is unchanged.
**
** This instruction throws an error if the memory cell is not initially
** an integer.
*/
case OP_MemMax: {
int i = pOp->p1;
Mem *pMem;
assert( pTos>=p->aStack );
assert( i>=0 && i<p->nMem );
pMem = &p->aMem[i];
assert( pMem->flags==MEM_Int );
Integerify(pTos);
if( pMem->i<pTos->i){
pMem->i = pTos->i;
}
break;
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Opcode: MemIncr P1 P2 *
**
** Increment the integer valued memory cell P1 by 1. If P2 is not zero