// Tests for fn_ui::sql_parse / sql_classify (cpp/functions/core/sql_parse). // Pura: tokeniza SQL multi-statement saltando strings y comentarios, y // clasifica por keyword inicial. #define CATCH_CONFIG_MAIN #include "catch_amalgamated.hpp" #include "core/sql_parse.h" using fn_ui::sql_parse; using fn_ui::sql_classify; using fn_ui::SqlStmtKind; TEST_CASE("sql_parse classifies common statements") { auto stmts = sql_parse("SELECT * FROM t; INSERT INTO t VALUES (1);"); REQUIRE(stmts.size() == 2); REQUIRE(stmts[0].kind == SqlStmtKind::Select); REQUIRE(stmts[1].kind == SqlStmtKind::Insert); } TEST_CASE("sql_parse handles strings and comments") { auto stmts = sql_parse("-- comment\nSELECT 'a;b' FROM t; /* x */ DELETE FROM t;"); REQUIRE(stmts.size() == 2); REQUIRE(stmts[0].kind == SqlStmtKind::Select); REQUIRE(stmts[1].kind == SqlStmtKind::Delete); } TEST_CASE("sql_parse trims and ignores empty") { auto stmts = sql_parse("; ; SELECT 1;;"); REQUIRE(stmts.size() == 1); REQUIRE(stmts[0].kind == SqlStmtKind::Select); } TEST_CASE("sql_parse: ddl and dcl keywords") { auto stmts = sql_parse("CREATE TABLE t(a); DROP TABLE t; ALTER TABLE t ADD b; UPDATE t SET a=1;"); REQUIRE(stmts.size() == 4); REQUIRE(stmts[0].kind == SqlStmtKind::Create); REQUIRE(stmts[1].kind == SqlStmtKind::Drop); REQUIRE(stmts[2].kind == SqlStmtKind::Alter); REQUIRE(stmts[3].kind == SqlStmtKind::Update); } TEST_CASE("sql_parse: pragma and explain") { auto stmts = sql_parse("PRAGMA foreign_keys = ON; EXPLAIN SELECT 1;"); REQUIRE(stmts.size() == 2); REQUIRE(stmts[0].kind == SqlStmtKind::Pragma); REQUIRE(stmts[1].kind == SqlStmtKind::Explain); } TEST_CASE("sql_parse: WITH clasifica como Select") { auto stmts = sql_parse("WITH x AS (SELECT 1) SELECT * FROM x;"); REQUIRE(stmts.size() == 1); REQUIRE(stmts[0].kind == SqlStmtKind::Select); } TEST_CASE("sql_parse: case-insensitive y trim") { auto stmts = sql_parse(" select 1;\n INSERT INTO t VALUES (2);"); REQUIRE(stmts.size() == 2); REQUIRE(stmts[0].kind == SqlStmtKind::Select); REQUIRE(stmts[1].kind == SqlStmtKind::Insert); } TEST_CASE("sql_parse: line tracking") { auto stmts = sql_parse("\n\nSELECT 1;\n-- skip\nDELETE FROM t;\n"); REQUIRE(stmts.size() == 2); REQUIRE(stmts[0].line == 3); REQUIRE(stmts[1].line == 5); } TEST_CASE("sql_parse: ultimo statement sin ;") { auto stmts = sql_parse("SELECT 1"); REQUIRE(stmts.size() == 1); REQUIRE(stmts[0].kind == SqlStmtKind::Select); } TEST_CASE("sql_classify: standalone") { REQUIRE(sql_classify("SELECT 1") == SqlStmtKind::Select); REQUIRE(sql_classify("garbage") == SqlStmtKind::Unknown); REQUIRE(sql_classify("") == SqlStmtKind::Unknown); REQUIRE(sql_classify("/* c */ DELETE FROM t") == SqlStmtKind::Delete); } TEST_CASE("sql_parse: ; dentro de string no separa") { auto stmts = sql_parse("SELECT 'a;b;c' FROM t;"); REQUIRE(stmts.size() == 1); REQUIRE(stmts[0].kind == SqlStmtKind::Select); } TEST_CASE("sql_parse: backtick identifier") { auto stmts = sql_parse("SELECT * FROM `weird;name`;"); REQUIRE(stmts.size() == 1); REQUIRE(stmts[0].kind == SqlStmtKind::Select); }