# 2022 May 17
#
# 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.
#

set testdir [file dirname $argv0]
source $testdir/tester.tcl
set testprefix joinH

do_execsql_test 1.0 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT);
  INSERT INTO t2(b) VALUES(NULL);
}

db nullvalue NULL

do_execsql_test 1.1 {
  SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
} {NULL}
do_execsql_test 1.2 {
  SELECT a FROM t1 FULL JOIN t2 ON true;
} {NULL}
do_execsql_test 1.3 {
  SELECT a FROM t1 FULL JOIN t2 ON true WHERE (b ISNULL);
} {NULL}
do_execsql_test 1.4 {
  SELECT DISTINCT a FROM t1 FULL JOIN t2 ON true;
} {NULL}

#-----------------------------------------------------------

reset_db
do_execsql_test 2.0 {
  CREATE TABLE r3(x);
  CREATE TABLE r4(y INTEGER PRIMARY KEY);
  INSERT INTO r4 VALUES(55);
}

do_execsql_test 2.1 {
  SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x);
} {value!}

do_execsql_test 2.2 {
  SELECT 'value!' FROM r3 FULL JOIN r4 ON (y=x) WHERE +y=55;
} {value!}

#-----------------------------------------------------------
reset_db
do_execsql_test 3.1 {
  CREATE TABLE t0 (c0);
  CREATE TABLE t1 (c0);
  CREATE TABLE t2 (c0 , c1 , c2 , UNIQUE (c0), UNIQUE (c2 DESC));
  INSERT INTO t2 VALUES ('x', 'y', 'z');
  ANALYZE;
  CREATE VIEW v0(c0) AS SELECT FALSE;
}

do_catchsql_test 3.2 {
  SELECT * FROM t0 LEFT OUTER JOIN t1 ON v0.c0 INNER JOIN v0 INNER JOIN t2 ON (t2.c2 NOT NULL); 
} {1 {ON clause references tables to its right}}

#-------------------------------------------------------------

reset_db
do_execsql_test 4.1 {
  CREATE TABLE t1(a,b,c,d,e,f,g,h,PRIMARY KEY(a,b,c)) WITHOUT ROWID;
  CREATE TABLE t2(i, j);
  INSERT INTO t2 VALUES(10, 20);
}

do_execsql_test 4.2 {
  SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
} {1}

do_execsql_test 4.3 {
  CREATE INDEX i1 ON t1( (d IS NULL), d );
}

do_execsql_test 4.4 {
  SELECT (d IS NULL) FROM t1 RIGHT JOIN t2 ON (j=33);
} {1}

#-------------------------------------------------------------------------
#
reset_db
do_execsql_test 5.0 {
  CREATE TABLE t0(w);
  CREATE TABLE t1(x);
  CREATE TABLE t2(y);
  CREATE TABLE t3(z);
  INSERT INTO t3 VALUES('t3val');
}

do_execsql_test 5.1 {
  SELECT * FROM t1 INNER JOIN t2 ON (0) RIGHT OUTER JOIN t3;
} {{} {} t3val}

do_execsql_test 5.2 {
  SELECT * FROM t1 INNER JOIN t2 ON (0) FULL OUTER JOIN t3;
} {{} {} t3val}

do_execsql_test 5.3 {
  SELECT * FROM t3 LEFT JOIN t2 ON (0);
} {t3val {}}

do_execsql_test 5.4 {
  SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0) RIGHT JOIN t3
} {{} {} {} t3val}

do_execsql_test 5.5 {
  SELECT * FROM t0 RIGHT JOIN t1 INNER JOIN t2 ON (0)
} {}


reset_db
db null NULL
do_execsql_test 6.0 {
  CREATE TABLE t1(a INT);
  CREATE TABLE t2(b INT);
  INSERT INTO t1 VALUES(3);
  SELECT CASE WHEN t2.b THEN 0 ELSE 1 END FROM t1 LEFT JOIN t2 ON true;
} {1}
do_execsql_test 6.1 {
  SELECT * FROM t1 LEFT JOIN t2 ON true WHERE CASE WHEN t2.b THEN 0 ELSE 1 END;
} {3 NULL}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 7.0 {
  CREATE TABLE t1(a, b);
  CREATE TABLE t2(c);
  CREATE TABLE t3(d);

  INSERT INTO t1 VALUES ('a', 'a');
  INSERT INTO t2 VALUES ('ddd');
  INSERT INTO t3 VALUES(1234);
}

