Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/en_US/release_notes_9_16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,4 @@ Bug fixes
| `Issue #9984 <https://github.com/pgadmin-org/pgadmin4/issues/9984>`_ - Fix the Docker entrypoint mishandling a quoted PGADMIN_CONFIG_CONFIG_DATABASE_URI, which caused a SQLAlchemy parse error and silently skipped PGADMIN_DEFAULT_EMAIL/PASSWORD setup.
| `Issue #9987 <https://github.com/pgadmin-org/pgadmin4/issues/9987>`_ - Fix "AttributeError: 'PgAdmin' object has no attribute 'login_manager'" crash when running setup.py user-management commands (add-user, update-user) from the CLI.
| `Issue #9988 <https://github.com/pgadmin-org/pgadmin4/issues/9988>`_ - Provide an actionable error when 'openid' is in OAUTH2_SCOPE but OAUTH2_SERVER_METADATA_URL is not set, instead of a cryptic Authlib failure.
| `Issue #10059 <https://github.com/pgadmin-org/pgadmin4/issues/10059>`_ - Fix the generated SQL for editing a SQL-language function/procedure whose body contains the word "return" (e.g. a RETURNING clause), which was wrongly treated as a SQL-standard body and produced a statement without the AS $BODY$ wrapper.
Original file line number Diff line number Diff line change
Expand Up @@ -1759,10 +1759,13 @@ def _is_function_def_sql_standard(resp_data):
r"^.*(?:\"|\')(?=.*(atomic)).*$"]

# valid regex, these combination a must in definition to detect a
# standard sql or pure sql
# standard sql or pure sql. The RETURN form must start the body
# (as a keyword) so that a plain SQL body which merely contains the
# substring "return" (e.g. a "RETURNING" clause or an identifier
# like "returned_value") is not mistaken for a SQL-standard body.
Comment on lines 1761 to +1765
valid_match = [
r"(?=.*begin)(.+?(\n)+)(?=.*atomic)|(?=.*begin)(?=.*atomic)",
r"(?=return)"
r"\A\s*return\b"
]

is_func_def_sql_std = False
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
##########################################################################
#
# pgAdmin 4 - PostgreSQL Tools
#
# Copyright (C) 2013 - 2026, The pgAdmin Development Team
# This software is released under the PostgreSQL Licence
#
##########################################################################

from pgadmin.utils.route import BaseTestGenerator
from .. import FunctionView


class TestIsFunctionDefSqlStandard(BaseTestGenerator):
"""
Unit tests for FunctionView._is_function_def_sql_standard.

This guards against a regression (issue #10059) where a plain SQL
function/procedure body that merely contained the substring "return"
(e.g. a "RETURNING" clause) was wrongly detected as a SQL-standard
body, causing the generated CREATE OR REPLACE statement to drop the
"AS $BODY$ ... $BODY$" wrapper and fail with a syntax error.
"""

scenarios = [
('SQL-standard BEGIN ATOMIC body is detected', dict(
data=dict(lanname='sql',
prosrc='\nBEGIN ATOMIC\n INSERT INTO t VALUES (1);\nEND'
),
expected=True
)),
('SQL-standard RETURN body is detected', dict(
data=dict(lanname='sql', prosrc='RETURN $1 + $2'),
expected=True
)),
('SQL-standard RETURN body with leading whitespace is detected',
dict(
data=dict(lanname='sql', prosrc='\n return a;'),
expected=True
)),
('Plain SQL body with a RETURNING clause is not SQL-standard', dict(
data=dict(lanname='sql',
prosrc='INSERT INTO t(a) VALUES (1) RETURNING a;'),
expected=False
)),
('Plain SQL body referencing a "returned" identifier is not '
'SQL-standard', dict(
data=dict(lanname='sql',
prosrc='SELECT my_returned_value FROM t;'),
expected=False
)),
('Plain SQL body is not SQL-standard', dict(
data=dict(lanname='sql', prosrc='SELECT 1;'),
expected=False
)),
('RETURN must start the body, not merely a later line', dict(
data=dict(lanname='sql', prosrc='SELECT 1;\nreturn x;'),
expected=False
)),
('Non-sql language is never SQL-standard', dict(
data=dict(lanname='plpgsql',
prosrc='BEGIN\n RETURN;\nEND;'),
expected=False
)),
('Empty body is not SQL-standard', dict(
data=dict(lanname='sql', prosrc=''),
expected=False
)),
]

def runTest(self):
result = FunctionView._is_function_def_sql_standard(self.data)
self.assertEqual(result, self.expected)
Loading