From 1672dd8e55bbff075555bed100c75e4620d70713 Mon Sep 17 00:00:00 2001 From: "Karl O. Pinc" Date: Sun, 18 Aug 2024 17:37:15 -0500 Subject: [PATCH] Report on syntax errors without crashing --- src/pgwui_sql/exceptions.py | 17 +++++++---------- src/pgwui_sql/views/sql.py | 30 +++++++++++++++++++++++++++++- 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/pgwui_sql/exceptions.py b/src/pgwui_sql/exceptions.py index 1256b18..e906793 100644 --- a/src/pgwui_sql/exceptions.py +++ b/src/pgwui_sql/exceptions.py @@ -42,20 +42,17 @@ class ExampleDetailedError(ExampleSetupError): super().__init__('Detailed error', descr=descr, detail=detail) -# Data error related exception +# SQL error related exception -class ExampleTooManyRowsError(core_ex.DataLineError): +class SQLError(core_ex.UploadError): ''' - Module exception rasied while line-by-line processing the uploaded - data. + Error raised when processing SQL - lineno The line number - e The error message + e The error severity descr More description of the error detail Extra HTML describing the error data The uploaded data ''' - def __init__(self, lineno, e, descr='', detail='', data=''): - if descr is None: - descr = 'Too many rows of uploaded data' - super().__init__(e, lineno, descr, detail, data) + def __init__(self, e, lineno, descr='', detail=''): + super().__init__(f'{e} when executing SQL', + lineno, descr=descr, detail=detail) diff --git a/src/pgwui_sql/views/sql.py b/src/pgwui_sql/views/sql.py index 2d1eda5..7307050 100644 --- a/src/pgwui_sql/views/sql.py +++ b/src/pgwui_sql/views/sql.py @@ -21,6 +21,8 @@ from pyramid.view import view_config from wtforms.fields import TextAreaField import attrs import logging +import markupsafe +import psycopg.errors import pgwui_core.core import pgwui_core.forms @@ -148,6 +150,32 @@ class SQLHandler(pgwui_core.core.SessionDBHandler): return response + def execute(self, cur, stmt_text): + try: + cur.execute(stmt_text) + except psycopg.errors.Error as err: + lineno = stmt_text.count( + '\n', 0, int(err.diag.statement_position) - 1) + 1 + + detail = [] + if err.diag.message_detail is not None: + detail.append(markupsafe.escape(err.diag.message_detail)) + if err.diag.message_hint is not None: + detail.append( + f'Hint: {markupsafe.escape(err.diag.message_hint)}') + detail = '
\n'.join(detail) + + numbered_stmts = [] + numbered_stmts.append('
    ') + for line in stmt_text.rstrip().split('\n'): + numbered_stmts.append(f'
  1. {markupsafe.escape(line)}
  2. ') + numbered_stmts.append('
') + + raise sql_ex.SQLError(err.diag.severity, + lineno, + descr=err.diag.message_primary, + detail=detail + '\n'.join(numbered_stmts)) + def get_result_rows(self, cur, sql_results): first = True while (row := cur.fetchone()) is not None: @@ -163,7 +191,7 @@ class SQLHandler(pgwui_core.core.SessionDBHandler): interleaving errors with output. ''' cur = self.cur - cur.execute(self.uf['sql']) + self.execute(cur, self.uf['sql']) sql_results = self.sql_results nextset = True -- 2.34.1