Hi,

Le sam. 23 mai 2020 à 14:53, Guillaume Lelarge <guilla...@lelarge.info> a
écrit :

> Le mer. 20 mai 2020 à 16:39, Tom Lane <t...@sss.pgh.pa.us> a écrit :
>
>> Guillaume Lelarge <guilla...@lelarge.info> writes:
>> > Le mer. 20 mai 2020 à 11:26, Daniel Gustafsson <dan...@yesql.se> a
>> écrit :
>> >>  The question is what --extensions should do: only dump any
>> >> extensions that objects in the schema depend on; require a pattern and
>> only
>> >> dump matching extensions; dump all extensions (probably not) or
>> something
>> >> else?
>>
>> > Actually, "dump all extensions" (#3) would make sense to me, and has my
>> > vote.
>>
>> I think that makes no sense at all.  By definition, a dump that's been
>> restricted with --schema, --table, or any similar switch is incomplete
>> and may not restore on its own.  Typical examples include foreign key
>> references to tables in other schemas, views using functions in other
>> schemas, etc etc.  I see no reason for extension dependencies to be
>> treated differently from those cases.
>>
>>
> Agreed.
>
> In any use of selective dump, it's the user's job to select a set of
>> objects that she wants dumped (or restored).  Trying to second-guess that
>> is mostly going to make the feature less usable for power-user cases.
>>
>>
> Agreed, though right now he has no way to do this for extensions.
>
> As a counterexample, what if you want the dump to be restorable on a
>> system that doesn't have all of the extensions available on the source?
>> You carefully pick out the tables that you need, which don't require the
>> unavailable extensions ... and then pg_dump decides you don't know what
>> you're doing and includes all the problematic extensions anyway.
>>
>>
> That's true.
>
> I could get behind an "--extensions=PATTERN" switch to allow selective
>> addition of extensions to a selective dump, but I don't want to see us
>> overruling the user's choices about what to dump.
>>
>>
> With all your comments, I can only agree to your views. I'll try to work
> on this anytime soon.
>
>
"Anytime soon" was a long long time ago, and I eventually completely forgot
this, sorry. As nobody worked on it yet, I took a shot at it. See attached
patch.

I don't know if I should add this right away in the commit fest app. If
yes, I guess it should go on the next commit fest (2021-03), right?


-- 
Guillaume.
commit 97c41b05b4aa20f4187aedbed79d67874d2cbbbd
Author: Guillaume Lelarge <guilla...@lelarge.info>
Date:   Mon Jan 25 14:25:53 2021 +0100

    Add a --extension flag to dump specific extensions
    
    Version 1.

diff --git a/doc/src/sgml/ref/pg_dump.sgml b/doc/src/sgml/ref/pg_dump.sgml
index bcbb7a25fb..95d45fabfb 100644
--- a/doc/src/sgml/ref/pg_dump.sgml
+++ b/doc/src/sgml/ref/pg_dump.sgml
@@ -215,6 +215,38 @@ PostgreSQL documentation
       </listitem>
      </varlistentry>
 
+     <varlistentry>
+      <term><option>-e <replaceable class="parameter">pattern</replaceable></option></term>
+      <term><option>--extension=<replaceable class="parameter">pattern</replaceable></option></term>
+      <listitem>
+       <para>
+        Dump only extensions matching <replaceable
+        class="parameter">pattern</replaceable>.  When this option is not
+        specified, all non-system extensions in the target database will be
+        dumped.  Multiple schemas can be selected by writing multiple
+        <option>-e</option> switches.  The <replaceable
+        class="parameter">pattern</replaceable> parameter is interpreted as a
+        pattern according to the same rules used by
+        <application>psql</application>'s <literal>\d</literal> commands (see
+        <xref linkend="app-psql-patterns"/>), so multiple extensions can also
+        be selected by writing wildcard characters in the pattern.  When using
+        wildcards, be careful to quote the pattern if needed to prevent the
+        shell from expanding the wildcards.
+       </para>
+
+       <note>
+        <para>
+         When <option>-e</option> is specified,
+         <application>pg_dump</application> makes no attempt to dump any other
+         database objects that the selected extension(s) might depend upon.
+         Therefore, there is no guarantee that the results of a
+         specific-extension dump can be successfully restored by themselves
+         into a clean database.
+        </para>
+       </note>
+      </listitem>
+     </varlistentry>
+
      <varlistentry>
       <term><option>-E <replaceable class="parameter">encoding</replaceable></option></term>
       <term><option>--encoding=<replaceable class="parameter">encoding</replaceable></option></term>
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 798d14580e..3c1203e85c 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -123,6 +123,9 @@ static SimpleOidList tabledata_exclude_oids = {NULL, NULL};
 static SimpleStringList foreign_servers_include_patterns = {NULL, NULL};
 static SimpleOidList foreign_servers_include_oids = {NULL, NULL};
 
+static SimpleStringList extension_include_patterns = {NULL, NULL};
+static SimpleOidList extension_include_oids = {NULL, NULL};
+
 static const CatalogId nilCatalogId = {0, 0};
 
 /* override for standard extra_float_digits setting */
@@ -151,6 +154,10 @@ static void expand_schema_name_patterns(Archive *fout,
 										SimpleStringList *patterns,
 										SimpleOidList *oids,
 										bool strict_names);
