pg.ddx.io pgsql-hackers@postgresql.org mailing list archive
help / color / mirror / Atom feed From: Dmitry Dolgov <9erthalion6@gmail.com>
To: Laurenz Albe <laurenz.albe@cybertec.at>
Cc: Tom Lane <tgl@sss.pgh.pa.us>
Cc: jian he <jian.universality@gmail.com>
Cc: Joe Conway <mail@joeconway.com>
Cc: pgsql-hackers@postgresql.org
Subject: Re: System views for versions reporting
Date: Tue, 22 Sep 2026 16:28:14 +0200
Message-ID: <arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb> (raw )
In-Reply-To: <1b327a0634514f39590703831c355aa64f894e65.camel@cybertec.at >
References: <yewkpc65y5g6fjd3kge2jetge3q2625hz64mietmyoczhqkmpu@ltotskxk4ndk >
<vyejydf4qnamuyz4slawjqzuhl3kgzfzgrtruwiuse2v6xitaa@ejvkxapdvqh5 >
<a7d6f24f338149a0abfe058d7f5be5bbf4a7cd67.camel@cybertec.at >
<jx5ozoohe653lf2f7p4j65b76pikqymdunpopjkeznfdzwgokv@bt43jrh226ee >
<xzbehdw5d7caffbvwfjhrmmqigmrha2qx7krshoivbr7dgcjd6@5enodmbfc5sz >
<d7d0315b35a5f71660b1b40fa1f5c3194d78dad8.camel@cybertec.at >
<gpniobijngfa4ibmsqe6ts3plfn7b7mzvzriiglak73x5elw4e@3ohzphiznekv >
<93754df439f9bb467fb5ee75e1113358f8295f91.camel@cybertec.at >
<hxoniue6zwezas2bnch63bljylhueixabqhshvot4lfbsecxjx@xa4udo2x4hmq >
<1b327a0634514f39590703831c355aa64f894e65.camel@cybertec.at >
> On Thu, Nov 27, 2025 at 03:27:21PM +0100, Laurenz Albe wrote:
> Thanks, the patch looks good now.
>
> There is one tiny thing that I noticed only now, sorry:
>
> > --- a/src/backend/utils/misc/Makefile
> > +++ b/src/backend/utils/misc/Makefile
> > @@ -32,7 +32,8 @@ OBJS = \
> > stack_depth.o \
> > superuser.o \
> > timeout.o \
> > - tzparser.o
> > + tzparser.o \
> > + system_version.o
>
> That looks like an alphabetically sorted list too, so you should preserve
> that ordering.
>
> Anyway, I'll set this patch "ready for committer".
>
> I am not sure if this reduced form (no report on zstd, lz4, openssl,
> zlib etc.) is good enough for release, but I'll leave that decision to a committer.
Delayed thanks.
I just have noticed that the patch is not applied cleanly for some time,
here is the rebase.
From 2d9a8898cecb310842fea4123f6835064357057a Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Mon, 21 Sep 2026 23:07:58 +0200
Subject: [PATCH v7 1/3] Add infrastructure for pg_system_versions view
Introduce a unified way of reporting versions (PostgreSQL itself, the
compiler, the host system, compile and runtime dependencies, etc.) via a
new system view pg_system_versions. This is going to be useful for
troubleshooting and should enhance bug reports, replacing manual
bug-prone collecting of the same information.
The view is backed by a hash table, that contains callbacks returning
version string for a particular component. The idea is to allow some
flexibility in reporting, making components responsible for how and when
the information is exposed.
---
doc/src/sgml/system-views.sgml | 65 ++++++++++++++
src/backend/catalog/system_views.sql | 8 ++
src/backend/utils/misc/Makefile | 1 +
src/backend/utils/misc/meson.build | 1 +
src/backend/utils/misc/system_version.c | 107 ++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 6 ++
src/include/utils/system_version.h | 38 +++++++++
src/test/regress/expected/rules.out | 8 ++
src/tools/pgindent/typedefs.list | 2 +
9 files changed, 236 insertions(+)
create mode 100644 src/backend/utils/misc/system_version.c
create mode 100644 src/include/utils/system_version.h
diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 77202e2c765..dc535642357 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -211,6 +211,11 @@
<entry>extended planner statistics for expressions</entry>
</row>
+ <row>
+ <entry><link linkend="view-pg-system-versions"><structname>pg_system_versions</structname></link></entry>
+ <entry>system versions</entry>
+ </row>
+
<row>
<entry><link linkend="view-pg-tables"><structname>pg_tables</structname></link></entry>
<entry>tables</entry>
@@ -5158,6 +5163,66 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
</sect1>
+ <sect1 id="view-pg-system-versions">
+ <title><structname>pg_system_versions</structname></title>
+
+ <indexterm zone="view-pg-system-versions">
+ <primary>pg_system_versions</primary>
+ </indexterm>
+
+ <para>
+ The view <structname>pg_system_versions</structname> provides description
+ about the versions of various system components, e.g. PostgreSQL itself,
+ the compiler used to build it, dependencies.
+ </para>
+
+ <table>
+ <title><structname>pg_system_versions</structname> Columns</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ Column Type
+ </para>
+ <para>
+ Description
+ </para></entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>name</structfield> <type>text</type>
+ </para>
+ <para>
+ Component name
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>version</structfield> <type>text</type>
+ </para>
+ <para>
+ Component version
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>type</structfield> <type>text</type>
+ </para>
+ <para>
+ Component type (Compile Time or Run Time)
+ </para></entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
+
<sect1 id="view-pg-tables">
<title><structname>pg_tables</structname></title>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index ad340887f54..fb0bc0981b8 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1569,3 +1569,11 @@ CREATE VIEW pg_aios AS
SELECT * FROM pg_get_aios();
REVOKE ALL ON pg_aios FROM PUBLIC;
GRANT SELECT ON pg_aios TO pg_read_all_stats;
+
+CREATE VIEW pg_system_versions AS
+ SELECT
+ name, version,
+ CASE type WHEN 0 THEN 'Compile Time'
+ WHEN 1 THEN 'Run Time'
+ END AS "type"
+ FROM pg_get_system_versions();
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index f142d17178b..03971b43cf4 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -31,6 +31,7 @@ OBJS = \
sampling.o \
stack_depth.o \
superuser.o \
+ system_version.o \
timeout.o \
tzparser.o
diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build
index 232e74d0af9..3eb7503af7f 100644
--- a/src/backend/utils/misc/meson.build
+++ b/src/backend/utils/misc/meson.build
@@ -16,6 +16,7 @@ backend_sources += files(
'sampling.c',
'stack_depth.c',
'superuser.c',
+ 'system_version.c',
'timeout.c',
'tzparser.c',
)
diff --git a/src/backend/utils/misc/system_version.c b/src/backend/utils/misc/system_version.c
new file mode 100644
index 00000000000..d80c53fcc7b
--- /dev/null
+++ b/src/backend/utils/misc/system_version.c
@@ -0,0 +1,107 @@
+/*------------------------------------------------------------------------
+ *
+ * system_version.c
+ * Functions for reporting version of system components.
+ *
+ * A system component is defined very broadly here, it might be the PostgreSQL
+ * core itself, the compiler, the host system, any dependency that is used at
+ * compile time or run time.
+ *
+ * Version reporting is implemented via a hash table containing the component's
+ * name as a key and the callback to fetch the version string. Every component
+ * can register such a callback during initialization and is responsible for
+ * exposing its own information. The idea is that storing a callback instead of
+ * a version string directly allows for more flexibility about how and when the
+ * information could be reported.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/misc/system_version.c
+ *
+ *------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "utils/builtins.h"
+#include "utils/hsearch.h"
+#include "utils/system_version.h"
+#include "utils/tuplestore.h"
+
+static HTAB *versions = NULL;
+
+void
+add_system_version(const char *name, SystemVersionCB cb, VersionType type)
+{
+ SystemVersion *hentry;
+ const char *key;
+ bool found;
+
+ if (!versions)
+ {
+ HASHCTL ctl;
+
+ ctl.keysize = NAMEDATALEN;
+ ctl.entrysize = sizeof(SystemVersion);
+
+ versions = hash_create("System versions table",
+ MAX_SYSTEM_VERSIONS,
+ &ctl,
+ HASH_ELEM | HASH_STRINGS);
+ }
+
+ key = pstrdup(name);
+ Assert(strlen(key) < NAMEDATALEN);
+
+ hentry = (SystemVersion *) hash_search(versions, key,
+ HASH_ENTER, &found);
+
+ /* Duplicated entries are not expected */
+ Assert(!found);
+
+ hentry->callback = cb;
+ hentry->type = type;
+}
+
+/*
+ * pg_get_system_versions
+ *
+ * List information about system versions.
+ */
+Datum
+pg_get_system_versions(PG_FUNCTION_ARGS)
+{
+#define PG_GET_SYS_VERSIONS_COLS 3
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ HASH_SEQ_STATUS status;
+ SystemVersion *hentry;
+
+ /* Build tuplestore to hold the result rows */
+ InitMaterializedSRF(fcinfo, 0);
+
+ if (!versions)
+ return (Datum) 0;
+
+ hash_seq_init(&status, versions);
+ while ((hentry = (SystemVersion *) hash_seq_search(&status)) != NULL)
+ {
+ Datum values[PG_GET_SYS_VERSIONS_COLS] = {0};
+ bool nulls[PG_GET_SYS_VERSIONS_COLS] = {0};
+ bool available = false;
+ const char *version = hentry->callback(&available);
+
+ if (!available)
+ continue;
+
+ values[0] = CStringGetTextDatum(hentry->name);
+ values[1] = CStringGetTextDatum(version);
+ values[2] = Int32GetDatum(hentry->type);
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+ }
+
+ return (Datum) 0;
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f46427258e3..99b8b01a012 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12778,4 +12778,10 @@
proname => 'hashoid8extended', prorettype => 'int8',
proargtypes => 'oid8 int8', prosrc => 'hashoid8extended' },
+{ oid => '9432', descr => 'describe system verions',
+ proname => 'pg_get_system_versions', procost => '10', prorows => '10',
+ proretset => 't', provolatile => 'v', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,text,int8}',
+ proargmodes => '{o,o,o}', proargnames => '{name,version,type}',
+ prosrc => 'pg_get_system_versions' },
]
diff --git a/src/include/utils/system_version.h b/src/include/utils/system_version.h
new file mode 100644
index 00000000000..18cb673d4ca
--- /dev/null
+++ b/src/include/utils/system_version.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ * system_version.h
+ * Definitions related to system versions reporting
+ *
+ * Copyright (c) 2001-2024, PostgreSQL Global Development Group
+ *
+ * src/include/utils/system_version.h
+ * ----------
+ */
+
+#ifndef SYSTEM_VERSION_H
+#define SYSTEM_VERSION_H
+
+#define MAX_SYSTEM_VERSIONS 100
+
+typedef enum VersionType
+{
+ CompileTime,
+ RunTime,
+} VersionType;
+
+/*
+ * Callback to return version string of a system component.
+ * The version might be not available, what is indicated via the argument.
+ */
+typedef const char *(*SystemVersionCB) (bool *available);
+
+typedef struct SystemVersion
+{
+ char name[NAMEDATALEN]; /* Unique component name, used as a key
+ * for versions HTAB */
+ VersionType type;
+ SystemVersionCB callback; /* Callback to fetch the version string */
+} SystemVersion;
+
+void add_system_version(const char *name, SystemVersionCB cb, VersionType type);
+
+#endif /* SYSTEM_VERSION_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 4a8cc759d7b..ee297499bea 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2839,6 +2839,14 @@ pg_stats_ext_exprs| SELECT cn.nspname AS schemaname,
JOIN LATERAL ( SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr,
unnest(sd.stxdexpr) AS a) stat ON ((stat.expr IS NOT NULL)))
WHERE (pg_has_role(c.relowner, 'USAGE'::text) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid))));
+pg_system_versions| SELECT name,
+ version,
+ CASE type
+ WHEN 0 THEN 'Compile Time'::text
+ WHEN 1 THEN 'Run Time'::text
+ ELSE NULL::text
+ END AS type
+ FROM pg_get_system_versions() pg_get_system_versions(name, version, type);
pg_tables| SELECT n.nspname AS schemaname,
c.relname AS tablename,
pg_get_userbyid(c.relowner) AS tableowner,
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 5d432074c2c..7159c1b7ae3 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3064,6 +3064,7 @@ SysloggerStartupData
SystemRowsSamplerData
SystemSamplerData
SystemTimeSamplerData
+SystemVersion
TAPtype
TAR_MEMBER
TBMIterateResult
@@ -4424,6 +4425,7 @@ varlena
vartag_external
vbits
verifier_context
+VersionType
walrcv_alter_slot_fn
walrcv_check_conninfo_fn
walrcv_connect_fn
base-commit: d39fda1cc404834781458376173e5293f870e83a
--
2.55.0
From dc95337047e6d378c14b464f0a1558497ae3e4f4 Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Wed, 26 Nov 2025 20:05:20 +0100
Subject: [PATCH v7 2/3] Add core versions to pg_system_versions
Populate pg_system_versions with a set of core versions: host system
architecture, ICU version, glibc version, PostgreSQL itself and compiler
which was used to build everything. Register the core versions at the
backend startup.
select * from pg_system_versions;
name | version | type
----------+--------------+--------------
Arch | x86_64-linux | Compile Time
ICU | 15.1 | Run Time
Core | 18devel | Compile Time
Compiler | gcc-14.0.1 | Compile Time
Glibc | 2.40 | Run Time
---
configure | 12 +++++
configure.ac | 4 ++
meson.build | 4 ++
src/backend/tcop/postgres.c | 12 +++++
src/backend/utils/misc/system_version.c | 72 +++++++++++++++++++++++++
src/include/pg_config.h.in | 4 ++
src/include/utils/system_version.h | 1 +
src/test/regress/expected/sysviews.out | 10 ++++
src/test/regress/sql/sysviews.sql | 6 +++
9 files changed, 125 insertions(+)
diff --git a/configure b/configure
index d42a7a794ff..5e834f5938c 100755
--- a/configure
+++ b/configure
@@ -19722,6 +19722,18 @@ else
fi
+cat >>confdefs.h <<_ACEOF
+#define PG_CC_STR "$cc_string"
+_ACEOF
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define PG_ARCH_STR "$host"
+_ACEOF
+
+
+
cat >>confdefs.h <<_ACEOF
#define PG_VERSION_STR "PostgreSQL $PG_VERSION on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"
_ACEOF
diff --git a/configure.ac b/configure.ac
index a331749fcb5..05fd396c89d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2541,6 +2541,10 @@ else
cc_string=$CC
fi
+AC_DEFINE_UNQUOTED(PG_CC_STR, ["$cc_string"], [C compiler version])
+
+AC_DEFINE_UNQUOTED(PG_ARCH_STR, ["$host"], [Platform])
+
AC_DEFINE_UNQUOTED(PG_VERSION_STR,
["PostgreSQL $PG_VERSION on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"],
[A string containing the version number, platform, and C compiler])
diff --git a/meson.build b/meson.build
index f4cde249242..a1d8f141f00 100644
--- a/meson.build
+++ b/meson.build
@@ -3292,6 +3292,10 @@ cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
cdata.set_quoted('DLSUFFIX', dlsuffix)
+cdata.set_quoted('PG_CC_STR', '@0@-@1@'.format(cc.get_id(), cc.version()))
+
+cdata.set_quoted('PG_ARCH_STR', '@0@-@1@'.format(
+ host_machine.cpu_family(), host_system))
# built later than the rest of the version metadata, we need SIZEOF_VOID_P
cdata.set_quoted('PG_VERSION_STR',
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index b6bdfe213fe..ede6b5b59e4 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -86,6 +86,7 @@
#include "utils/timeout.h"
#include "utils/timestamp.h"
#include "utils/varlena.h"
+#include "utils/system_version.h"
/* ----------------
* global variables
@@ -199,6 +200,7 @@ static void report_recovery_conflict(RecoveryConflictReason reason);
static void log_disconnections(int code, Datum arg);
static void enable_statement_timeout(void);
static void disable_statement_timeout(void);
+static void register_system_versions(void);
/* ----------------------------------------------------------------
@@ -4489,6 +4491,9 @@ PostgresMain(const char *dbname, const char *username)
*/
BeginReportingGUCOptions();
+ /* Prepare information for reporting versions and libraries. */
+ register_system_versions();
+
/*
* Also set up handler to log session end; we have to wait till now to be
* sure Log_disconnections has its final value.
@@ -5408,3 +5413,10 @@ disable_statement_timeout(void)
if (get_timeout_active(STATEMENT_TIMEOUT))
disable_timeout(STATEMENT_TIMEOUT, false);
}
+
+static void
+register_system_versions()
+{
+ /* Set up reporting of core versions. */
+ register_core_versions();
+}
diff --git a/src/backend/utils/misc/system_version.c b/src/backend/utils/misc/system_version.c
index d80c53fcc7b..3bfd1318320 100644
--- a/src/backend/utils/misc/system_version.c
+++ b/src/backend/utils/misc/system_version.c
@@ -25,6 +25,14 @@
*/
#include "postgres.h"
+#ifdef USE_ICU
+#include <unicode/uchar.h>
+#endif
+
+#ifdef __GLIBC__
+#include <gnu/libc-version.h>
+#endif
+
#include "funcapi.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
@@ -66,6 +74,70 @@ add_system_version(const char *name, SystemVersionCB cb, VersionType type)
hentry->type = type;
}
+static const char *
+core_get_version(bool *available)
+{
+ *available = true;
+ return (const char *) psprintf("%s", PG_VERSION);
+}
+
+static const char *
+core_get_arch(bool *available)
+{
+ *available = true;
+ return (const char *) psprintf("%s", PG_ARCH_STR);
+}
+
+static const char *
+core_get_compiler(bool *available)
+{
+ *available = true;
+ return (const char *) psprintf("%s", PG_CC_STR);
+}
+
+#ifdef USE_ICU
+static const char *
+icu_get_version(bool *available)
+{
+ UVersionInfo UCDVersion;
+ char *version = palloc0(U_MAX_VERSION_STRING_LENGTH);
+
+ *available = true;
+ u_getUnicodeVersion(UCDVersion);
+ u_versionToString(UCDVersion, version);
+ return (const char *) version;
+}
+#endif
+
+#ifdef __GLIBC__
+static const char *
+glibc_get_version(bool *available)
+{
+ *available = true;
+ return (const char *) gnu_get_libc_version();
+}
+#endif
+
+/*
+ * Register versions that describe core components and do not correspond to any
+ * individual component.
+ */
+void
+register_core_versions()
+{
+ add_system_version("Core", core_get_version, CompileTime);
+ add_system_version("Arch", core_get_arch, CompileTime);
+ add_system_version("Compiler", core_get_compiler, CompileTime);
+
+#ifdef USE_ICU
+ add_system_version("ICU", icu_get_version, RunTime);
+#endif
+
+#ifdef __GLIBC__
+ add_system_version("Glibc", glibc_get_version, RunTime);
+#endif
+}
+
/*
* pg_get_system_versions
*
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 661c4a9b168..1bea53c05bd 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -617,6 +617,10 @@
/* PostgreSQL version as a number */
#undef PG_VERSION_NUM
+#undef PG_CC_STR
+
+#undef PG_ARCH_STR
+
/* A string containing the version number, platform, and C compiler */
#undef PG_VERSION_STR
diff --git a/src/include/utils/system_version.h b/src/include/utils/system_version.h
index 18cb673d4ca..49685b6809f 100644
--- a/src/include/utils/system_version.h
+++ b/src/include/utils/system_version.h
@@ -34,5 +34,6 @@ typedef struct SystemVersion
} SystemVersion;
void add_system_version(const char *name, SystemVersionCB cb, VersionType type);
+extern void register_core_versions(void);
#endif /* SYSTEM_VERSION_H */
diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out
index 1e327c2afa4..a5668288ed7 100644
--- a/src/test/regress/expected/sysviews.out
+++ b/src/test/regress/expected/sysviews.out
@@ -241,3 +241,13 @@ select * from pg_timezone_abbrevs where abbrev = 'LMT';
LMT | @ 7 hours 52 mins 58 secs ago | f
(1 row)
+-- Check that the pg_system_versions contains something. Three core versions
+-- should be present: architecture, core and compiler and glibc. More records
+-- may be present depending on the build configuration (e.g. with ICU, GlibC or
+-- JIT support).
+select exists (table pg_system_versions);
+ exists
+--------
+ t
+(1 row)
+
diff --git a/src/test/regress/sql/sysviews.sql b/src/test/regress/sql/sysviews.sql
index 507e400ad4a..7d504f9647e 100644
--- a/src/test/regress/sql/sysviews.sql
+++ b/src/test/regress/sql/sysviews.sql
@@ -104,3 +104,9 @@ select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs;
-- One specific case we can check without much fear of breakage
-- is the historical local-mean-time value used for America/Los_Angeles.
select * from pg_timezone_abbrevs where abbrev = 'LMT';
+
+-- Check that the pg_system_versions contains something. Three core versions
+-- should be present: architecture, core and compiler and glibc. More records
+-- may be present depending on the build configuration (e.g. with ICU, GlibC or
+-- JIT support).
+select exists (table pg_system_versions);
--
2.55.0
From 1f027c0f6f918a35efbf56c295c5133c5c4b5187 Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Sat, 5 Oct 2024 18:31:36 +0200
Subject: [PATCH v7 3/3] Add JIT provider version to pg_system_versions
Populate pg_system_versions with the JIT provider version. To actually
fetch the version, extend the JIT provider callbacks with the
get_version method. For LLVM provider llvm_version will be used, which
utilizes C-API LLVMGetVersion, available since LLVM 16.
The JIT provider will be initialized, when a first expression will be
compiled. For reporting purposes it's too late, thus register the
version at the backend startup, right after the core versions.
---
src/backend/jit/jit.c | 24 ++++++++++++++++++++++++
src/backend/jit/llvm/llvmjit.c | 17 +++++++++++++++++
src/backend/tcop/postgres.c | 7 +++++++
src/backend/utils/misc/system_version.c | 7 +++++++
src/include/jit/jit.h | 9 +++++++++
src/include/jit/llvmjit.h | 2 ++
6 files changed, 66 insertions(+)
diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index 3dc82b7b268..1714f310125 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -189,3 +189,27 @@ InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
INSTR_TIME_ADD(dst->optimization_counter, add->optimization_counter);
INSTR_TIME_ADD(dst->emission_counter, add->emission_counter);
}
+
+/*
+ * Callback for add_system_version, returns JIT provider's version string and
+ * reports if it's not available.
+ */
+const char *
+jit_get_version(bool *available)
+{
+ const char *version;
+
+ if (provider_init())
+ {
+ version = provider.get_version();
+
+ if (version)
+ {
+ *available = true;
+ return version;
+ }
+ }
+
+ *available = false;
+ return "";
+}
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 957ab4751b5..8165898dd29 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -154,6 +154,7 @@ _PG_jit_provider_init(JitProviderCallbacks *cb)
cb->reset_after_error = llvm_reset_after_error;
cb->release_context = llvm_release_context;
cb->compile_expr = llvm_compile_expr;
+ cb->get_version = llvm_version;
}
@@ -1287,3 +1288,19 @@ ResOwnerReleaseJitContext(Datum res)
context->resowner = NULL;
jit_release_context(&context->base);
}
+
+const char *
+llvm_version()
+{
+#if LLVM_VERSION_MAJOR > 15
+ unsigned int major,
+ minor,
+ patch;
+
+ LLVMGetVersion(&major, &minor, &patch);
+
+ return (const char *) psprintf("%d.%d.%d", major, minor, patch);
+#else
+ return NULL;
+#endif
+}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index ede6b5b59e4..c5af184d910 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -5419,4 +5419,11 @@ register_system_versions()
{
/* Set up reporting of core versions. */
register_core_versions();
+
+ /*
+ * Set up reporting for JIT provider version. JIT provider initialization
+ * happens when the first expression is getting compiled, which is too
+ * late. Thus register the callback here instead.
+ */
+ jit_register_version();
}
diff --git a/src/backend/utils/misc/system_version.c b/src/backend/utils/misc/system_version.c
index 3bfd1318320..207b8d87703 100644
--- a/src/backend/utils/misc/system_version.c
+++ b/src/backend/utils/misc/system_version.c
@@ -34,6 +34,7 @@
#endif
#include "funcapi.h"
+#include "jit/jit.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/system_version.h"
@@ -118,6 +119,12 @@ glibc_get_version(bool *available)
}
#endif
+void
+jit_register_version(void)
+{
+ add_system_version("LLVM", jit_get_version, RunTime);
+}
+
/*
* Register versions that describe core components and do not correspond to any
* individual component.
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index e2baa4c2ed0..6e0e5114247 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -70,12 +70,14 @@ typedef void (*JitProviderResetAfterErrorCB) (void);
typedef void (*JitProviderReleaseContextCB) (JitContext *context);
struct ExprState;
typedef bool (*JitProviderCompileExprCB) (struct ExprState *state);
+typedef const char *(*JitProviderVersion) (void);
struct JitProviderCallbacks
{
JitProviderResetAfterErrorCB reset_after_error;
JitProviderReleaseContextCB release_context;
JitProviderCompileExprCB compile_expr;
+ JitProviderVersion get_version;
};
@@ -102,5 +104,12 @@ extern void jit_release_context(JitContext *context);
extern bool jit_compile_expr(struct ExprState *state);
extern void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add);
+/*
+ * Callback for add_system_version, get the provider's version string. The flag
+ * indicating availability is passed as an argument.
+ */
+extern const char *jit_get_version(bool *available);
+
+extern void jit_register_version(void);
#endif /* JIT_H */
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index a647dd65ba2..632d7e2f142 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -145,6 +145,8 @@ extern LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r);
extern LLVMOrcObjectLayerRef LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(LLVMOrcExecutionSessionRef ES);
#endif
+extern const char* llvm_version(void);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
--
2.55.0
Attachments:
[text/plain] v7-0001-Add-infrastructure-for-pg_system_versions-view.patch (11.5K, ../arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb/2-v7-0001-Add-infrastructure-for-pg_system_versions-view.patch)
download | inline diff:
From 2d9a8898cecb310842fea4123f6835064357057a Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Mon, 21 Sep 2026 23:07:58 +0200
Subject: [PATCH v7 1/3] Add infrastructure for pg_system_versions view
Introduce a unified way of reporting versions (PostgreSQL itself, the
compiler, the host system, compile and runtime dependencies, etc.) via a
new system view pg_system_versions. This is going to be useful for
troubleshooting and should enhance bug reports, replacing manual
bug-prone collecting of the same information.
The view is backed by a hash table, that contains callbacks returning
version string for a particular component. The idea is to allow some
flexibility in reporting, making components responsible for how and when
the information is exposed.
---
doc/src/sgml/system-views.sgml | 65 ++++++++++++++
src/backend/catalog/system_views.sql | 8 ++
src/backend/utils/misc/Makefile | 1 +
src/backend/utils/misc/meson.build | 1 +
src/backend/utils/misc/system_version.c | 107 ++++++++++++++++++++++++
src/include/catalog/pg_proc.dat | 6 ++
src/include/utils/system_version.h | 38 +++++++++
src/test/regress/expected/rules.out | 8 ++
src/tools/pgindent/typedefs.list | 2 +
9 files changed, 236 insertions(+)
create mode 100644 src/backend/utils/misc/system_version.c
create mode 100644 src/include/utils/system_version.h
diff --git a/doc/src/sgml/system-views.sgml b/doc/src/sgml/system-views.sgml
index 77202e2c765..dc535642357 100644
--- a/doc/src/sgml/system-views.sgml
+++ b/doc/src/sgml/system-views.sgml
@@ -211,6 +211,11 @@
<entry>extended planner statistics for expressions</entry>
</row>
+ <row>
+ <entry><link linkend="view-pg-system-versions"><structname>pg_system_versions</structname></link></entry>
+ <entry>system versions</entry>
+ </row>
+
<row>
<entry><link linkend="view-pg-tables"><structname>pg_tables</structname></link></entry>
<entry>tables</entry>
@@ -5158,6 +5163,66 @@ SELECT * FROM pg_locks pl LEFT JOIN pg_prepared_xacts ppx
</sect1>
+ <sect1 id="view-pg-system-versions">
+ <title><structname>pg_system_versions</structname></title>
+
+ <indexterm zone="view-pg-system-versions">
+ <primary>pg_system_versions</primary>
+ </indexterm>
+
+ <para>
+ The view <structname>pg_system_versions</structname> provides description
+ about the versions of various system components, e.g. PostgreSQL itself,
+ the compiler used to build it, dependencies.
+ </para>
+
+ <table>
+ <title><structname>pg_system_versions</structname> Columns</title>
+ <tgroup cols="1">
+ <thead>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ Column Type
+ </para>
+ <para>
+ Description
+ </para></entry>
+ </row>
+ </thead>
+
+ <tbody>
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>name</structfield> <type>text</type>
+ </para>
+ <para>
+ Component name
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>version</structfield> <type>text</type>
+ </para>
+ <para>
+ Component version
+ </para></entry>
+ </row>
+
+ <row>
+ <entry role="catalog_table_entry"><para role="column_definition">
+ <structfield>type</structfield> <type>text</type>
+ </para>
+ <para>
+ Component type (Compile Time or Run Time)
+ </para></entry>
+ </row>
+
+ </tbody>
+ </tgroup>
+ </table>
+ </sect1>
+
<sect1 id="view-pg-tables">
<title><structname>pg_tables</structname></title>
diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql
index ad340887f54..fb0bc0981b8 100644
--- a/src/backend/catalog/system_views.sql
+++ b/src/backend/catalog/system_views.sql
@@ -1569,3 +1569,11 @@ CREATE VIEW pg_aios AS
SELECT * FROM pg_get_aios();
REVOKE ALL ON pg_aios FROM PUBLIC;
GRANT SELECT ON pg_aios TO pg_read_all_stats;
+
+CREATE VIEW pg_system_versions AS
+ SELECT
+ name, version,
+ CASE type WHEN 0 THEN 'Compile Time'
+ WHEN 1 THEN 'Run Time'
+ END AS "type"
+ FROM pg_get_system_versions();
diff --git a/src/backend/utils/misc/Makefile b/src/backend/utils/misc/Makefile
index f142d17178b..03971b43cf4 100644
--- a/src/backend/utils/misc/Makefile
+++ b/src/backend/utils/misc/Makefile
@@ -31,6 +31,7 @@ OBJS = \
sampling.o \
stack_depth.o \
superuser.o \
+ system_version.o \
timeout.o \
tzparser.o
diff --git a/src/backend/utils/misc/meson.build b/src/backend/utils/misc/meson.build
index 232e74d0af9..3eb7503af7f 100644
--- a/src/backend/utils/misc/meson.build
+++ b/src/backend/utils/misc/meson.build
@@ -16,6 +16,7 @@ backend_sources += files(
'sampling.c',
'stack_depth.c',
'superuser.c',
+ 'system_version.c',
'timeout.c',
'tzparser.c',
)
diff --git a/src/backend/utils/misc/system_version.c b/src/backend/utils/misc/system_version.c
new file mode 100644
index 00000000000..d80c53fcc7b
--- /dev/null
+++ b/src/backend/utils/misc/system_version.c
@@ -0,0 +1,107 @@
+/*------------------------------------------------------------------------
+ *
+ * system_version.c
+ * Functions for reporting version of system components.
+ *
+ * A system component is defined very broadly here, it might be the PostgreSQL
+ * core itself, the compiler, the host system, any dependency that is used at
+ * compile time or run time.
+ *
+ * Version reporting is implemented via a hash table containing the component's
+ * name as a key and the callback to fetch the version string. Every component
+ * can register such a callback during initialization and is responsible for
+ * exposing its own information. The idea is that storing a callback instead of
+ * a version string directly allows for more flexibility about how and when the
+ * information could be reported.
+ *
+ * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/misc/system_version.c
+ *
+ *------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "funcapi.h"
+#include "utils/builtins.h"
+#include "utils/hsearch.h"
+#include "utils/system_version.h"
+#include "utils/tuplestore.h"
+
+static HTAB *versions = NULL;
+
+void
+add_system_version(const char *name, SystemVersionCB cb, VersionType type)
+{
+ SystemVersion *hentry;
+ const char *key;
+ bool found;
+
+ if (!versions)
+ {
+ HASHCTL ctl;
+
+ ctl.keysize = NAMEDATALEN;
+ ctl.entrysize = sizeof(SystemVersion);
+
+ versions = hash_create("System versions table",
+ MAX_SYSTEM_VERSIONS,
+ &ctl,
+ HASH_ELEM | HASH_STRINGS);
+ }
+
+ key = pstrdup(name);
+ Assert(strlen(key) < NAMEDATALEN);
+
+ hentry = (SystemVersion *) hash_search(versions, key,
+ HASH_ENTER, &found);
+
+ /* Duplicated entries are not expected */
+ Assert(!found);
+
+ hentry->callback = cb;
+ hentry->type = type;
+}
+
+/*
+ * pg_get_system_versions
+ *
+ * List information about system versions.
+ */
+Datum
+pg_get_system_versions(PG_FUNCTION_ARGS)
+{
+#define PG_GET_SYS_VERSIONS_COLS 3
+ ReturnSetInfo *rsinfo = (ReturnSetInfo *) fcinfo->resultinfo;
+ HASH_SEQ_STATUS status;
+ SystemVersion *hentry;
+
+ /* Build tuplestore to hold the result rows */
+ InitMaterializedSRF(fcinfo, 0);
+
+ if (!versions)
+ return (Datum) 0;
+
+ hash_seq_init(&status, versions);
+ while ((hentry = (SystemVersion *) hash_seq_search(&status)) != NULL)
+ {
+ Datum values[PG_GET_SYS_VERSIONS_COLS] = {0};
+ bool nulls[PG_GET_SYS_VERSIONS_COLS] = {0};
+ bool available = false;
+ const char *version = hentry->callback(&available);
+
+ if (!available)
+ continue;
+
+ values[0] = CStringGetTextDatum(hentry->name);
+ values[1] = CStringGetTextDatum(version);
+ values[2] = Int32GetDatum(hentry->type);
+
+ tuplestore_putvalues(rsinfo->setResult, rsinfo->setDesc, values, nulls);
+ }
+
+ return (Datum) 0;
+}
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index f46427258e3..99b8b01a012 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -12778,4 +12778,10 @@
proname => 'hashoid8extended', prorettype => 'int8',
proargtypes => 'oid8 int8', prosrc => 'hashoid8extended' },
+{ oid => '9432', descr => 'describe system verions',
+ proname => 'pg_get_system_versions', procost => '10', prorows => '10',
+ proretset => 't', provolatile => 'v', prorettype => 'record',
+ proargtypes => '', proallargtypes => '{text,text,int8}',
+ proargmodes => '{o,o,o}', proargnames => '{name,version,type}',
+ prosrc => 'pg_get_system_versions' },
]
diff --git a/src/include/utils/system_version.h b/src/include/utils/system_version.h
new file mode 100644
index 00000000000..18cb673d4ca
--- /dev/null
+++ b/src/include/utils/system_version.h
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ * system_version.h
+ * Definitions related to system versions reporting
+ *
+ * Copyright (c) 2001-2024, PostgreSQL Global Development Group
+ *
+ * src/include/utils/system_version.h
+ * ----------
+ */
+
+#ifndef SYSTEM_VERSION_H
+#define SYSTEM_VERSION_H
+
+#define MAX_SYSTEM_VERSIONS 100
+
+typedef enum VersionType
+{
+ CompileTime,
+ RunTime,
+} VersionType;
+
+/*
+ * Callback to return version string of a system component.
+ * The version might be not available, what is indicated via the argument.
+ */
+typedef const char *(*SystemVersionCB) (bool *available);
+
+typedef struct SystemVersion
+{
+ char name[NAMEDATALEN]; /* Unique component name, used as a key
+ * for versions HTAB */
+ VersionType type;
+ SystemVersionCB callback; /* Callback to fetch the version string */
+} SystemVersion;
+
+void add_system_version(const char *name, SystemVersionCB cb, VersionType type);
+
+#endif /* SYSTEM_VERSION_H */
diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out
index 4a8cc759d7b..ee297499bea 100644
--- a/src/test/regress/expected/rules.out
+++ b/src/test/regress/expected/rules.out
@@ -2839,6 +2839,14 @@ pg_stats_ext_exprs| SELECT cn.nspname AS schemaname,
JOIN LATERAL ( SELECT unnest(pg_get_statisticsobjdef_expressions(s.oid)) AS expr,
unnest(sd.stxdexpr) AS a) stat ON ((stat.expr IS NOT NULL)))
WHERE (pg_has_role(c.relowner, 'USAGE'::text) AND ((c.relrowsecurity = false) OR (NOT row_security_active(c.oid))));
+pg_system_versions| SELECT name,
+ version,
+ CASE type
+ WHEN 0 THEN 'Compile Time'::text
+ WHEN 1 THEN 'Run Time'::text
+ ELSE NULL::text
+ END AS type
+ FROM pg_get_system_versions() pg_get_system_versions(name, version, type);
pg_tables| SELECT n.nspname AS schemaname,
c.relname AS tablename,
pg_get_userbyid(c.relowner) AS tableowner,
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 5d432074c2c..7159c1b7ae3 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3064,6 +3064,7 @@ SysloggerStartupData
SystemRowsSamplerData
SystemSamplerData
SystemTimeSamplerData
+SystemVersion
TAPtype
TAR_MEMBER
TBMIterateResult
@@ -4424,6 +4425,7 @@ varlena
vartag_external
vbits
verifier_context
+VersionType
walrcv_alter_slot_fn
walrcv_check_conninfo_fn
walrcv_connect_fn
base-commit: d39fda1cc404834781458376173e5293f870e83a
--
2.55.0
[text/plain] v7-0002-Add-core-versions-to-pg_system_versions.patch (8.3K, ../arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb/3-v7-0002-Add-core-versions-to-pg_system_versions.patch)
download | inline diff:
From dc95337047e6d378c14b464f0a1558497ae3e4f4 Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Wed, 26 Nov 2025 20:05:20 +0100
Subject: [PATCH v7 2/3] Add core versions to pg_system_versions
Populate pg_system_versions with a set of core versions: host system
architecture, ICU version, glibc version, PostgreSQL itself and compiler
which was used to build everything. Register the core versions at the
backend startup.
select * from pg_system_versions;
name | version | type
----------+--------------+--------------
Arch | x86_64-linux | Compile Time
ICU | 15.1 | Run Time
Core | 18devel | Compile Time
Compiler | gcc-14.0.1 | Compile Time
Glibc | 2.40 | Run Time
---
configure | 12 +++++
configure.ac | 4 ++
meson.build | 4 ++
src/backend/tcop/postgres.c | 12 +++++
src/backend/utils/misc/system_version.c | 72 +++++++++++++++++++++++++
src/include/pg_config.h.in | 4 ++
src/include/utils/system_version.h | 1 +
src/test/regress/expected/sysviews.out | 10 ++++
src/test/regress/sql/sysviews.sql | 6 +++
9 files changed, 125 insertions(+)
diff --git a/configure b/configure
index d42a7a794ff..5e834f5938c 100755
--- a/configure
+++ b/configure
@@ -19722,6 +19722,18 @@ else
fi
+cat >>confdefs.h <<_ACEOF
+#define PG_CC_STR "$cc_string"
+_ACEOF
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define PG_ARCH_STR "$host"
+_ACEOF
+
+
+
cat >>confdefs.h <<_ACEOF
#define PG_VERSION_STR "PostgreSQL $PG_VERSION on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"
_ACEOF
diff --git a/configure.ac b/configure.ac
index a331749fcb5..05fd396c89d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2541,6 +2541,10 @@ else
cc_string=$CC
fi
+AC_DEFINE_UNQUOTED(PG_CC_STR, ["$cc_string"], [C compiler version])
+
+AC_DEFINE_UNQUOTED(PG_ARCH_STR, ["$host"], [Platform])
+
AC_DEFINE_UNQUOTED(PG_VERSION_STR,
["PostgreSQL $PG_VERSION on $host, compiled by $cc_string, `expr $ac_cv_sizeof_void_p \* 8`-bit"],
[A string containing the version number, platform, and C compiler])
diff --git a/meson.build b/meson.build
index f4cde249242..a1d8f141f00 100644
--- a/meson.build
+++ b/meson.build
@@ -3292,6 +3292,10 @@ cdata.set('USE_@0@_SEMAPHORES'.format(sema_kind.to_upper()), 1)
cdata.set('MEMSET_LOOP_LIMIT', memset_loop_limit)
cdata.set_quoted('DLSUFFIX', dlsuffix)
+cdata.set_quoted('PG_CC_STR', '@0@-@1@'.format(cc.get_id(), cc.version()))
+
+cdata.set_quoted('PG_ARCH_STR', '@0@-@1@'.format(
+ host_machine.cpu_family(), host_system))
# built later than the rest of the version metadata, we need SIZEOF_VOID_P
cdata.set_quoted('PG_VERSION_STR',
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index b6bdfe213fe..ede6b5b59e4 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -86,6 +86,7 @@
#include "utils/timeout.h"
#include "utils/timestamp.h"
#include "utils/varlena.h"
+#include "utils/system_version.h"
/* ----------------
* global variables
@@ -199,6 +200,7 @@ static void report_recovery_conflict(RecoveryConflictReason reason);
static void log_disconnections(int code, Datum arg);
static void enable_statement_timeout(void);
static void disable_statement_timeout(void);
+static void register_system_versions(void);
/* ----------------------------------------------------------------
@@ -4489,6 +4491,9 @@ PostgresMain(const char *dbname, const char *username)
*/
BeginReportingGUCOptions();
+ /* Prepare information for reporting versions and libraries. */
+ register_system_versions();
+
/*
* Also set up handler to log session end; we have to wait till now to be
* sure Log_disconnections has its final value.
@@ -5408,3 +5413,10 @@ disable_statement_timeout(void)
if (get_timeout_active(STATEMENT_TIMEOUT))
disable_timeout(STATEMENT_TIMEOUT, false);
}
+
+static void
+register_system_versions()
+{
+ /* Set up reporting of core versions. */
+ register_core_versions();
+}
diff --git a/src/backend/utils/misc/system_version.c b/src/backend/utils/misc/system_version.c
index d80c53fcc7b..3bfd1318320 100644
--- a/src/backend/utils/misc/system_version.c
+++ b/src/backend/utils/misc/system_version.c
@@ -25,6 +25,14 @@
*/
#include "postgres.h"
+#ifdef USE_ICU
+#include <unicode/uchar.h>
+#endif
+
+#ifdef __GLIBC__
+#include <gnu/libc-version.h>
+#endif
+
#include "funcapi.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
@@ -66,6 +74,70 @@ add_system_version(const char *name, SystemVersionCB cb, VersionType type)
hentry->type = type;
}
+static const char *
+core_get_version(bool *available)
+{
+ *available = true;
+ return (const char *) psprintf("%s", PG_VERSION);
+}
+
+static const char *
+core_get_arch(bool *available)
+{
+ *available = true;
+ return (const char *) psprintf("%s", PG_ARCH_STR);
+}
+
+static const char *
+core_get_compiler(bool *available)
+{
+ *available = true;
+ return (const char *) psprintf("%s", PG_CC_STR);
+}
+
+#ifdef USE_ICU
+static const char *
+icu_get_version(bool *available)
+{
+ UVersionInfo UCDVersion;
+ char *version = palloc0(U_MAX_VERSION_STRING_LENGTH);
+
+ *available = true;
+ u_getUnicodeVersion(UCDVersion);
+ u_versionToString(UCDVersion, version);
+ return (const char *) version;
+}
+#endif
+
+#ifdef __GLIBC__
+static const char *
+glibc_get_version(bool *available)
+{
+ *available = true;
+ return (const char *) gnu_get_libc_version();
+}
+#endif
+
+/*
+ * Register versions that describe core components and do not correspond to any
+ * individual component.
+ */
+void
+register_core_versions()
+{
+ add_system_version("Core", core_get_version, CompileTime);
+ add_system_version("Arch", core_get_arch, CompileTime);
+ add_system_version("Compiler", core_get_compiler, CompileTime);
+
+#ifdef USE_ICU
+ add_system_version("ICU", icu_get_version, RunTime);
+#endif
+
+#ifdef __GLIBC__
+ add_system_version("Glibc", glibc_get_version, RunTime);
+#endif
+}
+
/*
* pg_get_system_versions
*
diff --git a/src/include/pg_config.h.in b/src/include/pg_config.h.in
index 661c4a9b168..1bea53c05bd 100644
--- a/src/include/pg_config.h.in
+++ b/src/include/pg_config.h.in
@@ -617,6 +617,10 @@
/* PostgreSQL version as a number */
#undef PG_VERSION_NUM
+#undef PG_CC_STR
+
+#undef PG_ARCH_STR
+
/* A string containing the version number, platform, and C compiler */
#undef PG_VERSION_STR
diff --git a/src/include/utils/system_version.h b/src/include/utils/system_version.h
index 18cb673d4ca..49685b6809f 100644
--- a/src/include/utils/system_version.h
+++ b/src/include/utils/system_version.h
@@ -34,5 +34,6 @@ typedef struct SystemVersion
} SystemVersion;
void add_system_version(const char *name, SystemVersionCB cb, VersionType type);
+extern void register_core_versions(void);
#endif /* SYSTEM_VERSION_H */
diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out
index 1e327c2afa4..a5668288ed7 100644
--- a/src/test/regress/expected/sysviews.out
+++ b/src/test/regress/expected/sysviews.out
@@ -241,3 +241,13 @@ select * from pg_timezone_abbrevs where abbrev = 'LMT';
LMT | @ 7 hours 52 mins 58 secs ago | f
(1 row)
+-- Check that the pg_system_versions contains something. Three core versions
+-- should be present: architecture, core and compiler and glibc. More records
+-- may be present depending on the build configuration (e.g. with ICU, GlibC or
+-- JIT support).
+select exists (table pg_system_versions);
+ exists
+--------
+ t
+(1 row)
+
diff --git a/src/test/regress/sql/sysviews.sql b/src/test/regress/sql/sysviews.sql
index 507e400ad4a..7d504f9647e 100644
--- a/src/test/regress/sql/sysviews.sql
+++ b/src/test/regress/sql/sysviews.sql
@@ -104,3 +104,9 @@ select count(distinct utc_offset) >= 24 as ok from pg_timezone_abbrevs;
-- One specific case we can check without much fear of breakage
-- is the historical local-mean-time value used for America/Los_Angeles.
select * from pg_timezone_abbrevs where abbrev = 'LMT';
+
+-- Check that the pg_system_versions contains something. Three core versions
+-- should be present: architecture, core and compiler and glibc. More records
+-- may be present depending on the build configuration (e.g. with ICU, GlibC or
+-- JIT support).
+select exists (table pg_system_versions);
--
2.55.0
[text/plain] v7-0003-Add-JIT-provider-version-to-pg_system_versions.patch (5.3K, ../arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb/4-v7-0003-Add-JIT-provider-version-to-pg_system_versions.patch)
download | inline diff:
From 1f027c0f6f918a35efbf56c295c5133c5c4b5187 Mon Sep 17 00:00:00 2001
From: Dmitrii Dolgov <9erthalion6@gmail.com>
Date: Sat, 5 Oct 2024 18:31:36 +0200
Subject: [PATCH v7 3/3] Add JIT provider version to pg_system_versions
Populate pg_system_versions with the JIT provider version. To actually
fetch the version, extend the JIT provider callbacks with the
get_version method. For LLVM provider llvm_version will be used, which
utilizes C-API LLVMGetVersion, available since LLVM 16.
The JIT provider will be initialized, when a first expression will be
compiled. For reporting purposes it's too late, thus register the
version at the backend startup, right after the core versions.
---
src/backend/jit/jit.c | 24 ++++++++++++++++++++++++
src/backend/jit/llvm/llvmjit.c | 17 +++++++++++++++++
src/backend/tcop/postgres.c | 7 +++++++
src/backend/utils/misc/system_version.c | 7 +++++++
src/include/jit/jit.h | 9 +++++++++
src/include/jit/llvmjit.h | 2 ++
6 files changed, 66 insertions(+)
diff --git a/src/backend/jit/jit.c b/src/backend/jit/jit.c
index 3dc82b7b268..1714f310125 100644
--- a/src/backend/jit/jit.c
+++ b/src/backend/jit/jit.c
@@ -189,3 +189,27 @@ InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add)
INSTR_TIME_ADD(dst->optimization_counter, add->optimization_counter);
INSTR_TIME_ADD(dst->emission_counter, add->emission_counter);
}
+
+/*
+ * Callback for add_system_version, returns JIT provider's version string and
+ * reports if it's not available.
+ */
+const char *
+jit_get_version(bool *available)
+{
+ const char *version;
+
+ if (provider_init())
+ {
+ version = provider.get_version();
+
+ if (version)
+ {
+ *available = true;
+ return version;
+ }
+ }
+
+ *available = false;
+ return "";
+}
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 957ab4751b5..8165898dd29 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -154,6 +154,7 @@ _PG_jit_provider_init(JitProviderCallbacks *cb)
cb->reset_after_error = llvm_reset_after_error;
cb->release_context = llvm_release_context;
cb->compile_expr = llvm_compile_expr;
+ cb->get_version = llvm_version;
}
@@ -1287,3 +1288,19 @@ ResOwnerReleaseJitContext(Datum res)
context->resowner = NULL;
jit_release_context(&context->base);
}
+
+const char *
+llvm_version()
+{
+#if LLVM_VERSION_MAJOR > 15
+ unsigned int major,
+ minor,
+ patch;
+
+ LLVMGetVersion(&major, &minor, &patch);
+
+ return (const char *) psprintf("%d.%d.%d", major, minor, patch);
+#else
+ return NULL;
+#endif
+}
diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c
index ede6b5b59e4..c5af184d910 100644
--- a/src/backend/tcop/postgres.c
+++ b/src/backend/tcop/postgres.c
@@ -5419,4 +5419,11 @@ register_system_versions()
{
/* Set up reporting of core versions. */
register_core_versions();
+
+ /*
+ * Set up reporting for JIT provider version. JIT provider initialization
+ * happens when the first expression is getting compiled, which is too
+ * late. Thus register the callback here instead.
+ */
+ jit_register_version();
}
diff --git a/src/backend/utils/misc/system_version.c b/src/backend/utils/misc/system_version.c
index 3bfd1318320..207b8d87703 100644
--- a/src/backend/utils/misc/system_version.c
+++ b/src/backend/utils/misc/system_version.c
@@ -34,6 +34,7 @@
#endif
#include "funcapi.h"
+#include "jit/jit.h"
#include "utils/builtins.h"
#include "utils/hsearch.h"
#include "utils/system_version.h"
@@ -118,6 +119,12 @@ glibc_get_version(bool *available)
}
#endif
+void
+jit_register_version(void)
+{
+ add_system_version("LLVM", jit_get_version, RunTime);
+}
+
/*
* Register versions that describe core components and do not correspond to any
* individual component.
diff --git a/src/include/jit/jit.h b/src/include/jit/jit.h
index e2baa4c2ed0..6e0e5114247 100644
--- a/src/include/jit/jit.h
+++ b/src/include/jit/jit.h
@@ -70,12 +70,14 @@ typedef void (*JitProviderResetAfterErrorCB) (void);
typedef void (*JitProviderReleaseContextCB) (JitContext *context);
struct ExprState;
typedef bool (*JitProviderCompileExprCB) (struct ExprState *state);
+typedef const char *(*JitProviderVersion) (void);
struct JitProviderCallbacks
{
JitProviderResetAfterErrorCB reset_after_error;
JitProviderReleaseContextCB release_context;
JitProviderCompileExprCB compile_expr;
+ JitProviderVersion get_version;
};
@@ -102,5 +104,12 @@ extern void jit_release_context(JitContext *context);
extern bool jit_compile_expr(struct ExprState *state);
extern void InstrJitAgg(JitInstrumentation *dst, JitInstrumentation *add);
+/*
+ * Callback for add_system_version, get the provider's version string. The flag
+ * indicating availability is passed as an argument.
+ */
+extern const char *jit_get_version(bool *available);
+
+extern void jit_register_version(void);
#endif /* JIT_H */
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index a647dd65ba2..632d7e2f142 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -145,6 +145,8 @@ extern LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r);
extern LLVMOrcObjectLayerRef LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(LLVMOrcExecutionSessionRef ES);
#endif
+extern const char* llvm_version(void);
+
#ifdef __cplusplus
} /* extern "C" */
#endif
--
2.55.0
view thread (26+ messages) latest in thread
Message-ID: <arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb>
Permalink: ../arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb/
Also on: postgresql.org/message-id/arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb
copy link · copy postgr.es · copy git am
reply Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Reply to all the recipients using the --to and --cc options:
reply via email
To: pgsql-hackers@postgresql.org
Cc: 9erthalion6@gmail.com, laurenz.albe@cybertec.at, tgl@sss.pgh.pa.us, jian.universality@gmail.com, mail@joeconway.com
Subject: Re: System views for versions reporting
In-Reply-To: <arKP4SWL-9eQXZH0@ddolgov-thinkpadt14sgen1.rmtde.csb>
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
This inbox is served by DDX for PostgreSQL; see mirroring instructions
for how to clone and mirror all data and code used for this inbox