Autoincrement code installed. Simple smoke-testing only. No regression

tests developed yet. (CVS 2091)

FossilOrigin-Name: 8fde833c812b91c5a574208a70b5f92b9d4b0a87
This commit is contained in:
drh 2004-11-12 03:56:15 +00:00
parent 817c60bd66
commit 2958a4e6a5
9 changed files with 135 additions and 40 deletions

View File

@ -1,5 +1,5 @@
C Website\supdates.\s(CVS\s2090)
D 2004-11-11T19:32:40
C Autoincrement\scode\sinstalled.\s\sSimple\ssmoke-testing\sonly.\s\sNo\sregression\ntests\sdeveloped\syet.\s(CVS\s2091)
D 2004-11-12T03:56:15
F Makefile.in c4d2416860f472a1e3393714d0372074197565df
F Makefile.linux-gcc a9e5a0d309fa7c38e7c14d3ecf7690879d3a5457
F README a01693e454a00cc117967e3f9fdab2d4d52e9bc1
@ -31,14 +31,14 @@ F src/attach.c e49d09dad9f5f9fb10b4b0c1be5a70ae4c45e689
F src/auth.c 3b81f2a42f48a62c2c9c9b0eda31a157c681edea
F src/btree.c 9fd74df65bad768a441afefc3b73174d45b85d5b
F src/btree.h 861e40b759a195ba63819740e484390012cf81ab
F src/build.c 27e3cc9e5d5187fa6f23d2e60b76e82c4bc0e7b0
F src/build.c 6d1687c66138af18e210981465ee342fe36985d3
F src/date.c 4fd4e90b3880dacd67305e96330940dc243ffc10
F src/delete.c f0af21a1ede15524a5edd59fe10ef486283a1ee9
F src/expr.c 5f9afecf27e048b8f3627b5a9be3136bc1d9bdf1
F src/expr.c 4ee3e47358c92a919062255b14057a7a8f641e01
F src/func.c 600e506bccf7648df8ad03efb417560d0f7ad4c1
F src/hash.c a97721a55440b7bea31ffe471bb2f6b4123cddd5
F src/hash.h 1b0c445e1c89ff2aaad9b4605ba61375af001e84
F src/insert.c 8bd40dc5a8e470cba5b9b14211fa88ea0350d2fa
F src/insert.c e80b009f9ef2864bbaaaae836286f56125a180f6
F src/legacy.c d58ea507bce885298a2c8c3cbb0f4bff5d47830b
F src/main.c c7dc54c62c86cab8b2e2883aef607c179eefa611
F src/md5.c 7ae1c39044b95de2f62e066f47bb1deb880a1070
@ -54,14 +54,14 @@ F src/os_win.c 9482dfc92f289b68205bb2c9315757c7e3946bfb
F src/os_win.h 41a946bea10f61c158ce8645e7646b29d44f122b
F src/pager.c ee88fcecb081e3635c281bc09d604e934429e2f5
F src/pager.h 9eba8c53dd91eae7f3f90743b2ee242da02a9862
F src/parse.y 02e0d88a6d465f6fd5ea79a200a8c23c92a877dc
F src/parse.y 91a01b5f1170a574b4b9f19871b32bd0f00923a9
F src/pragma.c bb1c76dae9911b9312997b353c1e316fa603a0c6
F src/printf.c 3d20b21cfecadacecac3fb7274e746cb81d3d357
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 701cbd435750eb854032eaa42e9a12499934e6ce
F src/sqliteInt.h 0fdf2b0cf6f2db12c4abefad0f1085268d911f74
F src/table.c 25b3ff2b39b7d87e8d4a5da0713d68dfc06cbee9
F src/tclsqlite.c 0302e3f42f015d132d1291f3388c06e86c24a008
F src/test1.c e80e070fe794cdc204ec144ce03bd7b27dab4946
@ -69,13 +69,13 @@ F src/test2.c b11fa244fff02190707dd0879987c37c75e61fc8
F src/test3.c 6f1ec93e13632a004b527049535079eda84c459d
F src/test4.c 7c6b9fc33dd1f3f93c7f1ee6e5e6d016afa6c1df
F src/test5.c b001fa7f1b9e2dc5c2331de62fc641b5ab2bd7a1
F src/tokenize.c c48221284e729be067237a8cfd7848fb62ee4a92
F src/tokenize.c 4dc14256d80d25da622d506bfe3b817153b97032
F src/trigger.c f9a0a8d3a87238de1a934eeb7d0b6b1f13e6a55b
F src/update.c 3cc67f6053495152e82a6a48c93ed331218e936e
F src/utf.c f4f83acd73389090e32d6589d307fc55d794c7ed
F src/util.c 005fdf2d008f3429d081766ad6098fdd86d8d8e6
F src/vacuum.c ecb4a2c6f1ac5cc9b394dc64d3bb14ca650c4f60
F src/vdbe.c 8bc549adf596ee792facd229ee7f7bfc0b690ad4
F src/vdbe.c 0fd9437a288b19681856ef3f803bfde6858567f1
F src/vdbe.h 067ca8d6750ba4f69a50284765e5883dee860181
F src/vdbeInt.h 6017100adff362b8dfa37a69e3f1431f084bfa5b
F src/vdbeapi.c 3965bf4678ae32c05f73550c1b5be3268f9f3006
@ -255,7 +255,7 @@ F www/tclsqlite.tcl 560ecd6a916b320e59f2917317398f3d59b7cc25
F www/vdbe.tcl 095f106d93875c94b47367384ebc870517431618
F www/version3.tcl 092a01f5ef430d2c4acc0ae558d74c4bb89638a0
F www/whentouse.tcl fdacb0ba2d39831e8a6240d05a490026ad4c4e4c
P d28d1d68e5104726e6088361dfa7bf2cdd9985c7
R d5f119c36b99dc5061fef0d1b11f7246
P 60fb0cef093b9827ac2d36b8a94e37f4b79dd2ea
R ab6b6f9534118088586ec8c53a8170c1
U drh
Z f55195d01ac4ebd4d023505baea63851
Z 72c9d0289de8ee06d1a20ab843f47f3d