+static void expand_extension_name_patterns(Archive *fout,
+											SimpleStringList *patterns,
+											SimpleOidList *oids,
+											bool strict_names);
 static void expand_foreign_server_name_patterns(Archive *fout,
 												SimpleStringList *patterns,
 												SimpleOidList *oids);
@@ -334,6 +341,7 @@ main(int argc, char **argv)
 		{"clean", no_argument, NULL, 'c'},
 		{"create", no_argument, NULL, 'C'},
 		{"dbname", required_argument, NULL, 'd'},
+		{"extension", required_argument, NULL, 'e'},
 		{"file", required_argument, NULL, 'f'},
 		{"format", required_argument, NULL, 'F'},
 		{"host", required_argument, NULL, 'h'},
@@ -424,7 +432,7 @@ main(int argc, char **argv)
 
 	InitDumpOptions(&dopt);
 
-	while ((c = getopt_long(argc, argv, "abBcCd:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
+	while ((c = getopt_long(argc, argv, "abBcCd:e:E:f:F:h:j:n:N:Op:RsS:t:T:U:vwWxZ:",
 							long_options, &optindex)) != -1)
 	{
 		switch (c)
@@ -453,6 +461,11 @@ main(int argc, char **argv)
 				dopt.cparams.dbname = pg_strdup(optarg);
 				break;
 
+			case 'e':			/* include extension(s) */
+				simple_string_list_append(&extension_include_patterns, optarg);
+				dopt.include_everything = false;
+				break;
+
 			case 'E':			/* Dump encoding */
 				dumpencoding = pg_strdup(optarg);
 				break;
@@ -832,6 +845,16 @@ main(int argc, char **argv)
 
 	/* non-matching exclusion patterns aren't an error */
 
+	/* Expand extension selection patterns into OID lists */
+	if (extension_include_patterns.head != NULL)
+	{
+		expand_extension_name_patterns(fout, &extension_include_patterns,
+									&extension_include_oids,
+									strict_names);
+		if (extension_include_oids.head == NULL)
+			fatal("no matching extensions were found");
+	}
+
 	/*
 	 * Dumping blobs is the default for dumps where an inclusion switch is not
 	 * used (an "include everything" dump).  -B can be used to exclude blobs
@@ -1019,6 +1042,7 @@ help(const char *progname)
 	printf(_("  -B, --no-blobs               exclude large objects in dump\n"));
 	printf(_("  -c, --clean                  clean (drop) database objects before recreating\n"));
 	printf(_("  -C, --create                 include commands to create database in dump\n"));
+	printf(_("  -e, --extension=PATTERN      dump the specified extension(s) only\n"));
 	printf(_("  -E, --encoding=ENCODING      dump the data in encoding ENCODING\n"));
 	printf(_("  -n, --schema=PATTERN         dump the specified schema(s) only\n"));
 	printf(_("  -N, --exclude-schema=PATTERN do NOT dump the specified schema(s)\n"));
@@ -1360,6 +1384,54 @@ expand_schema_name_patterns(Archive *fout,
 	destroyPQExpBuffer(query);
 }
 
+/*
+ * Find the OIDs of all extensions matching the given list of patterns,
+ * and append them to the given OID list.
+ */
+static void
+expand_extension_name_patterns(Archive *fout,
+							SimpleStringList *patterns,
+							SimpleOidList *oids,
+							bool strict_names)
+{
+	PQExpBuffer query;
+	PGresult   *res;
+	SimpleStringListCell *cell;
+	int			i;
+
+	if (patterns->head == NULL)
+		return;					/* nothing to do */
+
+	query = createPQExpBuffer();
+
+	/*
+	 * The loop below runs multiple SELECTs might sometimes result in
+	 * duplicate entries in the OID list, but we don't care.
+	 */
+
+	for (cell = patterns->head; cell; cell = cell->next)
+	{
+		appendPQExpBufferStr(query,
+							 "SELECT oid FROM pg_catalog.pg_extension e\n");
+		processSQLNamePattern(GetConnection(fout), query, cell->val, false,
+							  false, NULL, "e.extname", NULL, NULL);
+
+		res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+		if (strict_names && PQntuples(res) == 0)
+			fatal("no matching extensions were found for pattern \"%s\"", cell->val);
+
+		for (i = 0; i < PQntuples(res); i++)
+		{
+			simple_oid_list_append(oids, atooid(PQgetvalue(res, i, 0)));
+		}
+
+		PQclear(res);
+		resetPQExpBuffer(query);
+	}
+
+	destroyPQExpBuffer(query);
+}
+
 /*
  * Find the OIDs of all foreign servers matching the given list of patterns,
  * and append them to the given OID list.
@@ -1799,6 +1871,11 @@ selectDumpableExtension(ExtensionInfo *extinfo, DumpOptions *dopt)
 	 */
 	if (extinfo->dobj.catId.oid <= (Oid) g_last_builtin_oid)
 		extinfo->dobj.dump = extinfo->dobj.dump_contains = DUMP_COMPONENT_ACL;
+	else if (extension_include_oids.head != NULL)
+		extinfo->dobj.dump_contains = extinfo->dobj.dump =
+			simple_oid_list_member(&extension_include_oids,
+								   extinfo->dobj.catId.oid) ?
+			DUMP_COMPONENT_ALL : DUMP_COMPONENT_NONE;
 	else
 		extinfo->dobj.dump = extinfo->dobj.dump_contains =
 			dopt->include_everything ? DUMP_COMPONENT_ALL :

Reply via email to