Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Added the last_insert_rowid API function. Improved documentation of the random ROWID algorithm. (CVS 349) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
f74d61aaf3fec06cde2c4a6f1465f86a |
User & Date: | drh 2002-01-16 21:00:27.000 |
Context
2002-01-16
| ||
21:05 | Version 2.2.3 (CVS 450) (check-in: a4fe893ce7 user: drh tags: trunk) | |
21:00 | Added the last_insert_rowid API function. Improved documentation of the random ROWID algorithm. (CVS 349) (check-in: f74d61aaf3 user: drh tags: trunk) | |
2002-01-15
| ||
18:39 | Added implementations for sqliteOsEnterMutex() and sqliteOsLeaveMutex(). (CVS 348) (check-in: f8a026a3ca user: drh tags: trunk) | |
Changes
Changes to VERSION.
|
| | | 1 | 2.2.3 |
Changes to src/main.c.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** Main file for the SQLite library. The routines in this file ** implement the programmer interface to the library. Routines in ** other files are for internal use by SQLite and should not be ** accessed by users of the library. ** ** $Id: main.c,v 1.56 2002/01/16 21:00:27 drh Exp $ */ #include "sqliteInt.h" #include "os.h" /* ** This is the callback routine for the code that initializes the ** database. See sqliteInit() below for additional information. |
︙ | ︙ | |||
353 354 355 356 357 358 359 360 361 362 363 364 365 366 | }else{ sqliteDeleteTable(db, pTab); } } sqliteHashClear(&temp1); db->flags &= ~SQLITE_Initialized; } /* ** Close an existing SQLite database */ void sqlite_close(sqlite *db){ sqliteBtreeClose(db->pBe); clearHashTable(db, 0); | > > > > > > > | 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 | }else{ sqliteDeleteTable(db, pTab); } } sqliteHashClear(&temp1); 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 */ void sqlite_close(sqlite *db){ sqliteBtreeClose(db->pBe); clearHashTable(db, 0); |
︙ | ︙ |
Changes to src/random.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** Random numbers are used by some of the database backends in order ** to generate random integer keys for tables or random filenames. ** | | > > > > > > > > > > | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | ************************************************************************* ** This file contains code to implement a pseudo-random number ** generator (PRNG) for SQLite. ** ** 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.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; /* All threads share a single random number generator. ** This structure is the current state of the generator. */ |
︙ | ︙ |
Changes to src/sqlite.h.in.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This header file defines the interface that the SQLite library ** presents to client programs. ** ** @(#) $Id: sqlite.h.in,v 1.25 2002/01/16 21:00:27 drh Exp $ */ #ifndef _SQLITE_H_ #define _SQLITE_H_ #include <stdarg.h> /* Needed for the definition of va_list */ /* ** The version of the SQLite library. |
︙ | ︙ | |||
158 159 160 161 162 163 164 165 166 167 168 169 170 171 | #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #define SQLITE_CONSTRAINT 19 /* Abort due to contraint violation */ #define SQLITE_MISMATCH 20 /* Data type mismatch */ /* 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. */ const char *sqlite_error_string(int); #define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */ | > > > > > > > > > > > | 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 | #define SQLITE_PROTOCOL 15 /* Database lock protocol error */ #define SQLITE_EMPTY 16 /* (Internal Only) Database table is empty */ #define SQLITE_SCHEMA 17 /* The database schema changed */ #define SQLITE_TOOBIG 18 /* Too much data for one row of a table */ #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. */ const char *sqlite_error_string(int); #define sqliteErrStr sqlite_error_string /* Legacy. Do not use in new code. */ |
︙ | ︙ |
Changes to src/sqliteInt.h.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** Internal interface definitions for SQLite. ** ** @(#) $Id: sqliteInt.h,v 1.77 2002/01/16 21:00:27 drh Exp $ */ #include "sqlite.h" #include "hash.h" #include "vdbe.h" #include "parse.h" #include "btree.h" #include <stdio.h> |
︙ | ︙ | |||
177 178 179 180 181 182 183 184 185 186 187 188 189 190 | int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ Hash tblHash; /* All tables indexed by name */ Hash idxHash; /* All (named) indices indexed by name */ Hash tblDrop; /* Uncommitted DROP TABLEs */ Hash idxDrop; /* Uncommitted DROP INDEXs */ int nextRowid; /* Next generated rowID */ }; /* ** Possible values for the sqlite.flags. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ | > | 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | int nTable; /* Number of tables in the database */ void *pBusyArg; /* 1st Argument to the busy callback */ int (*xBusyCallback)(void *,const char*,int); /* The busy callback */ Hash tblHash; /* All tables indexed by name */ 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 */ }; /* ** Possible values for the sqlite.flags. */ #define SQLITE_VdbeTrace 0x00000001 /* True to trace VDBE execution */ |
︙ | ︙ |
Changes to src/tclsqlite.c.
1 2 3 4 5 6 7 8 9 10 11 12 13 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | /* ** 2001 September 15 ** ** The author disclaims copyright to this source code. In place of ** a legal notice, here is a blessing: ** ** May you do good and not evil. ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** A TCL Interface to SQLite ** ** $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 */ #include "sqlite.h" #include "tcl.h" #include <stdlib.h> #include <string.h> |
︙ | ︙ | |||
264 265 266 267 268 269 270 | ** and calls that connection "db1". The second command causes this ** subroutine to be invoked. */ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *pDb = (SqliteDb*)cd; int choice; static char *DB_optStrs[] = { | | | | 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 | ** and calls that connection "db1". The second command causes this ** subroutine to be invoked. */ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){ SqliteDb *pDb = (SqliteDb*)cd; int choice; static char *DB_optStrs[] = { "busy", "close", "complete", "eval", "last_insert_rowid", "timeout", 0 }; enum DB_opts { DB_BUSY, DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_LAST_INSERT_ROWID, DB_TIMEOUT }; if( objc<2 ){ Tcl_WrongNumArgs(interp, 1, objv, "SUBCOMMAND ..."); return TCL_ERROR; } if( Tcl_GetIndexFromObj(interp, objv[1], DB_optStrs, "option", 0, &choice) ){ |
︙ | ︙ | |||
419 420 421 422 423 424 425 426 427 428 429 430 431 432 | } free(cbData.azColName); cbData.azColName = 0; } #endif return rc; } /* ** $db timeout MILLESECONDS ** ** Delay for the number of milliseconds specified when a file is locked. */ case DB_TIMEOUT: { | > > > > > > > > > > > > > > > > > > | 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 | } free(cbData.azColName); cbData.azColName = 0; } #endif 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 ** ** Delay for the number of milliseconds specified when a file is locked. */ case DB_TIMEOUT: { |
︙ | ︙ |
Changes to src/test1.c.
︙ | ︙ | |||
9 10 11 12 13 14 15 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | ** May you share freely, never taking more than you give. ** ************************************************************************* ** Code for testing the printf() interface to SQLite. This code ** is not included in the SQLite library. It is used for automated ** testing of the SQLite library. ** ** $Id: test1.c,v 1.6 2002/01/16 21:00:27 drh Exp $ */ #include "sqliteInt.h" #include "tcl.h" #include <stdlib.h> #include <string.h> /* |
︙ | ︙ | |||
146 147 148 149 150 151 152 153 154 155 156 157 158 159 | Tcl_AppendElement(interp, zErr); } sqlite_free_table(aResult); if( zErr ) free(zErr); return TCL_OK; } /* ** Usage: sqlite_close DB ** ** Closes the database opened by sqlite_open. */ static int sqlite_test_close( void *NotUsed, | > > > > > > > > > > > > > > > > > > > > > > > > > | 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 | Tcl_AppendElement(interp, zErr); } sqlite_free_table(aResult); if( zErr ) free(zErr); 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 ** ** Closes the database opened by sqlite_open. */ static int sqlite_test_close( void *NotUsed, |
︙ | ︙ | |||
304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 | */ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite_search_count; Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0); 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_exec_printf", test_exec_printf, 0, 0); Tcl_CreateCommand(interp, "sqlite_get_table_printf", test_get_table_printf, 0, 0); Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); Tcl_LinkVar(interp, "sqlite_search_count", (char*)&sqlite_search_count, TCL_LINK_INT); #ifdef MEMORY_DEBUG Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0); Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0); #endif return TCL_OK; } | > | 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | */ int Sqlitetest1_Init(Tcl_Interp *interp){ extern int sqlite_search_count; Tcl_CreateCommand(interp, "sqlite_mprintf_int", sqlite_mprintf_int, 0, 0); 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); Tcl_CreateCommand(interp, "sqlite_close", sqlite_test_close, 0, 0); Tcl_LinkVar(interp, "sqlite_search_count", (char*)&sqlite_search_count, TCL_LINK_INT); #ifdef MEMORY_DEBUG Tcl_CreateCommand(interp, "sqlite_malloc_fail", sqlite_malloc_fail, 0, 0); Tcl_CreateCommand(interp, "sqlite_malloc_stat", sqlite_malloc_stat, 0, 0); #endif return TCL_OK; } |
Changes to src/vdbe.c.
︙ | ︙ | |||
26 27 28 29 30 31 32 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** | | | 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | ** type to the other occurs as necessary. ** ** Most of the code in this file is taken up by the sqliteVdbeExec() ** function which does the work of interpreting a VDBE program. ** But other routines are also provided to help in building up ** a program instruction by instruction. ** ** $Id: vdbe.c,v 1.107 2002/01/16 21:00:27 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** The following global variable is incremented every time a cursor ** moves, either by the OP_MoveTo or the OP_Next opcode. The test |
︙ | ︙ | |||
2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 | ** 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 ** non-zero probability, but it is still vanishingly small and should ** never cause a problem. You are much, much more likely to have a ** hardware failure than for this algorithm to fail. ** ** 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 ** to double the speed of the COPY operation. */ int res, rx, cnt, x; | > > > > > > > | 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 2743 2744 2745 2746 | ** 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 ** non-zero probability, but it is still vanishingly small and should ** 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 ** to double the speed of the COPY operation. */ int res, rx, cnt, x; |
︙ | ︙ | |||
2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 | if( Stringify(p, nos) ) goto no_mem; nKey = aStack[nos].n; zKey = zStack[nos]; }else{ nKey = sizeof(int); iKey = intToKey(aStack[nos].i); zKey = (char*)&iKey; } if( pOp->p2 ){ int res; rc = sqliteBtreeMoveto(p->aCsr[i].pCursor, zKey, nKey, &res); if( res==0 && rc==SQLITE_OK ){ rc = SQLITE_CONSTRAINT; } | > | 2793 2794 2795 2796 2797 2798 2799 2800 2801 2802 2803 2804 2805 2806 2807 | if( Stringify(p, nos) ) goto no_mem; nKey = aStack[nos].n; zKey = zStack[nos]; }else{ nKey = sizeof(int); iKey = intToKey(aStack[nos].i); zKey = (char*)&iKey; db->lastRowid = aStack[nos].i; } if( pOp->p2 ){ int res; rc = sqliteBtreeMoveto(p->aCsr[i].pCursor, zKey, nKey, &res); if( res==0 && rc==SQLITE_OK ){ rc = SQLITE_CONSTRAINT; } |
︙ | ︙ |
Changes to test/intpkey.test.
︙ | ︙ | |||
9 10 11 12 13 14 15 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the special processing associated # with INTEGER PRIMARY KEY columns. # | | | 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | # #*********************************************************************** # This file implements regression tests for SQLite library. # # This file implements tests for the special processing associated # with INTEGER PRIMARY KEY columns. # # $Id: intpkey.test,v 1.6 2002/01/16 21:00:28 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a table with a primary key and a datatype other than # integer # |
︙ | ︙ | |||
51 52 53 54 55 56 57 | # Insert some records into the new table. Specify the primary key # and verify that the key is used as the record number. # do_test intpkey-1.3 { execsql { INSERT INTO t1 VALUES(5,'hello','world'); } | > | | 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | # Insert some records into the new table. Specify the primary key # and verify that the key is used as the record number. # do_test intpkey-1.3 { execsql { INSERT INTO t1 VALUES(5,'hello','world'); } db last_insert_rowid } {5} do_test intpkey-1.4 { execsql { SELECT * FROM t1; } } {5 hello world} do_test intpkey-1.5 { execsql { |
︙ | ︙ | |||
83 84 85 86 87 88 89 90 91 92 93 94 95 96 | } {5 5 hello world} do_test intpkey-1.8 { set r [catch {execsql { INSERT INTO t1 VALUES(6,'second','entry'); }} msg] lappend r $msg } {0 {}} do_test intpkey-1.9 { execsql { SELECT rowid, * FROM t1; } } {5 5 hello world 6 6 second entry} # A ROWID is automatically generated for new records that do not specify | > > > | 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 | } {5 5 hello world} do_test intpkey-1.8 { set r [catch {execsql { INSERT INTO t1 VALUES(6,'second','entry'); }} 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; } } {5 5 hello world 6 6 second entry} # A ROWID is automatically generated for new records that do not specify |
︙ | ︙ |
Changes to test/tclsqlite.test.
︙ | ︙ | |||
11 12 13 14 15 16 17 | # This file implements regression tests for TCL interface to the # SQLite library. # # Actually, all tests are based on the TCL interface, so the main # interface is pretty well tested. This file contains some addition # tests for fringe issues that the main test suite does not cover. # | | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | # This file implements regression tests for TCL interface to the # SQLite library. # # Actually, all tests are based on the TCL interface, so the main # 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.5 2002/01/16 21:00:28 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Check the error messages generated by tclsqlite # do_test tcl-1.1 { set v [catch {sqlite bogus} msg] lappend v $msg } {1 {wrong # args: should be "sqlite HANDLE FILENAME ?MODE?"}} do_test tcl-1.2 { set v [catch {db bogus} msg] lappend v $msg } {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)} set v [catch { db eval {SELECT * FROM t1} data { error "The error message" } |
︙ | ︙ |
Changes to www/c_interface.tcl.
1 2 3 | # # Run this Tcl script to generate the sqlite.html file. # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this Tcl script to generate the sqlite.html file. # set rcsid {$Id: c_interface.tcl,v 1.23 2002/01/16 21:00:28 drh Exp $} puts {<html> <head> <title>The C language interface to the SQLite library</title> </head> <body bgcolor=white> <h1 align=center> |
︙ | ︙ | |||
301 302 303 304 305 306 307 308 309 310 311 312 313 314 | <p>Only the three core routines shown above are required to use SQLite. But there are many other functions that provide useful interfaces. These extended routines are as follows: </p> <blockquote><pre> int sqlite_get_table( sqlite*, char *sql, char ***result, int *nrow, int *ncolumn, char **errmsg | > > | 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 | <p>Only the three core routines shown above are required to use SQLite. But there are many other functions that provide useful interfaces. These extended routines are as follows: </p> <blockquote><pre> int sqlite_last_insert_rowid(sqlite*); int sqlite_get_table( sqlite*, char *sql, char ***result, int *nrow, int *ncolumn, char **errmsg |
︙ | ︙ | |||
367 368 369 370 371 372 373 374 375 376 377 378 379 380 | ); </pre></blockquote> <p>All of the above definitions are included in the "sqlite.h" header file that comes in the source tree.</p> <h2>Querying without using a callback function</h2> <p>The <b>sqlite_get_table()</b> function is a wrapper around <b>sqlite_exec()</b> that collects all the information from successive callbacks and write it into memory obtained from malloc(). This is a convenience function that allows the application to get the entire result of a database query with a single function call.</p> | > > > > > > > > > > > > > > > > | 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 | ); </pre></blockquote> <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 <b>sqlite_exec()</b> that collects all the information from successive callbacks and write it into memory obtained from malloc(). This is a convenience function that allows the application to get the entire result of a database query with a single function call.</p> |
︙ | ︙ |
Changes to www/changes.tcl.
︙ | ︙ | |||
13 14 15 16 17 18 19 | proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } | | > | 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | proc chng {date desc} { puts "<DT><B>$date</B></DT>" puts "<DD><P><UL>$desc</UL></P></DD>" } 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)} { <li>Bug fix: An assertion was failing when a temporary table with an index had the same name as a permanent table created by a separate process.</li> <li>Bug fix: Updates to tables containing an INTEGER PRIMARY KEY and an index could fail.</li> |
︙ | ︙ |
Changes to www/faq.tcl.
1 2 3 | # # Run this script to generated a faq.html output file # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this script to generated a faq.html output file # set rcsid {$Id: faq.tcl,v 1.6 2002/01/16 21:00:28 drh Exp $} puts {<html> <head> <title>SQLite Frequently Asked Questions</title> </head> <body bgcolor="white"> <h1 align="center">Frequently Asked Questions</h1> |
︙ | ︙ | |||
77 78 79 80 81 82 83 84 85 86 87 88 89 90 | <p>The randomly generated keys in this case are 1597027670 and 1597027853. You will probably get different keys every time you try this. The keys will often be ascending, but this is not always 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> } faq { SQLite lets me insert a string into a database column of type integer! } { <p>This is a feature, not a bug. SQLite is typeless. Any data can be inserted into any column. You can put arbitrary length strings into | > > > > > | 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 | <p>The randomly generated keys in this case are 1597027670 and 1597027853. You will probably get different keys every time you try this. The keys will often be ascending, but this is not always 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 { SQLite lets me insert a string into a database column of type integer! } { <p>This is a feature, not a bug. SQLite is typeless. Any data can be inserted into any column. You can put arbitrary length strings into |
︙ | ︙ |
Changes to www/tclsqlite.tcl.
1 2 3 | # # Run this Tcl script to generate the tclsqlite.html file. # | | | 1 2 3 4 5 6 7 8 9 10 11 | # # Run this Tcl script to generate the tclsqlite.html file. # set rcsid {$Id: tclsqlite.tcl,v 1.6 2002/01/16 21:00:28 drh Exp $} puts {<html> <head> <title>The Tcl interface to the SQLite library</title> </head> <body bgcolor=white> <h1 align=center> |
︙ | ︙ | |||
46 47 48 49 50 51 52 | <p> The name of the database is just the name of a disk file in which the database is stored. </p> <p> Once an SQLite database is open, it can be controlled using | | > | 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | <p> The name of the database is just the name of a disk file in which the database is stored. </p> <p> Once an SQLite database is open, it can be controlled using methods of the <i>dbcmd</i>. There are currently 6 methods defined:</p> <p> <ul> <li> busy <li> close <li> complete <li> eval <li> last_insert_rowid <li> timeout </ul> </p> <p>We will explain all of these methods, though not in that order. We will be begin with the "close" method.</p> |
︙ | ︙ | |||
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 | Tcl procedure that is invoked whenever SQLite tries to open a locked database. This callback can do whatever is desired. Presumably, the callback will do some other useful work for a short while then return so that the lock can be tried again. The callback procedure should 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. } puts { <p><hr /></p> <p><a href="index.html"><img src="/goback.jpg" border=0 /> Back to the SQLite Home Page</a> </p> </body></html>} | > > > > > | 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 | Tcl procedure that is invoked whenever SQLite tries to open a locked database. This callback can do whatever is desired. Presumably, the callback will do some other useful work for a short while then return so that the lock can be tried again. The callback procedure should 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 { <p><hr /></p> <p><a href="index.html"><img src="/goback.jpg" border=0 /> Back to the SQLite Home Page</a> </p> </body></html>} |