:-) (CVS 125)
FossilOrigin-Name: ab9c533a3a256ca9d59a6a580c6064c903d962a5
diff --git a/manifest b/manifest
index 95cd5af..aba266b 100644
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C spelling\serror\s(CVS\s124)
-D 2000-08-03T15:13:30
+C :-)\s(CVS\s125)
+D 2000-08-04T13:49:02
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
F Makefile.in 670aa9413cb2cdcded23b328a9e255c845c41a1e
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
@@ -18,7 +18,7 @@
F src/shell.c 2fd370838742afa068cfcdd05b667ff89bab25b6
F src/sqlite.h 82ae53028e27919250f886ff9d7c4927de81978a
F src/sqliteInt.h f6d1e139b3bfa4ceff2136684e19d76b53178ec0
-F src/tclsqlite.c 9f358618ae803bedf4fb96da5154fd45023bc1f7
+F src/tclsqlite.c 6ced80832c13e70dae5a176da2dff3d5f4801d92
F src/tokenize.c 77ff8164a8751994bc9926ce282847f653ac0c16
F src/update.c 51b9ef7434b15e31096155da920302e9db0d27fc
F src/util.c b75b33e6bd5d47898bb7ed9fdd0dea4fe7c19b00
@@ -61,14 +61,14 @@
F www/c_interface.tcl 29593cf77025bab137b7ba64b9459eb5eb6b4873
F www/changes.tcl 4a1aaaaad9a9b4cf3259264955c225b98a9d025d
F www/crosscompile.tcl 19734ce7f18b16ff2ed8479412abf8aca56e1dcc
-F www/fileformat.tcl 1c353d202cc75de55a916a1bab80e7b3cc5660ee
-F www/index.tcl 2ea89f6f90d4d4efd591b9679f0e71a9a4adc2f5
-F www/lang.tcl 1645e9107d75709be4c6099b643db235bbe0a151
+F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
+F www/index.tcl 421bcabc6839eb00698b75b169caa8a559454515
+F www/lang.tcl 9192e114b19987e630a41e879585b87006eb84a1
F www/mingw.tcl fc5f4ba9d336b6e8c97347cc6496d6162461ef60
F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
-F www/sqlite.tcl 69781eaffb02e17aa4af28b76a2bedb19baa8e9f
+F www/sqlite.tcl 7c2ee68063fa59463f55d5bac1ffe3e50d8a817f
F www/vdbe.tcl bcbfc33bcdd0ebad95eab31286adb9e1bc289520
-P 4dabf5e4e647f6dcdcfd45d1e885e379357a2d57
-R 32c359deccb869c0c62b7f96f90c83a2
+P 577421e5d370e220b5f228f4c711d49ce95612dc
+R 2cf2ed69cb63137ea0c1416ab3f1b043
U drh
-Z e70ff0d215fda57f6188c3a588c372be
+Z 70478f10c211823f0de6f883859c4135
diff --git a/manifest.uuid b/manifest.uuid
index 5e81261..c5d6c99 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-577421e5d370e220b5f228f4c711d49ce95612dc
\ No newline at end of file
+ab9c533a3a256ca9d59a6a580c6064c903d962a5
\ No newline at end of file
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index e3e88d0..b15f10d 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -23,7 +23,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.5 2000/06/04 12:58:38 drh Exp $
+** $Id: tclsqlite.c,v 1.6 2000/08/04 13:49:02 drh Exp $
*/
#include "sqlite.h"
#include <tcl.h>
@@ -31,6 +31,17 @@
#include <string.h>
/*
+** There is one instance of this structure for each SQLite database
+** that has been opened by the SQLite TCL interface.
+*/
+typedef struct SqliteDb SqliteDb;
+struct SqliteDb {
+ sqlite *db; /* The "real" database structure */
+ Tcl_Interp *interp; /* The interpreter used for this database */
+ char *zBusy; /* The name of the busy callback routine */
+};
+
+/*
** An instance of this structure passes information thru the sqlite
** logic from the original TCL command into the callback routine.
*/
@@ -81,7 +92,38 @@
** Called when the command is deleted.
*/
static void DbDeleteCmd(void *db){
- sqlite_close((sqlite*)db);
+ SqliteDb *pDb = (SqliteDb*)db;
+ sqlite_close(pDb->db);
+ if( pDb->zBusy ){
+ Tcl_Free(pDb->zBusy);
+ }
+ Tcl_Free((char*)pDb);
+}
+
+/*
+** This routine is called when a database file is locked while trying
+** to execute SQL.
+*/
+static int DbBusyHandler(void *cd, const char *zTable, int nTries){
+ SqliteDb *pDb = (SqliteDb*)cd;
+ int rc;
+ char zVal[30];
+ char *zCmd;
+ char *zResult;
+ Tcl_DString cmd;
+
+ Tcl_DStringInit(&cmd);
+ Tcl_DStringAppend(&cmd, pDb->zBusy, -1);
+ Tcl_DStringAppendElement(&cmd, zTable);
+ sprintf(zVal, " %d", nTries);
+ Tcl_DStringAppend(&cmd, zVal, -1);
+ zCmd = Tcl_DStringValue(&cmd);
+ rc = Tcl_Eval(pDb->interp, zCmd);
+ Tcl_DStringFree(&cmd);
+ if( rc!=TCL_OK || atoi(Tcl_GetStringResult(pDb->interp)) ){
+ return 0;
+ }
+ return 1;
}
/*
@@ -100,7 +142,7 @@
static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
char *z;
int n, c;
- sqlite *db = cd;
+ SqliteDb *pDb = (SqliteDb*)cd;
if( argc<2 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
" SUBCOMMAND ...\"", 0);
@@ -110,6 +152,38 @@
n = strlen(z);
c = z[0];
+ /* $db busy ?CALLBACK?
+ **
+ ** Invoke the given callback if an SQL statement attempts to open
+ ** a locked database file.
+ */
+ if( c=='b' && strncmp(z,"busy",n)==0 ){
+ if( argc>3 ){
+ Tcl_AppendResult(interp,"wrong # args: should be \"",
+ argv[0], " busy ?CALLBACK?", 0);
+ return TCL_ERROR;
+ }else if( argc==2 ){
+ if( pDb->zBusy ){
+ Tcl_AppendResult(interp, pDb->zBusy, 0);
+ }
+ }else{
+ if( pDb->zBusy ){
+ Tcl_Free(pDb->zBusy);
+ pDb->zBusy = 0;
+ }
+ if( argv[2][0] ){
+ pDb->zBusy = Tcl_Alloc( strlen(argv[2]) + 1 );
+ if( pDb->zBusy ){
+ strcpy(pDb->zBusy, argv[2]);
+ }
+ }
+ if( pDb->zBusy ){
+ pDb->interp = interp;
+ sqlite_busy_handler(pDb->db, DbBusyHandler, pDb);
+ }
+ }
+ }else
+
/* $db close
**
** Shutdown the database
@@ -139,7 +213,7 @@
** $db eval $sql ?array { ...code... }?
**
** The SQL statement in $sql is evaluated. For each row, the values are
- ** placed in elements of the array named "array" and ...code.. is executed.
+ ** placed in elements of the array named "array" and ...code... is executed.
** If "array" and "code" are omitted, then no callback is every invoked.
** If "array" is an empty string, then the values are placed in variables
** that have the same name as the fields extracted by the query.
@@ -154,26 +228,43 @@
" eval SQL ?ARRAY-NAME CODE?", 0);
return TCL_ERROR;
}
+ pDb->interp = interp;
if( argc==5 ){
cbData.interp = interp;
cbData.once = 1;
cbData.zArray = argv[3];
cbData.zCode = argv[4];
zErrMsg = 0;
- rc = sqlite_exec(db, argv[2], DbEvalCallback, &cbData, &zErrMsg);
+ rc = sqlite_exec(pDb->db, argv[2], DbEvalCallback, &cbData, &zErrMsg);
}else{
- rc = sqlite_exec(db, argv[2], 0, 0, &zErrMsg);
+ rc = sqlite_exec(pDb->db, argv[2], 0, 0, &zErrMsg);
}
if( zErrMsg ){
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
free(zErrMsg);
}
return rc;
- }
+ }else
+
+ /*
+ ** $db timeout MILLESECONDS
+ **
+ ** Delay for the number of milliseconds specified when a file is locked.
+ */
+ if( c=='t' && strncmp(z,"timeout",n)==0 ){
+ int ms;
+ if( argc!=3 ){
+ Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
+ " timeout MILLISECONDS", 0);
+ return TCL_ERROR;
+ }
+ if( Tcl_GetInt(interp, argv[2], &ms) ) return TCL_ERROR;
+ sqlite_busy_timeout(pDb->db, ms);
+ }else
/* The default
*/
- else{
+ {
Tcl_AppendResult(interp,"unknown subcommand \"", z,
"\" - should be one of: close complete eval", 0);
return TCL_ERROR;
@@ -197,7 +288,7 @@
*/
static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
int mode;
- sqlite *p;
+ SqliteDb *p;
char *zErrMsg;
if( argc!=3 && argc!=4 ){
Tcl_AppendResult(interp,"wrong # args: should be \"", argv[0],
@@ -210,13 +301,20 @@
return TCL_ERROR;
}
zErrMsg = 0;
- p = sqlite_open(argv[2], mode, &zErrMsg);
+ p = Tcl_Alloc( sizeof(*p) );
if( p==0 ){
+ Tcl_SetResult(interp, "malloc failed", TCL_STATIC);
+ return TCL_ERROR;
+ }
+ memset(p, 0, sizeof(*p));
+ p->db = sqlite_open(argv[2], mode, &zErrMsg);
+ if( p->db==0 ){
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
+ Tcl_Free((char*)p);
free(zErrMsg);
return TCL_ERROR;
}
- Tcl_CreateCommand(interp, argv[1], DbCmd, p, DbDeleteCmd);
+ Tcl_CreateCommand(interp, argv[1], DbCmd, (char*)p, DbDeleteCmd);
return TCL_OK;
}
diff --git a/www/fileformat.tcl b/www/fileformat.tcl
index d519e8d..7b8a743 100644
--- a/www/fileformat.tcl
+++ b/www/fileformat.tcl
@@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the fileformat.html file.
#
-set rcsid {$Id: fileformat.tcl,v 1.3 2000/08/02 12:26:30 drh Exp $}
+set rcsid {$Id: fileformat.tcl,v 1.4 2000/08/04 13:49:03 drh Exp $}
puts {<html>
<head>
@@ -215,8 +215,7 @@
The index entry for -11 contains only a single entry and is 4
bytes in size. The index entry for 10 is 16 bytes in size but
contains only 2 entries. The first integer is the number of
-entires. The two integer keys follow. The last 4 bytes unused
-and are set to zero.
+entires. The two integer keys follow. The last 4 bytes are unused.
}
puts {
diff --git a/www/index.tcl b/www/index.tcl
index 6f97871..44ee66d 100644
--- a/www/index.tcl
+++ b/www/index.tcl
@@ -1,7 +1,7 @@
#
# Run this TCL script to generate HTML for the index.html file.
#
-set rcsid {$Id: index.tcl,v 1.25 2000/08/03 15:13:30 drh Exp $}
+set rcsid {$Id: index.tcl,v 1.26 2000/08/04 13:49:03 drh Exp $}
puts {<html>
<head><title>SQLite: An SQL Database Engine Built Atop GDBM</title></head>
@@ -132,7 +132,7 @@
tarball was last modified at [clock format [file mtime sqlite.tar.gz]]"
puts {</p>
-<p>To build sqlite, just unwrap the tarball, create a separate
+<p>To build sqlite under Unix, just unwrap the tarball, create a separate
build directory, run configure from the build directory and then
type "make". For example:</p>
@@ -144,6 +144,9 @@
$ make <i> Builds "sqlite" and "libsqlite.a" </i>
$ make test <i> Optional: run regression tests </i>
</pre></blockquote>
+
+<p>Instructions for building SQLite for WindowsNT are
+found <a href="crosscompile.html">here</a>.
}
puts {<h2>Command-line Usage Example</h2>
diff --git a/www/lang.tcl b/www/lang.tcl
index 66f035c..49db367 100644
--- a/www/lang.tcl
+++ b/www/lang.tcl
@@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: lang.tcl,v 1.4 2000/06/09 14:14:34 drh Exp $}
+set rcsid {$Id: lang.tcl,v 1.5 2000/08/04 13:49:03 drh Exp $}
puts {<html>
<head>
@@ -139,7 +139,7 @@
puts {
<p>The CREATE INDEX command consists of the keywords "CREATE INDEX" followed
-by the name of the new index, the keyword "ON" the name of a previously
+by the name of the new index, the keyword "ON", the name of a previously
created table that is to be indexed, and a parenthesized list of names of
columns in the table that are used for the index key.
Each column name can be followed by one of the "ASC" or "DESC" keywords
diff --git a/www/sqlite.tcl b/www/sqlite.tcl
index 44e4ffb..ed3bb31 100644
--- a/www/sqlite.tcl
+++ b/www/sqlite.tcl
@@ -1,7 +1,7 @@
#
# Run this Tcl script to generate the sqlite.html file.
#
-set rcsid {$Id: sqlite.tcl,v 1.11 2000/07/28 14:32:51 drh Exp $}
+set rcsid {$Id: sqlite.tcl,v 1.12 2000/08/04 13:49:03 drh Exp $}
puts {<html>
<head>
@@ -28,8 +28,9 @@
a directory full of GDBM files, so the argument to the sqlite command
should really be the name of a directory on your disk. If that
directory did not previously contain an SQLite database, a new one
-is created for you automatically. The <b>sqlite</b> program will
-prompt you to enter SQL. Type in SQL statements (terminated by a
+is created for you automatically. If the directory did not previously
+exist, it is automatically created. The <b>sqlite</b> program will
+then prompt you to enter SQL. Type in SQL statements (terminated by a
semicolon), press "Enter" and the SQL will be executed. It's as
simple as that!</p>
@@ -49,7 +50,6 @@
}
Code {
-$ (((mkdir ex1)))
$ (((sqlite ex1)))
Enter ".help" for instructions
sqlite> (((create table tbl1(one varchar(10), two smallint);)))
@@ -230,7 +230,7 @@
}
puts {
-<p>By default, each column is 10 characters wide.
+<p>By default, each column is at least 10 characters wide.
Data that is too wide to fit in a column is truncated. You can
adjust the column widths using the ".width" command. Like this:</p>}
@@ -251,6 +251,13 @@
necessary to specify the widths of as many columns as are in your
query results.</p>
+<p>If you specify a column a width of 0, then the column
+width is automatically adjusted to be the maximum of three
+numbers: 10, the width of the header, and the width of the
+first row of data. This makes the column width self-adjusting.
+The default width setting for every column is this
+auto-adjusting 0 value.</p>
+
<p>The column labels that appear on the first two lines of output
can be turned on and off using the ".header" dot command. In the
examples above, the column labels are on. To turn them off you
@@ -270,6 +277,19 @@
mode to generate text that can later be used to input data into a
different database.</p>
+<p>When specifying insert mode, you have to give an extra argument
+which is the name of the table to be inserted into. For example:</p>
+}
+
+Code {
+sqlite> (((.mode insert new_table)))
+sqlite> (((select * from tbl1;)))
+INSERT INTO 'new_table' VALUES('hello',10);
+INSERT INTO 'new_table' VALUES('goodbye',20);
+sqlite>
+}
+
+puts {
<p>The last output mode is "html". In this mode, sqlite writes
the results of the query as an XHTML table. The beginning
<TABLE> and the ending </TABLE> are not written, but
@@ -365,6 +385,7 @@
<blockquote><pre>
SELECT sql FROM sqlite_master
+WHERE type!='meta'
ORDER BY tbl_name, type DESC, name
</pre></blockquote>
@@ -373,7 +394,7 @@
<blockquote><pre>
SELECT sql FROM sqlite_master
-WHERE tbl_name LIKE '%s'
+WHERE tbl_name LIKE '%s' AND type!='meta'
ORDER BY type DESC, name
</pre></blockquote>