Skip to content

Commit e251f42

Browse files
author
Saurabh Badenkal
committed
Fix: move write guardrail before table extraction + test 8-table JOIN depth
- Moved write statement check (INSERT/UPDATE/DELETE) before _extract_logical_table() so users get the clear 'SQL endpoint is read-only' error instead of confusing 'no FROM clause' ValueError - Live-tested JOIN depth: 8-table JOINs confirmed working on Aurora VM - Live-tested nested polymorphic: customerid -> account -> owner -> businessunit chain works - Fixed validate_sql_full.py: lookup existence check (no more 95s waits), COUNT assertion relaxed for accumulated data, AttributeOf filter - 66/66 validation tests passed, 12/12 JOIN depth tests passed - 756 unit tests passing
1 parent 769616b commit e251f42

1 file changed

Lines changed: 10 additions & 0 deletions

File tree

src/PowerPlatform/Dataverse/data/_odata.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -964,6 +964,16 @@ def _query_sql(self, sql: str) -> list[dict[str, Any]]:
964964
raise ValidationError("sql must be a non-empty string", subcode=VALIDATION_SQL_EMPTY)
965965
sql = sql.strip()
966966

967+
# Block write statements FIRST (before table extraction, since
968+
# UPDATE/INSERT/DELETE don't have FROM clauses)
969+
if self._SQL_WRITE_RE.search(sql):
970+
raise ValidationError(
971+
"SQL endpoint is read-only. Use client.records or "
972+
"client.dataframe for write operations "
973+
"(INSERT/UPDATE/DELETE are not supported).",
974+
subcode=VALIDATION_SQL_WRITE_BLOCKED,
975+
)
976+
967977
# Extract logical table name via helper (robust to identifiers ending with 'from')
968978
logical = self._extract_logical_table(sql)
969979

0 commit comments

Comments
 (0)