git-subtree-dir: fiscal git-subtree-mainline:d95165fc8fgit-subtree-split:102ba84500
111 lines
3.0 KiB
Python
111 lines
3.0 KiB
Python
import pytest
|
|
|
|
from gti_discovery.read_only import validate_read_only
|
|
|
|
|
|
def test_accepts_and_normalizes_select_query():
|
|
assert validate_read_only(" SELECT * FROM RDB$DATABASE ; ") == (
|
|
"SELECT * FROM RDB$DATABASE"
|
|
)
|
|
|
|
|
|
def test_accepts_with_query():
|
|
sql = "WITH x AS (SELECT 1 AS n FROM RDB$DATABASE) SELECT n FROM x"
|
|
assert validate_read_only(sql) == sql
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql",
|
|
[
|
|
"INSERT INTO X VALUES (1)",
|
|
"UPDATE X SET A=1",
|
|
"DELETE FROM X",
|
|
"CREATE TABLE X(A INT)",
|
|
"ALTER TABLE X ADD A INT",
|
|
"DROP TABLE X",
|
|
"TRUNCATE TABLE X",
|
|
"EXECUTE PROCEDURE P",
|
|
"WITH x AS (SELECT 1 FROM RDB$DATABASE) INSERT INTO X VALUES (1)",
|
|
],
|
|
)
|
|
def test_rejects_write_or_side_effect_sql(sql):
|
|
with pytest.raises(ValueError):
|
|
validate_read_only(sql)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql",
|
|
[
|
|
"SELECT 1 FROM RDB$DATABASE; SELECT 2 FROM RDB$DATABASE",
|
|
"SELECT 1 FROM RDB$DATABASE -- comment",
|
|
"SELECT 1 /* comment */ FROM RDB$DATABASE",
|
|
"",
|
|
"VACUUM TABLE X",
|
|
],
|
|
)
|
|
def test_rejects_multiple_statements_comments_and_non_queries(sql):
|
|
with pytest.raises(ValueError):
|
|
validate_read_only(sql)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql",
|
|
[
|
|
"SELECT * FROM SIDE_EFFECTING_PROC(1)",
|
|
"SELECT GEN_ID(MY_GENERATOR, 1) FROM RDB$DATABASE",
|
|
"SELECT NEXT VALUE FOR MY_GENERATOR FROM RDB$DATABASE",
|
|
"SELECT * FROM X WITH LOCK",
|
|
"SELECT * FROM X FOR UPDATE",
|
|
"SELECT * FROM PKG . SELECTABLE_PROC (1)",
|
|
],
|
|
)
|
|
def test_rejects_known_side_effecting_select_constructs(sql):
|
|
with pytest.raises(ValueError):
|
|
validate_read_only(sql)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql",
|
|
[
|
|
"SELECT IIF(RDB$SYSTEM_FLAG = 1, 'SYSTEM', 'USER') FROM RDB$RELATIONS",
|
|
"SELECT EXTRACT(YEAR FROM CURRENT_DATE) FROM RDB$DATABASE",
|
|
"SELECT COALESCE(RDB$RELATION_NAME, '') FROM RDB$RELATIONS",
|
|
],
|
|
)
|
|
def test_accepts_legitimate_firebird_read_only_expressions(sql):
|
|
assert validate_read_only(sql) == sql
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql",
|
|
[
|
|
"SELECT EXECUTE(1) FROM RDB$DATABASE",
|
|
"SELECT GEN_ID(MY_GENERATOR, 1) FROM RDB$DATABASE",
|
|
"SELECT * FROM SELECTABLE_PROC(1)",
|
|
"SELECT * FROM PKG . SELECTABLE_PROC (1)",
|
|
"SELECT * FROM PKG\t.\tSELECTABLE_PROC\t(1)",
|
|
],
|
|
)
|
|
def test_rejects_explicit_unsafe_callable_forms(sql):
|
|
with pytest.raises(ValueError):
|
|
validate_read_only(sql)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"sql",
|
|
[
|
|
"SELECT SIDE_EFFECTING_UDF(ID) FROM X",
|
|
"SELECT PKG . SIDE_EFFECTING_UDF(ID) FROM X",
|
|
],
|
|
)
|
|
def test_rejects_unknown_callable_in_select_projection(sql):
|
|
with pytest.raises(ValueError, match="callable"):
|
|
validate_read_only(sql)
|
|
|
|
|
|
def test_normalization_does_not_change_quoted_literal_contents():
|
|
sql = " SELECT ' keep spaces ; -- text ' FROM RDB$DATABASE ; "
|
|
assert validate_read_only(sql) == (
|
|
"SELECT ' keep spaces ; -- text ' FROM RDB$DATABASE"
|
|
)
|