View File

@ -1 +1 @@
60fb0cef093b9827ac2d36b8a94e37f4b79dd2ea
8fde833c812b91c5a574208a70b5f92b9d4b0a87

View File

@ -22,7 +22,7 @@
** COMMIT
** ROLLBACK
**
** $Id: build.c,v 1.275 2004/11/10 11:55:12 danielk1977 Exp $
** $Id: build.c,v 1.276 2004/11/12 03:56:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -321,6 +321,7 @@ void sqlite3ResetInternalSchema(sqlite3 *db, int iDb){
sqlite3DeleteTable(db, pTab);
}
sqlite3HashClear(&temp1);
pDb->pSeqTab = 0;
DbClearProperty(db, i, DB_SchemaLoaded);
if( iDb>0 ) return;
}
@ -517,12 +518,15 @@ void sqlite3OpenMasterTable(Vdbe *v, int iDb){
int findDb(sqlite3 *db, Token *pName){
int i;
Db *pDb;
char *zName = sqlite3NameFromToken(pName);
int n = strlen(zName);
for(pDb=db->aDb, i=0; i<db->nDb; i++, pDb++){
if( pName->n==strlen(pDb->zName) &&
0==sqlite3StrNICmp(pDb->zName, pName->z, pName->n) ){
if( n==strlen(pDb->zName) && 0==sqlite3StrICmp(pDb->zName, zName) ){
sqliteFree(zName);
return i;
}
}
sqliteFree(zName);
return -1;
}
@ -720,7 +724,6 @@ void sqlite3StartTable(
*/
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( strcmp(zName, "sqlite_sequence")==0 ){
assert( db->aDb[iDb].pSeqTab==0 );
db->aDb[iDb].pSeqTab = pTable;
}
#endif
@ -1452,13 +1455,34 @@ void sqlite3EndTable(Parse *pParse, Token *pEnd, Select *pSelect){
zStmt
);
sqliteFree(zStmt);
sqlite3ChangeCookie(db, v, p->iDb);
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Check to see if we need to create an sqlite_sequence table for
** keeping track of autoincrement keys.
*/
if( p->autoInc ){
Db *pDb = &db->aDb[p->iDb];
if( pDb->pSeqTab==0 ){
sqlite3NestedParse(pParse,
"CREATE TABLE %Q.sqlite_sequence AS SELECT %Q AS name, 0 AS seq;",
pDb->zName, p->zName
);
}else{
sqlite3NestedParse(pParse,
"INSERT INTO %Q.sqlite_sequence VALUES(%Q,0)",
pDb->zName, p->zName
);
}
}
#endif
/* Reparse everything to update our internal data structures */
sqlite3ChangeCookie(db, v, p->iDb);
sqlite3VdbeOp3(v, OP_ParseSchema, p->iDb, 0,
sqlite3MPrintf("tbl_name='%q'",p->zName), P3_DYNAMIC);
}
/* Add the table to the in-memory representation of the database.
*/
if( db->init.busy && pParse->nErr==0 ){
@ -1807,7 +1831,9 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
v = sqlite3GetVdbe(pParse);
if( v ){
Trigger *pTrigger;
sqlite3BeginWriteOperation(pParse, 0, pTab->iDb);
int iDb = pTab->iDb;
Db *pDb = &db->aDb[iDb];
sqlite3BeginWriteOperation(pParse, 0, iDb);
/* Drop all triggers associated with the table being dropped. Code
** is generated to remove entries from sqlite_master and/or
@ -1815,7 +1841,7 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
*/
pTrigger = pTab->pTrigger;
while( pTrigger ){
assert( pTrigger->iDb==pTab->iDb || pTrigger->iDb==1 );
assert( pTrigger->iDb==iDb || pTrigger->iDb==1 );
sqlite3DropTriggerPtr(pParse, pTrigger, 1);
pTrigger = pTrigger->pNext;
}
@ -1829,11 +1855,25 @@ void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView){
*/
sqlite3NestedParse(pParse,
"DELETE FROM %Q.%s WHERE tbl_name=%Q and type!='trigger'",
db->aDb[pTab->iDb].zName, SCHEMA_TABLE(pTab->iDb), pTab->zName);
pDb->zName, SCHEMA_TABLE(iDb), pTab->zName);
if( !isView ){
destroyTable(pParse, pTab);
}
sqlite3VdbeOp3(v, OP_DropTable, pTab->iDb, 0, pTab->zName, 0);
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Remove any entries of the sqlite_sequence table associated with
** the table being dropped */
if( pTab->autoInc ){
sqlite3NestedParse(pParse,
"DELETE FROM %s.sqlite_sequence WHERE name=%Q",
pDb->zName, pTab->zName
);
}
#endif
/* Remove the table entry from SQLite's internal schema
*/
sqlite3VdbeOp3(v, OP_DropTable, iDb, 0, pTab->zName, 0);
}
sqliteViewResetAll(db, iDb);

View File

@ -12,7 +12,7 @@
** This file contains routines used for analyzing expressions and
** for generating VDBE code that evaluates expressions in SQLite.
**
** $Id: expr.c,v 1.169 2004/11/09 12:44:38 danielk1977 Exp $
** $Id: expr.c,v 1.170 2004/11/12 03:56:15 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
@ -202,7 +202,8 @@ Expr *sqlite3Expr(int op, Expr *pLeft, Expr *pRight, Token *pToken){
** When doing a nested parse, you can include terms in an expression
** that look like this: #0 #1 #2 ... These terms refer to elements
** on the stack. "#0" (or just "#") means the top of the stack.
** "#1" means the next down on the stack. And so forth.
** "#1" means the next down on the stack. And so forth. #-1 means
** memory location 0. #-2 means memory location 1. And so forth.
**
** This routine is called by the parser to deal with on of those terms.
** It immediately generates code to store the value in a memory location.
@ -220,9 +221,13 @@ Expr *sqlite3RegisterExpr(Parse *pParse, Token *pToken){
}
p = sqlite3Expr(TK_REGISTER, 0, 0, pToken);
depth = atoi(&pToken->z[1]);
p->iTable = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
if( depth>=0 ){
p->iTable = pParse->nMem++;
sqlite3VdbeAddOp(v, OP_Dup, depth, 0);
sqlite3VdbeAddOp(v, OP_MemStore, p->iTable, 1);
}else{
p->iTable = -1-depth;
}
return p;
}

View File

@ -12,7 +12,7 @@
** This file contains C code routines that are called by the parser
** to handle INSERT statements in SQLite.
**
** $Id: insert.c,v 1.124 2004/11/09 12:44:38 danielk1977 Exp $
** $Id: insert.c,v 1.125 2004/11/12 03:56:15 drh Exp $
*/
#include "sqliteInt.h"
@ -189,6 +189,8 @@ void sqlite3Insert(
int iInsertBlock = 0; /* Address of the subroutine used to insert data */
int iCntMem = 0; /* Memory cell used for the row counter */
int newIdx = -1; /* Cursor for the NEW table */
Db *pDb; /* The database containing table being inserted into */
int counterMem = 0; /* Memory cell holding AUTOINCREMENT counter */
#ifndef SQLITE_OMIT_TRIGGER
int isView; /* True if attempting to insert into a view */
@ -210,7 +212,8 @@ void sqlite3Insert(
goto insert_cleanup;
}
assert( pTab->iDb<db->nDb );
zDb = db->aDb[pTab->iDb].zName;
pDb = &db->aDb[pTab->iDb];
zDb = pDb->zName;
if( sqlite3AuthCheck(pParse, SQLITE_INSERT, pTab->zName, 0, zDb) ){
goto insert_cleanup;
}
@ -270,6 +273,21 @@ void sqlite3Insert(
newIdx = pParse->nTab++;
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* If this is an AUTOINCREMENT table, look up the sequence number in the
** sqlite_sequence table and store it in a memory cell. Create a new
** sqlite_sequence table entry if one does not already exist.
*/
if( pTab->autoInc ){
counterMem = ++pParse->nMem;
assert( counterMem>0 ); /* Must be so for OP_NewRecno to work right */
sqlite3NestedParse(pParse,
"SELECT seq FROM %Q.sqlite_sequence WHERE name=%Q INTO %d",
pDb->zName, pTab->zName, counterMem
);
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Figure out how many columns of data are supplied. If the data
** is coming from a SELECT statement, then this step also generates
** all the code to implement the SELECT statement and invoke a subroutine
@ -545,11 +563,16 @@ void sqlite3Insert(
*/
sqlite3VdbeAddOp(v, OP_NotNull, -1, sqlite3VdbeCurrentAddr(v)+3);
sqlite3VdbeAddOp(v, OP_Pop, 1, 0);
sqlite3VdbeAddOp(v, OP_NewRecno, base, 0);
sqlite3VdbeAddOp(v, OP_NewRecno, base, counterMem);
sqlite3VdbeAddOp(v, OP_MustBeInt, 0, 0);
}else{
sqlite3VdbeAddOp(v, OP_NewRecno, base, 0);
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( pTab->autoInc ){
sqlite3VdbeAddOp(v, OP_MemMax, counterMem, 0);
}
#endif /* SQLITE_OMIT_AUTOINCREMENT */
/* Push onto the stack, data for all columns of the new entry, beginning
** with the first column.
@ -633,6 +656,17 @@ void sqlite3Insert(
}
}
#ifndef SQLITE_OMIT_AUTOINCREMENT
/* Update the sqlite_sequence table
*/
if( pTab->autoInc ){
sqlite3NestedParse(pParse,
"UPDATE %Q.sqlite_sequence SET seq=#-%d WHERE name=%Q",
pDb->zName, counterMem+1, pTab->zName
);
}
#endif
/*
** Return the number of rows inserted. If this routine is
** generating code because of a call to sqlite3NestedParse(), do not

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.152 2004/11/09 16:13:33 danielk1977 Exp $
** @(#) $Id: parse.y,v 1.153 2004/11/12 03:56:15 drh Exp $
*/
%token_prefix TK_
%token_type {Token}
@ -150,7 +150,7 @@ id(A) ::= ID(X). {A = X;}
%ifdef SQLITE_OMIT_COMPOUND_SELECT
EXCEPT INTERSECT UNION
%endif
REINDEX RENAME AUTOINCR CDATE CTIME CTIMESTAMP ALTER
REINDEX RENAME CDATE CTIME CTIMESTAMP ALTER
.
// Define operator precedence early so that this is the first occurance
@ -230,8 +230,8 @@ 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;}
autoinc(X) ::= . {X = 0;}
autoinc(X) ::= AUTOINCR. {X = 1;}
// The next group of rules parses the arguments to a REFERENCES clause
// that determine if the referential integrity checking is deferred or
@ -320,6 +320,21 @@ cmd ::= select(X). {
sqlite3SelectDelete(X);
}
%ifndef SQLITE_OMIT_AUTOINCREMENT
// The INTO clause after a select only works in nested mode. It causes
// the result of the SELECT to be stored in a memory register of the
// virtual machine.
//
cmd ::= select(X) INTO INTEGER(M). {
if( pParse->nested ){
sqlite3Select(pParse, X, SRT_Mem, atoi(M.z), 0, 0, 0, 0);
}else{
sqlite3ErrorMsg(pParse, "near \"INTO\": syntax error");
}
sqlite3SelectDelete(X);
}
%endif // SQLITE_OMIT_AUTOINCREMENT
%type select {Select*}
%destructor select {sqlite3SelectDelete($$);}
%type oneselect {Select*}

View File

@ -11,7 +11,7 @@
*************************************************************************
** Internal interface definitions for SQLite.
**
** @(#) $Id: sqliteInt.h,v 1.337 2004/11/10 15:27:38 danielk1977 Exp $
** @(#) $Id: sqliteInt.h,v 1.338 2004/11/12 03:56:15 drh Exp $
*/
#ifndef _SQLITEINT_H_
#define _SQLITEINT_H_
@ -1457,5 +1457,6 @@ sqlite3_value *sqlite3GetTransientValue(sqlite3*db);
extern const unsigned char sqlite3UpperToLower[];
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
void sqlite3NestedParse(Parse*, const char*, ...);
#endif

View File

@ -15,7 +15,7 @@
** individual tokens and sends those tokens one-by-one over to the
** parser for analysis.
**
** $Id: tokenize.c,v 1.95 2004/11/05 05:10:29 drh Exp $
** $Id: tokenize.c,v 1.96 2004/11/12 03:56:15 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -178,7 +178,7 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){
return 1;
}
case '#': {
for(i=1; isdigit(z[i]); i++){}
for(i=1; isdigit(z[i]) || (i==1 && z[1]=='-'); i++){}
*tokenType = TK_REGISTER;
return i;
}
@ -409,7 +409,7 @@ abort_parse:
pParse->zErrMsg = 0;
if( !nErr ) nErr++;
}
if( pParse->pVdbe && pParse->nErr>0 ){
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){
sqlite3VdbeDelete(pParse->pVdbe);
pParse->pVdbe = 0;
}

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.425 2004/11/10 11:55:13 danielk1977 Exp $
** $Id: vdbe.c,v 1.426 2004/11/12 03:56:15 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
@ -2822,7 +2822,7 @@ case OP_NotExists: {
**
** 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
** than this value. When this value reaches its maximum, 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.