From 195e6967fb489401471c7ab99e3c4042d07347f4 Mon Sep 17 00:00:00 2001 From: drh Date: Sat, 25 May 2002 00:18:20 +0000 Subject: [PATCH] Additional testing of LEFT OUTER JOIN. (CVS 588) FossilOrigin-Name: d8d04c14f18d1feba89ccea0be70530a18248c51 --- manifest | 16 +++--- manifest.uuid | 2 +- src/select.c | 18 ++++--- src/sqliteInt.h | 7 ++- test/join.test | 141 +++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 163 insertions(+), 21 deletions(-) diff --git a/manifest b/manifest index 3845b14f97..3a7b09999a 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Initial\simplementation\sof\sLEFT\sOUTER\sJOIN\sincluding\sthe\sexpanded\sSQL92\sjoin\nsyntax.\sThe\sbasic\sfunctionality\sis\sthere\sbut\sthere\sis\sstill\sa\slot\sof\stesting\nto\sdo.\s(CVS\s587) -D 2002-05-24T20:31:37 +C Additional\stesting\sof\sLEFT\sOUTER\sJOIN.\s(CVS\s588) +D 2002-05-25T00:18:21 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -37,11 +37,11 @@ F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e F src/parse.y c681da701bf142967325b8791f22418e2d81552d F src/printf.c d8032ee18b860c812eeff596c9bebfdacb7930fd F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe -F src/select.c 8f0ec9de36a22d167402af6ff8936e142ada4a11 +F src/select.c bbf00ee2b4412c7249baf0ba737ba6a93fe82e78 F src/shell.c 1d22fe870ee852cfb975fd000dbe3973713d0a15 F src/shell.tcl 27ecbd63dd88396ad16d81ab44f73e6c0ea9d20e F src/sqlite.h.in 0038faa6d642de06b91143ee65a131bd831d020b -F src/sqliteInt.h 5b71407c8546514168ae6984c18c5d035a2643ce +F src/sqliteInt.h 9d565908e2ca53c54d1a0ae445cba039ee018aba F src/table.c eed2098c9b577aa17f8abe89313a9c4413f57d63 F src/tclsqlite.c 9300c9606a38bc0c75d6c0bc8a6197ab979353d1 F src/test1.c 09d95048b66ce6dcd2bae90f443589043d7d631e @@ -71,7 +71,7 @@ F test/insert.test 58d44c19b3557f67f4aeb5110ed9ef02038c3684 F test/insert2.test eb8481878a7f52ccb4e3346f87550f5afdd77f76 F test/intpkey.test 31b5f28b2c44273e6695cf36ab2e4133aee7753c F test/ioerr.test 57d9bffaca18b34f9e976f786eadc2591d6efc6a -F test/join.test 905f4b13f8505f6b5b25af82ef11180860e6b180 +F test/join.test ea6a4097e4fcebbb16eac7ec819569e759336a74 F test/limit.test 6f98bcefc92209103bb3764c81975a6ec21d6702 F test/lock.test 3fcfd46a73119f6a18094673328a32c7b3047a8f F test/main.test c66b564554b770ee7fdbf6a66c0cd90329bc2c85 @@ -135,7 +135,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P e238643efdbe1394c7ff85e34e486f7c6082b6cc -R b59d515c126e5f1a822d5f6777b2906b +P 99bd1f5b9a1a20bfeefe15c00d96a34a5f40923e +R 289d0473700b92bde61e98c6617d8be0 U drh -Z 38ee23869a9185b6bcb4ab87628c02b5 +Z f910247eaeb3d662acb5a7b6aeac9b33 diff --git a/manifest.uuid b/manifest.uuid index b7468024c6..65d176ce96 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -99bd1f5b9a1a20bfeefe15c00d96a34a5f40923e \ No newline at end of file +d8d04c14f18d1feba89ccea0be70530a18248c51 \ No newline at end of file diff --git a/src/select.c b/src/select.c index f6b719984f..e4117f9d67 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.84 2002/05/24 20:31:37 drh Exp $ +** $Id: select.c,v 1.85 2002/05/25 00:18:21 drh Exp $ */ #include "sqliteInt.h" @@ -81,9 +81,9 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ int code; } keywords[] = { { "natural", 7, JT_NATURAL }, - { "left", 4, JT_LEFT }, - { "right", 5, JT_RIGHT }, - { "full", 4, JT_FULL }, + { "left", 4, JT_LEFT|JT_OUTER }, + { "right", 5, JT_RIGHT|JT_OUTER }, + { "full", 4, JT_LEFT|JT_RIGHT|JT_OUTER }, { "outer", 5, JT_OUTER }, { "inner", 5, JT_INNER }, { "cross", 5, JT_INNER }, @@ -92,7 +92,7 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ apAll[0] = pA; apAll[1] = pB; apAll[2] = pC; - for(i=0; apAll[i]; i++){ + for(i=0; i<3 && apAll[i]; i++){ p = apAll[i]; for(j=0; jn==keywords[j].nChar @@ -108,8 +108,7 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ } if( (jointype & (JT_INNER|JT_OUTER))==(JT_INNER|JT_OUTER) || - (jointype & JT_ERROR)!=0 || - (jointype & JT_RIGHT)==JT_RIGHT + (jointype & JT_ERROR)!=0 ){ static Token dummy = { 0, 0 }; char *zSp1 = " ", *zSp2 = " "; @@ -119,6 +118,11 @@ int sqliteJoinType(Parse *pParse, Token *pA, Token *pB, Token *pC){ pA->z, pA->n, zSp1, 1, pB->z, pB->n, zSp2, 1, pC->z, pC->n, 0); pParse->nErr++; jointype = JT_INNER; + }else if( jointype & JT_RIGHT ){ + sqliteSetString(&pParse->zErrMsg, + "RIGHT and FULL OUTER JOINs are not currently supported", 0); + pParse->nErr++; + jointype = JT_INNER; } return jointype; } diff --git a/src/sqliteInt.h b/src/sqliteInt.h index d323174e7e..77cfe62820 100644 --- a/src/sqliteInt.h +++ b/src/sqliteInt.h @@ -11,7 +11,7 @@ ************************************************************************* ** Internal interface definitions for SQLite. ** -** @(#) $Id: sqliteInt.h,v 1.115 2002/05/24 20:31:37 drh Exp $ +** @(#) $Id: sqliteInt.h,v 1.116 2002/05/25 00:18:21 drh Exp $ */ #include "sqlite.h" #include "hash.h" @@ -461,9 +461,8 @@ struct SrcList { */ #define JT_INNER 0x0001 /* Any kind of inner or cross join */ #define JT_NATURAL 0x0002 /* True for a "natural" join */ -#define JT_LEFT 0x0014 /* Left outer join */ -#define JT_RIGHT 0x0018 /* Right outer join */ -#define JT_FULL 0x001a /* Combination of left and right outer join */ +#define JT_LEFT 0x0004 /* Left outer join */ +#define JT_RIGHT 0x0008 /* Right outer join */ #define JT_OUTER 0x0010 /* The "OUTER" keyword is present */ #define JT_ERROR 0x0020 /* unknown or unsupported join type */ diff --git a/test/join.test b/test/join.test index 6aa70ea804..c7fb82b11a 100644 --- a/test/join.test +++ b/test/join.test @@ -12,7 +12,7 @@ # # This file implements tests for joins, including outer joins. # -# $Id: join.test,v 1.1 2002/05/24 20:31:38 drh Exp $ +# $Id: join.test,v 1.2 2002/05/25 00:18:21 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -41,6 +41,11 @@ do_test join-1.3 { SELECT * FROM t1 NATURAL JOIN t2; } } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5} +do_test join-1.3.1 { + execsql2 { + SELECT * FROM t2 NATURAL JOIN t1; + } +} {t2.b 2 t2.c 3 t2.d 4 t1.a 1 t2.b 3 t2.c 4 t2.d 5 t1.a 2} do_test join-1.4 { execsql2 { SELECT * FROM t1 INNER JOIN t2 USING(b,c); @@ -62,10 +67,144 @@ do_test join-1.7 { } } {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t1.a 2 t1.b 3 t1.c 4 t2.d 5} +do_test join-1.8 { + execsql { + SELECT * FROM t1 NATURAL CROSS JOIN t2; + } +} {1 2 3 4 2 3 4 5} +do_test join-1.9 { + execsql { + SELECT * FROM t1 CROSS JOIN t2 USING(b,c); + } +} {1 2 3 4 2 3 4 5} +do_test join-1.10 { + execsql { + SELECT * FROM t1 NATURAL INNER JOIN t2; + } +} {1 2 3 4 2 3 4 5} +do_test join-1.11 { + execsql { + SELECT * FROM t1 INNER JOIN t2 USING(b,c); + } +} {1 2 3 4 2 3 4 5} +do_test join-1.12 { + execsql { + SELECT * FROM t1 natural inner join t2; + } +} {1 2 3 4 2 3 4 5} +do_test join-1.13 { + execsql2 { + SELECT * FROM t1 NATURAL JOIN + (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as t3 + } +} {t1.a 1 t1.b 2 t1.c 3 t3.d 4 t3.e 5} +do_test join-1.14 { + execsql2 { + SELECT * FROM (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as 'tx' + NATURAL JOIN t1 + } +} {tx.c 3 tx.d 4 tx.e 5 t1.a 1 t1.b 2} + +do_test join-1.15 { + execsql { + CREATE TABLE t3(c,d,e); + INSERT INTO t3 VALUES(2,3,4); + INSERT INTO t3 VALUES(3,4,5); + INSERT INTO t3 VALUES(4,5,6); + SELECT * FROM t3; + } +} {2 3 4 3 4 5 4 5 6} +do_test join-1.16 { + execsql { + SELECT * FROM t1 natural join t2 natural join t3; + } +} {1 2 3 4 5 2 3 4 5 6} +do_test join-1.17 { + execsql2 { + SELECT * FROM t1 natural join t2 natural join t3; + } +} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t3.e 5 t1.a 2 t1.b 3 t1.c 4 t2.d 5 t3.e 6} +do_test join-1.18 { + execsql { + CREATE TABLE t4(d,e,f); + INSERT INTO t4 VALUES(2,3,4); + INSERT INTO t4 VALUES(3,4,5); + INSERT INTO t4 VALUES(4,5,6); + SELECT * FROM t4; + } +} {2 3 4 3 4 5 4 5 6} +do_test join-1.19 { + execsql { + SELECT * FROM t1 natural join t2 natural join t4; + } +} {1 2 3 4 5 6} +do_test join-1.19 { + execsql2 { + SELECT * FROM t1 natural join t2 natural join t4; + } +} {t1.a 1 t1.b 2 t1.c 3 t2.d 4 t4.e 5 t4.f 6} +do_test join-1.20 { + execsql { + SELECT * FROM t1 natural join t2 natural join t3 WHERE t1.a=1 + } +} {1 2 3 4 5} + do_test join-2.1 { execsql { SELECT * FROM t1 NATURAL LEFT JOIN t2; } } {1 2 3 4 2 3 4 5 3 4 5 {}} +do_test join-2.2 { + execsql { + SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1; + } +} {1 2 3 {} 2 3 4 1 3 4 5 2} +do_test join-2.3 { + catchsql { + SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2; + } +} {1 {RIGHT and FULL OUTER JOINs are not currently supported}} + +do_test join-3.1 { + catchsql { + SELECT * FROM t1 NATURAL JOIN t2 ON t1.a=t2.b; + } +} {1 {a NATURAL join may not have an ON or USING clause}} +do_test join-3.2 { + catchsql { + SELECT * FROM t1 NATURAL JOIN t2 USING(b); + } +} {1 {a NATURAL join may not have an ON or USING clause}} +do_test join-3.3 { + catchsql { + SELECT * FROM t1 JOIN t2 ON t1.a=t2.b USING(b); + } +} {1 {cannot have both ON and USING clauses in the same join}} +do_test join-3.4 { + catchsql { + SELECT * FROM t1 JOIN t2 USING(a); + } +} {1 {cannot join using column a - column not present in both tables}} +do_test join-3.5 { + catchsql { + SELECT * FROM t1 USING(a); + } +} {0 {1 2 3 2 3 4 3 4 5}} +do_test join-3.6 { + catchsql { + SELECT * FROM t1 JOIN t2 ON t3.a=t2.b; + } +} {1 {no such column: t3.a}} +do_test join-3.7 { + catchsql { + SELECT * FROM t1 INNER OUTER JOIN t2; + } +} {1 {unknown or unsupported join type: INNER OUTER}} +do_test join-3.7 { + catchsql { + SELECT * FROM t1 BOGUS JOIN t2; + } +} {1 {unknown or unsupported join type: BOGUS}} + finish_test