Files
MyGoNavi/internal/app/sql_split_test.go
Syngnat 1a9d417c0a 🐛 fix(query-editor): 修复过程脚本斜杠分隔符误执行
- 前端语句选择跳过独立 SQL*Plus 斜杠分隔符

- 后端 SQL 拆分和流式文件执行保持过程体完整

- 增加 Oracle 过程脚本执行回归测试
2026-06-24 21:10:59 +08:00

275 lines
8.2 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package app
import (
"reflect"
"testing"
)
func TestSplitSQLStatements_BasicSplit(t *testing.T) {
input := "SELECT 1; SELECT 2; SELECT 3"
got := splitSQLStatements(input)
want := []string{"SELECT 1", "SELECT 2", "SELECT 3"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_QuotedSemicolon(t *testing.T) {
input := `SELECT 'hello;world'; SELECT 2`
got := splitSQLStatements(input)
want := []string{`SELECT 'hello;world'`, "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_LineComment(t *testing.T) {
input := "SELECT 1; -- this is a comment;\nSELECT 2"
got := splitSQLStatements(input)
want := []string{"SELECT 1", "-- this is a comment;\nSELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_BlockComment(t *testing.T) {
input := "SELECT /* ; */ 1; SELECT 2"
got := splitSQLStatements(input)
want := []string{"SELECT /* ; */ 1", "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_EmptyInput(t *testing.T) {
got := splitSQLStatements("")
if len(got) != 0 {
t.Errorf("splitSQLStatements(\"\") = %v, want empty slice", got)
}
}
func TestSplitSQLStatements_SingleStatement(t *testing.T) {
input := "SELECT * FROM users WHERE id = 1"
got := splitSQLStatements(input)
want := []string{"SELECT * FROM users WHERE id = 1"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_DollarQuoting(t *testing.T) {
input := "SELECT $tag$hello;world$tag$; SELECT 2"
got := splitSQLStatements(input)
want := []string{"SELECT $tag$hello;world$tag$", "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_PostgresCreateFunctionDollarQuoting(t *testing.T) {
input := `CREATE OR REPLACE FUNCTION refresh_stats() RETURNS void AS $$
BEGIN
PERFORM refresh_now();
END;
$$ LANGUAGE plpgsql;
SELECT 2;`
got := splitSQLStatements(input)
want := []string{
`CREATE OR REPLACE FUNCTION refresh_stats() RETURNS void AS $$
BEGIN
PERFORM refresh_now();
END;
$$ LANGUAGE plpgsql`,
"SELECT 2",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}
func TestSplitSQLStatements_FullWidthSemicolon(t *testing.T) {
input := "SELECT 1SELECT 2"
got := splitSQLStatements(input)
want := []string{"SELECT 1", "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_Backtick(t *testing.T) {
input := "SELECT `col;name` FROM t; SELECT 2"
got := splitSQLStatements(input)
want := []string{"SELECT `col;name` FROM t", "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_TrailingSemicolon(t *testing.T) {
input := "SELECT 1; SELECT 2;"
got := splitSQLStatements(input)
want := []string{"SELECT 1", "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_SQLEscapedQuote(t *testing.T) {
input := "SELECT 'it''s a test'; SELECT 2"
got := splitSQLStatements(input)
want := []string{"SELECT 'it''s a test'", "SELECT 2"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_SQLEscapedQuoteMultiple(t *testing.T) {
input := "INSERT INTO t VALUES ('O''Brien', 'it''s OK'); SELECT 1"
got := splitSQLStatements(input)
want := []string{"INSERT INTO t VALUES ('O''Brien', 'it''s OK')", "SELECT 1"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %v, want %v", input, got, want)
}
}
func TestSplitSQLStatements_OracleAnonymousBlock(t *testing.T) {
input := `BEGIN
INSERT INTO tmp_disable_trigger (table_name) VALUES ('t_memcard_reg');
UPDATE t_memcard_reg SET CARDLEVEL = 1 WHERE MEMCARDNO = '8032277312';
DELETE FROM tmp_disable_trigger WHERE table_name = 't_memcard_reg';
END;
SELECT 1 FROM dual;`
got := splitSQLStatements(input)
want := []string{
`BEGIN
INSERT INTO tmp_disable_trigger (table_name) VALUES ('t_memcard_reg');
UPDATE t_memcard_reg SET CARDLEVEL = 1 WHERE MEMCARDNO = '8032277312';
DELETE FROM tmp_disable_trigger WHERE table_name = 't_memcard_reg';
END;`,
"SELECT 1 FROM dual",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}
func TestSplitSQLStatements_OracleDeclareBlock(t *testing.T) {
input := `DECLARE
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM t_memcard_reg;
UPDATE t_memcard_reg SET CARDLEVEL = v_count WHERE MEMCARDNO = '8032277312';
END;
SELECT 1 FROM dual;`
got := splitSQLStatements(input)
want := []string{
`DECLARE
v_count NUMBER;
BEGIN
SELECT COUNT(*) INTO v_count FROM t_memcard_reg;
UPDATE t_memcard_reg SET CARDLEVEL = v_count WHERE MEMCARDNO = '8032277312';
END;`,
"SELECT 1 FROM dual",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}
func TestSplitSQLStatements_OracleCreateProcedureBlock(t *testing.T) {
input := `CREATE OR REPLACE PROCEDURE proc_tally2accept(
p_tallyacceptno IN t_tally_accept_h.acceptno%TYPE,
out_acceptno OUT t_accept_h.acceptno%TYPE
) IS
v_busno t_tally_accept_h.busno%TYPE;
v_count PLS_INTEGER;
BEGIN
SELECT COUNT(*) INTO v_count FROM t_tally_accept_h WHERE acceptno = p_tallyacceptno;
IF v_count > 0 THEN
out_acceptno := p_tallyacceptno;
END IF;
END;
SELECT 1 FROM dual;`
got := splitSQLStatements(input)
want := []string{
`CREATE OR REPLACE PROCEDURE proc_tally2accept(
p_tallyacceptno IN t_tally_accept_h.acceptno%TYPE,
out_acceptno OUT t_accept_h.acceptno%TYPE
) IS
v_busno t_tally_accept_h.busno%TYPE;
v_count PLS_INTEGER;
BEGIN
SELECT COUNT(*) INTO v_count FROM t_tally_accept_h WHERE acceptno = p_tallyacceptno;
IF v_count > 0 THEN
out_acceptno := p_tallyacceptno;
END IF;
END;`,
"SELECT 1 FROM dual",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}
func TestSplitSQLStatements_OracleCreateProcedureSkipsSqlPlusSlashDelimiter(t *testing.T) {
input := `CREATE OR REPLACE PROCEDURE cproc_tzhssr_order2sale_new(
p_sourceid IN VARCHAR2
) IS
v_memcardno VARCHAR2(40);
v_ecnt NUMBER;
CURSOR cur_ware IS
SELECT d.goodsid, d.goodsqty
FROM t_order_d d
WHERE d.sourceid = p_sourceid;
BEGIN
FOR row_ware IN cur_ware LOOP
v_ecnt := row_ware.goodsqty;
END LOOP;
END;
/
SELECT 1 FROM dual;`
got := splitSQLStatements(input)
want := []string{
`CREATE OR REPLACE PROCEDURE cproc_tzhssr_order2sale_new(
p_sourceid IN VARCHAR2
) IS
v_memcardno VARCHAR2(40);
v_ecnt NUMBER;
CURSOR cur_ware IS
SELECT d.goodsid, d.goodsqty
FROM t_order_d d
WHERE d.sourceid = p_sourceid;
BEGIN
FOR row_ware IN cur_ware LOOP
v_ecnt := row_ware.goodsqty;
END LOOP;
END;`,
"SELECT 1 FROM dual",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}
func TestSplitSQLStatements_DoesNotTreatSlashOperatorLineAsDelimiter(t *testing.T) {
input := "SELECT 10\n/\n2 FROM dual;"
got := splitSQLStatements(input)
want := []string{"SELECT 10\n/\n2 FROM dual"}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}
func TestSplitSQLStatements_TransactionBeginStillSplits(t *testing.T) {
input := "BEGIN; UPDATE accounts SET balance = balance - 1 WHERE id = 1; COMMIT;"
got := splitSQLStatements(input)
want := []string{
"BEGIN",
"UPDATE accounts SET balance = balance - 1 WHERE id = 1",
"COMMIT",
}
if !reflect.DeepEqual(got, want) {
t.Errorf("splitSQLStatements(%q) = %#v, want %#v", input, got, want)
}
}