chore: establish project baseline
This commit is contained in:
@@ -0,0 +1,110 @@
|
||||
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"
|
||||
)
|
||||
Reference in New Issue
Block a user