Skip to content

Commit 9f89355

Browse files
committed
[DOP-31721] Validate SQL transformation FROM clause
1 parent cc7311e commit 9f89355

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

syncmaster/schemas/v1/transfers/transformations/sql.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55

66
from pydantic import BaseModel, Field, field_validator
77

8-
ALLOWED_SELECT_QUERY = re.compile(r"^\s*(SELECT|WITH)\b", re.IGNORECASE)
8+
ALLOWED_QUERY_TYPE = re.compile(r"^\s*(SELECT|WITH)\b", re.IGNORECASE)
9+
QUERY_CONTAINS_FROM_SOURCE = re.compile(r"\bFROM\s+source\b", re.IGNORECASE)
910

1011

1112
class Sql(BaseModel):
@@ -16,8 +17,12 @@ class Sql(BaseModel):
1617
@field_validator("query", mode="after")
1718
@classmethod
1819
def _validate_query(cls, value: str) -> str:
19-
if not ALLOWED_SELECT_QUERY.match(value):
20-
msg = f"Query must be a SELECT statement, got '{value}'"
20+
if not ALLOWED_QUERY_TYPE.match(value):
21+
msg = "Query must be a SELECT statement"
22+
raise ValueError(msg)
23+
24+
if not QUERY_CONTAINS_FROM_SOURCE.match(value):
25+
msg = "Query must contain `FROM source` clause"
2126
raise ValueError(msg)
2227

2328
return value

tests/test_unit/test_transfers/test_create_transfer.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -832,7 +832,7 @@ async def test_superuser_can_create_transfer(
832832
"sql",
833833
"query",
834834
],
835-
"message": "Value error, Query must be a SELECT statement, got 'INSERT INTO table1 VALUES (1, 2)'",
835+
"message": "Value error, Query must be a SELECT statement",
836836
"code": "value_error",
837837
"context": {},
838838
"input": "INSERT INTO table1 VALUES (1, 2)",
@@ -842,6 +842,39 @@ async def test_superuser_can_create_transfer(
842842
},
843843
id="sql_non_select_query",
844844
),
845+
pytest.param(
846+
{
847+
"transformations": [
848+
{
849+
"type": "sql",
850+
"query": "SELECT * FROM table1",
851+
"dialect": "spark",
852+
},
853+
],
854+
},
855+
{
856+
"error": {
857+
"code": "invalid_request",
858+
"message": "Invalid request",
859+
"details": [
860+
{
861+
"location": [
862+
"body",
863+
"transformations",
864+
0,
865+
"sql",
866+
"query",
867+
],
868+
"message": "Value error, Query must contain `FROM source` clause",
869+
"code": "value_error",
870+
"context": {},
871+
"input": "SELECT * FROM table1",
872+
},
873+
],
874+
},
875+
},
876+
id="sql_invalid_select_query",
877+
),
845878
pytest.param(
846879
{
847880
"transformations": [

0 commit comments

Comments
 (0)