On Mon, Oct 31, 2022 at 01:55:05AM -0400, Regina Obe wrote: > > Sandro, can you submit an updated version of this patch. > I was testing it out and looked good first time.
Attached updated version of the patch. > If everyone is okay with this patch, we'll go ahead and add tests and > documentation to go with it. Yes please let us know if there's any chance of getting this mechanism approved or if we should keep advertising works around this limitation (it's not just installing 100s of files but also still missing needed upgrade paths when doing so). --strk;
>From 8725c616c31a9bc25478c7128ea81ce753e51089 Mon Sep 17 00:00:00 2001 From: Sandro Santilli <s...@kbt.io> Date: Wed, 14 Sep 2022 11:10:10 +0200 Subject: [PATCH] Allow wildcard (%) in extension upgrade paths A wildcard character "%" will be accepted in the "source" side of the upgrade script and be considered usable to upgrade any version to the "target" side. Using wildcards needs to be explicitly requested by extensions via a "wildcard_upgrades" setting in their control file. --- src/backend/commands/extension.c | 58 ++++++++++++++++++++++++++++---- 1 file changed, 52 insertions(+), 6 deletions(-) diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c index 1a62e5dac5..ea8825fcff 100644 --- a/src/backend/commands/extension.c +++ b/src/backend/commands/extension.c @@ -86,6 +86,7 @@ typedef struct ExtensionControlFile bool relocatable; /* is ALTER EXTENSION SET SCHEMA supported? */ bool superuser; /* must be superuser to install? */ bool trusted; /* allow becoming superuser on the fly? */ + bool wildcard_upgrades; /* allow using wildcards in upgrade scripts */ int encoding; /* encoding of the script file, or -1 */ List *requires; /* names of prerequisite extensions */ } ExtensionControlFile; @@ -128,6 +129,7 @@ static void ApplyExtensionUpdates(Oid extensionOid, bool cascade, bool is_create); static char *read_whole_file(const char *filename, int *length); +static bool file_exists(const char *name); /* @@ -579,6 +581,14 @@ parse_extension_control_file(ExtensionControlFile *control, errmsg("parameter \"%s\" requires a Boolean value", item->name))); } + else if (strcmp(item->name, "wildcard_upgrades") == 0) + { + if (!parse_bool(item->value, &control->wildcard_upgrades)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("parameter \"%s\" requires a Boolean value", + item->name))); + } else if (strcmp(item->name, "encoding") == 0) { control->encoding = pg_valid_server_encoding(item->value); @@ -636,6 +646,7 @@ read_extension_control_file(const char *extname) control->relocatable = false; control->superuser = true; control->trusted = false; + control->wildcard_upgrades = false; control->encoding = -1; /* @@ -890,7 +901,15 @@ execute_extension_script(Oid extensionOid, ExtensionControlFile *control, if (from_version == NULL) elog(DEBUG1, "executing extension script for \"%s\" version '%s'", control->name, version); else + { + if ( control->wildcard_upgrades && ! file_exists(filename) ) + { + elog(DEBUG1, "extension upgrade script \"%s\" does not exist, will try wildcard", filename); + /* if filename does not exist, try wildcard */ + filename = get_extension_script_filename(control, "%", version); + } elog(DEBUG1, "executing extension script for \"%s\" update from version '%s' to '%s'", control->name, from_version, version); + } /* * If installing a trusted extension on behalf of a non-superuser, become @@ -1215,13 +1234,23 @@ identify_update_path(ExtensionControlFile *control, /* Find shortest path */ result = find_update_path(evi_list, evi_start, evi_target, false, false); - if (result == NIL) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"", - control->name, oldVersion, newVersion))); + if (result != NIL) + return result; - return result; + /* Find wildcard path, if allowed by control file */ + if ( control->wildcard_upgrades ) + { + evi_start = get_ext_ver_info("%", &evi_list); + result = find_update_path(evi_list, evi_start, evi_target, false, false); + + if (result != NIL) + return result; + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("extension \"%s\" has no update path from version \"%s\" to version \"%s\"", + control->name, oldVersion, newVersion))); } /* @@ -3392,3 +3421,20 @@ read_whole_file(const char *filename, int *length) buf[*length] = '\0'; return buf; } + +static bool +file_exists(const char *name) +{ + struct stat st; + + Assert(name != NULL); + + if (stat(name, &st) == 0) + return !S_ISDIR(st.st_mode); + else if (!(errno == ENOENT || errno == ENOTDIR || errno == EACCES)) + ereport(ERROR, + (errcode_for_file_access(), + errmsg("could not access file \"%s\": %m", name))); + + return false; +} -- 2.34.1