mirror of
https://github.com/sqlite/sqlite.git
synced 2025-07-30 19:03:16 +03:00
Bug fixes and additional tests for the subquery flattener. (CVS 411)
FossilOrigin-Name: 2c05389eda391e38894fc6969e29766df82a8fec
This commit is contained in:
24
manifest
24
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
|
||||
|
@ -1 +1 @@
|
||||
cf1ebcfb741786f84a596c406f4c492f68cbe881
|
||||
2c05389eda391e38894fc6969e29766df82a8fec
|
65
src/select.c
65
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,14 +760,18 @@ 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; i<pExpr->pList->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; i<pList->nExpr; 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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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) ){
|
||||
return rc;
|
||||
}
|
||||
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( pParent && pParentAgg &&
|
||||
flattenSubquery(pParent, parentTab, *pParentAgg, isAgg) ){
|
||||
if( isAgg ) *pParentAgg = 1;
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Do an analysis of aggregate expressions.
|
||||
*/
|
||||
|
@ -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*);
|
||||
|
10
src/vdbe.c
10
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 <ctype.h>
|
||||
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -3103,13 +3103,16 @@ int mhflag; /* Output in makeheaders format if true */
|
||||
}
|
||||
|
||||
/* Print the hash table */
|
||||
if( tablesize>0 ){
|
||||
fprintf(out,"/* State %d */\n",stp->index); lineno++;
|
||||
}
|
||||
for(j=0; j<tablesize; j++){
|
||||
assert( table[j]!=0 );
|
||||
fprintf(out," {%4d,%4d,%4d}, /* ",
|
||||
fprintf(out," {%4d,%4d,%4d}, /* %2d: ",
|
||||
table[j]->sp->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++;
|
||||
|
Reference in New Issue
Block a user