mirror of
https://github.com/yogeshojha/rengine.git
synced 2026-10-20 07:11:28 +02:00
Eleven call sites across six services each spelled the same QueryError(message=..., hint=..., start=..., end=...) so the UI could underline the query in place. errors.py already owned the other half of that vocabulary, query_error_for(DBAPIError); syntax_error() is its counterpart and the services call it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01DafWxfoWZXVDgr9KroJBDZ
37 lines
1.2 KiB
Python
37 lines
1.2 KiB
Python
from __future__ import annotations
|
|
|
|
from sqlalchemy.exc import DBAPIError
|
|
|
|
from shared.models.asset_query import QueryError
|
|
|
|
from .ast import QuerySyntaxError
|
|
|
|
STATEMENT_TIMEOUT = "SET LOCAL statement_timeout = '20s'"
|
|
NO_JIT = "SET LOCAL jit = off"
|
|
|
|
QUERY_SQLSTATES = {
|
|
"2201B": (
|
|
"Invalid regular expression.",
|
|
"PostgreSQL regular expression syntax applies.",
|
|
),
|
|
"2201G": ("Invalid regular expression.", None),
|
|
"57014": ("The search timed out.", "Add a field filter."),
|
|
"22003": ("A number is out of range.", None),
|
|
"22P02": ("A value has the wrong type.", None),
|
|
"54000": ("A search term is too long to index.", None),
|
|
}
|
|
|
|
|
|
def query_error_for(exc: DBAPIError) -> QueryError | None:
|
|
sqlstate = getattr(exc.orig, "sqlstate", None) or getattr(exc.orig, "pgcode", None)
|
|
known = QUERY_SQLSTATES.get(str(sqlstate))
|
|
if known is None:
|
|
return None
|
|
message, hint = known
|
|
return QueryError(message=message, hint=hint)
|
|
|
|
|
|
def syntax_error(exc: QuerySyntaxError) -> QueryError:
|
|
"""What the UI underlines in place of the query it could not parse."""
|
|
return QueryError(message=exc.message, hint=exc.hint, start=exc.start, end=exc.end)
|