-- Automatically generated by SQLQueryTestSuite
-- !query
CREATE TEMPORARY VIEW tbl_view AS SELECT * FROM VALUES
  (10, 'name1', named_struct('f1', 1, 's2', named_struct('f2', 101, 'f3', 'a'))),
  (20, 'name2', named_struct('f1', 2, 's2', named_struct('f2', 202, 'f3', 'b'))),
  (30, 'name3', named_struct('f1', 3, 's2', named_struct('f2', 303, 'f3', 'c'))),
  (40, 'name4', named_struct('f1', 4, 's2', named_struct('f2', 404, 'f3', 'd'))),
  (50, 'name5', named_struct('f1', 5, 's2', named_struct('f2', 505, 'f3', 'e'))),
  (60, 'name6', named_struct('f1', 6, 's2', named_struct('f2', 606, 'f3', 'f'))),
  (70, 'name7', named_struct('f1', 7, 's2', named_struct('f2', 707, 'f3', 'g')))
AS tbl_view(id, name, data);
CREATE TABLE x (id INT) USING csv;

DECLARE sql_string STRING;
SET VAR sql_string = 'SELECT * from tbl_view where name = \'name1\'';

-- test commands
EXECUTE IMMEDIATE 'SET spark.sql.ansi.enabled=true';
EXECUTE IMMEDIATE 'CREATE TEMPORARY VIEW IDENTIFIER(:tblName) AS SELECT id, name FROM tbl_view' USING 'tbl_view_tmp' as tblName;
EXECUTE IMMEDIATE 'SELECT * FROM tbl_view_tmp';

EXECUTE IMMEDIATE 'REFRESH TABLE IDENTIFIER(:tblName)' USING 'x' as tblName;

-- test execute immediate without parameters
EXECUTE IMMEDIATE sql_string;
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = \'name1\'';

-- test positional parameters
SET VAR sql_string = 'SELECT * from tbl_view where name = ? or name = ?';
DECLARE a STRING;
SET VAR a = 'name1';
EXECUTE IMMEDIATE sql_string USING 'name1', 'name3';
EXECUTE IMMEDIATE sql_string USING a, 'name2';
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = ? or name = ?' USING 'name1', 'name3';
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = ? or name = ?' USING a, 'name2';
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = ? or name = ?' USING (a, 'name2');
-- test positional command
EXECUTE IMMEDIATE 'INSERT INTO x VALUES(?)' USING 1;
SELECT * from x;

-- test named parameters
SET VAR sql_string = 'SELECT * from tbl_view where name = :first or id = :second';
DECLARE b INT;
SET VAR b = 40;
EXECUTE IMMEDIATE sql_string USING 40 as second, 'name7' as first;
EXECUTE IMMEDIATE sql_string USING b as second, 'name7' as first;
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = :first or id = :second' USING 40 as second, 'name7' as first;
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = :first or id = :second' USING 'name7' as first, b as second;
-- named parameter used multiple times
EXECUTE IMMEDIATE 'SELECT tbl_view.*, :first as p FROM tbl_view WHERE name = :first' USING 'name7' as first;

-- test named command and setup for next test
EXECUTE IMMEDIATE 'SET VAR sql_string = ?' USING 'SELECT id from tbl_view where name = :first';
SELECT sql_string;

-- test into
DECLARE res_id INT;
EXECUTE IMMEDIATE sql_string INTO res_id USING 'name7' as first;
SELECT res_id;
EXECUTE IMMEDIATE sql_string INTO res_id USING a as first;
SELECT res_id;

-- test into without using
SET VAR sql_string = 'SELECT * from tbl_view where name = :first or id = :second';
EXECUTE IMMEDIATE 'SELECT 42' INTO res_id;
SELECT res_id;

-- multiple INTOs
EXECUTE IMMEDIATE 'SELECT id, name FROM tbl_view WHERE id = ?' INTO b, a USING 10;
SELECT b, a;

-- use AS for using positional params
EXECUTE IMMEDIATE 'SELECT * FROM tbl_view where id = ? AND name = ?' USING b as first, a;

-- empty query
EXECUTE IMMEDIATE 'SELECT 42 WHERE 2 = 1' INTO res_id;
SELECT res_id;

-- implicit casting
EXECUTE IMMEDIATE 'SELECT \'1707\'' INTO res_id;
SELECT res_id;

-- test errors
-- string to int error
EXECUTE IMMEDIATE 'SELECT \'invalid_cast_error_expected\'' INTO res_id;

-- require query when using INTO
EXECUTE IMMEDIATE 'INSERT INTO x VALUES (?)' INTO res_id USING 1;

-- use column in using - should fail as we expect variable here
EXECUTE IMMEDIATE 'SELECT * FROM tbl_view WHERE ? = id' USING id;

-- either positional or named parameters must be used
EXECUTE IMMEDIATE 'SELECT * FROM tbl_view where ? = id and :first = name' USING 1, 'name2' as first;

-- all paramerers must be named
EXECUTE IMMEDIATE 'SELECT * FROM tbl_view where :first = name' USING 1, 'name2' as first;

-- internal syntax error
EXECUTE IMMEDIATE 'SELCT Fa';

-- internal syntax error - test that both parseQuery and parsePlan fail
EXECUTE IMMEDIATE 'SELCT Fa' INTO res_id;

-- Parameter passed must be STRING
EXECUTE IMMEDIATE b;

-- test expressions should fail with parser error
SET VAR sql_string = 'SELECT * from tbl_view where name = :first or id = :second';
SET VAR a = 'na';

-- expressions not supported - feature not supported
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = :first' USING CONCAT(a , "me1") as first;
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = :first' USING (SELECT 42) as first, 'name2' as second;

-- INTO variables not matching scalar types
EXECUTE IMMEDIATE 'SELECT id, name FROM tbl_view WHERE id = ?' INTO a, b USING 10;

-- INTO does not support braces - parser error
EXECUTE IMMEDIATE 'SELECT id, name FROM tbl_view WHERE id = ?' INTO (a, b) USING 10;

-- Error too many rows
EXECUTE IMMEDIATE 'SELECT id FROM tbl_view' INTO res_id;

-- Error mismatch cardinality
EXECUTE IMMEDIATE 'SELECT id, data.f1 FROM tbl_view' INTO res_id;
EXECUTE IMMEDIATE 'SELECT id FROM tbl_view' INTO res_id, b;

-- duplicate aliases
EXECUTE IMMEDIATE 'SELECT id FROM tbl_view WHERE id = :first' USING 10 as first, 20 as first;

-- no alias
DECLARE p = 10;
EXECUTE IMMEDIATE 'SELECT id FROM tbl_view WHERE id = :p' USING p;

-- mixing literals and named parameters
EXECUTE IMMEDIATE 'SELECT id FROM tbl_view WHERE id = :p' USING p, 'p';

-- duplicate into entry
EXECUTE IMMEDIATE 'SELECT id, data.f1 FROM tbl_view WHERE id = 10' INTO res_id, res_id;

-- nested execute immediate
EXECUTE IMMEDIATE 'EXECUTE IMMEDIATE \'SELECT id FROM tbl_view WHERE id = ? USING 10\'';

-- sqlString is null
SET VAR sql_string = null;
EXECUTE IMMEDIATE sql_string;

DROP TABLE x;