Hi

st 8. 3. 2023 v 17:58 odesílatel Pavel Stehule <pavel.steh...@gmail.com>
napsal:

> Hi
>
> I try to write a safeguard check that ensures the expected extension
> version for an extension library.
>
> Some like
>
> const char *expected_extversion = "2.5";
>
> ...
>
> extoid = getExtensionOfObject(ProcedureRelationId,
> fcinfo->flinfo->fn_oid));
> extversion = get_extension_version(extoid);
> if (strcmp(expected_extversion, extversion) != 0)
>    elog(ERROR, "extension \"%s\" needs \"ALTER EXTENSION %s UPDATE\",
>           get_extension_name(extversion),
>           get_extension_name(extversion)))
>
> Currently the extension version is not simply readable - I need to read
> directly from the table.
>
> Notes, comments?
>

attached patch

Regards

Pavel


>
> Regards
>
> Pavel
>
>
From b12a43d885af4311dbb61684d65b6f5fc41b60d2 Mon Sep 17 00:00:00 2001
From: "ok...@github.com" <pavel.steh...@gmail.com>
Date: Sat, 11 Mar 2023 05:04:28 +0100
Subject: [PATCH] get_extension_version - given an extension OID, look up the
 version

Returns a palloc'd string, or NULL if no such extension.
---
 src/backend/commands/extension.c | 50 ++++++++++++++++++++++++++++++++
 src/include/commands/extension.h |  1 +
 2 files changed, 51 insertions(+)

diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 02ff4a9a7f..ea347750fe 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -256,6 +256,56 @@ get_extension_schema(Oid ext_oid)
 	return result;
 }
 
+/*
+ * get_extension_version - given an extension OID, look up the version
+ *
+ * Returns a palloc'd string, or NULL if no such extension.
+ */
+char *
+get_extension_version(Oid ext_oid)
+{
+	char	   *result;
+	Relation	rel;
+	SysScanDesc scandesc;
+	HeapTuple	tuple;
+	ScanKeyData entry[1];
+
+	rel = table_open(ExtensionRelationId, AccessShareLock);
+
+	ScanKeyInit(&entry[0],
+				Anum_pg_extension_oid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(ext_oid));
+
+	scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
+								  NULL, 1, entry);
+
+	tuple = systable_getnext(scandesc);
+
+	/* We assume that there can be at most one matching tuple */
+	if (HeapTupleIsValid(tuple))
+	{
+		Datum		datum;
+		bool		isnull;
+
+		datum = heap_getattr(tuple, Anum_pg_extension_extversion,
+							 RelationGetDescr(rel), &isnull);
+
+		if (isnull)
+			elog(ERROR, "extversion is null");
+
+		result = text_to_cstring(DatumGetTextPP(datum));
+	}
+	else
+		result = NULL;
+
+	systable_endscan(scandesc);
+
+	table_close(rel, AccessShareLock);
+
+	return result;
+}
+
 /*
  * Utility functions to check validity of extension and version names
  */
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 74ae391395..3563e07b9f 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -48,6 +48,7 @@ extern ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *
 extern Oid	get_extension_oid(const char *extname, bool missing_ok);
 extern char *get_extension_name(Oid ext_oid);
 extern Oid	get_extension_schema(Oid ext_oid);
+extern char *get_extension_version(Oid ext_oid);
 extern bool extension_file_exists(const char *extensionName);
 
 extern ObjectAddress AlterExtensionNamespace(const char *extensionName, const char *newschema,
-- 
2.39.2

Reply via email to