diff --git a/manifest b/manifest index 8397849c93..17db1acb9e 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Pager\soptimization:\sdo\snot\swrite\sor\sjournal\sfree\spages.\s\sThis\sresults\sin\na\s2x\sperformance\sgain\sfor\slarge\sINSERTs\sand\sa\s5x\sperformance\sgain\sfor\nlarge\sDELETEs.\s(CVS\s410) -D 2002-03-02T20:41:58 +C Bug\sfixes\sand\sadditional\stests\sfor\sthe\ssubquery\sflattener.\s(CVS\s411) +D 2002-03-03T02:49:51 F Makefile.in 50f1b3351df109b5774771350d8c1b8d3640130d F Makefile.template 89e373b2dad0321df00400fa968dc14b61a03296 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -37,11 +37,11 @@ F src/pager.h feb18aab2f6dea439393f23a382699b9b1053c32 F src/parse.y d62960cdee2d2e7821f277d2fe63d823c86602ba F src/printf.c 300a90554345751f26e1fc0c0333b90a66110a1d F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c b99de04f6f2414bb21a065150e0748ccd8329519 +F src/select.c 285a9cfa670c3fc47d8f42c9873be88860a015a1 F src/shell.c 9f8249ca5b8f8aad40becd778c151b58c0d6109e F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in a9b5772604265f98f3120573ef29e37b9d917216 -F src/sqliteInt.h df68f09091ab37d904020ac48ca2ea29e4985442 +F src/sqliteInt.h 272c356245e3fdb33e91e87a3f7c0324d118cac9 F src/table.c 203a09d5d0009eeeb1f670370d52b4ce163a3b52 F src/tclsqlite.c b9cf346e95291cb4c4f1bf5ac1d77db6b8ad023d F src/test1.c 33efd350dca27c52c58c553c04fd3a6a51f13c1f @@ -51,7 +51,7 @@ F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f F src/tokenize.c 4b5d30590a744b9bb5605a92d1f620ab2e7e75af F src/update.c 943b821901efb796dc82d91653621aeeb48d223b F src/util.c 00a35b421c92ae0d7cfa51bd87f7d4995f464d19 -F src/vdbe.c 91311e99efe980459a78e8f5b9e5456d772c9e23 +F src/vdbe.c 4989cd3e6f4f699c9b08cd1980d1b588cede5c1f F src/vdbe.h f9be1f6e9a336c3ff4d14ea7489ee976e07460cc F src/where.c 34d91fd5d822c2663caeb023f72d60df316ebf29 F test/all.test 7a8a8a7a579ed2bb4d8976d55402f21eacd58049 @@ -67,7 +67,7 @@ F test/func.test 4359344586067e79abf4c710c4737d67ed3cf963 F test/in.test c09312672e3f0709fa02c8e2e9cd8fb4bd6269aa F test/index.test c8a471243bbf878974b99baf5badd59407237cf3 F test/insert.test c36d534a4ab58c2cd452a273e51b2b0dd1ede1f9 -F test/insert2.test 65c2b2aae0bae7a7bbe500f77981cd916b81e91b +F test/insert2.test 2f02b1e0dbfba3e8c76496209be5f4010b584181 F test/intpkey.test 101ec266222e88b24e6f1e204b9b6873404cd4dc F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a F test/limit.test a930f3eba2a7691c8397ccab33710b931589566a @@ -87,7 +87,7 @@ F test/select2.test ed2c1882857106b85478f54f67000e14966be4c4 F test/select3.test 9469c332250a75a0ef1771fb5da62dc04ec77f18 F test/select4.test 29a2ffb187f3d8b6ca42a0a6b619e9cabe12e228 F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac -F test/select6.test d9fb417d6cab75a072b547ba6303120f327fd6fd +F test/select6.test 8ccbcd3b53df4735a5bb3a8cd4bf4e495cae26c0 F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b F test/subselect.test 335d3dad8d585726c447dfee8d9c4f7383c76b78 F test/table.test 17b0b6eafa3faaee5545b7a94e6c1ff73f0880f3 @@ -98,10 +98,10 @@ F test/tester.tcl 96db1b49157388edb57e11bf33285e3811a897e4 F test/trans.test 9e49495c06b1c41f889bf4f0fb195a015b126de0 F test/unique.test 07776624b82221a80c8b4138ce0dd8b0853bb3ea F test/update.test 3cf1ca0565f678063c2dfa9a7948d2d66ae1a778 -F test/vacuum.test 8acf8669f3b627e54149b25165b034aa06c2432e +F test/vacuum.test 059871b312eb910bbe49dafde1d01490cc2c6bbe F test/view.test 4619ebede587102e577e19ce52e9852ec8293cbc F test/where.test 032d581c3de4893eba33b569e581c46b941bb02a -F tool/lemon.c d4b4e127e70633be1bbea49c2ccba5cdb4b77a5f +F tool/lemon.c a26214e008a7351c0c9fc57c5aab44b403c36c42 F tool/lempar.c 2ff255186fffb38a43a9f7b010e87eee6308edcc F tool/memleak.awk 296dfbce7a9ca499b95ce04e30334e64a50052e0 F tool/opNames.awk 5ba1f48aa854ee3b7c3d2b54233665bc3e649ea2 @@ -127,7 +127,7 @@ F www/speed.tcl 83457b2bf6bb430900bd48ca3dd98264d9a916a5 F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 829b393d1ab187fd7a5e978631b3429318885c49 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P abbb999d4fc3fe142567b6ede5e625e7bf0da714 -R 65be3ccaeb081927d6806e4071f74e0f +P cf1ebcfb741786f84a596c406f4c492f68cbe881 +R 15fdb1a16caac3bbe9fb9691324e3176 U drh -Z 3493ea99db08effd4dc1d635e5b15238 +Z 2b80ac05372abd52845156b2368b8bf6 diff --git a/manifest.uuid b/manifest.uuid index 75e1b749c1..e74ffaeaa8 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -cf1ebcfb741786f84a596c406f4c492f68cbe881 \ No newline at end of file +2c05389eda391e38894fc6969e29766df82a8fec \ No newline at end of file diff --git a/src/select.c b/src/select.c index 94eb2ae0be..fb55a3fe68 100644 --- a/src/select.c +++ b/src/select.c @@ -12,7 +12,7 @@ ** This file contains C code routines that are called by the parser ** to handle SELECT statements in SQLite. ** -** $Id: select.c,v 1.71 2002/03/02 17:04:08 drh Exp $ +** $Id: select.c,v 1.72 2002/03/03 02:49:51 drh Exp $ */ #include "sqliteInt.h" @@ -760,13 +760,17 @@ static void changeTables(Expr *pExpr, int iFrom, int iTo){ if( pExpr->op==TK_COLUMN && pExpr->iTable==iFrom ){ pExpr->iTable = iTo; }else{ + static void changeTablesInList(ExprList*, int, int); changeTables(pExpr->pLeft, iFrom, iTo); changeTables(pExpr->pRight, iFrom, iTo); - if( pExpr->pList ){ - int i; - for(i=0; ipList->nExpr; i++){ - changeTables(pExpr->pList->a[i].pExpr, iFrom, iTo); - } + changeTablesInList(pExpr->pList, iFrom, iTo); + } +} +static void changeTablesInList(ExprList *pList, int iFrom, int iTo){ + if( pList ){ + int i; + for(i=0; inExpr; i++){ + changeTables(pList->a[i].pExpr, iFrom, iTo); } } } @@ -799,6 +803,7 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList, int iSub){ pExpr->iTable = pNew->iTable; pExpr->iColumn = pNew->iColumn; pExpr->iAgg = pNew->iAgg; + pExpr->token = pNew->token; if( iSub!=iTable ){ changeTables(pExpr, iSub, iTable); } @@ -908,8 +913,10 @@ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ pList->a[i].zName = sqliteStrNDup(pExpr->span.z, pExpr->span.n); } } - substExprList(p->pGroupBy, iParent, pSub->pEList, iSub); - substExpr(p->pHaving, iParent, pSub->pEList, iSub); + if( isAgg ){ + substExprList(p->pGroupBy, iParent, pSub->pEList, iSub); + substExpr(p->pHaving, iParent, pSub->pEList, iSub); + } substExprList(p->pOrderBy, iParent, pSub->pEList, iSub); if( pSub->pWhere ){ pWhere = sqliteExprDup(pSub->pWhere); @@ -921,8 +928,25 @@ int flattenSubquery(Select *p, int iFrom, int isAgg, int subqueryIsAgg){ } if( subqueryIsAgg ){ assert( p->pHaving==0 ); - p->pHaving = pWhere; + p->pHaving = p->pWhere; + p->pWhere = pWhere; substExpr(p->pHaving, iParent, pSub->pEList, iSub); + if( pSub->pHaving ){ + Expr *pHaving = sqliteExprDup(pSub->pHaving); + if( iParent!=iSub ){ + changeTables(pHaving, iSub, iParent); + } + if( p->pHaving ){ + p->pHaving = sqliteExpr(TK_AND, p->pHaving, pHaving, 0); + }else{ + p->pHaving = pHaving; + } + } + assert( p->pGroupBy==0 ); + p->pGroupBy = sqliteExprListDup(pSub->pGroupBy); + if( iParent!=iSub ){ + changeTablesInList(p->pGroupBy, iSub, iParent); + } }else if( p->pWhere==0 ){ p->pWhere = pWhere; }else{ @@ -1083,6 +1107,13 @@ static int simpleMinMaxQuery(Parse *pParse, Select *p, int eDest, int iParm){ ** ** This routine does NOT free the Select structure passed in. The ** calling function needs to do that. +** +** The pParent, parentTab, and *pParentAgg fields are filled in if this +** SELECT is a subquery. This routine may try to combine this SELECT +** with its parent to form a single flat query. In so doing, it might +** change the parent query from a non-aggregate to an aggregate query. +** For that reason, the pParentAgg flag is passed as a pointer, so it +** can be changed. */ int sqliteSelect( Parse *pParse, /* The parser context */ @@ -1091,7 +1122,7 @@ int sqliteSelect( int iParm, /* Save result in this memory location, if >=0 */ Select *pParent, /* Another SELECT for which this is a sub-query */ int parentTab, /* Index in pParent->pSrc of this query */ - int parentAgg /* True if pParent uses aggregate functions */ + int *pParentAgg /* True if pParent uses aggregate functions */ ){ int i; WhereInfo *pWInfo; @@ -1254,21 +1285,23 @@ int sqliteSelect( if( pTabList->a[i].pSelect==0 ) continue; sqliteVdbeAddOp(v, OP_OpenTemp, base+i, 0); sqliteSelect(pParse, pTabList->a[i].pSelect, SRT_Table, base+i, - p, i, isAgg); + p, i, &isAgg); + pTabList = p->pSrc; + pWhere = p->pWhere; + pOrderBy = p->pOrderBy; + pGroupBy = p->pGroupBy; + pHaving = p->pHaving; + isDistinct = p->isDistinct; } /* Check to see if this is a subquery that can be "flattened" into its parent. ** If flattening is a possiblity, do so and return immediately. */ - if( flattenSubquery(pParent, parentTab, parentAgg, isAgg) ){ + if( pParent && pParentAgg && + flattenSubquery(pParent, parentTab, *pParentAgg, isAgg) ){ + if( isAgg ) *pParentAgg = 1; return rc; } - pTabList = p->pSrc; - pWhere = p->pWhere; - pOrderBy = p->pOrderBy; - pGroupBy = p->pGroupBy; - pHaving = p->pHaving; - isDistinct = p->isDistinct; /* Do an analysis of aggregate expressions. */ diff --git a/src/sqliteInt.h b/src/sqliteInt.h index 3dcda0a66a..bb6ee1aacd 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.97 2002/03/02 17:04:08 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.98 2002/03/03 02:49:51 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -589,7 +589,7 @@ void sqliteIdListAddAlias(IdList*, Token*); void sqliteIdListDelete(IdList*); void sqliteCreateIndex(Parse*, Token*, Token*, IdList*, int, Token*, Token*); void sqliteDropIndex(Parse*, Token*); -int sqliteSelect(Parse*, Select*, int, int, Select*, int, int); +int sqliteSelect(Parse*, Select*, int, int, Select*, int, int*); Select *sqliteSelectNew(ExprList*,IdList*,Expr*,ExprList*,Expr*,ExprList*, int,int,int); void sqliteSelectDelete(Select*); diff --git a/src/vdbe.c b/src/vdbe.c index 5514df12d4..1d8989740b 100644 --- a/src/vdbe.c +++ b/src/vdbe.c @@ -30,7 +30,7 @@ ** But other routines are also provided to help in building up ** a program instruction by instruction. ** -** $Id: vdbe.c,v 1.129 2002/02/28 03:31:11 drh Exp $ +** $Id: vdbe.c,v 1.130 2002/03/03 02:49:51 drh Exp $ */ #include "sqliteInt.h" #include @@ -1096,6 +1096,7 @@ int sqliteVdbeList( char zAddr[20]; char zP1[20]; char zP2[20]; + char zP3[40]; static char *azColumnNames[] = { "addr", "opcode", "p1", "p2", "p3", 0 }; @@ -1116,7 +1117,12 @@ int sqliteVdbeList( sprintf(zAddr,"%d",i); sprintf(zP1,"%d", p->aOp[i].p1); sprintf(zP2,"%d", p->aOp[i].p2); - azValue[4] = p->aOp[i].p3type!=P3_POINTER ? p->aOp[i].p3 : ""; + if( p->aOp[i].p3type==P3_POINTER ){ + sprintf(zP3, "ptr(%#x)", (int)p->aOp[i].p3); + azValue[4] = zP3; + }else{ + azValue[4] = p->aOp[i].p3; + } azValue[1] = zOpName[p->aOp[i].opcode]; if( xCallback(pArg, 5, azValue, azColumnNames) ){ rc = SQLITE_ABORT; diff --git a/test/insert2.test b/test/insert2.test index 16261ae19c..fca4865edb 100644 --- a/test/insert2.test +++ b/test/insert2.test @@ -12,7 +12,7 @@ # focus of this file is testing the INSERT statement that takes is # result from a SELECT. # -# $Id: insert2.test,v 1.7 2002/02/19 13:39:23 drh Exp $ +# $Id: insert2.test,v 1.8 2002/03/03 02:49:52 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -112,10 +112,75 @@ do_test insert2-2.3 { } } {hi 2 1} -do_test insert2-4.0 { +do_test insert2-3.0 { set x [execsql {PRAGMA integrity_check}] if {$x==""} {set x ok} set x } {ok} +# File table t4 with lots of data +# +do_test insert2-3.1 { + execsql { + SELECT * from t4; + } +} {1 2} +do_test insert2-3.2 { + execsql { + BEGIN; + INSERT INTO t4 VALUES(2,4); + INSERT INTO t4 VALUES(3,6); + INSERT INTO t4 VALUES(4,8); + INSERT INTO t4 VALUES(5,10); + INSERT INTO t4 VALUES(6,12); + INSERT INTO t4 VALUES(7,14); + INSERT INTO t4 VALUES(8,16); + INSERT INTO t4 VALUES(9,18); + INSERT INTO t4 VALUES(10,20); + COMMIT; + SELECT count(*) FROM t4; + } +} {10} +do_test insert2-3.3 { + execsql { + BEGIN; + INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; + INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; + INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; + INSERT INTO t4 SELECT x+(SELECT max(x) FROM t4),y FROM t4; + COMMIT; + SELECT count(*) FROM t4; + } +} {160} +do_test insert2-3.4 { + execsql { + BEGIN; + UPDATE t4 SET y='lots of data for the row where x=' || x + || ' and y=' || y || ' - even more data to fill space'; + COMMIT; + SELECT count(*) FROM t4; + } +} {160} +do_test insert2-3.5 { + execsql { + BEGIN; + INSERT INTO t4 SELECT x+(SELECT max(x)+1 FROM t4),y FROM t4; + SELECT count(*) from t4; + ROLLBACK; + } +} {320} +do_test insert2-3.6 { + execsql { + SELECT count(*) FROM t4; + } +} {160} +do_test insert2-3.7 { + execsql { + BEGIN; + DELETE FROM t4 WHERE x!=123; + SELECT count(*) FROM t4; + ROLLBACK; + } +} {1} + finish_test diff --git a/test/select6.test b/test/select6.test index fbad950c29..afbff9037b 100644 --- a/test/select6.test +++ b/test/select6.test @@ -12,7 +12,7 @@ # focus of this file is testing SELECT statements that contain # subqueries in their FROM clause. # -# $Id: select6.test,v 1.2 2002/02/18 13:35:33 drh Exp $ +# $Id: select6.test,v 1.3 2002/03/03 02:49:52 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -166,4 +166,103 @@ do_test sqlite6-3.2 { ORDER BY [a.q] } } {1 1 1 2 2 3 3 4 7 4 8 15 5 5 20} + +do_test select6-3.3 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1) + } +} {10.5 3.7 14.2} +do_test select6-3.4 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4) + } +} {11.5 4 15.5} +do_test select6-3.5 { + execsql { + SELECT x,y,x+y FROM (SELECT avg(a) as 'x', avg(b) as 'y' FROM t2 WHERE a=4) + } +} {4 3 7} +do_test select6-3.6 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1) + WHERE a>10 + } +} {10.5 3.7 14.2} +do_test select6-3.7 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1) + WHERE a<10 + } +} {} +do_test select6-3.8 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4) + WHERE a>10 + } +} {11.5 4 15.5} +do_test select6-3.9 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', avg(y) as 'b' FROM t1 WHERE y=4) + WHERE a<10 + } +} {} +do_test select6-3.10 { + execsql { + SELECT a,b,a+b FROM (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b) + ORDER BY a + } +} {1 1 2 2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18 5 23} +do_test select6-3.11 { + execsql { + SELECT a,b,a+b FROM + (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b) + WHERE b<4 ORDER BY a + } +} {1 1 2 2.5 2 4.5 5.5 3 8.5} +do_test select6-3.12 { + execsql { + SELECT a,b,a+b FROM + (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1) + WHERE b<4 ORDER BY a + } +} {2.5 2 4.5 5.5 3 8.5} +do_test select6-3.13 { + execsql { + SELECT a,b,a+b FROM + (SELECT avg(x) as 'a', y as 'b' FROM t1 GROUP BY b HAVING a>1) + ORDER BY a + } +} {2.5 2 4.5 5.5 3 8.5 11.5 4 15.5 18 5 23} +do_test select6-3.14 { + execsql { + SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y) + ORDER BY [count(*)] + } +} {1 1 2 2 4 3 5 5 8 4} +do_test select6-3.15 { + execsql { + SELECT [count(*)],y FROM (SELECT count(*), y FROM t1 GROUP BY y) + ORDER BY y + } +} {1 1 2 2 4 3 8 4 5 5} + +do_test select6-4.1 { + execsql { + SELECT a,b,c FROM + (SELECT x AS 'a', y AS 'b', x+y AS 'c' FROM t1 WHERE y=4) + WHERE a<10 ORDER BY a; + } +} {8 4 12 9 4 13} +do_test select6-4.2 { + execsql { + SELECT y FROM (SELECT DISTINCT y FROM t1) WHERE y<5 ORDER BY y + } +} {1 2 3 4} +do_test select6-4.3 { + execsql { + SELECT DISTINCT y FROM (SELECT y FROM t1) WHERE y<5 ORDER BY y + } +} {1 2 3 4} + + finish_test diff --git a/test/vacuum.test b/test/vacuum.test index 6cc8838bac..83f99484bd 100644 --- a/test/vacuum.test +++ b/test/vacuum.test @@ -11,63 +11,12 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the VACUUM statement. # -# $Id: vacuum.test,v 1.6 2001/09/16 00:13:28 drh Exp $ +# $Id: vacuum.test,v 1.7 2002/03/03 02:49:52 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl -if {0} { +# The vacuum command no longer functions. There is +# nothing to test. -# Try to vacuum a non-existant table. -# -do_test vacuum-1.1 { - set v [catch {execsql {VACUUM dummy1}} msg] - lappend v $msg -} {1 {no such table or index: dummy1}} - -# It is OK to vacuum sqlite_master... -# -do_test vacuum-1.2 { - set v [catch {execsql {VACUUM sqlite_master}} msg] - lappend v $msg -} {0 {}} - -# Create some tables and indices to test against. -# -execsql {CREATE TABLE test1(a int)} -execsql {CREATE TABLE test2(b int)} -execsql {CREATE INDEX index1 ON test1(a)} -execsql {INSERT INTO test1 VALUES(1)} -execsql {INSERT INTO test1 VALUES(1)} -execsql {INSERT INTO test1 VALUES(2)} -execsql {INSERT INTO test1 VALUES(3)} -execsql {INSERT INTO test2 VALUES(4)} - -do_test vacuum-1.3 { - set b1 [file mtime testdb/test1.tbl] - set b2 [file mtime testdb/test2.tbl] - set b3 [file mtime testdb/index1.tbl] - after 1000 - execsql {VACUUM test1} - set a1 [file mtime testdb/test1.tbl] - set a2 [file mtime testdb/test2.tbl] - set a3 [file mtime testdb/index1.tbl] - expr {$a1>$b1 && $a2==$b2 && $a3==$b3} -} {1} -if {$::tcl_platform(platform)!="windows"} { -do_test vacuum-1.4 { - set b1 [file mtime testdb/test1.tbl] - set b2 [file mtime testdb/test2.tbl] - set b3 [file mtime testdb/index1.tbl] - after 1000 - execsql {VACUUM} - set a1 [file mtime testdb/test1.tbl] - set a2 [file mtime testdb/test2.tbl] - set a3 [file mtime testdb/index1.tbl] - expr {$a1>$b1 && $a2>$b2 && $a3>$b3} -} {1} -} ;# End if( platform!=windows ) - -finish_test - -} +# finish_test diff --git a/tool/lemon.c b/tool/lemon.c index eae3c09fd4..7cb108027f 100644 --- a/tool/lemon.c +++ b/tool/lemon.c @@ -3103,13 +3103,16 @@ int mhflag; /* Output in makeheaders format if true */ } /* Print the hash table */ - fprintf(out,"/* State %d */\n",stp->index); lineno++; + if( tablesize>0 ){ + fprintf(out,"/* State %d */\n",stp->index); lineno++; + } for(j=0; jsp->index, collide[j]+1, - compute_action(lemp,table[j])); + compute_action(lemp,table[j]), + j+1); PrintAction(table[j],out,22); fprintf(out," */\n"); lineno++;