-- 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;

-- require query when using INTO with SET VAR command
DECLARE OR REPLACE testvarA INT;
EXECUTE IMMEDIATE 'SET VAR testVarA = 1' INTO testVarA;

-- 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 as x, 'name2' as first;

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

-- all parameters 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';

-- constant expressions are supported
EXECUTE IMMEDIATE 'SELECT * from tbl_view where name = :first' USING CONCAT(a , "me1") as first;

-- subquery in using not supported
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;

-- sqlString is not a string
SET VAR sql_string = 5;
EXECUTE IMMEDIATE sql_string;

-- sqlString is not a well formed SQL statement.
SET VAR sql_string = 'hello';
EXECUTE IMMEDIATE length(sql_string);

-- mixed positional and named parameters in query
EXECUTE IMMEDIATE 'SELECT 42 where ? = :first' USING 1, 2 as first;

-- non-string variable as sqlString parameter
DECLARE int_var INT;
SET VAR int_var = 42;
EXECUTE IMMEDIATE int_var;

-- null string as sqlString parameter
DECLARE null_var STRING;
SET VAR null_var = null;
EXECUTE IMMEDIATE null_var;

-- unsupported expression for parameter (subquery)
EXECUTE IMMEDIATE 'SELECT ?' USING (SELECT 1);

-- named query with unnamed parameters
EXECUTE IMMEDIATE 'SELECT :first' USING 2, 3;

-- Query is not a constant
EXECUTE IMMEDIATE (SELECT c FROM (VALUES(1)) AS T(c));

DROP TABLE x;

-- Test data type conversion correctness for LiteralToSqlConverter
-- Each test validates that the parameter is correctly converted to SQL and executed

-- !query
-- Basic numeric types
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 5 AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 5L AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 5S AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 5Y AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 3.14F AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 3.14159D AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 123.45BD AS p;

-- !query
-- Boolean type
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING true AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING false AS p;

-- !query
-- String types
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 'hello world' AS p;

-- !query
-- String with single quotes (test escaping)
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 'it''s a test' AS p;

-- !query
-- Date and timestamp types
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING DATE '2023-12-25' AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING TIMESTAMP '2023-12-25 10:30:45' AS p;

-- !query
-- TimestampNTZ type
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING TIMESTAMP_NTZ '2023-12-25 10:30:45' AS p;

-- !query
-- Null values
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING CAST(NULL AS INT) AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING CAST(NULL AS STRING) AS p;

-- !query
-- Binary type
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, hex(:p) as val' USING X'010203FF' AS p;

-- !query
-- Interval types
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING INTERVAL '3' DAY AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING INTERVAL '2' YEAR AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING INTERVAL '1-2' YEAR TO MONTH AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING INTERVAL '3 4:5:6' DAY TO SECOND AS p;

-- !query
-- Additional numeric type tests
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING 999.999BD AS p;

-- !query
-- Test multiple parameters with different types
EXECUTE IMMEDIATE 'SELECT typeof(:p1) as type1, :p1 as val1, typeof(:p2) as type2, :p2 as val2' 
  USING 42 as p1, 'test string' as p2;

-- !query
-- Array types (simple)
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING ARRAY(1, 2, 3) AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING ARRAY('a', 'b', 'c') AS p;

-- !query
-- Nested array
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING ARRAY(ARRAY(1, 2), ARRAY(3, 4)) AS p;

-- !query
-- Map types
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING MAP('key1', 'value1', 'key2', 'value2') AS p;

-- !query
EXECUTE IMMEDIATE 'SELECT typeof(:p) as type, :p as val' USING MAP(1, 'one', 2, 'two') AS p;

-- !query
-- Test unbound parameter markers without USING clause
-- named parameter without USING clause should fail
EXECUTE IMMEDIATE 'SELECT :param';

-- !query
-- positional parameter without USING clause should fail
EXECUTE IMMEDIATE 'SELECT ?';
