:-) (CVS 125)

FossilOrigin-Name: ab9c533a3a256ca9d59a6a580c6064c903d962a5
This commit is contained in:
drh 2000-08-04 13:49:02 +00:00
parent 60bfa67829
commit bec3f4022f
7 changed files with 156 additions and 35 deletions

View File

@ -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/select.c d382e96c2221d08367cc87976f2b574537c9de97
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/arch.tcl 4f6a9afecc099a27bba17b4f8cc9561abc15dc40
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

View File

@ -1 +1 @@
577421e5d370e220b5f228f4c711d49ce95612dc
ab9c533a3a256ca9d59a6a580c6064c903d962a5

View File

@ -23,13 +23,24 @@
*************************************************************************
** 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>
#include <stdlib.h>
#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 @@ static int DbEvalCallback(
** 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 void DbDeleteCmd(void *db){
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 @@ static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
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 @@ static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
** $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 @@ static int DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
" 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 DbCmd(void *cd, Tcl_Interp *interp, int argc, char **argv){
*/
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 @@ static int DbMain(void *cd, Tcl_Interp *interp, int argc, char **argv){
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;
}

View File

@ -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 @@ table that has the corresponding value for the <b>a</b> column.</p>
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 {

View File

@ -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 @@ puts "This is a [file size sqlite.tar.gz] byte download. The
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 @@ $ ../sqlite/configure
$ 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>

View File

@ -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 @@ ON <table-name> ( <column-name> [, <column-name>]* )
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

View File

@ -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 @@ the name of an SQLite database. An SQLite database is really just
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 @@ proc Code {body} {
}
Code {
$ (((mkdir ex1)))
$ (((sqlite ex1)))
Enter ".help" for instructions
sqlite> (((create table tbl1(one varchar(10), two smallint);)))
@ -230,7 +230,7 @@ sqlite>
}
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 @@ widths were unaltered. You can gives as many arguments to ".width" as
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 @@ is formatted to look like SQL INSERT statements. You can use insert
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
&lt;TABLE&gt; and the ending &lt;/TABLE&gt; are not written, but
@ -365,6 +385,7 @@ list mode, then entering the following query:</p>
<blockquote><pre>
SELECT sql FROM sqlite_master
WHERE type!='meta'
ORDER BY tbl_name, type DESC, name
</pre></blockquote>
@ -373,7 +394,7 @@ want the schema for a single table, the query looks like this:</p>
<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>