]> git.ipfire.org Git - thirdparty/sqlite.git/commitdiff
Fix a problem with virtual tables and joins. (CVS 3278)
authordanielk1977 <danielk1977@noemail.net>
Wed, 21 Jun 2006 07:02:33 +0000 (07:02 +0000)
committerdanielk1977 <danielk1977@noemail.net>
Wed, 21 Jun 2006 07:02:33 +0000 (07:02 +0000)
FossilOrigin-Name: 643e63e5883eec109a91a44dae62b58650646575

manifest
manifest.uuid
src/select.c
src/test8.c
test/vtab1.test
test/vtab6.test [new file with mode: 0644]

index f4024971769c938a19d7a4a25fd1ec6374cfbfab..7dbc0a6fc36a49d8291180b83a0307ef02d5024e 100644 (file)
--- a/manifest
+++ b/manifest
@@ -1,5 +1,5 @@
-C Fix\ssome\sproblems\swith\svirtual\stables\sand\sjoins\sin\swhere.c.\s(CVS\s3277)
-D 2006-06-20T13:07:27
+C Fix\sa\sproblem\swith\svirtual\stables\sand\sjoins.\s(CVS\s3278)
+D 2006-06-21T07:02:33
 F Makefile.in f839b470345d3cb4b0644068474623fe2464b5d3
 F Makefile.linux-gcc 2d8574d1ba75f129aba2019f0b959db380a90935
 F README 9c4e2d6706bdcc3efdd773ce752a8cdab4f90028
@@ -69,7 +69,7 @@ F src/pragma.c 27d5e395c5d950931c7ac4fe610e7c2993e2fa55
 F src/prepare.c 6dc945dab34cf97364c661d2b7a12be65d338267
 F src/printf.c 7029e5f7344a478394a02c52837ff296ee1ab240
 F src/random.c d40f8d356cecbd351ccfab6eaedd7ec1b54f5261
-F src/select.c 6dd3fdfeaebe2565944241e7e7a0d3e1d8469c12
+F src/select.c 380fa06c99ae01050c0054c4b1db91e9f1d8322d
 F src/server.c 087b92a39d883e3fa113cae259d64e4c7438bc96
 F src/shell.c ad73192b30a338a58fe81183d4a5d5a1d4e51d36
 F src/sqlite.h.in 7855b46387f3f6ac1925301f450df9cbd7a1269b
@@ -84,7 +84,7 @@ F src/test4.c 8b784cd82de158a2317cb4ac4bc86f91ad315e25
 F src/test5.c 7162f8526affb771c4ed256826eee7bb9eca265f
 F src/test6.c 60a02961ceb7b3edc25f5dc5c1ac2556622a76de
 F src/test7.c 03fa8d787f6aebc6d1f72504d52f33013ad2c8e3
-F src/test8.c ec03e990c8c64d6d71dae459bf1dd72e75996362
+F src/test8.c 03563ba045b2c46dc98284144d3e0052d9ea08ba
 F src/test_async.c e3deaedd4d86a56391b81808fde9e44fbd92f1d3
 F src/test_loadext.c 22065d601a18878e5542191001f0eaa5d77c0ed8
 F src/test_md5.c 6c42bc0a3c0b54be34623ff77a0eec32b2fa96e3
@@ -291,11 +291,12 @@ F test/vacuum.test 37f998b841cb335397c26d9bbc3457182af2565f
 F test/vacuum2.test 5aea8c88a65cb29f7d175296e7c819c6158d838c
 F test/varint.test ab7b110089a08b9926ed7390e7e97bdefeb74102
 F test/view.test 16e2774fe35e47a07ac4471b7f0bcc948b1aa6d5
-F test/vtab1.test 1a5233154cbdf3e5324feba9c74dda0eee0ac135
+F test/vtab1.test ab6cf2670f769efc0ac8a7d8c272f910da296dbc
 F test/vtab2.test e57f9865368df26ef5eb8bc630962d82086f174b
 F test/vtab3.test f38d6d7d19f08bffdadce4d5b8cba078f8118587
 F test/vtab4.test 4b4293341443839ef6dc02f8d9e614702a6c67ff
 F test/vtab5.test a275f233722cbc89141710e5df62421ae26d456b