do_execsql_test 7.1 {
  SELECT t2.rowid FROM t1 JOIN (t2 JOIN t3);
} {1}

do_execsql_test 7.1 {
  UPDATE t1 SET b = t2.rowid FROM t2, t3;
}

do_execsql_test 7.2 { 
  SELECT * FROM t1
} {a 1}

#-------------------------------------------------------------------------
reset_db
do_execsql_test 8.0 {
  CREATE TABLE x1(a INTEGER PRIMARY KEY, b);
  CREATE TABLE x2(c, d);
  CREATE TABLE x3(rowid, _rowid_);

  CREATE TABLE x4(rowid, _rowid_, oid);

  INSERT INTO x1 VALUES(1000, 'thousand');
  INSERT INTO x2 VALUES('c', 'd');
  INSERT INTO x3(oid, rowid, _rowid_) VALUES(43, 'hello', 'world');
  INSERT INTO x4(oid, rowid, _rowid_) VALUES('forty three', 'hello', 'world');
}

do_execsql_test 8.1 {
  SELECT x3.oid FROM x1 JOIN (x2 JOIN x3 ON c='c')
} 43

breakpoint
do_execsql_test 8.2 {
  SELECT x3.rowid FROM x1 JOIN (x2 JOIN x3 ON c='c')
} {hello}

do_execsql_test 8.3 {
  SELECT x4.oid FROM x1 JOIN (x2 JOIN x4 ON c='c')
} {{forty three}}


#---------------------------------------------------------------------
#
reset_db
do_execsql_test 9.0 {
  CREATE TABLE x1(a);
  CREATE TABLE x2(b);
  CREATE TABLE x3(c);

  CREATE TABLE wo1(a PRIMARY KEY, b) WITHOUT ROWID;
  CREATE TABLE wo2(a PRIMARY KEY, rowid) WITHOUT ROWID;
  CREATE TABLE wo3(a PRIMARY KEY, b) WITHOUT ROWID;
}

do_catchsql_test 9.1 {
  SELECT rowid FROM wo1, x1, x2;
} {1 {no such column: rowid}}
do_catchsql_test 9.2 {
  SELECT rowid FROM wo1, (x1, x2);
} {1 {no such column: rowid}}
do_catchsql_test 9.3 {
  SELECT rowid FROM wo1 JOIN (x1 JOIN x2);
} {1 {no such column: rowid}}
do_catchsql_test 9.4 {
  SELECT a FROM wo1, x1, x2;
} {1 {ambiguous column name: a}}


# It is not possible to use "rowid" in a USING clause.
#
do_catchsql_test 9.5 {
  SELECT * FROM x1 JOIN x2 USING (rowid);
} {1 {cannot join using column rowid - column not present in both tables}}
do_catchsql_test 9.6 {
  SELECT * FROM wo2 JOIN x2 USING (rowid);
} {1 {cannot join using column rowid - column not present in both tables}}

# "rowid" columns are not matched by NATURAL JOIN. If they were, then
# the SELECT below would return zero rows.
do_execsql_test 9.7 {
  INSERT INTO x1(rowid, a) VALUES(101, 'A');
  INSERT INTO x2(rowid, b) VALUES(55, 'B');
  SELECT * FROM x1 NATURAL JOIN x2;
} {A B}

do_execsql_test 9.8 {
  INSERT INTO wo1(a, b) VALUES('mya', 'myb');
  INSERT INTO wo2(a, rowid) VALUES('mypk', 'myrowid');
  INSERT INTO wo3(a, b) VALUES('MYA', 'MYB');
  INSERT INTO x3(rowid, c) VALUES(99, 'x3B');
}

do_catchsql_test 9.8 {
  SELECT rowid FROM x1 JOIN (x2 JOIN wo2);
} {0 myrowid}
do_catchsql_test 9.9 {
  SELECT _rowid_ FROM wo1 JOIN (wo3 JOIN x3)
} {0 99}
do_catchsql_test 9.10 {
  SELECT oid FROM wo1 JOIN (wo3 JOIN x3)
} {0 99}
do_catchsql_test 9.11 {
  SELECT oid FROM wo2 JOIN (wo3 JOIN x3)
} {0 99}


finish_test