-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathvalidate.py
More file actions
65 lines (59 loc) · 3.18 KB
/
validate.py
File metadata and controls
65 lines (59 loc) · 3.18 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
import logging
from fastapi import APIRouter, HTTPException
from sqlalchemy import text
from sqlalchemy.exc import OperationalError, ProgrammingError, SQLAlchemyError
from src.schemas.validation import VqlValidateRequest, VqlValidationApiResponse
from src.utils.ai_analyzer import analyze_vql_validation_error
from src.db.session import get_engine
from src.schemas.validation import ValidationError # Use the centralized engine
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/validate", response_model=VqlValidationApiResponse, tags=["VQL Forge"])
def validate_vql_query_endpoint(request: VqlValidateRequest) -> VqlValidationApiResponse:
engine = get_engine() # Get engine, will raise ConnectionError if not init
if engine is None: # Should be caught by get_engine, but as a safeguard
raise HTTPException(
status_code=503,
detail="Database connection is not available. Check server logs.",
)
# The original request.sql might be the SQL that was translated to VQL.
# The request.vql is what we are validating.
# For AI analysis, we probably want to pass the VQL that failed.
desc_query_plan_vql: str = f"DESC QUERYPLAN {request.vql}"
logger.info(f"Attempting to validate VQL (via DESC QUERYPLAN): {request.vql[:100]}...")
try:
with engine.connect() as connection:
# DESC QUERYPLAN doesn't return rows on success, just executes
connection.execute(text(desc_query_plan_vql))
logger.info("VQL validation successful via DESC QUERYPLAN.")
return VqlValidationApiResponse(
validated=True,
message="VQL syntax check successful!",
)
except (OperationalError, ProgrammingError) as e:
db_error_message = str(getattr(e, "orig", e)) # Get specific DB error
logger.warning(f"Denodo VQL validation failed: {db_error_message}")
try:
ai_analysis_result: ValidationError = analyze_vql_validation_error(db_error_message, request.vql)
return VqlValidationApiResponse(
validated=False, error_analysis=ai_analysis_result
)
except HTTPException as http_exc: # AI service's own HTTPExceptions
logger.error(f"AI analysis failed during validation handling: {http_exc.detail}")
raise http_exc # Re-raise if it's an issue like API key
except Exception as ai_err:
logger.error(f"Unexpected error during AI validation analysis: {ai_err}", exc_info=True)
return VqlValidationApiResponse(
validated=False,
message=f"Validation Failed: {db_error_message}. AI analysis also encountered an error: {ai_err}",
)
except SQLAlchemyError as e:
logger.error(f"Database connection/SQLAlchemy error during validation: {e}", exc_info=True)
return VqlValidationApiResponse(
validated=False, message=f"Database error during validation: {str(e)}"
)
except Exception as e:
logger.error(f"Unexpected error during VQL validation: {e}", exc_info=True)
return VqlValidationApiResponse(
validated=False, message=f"An unexpected error occurred: {str(e)}"
)