From 960e8c6317c3550faa1dab181a473d611f2fe378 Mon Sep 17 00:00:00 2001
From: drh
Date: Tue, 3 Apr 2001 16:53:21 +0000
Subject: [PATCH] Bug fixes from Oleg Oleinick (CVS 195)
FossilOrigin-Name: 1f0197d504fa2bde15b287ac6c0102cacdb1e482
---
Makefile.in | 3 +-
VERSION | 2 +-
manifest | 37 +++++++++++----------
manifest.uuid | 2 +-
src/dbbe.h | 18 +++++-----
src/dbbegdbm.c | 7 ++--
src/dbbemem.c | 6 ++--
src/pager.h | 56 +++++++++++++++++++++++++++++++
src/sqlite.h.in | 4 ++-
src/tclsqlite.c | 15 +++++++--
src/test.file | 1 -
test/dbbe.test | 4 +--
test/lock.test | 4 +--
test/tclsqlite.test | 80 +++++++++++++++++++++++++++++++++++++++++++++
tool/lemon.c | 57 +++++++++++++++++++++++++-------
tool/lempar.c | 32 ++++++++++--------
www/changes.tcl | 6 ++++
17 files changed, 266 insertions(+), 68 deletions(-)
create mode 100644 src/pager.h
delete mode 100644 src/test.file
create mode 100644 test/tclsqlite.test
diff --git a/Makefile.in b/Makefile.in
index b8d5f839c4..113efaa354 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -56,9 +56,8 @@ LIBOBJ = build.o dbbe.o dbbegdbm.o dbbemem.o delete.o expr.o insert.o \
SRC = \
$(TOP)/src/build.c \
$(TOP)/src/dbbe.c \
- $(TOP)/src/dbbegdbm.c \
- $(TOP)/src/dbbemem.c \
$(TOP)/src/dbbe.h \
+ $(TOP)/src/dbbegdbm.c \
$(TOP)/src/dbbemem.c \
$(TOP)/src/delete.c \
$(TOP)/src/expr.c \
diff --git a/VERSION b/VERSION
index adb7b04cb2..8b54409523 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-1.0.27
+1.0.28
diff --git a/manifest b/manifest
index c48e1a771f..5d1dd7e794 100644
--- a/manifest
+++ b/manifest
@@ -1,9 +1,9 @@
-C Version\s1.0.27\s(CVS\s476)
-D 2001-03-20T22:15:00
+C Bug\sfixes\sfrom\sOleg\sOleinick\s(CVS\s195)
+D 2001-04-03T16:53:22
F COPYRIGHT 74a8a6531a42e124df07ab5599aad63870fa0bd4
-F Makefile.in 7efa81e2985b45ba73db27d55b70cc927f5abfd7
+F Makefile.in fd8815aa01a7181f60f786158b7737a35413189e
F README 51f6a4e7408b34afa5bc1c0485f61b6a4efb6958
-F VERSION dee81fa1259d8cbb43230e982a9392f11f89859d
+F VERSION 010a68e4026cf015511e2c5acc54815fa374d11b
F configure 3dc1edb9dcf60215e31ff72b447935ab62211442 x
F configure.in d892ca33db7e88a055519ce2f36dcb11020e8fff
F doc/lemon.html e233a3e97a779c7a87e1bc4528c664a58e49dd47
@@ -11,9 +11,9 @@ F doc/report1.txt 734cbae63b1310cc643fe5e9e3da1ab55a79b99e
F src/TODO 38a68a489e56e9fd4a96263e0ff9404a47368ad4
F src/build.c 7aa5879bf58ea6bbff22c26c59d1130021fa6ca4
F src/dbbe.c b178f0959f6bac5ef8a109484c1571053f31abe5
-F src/dbbe.h 57d6debb99f6d7a91364b73cf3f0b129058ebbb3
-F src/dbbegdbm.c 84b2bf31d220f1de1cb0507ea051d30128fd681b
-F src/dbbemem.c d0fb86f1e8a52cdb195dc91d07f43765cf48bb95
+F src/dbbe.h 4b33f0cf884dfab49e39a422b2dcaf7a2a0e626c
+F src/dbbegdbm.c c4b2857e242ff8b4e8a5ac2d95e2e35f462ce8eb
+F src/dbbemem.c f0007eff4a00f28126c093f37f8e7dd2fcaa123b
F src/delete.c 7aa9dcb86d5e98c3eb9dee00a459e0ef9b73fbe3
F src/ex/README b745b00acce2d892f60c40111dacdfc48e0c1c7a
F src/ex/db.c f1419ae6c93e40b5ac6e39fe7efd95d868e6f9d7
@@ -26,17 +26,17 @@ F src/ex/sizes.tcl f54bad4a2ac567624be59131a6ee42d71b41a3d7
F src/expr.c 49bc261fdc4f4fb91c74cd668a9a952c00e85931
F src/insert.c 4bc1cab84f7805d560a1417734a532843e30b762
F src/main.c 5afe29c425b875acede20f609485866eb5b276f6
+F src/pager.h 889c5cf517ad30704e295540793c893ac843fd5f
F src/parse.y 25ee4d8efccc4b247c32fe4ab194e3dd8fd5a4ee
F src/printf.c af0dc65c293427272e1949c7807b1d88f10004fd
F src/random.c b36c3f57dc80c8f354e6bfbf39cf1e1de021d54a
F src/select.c faac634ef0c717bc82ca112a4531a257886f2c7a
F src/shell.c 441e20913cde0bb71281f4027623c623530241cd
F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e
-F src/sqlite.h.in 7c1a53f020418d89d13ed2fe9c477ff54540755d
+F src/sqlite.h.in 3b446fcbed6005f0ab89632f3356c4708b349e88
F src/sqliteInt.h 9887d207b98362392668410a11c59b3e334f51a1
F src/table.c 5be76051a8ed6f6bfa641f4adc52529efa34fbf9
-F src/tclsqlite.c 2a925e1835c348f07dd17c87d95ae9a577833407
-F src/test.file 55ca6286e3e4f4fba5d0448333fa99fc5a404a73
+F src/tclsqlite.c f654b0399ea8a29262637dbe71fdfe7c26bd9032
F src/tokenize.c c7ad428f38e56342eb2025320480b5ae9ece1b90
F src/update.c 8365b3922ea098330d1e20862d6e64911e4e03d0
F src/util.c f4573201fc2b581dbf601c53787349310b7da150
@@ -45,7 +45,7 @@ F src/vdbe.h 031b7dd7d6f94c51dc37cdf26efe43d1619bb672
F src/where.c 478fde7c930969ca428de2d80b137959d25ee2fb
F test/all.test 15cac2f6b2d4c55bf896212aff3cc9d6597b0490
F test/copy.test b77a1214bd7756f2849d5c4fa6e715c0ff0c34eb
-F test/dbbe.test 03a6940807f8a1e7538897b4c802a7937677e053
+F test/dbbe.test a022fe2d983848f786e17ef1fc6809cfd37fb02c
F test/delete.test 50b9b1f06c843d591741dba7869433a105360dbf
F test/expr.test 48273bf48a15d226c35829f702af4254c0ff6795
F test/func.test 02aed8845b98bde1043dda97455de1d37238ebb3
@@ -53,7 +53,7 @@ F test/in.test 2c560c0f55fb777029fd9bb5378f2997582aa603
F test/index.test ee060ef8912be47ba616e50cce7985259a68d58a
F test/insert.test 66f4c3bd600fec8eb1e733b928cbe6fa885eff0c
F test/insert2.test 732405e30331635af8d159fccabe835eea5cd0c6
-F test/lock.test d8f0fc54f2a88969368c15490ea82811e2d7dd37
+F test/lock.test bca7d53de73138b1f670a2fbdb1f481ff7eaa45a
F test/main.test 5b0ed3d586c15b9136b9fd4916dcc95086639387
F test/select1.test 68ff778c24fc8982e63dda37acb5b0396913adf7
F test/select2.test 04ac3bd69298f58c7d0883159bab42ab9ad6021c
@@ -63,14 +63,15 @@ F test/select5.test e2b9d51d88cbd6c307c2c05b0ef55fe7ba811ac2
F test/sort.test d582086c4bb7df3fbf50aa72e69d7e235e9f8e31
F test/subselect.test bf8b251a92fb091973c1c469ce499dc9648a41d5
F test/table.test eaa25951c0f18615763cd3dc248ea4bc38739c05
+F test/tclsqlite.test d2aa55926874783b2401f0146e839f773c6796e1
F test/tester.tcl 01f881142be3bd8713abcea06747652067dafb78
F test/update.test 72c0c93310483b86dc904a992220c5b84c7ce100
F test/vacuum.test b95d8119a0a83dc6c4ac63888f8872f06199e065
F test/where.test bbab5a308055fb6087dc23d600b4ad2b72797397
F tool/gdbmdump.c 529e67c78d920606ba196326ea55b57b75fcc82b
F tool/gdbmstat.c 56a9033531e5f5a48413f6ec436d5fb0341632c1
-F tool/lemon.c b13a31798574af881753d38f4da7d505929259c3
-F tool/lempar.c a1eec94d6eacc12332368660ec65f3b248853833
+F tool/lemon.c e007bfdbc79a51a4cd7c8a5f81f517cebd121150
+F tool/lempar.c 943b476d44b319eed525e46bb29e15f2c5986b37
F tool/memleak.awk a0a11dd84bf4582acc81c3c61271021ae49b3f15
F tool/opNames.awk 2bd9071a138e4e2be13dc98fe066398a61219e1e
F tool/opcodeDoc.awk b3a2a3d5d3075b8bd90b7afe24283efdd586659c
@@ -80,7 +81,7 @@ F www/arch.fig 4f246003b7da23bd63b8b0af0618afb4ee3055c8
F www/arch.png 8dae0766d42ed3de9ed013c1341a5792bcf633e6
F www/arch.tcl a40380c1fe0080c43e6cc5c20ed70731511b06be
F www/c_interface.tcl 11be2d5826eb7d6efd629751d3b483c1ed78ba14
-F www/changes.tcl e01a5257038fafe0302b629d1b278789409029d2
+F www/changes.tcl 1be73dbd1d45471fdef05f627e8332206768f179
F www/crosscompile.tcl c99efacb3aefaa550c6e80d91b240f55eb9fd33e
F www/dynload.tcl 02eb8273aa78cfa9070dd4501dca937fb22b466c
F www/fileformat.tcl cfb7fba80b7275555281ba2f256c00734bcdd1c9
@@ -91,7 +92,7 @@ F www/opcode.tcl cb3a1abf8b7b9be9f3a228d097d6bf8b742c2b6f
F www/sqlite.tcl cb0d23d8f061a80543928755ec7775da6e4f362f
F www/tclsqlite.tcl 06f81c401f79a04f2c5ebfb97e7c176225c0aef2
F www/vdbe.tcl 0c8aaa529dd216ccbf7daaabd80985e413d5f9ad
-P daea156e2430762e683ff5460f9f8bb3204ae168
-R e053fcd301655951022cbe2ddba947b1
+P 833291c22734b2ac2342da84710320eb28f5d8cc
+R b3979afeb1b2a68085466c778c74b02f
U drh
-Z ad447a72b5a7a06ad29b2399f5aa6480
+Z ceda48d7a4b9b3c738f23f47b38664dd
diff --git a/manifest.uuid b/manifest.uuid
index c719651356..d89cf8b8eb 100644
--- a/manifest.uuid
+++ b/manifest.uuid
@@ -1 +1 @@
-833291c22734b2ac2342da84710320eb28f5d8cc
\ No newline at end of file
+1f0197d504fa2bde15b287ac6c0102cacdb1e482
\ No newline at end of file
diff --git a/src/dbbe.h b/src/dbbe.h
index 6a386adf9a..31c6252f5c 100644
--- a/src/dbbe.h
+++ b/src/dbbe.h
@@ -28,7 +28,7 @@
** This library was originally designed to support the following
** backends: GDBM, NDBM, SDBM, Berkeley DB.
**
-** $Id: dbbe.h,v 1.11 2001/03/20 22:05:00 drh Exp $
+** $Id: dbbe.h,v 1.12 2001/04/03 16:53:22 drh Exp $
*/
#ifndef _SQLITE_DBBE_H_
#define _SQLITE_DBBE_H_
@@ -75,18 +75,19 @@ struct DbbeMethods {
/* Close the whole database. */
void (*Close)(Dbbe*);
- /* Open a cursor into particular file of a previously opened database.
- ** Create the file if it doesn't already exist and writeable!=0. zName
- ** is the base name of the file to be opened. This routine will add
- ** an appropriate path and extension to the filename to locate the
+ /* Open a cursor into a particular table of a previously opened database.
+ ** Create the table if it doesn't already exist and writeable!=0. zName
+ ** is the base name of the table to be opened. If the database is
+ ** implement as one file per table, then this routine will add an
+ ** appropriate path and extension to the table name to locate the
** actual file.
**
- ** The keyType parameter is TRUE if this table will only be accessed
+ ** The intKeyOnly parameter is TRUE if this table will only be accessed
** using integer keys. This parameter allows the database backend to
** use a faster algorithm for the special case of integer keys, if it
** wants to.
**
- ** If zName is 0 or "", then a temporary file is created that
+ ** If zName is 0 or "", then a temporary table is created that
** will be deleted when closed.
*/
int (*OpenCursor)(Dbbe*, const char *zName, int writeable,
@@ -165,7 +166,8 @@ struct DbbeMethods {
struct Dbbe {
struct DbbeMethods *x; /* Backend-specific methods for database access */
/* There used to be other information here, but it has since
- ** been removed. */
+ ** been removed. We'll keep the same design, though, in case we
+ ** ever want to add some new fields in the future. */
};
#endif /* defined(_SQLITE_DBBE_H_) */
diff --git a/src/dbbegdbm.c b/src/dbbegdbm.c
index 777c7dacef..8aba06b32f 100644
--- a/src/dbbegdbm.c
+++ b/src/dbbegdbm.c
@@ -30,7 +30,7 @@
** relatively simple to convert to a different database such
** as NDBM, SDBM, or BerkeleyDB.
**
-** $Id: dbbegdbm.c,v 1.4 2001/03/20 22:05:00 drh Exp $
+** $Id: dbbegdbm.c,v 1.5 2001/04/03 16:53:22 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -46,6 +46,9 @@
** for a self-join, for example) then two DbbeCursor structures are
** created but there is only a single BeFile structure with an
** nRef of 2.
+**
+** This backend uses a separate disk file for each database table
+** and index.
*/
typedef struct BeFile BeFile;
struct BeFile {
@@ -545,7 +548,7 @@ static int sqliteGdbmDelete(DbbeCursor *pCursr, int nKey, char *pKey){
** used to implement the GDBM backend.
*/
static struct DbbeMethods gdbmMethods = {
- /* n Close */ sqliteGdbmClose,
+ /* Close */ sqliteGdbmClose,
/* OpenCursor */ sqliteGdbmOpenCursor,
/* DropTable */ sqliteGdbmDropTable,
/* ReorganizeTable */ sqliteGdbmReorganizeTable,
diff --git a/src/dbbemem.c b/src/dbbemem.c
index 6bf1cc0f2f..86ddcf5706 100644
--- a/src/dbbemem.c
+++ b/src/dbbemem.c
@@ -27,8 +27,10 @@
** of information to the disk.
**
** This file uses an in-memory hash table as the database backend.
+** Nothing is ever written to disk using this backend. All information
+** is forgotten when the program exits.
**
-** $Id: dbbemem.c,v 1.11 2001/03/20 22:05:00 drh Exp $
+** $Id: dbbemem.c,v 1.12 2001/04/03 16:53:22 drh Exp $
*/
#include "sqliteInt.h"
#include
@@ -720,7 +722,7 @@ static int sqliteMemDelete(DbbeCursor *pCursr, int nKey, char *pKey){
** used to implement the MEMORY backend.
*/
static struct DbbeMethods memoryMethods = {
- /* n Close */ sqliteMemClose,
+ /* Close */ sqliteMemClose,
/* OpenCursor */ sqliteMemOpenCursor,
/* DropTable */ sqliteMemDropTable,
/* ReorganizeTable */ sqliteMemReorganizeTable,
diff --git a/src/pager.h b/src/pager.h
new file mode 100644
index 0000000000..cec8f4ea70
--- /dev/null
+++ b/src/pager.h
@@ -0,0 +1,56 @@
+/*
+** Copyright (c) 2001 D. Richard Hipp
+**
+** This program is free software; you can redistribute it and/or
+** modify it under the terms of the GNU General Public
+** License as published by the Free Software Foundation; either
+** version 2 of the License, or (at your option) any later version.
+**
+** This program is distributed in the hope that it will be useful,
+** but WITHOUT ANY WARRANTY; without even the implied warranty of
+** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+** General Public License for more details.
+**
+** You should have received a copy of the GNU General Public
+** License along with this library; if not, write to the
+** Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+** Boston, MA 02111-1307, USA.
+**
+** Author contact information:
+** drh@hwaci.com
+** http://www.hwaci.com/drh/
+**
+*************************************************************************
+** This header file defines the interface that the sqlite page cache
+** subsystem. The page cache subsystem reads and writes a file a page
+** at a time and provides a journal for rollback.
+**
+** @(#) $Id: pager.h,v 1.1 2001/04/03 16:53:22 drh Exp $
+*/
+#include "sqliteInt.h"
+
+/*
+** The size of one page
+*/
+#define SQLITE_PAGE_SIZE 1024
+
+/*
+** The type used to represent a page number. The first page in a file
+** is called page 1. 0 is used to represent "not a page".
+*/
+typedef unsigned int Pgno;
+
+/*
+** Each open file is managed by a separate instance of the "Pager" structure.
+*/
+typedef struct Pager Pager;
+
+int sqlite_pager_open(Pager **ppPager, const char *zFilename);
+int sqlite_pager_close(Pager *pPager);
+int sqlite_pager_get(Pager *pPager, Pgno pgno, void **ppPage);
+int sqlite_pager_unref(void*);
+Pgno sqlite_pager_pagenumber(void*);
+int sqlite_pager_write(void*);
+int sqlite_pager_pagecount(Pager*);
+int sqlite_pager_commit(Pager*);
+int sqlite_pager_rollback(Pager*);
diff --git a/src/sqlite.h.in b/src/sqlite.h.in
index 1f1980dc1d..59332dcf92 100644
--- a/src/sqlite.h.in
+++ b/src/sqlite.h.in
@@ -24,7 +24,7 @@
** This header file defines the interface that the sqlite library
** presents to client programs.
**
-** @(#) $Id: sqlite.h.in,v 1.9 2001/01/20 19:52:49 drh Exp $
+** @(#) $Id: sqlite.h.in,v 1.10 2001/04/03 16:53:22 drh Exp $
*/
#ifndef _SQLITE_H_
#define _SQLITE_H_
@@ -142,6 +142,8 @@ int sqlite_exec(
#define SQLITE_CORRUPT 10 /* The database disk image is malformed */
#define SQLITE_NOTFOUND 11 /* Table or record not found */
#define SQLITE_FULL 12 /* Insertion failed because database is full */
+#define SQLITE_CANTOPEN 13 /* Unable to open the database file */
+#define SQLITE_PROTOCOL 14 /* Database lock protocol error */
/* This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
diff --git a/src/tclsqlite.c b/src/tclsqlite.c
index 81c9ddb7e2..c880524220 100644
--- a/src/tclsqlite.c
+++ b/src/tclsqlite.c
@@ -23,7 +23,7 @@
*************************************************************************
** A TCL Interface to SQLite
**
-** $Id: tclsqlite.c,v 1.13 2001/01/31 13:28:09 drh Exp $
+** $Id: tclsqlite.c,v 1.14 2001/04/03 16:53:22 drh Exp $
*/
#ifndef NO_TCL /* Omit this whole file if TCL is unavailable */
@@ -53,6 +53,7 @@ struct CallbackData {
char *zArray; /* The array into which data is written */
Tcl_Obj *pCode; /* The code to execute for each row */
int once; /* Set only for the first invocation of callback */
+ int tcl_rc; /* Return code from TCL script */
};
/*
@@ -88,7 +89,9 @@ static int DbEvalCallback(
}
cbData->once = 0;
rc = Tcl_EvalObj(cbData->interp, cbData->pCode);
- return rc!=TCL_OK && rc!=TCL_CONTINUE;
+ if( rc==TCL_CONTINUE ) rc = TCL_OK;
+ cbData->tcl_rc = rc;
+ return rc!=TCL_OK;
}
/*
@@ -171,7 +174,7 @@ 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", "timeout"
+ "busy", "close", "complete", "eval", "timeout", 0
};
enum DB_opts {
DB_BUSY, DB_CLOSE, DB_COMPLETE, DB_EVAL, DB_TIMEOUT
@@ -278,20 +281,26 @@ static int DbObjCmd(void *cd, Tcl_Interp *interp, int objc,Tcl_Obj *const*objv){
cbData.once = 1;
cbData.zArray = Tcl_GetStringFromObj(objv[3], 0);
cbData.pCode = objv[4];
+ cbData.tcl_rc = TCL_OK;
zErrMsg = 0;
Tcl_IncrRefCount(objv[3]);
Tcl_IncrRefCount(objv[4]);
rc = sqlite_exec(pDb->db, zSql, DbEvalCallback, &cbData, &zErrMsg);
Tcl_DecrRefCount(objv[4]);
Tcl_DecrRefCount(objv[3]);
+ if( cbData.tcl_rc==TCL_BREAK ){ cbData.tcl_rc = TCL_OK; }
}else{
Tcl_Obj *pList = Tcl_NewObj();
+ cbData.tcl_rc = TCL_OK;
rc = sqlite_exec(pDb->db, zSql, DbEvalCallback2, pList, &zErrMsg);
Tcl_SetObjResult(interp, pList);
}
if( zErrMsg ){
Tcl_SetResult(interp, zErrMsg, TCL_VOLATILE);
free(zErrMsg);
+ rc = TCL_ERROR;
+ }else{
+ rc = cbData.tcl_rc;
}
Tcl_DecrRefCount(objv[2]);
return rc;
diff --git a/src/test.file b/src/test.file
deleted file mode 100644
index 45b983be36..0000000000
--- a/src/test.file
+++ /dev/null
@@ -1 +0,0 @@
-hi
diff --git a/test/dbbe.test b/test/dbbe.test
index d30047bc15..c9cd2148c3 100644
--- a/test/dbbe.test
+++ b/test/dbbe.test
@@ -23,7 +23,7 @@
# This file implements regression tests for SQLite library. The
# focus of this file is exercising the code in dbbe.c.
#
-# $Id: dbbe.test,v 1.6 2001/03/20 12:55:14 drh Exp $
+# $Id: dbbe.test,v 1.7 2001/04/03 16:53:22 drh Exp $
set testdir [file dirname $argv0]
source $testdir/tester.tcl
@@ -134,7 +134,7 @@ do_test dbbe-3.1 {
sqlite db testdb 0444
set v [catch {execsql {INSERT INTO t1 VALUES(1)}} msg]
lappend v $msg
-} {7 {table t1 is readonly}}
+} {1 {table t1 is readonly}}
finish_test
diff --git a/test/lock.test b/test/lock.test
index bae3864e25..ce93b0e776 100644
--- a/test/lock.test
+++ b/test/lock.test
@@ -23,7 +23,7 @@
# This file implements regression tests for SQLite library. The
# focus of this script is database locks.
#
-# $Id: lock.test,v 1.7 2001/03/20 12:55:14 drh Exp $
+# $Id: lock.test,v 1.8 2001/04/03 16:53:22 drh Exp $
if {$dbprefix=="gdbm:" && $::tcl_platform(platform)!="windows"} {
@@ -60,7 +60,7 @@ do_probtest lock-1.2 {
#
set v [catch {execsql {UPDATE big SET f2='xyz' WHERE f1=11}} msg]
lappend v $msg
-} {5 {table big is locked}}
+} {1 {table big is locked}}
do_probtest lock-1.3 {
# Try to update the database in a separate process
diff --git a/test/tclsqlite.test b/test/tclsqlite.test
new file mode 100644
index 0000000000..fd1f37af0e
--- /dev/null
+++ b/test/tclsqlite.test
@@ -0,0 +1,80 @@
+# Copyright (c) 1999, 2000 D. Richard Hipp
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public
+# License along with this library; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+#
+# Author contact information:
+# drh@hwaci.com
+# http://www.hwaci.com/drh/
+#
+#***********************************************************************
+# 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.1 2001/04/03 16:53:22 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, 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"
+ }
+ } msg]
+ lappend v $msg
+} {1 {The error message}}
+do_test tcl-1.4 {
+ set v [catch {
+ db eval {SELECT * FROM t2} data {
+ error "The error message"
+ }
+ } msg]
+ lappend v $msg
+} {1 {no such table: t2}}
+do_test tcl-1.5 {
+ set v [catch {
+ db eval {SELECT * FROM t1} data {
+ break
+ }
+ } msg]
+ lappend v $msg
+} {0 {}}
+do_test tcl-1.6 {
+ set v [catch {
+ db eval {SELECT * FROM t1} data {
+ expr x*
+ }
+ } msg]
+ lappend v $msg
+} {1 {syntax error in expression "x*"}}
+
+finish_test
diff --git a/tool/lemon.c b/tool/lemon.c
index e0ea780439..41426caa97 100644
--- a/tool/lemon.c
+++ b/tool/lemon.c
@@ -3,8 +3,8 @@
**
** This file contains all sources (including headers) to the LEMON
** LALR(1) parser generator. The sources have been combined into a
-** single file to make it easy to include LEMON as part of another
-** program.
+** single file to make it easy to include LEMON in the source tree
+** and Makefile of another program.
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public
@@ -263,6 +263,7 @@ struct lemon {
char *name; /* Name of the generated parser */
char *arg; /* Declaration of the 3th argument to parser */
char *tokentype; /* Type of terminal symbols in the parser stack */
+ char *vartype; /* The default type of non-terminal symbols */
char *start; /* Name of the start symbol for the grammar */
char *stacksize; /* Size of the parser stack */
char *include; /* Code to put at the start of the C file */
@@ -279,6 +280,8 @@ struct lemon {
int extracodeln; /* Line number for the start of the extra code */
char *tokendest; /* Code to execute to destroy token data */
int tokendestln; /* Line number for token destroyer code */
+ char *vardest; /* Code for the default non-terminal destructor */
+ int vardestln; /* Line number for default non-term destructor code*/
char *filename; /* Name of the input file */
char *outname; /* Name of the current output file */
char *tokenprefix; /* A prefix added to token names in the .h file */
@@ -1216,9 +1219,11 @@ char **argv;
lem.basisflag = basisflag;
lem.nconflict = 0;
lem.name = lem.include = lem.arg = lem.tokentype = lem.start = 0;
+ lem.vartype = 0;
lem.stacksize = 0;
lem.error = lem.overflow = lem.failure = lem.accept = lem.tokendest =
lem.tokenprefix = lem.outname = lem.extracode = 0;
+ lem.vardest = 0;
lem.tablesize = 0;
Symbol_new("$");
lem.errsym = Symbol_new("error");
@@ -1967,6 +1972,9 @@ to follow the previous rule.");
}else if( strcmp(x,"token_destructor")==0 ){
psp->declargslot = &psp->gp->tokendest;
psp->decllnslot = &psp->gp->tokendestln;
+ }else if( strcmp(x,"default_destructor")==0 ){
+ psp->declargslot = &psp->gp->vardest;
+ psp->decllnslot = &psp->gp->vardestln;
}else if( strcmp(x,"token_prefix")==0 ){
psp->declargslot = &psp->gp->tokenprefix;
}else if( strcmp(x,"syntax_error")==0 ){
@@ -1985,6 +1993,8 @@ to follow the previous rule.");
psp->declargslot = &(psp->gp->arg);
}else if( strcmp(x,"token_type")==0 ){
psp->declargslot = &(psp->gp->tokentype);
+ }else if( strcmp(x,"default_type")==0 ){
+ psp->declargslot = &(psp->gp->vartype);
}else if( strcmp(x,"stack_size")==0 ){
psp->declargslot = &(psp->gp->stacksize);
}else if( strcmp(x,"start_symbol")==0 ){
@@ -2210,7 +2220,7 @@ struct lemon *gp;
}
}
if( c==0 ){
- ErrorMsg(ps.filename,startline,
+ ErrorMsg(ps.filename,ps.tokenlineno,
"C code starting on this line is not terminated before the end of the file.");
ps.errorcnt++;
nextcp = cp;
@@ -2643,6 +2653,8 @@ struct lemon *lemp;
}
if( access(buf,004)==0 ){
tpltname = buf;
+ }else if( access(templatename,004)==0 ){
+ tpltname = templatename;
}else{
tpltname = pathsearch(lemp->argv0,templatename,0);
}
@@ -2697,10 +2709,13 @@ int *lineno;
cp = lemp->tokendest;
if( cp==0 ) return;
fprintf(out,"#line %d \"%s\"\n{",lemp->tokendestln,lemp->filename);
- }else{
+ }else if( sp->destructor ){
cp = sp->destructor;
- if( cp==0 ) return;
fprintf(out,"#line %d \"%s\"\n{",sp->destructorln,lemp->filename);
+ }else if( lemp->vardest ){
+ cp = lemp->vardest;
+ if( cp==0 ) return;
+ fprintf(out,"#line %d \"%s\"\n{",lemp->vardestln,lemp->filename);
}
for(; *cp; cp++){
if( *cp=='$' && cp[1]=='$' ){
@@ -2717,7 +2732,7 @@ int *lineno;
}
/*
-** Return TRUE (non-zero) if the given symbol has a distructor.
+** Return TRUE (non-zero) if the given symbol has a destructor.
*/
int has_destructor(sp, lemp)
struct symbol *sp;
@@ -2727,7 +2742,7 @@ struct lemon *lemp;
if( sp->type==TERMINAL ){
ret = lemp->tokendest!=0;
}else{
- ret = sp->destructor!=0;
+ ret = lemp->vardest!=0 || sp->destructor!=0;
}
return ret;
}
@@ -2796,7 +2811,7 @@ int *lineno;
for(i=0; inrhs; i++){
if( rp->rhsalias[i] && !used[i] ){
ErrorMsg(lemp->filename,rp->ruleline,
- "Label $%s$ for \"%s(%s)\" is never used.",
+ "Label %s for \"%s(%s)\" is never used.",
rp->rhsalias[i],rp->rhs[i]->name,rp->rhsalias[i]);
lemp->errorcnt++;
}else if( rp->rhsalias[i]==0 ){
@@ -2840,6 +2855,9 @@ int mhflag; /* True if generating makeheaders output */
types = (char**)malloc( arraysize * sizeof(char*) );
for(i=0; ivartype ){
+ maxdtlength = strlen(lemp->vartype);
+ }
for(i=0; insymbol; i++){
int len;
struct symbol *sp = lemp->symbols[i];
@@ -2855,8 +2873,10 @@ int mhflag; /* True if generating makeheaders output */
/* Build a hash table of datatypes. The ".dtnum" field of each symbol
** is filled in with the hash index plus 1. A ".dtnum" value of 0 is
- ** used for terminal symbols and for nonterminals which don't specify
- ** a datatype using the %type directive. */
+ ** used for terminal symbols. If there is no %default_type defined then
+ ** 0 is also used as the .dtnum value for nonterminals which do not specify
+ ** a datatype using the %type directive.
+ */
for(i=0; insymbol; i++){
struct symbol *sp = lemp->symbols[i];
char *cp;
@@ -2864,11 +2884,12 @@ int mhflag; /* True if generating makeheaders output */
sp->dtnum = arraysize+1;
continue;
}
- if( sp->type!=NONTERMINAL || sp->datatype==0 ){
+ if( sp->type!=NONTERMINAL || (sp->datatype==0 && lemp->vartype==0) ){
sp->dtnum = 0;
continue;
}
cp = sp->datatype;
+ if( cp==0 ) cp = lemp->vartype;
j = 0;
while( isspace(*cp) ) cp++;
while( *cp ) stddt[j++] = *cp++;
@@ -3159,6 +3180,20 @@ int mhflag; /* Output in makeheaders format if true */
emit_destructor_code(out,lemp->symbols[i],lemp,&lineno);
fprintf(out," break;\n"); lineno++;
}
+ if( lemp->vardest ){
+ struct symbol *dflt_sp = 0;
+ for(i=0; insymbol; i++){
+ struct symbol *sp = lemp->symbols[i];
+ if( sp==0 || sp->type==TERMINAL ||
+ sp->index<=0 || sp->destructor!=0 ) continue;
+ fprintf(out," case %d:\n",sp->index); lineno++;
+ dflt_sp = sp;
+ }
+ if( dflt_sp!=0 ){
+ emit_destructor_code(out,dflt_sp,lemp,&lineno);
+ fprintf(out," break;\n"); lineno++;
+ }
+ }
tplt_xfer(lemp->name,in,out,&lineno);
/* Generate code which executes whenever the parser stack overflows */
diff --git a/tool/lempar.c b/tool/lempar.c
index e5293b1de2..8b35e86bf8 100644
--- a/tool/lempar.c
+++ b/tool/lempar.c
@@ -1,9 +1,5 @@
/* Driver template for the LEMON parser generator.
** Copyright 1991-1995 by D. Richard Hipp.
-*
-* This version is specially modified for use with sqlite.
-* @(#) $Id: lempar.c,v 1.1 2000/05/29 14:26:02 drh Exp $
-*
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Library General Public
@@ -177,7 +173,6 @@ static char *yyTracePrompt = 0;
** Outputs:
** None.
*/
-/* SQLITE MODIFICATION: Give the function file scope */
void ParseTrace(FILE *TraceFILE, char *zTracePrompt){
yyTraceFILE = TraceFILE;
yyTracePrompt = zTracePrompt;
@@ -195,6 +190,18 @@ static char *yyTokenName[] = {
#define YYTRACE(X)
#endif
+/*
+** This function returns the symbolic name associated with a token
+** value.
+*/
+const char *ParseTokenName(int tokenType){
+ if( tokenType>0 && tokenType<(sizeof(yyTokenName)/sizeof(yyTokenName[0])) ){
+ return yyTokenName[tokenType];
+ }else{
+ return "Unknown";
+ }
+}
+
/*
** This function allocates a new parser.
** The only argument is a pointer to a function which works like
@@ -207,10 +214,9 @@ static char *yyTokenName[] = {
** A pointer to a parser. This pointer is used in subsequent calls
** to Parse and ParseFree.
*/
-/* SQLITE MODIFICATION: Give the function file scope */
-void *ParseAlloc(void *(*mallocProc)()){
+void *ParseAlloc(void *(*mallocProc)(int)){
yyParser *pParser;
- pParser = (yyParser*)(*mallocProc)( sizeof(yyParser), __FILE__, __LINE__ );
+ pParser = (yyParser*)(*mallocProc)( (int)sizeof(yyParser) );
if( pParser ){
pParser->idx = -1;
}
@@ -277,15 +283,14 @@ static int yy_pop_parser_stack(yyParser *pParser){
** from malloc.
**
*/
-/* SQLITE MODIFICATION: Give the function file scope */
void ParseFree(
- void *p, /* The parser to be deleted */
- void (*freeProc)() /* Function used to reclaim memory */
+ void *p, /* The parser to be deleted */
+ void (*freeProc)(void*) /* Function used to reclaim memory */
){
yyParser *pParser = (yyParser*)p;
if( pParser==0 ) return;
while( pParser->idx>=0 ) yy_pop_parser_stack(pParser);
- (*freeProc)(pParser, __FILE__, __LINE__);
+ (*freeProc)((void*)pParser);
}
/*
@@ -366,7 +371,7 @@ static struct {
%%
};
-static void yy_accept(); /* Forward declaration */
+static void yy_accept(yyParser * ParseANSIARGDECL); /* Forward Declaration */
/*
** Perform a reduce action and the shift that must immediately
@@ -475,7 +480,6 @@ static void yy_accept(
** Outputs:
** None.
*/
-/* SQLITE MODIFICATION: Give the function file scope */
void Parse(
void *yyp, /* The parser */
int yymajor, /* The major token code number */
diff --git a/www/changes.tcl b/www/changes.tcl
index 111276c81a..ac8dd670e0 100644
--- a/www/changes.tcl
+++ b/www/changes.tcl
@@ -17,6 +17,12 @@ proc chng {date desc} {
puts "
"
}
+chng {2001 Apr 3 (1.0.28)} {
+Changes to the "lemon" parser generator to help it work better when
+ compiled using MSVC.
+Bug fixes in the TCL interface identified by Oleg Oleinick.
+}
+
chng {2001 Mar 20 (1.0.27)} {
When doing DELETE and UPDATE, the library used to write the record
numbers of records to be deleted or updated into a temporary file.