+F test/vtab6.test 0b4fe07e421b2b9a334bec8781e75cbd8e230bd3
 F test/where.test ee7c9a6659b07e1ee61177f6e7ff71565ee2c9df
 F test/where2.test a16476a5913e75cf65b38f2daa6157a6b7791394
 F test/where3.test 3b5ad2c58069e12be2bd86bc5e211a82810521aa
@@ -371,7 +372,7 @@ F www/tclsqlite.tcl bb0d1357328a42b1993d78573e587c6dcbc964b9
 F www/vdbe.tcl 87a31ace769f20d3627a64fa1fade7fed47b90d0
 F www/version3.tcl 890248cf7b70e60c383b0e84d77d5132b3ead42b
 F www/whentouse.tcl 97e2b5cd296f7d8057e11f44427dea8a4c2db513
-P c6ea353bd9f5fe6c9cc3349d2034ada283f9c80e
-R 29f7d43d1ba21e43482cd4da4cb99600
+P 3e19a7d8eabcd2fa71ced3f76c5f9bc1f3900b81
+R dd2e65c82fc19b7cf06d61c3f62a9682
 U danielk1977
-Z 1d9af2117d83aafa007dd01f8ea28b29
+Z 403c1a151f48024ee7e51bb28ac7757a
index fd2061af5ecc19fb09c1ac9e3dd52cbed1c85b1c..8cab2de92aa5b16a63f8238c8be9d3f912bcbb3f 100644 (file)
@@ -1 +1 @@
-3e19a7d8eabcd2fa71ced3f76c5f9bc1f3900b81
\ No newline at end of file
+643e63e5883eec109a91a44dae62b58650646575
\ No newline at end of file
index be9c6c23c71c30020362db1f4147b954d5d126e0..c909fc00f55d3f7469507e1c3d66438aa7de943c 100644 (file)
@@ -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.317 2006/06/20 13:07:27 danielk1977 Exp $
+** $Id: select.c,v 1.318 2006/06/21 07:02:33 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 
@@ -2008,6 +2008,7 @@ static void substExpr(Expr *pExpr, int iTable, ExprList *pEList){
       assert( pExpr->pList==0 );
       pExpr->pList = sqlite3ExprListDup(pNew->pList);
       pExpr->iTable = pNew->iTable;
+      pExpr->pTab = pNew->pTab;
       pExpr->iColumn = pNew->iColumn;
       pExpr->iAgg = pNew->iAgg;
       sqlite3TokenCopy(&pExpr->token, &pNew->token);
index 9bf61b0f692610f91fe7385352a4c435bdd890ad..70f1ebb75426c698e5a55db75bbd95461b587a22 100644 (file)
@@ -13,7 +13,7 @@
 ** is not included in the SQLite library.  It is used for automated
 ** testing of the SQLite library.
 **
-** $Id: test8.c,v 1.27 2006/06/20 11:01:08 danielk1977 Exp $
+** $Id: test8.c,v 1.28 2006/06/21 07:02:34 danielk1977 Exp $
 */
 #include "sqliteInt.h"
 #include "tcl.h"
@@ -325,9 +325,12 @@ static int echoColumn(sqlite3_vtab_cursor *cur, sqlite3_context *ctx, int i){
   if( ((echo_cursor *)cur)->errcode ){
     return ((echo_cursor *)cur)->errcode;
   }
-
-  assert( sqlite3_data_count(pStmt)>iCol );
-  sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
+  if( !pStmt ){
+    sqlite3_result_null(ctx);
+  }else{
+    assert( sqlite3_data_count(pStmt)>iCol );
+    sqlite3_result_value(ctx, sqlite3_column_value(pStmt, iCol));
+  }
   return SQLITE_OK;
 }
 
@@ -373,6 +376,7 @@ static int echoFilter(
   sqlite3_finalize(pCur->pStmt);
   pCur->pStmt = 0;
   rc = sqlite3_prepare(db, idxStr, -1, &pCur->pStmt, 0);
+  assert( pCur->pStmt || rc!=SQLITE_OK );
   for(i=0; rc==SQLITE_OK && i<argc; i++){
     switch( sqlite3_value_type(argv[i]) ){
       case SQLITE_INTEGER: {
index c65952640932381c9f5a2f3eb050b5afd92a7e08..ebc7334588a75d132e9a9c5c3118f0b79649af54 100644 (file)
@@ -11,7 +11,7 @@
 # This file implements regression tests for SQLite library.  The
 # focus of this file is creating and dropping virtual tables.
 #
-# $Id: vtab1.test,v 1.24 2006/06/20 13:07:28 danielk1977 Exp $
+# $Id: vtab1.test,v 1.25 2006/06/21 07:02:34 danielk1977 Exp $
 
 set testdir [file dirname $argv0]
 source $testdir/tester.tcl
@@ -280,6 +280,11 @@ do_test vtab1-3.7 {
     SELECT rowid, * FROM t1;
   }
 } {1 1 2 3 2 4 5 6}
+do_test vtab1-3.8 {
+  execsql {
+    SELECT a AS d, b AS e, c AS f FROM t1;
+  }
+} {1 2 3 4 5 6}
 
 # Execute some SELECT statements with WHERE clauses on the t1 table.
 # Then check the echo_module variable (written to by the module methods
diff --git a/test/vtab6.test b/test/vtab6.test
new file mode 100644 (file)
index 0000000..22c8c57
--- /dev/null
@@ -0,0 +1,452 @@
+# 2002 May 24
+#
+# The author disclaims copyright to this source code.  In place of
+# a legal notice, here is a blessing:
+#
+#    May you do good and not evil.
+#    May you find forgiveness for yourself and forgive others.
+#    May you share freely, never taking more than you give.
+#
+#***********************************************************************
+# This file implements regression tests for SQLite library.
+#
+# This file implements tests for joins, including outer joins involving
+# virtual tables. The test cases in this file are copied from the file
+# join.test, and some of the comments still reflect that.
+#
+# $Id: vtab6.test,v 1.1 2006/06/21 07:02:34 danielk1977 Exp $
+
+set testdir [file dirname $argv0]
+source $testdir/tester.tcl
+
+register_echo_module [sqlite3_connection_pointer db]
+
+execsql {
+  CREATE TABLE real_t1(a,b,c);
+  CREATE TABLE real_t2(b,c,d);
+  CREATE TABLE real_t3(c,d,e);
+  CREATE TABLE real_t4(d,e,f);
+  CREATE TABLE real_t5(a INTEGER PRIMARY KEY);
+  CREATE TABLE real_t6(a INTEGER);
+  CREATE TABLE real_t7 (x, y);
+  CREATE TABLE real_t8 (a integer primary key, b);
+  CREATE TABLE real_t9(a INTEGER PRIMARY KEY, b);
+  CREATE TABLE real_t10(x INTEGER PRIMARY KEY, y);
+  CREATE TABLE real_t11(p INTEGER PRIMARY KEY, q);
+  CREATE TABLE real_t12(a,b);
+  CREATE TABLE real_t13(b,c);
+  CREATE TABLE real_t21(a,b,c);
+  CREATE TABLE real_t22(p,q);
+}
+foreach t [list t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t13 t21 t22] {
+  execsql "CREATE VIRTUAL TABLE $t USING echo(real_$t)"
+}
+
+do_test vtab6-1.1 {
+  execsql {
+    INSERT INTO t1 VALUES(1,2,3);
+    INSERT INTO t1 VALUES(2,3,4);
+    INSERT INTO t1 VALUES(3,4,5);
+    SELECT * FROM t1;
+  }  
+} {1 2 3 2 3 4 3 4 5}
+do_test vtab6-1.2 {
+  execsql {
+    INSERT INTO t2 VALUES(1,2,3);
+    INSERT INTO t2 VALUES(2,3,4);
+    INSERT INTO t2 VALUES(3,4,5);
+    SELECT * FROM t2;
+  }  
+} {1 2 3 2 3 4 3 4 5}
+
+do_test vtab6-1.3 {
+  execsql2 {
+    SELECT * FROM t1 NATURAL JOIN t2;
+  }
+} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
+do_test vtab6-1.3.1 {
+  execsql2 {
+    SELECT * FROM t2 NATURAL JOIN t1;
+  }
+} {b 2 c 3 d 4 a 1 b 3 c 4 d 5 a 2}
+do_test vtab6-1.3.2 {
+  execsql2 {
+    SELECT * FROM t2 AS x NATURAL JOIN t1;
+  }
+} {b 2 c 3 d 4 a 1 b 3 c 4 d 5 a 2}
+do_test vtab6-1.3.3 {
+  execsql2 {
+    SELECT * FROM t2 NATURAL JOIN t1 AS y;
+  }
+} {b 2 c 3 d 4 a 1 b 3 c 4 d 5 a 2}
+do_test vtab6-1.3.4 {
+  execsql {
+    SELECT b FROM t1 NATURAL JOIN t2;
+  }
+} {2 3}
+do_test vtab6-1.4.1 {
+  execsql2 {
+    SELECT * FROM t1 INNER JOIN t2 USING(b,c);
+  }
+} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
+do_test vtab6-1.4.2 {
+  execsql2 {
+    SELECT * FROM t1 AS x INNER JOIN t2 USING(b,c);
+  }
+} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
+do_test vtab6-1.4.3 {
+  execsql2 {
+    SELECT * FROM t1 INNER JOIN t2 AS y USING(b,c);
+  }
+} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
+do_test vtab6-1.4.4 {
+  execsql2 {
+    SELECT * FROM t1 AS x INNER JOIN t2 AS y USING(b,c);
+  }
+} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
+do_test vtab6-1.4.5 {
+  execsql {
+    SELECT b FROM t1 JOIN t2 USING(b);
+  }
+} {2 3}
+do_test vtab6-1.5 {
+  execsql2 {
+    SELECT * FROM t1 INNER JOIN t2 USING(b);
+  }
+} {a 1 b 2 c 3 c 3 d 4 a 2 b 3 c 4 c 4 d 5}
+do_test vtab6-1.6 {
+  execsql2 {
+    SELECT * FROM t1 INNER JOIN t2 USING(c);
+  }
+} {a 1 b 2 c 3 b 2 d 4 a 2 b 3 c 4 b 3 d 5}
+do_test vtab6-1.7 {
+  execsql2 {
+    SELECT * FROM t1 INNER JOIN t2 USING(c,b);
+  }
+} {a 1 b 2 c 3 d 4 a 2 b 3 c 4 d 5}
+
+do_test vtab6-1.8 {
+  execsql {
+    SELECT * FROM t1 NATURAL CROSS JOIN t2;
+  }
+} {1 2 3 4 2 3 4 5}
+do_test vtab6-1.9 {
+  execsql {
+    SELECT * FROM t1 CROSS JOIN t2 USING(b,c);
+  }
+} {1 2 3 4 2 3 4 5}
+do_test vtab6-1.10 {
+  execsql {
+    SELECT * FROM t1 NATURAL INNER JOIN t2;
+  }
+} {1 2 3 4 2 3 4 5}
+do_test vtab6-1.11 {
+  execsql {
+    SELECT * FROM t1 INNER JOIN t2 USING(b,c);
+  }
+} {1 2 3 4 2 3 4 5}
+do_test vtab6-1.12 {
+  execsql {
+    SELECT * FROM t1 natural inner join t2;
+  }
+} {1 2 3 4 2 3 4 5}
+
+ifcapable subquery {
+breakpoint
+  do_test vtab6-1.13 {
+    execsql2 {
+      SELECT * FROM t1 NATURAL JOIN 
+        (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as t3
+    }
+  } {a 1 b 2 c 3 d 4 e 5}
+  do_test vtab6-1.14 {
+    execsql2 {
+      SELECT * FROM (SELECT b as 'c', c as 'd', d as 'e' FROM t2) as 'tx'
+          NATURAL JOIN t1
+    }
+  } {c 3 d 4 e 5 a 1 b 2}
+}
+
+do_test vtab6-1.15 {
+  execsql {
+    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 vtab6-1.16 {
+  execsql {
+    SELECT * FROM t1 natural join t2 natural join t3;
+  }
+} {1 2 3 4 5 2 3 4 5 6}
+do_test vtab6-1.17 {
+  execsql2 {
+    SELECT * FROM t1 natural join t2 natural join t3;
+  }
+} {a 1 b 2 c 3 d 4 e 5 a 2 b 3 c 4 d 5 e 6}
+do_test vtab6-1.18 {
+  execsql {
+    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 vtab6-1.19.1 {
+  execsql {
+    SELECT * FROM t1 natural join t2 natural join t4;
+  }
+} {1 2 3 4 5 6}
+do_test vtab6-1.19.2 {
+  execsql2 {
+    SELECT * FROM t1 natural join t2 natural join t4;
+  }
+} {a 1 b 2 c 3 d 4 e 5 f 6}
+do_test vtab6-1.20 {
+  execsql {
+    SELECT * FROM t1 natural join t2 natural join t3 WHERE t1.a=1
+  }
+} {1 2 3 4 5}
+
+do_test vtab6-2.1 {
+  execsql {
+    SELECT * FROM t1 NATURAL LEFT JOIN t2;
+  }
+} {1 2 3 4 2 3 4 5 3 4 5 {}}
+do_test vtab6-2.2 {
+  execsql {
+    SELECT * FROM t2 NATURAL LEFT OUTER JOIN t1;
+  }
+} {1 2 3 {} 2 3 4 1 3 4 5 2}
+do_test vtab6-2.3 {
+  catchsql {
+    SELECT * FROM t1 NATURAL RIGHT OUTER JOIN t2;
+  }
+} {1 {RIGHT and FULL OUTER JOINs are not currently supported}}
+do_test vtab6-2.4 {
+  execsql {
+    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d
+  }
+} {1 2 3 {} {} {} 2 3 4 {} {} {} 3 4 5 1 2 3}
+do_test vtab6-2.5 {
+  execsql {
+    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t1.a>1
+  }
+} {2 3 4 {} {} {} 3 4 5 1 2 3}
+do_test vtab6-2.6 {
+  execsql {
+    SELECT * FROM t1 LEFT JOIN t2 ON t1.a=t2.d WHERE t2.b IS NULL OR t2.b>1
+  }
+} {1 2 3 {} {} {} 2 3 4 {} {} {}}
+
+do_test vtab6-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 vtab6-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 vtab6-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 vtab6-3.4 {
+  catchsql {
+    SELECT * FROM t1 JOIN t2 USING(a);
+  }
+} {1 {cannot join using column a - column not present in both tables}}
+do_test vtab6-3.5 {
+  catchsql {
+    SELECT * FROM t1 USING(a);
+  }
+} {0 {1 2 3 2 3 4 3 4 5}}
+do_test vtab6-3.6 {
+  catchsql {
+    SELECT * FROM t1 JOIN t2 ON t3.a=t2.b;
+  }
+} {1 {no such column: t3.a}}
+do_test vtab6-3.7 {
+  catchsql {
+    SELECT * FROM t1 INNER OUTER JOIN t2;
+  }
+} {1 {unknown or unsupported join type: INNER OUTER}}
+do_test vtab6-3.7 {
+  catchsql {
+    SELECT * FROM t1 LEFT BOGUS JOIN t2;
+  }
+} {1 {unknown or unsupported join type: LEFT BOGUS}}
+
+do_test vtab6-4.1 {
+  execsql {
+    BEGIN;
+    INSERT INTO t6 VALUES(NULL);
+    INSERT INTO t6 VALUES(NULL);
+    INSERT INTO t6 SELECT * FROM t6;
+    INSERT INTO t6 SELECT * FROM t6;
+    INSERT INTO t6 SELECT * FROM t6;
+    INSERT INTO t6 SELECT * FROM t6;
+    INSERT INTO t6 SELECT * FROM t6;
+    INSERT INTO t6 SELECT * FROM t6;
+    COMMIT;
+  }
+  execsql {
+    SELECT * FROM t6 NATURAL JOIN t5;
+  }
+} {}
+do_test vtab6-4.2 {
+  execsql {
+    SELECT * FROM t6, t5 WHERE t6.a<t5.a;
+  }
+} {}
+do_test vtab6-4.3 {
+  execsql {
+    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
+  }
+} {}
+do_test vtab6-4.4 {
+  execsql {
+    UPDATE t6 SET a='xyz';
+    SELECT * FROM t6 NATURAL JOIN t5;
+  }
+} {}
+do_test vtab6-4.6 {
+  execsql {
+    SELECT * FROM t6, t5 WHERE t6.a<t5.a;
+  }
+} {}
+do_test vtab6-4.7 {
+  execsql {
+    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
+  }
+} {}
+do_test vtab6-4.8 {
+  execsql {
+    UPDATE t6 SET a=1;
+    SELECT * FROM t6 NATURAL JOIN t5;
+  }
+} {}
+do_test vtab6-4.9 {
+  execsql {
+    SELECT * FROM t6, t5 WHERE t6.a<t5.a;
+  }
+} {}
+do_test vtab6-4.10 {
+  execsql {
+    SELECT * FROM t6, t5 WHERE t6.a>t5.a;
+  }
+} {}
+
+# A test for ticket #247.
+#
+do_test vtab6-7.1 {
+  execsql {
+    INSERT INTO t7 VALUES ("pa1", 1);
+    INSERT INTO t7 VALUES ("pa2", NULL);
+    INSERT INTO t7 VALUES ("pa3", NULL);
+    INSERT INTO t7 VALUES ("pa4", 2);
+    INSERT INTO t7 VALUES ("pa30", 131);
+    INSERT INTO t7 VALUES ("pa31", 130);
+    INSERT INTO t7 VALUES ("pa28", NULL);
+
+    INSERT INTO t8 VALUES (1, "pa1");
+    INSERT INTO t8 VALUES (2, "pa4");
+    INSERT INTO t8 VALUES (3, NULL);
+    INSERT INTO t8 VALUES (4, NULL);
+    INSERT INTO t8 VALUES (130, "pa31");
+    INSERT INTO t8 VALUES (131, "pa30");
+
+    SELECT coalesce(t8.a,999) from t7 LEFT JOIN t8 on y=a;
+  }
+} {1 999 999 2 131 130 999}
+
+# Make sure a left join where the right table is really a view that
+# is itself a join works right.  Ticket #306.
+#
+ifcapable view {
+do_test vtab6-8.1 {
+  execsql {
+    BEGIN;
+    INSERT INTO t9 VALUES(1,11);
+    INSERT INTO t9 VALUES(2,22);
+    INSERT INTO t10 VALUES(1,2);
+    INSERT INTO t10 VALUES(3,3);    
+    INSERT INTO t11 VALUES(2,111);
+    INSERT INTO t11 VALUES(3,333);    
+    CREATE VIEW v10_11 AS SELECT x, q FROM t10, t11 WHERE t10.y=t11.p;
+    COMMIT;
+    SELECT * FROM t9 LEFT JOIN v10_11 ON( a=x );
+  }
+} {1 11 1 111 2 22 {} {}}
+ifcapable subquery {
+  do_test vtab6-8.2 {
+    execsql {
+      SELECT * FROM t9 LEFT JOIN (SELECT x, q FROM t10, t11 WHERE t10.y=t11.p)
+           ON( a=x);
+    }
+  } {1 11 1 111 2 22 {} {}}
+}
+do_test vtab6-8.3 {
+  execsql {
+    SELECT * FROM v10_11 LEFT JOIN t9 ON( a=x );
+  }
+} {1 111 1 11 3 333 {} {}}
+} ;# ifcapable view
+
+# Ticket #350 describes a scenario where LEFT OUTER JOIN does not
+# function correctly if the right table in the join is really
+# subquery.
+#
+# To test the problem, we generate the same LEFT OUTER JOIN in two
+# separate selects but with on using a subquery and the other calling
+# the table directly.  Then connect the two SELECTs using an EXCEPT.
+# Both queries should generate the same results so the answer should
+# be an empty set.
+#
+ifcapable compound {
+do_test vtab6-9.1 {
+  execsql {
+    BEGIN;
+    INSERT INTO t12 VALUES(1,11);
+    INSERT INTO t12 VALUES(2,22);
+    INSERT INTO t13 VALUES(22,222);
+    COMMIT;
+  }
+} {}
+
+ifcapable subquery {
+  do_test vtab6-9.1.1 {
+    execsql {
+      SELECT * FROM t12 NATURAL LEFT JOIN t13
+      EXCEPT
+      SELECT * FROM t12 NATURAL LEFT JOIN (SELECT * FROM t13 WHERE b>0);
+    }
+  } {}
+}
+ifcapable view {
+  do_test vtab6-9.2 {
+    execsql {
+      CREATE VIEW v13 AS SELECT * FROM t13 WHERE b>0;
+      SELECT * FROM t12 NATURAL LEFT JOIN t13
+        EXCEPT
+        SELECT * FROM t12 NATURAL LEFT JOIN v13;
+    }
+  } {}
+} ;# ifcapable view
+} ;# ifcapable compound
+
+ifcapable subquery {
+do_test vtab6-10.1 {
+  execsql {
+    CREATE INDEX i22 ON real_t22(q);
+    SELECT a FROM t21 LEFT JOIN t22 ON b=p WHERE q=
+       (SELECT max(m.q) FROM t22 m JOIN t21 n ON n.b=m.p WHERE n.c=1);
+  }  
+} {}
+} ;# ifcapable subquery
+
+finish_test