-C Added\simplementations\sfor\ssqliteOsEnterMutex()\sand\ssqliteOsLeaveMutex().\s(CVS\s348)
-D 2002-01-15T18:39:44
+C Added\sthe\slast_insert_rowid\sAPI\sfunction.\s\sImproved\sdocumentation\sof\nthe\srandom\sROWID\salgorithm.\s(CVS\s349)
+D 2002-01-16T21:00:27
F Makefile.in 9fa4277413bf1d9cf91365f07d4108d7d87ed2af
F Makefile.template 3e26a3b9e7aee1b811deaf673e8d8973bdb3f22d
F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0
-F VERSION e4851f0e1fd8b7411787e28c5062067c23d706f1
+F VERSION da55054c39447bab51e716c492a9fa987086fa17
F aclocal.m4 11faa843caa38fd451bc6aeb43e248d1723a269d
F config.guess f38b1e93d1e0fa6f5a6913e9e7b12774b9232588
F config.log 6a73d03433669b10a3f0c221198c3f26b9413914
F src/hash.c 8f7c740ef2eaaa8decfa8751f2be30680b123e46
F src/hash.h a5f5b3ce2d086a172c5879b0b06a27a82eac9fac
F src/insert.c 813c37719866c583e6ca7660f94f10230f4e385d
-F src/main.c bdce5ed20f2828cd5b390c3880d5820b70e09871
+F src/main.c 0205771a6c31a9858ff131fc1e797b589afb76bf
F src/md5.c 52f677bfc590e09f71d07d7e327bd59da738d07c
F src/os.c c615faa4d23e742e0650e0751a6ad2a18438ad53
F src/os.h 5405a5695bf16889d4fc6caf9d42043caa41c269
F src/pager.h f78d064c780855ff70beacbeba0e2324471b26fe
F src/parse.y f3fc4fb5766393003577bd175eb611495f6efd9f
F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d
-F src/random.c 2a9cc2c9716d14815fd4c2accf89d87a1143e46b
+F src/random.c f6b36bec5ebd3edb3440224bf5bf811fe4ac9a1b
F src/select.c bddd8b5d07ffdae0d798c10b20dc7167469a3904
F src/shell.c 539a41d4121ed371d438d57d829e53056a54471c
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in a4c11d38d62b1bfbd50a5804edee8ca54c1adc9b
-F src/sqliteInt.h 7a7c5213a422e29883dcfe4c07d1f1def24f03fd
+F src/sqlite.h.in f57074c84a2c112a5093ba7a9d9636aa9cacc87c
+F src/sqliteInt.h 2382456c76bd66d0255d385820af1c72c961540c
F src/table.c c89698bd5bb4b8d14722d6ee7e9be014c383d24a
-F src/tclsqlite.c b82e4faeae89fdb7304b3c970979ade299336a1f
-F src/test1.c 41eabe255970ef947263b94145c9b2766bab8675
+F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d
+F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f
F src/test2.c e9f99aa5ee73872819259d6612c11e55e1644321
F src/test3.c d6775f95fd91f5b3cf0e2382a28e5aaeb68f745b
F src/tokenize.c 830e9ef684334070a26583d94770bb869e2727bf
F src/update.c 5cb326ed4bace89cbad7d919b828da6c2a9064e4
F src/util.c 3958a14a2dbfb13fa5f779976b4d0daf9ab49bb1
-F src/vdbe.c 7c64ac039a603036ce08d4f1dda3856d2825d3b6
+F src/vdbe.c 158bab65e4eafceb75a83f616caafa2c58f00242
F src/vdbe.h e5cc6fb13d1905a4339db4d6dba4ab393c0765fa
F src/where.c a9b286ac7323e7ebed5d3d217b3963acf1e6a355
F test/all.test 2a51e5395ac7c2c539689b123b9782a05e3837fe
F test/index.test c8a471243bbf878974b99baf5badd59407237cf3
F test/insert.test a5c122aa726f1cef6f07d6767e8fd6f220994c11
F test/insert2.test d6901ca931e308fea7fca8c95ebe7dc957cc9fc2
-F test/intpkey.test c9f427cb7b74835deeef112ed7f2af13d2ad662b
+F test/intpkey.test d6c7f42679b3f87da3933f5dddac92c822dd89c5
F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a
F test/limit.test a930f3eba2a7691c8397ccab33710b931589566a
F test/lock.test 19593689260c419efe7ced55b1418653a4b7bcd1
F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78
F test/table.test 3ef4254d62ece31a3872ab11cdaec846f6fa8fd1
F test/tableapi.test 51d0c209aa6b1158cb952ec917c656d4ce66e9e4
-F test/tclsqlite.test 9cbac5a39e78851df6b3608d3cc6b71617407bdd
+F test/tclsqlite.test ca8dd89b02ab68bd4540163c24551756a69f6783
F test/temptable.test 0e9934283259a5e637eec756a7eefd6964c0f79b
F test/tester.tcl 96db1b49157388edb57e11bf33285e3811a897e4
F test/trans.test 9e49495c06b1c41f889bf4f0fb195a015b126de0
F www/arch.fig d5f9752a4dbf242e9cfffffd3f5762b6c63b3bcf
F www/arch.png 82ef36db1143828a7abc88b1e308a5f55d4336f4
F www/arch.tcl 72a0c80e9054cc7025a50928d28d9c75c02c2b8b
-F www/c_interface.tcl 9123810452845783fac8e3184929463d9e70d609
-F www/changes.tcl a3499bf739cd6eecfdfab30485a51a96a048a775
+F www/c_interface.tcl 82a026b1681757f13b3f62e035f3a31407c1d353
+F www/changes.tcl 21116410e94d5f0852b49880ddf65f390423f24c
F www/crosscompile.tcl 3622ebbe518927a3854a12de51344673eb2dd060
F www/download.tcl 1ea61f9d89a2a5a9b2cee36b0d5cf97321bdefe0
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
-F www/faq.tcl f475a9ca61697d6d9cdae5497fa1a539df3f7e05
+F www/faq.tcl 324ec51080e5c3d62ccce4fb22a8b839eaded694
F www/formatchng.tcl d96e5e937dcbbebd481720aa08745ca5a906a63f
F www/index.tcl 571c585a5c0b577db2fe7cb88cf1f12cccd96ceb
F www/lang.tcl 6843fd3f85cba95fd199a350533ce742c706603c
F www/opcode.tcl bdec8ef9f100dbd87bbef8976c54b88e43fd8ccc
F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5
F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279
-F www/tclsqlite.tcl 880ef67cb4f2797b95bf1368fc4e0d8ca0fda956
+F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49
F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218
-P f3038d218c91b44b70b75a7b881ea24c87fa6a02
-R afcefb473faa5582942ee6c805ad94f5
+P f8a026a3ca14ef0b0d562029dd6b184f060457f4
+R 0e682a68cf7bb91386b1d3da8599787d
U drh
-Z ddd0c4146a965f893289115586945425
+Z 80f27b8d44ccea1a5a5d9cef7e210848
-f8a026a3ca14ef0b0d562029dd6b184f060457f4
\ No newline at end of file
+f74d61aaf3fec06cde2c4a6f1465f86ac9058ad2
\ No newline at end of file
** other files are for internal use by SQLite and should not be
** accessed by users of the library.
**
-** $Id: main.c,v 1.55 2002/01/10 14:31:49 drh Exp $
+** $Id: main.c,v 1.56 2002/01/16 21:00:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
db->flags &= ~SQLITE_Initialized;
}
+/*
+** Return the ROWID of the most recent insert
+*/
+int sqlite_last_insert_rowid(sqlite *db){
+ return db->lastRowid;
+}
+
/*
** Close an existing SQLite database
*/
** Random numbers are used by some of the database backends in order
** to generate random integer keys for tables or random filenames.
**
-** $Id: random.c,v 1.8 2001/10/09 04:19:47 drh Exp $
+** $Id: random.c,v 1.9 2002/01/16 21:00:27 drh Exp $
*/
#include "sqliteInt.h"
#include "os.h"
+
/*
** Get a single 8-bit random value from the RC4 PRNG. The Mutex
** must be held while executing this routine.
+**
+** Why not just use a library random generator like lrand48() for this?
+** Because the OP_NewRecno opcode in the VDBE depends on having a very
+** good source of random numbers. The lrand48() library function may
+** well be good enough. But maybe not. Or maybe lrand48() has some
+** subtle problems on some systems that could cause problems. It is hard
+** to know. To minimize the risk of problems due to bad lrand48()
+** implementations, SQLite uses is this random number generator based
+** on RC4, which we know works very well.
*/
static int randomByte(){
int t;
** This header file defines the interface that the SQLite library
** presents to client programs.
**
-** @(#) $Id: sqlite.h.in,v 1.24 2001/12/22 14:49:25 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.25 2002/01/16 21:00:27 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
#define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */
#define SQLITE_MISMATCH 20 /* Data type mismatch */
+/*
+** Each entry in an SQLite table has a unique integer key. (The key is
+** the value of the INTEGER PRIMARY KEY column if there is such a column,
+** otherwise the key is generated at random. The unique key is always
+** available as the ROWID, OID, or _ROWID_ column.) The following routine
+** returns the integer key of the most recent insert in the database.
+**
+** This function is similar to the mysql_insert_id() function from MySQL.
+*/
+int sqlite_last_insert_rowid(sqlite*);
+
/* If the parameter to this routine is one of the return value constants
** defined above, then this routine returns a constant text string which
** descripts (in English) the meaning of the return value.
*************************************************************************
** Internal interface definitions for SQLite.
**
-** @(#) $Id: sqliteInt.h,v 1.76 2002/01/09 03:20:00 drh Exp $
+** @(#) $Id: sqliteInt.h,v 1.77 2002/01/16 21:00:27 drh Exp $
*/
#include "sqlite.h"
#include "hash.h"
Hash idxHash; /* All (named) indices indexed by name */
Hash tblDrop; /* Uncommitted DROP TABLEs */
Hash idxDrop; /* Uncommitted DROP INDEXs */
+ int lastRowid; /* ROWID of most recent insert */
int nextRowid; /* Next generated rowID */
};
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.28 2001/11/09 13:41:10 drh Exp $
+** $Id: tclsqlite.c,v 1.29 2002/01/16 21:00:27 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
SqliteDb *pDb = (SqliteDb*)cd;
int choice;
static char *DB_optStrs[] = {
- "busy", "close", "complete", "eval", "timeout", 0
+ "busy", "close", "complete", "eval", "last_insert_rowid", "timeout", 0
};
enum DB_opts {
- DB_BUSY, DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_TIMEOUT
+ DB_BUSY, DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_LAST_INSERT_ROWID, DB_TIMEOUT
};
if( objc<2 ){
return rc;
}
+ /*
+ ** $db last_insert_rowid
+ **
+ ** Return an integer which is the ROWID for the most recent insert.
+ */
+ case DB_LAST_INSERT_ROWID: {
+ Tcl_Obj *pResult;
+ int rowid;
+ if( objc!=2 ){
+ Tcl_WrongNumArgs(interp, 2, objv, "");
+ return TCL_ERROR;
+ }
+ rowid = sqlite_last_insert_rowid(pDb->db);
+ pResult = Tcl_GetObjResult(interp);
+ Tcl_SetIntObj(pResult, rowid);
+ break;
+ }
+
/*
** $db timeout MILLESECONDS
**
** is not included in the SQLite library. It is used for automated
** testing of the SQLite library.
**
-** $Id: test1.c,v 1.5 2001/11/08 00:45:21 drh Exp $
+** $Id: test1.c,v 1.6 2002/01/16 21:00:27 drh Exp $
*/
#include "sqliteInt.h"
#include "tcl.h"
return TCL_OK;
}
+
+/*
+** Usage: sqlite_last_insert_rowid DB
+**
+** Returns the integer ROWID of the most recent insert.
+*/
+static int test_last_rowid(
+ void *NotUsed,
+ Tcl_Interp *interp, /* The TCL interpreter that invoked this command */
+ int argc, /* Number of arguments */
+ char **argv /* Text of each argument */
+){
+ sqlite *db;
+ char zBuf[30];
+
+ if( argc!=2 ){
+ Tcl_AppendResult(interp, "wrong # args: should be \"", argv[0], " DB\"", 0);
+ return TCL_ERROR;
+ }
+ db = (sqlite*)atoi(argv[1]);
+ sprintf(zBuf, "%d", sqlite_last_insert_rowid(db));
+ Tcl_AppendResult(interp, zBuf, 0);
+ return SQLITE_OK;
+}
+
/*
** Usage: sqlite_close DB
**
Tcl_CreateCommand(interp, "sqlite_mprintf_str", sqlite_mprintf_str, 0, 0);
Tcl_CreateCommand(interp, "sqlite_mprintf_double", sqlite_mprintf_double,0,0);
Tcl_CreateCommand(interp, "sqlite_open", sqlite_test_open, 0, 0);
+ Tcl_CreateCommand(interp, "sqlite_last_insert_rowid", test_last_rowid, 0, 0);
Tcl_CreateCommand(interp, "sqlite_exec_printf", test_exec_printf, 0, 0);
Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf,
0, 0);
** But other routines are also provided to help in building up
** a program instruction by instruction.
**
-** $Id: vdbe.c,v 1.106 2002/01/14 09:28:20 drh Exp $
+** $Id: vdbe.c,v 1.107 2002/01/16 21:00:27 drh Exp $
*/
#include "sqliteInt.h"
#include <ctype.h>
** never cause a problem. You are much, much more likely to have a
** hardware failure than for this algorithm to fail.
**
+ ** The analysis in the previous paragraph assumes that you have a good
+ ** source of random numbers. Is a library function like lrand48()
+ ** good enough? Maybe. Maybe not. It's hard to know whether there
+ ** might be subtle bugs is some implementations of lrand48() that
+ ** could cause problems. To avoid uncertainty, SQLite uses its own
+ ** 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
** larger than the previous rowid. This has been shown experimentally
nKey = sizeof(int);
iKey = intToKey(aStack[nos].i);
zKey = (char*)&iKey;
+ db->lastRowid = aStack[nos].i;
}
if( pOp->p2 ){
int res;
# This file implements tests for the special processing associated
# with INTEGER PRIMARY KEY columns.
#
-# $Id: intpkey.test,v 1.5 2002/01/14 02:56:26 drh Exp $
+# $Id: intpkey.test,v 1.6 2002/01/16 21:00:28 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
execsql {
INSERT INTO t1 VALUES(5,'hello','world');
}
-} {}
+ db last_insert_rowid
+} {5}
do_test intpkey-1.4 {
execsql {
SELECT * FROM t1;
}} msg]
lappend r $msg
} {0 {}}
+do_test intpkey-1.8.1 {
+ db last_insert_rowid
+} {6}
do_test intpkey-1.9 {
execsql {
SELECT rowid, * FROM t1;
# interface is pretty well tested. This file contains some addition
# tests for fringe issues that the main test suite does not cover.
#
-# $Id: tclsqlite.test,v 1.4 2002/01/15 18:39:45 drh Exp $
+# $Id: tclsqlite.test,v 1.5 2002/01/16 21:00:28 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
do_test tcl-1.2 {
set v [catch {db bogus} msg]
lappend v $msg
-} {1 {bad option "bogus": must be busy, close, complete, eval, or timeout}}
+} {1 {bad option "bogus": must be busy, close, complete, eval, last_insert_rowid, or timeout}}
do_test tcl-1.3 {
execsql {CREATE TABLE t1(a int, b int)}
execsql {INSERT INTO t1 VALUES(10,20)}
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: c_interface.tcl,v 1.22 2001/12/22 19:27:41 drh Exp $}
+set rcsid {$Id: c_interface.tcl,v 1.23 2002/01/16 21:00:28 drh Exp $}
puts {<html>
<head>
</p>
<blockquote><pre>
+int sqlite_last_insert_rowid(sqlite*);
+
int sqlite_get_table(
sqlite*,
char *sql,
<p>All of the above definitions are included in the "sqlite.h"
header file that comes in the source tree.</p>
+<h2>The ROWID of the most recent insert</h2>
+
+<p>Every row of an SQLite table has a unique integer key. If the
+table has a column labeled INTEGER PRIMARY KEY, then that column
+servers as the key. If there is no INTEGER PRIMARY KEY column then
+the key is a random integer. The key for a row can be accessed in
+a SELECT statement or used in a WHERE or ORDER BY clause using any
+of the names "ROWID", "OID", or "_ROWID_".</p>
+
+<p>When you do an insert into a table that does not have an INTEGER PRIMARY
+KEY column, or if the table does have an INTEGER PRIMARY KEY but the value
+for that column is not specified in the VALUES clause of the insert, then
+the key is automatically generated. You can find the value of the key
+for the most recent INSERT statement using the
+<b>sqlite_last_insert_rowid()</b> API function.</p>
+
<h2>Querying without using a callback function</h2>
<p>The <b>sqlite_get_table()</b> function is a wrapper around
puts "<DD><P><UL>$desc</UL></P></DD>"
}
-chng {2002 Jan 14 (2.2.3)} {
+chng {2002 Jan 16 (2.2.3)} {
<li>Fix warning messages in VC++ 7.0. (Patches from nicolas352001)</li>
<li>Make the library thread-safe. (The code is there and appears to work
but has not been stressed.)</li>
+<li>Added the new <b>sqlite_last_insert_rowid()</b> API function.</li>
}
chng {2002 Jan 13 (2.2.2)} {
#
# Run this script to generated a faq.html output file
#
-set rcsid {$Id: faq.tcl,v 1.5 2001/12/22 19:27:41 drh Exp $}
+set rcsid {$Id: faq.tcl,v 1.6 2002/01/16 21:00:28 drh Exp $}
puts {<html>
<head>
the case and you cannot count on that behavior. The keys will never
be sequential. If you need sequential keys, use the counter implemention
described first.</p>
+
+ <p>Beginning with version 2.2.3, there is a new API function named
+ <b>sqlite_last_insert_rowid()</b> which will return the integer key
+ for the most recent insert operation. See the API documentation for
+ details.</p>
}
faq {
#
# Run this Tcl script to generate the tclsqlite.html file.
#
-set rcsid {$Id: tclsqlite.tcl,v 1.5 2001/11/24 13:23:05 drh Exp $}
+set rcsid {$Id: tclsqlite.tcl,v 1.6 2002/01/16 21:00:28 drh Exp $}
puts {<html>
<head>
<p>
Once an SQLite database is open, it can be controlled using
-methods of the <i>dbcmd</i>. There are currently 5 methods
+methods of the <i>dbcmd</i>. There are currently 6 methods
defined:</p>
<p>
<li> close
<li> complete
<li> eval
+<li> last_insert_rowid
<li> timeout
</ul>
</p>
return "0" if it wants SQLite to try again to open the database and
should return "1" if it wants SQLite to abandon the current operation.
+<h2>The "last_insert_rowid" method</h2>
+
+<p>The "last_insert_rowid" method returns an integer which is the ROWID
+of the most recently inserted database row.</p>
+
}
puts {