-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
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
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
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
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
-60fb0cef093b9827ac2d36b8a94e37f4b79dd2ea
\ No newline at end of file
+8fde833c812b91c5a574208a70b5f92b9d4b0a87
\ No newline at end of file
** 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>
sqlite3DeleteTable(db, pTab);
}
sqlite3HashClear(&temp1);
+ pDb->pSeqTab = 0;
DbClearProperty(db, i, DB_SchemaLoaded);
if( iDb>0 ) return;
}
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;
}
*/
#ifndef SQLITE_OMIT_AUTOINCREMENT
if( strcmp(zName, "sqlite_sequence")==0 ){
- assert( db->aDb[iDb].pSeqTab==0 );
db->aDb[iDb].pSeqTab = pTable;
}
#endif
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 ){
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
*/
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;
}
*/
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);
** 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>
** 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.
}
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;
}
** 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"
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 */
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;
}
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
*/
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.
}
}
+#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
** 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}
%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
// 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
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*}
*************************************************************************
** 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_
extern const unsigned char sqlite3UpperToLower[];
void sqlite3RootPageMoved(Db*, int, int);
void sqlite3Reindex(Parse*, Token*, Token*);
+void sqlite3NestedParse(Parse*, const char*, ...);
#endif
** 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"
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;
}
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;
}
** 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"
**
** 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.