What happened?
Description
salt/returners/pgjsonb.py:get_fun issues a query that uses MySQL-style backtick identifier quoting:
sql = """SELECT s.id,s.jid, s.full_ret
FROM salt_returns s
JOIN ( SELECT MAX(`jid`) as jid
from salt_returns GROUP BY fun, id) max
ON s.jid = max.jid
WHERE s.fun = %s
"""
PostgreSQL — the only server pgjsonb talks to — rejects backticks at parse time:
ERROR: syntax error at or near "`"
LINE 3: JOIN ( SELECT MAX(`jid`) as jid
^
The query is a near-verbatim copy-paste from salt/returners/mysql.py where the syntax is valid; the identifier quoting was overlooked when the file was adapted for PostgreSQL.
The bug is dormant in typical deployments. Stock master_job_cache: pgjsonb operation routes through get_load, get_jid, get_jids, get_minions, prep_jid, save_load, returner and event_return — none of those reach get_fun. The function surfaces only when an operator or an extension calls pgjsonb.get_fun explicitly, e.g. via a custom runner, or sets master_job_cache.get_fun to it from external tooling.
Setup
Any deployment that uses master_job_cache: pgjsonb and either calls pgjsonb.get_fun directly or has tooling that does.
Steps to Reproduce the behavior
- Configure
master_job_cache: pgjsonb.
- From a runner or REPL:
salt-run salt.cmd pgjsonb.get_fun test.ping.
- The call raises
psycopg2.errors.SyntaxError: syntax error at or near "\"`.
Expected behavior
get_fun returns a {minion_id: full_ret} dict for the last execution of the given function across all minions.
Additional context
The accompanying PR drops the backticks (PostgreSQL does not require quoting around jid since it is not a reserved word) and adds a behavioural unit test that asserts the per-minion mapping is built correctly and guards against backticks creeping back into the SQL through future copy-paste from the mysql returner.
A separate, more interesting issue with this function — the MAX(jid) algorithm for "last execution" works only because the default Salt jid format (YYYYMMDDHHMMSSffffff) happens to be lexicographically sortable as a timestamp. Operators who override master_job_cache.gen_jid with a non-sortable id format (UUID, snowflake, random) get a silently-wrong answer here. That is a deeper bug and will be tracked as its own follow-up.
Type of salt install
Official deb
Major version
3006.x, 3007.x
What supported OS are you seeing the problem on? Can select multiple. (If bug appears on an unsupported OS, please open a GitHub Discussion instead)
debian-11, debian-12
salt --versions-report output
salt --versions-report
Salt Version:
Salt: 3007.13
Python Version:
Python: 3.10.19 (main, Feb 5 2026, 07:05:38) [GCC 11.2.0]
Dependency Versions:
cffi: 2.0.0
cherrypy: unknown
cryptography: 42.0.5
dateutil: 2.8.2
docker-py: Not Installed
gitdb: Not Installed
gitpython: Not Installed
Jinja2: 3.1.6
libgit2: 1.9.1
looseversion: 1.3.0
M2Crypto: Not Installed
Mako: Not Installed
msgpack: 1.0.7
msgpack-pure: Not Installed
mysql-python: Not Installed
packaging: 24.0
pycparser: 2.21
pycrypto: Not Installed
pycryptodome: 3.19.1
pygit2: 1.18.2
python-gnupg: 0.5.2
PyYAML: 6.0.1
PyZMQ: 25.1.2
relenv: 0.22.3
smmap: Not Installed
timelib: 0.3.0
Tornado: 6.5.4
ZMQ: 4.3.4
Salt Extensions:
saltext.vault: 1.5.0
Salt Package Information:
Package Type: onedir
System Versions:
dist: debian 12.13 bookworm
locale: utf-8
machine: x86_64
release: 6.12.73+deb12-amd64
system: Linux
version: Debian GNU/Linux 12.13 bookworm
What happened?
Description
salt/returners/pgjsonb.py:get_funissues a query that uses MySQL-style backtick identifier quoting:PostgreSQL — the only server pgjsonb talks to — rejects backticks at parse time:
The query is a near-verbatim copy-paste from
salt/returners/mysql.pywhere the syntax is valid; the identifier quoting was overlooked when the file was adapted for PostgreSQL.The bug is dormant in typical deployments. Stock
master_job_cache: pgjsonboperation routes throughget_load,get_jid,get_jids,get_minions,prep_jid,save_load,returnerandevent_return— none of those reachget_fun. The function surfaces only when an operator or an extension callspgjsonb.get_funexplicitly, e.g. via a custom runner, or setsmaster_job_cache.get_funto it from external tooling.Setup
Any deployment that uses
master_job_cache: pgjsonband either callspgjsonb.get_fundirectly or has tooling that does.Steps to Reproduce the behavior
master_job_cache: pgjsonb.salt-run salt.cmd pgjsonb.get_fun test.ping.psycopg2.errors.SyntaxError: syntax error at or near "\"`.Expected behavior
get_funreturns a{minion_id: full_ret}dict for the last execution of the given function across all minions.Additional context
The accompanying PR drops the backticks (PostgreSQL does not require quoting around
jidsince it is not a reserved word) and adds a behavioural unit test that asserts the per-minion mapping is built correctly and guards against backticks creeping back into the SQL through future copy-paste from the mysql returner.A separate, more interesting issue with this function — the
MAX(jid)algorithm for "last execution" works only because the default Salt jid format (YYYYMMDDHHMMSSffffff) happens to be lexicographically sortable as a timestamp. Operators who overridemaster_job_cache.gen_jidwith a non-sortable id format (UUID, snowflake, random) get a silently-wrong answer here. That is a deeper bug and will be tracked as its own follow-up.Type of salt install
Official deb
Major version
3006.x, 3007.x
What supported OS are you seeing the problem on? Can select multiple. (If bug appears on an unsupported OS, please open a GitHub Discussion instead)
debian-11, debian-12
salt --versions-report output
salt --versions-report Salt Version: Salt: 3007.13 Python Version: Python: 3.10.19 (main, Feb 5 2026, 07:05:38) [GCC 11.2.0] Dependency Versions: cffi: 2.0.0 cherrypy: unknown cryptography: 42.0.5 dateutil: 2.8.2 docker-py: Not Installed gitdb: Not Installed gitpython: Not Installed Jinja2: 3.1.6 libgit2: 1.9.1 looseversion: 1.3.0 M2Crypto: Not Installed Mako: Not Installed msgpack: 1.0.7 msgpack-pure: Not Installed mysql-python: Not Installed packaging: 24.0 pycparser: 2.21 pycrypto: Not Installed pycryptodome: 3.19.1 pygit2: 1.18.2 python-gnupg: 0.5.2 PyYAML: 6.0.1 PyZMQ: 25.1.2 relenv: 0.22.3 smmap: Not Installed timelib: 0.3.0 Tornado: 6.5.4 ZMQ: 4.3.4 Salt Extensions: saltext.vault: 1.5.0 Salt Package Information: Package Type: onedir System Versions: dist: debian 12.13 bookworm locale: utf-8 machine: x86_64 release: 6.12.73+deb12-amd64 system: Linux version: Debian GNU/Linux 12.13 bookworm