ArchiveEntry optional arguments refactoring

Started by Dmitry Dolgovalmost 7 years ago28 messages
#1Dmitry Dolgov
9erthalion6@gmail.com

Hi,

During the discussion in [1]/messages/by-id/20180703070645.wchpu5muyto5n647@alap3.anarazel.de an idea about refactoring ArchiveEntry was
suggested. The reason is that currently this function has significant number of
arguments that are "optional", and every change that has to deal with it
introduces a lot of useless diffs. In the thread, mentioned above, such an
example is tracking current table access method, and I guess "Remove WITH OIDS"
commit 578b229718e is also similar.

Proposed idea is to refactor out all/optional arguments into a separate data
structure, so that adding/removing a new argument wouldn't change that much of
unrelated code. Then for every invocation of ArchiveEntry this structure needs
to be prepared before the call, or as Andres suggested:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

Another suggestion from Amit is to have an ArchiveEntry() function with limited
number of parameters, and an ArchiveEntryEx() with those extra parameters which
are not needed in usual cases.

I want to prepare a patch for that, and I'm inclined to go with the first
option, but since there are two solutions to choose from, I would love to hear
more opinion about this topic. Any pros/cons we don't see yet?

[1]: /messages/by-id/20180703070645.wchpu5muyto5n647@alap3.anarazel.de

#2Dmitry Dolgov
9erthalion6@gmail.com
In reply to: Dmitry Dolgov (#1)
Re: ArchiveEntry optional arguments refactoring

On Wed, Jan 16, 2019 at 1:16 PM Dmitry Dolgov <9erthalion6@gmail.com> wrote:

Hi,

During the discussion in [1] an idea about refactoring ArchiveEntry was
suggested. The reason is that currently this function has significant number of
arguments that are "optional", and every change that has to deal with it
introduces a lot of useless diffs. In the thread, mentioned above, such an
example is tracking current table access method, and I guess "Remove WITH OIDS"
commit 578b229718e is also similar.

Proposed idea is to refactor out all/optional arguments into a separate data
structure, so that adding/removing a new argument wouldn't change that much of
unrelated code. Then for every invocation of ArchiveEntry this structure needs
to be prepared before the call, or as Andres suggested:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

Another suggestion from Amit is to have an ArchiveEntry() function with limited
number of parameters, and an ArchiveEntryEx() with those extra parameters which
are not needed in usual cases.

I want to prepare a patch for that, and I'm inclined to go with the first
option, but since there are two solutions to choose from, I would love to hear
more opinion about this topic. Any pros/cons we don't see yet?

[1]: /messages/by-id/20180703070645.wchpu5muyto5n647@alap3.anarazel.de

[CC Andres and Amit]

#3Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Dmitry Dolgov (#1)
Re: ArchiveEntry optional arguments refactoring

On 2019-Jan-16, Dmitry Dolgov wrote:

Proposed idea is to refactor out all/optional arguments into a separate data
structure, so that adding/removing a new argument wouldn't change that much of
unrelated code. Then for every invocation of ArchiveEntry this structure needs
to be prepared before the call, or as Andres suggested:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

Prepping the struct before the call would be our natural style, I think.
This one where the struct is embedded in the function call does not look
*too* horrible, but I'm curious as to what does pgindent do with it.

Another suggestion from Amit is to have an ArchiveEntry() function with limited
number of parameters, and an ArchiveEntryEx() with those extra parameters which
are not needed in usual cases.

Is there real savings to be had by doing this? What would be the
arguments to each function? Off-hand, I'm not liking this idea too
much. But maybe we can combine both ideas and have one "normal"
function with only the most common args, and create ArchiveEntryExtended
to use the struct as proposed by Andres.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#4Tom Lane
tgl@sss.pgh.pa.us
In reply to: Alvaro Herrera (#3)
Re: ArchiveEntry optional arguments refactoring

Alvaro Herrera <alvherre@2ndquadrant.com> writes:

On 2019-Jan-16, Dmitry Dolgov wrote:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

Is there real savings to be had by doing this? What would be the
arguments to each function? Off-hand, I'm not liking this idea too
much.

I'm not either. What this looks like it will mainly do is create
a back-patching barrier, with little if any readability improvement.

I don't buy the argument that this would move the goalposts in terms
of how much work it is to add a new argument. You'd still end up
touching every call site.

regards, tom lane

#5Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#4)
Re: ArchiveEntry optional arguments refactoring

On 2019-01-17 10:23:39 -0500, Tom Lane wrote:

Alvaro Herrera <alvherre@2ndquadrant.com> writes:

On 2019-Jan-16, Dmitry Dolgov wrote:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

Is there real savings to be had by doing this? What would be the
arguments to each function? Off-hand, I'm not liking this idea too
much.

I'm not either. What this looks like it will mainly do is create
a back-patching barrier, with little if any readability improvement.

I don't really buy this. We've whacked around the arguments to
ArchiveEntry() repeatedly over the last few releases, so there's already
a hindrance to backpatching. And given the current setup we've to whack
around all 70+ callsites whenever a single argument is added. With the
setup I'd suggested you don't, because the designated initializer syntax
allows you to omit items that ought to be zero-initialized.

And given the number of arguments to ArchiveEntry() having a name for
each argument would help for readability too. It's currently not exactly
obvious what is an argument for what:
ArchiveEntry(AH, nilCatalogId, createDumpId(),
"ENCODING", NULL, NULL, "",
"ENCODING", SECTION_PRE_DATA,
qry->data, "", NULL,
NULL, 0,
NULL, NULL);

If you compare that with

ArchiveEntry(AH,
(ArchiveEntry){.catalogId = nilCatalogId,
.dumpId = createDumpId(),
.tag = "ENCODING",
.desc = "ENCODING",
.section = SECTION_PRE_DATA,
.defn = qry->data});

it's definitely easier to see what argument is what.

I don't buy the argument that this would move the goalposts in terms
of how much work it is to add a new argument. You'd still end up
touching every call site.

Why? A lot of arguments that'd be potentially added or removed would not
be set by each callsites.

If you e.g. look at

you can see that a lot of changes where like
        ArchiveEntry(fout, nilCatalogId, createDumpId(),
                     "pg_largeobject", NULL, NULL, "",
-                    false, "pg_largeobject", SECTION_PRE_DATA,
+                    "pg_largeobject", SECTION_PRE_DATA,
                     loOutQry->data, "", NULL,
                     NULL, 0,
                     NULL, NULL);

i.e. just removing a 'false' argument. In like 70+ callsites. With the
above scheme, we'd instead just have removed a single .withoids = true,
from dumpTableSchema()'s ArchiveEntry() call.

Greetings,

Andres Freund

#6Stephen Frost
sfrost@snowman.net
In reply to: Andres Freund (#5)
Re: ArchiveEntry optional arguments refactoring

Greetings,

* Andres Freund (andres@anarazel.de) wrote:

On 2019-01-17 10:23:39 -0500, Tom Lane wrote:

Alvaro Herrera <alvherre@2ndquadrant.com> writes:

On 2019-Jan-16, Dmitry Dolgov wrote:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

Is there real savings to be had by doing this? What would be the
arguments to each function? Off-hand, I'm not liking this idea too
much.

I'm not either. What this looks like it will mainly do is create
a back-patching barrier, with little if any readability improvement.

I don't really buy this. We've whacked around the arguments to
ArchiveEntry() repeatedly over the last few releases, so there's already
a hindrance to backpatching. And given the current setup we've to whack
around all 70+ callsites whenever a single argument is added. With the
setup I'd suggested you don't, because the designated initializer syntax
allows you to omit items that ought to be zero-initialized.

And given the number of arguments to ArchiveEntry() having a name for
each argument would help for readability too. It's currently not exactly
obvious what is an argument for what:
ArchiveEntry(AH, nilCatalogId, createDumpId(),
"ENCODING", NULL, NULL, "",
"ENCODING", SECTION_PRE_DATA,
qry->data, "", NULL,
NULL, 0,
NULL, NULL);

If you compare that with

ArchiveEntry(AH,
(ArchiveEntry){.catalogId = nilCatalogId,
.dumpId = createDumpId(),
.tag = "ENCODING",
.desc = "ENCODING",
.section = SECTION_PRE_DATA,
.defn = qry->data});

it's definitely easier to see what argument is what.

+1. I was on the fence about this approach when David started using it
in pgBackRest but I've come to find that it's actually pretty nice and
being able to omit things which should be zero/default is very nice. I
feel like it's quite similar to what we do in other places too- just
look for things like:

utils/adt/jsonfuncs.c:600

sem = palloc0(sizeof(JsonSemAction));

...

sem->semstate = (void *) state;
sem->array_start = okeys_array_start;
sem->scalar = okeys_scalar;
sem->object_field_start = okeys_object_field_start;
/* remainder are all NULL, courtesy of palloc0 above */

pg_parse_json(lex, sem);

...

pfree(sem);

I don't buy the argument that this would move the goalposts in terms
of how much work it is to add a new argument. You'd still end up
touching every call site.

Why? A lot of arguments that'd be potentially added or removed would not
be set by each callsites.

If you e.g. look at

you can see that a lot of changes where like
ArchiveEntry(fout, nilCatalogId, createDumpId(),
"pg_largeobject", NULL, NULL, "",
-                    false, "pg_largeobject", SECTION_PRE_DATA,
+                    "pg_largeobject", SECTION_PRE_DATA,
loOutQry->data, "", NULL,
NULL, 0,
NULL, NULL);

i.e. just removing a 'false' argument. In like 70+ callsites. With the
above scheme, we'd instead just have removed a single .withoids = true,
from dumpTableSchema()'s ArchiveEntry() call.

Agreed. Using this approach in more places, when appropriate and
sensible, seems like a good direction to go in. To be clear, I don't
think we should go rewrite pieces of code just for the sake of it as
that would make back-patching more difficult, but when we're making
changes anyway, or where it wouldn't really change the landscape for
back-patching, then it seems like a good change.

Thanks!

Stephen

#7Andres Freund
andres@anarazel.de
In reply to: Andres Freund (#5)
Re: ArchiveEntry optional arguments refactoring

Hi,

On 2019-01-17 09:29:04 -0800, Andres Freund wrote:

On 2019-01-17 10:23:39 -0500, Tom Lane wrote:

I don't buy the argument that this would move the goalposts in terms
of how much work it is to add a new argument. You'd still end up
touching every call site.

Why? A lot of arguments that'd be potentially added or removed would not
be set by each callsites.

If you e.g. look at

you can see that a lot of changes where like
ArchiveEntry(fout, nilCatalogId, createDumpId(),
"pg_largeobject", NULL, NULL, "",
-                    false, "pg_largeobject", SECTION_PRE_DATA,
+                    "pg_largeobject", SECTION_PRE_DATA,
loOutQry->data, "", NULL,
NULL, 0,
NULL, NULL);

i.e. just removing a 'false' argument. In like 70+ callsites. With the
above scheme, we'd instead just have removed a single .withoids = true,
from dumpTableSchema()'s ArchiveEntry() call.

the "at" I was trying to reference above is
578b229718e8f15fa779e20f086c4b6bb3776106 / the WITH OID removal, and
therein specifically the pg_dump changes.

Greetings,

Andres Freund

#8Amit Khandekar
amitdkhan.pg@gmail.com
In reply to: Dmitry Dolgov (#1)
Re: ArchiveEntry optional arguments refactoring

On Wed, 16 Jan 2019 at 17:45, Dmitry Dolgov <9erthalion6@gmail.com> wrote:

Hi,

During the discussion in [1] an idea about refactoring ArchiveEntry was
suggested. The reason is that currently this function has significant number of
arguments that are "optional", and every change that has to deal with it
introduces a lot of useless diffs. In the thread, mentioned above, such an
example is tracking current table access method, and I guess "Remove WITH OIDS"
commit 578b229718e is also similar.

Proposed idea is to refactor out all/optional arguments into a separate data
structure, so that adding/removing a new argument wouldn't change that much of
unrelated code. Then for every invocation of ArchiveEntry this structure needs
to be prepared before the call, or as Andres suggested:

ArchiveEntry((ArchiveArgs){.tablespace = 3,
.dumpFn = somefunc,
...});

I didn't know we could do it this way. I thought we would have to
declare a variable and have to initialize fields with non-const values
separately. This looks nice. We could even initialize fields with
non-const values. +1 from me.

I think, we could use the same TocEntry structure as parameter, rather
than a new structure. Most of the arguments already resemble fields of
this structure. Also, we could pass pointer to that structure :

ArchiveEntry( &(TocEntry){.tablespace = 3,
.dumpFn = somefunc,
...});

--
Thanks,
-Amit Khandekar
EnterpriseDB Corporation
The Postgres Database Company

#9Dmitry Dolgov
9erthalion6@gmail.com
In reply to: Andres Freund (#7)
1 attachment(s)
Re: ArchiveEntry optional arguments refactoring

On 2019-01-17 09:29:04 -0800, Andres Freund wrote:
On 2019-01-17 10:23:39 -0500, Tom Lane wrote:

I don't buy the argument that this would move the goalposts in terms
of how much work it is to add a new argument. You'd still end up
touching every call site.

Why? A lot of arguments that'd be potentially added or removed would not
be set by each callsites.

If you e.g. look at

you can see that a lot of changes where like
ArchiveEntry(fout, nilCatalogId, createDumpId(),
"pg_largeobject", NULL, NULL, "",
-                    false, "pg_largeobject", SECTION_PRE_DATA,
+                    "pg_largeobject", SECTION_PRE_DATA,
loOutQry->data, "", NULL,
NULL, 0,
NULL, NULL);

i.e. just removing a 'false' argument. In like 70+ callsites. With the
above scheme, we'd instead just have removed a single .withoids = true,
from dumpTableSchema()'s ArchiveEntry() call.

To make this discussion a bit more specific, I've created a patch of how it can
look like. All the arguments, except Archive, CatalogId and DumpId I've moved
into the ArchiveOpts structure. Not all of them could be empty before, but
anyway it seems better for consistency and readability. Some of the arguments
had empty string as a default value, I haven't changed anything here yet
(although this mixture of NULL and "" in ArchiveEntry looks a bit confusing).

As Andres mentioned above, for 578b229718e / the WITH OID removal and pg_dump
modification from pluggable storage thread, this patch reduces number of
changes, related to ArchiveEntry, from 70+ to just one.

Attachments:

0001-ArchiveOpts-structure.patchapplication/octet-stream; name=0001-ArchiveOpts-structure.patchDownload
From e81ab8f266002793274e3c6b6ecfe2f8219f0330 Mon Sep 17 00:00:00 2001
From: erthalion <9erthalion6@gmail.com>
Date: Wed, 23 Jan 2019 14:58:33 +0100
Subject: [PATCH] ArchiveOpts structure

ArchiveEntry function has some number of arguments, that can be
considered as optional. Refactor out arguments for ArchiveEntry into
ArchiveOpts structure, to make it more flexible for changes.
---
 src/bin/pg_dump/pg_backup_archiver.c |   49 +-
 src/bin/pg_dump/pg_backup_archiver.h |   29 +-
 src/bin/pg_dump/pg_dump.c            | 1085 ++++++++++++++++++----------------
 3 files changed, 624 insertions(+), 539 deletions(-)

diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 2c2f6fb4a9..48a0eee7f6 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -1066,17 +1066,8 @@ WriteData(Archive *AHX, const void *data, size_t dLen)
 
 /* Public */
 TocEntry *
-ArchiveEntry(Archive *AHX,
-			 CatalogId catalogId, DumpId dumpId,
-			 const char *tag,
-			 const char *namespace,
-			 const char *tablespace,
-			 const char *owner,
-			 const char *desc, teSection section,
-			 const char *defn,
-			 const char *dropStmt, const char *copyStmt,
-			 const DumpId *deps, int nDeps,
-			 DataDumperPtr dumpFn, void *dumpArg)
+ArchiveEntry(Archive *AHX, CatalogId catalogId,
+			 DumpId dumpId, ArchiveOpts *opts)
 {
 	ArchiveHandle *AH = (ArchiveHandle *) AHX;
 	TocEntry   *newToc;
@@ -1094,22 +1085,22 @@ ArchiveEntry(Archive *AHX,
 
 	newToc->catalogId = catalogId;
 	newToc->dumpId = dumpId;
-	newToc->section = section;
-
-	newToc->tag = pg_strdup(tag);
-	newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
-	newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
-	newToc->owner = pg_strdup(owner);
-	newToc->desc = pg_strdup(desc);
-	newToc->defn = pg_strdup(defn);
-	newToc->dropStmt = pg_strdup(dropStmt);
-	newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
-
-	if (nDeps > 0)
+	newToc->section = opts->section;
+
+	newToc->tag = pg_strdup(opts->tag);
+	newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
+	newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
+	newToc->owner = opts->owner ? pg_strdup(opts->owner) : "";
+	newToc->desc = pg_strdup(opts->desc);
+	newToc->defn = opts->defn ? pg_strdup(opts->defn) : "";
+	newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : "";
+	newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
+
+	if (opts->nDeps > 0)
 	{
-		newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
-		memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
-		newToc->nDeps = nDeps;
+		newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
+		memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
+		newToc->nDeps = opts->nDeps;
 	}
 	else
 	{
@@ -1117,9 +1108,9 @@ ArchiveEntry(Archive *AHX,
 		newToc->nDeps = 0;
 	}
 
-	newToc->dataDumper = dumpFn;
-	newToc->dataDumperArg = dumpArg;
-	newToc->hadDumper = dumpFn ? true : false;
+	newToc->dataDumper = opts->dumpFn;
+	newToc->dataDumperArg = opts->dumpArg;
+	newToc->hadDumper = opts->dumpFn ? true : false;
 
 	newToc->formatData = NULL;
 	newToc->dataLength = 0;
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 306d2ceba9..e484683dcf 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -405,17 +405,26 @@ extern void on_exit_close_archive(Archive *AHX);
 
 extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) pg_attribute_printf(3, 4);
 
+typedef struct
+{
+	const char 		*tag;
+	const char 		*namespace;
+	const char 		*tablespace;
+	const char 		*owner;
+	const char 		*desc;
+	teSection 		section;
+	const char 		*defn;
+	const char 		*dropStmt;
+	const char 		*copyStmt;
+	const DumpId 	*deps;
+	int 			nDeps;
+	DataDumperPtr 	dumpFn;
+	void 			*dumpArg;
+} ArchiveOpts;
+
 /* Called to add a TOC entry */
-extern TocEntry *ArchiveEntry(Archive *AHX,
-			 CatalogId catalogId, DumpId dumpId,
-			 const char *tag,
-			 const char *namespace, const char *tablespace,
-			 const char *owner,
-			 const char *desc, teSection section,
-			 const char *defn,
-			 const char *dropStmt, const char *copyStmt,
-			 const DumpId *deps, int nDeps,
-			 DataDumperPtr dumpFn, void *dumpArg);
+extern TocEntry *ArchiveEntry(Archive *AHX, CatalogId catalogId,
+							  DumpId dumpId, ArchiveOpts *opts);
 
 extern void WriteTOC(ArchiveHandle *AH);
 extern void ReadTOC(ArchiveHandle *AH);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2b1a94733b..6c639bb096 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2135,12 +2135,18 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
 		TocEntry   *te;
 
 		te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
-						  tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
-						  NULL, tbinfo->rolname,
-						  "TABLE DATA", SECTION_DATA,
-						  "", "", copyStmt,
-						  &(tbinfo->dobj.dumpId), 1,
-						  dumpFn, tdinfo);
+						  &(ArchiveOpts){
+							.tag = tbinfo->dobj.name,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.desc = "TABLE DATA",
+							.section = SECTION_DATA,
+							.copyStmt = copyStmt,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+							.dumpFn = dumpFn,
+							.dumpArg = tdinfo,
+						  });
 
 		/*
 		 * Set the TocEntry's dataLength in case we are doing a parallel dump
@@ -2184,19 +2190,16 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
 		ArchiveEntry(fout,
 					 tdinfo->dobj.catId,	/* catalog ID */
 					 tdinfo->dobj.dumpId,	/* dump ID */
-					 tbinfo->dobj.name, /* Name */
-					 tbinfo->dobj.namespace->dobj.name, /* Namespace */
-					 NULL,		/* Tablespace */
-					 tbinfo->rolname,	/* Owner */
-					 "MATERIALIZED VIEW DATA",	/* Desc */
-					 SECTION_POST_DATA, /* Section */
-					 q->data,	/* Create */
-					 "",		/* Del */
-					 NULL,		/* Copy */
-					 tdinfo->dobj.dependencies, /* Deps */
-					 tdinfo->dobj.nDeps,	/* # Deps */
-					 NULL,		/* Dumper */
-					 NULL);		/* Dumper Arg */
+					 &(ArchiveOpts){
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "MATERIALIZED VIEW DATA",
+						.section = SECTION_POST_DATA,
+						.defn = q->data,
+						.deps = tdinfo->dobj.dependencies,
+						.nDeps = tdinfo->dobj.nDeps,
+					 });
 
 	destroyPQExpBuffer(q);
 }
@@ -2722,19 +2725,14 @@ dumpDatabase(Archive *fout)
 	ArchiveEntry(fout,
 				 dbCatId,		/* catalog ID */
 				 dbDumpId,		/* dump ID */
-				 datname,		/* Name */
-				 NULL,			/* Namespace */
-				 NULL,			/* Tablespace */
-				 dba,			/* Owner */
-				 "DATABASE",	/* Desc */
-				 SECTION_PRE_DATA,	/* Section */
-				 creaQry->data, /* Create */
-				 delQry->data,	/* Del */
-				 NULL,			/* Copy */
-				 NULL,			/* Deps */
-				 0,				/* # Deps */
-				 NULL,			/* Dumper */
-				 NULL);			/* Dumper Arg */
+				 &(ArchiveOpts){
+					.tag = datname,
+					.owner = dba,
+					.desc = "DATABASE",
+					.section = SECTION_PRE_DATA,
+					.defn = creaQry->data,
+					.dropStmt = delQry->data,
+				 });
 
 	/* Compute correct tag for archive entry */
 	appendPQExpBuffer(labelq, "DATABASE %s", qdatname);
@@ -2762,11 +2760,15 @@ dumpDatabase(Archive *fout)
 			appendPQExpBufferStr(dbQry, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 labelq->data, NULL, NULL, dba,
-						 "COMMENT", SECTION_NONE,
-						 dbQry->data, "", NULL,
-						 &(dbDumpId), 1,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = labelq->data,
+							.owner = dba,
+							.desc = "COMMENT",
+							.section = SECTION_NONE,
+							.defn = dbQry->data,
+							.deps = &(dbDumpId),
+							.nDeps = 1,
+						 });
 		}
 	}
 	else
@@ -2789,11 +2791,15 @@ dumpDatabase(Archive *fout)
 		emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
 		if (seclabelQry->len > 0)
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 labelq->data, NULL, NULL, dba,
-						 "SECURITY LABEL", SECTION_NONE,
-						 seclabelQry->data, "", NULL,
-						 &(dbDumpId), 1,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = labelq->data,
+							.owner = dba,
+							.desc = "SECURITY LABEL",
+							.section = SECTION_NONE,
+							.defn = seclabelQry->data,
+							.deps = &(dbDumpId),
+							.nDeps = 1,
+						 });
 		destroyPQExpBuffer(seclabelQry);
 		PQclear(shres);
 	}
@@ -2859,11 +2865,15 @@ dumpDatabase(Archive *fout)
 
 	if (creaQry->len > 0)
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 datname, NULL, NULL, dba,
-					 "DATABASE PROPERTIES", SECTION_PRE_DATA,
-					 creaQry->data, delQry->data, NULL,
-					 &(dbDumpId), 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = datname,
+						.owner = dba,
+						.desc = "DATABASE PROPERTIES",
+						.section = SECTION_PRE_DATA,
+						.defn = creaQry->data,
+						.dropStmt = delQry->data,
+						.deps = &(dbDumpId),
+					 });
 
 	/*
 	 * pg_largeobject comes from the old system intact, so set its
@@ -2904,11 +2914,12 @@ dumpDatabase(Archive *fout)
 						  atooid(PQgetvalue(lo_res, 0, i_relminmxid)),
 						  LargeObjectRelationId);
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 "pg_largeobject", NULL, NULL, "",
-					 "pg_largeobject", SECTION_PRE_DATA,
-					 loOutQry->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = "pg_largeobject",
+						.desc = "pg_largeobject",
+						.section = SECTION_PRE_DATA,
+						.defn = loOutQry->data,
+					 });
 
 		PQclear(lo_res);
 
@@ -3014,11 +3025,12 @@ dumpEncoding(Archive *AH)
 	appendPQExpBufferStr(qry, ";\n");
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "ENCODING", NULL, NULL, "",
-				 "ENCODING", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 &(ArchiveOpts){
+					.tag = "ENCODING",
+					.desc = "ENCODING",
+					.section = SECTION_PRE_DATA,
+					.defn = qry->data,
+				 });
 
 	destroyPQExpBuffer(qry);
 }
@@ -3041,11 +3053,12 @@ dumpStdStrings(Archive *AH)
 					  stdstrings);
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "STDSTRINGS", NULL, NULL, "",
-				 "STDSTRINGS", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 &(ArchiveOpts){
+					.tag = "STDSTRINGS",
+					.desc = "STDSTRINGS",
+					.section = SECTION_PRE_DATA,
+					.defn = qry->data,
+				 });
 
 	destroyPQExpBuffer(qry);
 }
@@ -3097,11 +3110,12 @@ dumpSearchPath(Archive *AH)
 		write_msg(NULL, "saving search_path = %s\n", path->data);
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "SEARCHPATH", NULL, NULL, "",
-				 "SEARCHPATH", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 &(ArchiveOpts){
+					.tag = "SEARCHPATH",
+					.desc = "SEARCHPATH",
+					.section = SECTION_PRE_DATA,
+					.defn = qry->data,
+				 });
 
 	/* Also save it in AH->searchpath, in case we're doing plain text dump */
 	AH->searchpath = pg_strdup(qry->data);
@@ -3273,13 +3287,14 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
 
 	if (binfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, binfo->dobj.catId, binfo->dobj.dumpId,
-					 binfo->dobj.name,
-					 NULL, NULL,
-					 binfo->rolname,
-					 "BLOB", SECTION_PRE_DATA,
-					 cquery->data, dquery->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = binfo->dobj.name,
+						.owner = binfo->rolname,
+						.desc = "BLOB",
+						.section = SECTION_PRE_DATA,
+						.defn = cquery->data,
+						.dropStmt = dquery->data,
+					 });
 
 	/* Dump comment if any */
 	if (binfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -3577,14 +3592,16 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 		 */
 		if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
 			ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-						 polinfo->dobj.name,
-						 polinfo->dobj.namespace->dobj.name,
-						 NULL,
-						 tbinfo->rolname,
-						 "ROW SECURITY", SECTION_POST_DATA,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = polinfo->dobj.name,
+							.namespace = polinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.desc = "ROW SECURITY",
+							.section = SECTION_POST_DATA,
+							.defn = query->data,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+						 });
 
 		destroyPQExpBuffer(query);
 		return;
@@ -3633,14 +3650,15 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 
 	if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
 		ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-					 tag,
-					 polinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "POLICY", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag,
+						.namespace = polinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "POLICY",
+						.section = SECTION_POST_DATA,
+						.defn = query->data,
+						.dropStmt = delqry->data,
+					 });
 
 	free(tag);
 	destroyPQExpBuffer(query);
@@ -3807,14 +3825,14 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 	appendPQExpBufferStr(query, "');\n");
 
 	ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
-				 pubinfo->dobj.name,
-				 NULL,
-				 NULL,
-				 pubinfo->rolname,
-				 "PUBLICATION", SECTION_POST_DATA,
-				 query->data, delq->data, NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 &(ArchiveOpts){
+					.tag = pubinfo->dobj.name,
+					.owner = pubinfo->rolname,
+					.desc = "PUBLICATION",
+					.section = SECTION_POST_DATA,
+					.defn = query->data,
+					.dropStmt = delq->data,
+				 });
 
 	if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "PUBLICATION", qpubname,
@@ -3950,14 +3968,13 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
 	 * done by table drop.
 	 */
 	ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
-				 tag,
-				 tbinfo->dobj.namespace->dobj.name,
-				 NULL,
-				 "",
-				 "PUBLICATION TABLE", SECTION_POST_DATA,
-				 query->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 &(ArchiveOpts){
+					.tag = tag,
+					.namespace = tbinfo->dobj.namespace->dobj.name,
+					.desc = "PUBLICATION TABLE",
+					.section = SECTION_POST_DATA,
+					.defn = query->data,
+				 });
 
 	free(tag);
 	destroyPQExpBuffer(query);
@@ -4143,14 +4160,14 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 	appendPQExpBufferStr(query, ");\n");
 
 	ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
-				 subinfo->dobj.name,
-				 NULL,
-				 NULL,
-				 subinfo->rolname,
-				 "SUBSCRIPTION", SECTION_POST_DATA,
-				 query->data, delq->data, NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 &(ArchiveOpts){
+					.tag = subinfo->dobj.name,
+					.owner = subinfo->rolname,
+					.desc = "SUBSCRIPTION",
+					.section = SECTION_POST_DATA,
+					.defn = query->data,
+					.dropStmt = delq->data,
+				 });
 
 	if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "SUBSCRIPTION", qsubname,
@@ -9377,11 +9394,16 @@ dumpComment(Archive *fout, const char *type, const char *name,
 		 * post-data.
 		 */
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, namespace, NULL, owner,
-					 "COMMENT", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(dumpId), 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag->data,
+						.namespace = namespace,
+						.owner = owner,
+						.desc = "COMMENT",
+						.section = SECTION_NONE,
+						.defn = query->data,
+						.deps = &(dumpId),
+						.nDeps = 1,
+					 });
 
 		destroyPQExpBuffer(query);
 		destroyPQExpBuffer(tag);
@@ -9443,13 +9465,16 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 tag->data,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL, tbinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = tag->data,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.desc = "COMMENT",
+							.section = SECTION_NONE,
+							.defn = query->data,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+						 });
 		}
 		else if (objsubid > 0 && objsubid <= tbinfo->numatts)
 		{
@@ -9467,13 +9492,16 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 tag->data,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL, tbinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = tag->data,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.desc = "COMMENT",
+							.section = SECTION_NONE,
+							.defn = query->data,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+						 });
 		}
 
 		comments++;
@@ -9750,11 +9778,12 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
 				TocEntry   *te;
 
 				te = ArchiveEntry(fout, dobj->catId, dobj->dumpId,
-								  dobj->name, NULL, NULL, "",
-								  "BLOBS", SECTION_DATA,
-								  "", "", NULL,
-								  NULL, 0,
-								  dumpBlobs, NULL);
+								  &(ArchiveOpts){
+									.tag = dobj->name,
+									.desc = "BLOBS",
+									.section = SECTION_DATA,
+									.dumpFn = dumpBlobs,
+								  });
 
 				/*
 				 * Set the TocEntry's dataLength in case we are doing a
@@ -9822,13 +9851,14 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
 	if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
-					 nspinfo->dobj.name,
-					 NULL, NULL,
-					 nspinfo->rolname,
-					 "SCHEMA", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = nspinfo->dobj.name,
+						.owner = nspinfo->rolname,
+						.desc = "SCHEMA",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Schema Comments and Security Labels */
 	if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -9958,13 +9988,13 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
 	if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
-					 extinfo->dobj.name,
-					 NULL, NULL,
-					 "",
-					 "EXTENSION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = extinfo->dobj.name,
+						.desc = "EXTENSION",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Extension Comments and Security Labels */
 	if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10108,14 +10138,15 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.desc = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10235,14 +10266,15 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.desc = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10308,14 +10340,15 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.desc = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10590,14 +10623,15 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.desc = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10747,14 +10781,15 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "DOMAIN", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.desc = "DOMAIN",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Domain Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10969,14 +11004,15 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.desc = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 
 	/* Dump Type Comments and Security Labels */
@@ -11105,13 +11141,16 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo)
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 target->data,
-						 tyinfo->dobj.namespace->dobj.name,
-						 NULL, tyinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tyinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = target->data,
+							.namespace = tyinfo->dobj.namespace->dobj.name,
+							.owner = tyinfo->rolname,
+							.desc = "COMMENT",
+							.section = SECTION_NONE,
+							.defn = query->data,
+							.deps = &(tyinfo->dobj.dumpId),
+							.nDeps = 1,
+						 });
 		}
 
 		comments++;
@@ -11160,14 +11199,14 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
 
 	if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
-					 stinfo->dobj.name,
-					 stinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 stinfo->baseType->rolname,
-					 "SHELL TYPE", SECTION_PRE_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = stinfo->dobj.name,
+						.namespace = stinfo->dobj.namespace->dobj.name,
+						.owner = stinfo->baseType->rolname,
+						.desc = "SHELL TYPE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+					 });
 
 	destroyPQExpBuffer(q);
 }
@@ -11272,12 +11311,14 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
 	if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
-					 plang->dobj.name,
-					 NULL, NULL, plang->lanowner,
-					 "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = plang->dobj.name,
+						.owner = plang->lanowner,
+						.desc = "PROCEDURAL LANGUAGE",
+						.section = SECTION_PRE_DATA,
+						.defn = defqry->data,
+						.dropStmt = delqry->data,
+					 });
 
 	/* Dump Proc Lang Comments and Security Labels */
 	if (plang->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -11942,14 +11983,15 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 
 	if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
-					 funcsig_tag,
-					 finfo->dobj.namespace->dobj.name,
-					 NULL,
-					 finfo->rolname,
-					 keyword, SECTION_PRE_DATA,
-					 q->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = funcsig_tag,
+						.namespace = finfo->dobj.namespace->dobj.name,
+						.owner = finfo->rolname,
+						.desc = keyword,
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delqry->data,
+					 });
 
 	/* Dump Function Comments and Security Labels */
 	if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12077,12 +12119,13 @@ dumpCast(Archive *fout, CastInfo *cast)
 
 	if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
-					 labelq->data,
-					 NULL, NULL, "",
-					 "CAST", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = labelq->data,
+						.desc = "CAST",
+						.section = SECTION_PRE_DATA,
+						.defn = defqry->data,
+						.dropStmt = delqry->data,
+					 });
 
 	/* Dump Cast Comments */
 	if (cast->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12205,12 +12248,15 @@ dumpTransform(Archive *fout, TransformInfo *transform)
 
 	if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId,
-					 labelq->data,
-					 NULL, NULL, "",
-					 "TRANSFORM", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 transform->dobj.dependencies, transform->dobj.nDeps,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = labelq->data,
+						.desc = "TRANSFORM",
+						.section = SECTION_PRE_DATA,
+						.defn = defqry->data,
+						.dropStmt = delqry->data,
+						.deps = transform->dobj.dependencies,
+						.nDeps = transform->dobj.nDeps,
+					 });
 
 	/* Dump Transform Comments */
 	if (transform->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12418,14 +12464,15 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
 
 	if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
-					 oprinfo->dobj.name,
-					 oprinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 oprinfo->rolname,
-					 "OPERATOR", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = oprinfo->dobj.name,
+						.namespace = oprinfo->dobj.namespace->dobj.name,
+						.owner = oprinfo->rolname,
+						.desc = "OPERATOR",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Operator Comments */
 	if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12588,14 +12635,13 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
 
 	if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
-					 aminfo->dobj.name,
-					 NULL,
-					 NULL,
-					 "",
-					 "ACCESS METHOD", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = aminfo->dobj.name,
+						.desc = "ACCESS METHOD",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Access Method Comments */
 	if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12954,14 +13000,15 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 
 	if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
-					 opcinfo->dobj.name,
-					 opcinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 opcinfo->rolname,
-					 "OPERATOR CLASS", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = opcinfo->dobj.name,
+						.namespace = opcinfo->dobj.namespace->dobj.name,
+						.owner = opcinfo->rolname,
+						.desc = "OPERATOR CLASS",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Operator Class Comments */
 	if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13221,14 +13268,15 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
 
 	if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
-					 opfinfo->dobj.name,
-					 opfinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 opfinfo->rolname,
-					 "OPERATOR FAMILY", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = opfinfo->dobj.name,
+						.namespace = opfinfo->dobj.namespace->dobj.name,
+						.owner = opfinfo->rolname,
+						.desc = "OPERATOR FAMILY",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Operator Family Comments */
 	if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13364,14 +13412,15 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
 
 	if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
-					 collinfo->dobj.name,
-					 collinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 collinfo->rolname,
-					 "COLLATION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = collinfo->dobj.name,
+						.namespace = collinfo->dobj.namespace->dobj.name,
+						.owner = collinfo->rolname,
+						.desc = "COLLATION",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Collation Comments */
 	if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13459,14 +13508,15 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
 
 	if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
-					 convinfo->dobj.name,
-					 convinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 convinfo->rolname,
-					 "CONVERSION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = convinfo->dobj.name,
+						.namespace = convinfo->dobj.namespace->dobj.name,
+						.owner = convinfo->rolname,
+						.desc = "CONVERSION",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Conversion Comments */
 	if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13948,14 +13998,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 	if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, agginfo->aggfn.dobj.catId,
 					 agginfo->aggfn.dobj.dumpId,
-					 aggsig_tag,
-					 agginfo->aggfn.dobj.namespace->dobj.name,
-					 NULL,
-					 agginfo->aggfn.rolname,
-					 "AGGREGATE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = aggsig_tag,
+						.namespace = agginfo->aggfn.dobj.namespace->dobj.name,
+						.owner = agginfo->aggfn.rolname,
+						.desc = "AGGREGATE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Aggregate Comments */
 	if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14046,14 +14097,14 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
 
 	if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
-					 prsinfo->dobj.name,
-					 prsinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "TEXT SEARCH PARSER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = prsinfo->dobj.name,
+						.namespace = prsinfo->dobj.namespace->dobj.name,
+						.desc = "TEXT SEARCH PARSER",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Parser Comments */
 	if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14126,14 +14177,15 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 
 	if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
-					 dictinfo->dobj.name,
-					 dictinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 dictinfo->rolname,
-					 "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = dictinfo->dobj.name,
+						.namespace = dictinfo->dobj.namespace->dobj.name,
+						.owner = dictinfo->rolname,
+						.desc = "TEXT SEARCH DICTIONARY",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Dictionary Comments */
 	if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14187,14 +14239,14 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
 
 	if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
-					 tmplinfo->dobj.name,
-					 tmplinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tmplinfo->dobj.name,
+						.namespace = tmplinfo->dobj.namespace->dobj.name,
+						.desc = "TEXT SEARCH TEMPLATE",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Template Comments */
 	if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14307,14 +14359,15 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 
 	if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
-					 cfginfo->dobj.name,
-					 cfginfo->dobj.namespace->dobj.name,
-					 NULL,
-					 cfginfo->rolname,
-					 "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = cfginfo->dobj.name,
+						.namespace = cfginfo->dobj.namespace->dobj.name,
+						.owner = cfginfo->rolname,
+						.desc = "TEXT SEARCH CONFIGURATION",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Configuration Comments */
 	if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14373,14 +14426,14 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 
 	if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
-					 fdwinfo->dobj.name,
-					 NULL,
-					 NULL,
-					 fdwinfo->rolname,
-					 "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = fdwinfo->dobj.name,
+						.owner = fdwinfo->rolname,
+						.desc = "FOREIGN DATA WRAPPER",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Foreign Data Wrapper Comments */
 	if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14464,14 +14517,14 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 
 	if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
-					 srvinfo->dobj.name,
-					 NULL,
-					 NULL,
-					 srvinfo->rolname,
-					 "SERVER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = srvinfo->dobj.name,
+						.owner = srvinfo->rolname,
+						.desc = "SERVER",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Foreign Server Comments */
 	if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14582,14 +14635,15 @@ dumpUserMappings(Archive *fout,
 						  usename, servername);
 
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data,
-					 namespace,
-					 NULL,
-					 owner,
-					 "USER MAPPING", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 &dumpId, 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag->data,
+						.namespace = namespace,
+						.owner = owner,
+						.desc = "USER MAPPING",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 	}
 
 	PQclear(res);
@@ -14661,14 +14715,15 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
 
 	if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
 		ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
-					 tag->data,
-					 daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
-					 NULL,
-					 daclinfo->defaclrole,
-					 "DEFAULT ACL", SECTION_POST_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag->data,
+						.namespace = daclinfo->dobj.namespace ?
+									 daclinfo->dobj.namespace->dobj.name : NULL,
+						.owner = daclinfo->defaclrole,
+						.desc = "DEFAULT ACL",
+						.section = SECTION_POST_DATA,
+						.defn = q->data,
+					 });
 
 	destroyPQExpBuffer(tag);
 	destroyPQExpBuffer(q);
@@ -14760,13 +14815,16 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
 			appendPQExpBuffer(tag, "%s %s", type, name);
 
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, nspname,
-					 NULL,
-					 owner ? owner : "",
-					 "ACL", SECTION_NONE,
-					 sql->data, "", NULL,
-					 &(objDumpId), 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag->data,
+						.namespace = nspname,
+						.owner = owner,
+						.desc = "ACL",
+						.section = SECTION_NONE,
+						.defn = sql->data,
+						.deps = &(objDumpId),
+						.nDeps = 1,
+					 });
 		destroyPQExpBuffer(tag);
 	}
 
@@ -14848,11 +14906,16 @@ dumpSecLabel(Archive *fout, const char *type, const char *name,
 
 		appendPQExpBuffer(tag, "%s %s", type, name);
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, namespace, NULL, owner,
-					 "SECURITY LABEL", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(dumpId), 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag->data,
+						.namespace = namespace,
+						.owner = owner,
+						.desc = "SECURITY LABEL",
+						.section = SECTION_NONE,
+						.defn = query->data,
+						.deps = &(dumpId),
+						.nDeps = 1,
+					 });
 		destroyPQExpBuffer(tag);
 	}
 
@@ -14928,13 +14991,16 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
 		appendPQExpBuffer(target, "%s %s", reltypename,
 						  fmtId(tbinfo->dobj.name));
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 target->data,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL, tbinfo->rolname,
-					 "SECURITY LABEL", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(tbinfo->dobj.dumpId), 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = target->data,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "SECURITY LABEL",
+						.section = SECTION_NONE,
+						.defn = query->data,
+						.deps = &(tbinfo->dobj.dumpId),
+						.nDeps = 1,
+					 });
 	}
 	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(target);
@@ -16012,16 +16078,18 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
 	if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
-					 tbinfo->rolname,
-					 reltypename,
-					 tbinfo->postponed_def ?
-					 SECTION_POST_DATA : SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.tablespace = (tbinfo->relkind == RELKIND_VIEW) ?
+									  NULL : tbinfo->reltablespace,
+						.owner = tbinfo->rolname,
+						.desc = reltypename,
+						.section = tbinfo->postponed_def ?
+								   SECTION_POST_DATA : SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 
 	/* Dump Table Comments */
@@ -16092,14 +16160,15 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
 
 	if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "DEFAULT", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "DEFAULT",
+						.section = SECTION_PRE_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	free(tag);
 	destroyPQExpBuffer(q);
@@ -16241,14 +16310,16 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
 
 		if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
-						 indxinfo->dobj.name,
-						 tbinfo->dobj.namespace->dobj.name,
-						 indxinfo->tablespace,
-						 tbinfo->rolname,
-						 "INDEX", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = indxinfo->dobj.name,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.tablespace = indxinfo->tablespace,
+							.owner = tbinfo->rolname,
+							.desc = "INDEX",
+							.section = SECTION_POST_DATA,
+							.defn = q->data,
+							.dropStmt = delq->data,
+						 });
 
 		if (indstatcolsarray)
 			free(indstatcolsarray);
@@ -16290,14 +16361,13 @@ dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo)
 						  fmtQualifiedDumpable(attachinfo->partitionIdx));
 
 		ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
-					 attachinfo->dobj.name,
-					 attachinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "INDEX ATTACH", SECTION_POST_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = attachinfo->dobj.name,
+						.namespace = attachinfo->dobj.namespace->dobj.name,
+						.desc = "INDEX ATTACH",
+						.section = SECTION_POST_DATA,
+						.defn = q->data,
+					 });
 
 		destroyPQExpBuffer(q);
 	}
@@ -16345,14 +16415,15 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
 	if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, statsextinfo->dobj.catId,
 					 statsextinfo->dobj.dumpId,
-					 statsextinfo->dobj.name,
-					 statsextinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 statsextinfo->rolname,
-					 "STATISTICS", SECTION_POST_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = statsextinfo->dobj.name,
+						.namespace = statsextinfo->dobj.namespace->dobj.name,
+						.owner = statsextinfo->rolname,
+						.desc = "STATISTICS",
+						.section = SECTION_POST_DATA,
+						.defn = q->data,
+						.dropStmt = delq->data,
+					 });
 
 	/* Dump Statistics Comments */
 	if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -16506,14 +16577,16 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 		if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-						 tag,
-						 tbinfo->dobj.namespace->dobj.name,
-						 indxinfo->tablespace,
-						 tbinfo->rolname,
-						 "CONSTRAINT", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = tag,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.tablespace = indxinfo->tablespace,
+							.owner = tbinfo->rolname,
+							.desc = "CONSTRAINT",
+							.section = SECTION_POST_DATA,
+							.defn = q->data,
+							.dropStmt = delq->data,
+						 });
 	}
 	else if (coninfo->contype == 'f')
 	{
@@ -16546,14 +16619,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 		if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-						 tag,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL,
-						 tbinfo->rolname,
-						 "FK CONSTRAINT", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 &(ArchiveOpts){
+							.tag = tag,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.desc = "FK CONSTRAINT",
+							.section = SECTION_POST_DATA,
+							.defn = q->data,
+							.dropStmt = delq->data,
+						 });
 	}
 	else if (coninfo->contype == 'c' && tbinfo)
 	{
@@ -16578,14 +16652,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 			if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-							 tag,
-							 tbinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tbinfo->rolname,
-							 "CHECK CONSTRAINT", SECTION_POST_DATA,
-							 q->data, delq->data, NULL,
-							 NULL, 0,
-							 NULL, NULL);
+							 &(ArchiveOpts){
+								.tag = tag,
+								.namespace = tbinfo->dobj.namespace->dobj.name,
+								.owner = tbinfo->rolname,
+								.desc = "CHECK CONSTRAINT",
+								.section = SECTION_POST_DATA,
+								.defn = q->data,
+								.dropStmt = delq->data,
+							 });
 		}
 	}
 	else if (coninfo->contype == 'c' && tbinfo == NULL)
@@ -16611,14 +16686,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 			if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-							 tag,
-							 tyinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tyinfo->rolname,
-							 "CHECK CONSTRAINT", SECTION_POST_DATA,
-							 q->data, delq->data, NULL,
-							 NULL, 0,
-							 NULL, NULL);
+							 &(ArchiveOpts){
+								.tag = tag,
+								.namespace = tyinfo->dobj.namespace->dobj.name,
+								.owner = tyinfo->rolname,
+								.desc = "CHECK CONSTRAINT",
+								.section = SECTION_POST_DATA,
+								.defn = q->data,
+								.dropStmt = delq->data,
+							 });
 		}
 	}
 	else
@@ -16885,14 +16961,15 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
 	if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "SEQUENCE", SECTION_PRE_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "SEQUENCE",
+						.section = SECTION_PRE_DATA,
+						.defn = query->data,
+						.dropStmt = delqry->data,
+					 });
 
 	/*
 	 * If the sequence is owned by a table column, emit the ALTER for it as a
@@ -16926,14 +17003,16 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
 			if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, nilCatalogId, createDumpId(),
-							 tbinfo->dobj.name,
-							 tbinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tbinfo->rolname,
-							 "SEQUENCE OWNED BY", SECTION_PRE_DATA,
-							 query->data, "", NULL,
-							 &(tbinfo->dobj.dumpId), 1,
-							 NULL, NULL);
+							 &(ArchiveOpts){
+								.tag = tbinfo->dobj.name,
+								.namespace = tbinfo->dobj.namespace->dobj.name,
+								.owner = tbinfo->rolname,
+								.desc = "SEQUENCE OWNED BY",
+								.section = SECTION_PRE_DATA,
+								.defn = query->data,
+								.deps = &(tbinfo->dobj.dumpId),
+								.nDeps = 1,
+							 });
 		}
 	}
 
@@ -16994,14 +17073,16 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo)
 
 	if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "SEQUENCE SET", SECTION_DATA,
-					 query->data, "", NULL,
-					 &(tbinfo->dobj.dumpId), 1,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "SEQUENCE SET",
+						.section = SECTION_DATA,
+						.defn = query->data,
+						.deps = &(tbinfo->dobj.dumpId),
+						.nDeps = 1,
+					 });
 
 	PQclear(res);
 
@@ -17193,14 +17274,15 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 
 	if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "TRIGGER", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "TRIGGER",
+						.section = SECTION_POST_DATA,
+						.defn = query->data,
+						.dropStmt = delqry->data,
+					 });
 
 	if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, trigprefix->data, qtabname,
@@ -17282,12 +17364,14 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
 
 	if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
-					 evtinfo->dobj.name, NULL, NULL,
-					 evtinfo->evtowner,
-					 "EVENT TRIGGER", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = evtinfo->dobj.name,
+						.owner = evtinfo->evtowner,
+						.desc = "EVENT TRIGGER",
+						.section = SECTION_POST_DATA,
+						.defn = query->data,
+						.dropStmt = delqry->data,
+					 });
 
 	if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "EVENT TRIGGER", qevtname,
@@ -17440,14 +17524,15 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 
 	if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "RULE", SECTION_POST_DATA,
-					 cmd->data, delcmd->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 &(ArchiveOpts){
+						.tag = tag,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.desc = "RULE",
+						.section = SECTION_POST_DATA,
+						.defn = cmd->data,
+						.dropStmt = delcmd->data,
+					 });
 
 	/* Dump rule comments */
 	if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-- 
2.16.4

#10Andres Freund
andres@anarazel.de
In reply to: Dmitry Dolgov (#9)
Re: ArchiveEntry optional arguments refactoring

Hi,

On 2019-01-23 16:12:15 +0100, Dmitry Dolgov wrote:

To make this discussion a bit more specific, I've created a patch of how it can
look like.

Thanks.

All the arguments, except Archive, CatalogId and DumpId I've moved
into the ArchiveOpts structure. Not all of them could be empty before, but
anyway it seems better for consistency and readability. Some of the arguments
had empty string as a default value, I haven't changed anything here yet
(although this mixture of NULL and "" in ArchiveEntry looks a bit confusing).

Probably worth changing at the same time, if we decide to go for it.

To me this does look like it'd be more maintainable going forward.

Greetings,

Andres Freund

#11Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Andres Freund (#10)
Re: ArchiveEntry optional arguments refactoring

Hello

On 2019-Jan-23, Andres Freund wrote:

All the arguments, except Archive, CatalogId and DumpId I've moved
into the ArchiveOpts structure. Not all of them could be empty before, but
anyway it seems better for consistency and readability. Some of the arguments
had empty string as a default value, I haven't changed anything here yet
(although this mixture of NULL and "" in ArchiveEntry looks a bit confusing).

Probably worth changing at the same time, if we decide to go for it.

To me this does look like it'd be more maintainable going forward.

It does. How does pgindent behave with it?

I'd use ArchiveEntryOpts as struct name; ArchiveOpts sounds wrong. Also,
the struct members could use better names -- "defn" for example could
perhaps be "createStmt" (to match dropStmt/copyStmt), and expand "desc"
to "description".

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#12Chapman Flack
chap@anastigmatix.net
In reply to: Dmitry Dolgov (#9)
Re: ArchiveEntry optional arguments refactoring

On 1/23/19 10:12 AM, Dmitry Dolgov wrote:

To make this discussion a bit more specific, I've created a patch of how
it can look like.

A little bit of vararg-macro action can make such a design look
even tidier, cf. [1]https://github.com/NetBSD/src/blob/trunk/sys/sys/midiio.h#L709.

Or are compilers without vararg macros still in the supported mix?

-Chap

[1]: https://github.com/NetBSD/src/blob/trunk/sys/sys/midiio.h#L709

The macros in [1]https://github.com/NetBSD/src/blob/trunk/sys/sys/midiio.h#L709 are not defined to create a function call, but only
the argument structure because there might be several functions to pass
it to, so a call would be written like func(&SEQ_MK_CHN(NOTEON, ...)).

In ArchiveEntry's case, if there's only one function involved, there'd
be no reason not to have a macro produce the whole call.

#13Tom Lane
tgl@sss.pgh.pa.us
In reply to: Chapman Flack (#12)
Re: ArchiveEntry optional arguments refactoring

Chapman Flack <chap@anastigmatix.net> writes:

Or are compilers without vararg macros still in the supported mix?

No.

regards, tom lane

#14Andres Freund
andres@anarazel.de
In reply to: Alvaro Herrera (#11)
Re: ArchiveEntry optional arguments refactoring

Hi,

On 2019-01-23 13:58:07 -0300, Alvaro Herrera wrote:

I'd use ArchiveEntryOpts as struct name; ArchiveOpts sounds wrong.

Brevity would be of some advantage IMO, because it'll probably determine
how pgindent indents the arguments, because the struct name will be in
the arguments.

Also, the struct members could use better names -- "defn" for example
could perhaps be "createStmt" (to match dropStmt/copyStmt), and expand
"desc" to "description".

True.

Greetings,

Andres Freund

#15Andres Freund
andres@anarazel.de
In reply to: Chapman Flack (#12)
Re: ArchiveEntry optional arguments refactoring

Hi,

On 2019-01-23 12:05:10 -0500, Chapman Flack wrote:

On 1/23/19 10:12 AM, Dmitry Dolgov wrote:

To make this discussion a bit more specific, I've created a patch of how
it can look like.

A little bit of vararg-macro action can make such a design look
even tidier, cf. [1].
[1] https://github.com/NetBSD/src/blob/trunk/sys/sys/midiio.h#L709

The macros in [1] are not defined to create a function call, but only
the argument structure because there might be several functions to pass
it to, so a call would be written like func(&SEQ_MK_CHN(NOTEON, ...)).

In ArchiveEntry's case, if there's only one function involved, there'd
be no reason not to have a macro produce the whole call.

I'm not really seeing this being more than obfuscation in this case. The
only point of the macro is to set the .tag and .op elements to something
without adding redundancies due to the struct name. Which we'd not have.

Greetings,

Andres Freund

#16Chapman Flack
chap@anastigmatix.net
In reply to: Andres Freund (#15)
Re: ArchiveEntry optional arguments refactoring

On 1/23/19 12:10 PM, Andres Freund wrote:

On 2019-01-23 12:05:10 -0500, Chapman Flack wrote:

[1] https://github.com/NetBSD/src/blob/trunk/sys/sys/midiio.h#L709

I'm not really seeing this being more than obfuscation in this case. The
only point of the macro is to set the .tag and .op elements to something
without adding redundancies due to the struct name. Which we'd not have.

Granted, that example is more elaborate than this case, but writing

ArchiveEntry(fout, dbCatId, dbDumpId, .tag = datname, .owner = dba,
.desc = "DATABASE", .section = SECTION_PRE_DATA,
.defn = creaQry->data, .dropStmt = delQry->data);

instead of

ArchiveEntry(fout, dbCatId, dbDumpId, &(ArchiveOpts){.tag = datname,
.owner = dba, .desc = "DATABASE",
.section = SECTION_PRE_DATA, .defn = creaQry->data,
.dropStmt = delQry->data});

would be easy, and still save a bit of visual noise.

Regards,
-Chap

#17Andres Freund
andres@anarazel.de
In reply to: Alvaro Herrera (#11)
Re: ArchiveEntry optional arguments refactoring

On 2019-01-23 13:58:07 -0300, Alvaro Herrera wrote:

Hello

On 2019-Jan-23, Andres Freund wrote:

All the arguments, except Archive, CatalogId and DumpId I've moved
into the ArchiveOpts structure. Not all of them could be empty before, but
anyway it seems better for consistency and readability. Some of the arguments
had empty string as a default value, I haven't changed anything here yet
(although this mixture of NULL and "" in ArchiveEntry looks a bit confusing).

Probably worth changing at the same time, if we decide to go for it.

To me this does look like it'd be more maintainable going forward.

It does. How does pgindent behave with it?

It craps out:
Error@3649: Unbalanced parens
Warning@3657: Extra )

But that can be worked around with something like

te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
ARCHIVE_ARGS(.tag = tbinfo->dobj.name,
.namespace = tbinfo->dobj.namespace->dobj.name,
.owner = tbinfo->rolname,
.desc = "TABLE DATA",
.section = SECTION_DATA,
.copyStmt = copyStmt,
.deps = &(tbinfo->dobj.dumpId),
.nDeps = 1,
.dumpFn = dumpFn,
.dumpArg = tdinfo,
));
which looks mildly simpler too.

Greetings,

Andres Freund

#18Andres Freund
andres@anarazel.de
In reply to: Chapman Flack (#16)
Re: ArchiveEntry optional arguments refactoring

On 2019-01-23 12:22:23 -0500, Chapman Flack wrote:

On 1/23/19 12:10 PM, Andres Freund wrote:

On 2019-01-23 12:05:10 -0500, Chapman Flack wrote:

[1] https://github.com/NetBSD/src/blob/trunk/sys/sys/midiio.h#L709

I'm not really seeing this being more than obfuscation in this case. The
only point of the macro is to set the .tag and .op elements to something
without adding redundancies due to the struct name. Which we'd not have.

Granted, that example is more elaborate than this case, but writing

ArchiveEntry(fout, dbCatId, dbDumpId, .tag = datname, .owner = dba,
.desc = "DATABASE", .section = SECTION_PRE_DATA,
.defn = creaQry->data, .dropStmt = delQry->data);

instead of

ArchiveEntry(fout, dbCatId, dbDumpId, &(ArchiveOpts){.tag = datname,
.owner = dba, .desc = "DATABASE",
.section = SECTION_PRE_DATA, .defn = creaQry->data,
.dropStmt = delQry->data});

would be easy, and still save a bit of visual noise.

IDK, it'd be harder to parse correctly as a C programmer though. I'm up
with a wrapper macro like
#define ARCHIVE_ARGS(...) &(ArchiveOpts){__VA_ARGS__}
but weirdly mixing struct arguments and normal function arguments seems
quite confusing.

Greetings,

Andres Freund

#19Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#17)
Re: ArchiveEntry optional arguments refactoring

Andres Freund <andres@anarazel.de> writes:

On 2019-01-23 13:58:07 -0300, Alvaro Herrera wrote:

It does. How does pgindent behave with it?

It craps out:
Error@3649: Unbalanced parens
Warning@3657: Extra )

But that can be worked around with something like

te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
ARCHIVE_ARGS(.tag = tbinfo->dobj.name,
.namespace = tbinfo->dobj.namespace->dobj.name,
.owner = tbinfo->rolname,
.desc = "TABLE DATA",
.section = SECTION_DATA,
.copyStmt = copyStmt,
.deps = &(tbinfo->dobj.dumpId),
.nDeps = 1,
.dumpFn = dumpFn,
.dumpArg = tdinfo,
));
which looks mildly simpler too.

That looks fairly reasonable from here, but I'd suggest
ARCHIVE_OPTS rather than ARCHIVE_ARGS.

Can we omit the initial dots if we use a wrapper macro? Would it be
a good idea to do so (I'm not really sure)?

regards, tom lane

#20Andres Freund
andres@anarazel.de
In reply to: Tom Lane (#19)
Re: ArchiveEntry optional arguments refactoring

On 2019-01-23 12:32:06 -0500, Tom Lane wrote:

Andres Freund <andres@anarazel.de> writes:

On 2019-01-23 13:58:07 -0300, Alvaro Herrera wrote:

It does. How does pgindent behave with it?

It craps out:
Error@3649: Unbalanced parens
Warning@3657: Extra )

But that can be worked around with something like

te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
ARCHIVE_ARGS(.tag = tbinfo->dobj.name,
.namespace = tbinfo->dobj.namespace->dobj.name,
.owner = tbinfo->rolname,
.desc = "TABLE DATA",
.section = SECTION_DATA,
.copyStmt = copyStmt,
.deps = &(tbinfo->dobj.dumpId),
.nDeps = 1,
.dumpFn = dumpFn,
.dumpArg = tdinfo,
));
which looks mildly simpler too.

That looks fairly reasonable from here, but I'd suggest
ARCHIVE_OPTS rather than ARCHIVE_ARGS.

WFM. Seems quite possible that we'd grow a few more of these over time,
so establishing some common naming seems good.

Btw, do you have an opionion on keeping catId / dumpId outside/inside
the argument struct?

Can we omit the initial dots if we use a wrapper macro? Would it be
a good idea to do so (I'm not really sure)?

Not easily, if at all, I think. We'd have to do a fair bit of weird
macro magic (and then still end up with limitations) to "process" each
argument individually. And even if it were easy, I don't think it's
particularly advantageous.

Greetings,

Andres Freund

#21Tom Lane
tgl@sss.pgh.pa.us
In reply to: Andres Freund (#20)
Re: ArchiveEntry optional arguments refactoring

Andres Freund <andres@anarazel.de> writes:

Btw, do you have an opionion on keeping catId / dumpId outside/inside
the argument struct?

I'd go for outside, since they're not optional. Not dead set on that
though.

regards, tom lane

#22Chapman Flack
chap@anastigmatix.net
In reply to: Andres Freund (#18)
Re: ArchiveEntry optional arguments refactoring

On 1/23/19 12:25 PM, Andres Freund wrote:

On 2019-01-23 12:22:23 -0500, Chapman Flack wrote:

ArchiveEntry(fout, dbCatId, dbDumpId, .tag = datname, .owner = dba,
.desc = "DATABASE", .section = SECTION_PRE_DATA,
.defn = creaQry->data, .dropStmt = delQry->data);

IDK, it'd be harder to parse correctly as a C programmer though. ...
weirdly mixing struct arguments and normal function arguments seems
quite confusing.

Hmm, I guess the rubric I think with goes something like "is a C
programmer who encounters this in a source file for the first time
likely to guess wrong about what it means?", and in the case above,
I can scarcely imagine it.

ISTM that these days, many people are familiar with several languages
that allow a few mandatory, positional parameters followed by optional
named ones, and so a likely reaction would be "hey look, somebody used
a macro here to make C look more like <insert other language I know>."

On 1/23/19 12:32 PM, Tom Lane wrote:

Can we omit the initial dots if we use a wrapper macro?

That, I think, is hard.

Getting to the form above is downright easy; making the dots go away,
even if achievable, seems way further down the path of diminishing
returns.

Regards,
-Chap

#23Dmitry Dolgov
9erthalion6@gmail.com
In reply to: Chapman Flack (#22)
1 attachment(s)
Re: ArchiveEntry optional arguments refactoring

Here is another version, where I accumulated all the suggestions:

* Use NULL as a default value where it was an empty string before (this
required few minor changes for some part of the code outside ArchiveEntry)

* Rename defn, descr to createStmt, description

* Use a macro to avoid pgindent errors

About the last one. I'm also inclined to use the simpler version of
ARCHIVE_OPTS macro, mostly because the difference between "optional" and
"positional" arguments in the alternative proposal is not that visible. So

mixing struct arguments and normal function arguments seems
quite confusing

could probably affect not only readability, but also would be bit more
problematic for updating this code (which was the goal in the first place).

Attachments:

0001-ArchiveOpts-structure_v2.patchapplication/octet-stream; name=0001-ArchiveOpts-structure_v2.patchDownload
From 287ba74f5ad0b4150339ce06111f83b50e6e83ec Mon Sep 17 00:00:00 2001
From: erthalion <9erthalion6@gmail.com>
Date: Wed, 23 Jan 2019 14:58:33 +0100
Subject: [PATCH] ArchiveOpts structure

ArchiveEntry function has some number of arguments, that can be
considered as optional. Refactor out arguments for ArchiveEntry into
ArchiveOpts structure, to make it more flexible for changes.
---
 src/bin/pg_dump/pg_backup_archiver.c |   57 +-
 src/bin/pg_dump/pg_backup_archiver.h |   31 +-
 src/bin/pg_dump/pg_dump.c            | 1085 ++++++++++++++++++----------------
 3 files changed, 632 insertions(+), 541 deletions(-)

diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 2c2f6fb4a9..ab6b042c58 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -1066,17 +1066,8 @@ WriteData(Archive *AHX, const void *data, size_t dLen)
 
 /* Public */
 TocEntry *
-ArchiveEntry(Archive *AHX,
-			 CatalogId catalogId, DumpId dumpId,
-			 const char *tag,
-			 const char *namespace,
-			 const char *tablespace,
-			 const char *owner,
-			 const char *desc, teSection section,
-			 const char *defn,
-			 const char *dropStmt, const char *copyStmt,
-			 const DumpId *deps, int nDeps,
-			 DataDumperPtr dumpFn, void *dumpArg)
+ArchiveEntry(Archive *AHX, CatalogId catalogId,
+			 DumpId dumpId, ArchiveOpts *opts)
 {
 	ArchiveHandle *AH = (ArchiveHandle *) AHX;
 	TocEntry   *newToc;
@@ -1094,22 +1085,22 @@ ArchiveEntry(Archive *AHX,
 
 	newToc->catalogId = catalogId;
 	newToc->dumpId = dumpId;
-	newToc->section = section;
-
-	newToc->tag = pg_strdup(tag);
-	newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
-	newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
-	newToc->owner = pg_strdup(owner);
-	newToc->desc = pg_strdup(desc);
-	newToc->defn = pg_strdup(defn);
-	newToc->dropStmt = pg_strdup(dropStmt);
-	newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
-
-	if (nDeps > 0)
+	newToc->section = opts->section;
+
+	newToc->tag = pg_strdup(opts->tag);
+	newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
+	newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
+	newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
+	newToc->desc = pg_strdup(opts->description);
+	newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
+	newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
+	newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
+
+	if (opts->nDeps > 0)
 	{
-		newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
-		memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
-		newToc->nDeps = nDeps;
+		newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
+		memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
+		newToc->nDeps = opts->nDeps;
 	}
 	else
 	{
@@ -1117,9 +1108,9 @@ ArchiveEntry(Archive *AHX,
 		newToc->nDeps = 0;
 	}
 
-	newToc->dataDumper = dumpFn;
-	newToc->dataDumperArg = dumpArg;
-	newToc->hadDumper = dumpFn ? true : false;
+	newToc->dataDumper = opts->dumpFn;
+	newToc->dataDumperArg = opts->dumpArg;
+	newToc->hadDumper = opts->dumpFn ? true : false;
 
 	newToc->formatData = NULL;
 	newToc->dataLength = 0;
@@ -3629,7 +3620,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 	}
 	else
 	{
-		if (strlen(te->defn) > 0)
+		if (te->defn && strlen(te->defn) > 0)
 			ahprintf(AH, "%s\n\n", te->defn);
 	}
 
@@ -3640,7 +3631,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 	 * with DROP commands must appear in one list or the other.
 	 */
 	if (!ropt->noOwner && !ropt->use_setsessauth &&
-		strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
+		te->owner && strlen(te->owner) > 0 &&
+		te->dropStmt && strlen(te->dropStmt) > 0)
 	{
 		if (strcmp(te->desc, "AGGREGATE") == 0 ||
 			strcmp(te->desc, "BLOB") == 0 ||
@@ -3723,6 +3715,9 @@ replace_line_endings(const char *str)
 	char	   *result;
 	char	   *s;
 
+	if (!str)
+		str = "";
+
 	result = pg_strdup(str);
 
 	for (s = result; *s != '\0'; s++)
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 306d2ceba9..adee1be7e4 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -405,17 +405,28 @@ extern void on_exit_close_archive(Archive *AHX);
 
 extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) pg_attribute_printf(3, 4);
 
+typedef struct
+{
+	const char 		*tag;
+	const char 		*namespace;
+	const char 		*tablespace;
+	const char 		*owner;
+	const char 		*description;
+	teSection 		section;
+	const char 		*createStmt;
+	const char 		*dropStmt;
+	const char 		*copyStmt;
+	const DumpId 	*deps;
+	int 			nDeps;
+	DataDumperPtr 	dumpFn;
+	void 			*dumpArg;
+} ArchiveOpts;
+
+#define ARCHIVE_OPTS(...) &(ArchiveOpts){__VA_ARGS__}
+
 /* Called to add a TOC entry */
-extern TocEntry *ArchiveEntry(Archive *AHX,
-			 CatalogId catalogId, DumpId dumpId,
-			 const char *tag,
-			 const char *namespace, const char *tablespace,
-			 const char *owner,
-			 const char *desc, teSection section,
-			 const char *defn,
-			 const char *dropStmt, const char *copyStmt,
-			 const DumpId *deps, int nDeps,
-			 DataDumperPtr dumpFn, void *dumpArg);
+extern TocEntry *ArchiveEntry(Archive *AHX, CatalogId catalogId,
+							  DumpId dumpId, ArchiveOpts *opts);
 
 extern void WriteTOC(ArchiveHandle *AH);
 extern void ReadTOC(ArchiveHandle *AH);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2b1a94733b..20ce7fc57b 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2135,12 +2135,18 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
 		TocEntry   *te;
 
 		te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
-						  tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
-						  NULL, tbinfo->rolname,
-						  "TABLE DATA", SECTION_DATA,
-						  "", "", copyStmt,
-						  &(tbinfo->dobj.dumpId), 1,
-						  dumpFn, tdinfo);
+						  ARCHIVE_OPTS(
+							.tag = tbinfo->dobj.name,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.description = "TABLE DATA",
+							.section = SECTION_DATA,
+							.copyStmt = copyStmt,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+							.dumpFn = dumpFn,
+							.dumpArg = tdinfo,
+						  ));
 
 		/*
 		 * Set the TocEntry's dataLength in case we are doing a parallel dump
@@ -2184,19 +2190,16 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
 		ArchiveEntry(fout,
 					 tdinfo->dobj.catId,	/* catalog ID */
 					 tdinfo->dobj.dumpId,	/* dump ID */
-					 tbinfo->dobj.name, /* Name */
-					 tbinfo->dobj.namespace->dobj.name, /* Namespace */
-					 NULL,		/* Tablespace */
-					 tbinfo->rolname,	/* Owner */
-					 "MATERIALIZED VIEW DATA",	/* Desc */
-					 SECTION_POST_DATA, /* Section */
-					 q->data,	/* Create */
-					 "",		/* Del */
-					 NULL,		/* Copy */
-					 tdinfo->dobj.dependencies, /* Deps */
-					 tdinfo->dobj.nDeps,	/* # Deps */
-					 NULL,		/* Dumper */
-					 NULL);		/* Dumper Arg */
+					 ARCHIVE_OPTS(
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "MATERIALIZED VIEW DATA",
+						.section = SECTION_POST_DATA,
+						.createStmt = q->data,
+						.deps = tdinfo->dobj.dependencies,
+						.nDeps = tdinfo->dobj.nDeps,
+					 ));
 
 	destroyPQExpBuffer(q);
 }
@@ -2722,19 +2725,14 @@ dumpDatabase(Archive *fout)
 	ArchiveEntry(fout,
 				 dbCatId,		/* catalog ID */
 				 dbDumpId,		/* dump ID */
-				 datname,		/* Name */
-				 NULL,			/* Namespace */
-				 NULL,			/* Tablespace */
-				 dba,			/* Owner */
-				 "DATABASE",	/* Desc */
-				 SECTION_PRE_DATA,	/* Section */
-				 creaQry->data, /* Create */
-				 delQry->data,	/* Del */
-				 NULL,			/* Copy */
-				 NULL,			/* Deps */
-				 0,				/* # Deps */
-				 NULL,			/* Dumper */
-				 NULL);			/* Dumper Arg */
+				 ARCHIVE_OPTS(
+					.tag = datname,
+					.owner = dba,
+					.description = "DATABASE",
+					.section = SECTION_PRE_DATA,
+					.createStmt = creaQry->data,
+					.dropStmt = delQry->data,
+				 ));
 
 	/* Compute correct tag for archive entry */
 	appendPQExpBuffer(labelq, "DATABASE %s", qdatname);
@@ -2762,11 +2760,15 @@ dumpDatabase(Archive *fout)
 			appendPQExpBufferStr(dbQry, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 labelq->data, NULL, NULL, dba,
-						 "COMMENT", SECTION_NONE,
-						 dbQry->data, "", NULL,
-						 &(dbDumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = labelq->data,
+							.owner = dba,
+							.description = "COMMENT",
+							.section = SECTION_NONE,
+							.createStmt = dbQry->data,
+							.deps = &(dbDumpId),
+							.nDeps = 1,
+						 ));
 		}
 	}
 	else
@@ -2789,11 +2791,15 @@ dumpDatabase(Archive *fout)
 		emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
 		if (seclabelQry->len > 0)
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 labelq->data, NULL, NULL, dba,
-						 "SECURITY LABEL", SECTION_NONE,
-						 seclabelQry->data, "", NULL,
-						 &(dbDumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = labelq->data,
+							.owner = dba,
+							.description = "SECURITY LABEL",
+							.section = SECTION_NONE,
+							.createStmt = seclabelQry->data,
+							.deps = &(dbDumpId),
+							.nDeps = 1,
+						 ));
 		destroyPQExpBuffer(seclabelQry);
 		PQclear(shres);
 	}
@@ -2859,11 +2865,15 @@ dumpDatabase(Archive *fout)
 
 	if (creaQry->len > 0)
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 datname, NULL, NULL, dba,
-					 "DATABASE PROPERTIES", SECTION_PRE_DATA,
-					 creaQry->data, delQry->data, NULL,
-					 &(dbDumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = datname,
+						.owner = dba,
+						.description = "DATABASE PROPERTIES",
+						.section = SECTION_PRE_DATA,
+						.createStmt = creaQry->data,
+						.dropStmt = delQry->data,
+						.deps = &(dbDumpId),
+					 ));
 
 	/*
 	 * pg_largeobject comes from the old system intact, so set its
@@ -2904,11 +2914,12 @@ dumpDatabase(Archive *fout)
 						  atooid(PQgetvalue(lo_res, 0, i_relminmxid)),
 						  LargeObjectRelationId);
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 "pg_largeobject", NULL, NULL, "",
-					 "pg_largeobject", SECTION_PRE_DATA,
-					 loOutQry->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = "pg_largeobject",
+						.description = "pg_largeobject",
+						.section = SECTION_PRE_DATA,
+						.createStmt = loOutQry->data,
+					 ));
 
 		PQclear(lo_res);
 
@@ -3014,11 +3025,12 @@ dumpEncoding(Archive *AH)
 	appendPQExpBufferStr(qry, ";\n");
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "ENCODING", NULL, NULL, "",
-				 "ENCODING", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(
+					.tag = "ENCODING",
+					.description = "ENCODING",
+					.section = SECTION_PRE_DATA,
+					.createStmt = qry->data,
+				 ));
 
 	destroyPQExpBuffer(qry);
 }
@@ -3041,11 +3053,12 @@ dumpStdStrings(Archive *AH)
 					  stdstrings);
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "STDSTRINGS", NULL, NULL, "",
-				 "STDSTRINGS", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(
+					.tag = "STDSTRINGS",
+					.description = "STDSTRINGS",
+					.section = SECTION_PRE_DATA,
+					.createStmt = qry->data,
+				 ));
 
 	destroyPQExpBuffer(qry);
 }
@@ -3097,11 +3110,12 @@ dumpSearchPath(Archive *AH)
 		write_msg(NULL, "saving search_path = %s\n", path->data);
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "SEARCHPATH", NULL, NULL, "",
-				 "SEARCHPATH", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(
+					.tag = "SEARCHPATH",
+					.description = "SEARCHPATH",
+					.section = SECTION_PRE_DATA,
+					.createStmt = qry->data,
+				 ));
 
 	/* Also save it in AH->searchpath, in case we're doing plain text dump */
 	AH->searchpath = pg_strdup(qry->data);
@@ -3273,13 +3287,14 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
 
 	if (binfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, binfo->dobj.catId, binfo->dobj.dumpId,
-					 binfo->dobj.name,
-					 NULL, NULL,
-					 binfo->rolname,
-					 "BLOB", SECTION_PRE_DATA,
-					 cquery->data, dquery->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = binfo->dobj.name,
+						.owner = binfo->rolname,
+						.description = "BLOB",
+						.section = SECTION_PRE_DATA,
+						.createStmt = cquery->data,
+						.dropStmt = dquery->data,
+					 ));
 
 	/* Dump comment if any */
 	if (binfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -3577,14 +3592,16 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 		 */
 		if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
 			ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-						 polinfo->dobj.name,
-						 polinfo->dobj.namespace->dobj.name,
-						 NULL,
-						 tbinfo->rolname,
-						 "ROW SECURITY", SECTION_POST_DATA,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = polinfo->dobj.name,
+							.namespace = polinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.description = "ROW SECURITY",
+							.section = SECTION_POST_DATA,
+							.createStmt = query->data,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+						 ));
 
 		destroyPQExpBuffer(query);
 		return;
@@ -3633,14 +3650,15 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 
 	if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
 		ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-					 tag,
-					 polinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "POLICY", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag,
+						.namespace = polinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "POLICY",
+						.section = SECTION_POST_DATA,
+						.createStmt = query->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	free(tag);
 	destroyPQExpBuffer(query);
@@ -3807,14 +3825,14 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 	appendPQExpBufferStr(query, "');\n");
 
 	ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
-				 pubinfo->dobj.name,
-				 NULL,
-				 NULL,
-				 pubinfo->rolname,
-				 "PUBLICATION", SECTION_POST_DATA,
-				 query->data, delq->data, NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(
+					.tag = pubinfo->dobj.name,
+					.owner = pubinfo->rolname,
+					.description = "PUBLICATION",
+					.section = SECTION_POST_DATA,
+					.createStmt = query->data,
+					.dropStmt = delq->data,
+				 ));
 
 	if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "PUBLICATION", qpubname,
@@ -3950,14 +3968,13 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
 	 * done by table drop.
 	 */
 	ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
-				 tag,
-				 tbinfo->dobj.namespace->dobj.name,
-				 NULL,
-				 "",
-				 "PUBLICATION TABLE", SECTION_POST_DATA,
-				 query->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(
+					.tag = tag,
+					.namespace = tbinfo->dobj.namespace->dobj.name,
+					.description = "PUBLICATION TABLE",
+					.section = SECTION_POST_DATA,
+					.createStmt = query->data,
+				 ));
 
 	free(tag);
 	destroyPQExpBuffer(query);
@@ -4143,14 +4160,14 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 	appendPQExpBufferStr(query, ");\n");
 
 	ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
-				 subinfo->dobj.name,
-				 NULL,
-				 NULL,
-				 subinfo->rolname,
-				 "SUBSCRIPTION", SECTION_POST_DATA,
-				 query->data, delq->data, NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(
+					.tag = subinfo->dobj.name,
+					.owner = subinfo->rolname,
+					.description = "SUBSCRIPTION",
+					.section = SECTION_POST_DATA,
+					.createStmt = query->data,
+					.dropStmt = delq->data,
+				 ));
 
 	if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "SUBSCRIPTION", qsubname,
@@ -9377,11 +9394,16 @@ dumpComment(Archive *fout, const char *type, const char *name,
 		 * post-data.
 		 */
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, namespace, NULL, owner,
-					 "COMMENT", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag->data,
+						.namespace = namespace,
+						.owner = owner,
+						.description = "COMMENT",
+						.section = SECTION_NONE,
+						.createStmt = query->data,
+						.deps = &(dumpId),
+						.nDeps = 1,
+					 ));
 
 		destroyPQExpBuffer(query);
 		destroyPQExpBuffer(tag);
@@ -9443,13 +9465,16 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 tag->data,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL, tbinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = tag->data,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.description = "COMMENT",
+							.section = SECTION_NONE,
+							.createStmt = query->data,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+						 ));
 		}
 		else if (objsubid > 0 && objsubid <= tbinfo->numatts)
 		{
@@ -9467,13 +9492,16 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 tag->data,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL, tbinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = tag->data,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.description = "COMMENT",
+							.section = SECTION_NONE,
+							.createStmt = query->data,
+							.deps = &(tbinfo->dobj.dumpId),
+							.nDeps = 1,
+						 ));
 		}
 
 		comments++;
@@ -9750,11 +9778,12 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
 				TocEntry   *te;
 
 				te = ArchiveEntry(fout, dobj->catId, dobj->dumpId,
-								  dobj->name, NULL, NULL, "",
-								  "BLOBS", SECTION_DATA,
-								  "", "", NULL,
-								  NULL, 0,
-								  dumpBlobs, NULL);
+								  ARCHIVE_OPTS(
+									.tag = dobj->name,
+									.description = "BLOBS",
+									.section = SECTION_DATA,
+									.dumpFn = dumpBlobs,
+								  ));
 
 				/*
 				 * Set the TocEntry's dataLength in case we are doing a
@@ -9822,13 +9851,14 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
 	if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
-					 nspinfo->dobj.name,
-					 NULL, NULL,
-					 nspinfo->rolname,
-					 "SCHEMA", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = nspinfo->dobj.name,
+						.owner = nspinfo->rolname,
+						.description = "SCHEMA",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Schema Comments and Security Labels */
 	if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -9958,13 +9988,13 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
 	if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
-					 extinfo->dobj.name,
-					 NULL, NULL,
-					 "",
-					 "EXTENSION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = extinfo->dobj.name,
+						.description = "EXTENSION",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Extension Comments and Security Labels */
 	if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10108,14 +10138,15 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.description = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10235,14 +10266,15 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.description = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10308,14 +10340,15 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.description = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10590,14 +10623,15 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.description = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10747,14 +10781,15 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "DOMAIN", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.description = "DOMAIN",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Domain Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10969,14 +11004,15 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tyinfo->dobj.name,
+						.namespace = tyinfo->dobj.namespace->dobj.name,
+						.owner = tyinfo->rolname,
+						.description = "TYPE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 
 	/* Dump Type Comments and Security Labels */
@@ -11105,13 +11141,16 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo)
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 target->data,
-						 tyinfo->dobj.namespace->dobj.name,
-						 NULL, tyinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tyinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = target->data,
+							.namespace = tyinfo->dobj.namespace->dobj.name,
+							.owner = tyinfo->rolname,
+							.description = "COMMENT",
+							.section = SECTION_NONE,
+							.createStmt = query->data,
+							.deps = &(tyinfo->dobj.dumpId),
+							.nDeps = 1,
+						 ));
 		}
 
 		comments++;
@@ -11160,14 +11199,14 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
 
 	if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
-					 stinfo->dobj.name,
-					 stinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 stinfo->baseType->rolname,
-					 "SHELL TYPE", SECTION_PRE_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = stinfo->dobj.name,
+						.namespace = stinfo->dobj.namespace->dobj.name,
+						.owner = stinfo->baseType->rolname,
+						.description = "SHELL TYPE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+					 ));
 
 	destroyPQExpBuffer(q);
 }
@@ -11272,12 +11311,14 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
 	if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
-					 plang->dobj.name,
-					 NULL, NULL, plang->lanowner,
-					 "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = plang->dobj.name,
+						.owner = plang->lanowner,
+						.description = "PROCEDURAL LANGUAGE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = defqry->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	/* Dump Proc Lang Comments and Security Labels */
 	if (plang->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -11942,14 +11983,15 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 
 	if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
-					 funcsig_tag,
-					 finfo->dobj.namespace->dobj.name,
-					 NULL,
-					 finfo->rolname,
-					 keyword, SECTION_PRE_DATA,
-					 q->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = funcsig_tag,
+						.namespace = finfo->dobj.namespace->dobj.name,
+						.owner = finfo->rolname,
+						.description = keyword,
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	/* Dump Function Comments and Security Labels */
 	if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12077,12 +12119,13 @@ dumpCast(Archive *fout, CastInfo *cast)
 
 	if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
-					 labelq->data,
-					 NULL, NULL, "",
-					 "CAST", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = labelq->data,
+						.description = "CAST",
+						.section = SECTION_PRE_DATA,
+						.createStmt = defqry->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	/* Dump Cast Comments */
 	if (cast->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12205,12 +12248,15 @@ dumpTransform(Archive *fout, TransformInfo *transform)
 
 	if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId,
-					 labelq->data,
-					 NULL, NULL, "",
-					 "TRANSFORM", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 transform->dobj.dependencies, transform->dobj.nDeps,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = labelq->data,
+						.description = "TRANSFORM",
+						.section = SECTION_PRE_DATA,
+						.createStmt = defqry->data,
+						.dropStmt = delqry->data,
+						.deps = transform->dobj.dependencies,
+						.nDeps = transform->dobj.nDeps,
+					 ));
 
 	/* Dump Transform Comments */
 	if (transform->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12418,14 +12464,15 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
 
 	if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
-					 oprinfo->dobj.name,
-					 oprinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 oprinfo->rolname,
-					 "OPERATOR", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = oprinfo->dobj.name,
+						.namespace = oprinfo->dobj.namespace->dobj.name,
+						.owner = oprinfo->rolname,
+						.description = "OPERATOR",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Operator Comments */
 	if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12588,14 +12635,13 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
 
 	if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
-					 aminfo->dobj.name,
-					 NULL,
-					 NULL,
-					 "",
-					 "ACCESS METHOD", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = aminfo->dobj.name,
+						.description = "ACCESS METHOD",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Access Method Comments */
 	if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12954,14 +13000,15 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 
 	if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
-					 opcinfo->dobj.name,
-					 opcinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 opcinfo->rolname,
-					 "OPERATOR CLASS", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = opcinfo->dobj.name,
+						.namespace = opcinfo->dobj.namespace->dobj.name,
+						.owner = opcinfo->rolname,
+						.description = "OPERATOR CLASS",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Operator Class Comments */
 	if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13221,14 +13268,15 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
 
 	if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
-					 opfinfo->dobj.name,
-					 opfinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 opfinfo->rolname,
-					 "OPERATOR FAMILY", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = opfinfo->dobj.name,
+						.namespace = opfinfo->dobj.namespace->dobj.name,
+						.owner = opfinfo->rolname,
+						.description = "OPERATOR FAMILY",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Operator Family Comments */
 	if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13364,14 +13412,15 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
 
 	if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
-					 collinfo->dobj.name,
-					 collinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 collinfo->rolname,
-					 "COLLATION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = collinfo->dobj.name,
+						.namespace = collinfo->dobj.namespace->dobj.name,
+						.owner = collinfo->rolname,
+						.description = "COLLATION",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Collation Comments */
 	if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13459,14 +13508,15 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
 
 	if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
-					 convinfo->dobj.name,
-					 convinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 convinfo->rolname,
-					 "CONVERSION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = convinfo->dobj.name,
+						.namespace = convinfo->dobj.namespace->dobj.name,
+						.owner = convinfo->rolname,
+						.description = "CONVERSION",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Conversion Comments */
 	if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13948,14 +13998,15 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 	if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, agginfo->aggfn.dobj.catId,
 					 agginfo->aggfn.dobj.dumpId,
-					 aggsig_tag,
-					 agginfo->aggfn.dobj.namespace->dobj.name,
-					 NULL,
-					 agginfo->aggfn.rolname,
-					 "AGGREGATE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = aggsig_tag,
+						.namespace = agginfo->aggfn.dobj.namespace->dobj.name,
+						.owner = agginfo->aggfn.rolname,
+						.description = "AGGREGATE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Aggregate Comments */
 	if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14046,14 +14097,14 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
 
 	if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
-					 prsinfo->dobj.name,
-					 prsinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "TEXT SEARCH PARSER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = prsinfo->dobj.name,
+						.namespace = prsinfo->dobj.namespace->dobj.name,
+						.description = "TEXT SEARCH PARSER",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Parser Comments */
 	if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14126,14 +14177,15 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 
 	if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
-					 dictinfo->dobj.name,
-					 dictinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 dictinfo->rolname,
-					 "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = dictinfo->dobj.name,
+						.namespace = dictinfo->dobj.namespace->dobj.name,
+						.owner = dictinfo->rolname,
+						.description = "TEXT SEARCH DICTIONARY",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Dictionary Comments */
 	if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14187,14 +14239,14 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
 
 	if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
-					 tmplinfo->dobj.name,
-					 tmplinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tmplinfo->dobj.name,
+						.namespace = tmplinfo->dobj.namespace->dobj.name,
+						.description = "TEXT SEARCH TEMPLATE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Template Comments */
 	if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14307,14 +14359,15 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 
 	if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
-					 cfginfo->dobj.name,
-					 cfginfo->dobj.namespace->dobj.name,
-					 NULL,
-					 cfginfo->rolname,
-					 "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = cfginfo->dobj.name,
+						.namespace = cfginfo->dobj.namespace->dobj.name,
+						.owner = cfginfo->rolname,
+						.description = "TEXT SEARCH CONFIGURATION",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Configuration Comments */
 	if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14373,14 +14426,14 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 
 	if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
-					 fdwinfo->dobj.name,
-					 NULL,
-					 NULL,
-					 fdwinfo->rolname,
-					 "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = fdwinfo->dobj.name,
+						.owner = fdwinfo->rolname,
+						.description = "FOREIGN DATA WRAPPER",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Foreign Data Wrapper Comments */
 	if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14464,14 +14517,14 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 
 	if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
-					 srvinfo->dobj.name,
-					 NULL,
-					 NULL,
-					 srvinfo->rolname,
-					 "SERVER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = srvinfo->dobj.name,
+						.owner = srvinfo->rolname,
+						.description = "SERVER",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Foreign Server Comments */
 	if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14582,14 +14635,15 @@ dumpUserMappings(Archive *fout,
 						  usename, servername);
 
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data,
-					 namespace,
-					 NULL,
-					 owner,
-					 "USER MAPPING", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 &dumpId, 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag->data,
+						.namespace = namespace,
+						.owner = owner,
+						.description = "USER MAPPING",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 	}
 
 	PQclear(res);
@@ -14661,14 +14715,15 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
 
 	if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
 		ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
-					 tag->data,
-					 daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
-					 NULL,
-					 daclinfo->defaclrole,
-					 "DEFAULT ACL", SECTION_POST_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag->data,
+						.namespace = daclinfo->dobj.namespace ?
+									 daclinfo->dobj.namespace->dobj.name : NULL,
+						.owner = daclinfo->defaclrole,
+						.description = "DEFAULT ACL",
+						.section = SECTION_POST_DATA,
+						.createStmt = q->data,
+					 ));
 
 	destroyPQExpBuffer(tag);
 	destroyPQExpBuffer(q);
@@ -14760,13 +14815,16 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
 			appendPQExpBuffer(tag, "%s %s", type, name);
 
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, nspname,
-					 NULL,
-					 owner ? owner : "",
-					 "ACL", SECTION_NONE,
-					 sql->data, "", NULL,
-					 &(objDumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag->data,
+						.namespace = nspname,
+						.owner = owner,
+						.description = "ACL",
+						.section = SECTION_NONE,
+						.createStmt = sql->data,
+						.deps = &(objDumpId),
+						.nDeps = 1,
+					 ));
 		destroyPQExpBuffer(tag);
 	}
 
@@ -14848,11 +14906,16 @@ dumpSecLabel(Archive *fout, const char *type, const char *name,
 
 		appendPQExpBuffer(tag, "%s %s", type, name);
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, namespace, NULL, owner,
-					 "SECURITY LABEL", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag->data,
+						.namespace = namespace,
+						.owner = owner,
+						.description = "SECURITY LABEL",
+						.section = SECTION_NONE,
+						.createStmt = query->data,
+						.deps = &(dumpId),
+						.nDeps = 1,
+					 ));
 		destroyPQExpBuffer(tag);
 	}
 
@@ -14928,13 +14991,16 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
 		appendPQExpBuffer(target, "%s %s", reltypename,
 						  fmtId(tbinfo->dobj.name));
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 target->data,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL, tbinfo->rolname,
-					 "SECURITY LABEL", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(tbinfo->dobj.dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = target->data,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "SECURITY LABEL",
+						.section = SECTION_NONE,
+						.createStmt = query->data,
+						.deps = &(tbinfo->dobj.dumpId),
+						.nDeps = 1,
+					 ));
 	}
 	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(target);
@@ -16012,16 +16078,18 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
 	if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
-					 tbinfo->rolname,
-					 reltypename,
-					 tbinfo->postponed_def ?
-					 SECTION_POST_DATA : SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.tablespace = (tbinfo->relkind == RELKIND_VIEW) ?
+									  NULL : tbinfo->reltablespace,
+						.owner = tbinfo->rolname,
+						.description = reltypename,
+						.section = tbinfo->postponed_def ?
+								   SECTION_POST_DATA : SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 
 	/* Dump Table Comments */
@@ -16092,14 +16160,15 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
 
 	if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "DEFAULT", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "DEFAULT",
+						.section = SECTION_PRE_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	free(tag);
 	destroyPQExpBuffer(q);
@@ -16241,14 +16310,16 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
 
 		if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
-						 indxinfo->dobj.name,
-						 tbinfo->dobj.namespace->dobj.name,
-						 indxinfo->tablespace,
-						 tbinfo->rolname,
-						 "INDEX", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = indxinfo->dobj.name,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.tablespace = indxinfo->tablespace,
+							.owner = tbinfo->rolname,
+							.description = "INDEX",
+							.section = SECTION_POST_DATA,
+							.createStmt = q->data,
+							.dropStmt = delq->data,
+						 ));
 
 		if (indstatcolsarray)
 			free(indstatcolsarray);
@@ -16290,14 +16361,13 @@ dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo)
 						  fmtQualifiedDumpable(attachinfo->partitionIdx));
 
 		ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
-					 attachinfo->dobj.name,
-					 attachinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "INDEX ATTACH", SECTION_POST_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = attachinfo->dobj.name,
+						.namespace = attachinfo->dobj.namespace->dobj.name,
+						.description = "INDEX ATTACH",
+						.section = SECTION_POST_DATA,
+						.createStmt = q->data,
+					 ));
 
 		destroyPQExpBuffer(q);
 	}
@@ -16345,14 +16415,15 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
 	if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, statsextinfo->dobj.catId,
 					 statsextinfo->dobj.dumpId,
-					 statsextinfo->dobj.name,
-					 statsextinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 statsextinfo->rolname,
-					 "STATISTICS", SECTION_POST_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = statsextinfo->dobj.name,
+						.namespace = statsextinfo->dobj.namespace->dobj.name,
+						.owner = statsextinfo->rolname,
+						.description = "STATISTICS",
+						.section = SECTION_POST_DATA,
+						.createStmt = q->data,
+						.dropStmt = delq->data,
+					 ));
 
 	/* Dump Statistics Comments */
 	if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -16506,14 +16577,16 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 		if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-						 tag,
-						 tbinfo->dobj.namespace->dobj.name,
-						 indxinfo->tablespace,
-						 tbinfo->rolname,
-						 "CONSTRAINT", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = tag,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.tablespace = indxinfo->tablespace,
+							.owner = tbinfo->rolname,
+							.description = "CONSTRAINT",
+							.section = SECTION_POST_DATA,
+							.createStmt = q->data,
+							.dropStmt = delq->data,
+						 ));
 	}
 	else if (coninfo->contype == 'f')
 	{
@@ -16546,14 +16619,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 		if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-						 tag,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL,
-						 tbinfo->rolname,
-						 "FK CONSTRAINT", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(
+							.tag = tag,
+							.namespace = tbinfo->dobj.namespace->dobj.name,
+							.owner = tbinfo->rolname,
+							.description = "FK CONSTRAINT",
+							.section = SECTION_POST_DATA,
+							.createStmt = q->data,
+							.dropStmt = delq->data,
+						 ));
 	}
 	else if (coninfo->contype == 'c' && tbinfo)
 	{
@@ -16578,14 +16652,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 			if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-							 tag,
-							 tbinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tbinfo->rolname,
-							 "CHECK CONSTRAINT", SECTION_POST_DATA,
-							 q->data, delq->data, NULL,
-							 NULL, 0,
-							 NULL, NULL);
+							 ARCHIVE_OPTS(
+								.tag = tag,
+								.namespace = tbinfo->dobj.namespace->dobj.name,
+								.owner = tbinfo->rolname,
+								.description = "CHECK CONSTRAINT",
+								.section = SECTION_POST_DATA,
+								.createStmt = q->data,
+								.dropStmt = delq->data,
+							 ));
 		}
 	}
 	else if (coninfo->contype == 'c' && tbinfo == NULL)
@@ -16611,14 +16686,15 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 			if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-							 tag,
-							 tyinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tyinfo->rolname,
-							 "CHECK CONSTRAINT", SECTION_POST_DATA,
-							 q->data, delq->data, NULL,
-							 NULL, 0,
-							 NULL, NULL);
+							 ARCHIVE_OPTS(
+								.tag = tag,
+								.namespace = tyinfo->dobj.namespace->dobj.name,
+								.owner = tyinfo->rolname,
+								.description = "CHECK CONSTRAINT",
+								.section = SECTION_POST_DATA,
+								.createStmt = q->data,
+								.dropStmt = delq->data,
+							 ));
 		}
 	}
 	else
@@ -16885,14 +16961,15 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
 	if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "SEQUENCE", SECTION_PRE_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "SEQUENCE",
+						.section = SECTION_PRE_DATA,
+						.createStmt = query->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	/*
 	 * If the sequence is owned by a table column, emit the ALTER for it as a
@@ -16926,14 +17003,16 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
 			if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, nilCatalogId, createDumpId(),
-							 tbinfo->dobj.name,
-							 tbinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tbinfo->rolname,
-							 "SEQUENCE OWNED BY", SECTION_PRE_DATA,
-							 query->data, "", NULL,
-							 &(tbinfo->dobj.dumpId), 1,
-							 NULL, NULL);
+							 ARCHIVE_OPTS(
+								.tag = tbinfo->dobj.name,
+								.namespace = tbinfo->dobj.namespace->dobj.name,
+								.owner = tbinfo->rolname,
+								.description = "SEQUENCE OWNED BY",
+								.section = SECTION_PRE_DATA,
+								.createStmt = query->data,
+								.deps = &(tbinfo->dobj.dumpId),
+								.nDeps = 1,
+							 ));
 		}
 	}
 
@@ -16994,14 +17073,16 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo)
 
 	if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "SEQUENCE SET", SECTION_DATA,
-					 query->data, "", NULL,
-					 &(tbinfo->dobj.dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tbinfo->dobj.name,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "SEQUENCE SET",
+						.section = SECTION_DATA,
+						.createStmt = query->data,
+						.deps = &(tbinfo->dobj.dumpId),
+						.nDeps = 1,
+					 ));
 
 	PQclear(res);
 
@@ -17193,14 +17274,15 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 
 	if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "TRIGGER", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "TRIGGER",
+						.section = SECTION_POST_DATA,
+						.createStmt = query->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, trigprefix->data, qtabname,
@@ -17282,12 +17364,14 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
 
 	if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
-					 evtinfo->dobj.name, NULL, NULL,
-					 evtinfo->evtowner,
-					 "EVENT TRIGGER", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = evtinfo->dobj.name,
+						.owner = evtinfo->evtowner,
+						.description = "EVENT TRIGGER",
+						.section = SECTION_POST_DATA,
+						.createStmt = query->data,
+						.dropStmt = delqry->data,
+					 ));
 
 	if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "EVENT TRIGGER", qevtname,
@@ -17440,14 +17524,15 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 
 	if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "RULE", SECTION_POST_DATA,
-					 cmd->data, delcmd->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(
+						.tag = tag,
+						.namespace = tbinfo->dobj.namespace->dobj.name,
+						.owner = tbinfo->rolname,
+						.description = "RULE",
+						.section = SECTION_POST_DATA,
+						.createStmt = cmd->data,
+						.dropStmt = delcmd->data,
+					 ));
 
 	/* Dump rule comments */
 	if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-- 
2.16.4

#24Daniel Gustafsson
daniel@yesql.se
In reply to: Dmitry Dolgov (#23)
Re: ArchiveEntry optional arguments refactoring

On 24 Jan 2019, at 13:12, Dmitry Dolgov <9erthalion6@gmail.com> wrote:

Here is another version, where I accumulated all the suggestions:

Nothing sticks out during review and AFAICT all comments have been addressed.
Everything works as expected during (light) testing between master and an older
version.

+1 on committing this, having spent a lot of time in this code I really
appreciate the improved readability.

cheers ./daniel

#25Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Dmitry Dolgov (#23)
1 attachment(s)
Re: ArchiveEntry optional arguments refactoring

pgindent didn't like your layout with two-space indents for the struct
members :-( I thought it was nice, but oh well. This means we can do
away with the newline at each callsite, and I didn't like the trailing
comma (and I have vague recollections that some old compilers might
complain about them too, though maybe we retired them already.)

* Use NULL as a default value where it was an empty string before (this
required few minor changes for some part of the code outside ArchiveEntry)

Ah, so this is why you changed replace_line_endings. So the comment on
that function now is wrong -- it fails to indicate that it returns a
malloc'ed "" on NULL input. But about half the callers want to have a
malloc'ed "-" on NULL input ... I think it'd make the code a little bit
simpler if we did that in replace_line_endings itself, maybe add a
"want_dash" bool argument, so this code

if (!ropt->noOwner)
sanitized_owner = replace_line_endings(te->owner);
else
sanitized_owner = pg_strdup("-");

can become
sanitized_owner = replace_line_endings(te->owner, true);

I don't quite understand why the comments about line sanitization were
added in the callsites rather than in replace_line_endings itself. I
would rename the function to sanitize_line() and put those comments
there (removing them from the callsites), then the new argument I
suggest would not be completely out of place.

What do you think?

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

Attachments:

0001-ArchiveOpts-structure.patchtext/x-diff; charset=us-asciiDownload
From 86781bda4cf852f198f32aee632281fb72f4b7d0 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 1 Feb 2019 08:16:20 -0300
Subject: [PATCH] ArchiveOpts structure

ArchiveEntry function has some number of arguments, that can be
considered as optional. Refactor out arguments for ArchiveEntry into
ArchiveOpts structure, to make it more flexible for changes.

Author: Dmitry Dolgov
Discussion: https://postgr.es/m/CA+q6zcXRxPE+qp6oerQWJ3zS061WPOhdxeMrdc-Yf-2V5vsrEw@mail.gmail.com
---
 src/bin/pg_dump/pg_backup_archiver.c | 113 ++---
 src/bin/pg_dump/pg_backup_archiver.h |  31 +-
 src/bin/pg_dump/pg_dump.c            | 952 +++++++++++++++++------------------
 3 files changed, 521 insertions(+), 575 deletions(-)

diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c
index 2c2f6fb4a9..a3e530bac7 100644
--- a/src/bin/pg_dump/pg_backup_archiver.c
+++ b/src/bin/pg_dump/pg_backup_archiver.c
@@ -77,7 +77,7 @@ static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
 static void _getObjectDescription(PQExpBuffer buf, TocEntry *te,
 					  ArchiveHandle *AH);
 static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData);
-static char *replace_line_endings(const char *str);
+static char *sanitize_line(const char *str, bool want_hyphen);
 static void _doSetFixedOutputState(ArchiveHandle *AH);
 static void _doSetSessionAuth(ArchiveHandle *AH, const char *user);
 static void _reconnectToDB(ArchiveHandle *AH, const char *dbname);
@@ -1066,17 +1066,8 @@ WriteData(Archive *AHX, const void *data, size_t dLen)
 
 /* Public */
 TocEntry *
-ArchiveEntry(Archive *AHX,
-			 CatalogId catalogId, DumpId dumpId,
-			 const char *tag,
-			 const char *namespace,
-			 const char *tablespace,
-			 const char *owner,
-			 const char *desc, teSection section,
-			 const char *defn,
-			 const char *dropStmt, const char *copyStmt,
-			 const DumpId *deps, int nDeps,
-			 DataDumperPtr dumpFn, void *dumpArg)
+ArchiveEntry(Archive *AHX, CatalogId catalogId,
+			 DumpId dumpId, ArchiveOpts *opts)
 {
 	ArchiveHandle *AH = (ArchiveHandle *) AHX;
 	TocEntry   *newToc;
@@ -1094,22 +1085,22 @@ ArchiveEntry(Archive *AHX,
 
 	newToc->catalogId = catalogId;
 	newToc->dumpId = dumpId;
-	newToc->section = section;
+	newToc->section = opts->section;
 
-	newToc->tag = pg_strdup(tag);
-	newToc->namespace = namespace ? pg_strdup(namespace) : NULL;
-	newToc->tablespace = tablespace ? pg_strdup(tablespace) : NULL;
-	newToc->owner = pg_strdup(owner);
-	newToc->desc = pg_strdup(desc);
-	newToc->defn = pg_strdup(defn);
-	newToc->dropStmt = pg_strdup(dropStmt);
-	newToc->copyStmt = copyStmt ? pg_strdup(copyStmt) : NULL;
+	newToc->tag = pg_strdup(opts->tag);
+	newToc->namespace = opts->namespace ? pg_strdup(opts->namespace) : NULL;
+	newToc->tablespace = opts->tablespace ? pg_strdup(opts->tablespace) : NULL;
+	newToc->owner = opts->owner ? pg_strdup(opts->owner) : NULL;
+	newToc->desc = pg_strdup(opts->description);
+	newToc->defn = opts->createStmt ? pg_strdup(opts->createStmt) : NULL;
+	newToc->dropStmt = opts->dropStmt ? pg_strdup(opts->dropStmt) : NULL;
+	newToc->copyStmt = opts->copyStmt ? pg_strdup(opts->copyStmt) : NULL;
 
-	if (nDeps > 0)
+	if (opts->nDeps > 0)
 	{
-		newToc->dependencies = (DumpId *) pg_malloc(nDeps * sizeof(DumpId));
-		memcpy(newToc->dependencies, deps, nDeps * sizeof(DumpId));
-		newToc->nDeps = nDeps;
+		newToc->dependencies = (DumpId *) pg_malloc(opts->nDeps * sizeof(DumpId));
+		memcpy(newToc->dependencies, opts->deps, opts->nDeps * sizeof(DumpId));
+		newToc->nDeps = opts->nDeps;
 	}
 	else
 	{
@@ -1117,9 +1108,9 @@ ArchiveEntry(Archive *AHX,
 		newToc->nDeps = 0;
 	}
 
-	newToc->dataDumper = dumpFn;
-	newToc->dataDumperArg = dumpArg;
-	newToc->hadDumper = dumpFn ? true : false;
+	newToc->dataDumper = opts->dumpFn;
+	newToc->dataDumperArg = opts->dumpArg;
+	newToc->hadDumper = opts->dumpFn ? true : false;
 
 	newToc->formatData = NULL;
 	newToc->dataLength = 0;
@@ -1152,7 +1143,7 @@ PrintTOCSummary(Archive *AHX)
 
 	ahprintf(AH, ";\n; Archive created at %s\n", stamp_str);
 	ahprintf(AH, ";     dbname: %s\n;     TOC Entries: %d\n;     Compression: %d\n",
-			 replace_line_endings(AH->archdbname),
+			 sanitize_line(AH->archdbname, false),
 			 AH->tocCount, AH->compression);
 
 	switch (AH->format)
@@ -1197,21 +1188,10 @@ PrintTOCSummary(Archive *AHX)
 			char	   *sanitized_owner;
 
 			/*
-			 * As in _printTocEntry(), sanitize strings that might contain
-			 * newlines, to ensure that each logical output line is in fact
-			 * one physical output line.  This prevents confusion when the
-			 * file is read by "pg_restore -L".  Note that we currently don't
-			 * bother to quote names, meaning that the name fields aren't
-			 * automatically parseable.  "pg_restore -L" doesn't care because
-			 * it only examines the dumpId field, but someday we might want to
-			 * try harder.
 			 */
-			sanitized_name = replace_line_endings(te->tag);
-			if (te->namespace)
-				sanitized_schema = replace_line_endings(te->namespace);
-			else
-				sanitized_schema = pg_strdup("-");
-			sanitized_owner = replace_line_endings(te->owner);
+			sanitized_name = sanitize_line(te->tag, false);
+			sanitized_schema = sanitize_line(te->namespace, true);
+			sanitized_owner = sanitize_line(te->owner, false);
 
 			ahprintf(AH, "%d; %u %u %s %s %s %s\n", te->dumpId,
 					 te->catalogId.tableoid, te->catalogId.oid,
@@ -3577,21 +3557,9 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 			}
 		}
 
-		/*
-		 * Zap any line endings embedded in user-supplied fields, to prevent
-		 * corruption of the dump (which could, in the worst case, present an
-		 * SQL injection vulnerability if someone were to incautiously load a
-		 * dump containing objects with maliciously crafted names).
-		 */
-		sanitized_name = replace_line_endings(te->tag);
-		if (te->namespace)
-			sanitized_schema = replace_line_endings(te->namespace);
-		else
-			sanitized_schema = pg_strdup("-");
-		if (!ropt->noOwner)
-			sanitized_owner = replace_line_endings(te->owner);
-		else
-			sanitized_owner = pg_strdup("-");
+		sanitized_name = sanitize_line(te->tag, false);
+		sanitized_schema = sanitize_line(te->namespace, true);
+		sanitized_owner = sanitize_line(ropt->noOwner ? NULL : te->owner, true);
 
 		ahprintf(AH, "-- %sName: %s; Type: %s; Schema: %s; Owner: %s",
 				 pfx, sanitized_name, te->desc, sanitized_schema,
@@ -3605,7 +3573,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 		{
 			char	   *sanitized_tablespace;
 
-			sanitized_tablespace = replace_line_endings(te->tablespace);
+			sanitized_tablespace = sanitize_line(te->tablespace, false);
 			ahprintf(AH, "; Tablespace: %s", sanitized_tablespace);
 			free(sanitized_tablespace);
 		}
@@ -3629,7 +3597,7 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 	}
 	else
 	{
-		if (strlen(te->defn) > 0)
+		if (te->defn && strlen(te->defn) > 0)
 			ahprintf(AH, "%s\n\n", te->defn);
 	}
 
@@ -3640,7 +3608,8 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 	 * with DROP commands must appear in one list or the other.
 	 */
 	if (!ropt->noOwner && !ropt->use_setsessauth &&
-		strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
+		te->owner && strlen(te->owner) > 0 &&
+		te->dropStmt && strlen(te->dropStmt) > 0)
 	{
 		if (strcmp(te->desc, "AGGREGATE") == 0 ||
 			strcmp(te->desc, "BLOB") == 0 ||
@@ -3713,16 +3682,30 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, bool isData)
 }
 
 /*
- * Sanitize a string to be included in an SQL comment or TOC listing,
- * by replacing any newlines with spaces.
- * The result is a freshly malloc'd string.
+ * Sanitize a string to be included in an SQL comment or TOC listing, by
+ * replacing any newlines with spaces.  This ensures each logical output line
+ * is in fact one physical output line, to prevent corruption of the dump
+ * (which could, in the worst case, present an SQL injection vulnerability
+ * if someone were to incautiously load a dump containing objects with
+ * maliciously crafted names).
+ *
+ * The result is a freshly malloc'd string.  If the input string is NULL,
+ * return a malloc'ed empty string, unless want_hyphen, in which case return a
+ * malloc'ed hyphen.
+ *
+ * Note that we currently don't bother to quote names, meaning that the name
+ * fields aren't automatically parseable.  "pg_restore -L" doesn't care because
+ * it only examines the dumpId field, but someday we might want to try harder.
  */
 static char *
-replace_line_endings(const char *str)
+sanitize_line(const char *str, bool want_hyphen)
 {
 	char	   *result;
 	char	   *s;
 
+	if (!str)
+		return pg_strdup(want_hyphen ? "-" : "");
+
 	result = pg_strdup(str);
 
 	for (s = result; *s != '\0'; s++)
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 306d2ceba9..d10321be18 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -405,17 +405,28 @@ extern void on_exit_close_archive(Archive *AHX);
 
 extern void warn_or_exit_horribly(ArchiveHandle *AH, const char *modulename, const char *fmt,...) pg_attribute_printf(3, 4);
 
+typedef struct
+{
+	const char *tag;
+	const char *namespace;
+	const char *tablespace;
+	const char *owner;
+	const char *description;
+	teSection	section;
+	const char *createStmt;
+	const char *dropStmt;
+	const char *copyStmt;
+	const DumpId *deps;
+	int			nDeps;
+	DataDumperPtr dumpFn;
+	void	   *dumpArg;
+} ArchiveOpts;
+
+#define ARCHIVE_OPTS(...) &(ArchiveOpts){__VA_ARGS__}
+
 /* Called to add a TOC entry */
-extern TocEntry *ArchiveEntry(Archive *AHX,
-			 CatalogId catalogId, DumpId dumpId,
-			 const char *tag,
-			 const char *namespace, const char *tablespace,
-			 const char *owner,
-			 const char *desc, teSection section,
-			 const char *defn,
-			 const char *dropStmt, const char *copyStmt,
-			 const DumpId *deps, int nDeps,
-			 DataDumperPtr dumpFn, void *dumpArg);
+extern TocEntry *ArchiveEntry(Archive *AHX, CatalogId catalogId,
+			 DumpId dumpId, ArchiveOpts *opts);
 
 extern void WriteTOC(ArchiveHandle *AH);
 extern void ReadTOC(ArchiveHandle *AH);
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 2b1a94733b..247bb6eefa 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -2135,12 +2135,16 @@ dumpTableData(Archive *fout, TableDataInfo *tdinfo)
 		TocEntry   *te;
 
 		te = ArchiveEntry(fout, tdinfo->dobj.catId, tdinfo->dobj.dumpId,
-						  tbinfo->dobj.name, tbinfo->dobj.namespace->dobj.name,
-						  NULL, tbinfo->rolname,
-						  "TABLE DATA", SECTION_DATA,
-						  "", "", copyStmt,
-						  &(tbinfo->dobj.dumpId), 1,
-						  dumpFn, tdinfo);
+						  ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+									   .namespace = tbinfo->dobj.namespace->dobj.name,
+									   .owner = tbinfo->rolname,
+									   .description = "TABLE DATA",
+									   .section = SECTION_DATA,
+									   .copyStmt = copyStmt,
+									   .deps = &(tbinfo->dobj.dumpId),
+									   .nDeps = 1,
+									   .dumpFn = dumpFn,
+									   .dumpArg = tdinfo));
 
 		/*
 		 * Set the TocEntry's dataLength in case we are doing a parallel dump
@@ -2184,19 +2188,14 @@ refreshMatViewData(Archive *fout, TableDataInfo *tdinfo)
 		ArchiveEntry(fout,
 					 tdinfo->dobj.catId,	/* catalog ID */
 					 tdinfo->dobj.dumpId,	/* dump ID */
-					 tbinfo->dobj.name, /* Name */
-					 tbinfo->dobj.namespace->dobj.name, /* Namespace */
-					 NULL,		/* Tablespace */
-					 tbinfo->rolname,	/* Owner */
-					 "MATERIALIZED VIEW DATA",	/* Desc */
-					 SECTION_POST_DATA, /* Section */
-					 q->data,	/* Create */
-					 "",		/* Del */
-					 NULL,		/* Copy */
-					 tdinfo->dobj.dependencies, /* Deps */
-					 tdinfo->dobj.nDeps,	/* # Deps */
-					 NULL,		/* Dumper */
-					 NULL);		/* Dumper Arg */
+					 ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "MATERIALIZED VIEW DATA",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = q->data,
+								  .deps = tdinfo->dobj.dependencies,
+								  .nDeps = tdinfo->dobj.nDeps));
 
 	destroyPQExpBuffer(q);
 }
@@ -2722,19 +2721,12 @@ dumpDatabase(Archive *fout)
 	ArchiveEntry(fout,
 				 dbCatId,		/* catalog ID */
 				 dbDumpId,		/* dump ID */
-				 datname,		/* Name */
-				 NULL,			/* Namespace */
-				 NULL,			/* Tablespace */
-				 dba,			/* Owner */
-				 "DATABASE",	/* Desc */
-				 SECTION_PRE_DATA,	/* Section */
-				 creaQry->data, /* Create */
-				 delQry->data,	/* Del */
-				 NULL,			/* Copy */
-				 NULL,			/* Deps */
-				 0,				/* # Deps */
-				 NULL,			/* Dumper */
-				 NULL);			/* Dumper Arg */
+				 ARCHIVE_OPTS(.tag = datname,
+							  .owner = dba,
+							  .description = "DATABASE",
+							  .section = SECTION_PRE_DATA,
+							  .createStmt = creaQry->data,
+							  .dropStmt = delQry->data));
 
 	/* Compute correct tag for archive entry */
 	appendPQExpBuffer(labelq, "DATABASE %s", qdatname);
@@ -2762,11 +2754,13 @@ dumpDatabase(Archive *fout)
 			appendPQExpBufferStr(dbQry, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 labelq->data, NULL, NULL, dba,
-						 "COMMENT", SECTION_NONE,
-						 dbQry->data, "", NULL,
-						 &(dbDumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = labelq->data,
+									  .owner = dba,
+									  .description = "COMMENT",
+									  .section = SECTION_NONE,
+									  .createStmt = dbQry->data,
+									  .deps = &(dbDumpId),
+									  .nDeps = 1));
 		}
 	}
 	else
@@ -2789,11 +2783,13 @@ dumpDatabase(Archive *fout)
 		emitShSecLabels(conn, shres, seclabelQry, "DATABASE", datname);
 		if (seclabelQry->len > 0)
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 labelq->data, NULL, NULL, dba,
-						 "SECURITY LABEL", SECTION_NONE,
-						 seclabelQry->data, "", NULL,
-						 &(dbDumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = labelq->data,
+									  .owner = dba,
+									  .description = "SECURITY LABEL",
+									  .section = SECTION_NONE,
+									  .createStmt = seclabelQry->data,
+									  .deps = &(dbDumpId),
+									  .nDeps = 1));
 		destroyPQExpBuffer(seclabelQry);
 		PQclear(shres);
 	}
@@ -2859,11 +2855,13 @@ dumpDatabase(Archive *fout)
 
 	if (creaQry->len > 0)
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 datname, NULL, NULL, dba,
-					 "DATABASE PROPERTIES", SECTION_PRE_DATA,
-					 creaQry->data, delQry->data, NULL,
-					 &(dbDumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = datname,
+								  .owner = dba,
+								  .description = "DATABASE PROPERTIES",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = creaQry->data,
+								  .dropStmt = delQry->data,
+								  .deps = &dbDumpId));
 
 	/*
 	 * pg_largeobject comes from the old system intact, so set its
@@ -2904,11 +2902,10 @@ dumpDatabase(Archive *fout)
 						  atooid(PQgetvalue(lo_res, 0, i_relminmxid)),
 						  LargeObjectRelationId);
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 "pg_largeobject", NULL, NULL, "",
-					 "pg_largeobject", SECTION_PRE_DATA,
-					 loOutQry->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = "pg_largeobject",
+								  .description = "pg_largeobject",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = loOutQry->data));
 
 		PQclear(lo_res);
 
@@ -3014,11 +3011,10 @@ dumpEncoding(Archive *AH)
 	appendPQExpBufferStr(qry, ";\n");
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "ENCODING", NULL, NULL, "",
-				 "ENCODING", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(.tag = "ENCODING",
+							  .description = "ENCODING",
+							  .section = SECTION_PRE_DATA,
+							  .createStmt = qry->data));
 
 	destroyPQExpBuffer(qry);
 }
@@ -3041,11 +3037,10 @@ dumpStdStrings(Archive *AH)
 					  stdstrings);
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "STDSTRINGS", NULL, NULL, "",
-				 "STDSTRINGS", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(.tag = "STDSTRINGS",
+							  .description = "STDSTRINGS",
+							  .section = SECTION_PRE_DATA,
+							  .createStmt = qry->data));
 
 	destroyPQExpBuffer(qry);
 }
@@ -3097,11 +3092,10 @@ dumpSearchPath(Archive *AH)
 		write_msg(NULL, "saving search_path = %s\n", path->data);
 
 	ArchiveEntry(AH, nilCatalogId, createDumpId(),
-				 "SEARCHPATH", NULL, NULL, "",
-				 "SEARCHPATH", SECTION_PRE_DATA,
-				 qry->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(.tag = "SEARCHPATH",
+							  .description = "SEARCHPATH",
+							  .section = SECTION_PRE_DATA,
+							  .createStmt = qry->data));
 
 	/* Also save it in AH->searchpath, in case we're doing plain text dump */
 	AH->searchpath = pg_strdup(qry->data);
@@ -3273,13 +3267,12 @@ dumpBlob(Archive *fout, BlobInfo *binfo)
 
 	if (binfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, binfo->dobj.catId, binfo->dobj.dumpId,
-					 binfo->dobj.name,
-					 NULL, NULL,
-					 binfo->rolname,
-					 "BLOB", SECTION_PRE_DATA,
-					 cquery->data, dquery->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = binfo->dobj.name,
+								  .owner = binfo->rolname,
+								  .description = "BLOB",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = cquery->data,
+								  .dropStmt = dquery->data));
 
 	/* Dump comment if any */
 	if (binfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -3577,14 +3570,14 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 		 */
 		if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
 			ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-						 polinfo->dobj.name,
-						 polinfo->dobj.namespace->dobj.name,
-						 NULL,
-						 tbinfo->rolname,
-						 "ROW SECURITY", SECTION_POST_DATA,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = polinfo->dobj.name,
+									  .namespace = polinfo->dobj.namespace->dobj.name,
+									  .owner = tbinfo->rolname,
+									  .description = "ROW SECURITY",
+									  .section = SECTION_POST_DATA,
+									  .createStmt = query->data,
+									  .deps = &(tbinfo->dobj.dumpId),
+									  .nDeps = 1));
 
 		destroyPQExpBuffer(query);
 		return;
@@ -3633,14 +3626,13 @@ dumpPolicy(Archive *fout, PolicyInfo *polinfo)
 
 	if (polinfo->dobj.dump & DUMP_COMPONENT_POLICY)
 		ArchiveEntry(fout, polinfo->dobj.catId, polinfo->dobj.dumpId,
-					 tag,
-					 polinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "POLICY", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag,
+								  .namespace = polinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "POLICY",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = query->data,
+								  .dropStmt = delqry->data));
 
 	free(tag);
 	destroyPQExpBuffer(query);
@@ -3807,14 +3799,12 @@ dumpPublication(Archive *fout, PublicationInfo *pubinfo)
 	appendPQExpBufferStr(query, "');\n");
 
 	ArchiveEntry(fout, pubinfo->dobj.catId, pubinfo->dobj.dumpId,
-				 pubinfo->dobj.name,
-				 NULL,
-				 NULL,
-				 pubinfo->rolname,
-				 "PUBLICATION", SECTION_POST_DATA,
-				 query->data, delq->data, NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(.tag = pubinfo->dobj.name,
+							  .owner = pubinfo->rolname,
+							  .description = "PUBLICATION",
+							  .section = SECTION_POST_DATA,
+							  .createStmt = query->data,
+							  .dropStmt = delq->data));
 
 	if (pubinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "PUBLICATION", qpubname,
@@ -3950,14 +3940,11 @@ dumpPublicationTable(Archive *fout, PublicationRelInfo *pubrinfo)
 	 * done by table drop.
 	 */
 	ArchiveEntry(fout, pubrinfo->dobj.catId, pubrinfo->dobj.dumpId,
-				 tag,
-				 tbinfo->dobj.namespace->dobj.name,
-				 NULL,
-				 "",
-				 "PUBLICATION TABLE", SECTION_POST_DATA,
-				 query->data, "", NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(.tag = tag,
+							  .namespace = tbinfo->dobj.namespace->dobj.name,
+							  .description = "PUBLICATION TABLE",
+							  .section = SECTION_POST_DATA,
+							  .createStmt = query->data));
 
 	free(tag);
 	destroyPQExpBuffer(query);
@@ -4143,14 +4130,12 @@ dumpSubscription(Archive *fout, SubscriptionInfo *subinfo)
 	appendPQExpBufferStr(query, ");\n");
 
 	ArchiveEntry(fout, subinfo->dobj.catId, subinfo->dobj.dumpId,
-				 subinfo->dobj.name,
-				 NULL,
-				 NULL,
-				 subinfo->rolname,
-				 "SUBSCRIPTION", SECTION_POST_DATA,
-				 query->data, delq->data, NULL,
-				 NULL, 0,
-				 NULL, NULL);
+				 ARCHIVE_OPTS(.tag = subinfo->dobj.name,
+							  .owner = subinfo->rolname,
+							  .description = "SUBSCRIPTION",
+							  .section = SECTION_POST_DATA,
+							  .createStmt = query->data,
+							  .dropStmt = delq->data));
 
 	if (subinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "SUBSCRIPTION", qsubname,
@@ -9377,11 +9362,14 @@ dumpComment(Archive *fout, const char *type, const char *name,
 		 * post-data.
 		 */
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, namespace, NULL, owner,
-					 "COMMENT", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag->data,
+								  .namespace = namespace,
+								  .owner = owner,
+								  .description = "COMMENT",
+								  .section = SECTION_NONE,
+								  .createStmt = query->data,
+								  .deps = &dumpId,
+								  .nDeps = 1));
 
 		destroyPQExpBuffer(query);
 		destroyPQExpBuffer(tag);
@@ -9443,13 +9431,14 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 tag->data,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL, tbinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = tag->data,
+									  .namespace = tbinfo->dobj.namespace->dobj.name,
+									  .owner = tbinfo->rolname,
+									  .description = "COMMENT",
+									  .section = SECTION_NONE,
+									  .createStmt = query->data,
+									  .deps = &(tbinfo->dobj.dumpId),
+									  .nDeps = 1));
 		}
 		else if (objsubid > 0 && objsubid <= tbinfo->numatts)
 		{
@@ -9467,13 +9456,14 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo,
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 tag->data,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL, tbinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tbinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = tag->data,
+									  .namespace = tbinfo->dobj.namespace->dobj.name,
+									  .owner = tbinfo->rolname,
+									  .description = "COMMENT",
+									  .section = SECTION_NONE,
+									  .createStmt = query->data,
+									  .deps = &(tbinfo->dobj.dumpId),
+									  .nDeps = 1));
 		}
 
 		comments++;
@@ -9750,11 +9740,10 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj)
 				TocEntry   *te;
 
 				te = ArchiveEntry(fout, dobj->catId, dobj->dumpId,
-								  dobj->name, NULL, NULL, "",
-								  "BLOBS", SECTION_DATA,
-								  "", "", NULL,
-								  NULL, 0,
-								  dumpBlobs, NULL);
+								  ARCHIVE_OPTS(.tag = dobj->name,
+											   .description = "BLOBS",
+											   .section = SECTION_DATA,
+											   .dumpFn = dumpBlobs));
 
 				/*
 				 * Set the TocEntry's dataLength in case we are doing a
@@ -9822,13 +9811,12 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
 
 	if (nspinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
-					 nspinfo->dobj.name,
-					 NULL, NULL,
-					 nspinfo->rolname,
-					 "SCHEMA", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = nspinfo->dobj.name,
+								  .owner = nspinfo->rolname,
+								  .description = "SCHEMA",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Schema Comments and Security Labels */
 	if (nspinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -9958,13 +9946,11 @@ dumpExtension(Archive *fout, ExtensionInfo *extinfo)
 
 	if (extinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, extinfo->dobj.catId, extinfo->dobj.dumpId,
-					 extinfo->dobj.name,
-					 NULL, NULL,
-					 "",
-					 "EXTENSION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = extinfo->dobj.name,
+								  .description = "EXTENSION",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Extension Comments and Security Labels */
 	if (extinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10108,14 +10094,13 @@ dumpEnumType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+								  .namespace = tyinfo->dobj.namespace->dobj.name,
+								  .owner = tyinfo->rolname,
+								  .description = "TYPE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10235,14 +10220,13 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+								  .namespace = tyinfo->dobj.namespace->dobj.name,
+								  .owner = tyinfo->rolname,
+								  .description = "TYPE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10308,14 +10292,13 @@ dumpUndefinedType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+								  .namespace = tyinfo->dobj.namespace->dobj.name,
+								  .owner = tyinfo->rolname,
+								  .description = "TYPE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10590,14 +10573,13 @@ dumpBaseType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+								  .namespace = tyinfo->dobj.namespace->dobj.name,
+								  .owner = tyinfo->rolname,
+								  .description = "TYPE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Type Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10747,14 +10729,13 @@ dumpDomain(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "DOMAIN", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+								  .namespace = tyinfo->dobj.namespace->dobj.name,
+								  .owner = tyinfo->rolname,
+								  .description = "DOMAIN",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Domain Comments and Security Labels */
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -10969,14 +10950,13 @@ dumpCompositeType(Archive *fout, TypeInfo *tyinfo)
 
 	if (tyinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tyinfo->dobj.catId, tyinfo->dobj.dumpId,
-					 tyinfo->dobj.name,
-					 tyinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tyinfo->rolname,
-					 "TYPE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tyinfo->dobj.name,
+								  .namespace = tyinfo->dobj.namespace->dobj.name,
+								  .owner = tyinfo->rolname,
+								  .description = "TYPE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 
 	/* Dump Type Comments and Security Labels */
@@ -11105,13 +11085,14 @@ dumpCompositeTypeColComments(Archive *fout, TypeInfo *tyinfo)
 			appendPQExpBufferStr(query, ";\n");
 
 			ArchiveEntry(fout, nilCatalogId, createDumpId(),
-						 target->data,
-						 tyinfo->dobj.namespace->dobj.name,
-						 NULL, tyinfo->rolname,
-						 "COMMENT", SECTION_NONE,
-						 query->data, "", NULL,
-						 &(tyinfo->dobj.dumpId), 1,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = target->data,
+									  .namespace = tyinfo->dobj.namespace->dobj.name,
+									  .owner = tyinfo->rolname,
+									  .description = "COMMENT",
+									  .section = SECTION_NONE,
+									  .createStmt = query->data,
+									  .deps = &(tyinfo->dobj.dumpId),
+									  .nDeps = 1));
 		}
 
 		comments++;
@@ -11160,14 +11141,12 @@ dumpShellType(Archive *fout, ShellTypeInfo *stinfo)
 
 	if (stinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, stinfo->dobj.catId, stinfo->dobj.dumpId,
-					 stinfo->dobj.name,
-					 stinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 stinfo->baseType->rolname,
-					 "SHELL TYPE", SECTION_PRE_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = stinfo->dobj.name,
+								  .namespace = stinfo->dobj.namespace->dobj.name,
+								  .owner = stinfo->baseType->rolname,
+								  .description = "SHELL TYPE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data));
 
 	destroyPQExpBuffer(q);
 }
@@ -11272,12 +11251,13 @@ dumpProcLang(Archive *fout, ProcLangInfo *plang)
 
 	if (plang->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, plang->dobj.catId, plang->dobj.dumpId,
-					 plang->dobj.name,
-					 NULL, NULL, plang->lanowner,
-					 "PROCEDURAL LANGUAGE", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = plang->dobj.name,
+								  .owner = plang->lanowner,
+								  .description = "PROCEDURAL LANGUAGE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = defqry->data,
+								  .dropStmt = delqry->data,
+								  ));
 
 	/* Dump Proc Lang Comments and Security Labels */
 	if (plang->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -11942,14 +11922,13 @@ dumpFunc(Archive *fout, FuncInfo *finfo)
 
 	if (finfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, finfo->dobj.catId, finfo->dobj.dumpId,
-					 funcsig_tag,
-					 finfo->dobj.namespace->dobj.name,
-					 NULL,
-					 finfo->rolname,
-					 keyword, SECTION_PRE_DATA,
-					 q->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = funcsig_tag,
+								  .namespace = finfo->dobj.namespace->dobj.name,
+								  .owner = finfo->rolname,
+								  .description = keyword,
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delqry->data));
 
 	/* Dump Function Comments and Security Labels */
 	if (finfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12077,12 +12056,11 @@ dumpCast(Archive *fout, CastInfo *cast)
 
 	if (cast->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, cast->dobj.catId, cast->dobj.dumpId,
-					 labelq->data,
-					 NULL, NULL, "",
-					 "CAST", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = labelq->data,
+								  .description = "CAST",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = defqry->data,
+								  .dropStmt = delqry->data));
 
 	/* Dump Cast Comments */
 	if (cast->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12205,12 +12183,13 @@ dumpTransform(Archive *fout, TransformInfo *transform)
 
 	if (transform->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, transform->dobj.catId, transform->dobj.dumpId,
-					 labelq->data,
-					 NULL, NULL, "",
-					 "TRANSFORM", SECTION_PRE_DATA,
-					 defqry->data, delqry->data, NULL,
-					 transform->dobj.dependencies, transform->dobj.nDeps,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = labelq->data,
+								  .description = "TRANSFORM",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = defqry->data,
+								  .dropStmt = delqry->data,
+								  .deps = transform->dobj.dependencies,
+								  .nDeps = transform->dobj.nDeps));
 
 	/* Dump Transform Comments */
 	if (transform->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12418,14 +12397,13 @@ dumpOpr(Archive *fout, OprInfo *oprinfo)
 
 	if (oprinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, oprinfo->dobj.catId, oprinfo->dobj.dumpId,
-					 oprinfo->dobj.name,
-					 oprinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 oprinfo->rolname,
-					 "OPERATOR", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = oprinfo->dobj.name,
+								  .namespace = oprinfo->dobj.namespace->dobj.name,
+								  .owner = oprinfo->rolname,
+								  .description = "OPERATOR",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Operator Comments */
 	if (oprinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12588,14 +12566,11 @@ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
 
 	if (aminfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
-					 aminfo->dobj.name,
-					 NULL,
-					 NULL,
-					 "",
-					 "ACCESS METHOD", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = aminfo->dobj.name,
+								  .description = "ACCESS METHOD",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Access Method Comments */
 	if (aminfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -12954,14 +12929,13 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo)
 
 	if (opcinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, opcinfo->dobj.catId, opcinfo->dobj.dumpId,
-					 opcinfo->dobj.name,
-					 opcinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 opcinfo->rolname,
-					 "OPERATOR CLASS", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = opcinfo->dobj.name,
+								  .namespace = opcinfo->dobj.namespace->dobj.name,
+								  .owner = opcinfo->rolname,
+								  .description = "OPERATOR CLASS",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Operator Class Comments */
 	if (opcinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13221,14 +13195,13 @@ dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo)
 
 	if (opfinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, opfinfo->dobj.catId, opfinfo->dobj.dumpId,
-					 opfinfo->dobj.name,
-					 opfinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 opfinfo->rolname,
-					 "OPERATOR FAMILY", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = opfinfo->dobj.name,
+								  .namespace = opfinfo->dobj.namespace->dobj.name,
+								  .owner = opfinfo->rolname,
+								  .description = "OPERATOR FAMILY",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Operator Family Comments */
 	if (opfinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13364,14 +13337,13 @@ dumpCollation(Archive *fout, CollInfo *collinfo)
 
 	if (collinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, collinfo->dobj.catId, collinfo->dobj.dumpId,
-					 collinfo->dobj.name,
-					 collinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 collinfo->rolname,
-					 "COLLATION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = collinfo->dobj.name,
+								  .namespace = collinfo->dobj.namespace->dobj.name,
+								  .owner = collinfo->rolname,
+								  .description = "COLLATION",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Collation Comments */
 	if (collinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13459,14 +13431,13 @@ dumpConversion(Archive *fout, ConvInfo *convinfo)
 
 	if (convinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, convinfo->dobj.catId, convinfo->dobj.dumpId,
-					 convinfo->dobj.name,
-					 convinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 convinfo->rolname,
-					 "CONVERSION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = convinfo->dobj.name,
+								  .namespace = convinfo->dobj.namespace->dobj.name,
+								  .owner = convinfo->rolname,
+								  .description = "CONVERSION",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Conversion Comments */
 	if (convinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -13948,14 +13919,13 @@ dumpAgg(Archive *fout, AggInfo *agginfo)
 	if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, agginfo->aggfn.dobj.catId,
 					 agginfo->aggfn.dobj.dumpId,
-					 aggsig_tag,
-					 agginfo->aggfn.dobj.namespace->dobj.name,
-					 NULL,
-					 agginfo->aggfn.rolname,
-					 "AGGREGATE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = aggsig_tag,
+								  .namespace = agginfo->aggfn.dobj.namespace->dobj.name,
+								  .owner = agginfo->aggfn.rolname,
+								  .description = "AGGREGATE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Aggregate Comments */
 	if (agginfo->aggfn.dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14046,14 +14016,12 @@ dumpTSParser(Archive *fout, TSParserInfo *prsinfo)
 
 	if (prsinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, prsinfo->dobj.catId, prsinfo->dobj.dumpId,
-					 prsinfo->dobj.name,
-					 prsinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "TEXT SEARCH PARSER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = prsinfo->dobj.name,
+								  .namespace = prsinfo->dobj.namespace->dobj.name,
+								  .description = "TEXT SEARCH PARSER",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Parser Comments */
 	if (prsinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14126,14 +14094,13 @@ dumpTSDictionary(Archive *fout, TSDictInfo *dictinfo)
 
 	if (dictinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, dictinfo->dobj.catId, dictinfo->dobj.dumpId,
-					 dictinfo->dobj.name,
-					 dictinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 dictinfo->rolname,
-					 "TEXT SEARCH DICTIONARY", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = dictinfo->dobj.name,
+								  .namespace = dictinfo->dobj.namespace->dobj.name,
+								  .owner = dictinfo->rolname,
+								  .description = "TEXT SEARCH DICTIONARY",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Dictionary Comments */
 	if (dictinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14187,14 +14154,12 @@ dumpTSTemplate(Archive *fout, TSTemplateInfo *tmplinfo)
 
 	if (tmplinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tmplinfo->dobj.catId, tmplinfo->dobj.dumpId,
-					 tmplinfo->dobj.name,
-					 tmplinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "TEXT SEARCH TEMPLATE", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tmplinfo->dobj.name,
+								  .namespace = tmplinfo->dobj.namespace->dobj.name,
+								  .description = "TEXT SEARCH TEMPLATE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Template Comments */
 	if (tmplinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14307,14 +14272,13 @@ dumpTSConfig(Archive *fout, TSConfigInfo *cfginfo)
 
 	if (cfginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, cfginfo->dobj.catId, cfginfo->dobj.dumpId,
-					 cfginfo->dobj.name,
-					 cfginfo->dobj.namespace->dobj.name,
-					 NULL,
-					 cfginfo->rolname,
-					 "TEXT SEARCH CONFIGURATION", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = cfginfo->dobj.name,
+								  .namespace = cfginfo->dobj.namespace->dobj.name,
+								  .owner = cfginfo->rolname,
+								  .description = "TEXT SEARCH CONFIGURATION",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Configuration Comments */
 	if (cfginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14373,14 +14337,12 @@ dumpForeignDataWrapper(Archive *fout, FdwInfo *fdwinfo)
 
 	if (fdwinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, fdwinfo->dobj.catId, fdwinfo->dobj.dumpId,
-					 fdwinfo->dobj.name,
-					 NULL,
-					 NULL,
-					 fdwinfo->rolname,
-					 "FOREIGN DATA WRAPPER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = fdwinfo->dobj.name,
+								  .owner = fdwinfo->rolname,
+								  .description = "FOREIGN DATA WRAPPER",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Foreign Data Wrapper Comments */
 	if (fdwinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14464,14 +14426,12 @@ dumpForeignServer(Archive *fout, ForeignServerInfo *srvinfo)
 
 	if (srvinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, srvinfo->dobj.catId, srvinfo->dobj.dumpId,
-					 srvinfo->dobj.name,
-					 NULL,
-					 NULL,
-					 srvinfo->rolname,
-					 "SERVER", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = srvinfo->dobj.name,
+								  .owner = srvinfo->rolname,
+								  .description = "SERVER",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Foreign Server Comments */
 	if (srvinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -14582,14 +14542,13 @@ dumpUserMappings(Archive *fout,
 						  usename, servername);
 
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data,
-					 namespace,
-					 NULL,
-					 owner,
-					 "USER MAPPING", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 &dumpId, 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag->data,
+								  .namespace = namespace,
+								  .owner = owner,
+								  .description = "USER MAPPING",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 	}
 
 	PQclear(res);
@@ -14661,14 +14620,13 @@ dumpDefaultACL(Archive *fout, DefaultACLInfo *daclinfo)
 
 	if (daclinfo->dobj.dump & DUMP_COMPONENT_ACL)
 		ArchiveEntry(fout, daclinfo->dobj.catId, daclinfo->dobj.dumpId,
-					 tag->data,
-					 daclinfo->dobj.namespace ? daclinfo->dobj.namespace->dobj.name : NULL,
-					 NULL,
-					 daclinfo->defaclrole,
-					 "DEFAULT ACL", SECTION_POST_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag->data,
+								  .namespace = daclinfo->dobj.namespace ?
+								  daclinfo->dobj.namespace->dobj.name : NULL,
+								  .owner = daclinfo->defaclrole,
+								  .description = "DEFAULT ACL",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = q->data));
 
 	destroyPQExpBuffer(tag);
 	destroyPQExpBuffer(q);
@@ -14760,13 +14718,14 @@ dumpACL(Archive *fout, CatalogId objCatId, DumpId objDumpId,
 			appendPQExpBuffer(tag, "%s %s", type, name);
 
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, nspname,
-					 NULL,
-					 owner ? owner : "",
-					 "ACL", SECTION_NONE,
-					 sql->data, "", NULL,
-					 &(objDumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag->data,
+								  .namespace = nspname,
+								  .owner = owner,
+								  .description = "ACL",
+								  .section = SECTION_NONE,
+								  .createStmt = sql->data,
+								  .deps = &(objDumpId),
+								  .nDeps = 1));
 		destroyPQExpBuffer(tag);
 	}
 
@@ -14848,11 +14807,14 @@ dumpSecLabel(Archive *fout, const char *type, const char *name,
 
 		appendPQExpBuffer(tag, "%s %s", type, name);
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tag->data, namespace, NULL, owner,
-					 "SECURITY LABEL", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag->data,
+								  .namespace = namespace,
+								  .owner = owner,
+								  .description = "SECURITY LABEL",
+								  .section = SECTION_NONE,
+								  .createStmt = query->data,
+								  .deps = &(dumpId),
+								  .nDeps = 1));
 		destroyPQExpBuffer(tag);
 	}
 
@@ -14928,13 +14890,14 @@ dumpTableSecLabel(Archive *fout, TableInfo *tbinfo, const char *reltypename)
 		appendPQExpBuffer(target, "%s %s", reltypename,
 						  fmtId(tbinfo->dobj.name));
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 target->data,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL, tbinfo->rolname,
-					 "SECURITY LABEL", SECTION_NONE,
-					 query->data, "", NULL,
-					 &(tbinfo->dobj.dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = target->data,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "SECURITY LABEL",
+								  .section = SECTION_NONE,
+								  .createStmt = query->data,
+								  .deps = &(tbinfo->dobj.dumpId),
+								  .nDeps = 1));
 	}
 	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(target);
@@ -16012,16 +15975,16 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 
 	if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 (tbinfo->relkind == RELKIND_VIEW) ? NULL : tbinfo->reltablespace,
-					 tbinfo->rolname,
-					 reltypename,
-					 tbinfo->postponed_def ?
-					 SECTION_POST_DATA : SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .tablespace = (tbinfo->relkind == RELKIND_VIEW) ?
+								  NULL : tbinfo->reltablespace,
+								  .owner = tbinfo->rolname,
+								  .description = reltypename,
+								  .section = tbinfo->postponed_def ?
+								  SECTION_POST_DATA : SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 
 	/* Dump Table Comments */
@@ -16092,14 +16055,13 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
 
 	if (adinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, adinfo->dobj.catId, adinfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "DEFAULT", SECTION_PRE_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "DEFAULT",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	free(tag);
 	destroyPQExpBuffer(q);
@@ -16241,14 +16203,14 @@ dumpIndex(Archive *fout, IndxInfo *indxinfo)
 
 		if (indxinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, indxinfo->dobj.catId, indxinfo->dobj.dumpId,
-						 indxinfo->dobj.name,
-						 tbinfo->dobj.namespace->dobj.name,
-						 indxinfo->tablespace,
-						 tbinfo->rolname,
-						 "INDEX", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = indxinfo->dobj.name,
+									  .namespace = tbinfo->dobj.namespace->dobj.name,
+									  .tablespace = indxinfo->tablespace,
+									  .owner = tbinfo->rolname,
+									  .description = "INDEX",
+									  .section = SECTION_POST_DATA,
+									  .createStmt = q->data,
+									  .dropStmt = delq->data));
 
 		if (indstatcolsarray)
 			free(indstatcolsarray);
@@ -16290,14 +16252,11 @@ dumpIndexAttach(Archive *fout, IndexAttachInfo *attachinfo)
 						  fmtQualifiedDumpable(attachinfo->partitionIdx));
 
 		ArchiveEntry(fout, attachinfo->dobj.catId, attachinfo->dobj.dumpId,
-					 attachinfo->dobj.name,
-					 attachinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 "",
-					 "INDEX ATTACH", SECTION_POST_DATA,
-					 q->data, "", NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = attachinfo->dobj.name,
+								  .namespace = attachinfo->dobj.namespace->dobj.name,
+								  .description = "INDEX ATTACH",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = q->data));
 
 		destroyPQExpBuffer(q);
 	}
@@ -16345,14 +16304,13 @@ dumpStatisticsExt(Archive *fout, StatsExtInfo *statsextinfo)
 	if (statsextinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, statsextinfo->dobj.catId,
 					 statsextinfo->dobj.dumpId,
-					 statsextinfo->dobj.name,
-					 statsextinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 statsextinfo->rolname,
-					 "STATISTICS", SECTION_POST_DATA,
-					 q->data, delq->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = statsextinfo->dobj.name,
+								  .namespace = statsextinfo->dobj.namespace->dobj.name,
+								  .owner = statsextinfo->rolname,
+								  .description = "STATISTICS",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = q->data,
+								  .dropStmt = delq->data));
 
 	/* Dump Statistics Comments */
 	if (statsextinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
@@ -16506,14 +16464,14 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 		if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-						 tag,
-						 tbinfo->dobj.namespace->dobj.name,
-						 indxinfo->tablespace,
-						 tbinfo->rolname,
-						 "CONSTRAINT", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = tag,
+									  .namespace = tbinfo->dobj.namespace->dobj.name,
+									  .tablespace = indxinfo->tablespace,
+									  .owner = tbinfo->rolname,
+									  .description = "CONSTRAINT",
+									  .section = SECTION_POST_DATA,
+									  .createStmt = q->data,
+									  .dropStmt = delq->data));
 	}
 	else if (coninfo->contype == 'f')
 	{
@@ -16546,14 +16504,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 		if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 			ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-						 tag,
-						 tbinfo->dobj.namespace->dobj.name,
-						 NULL,
-						 tbinfo->rolname,
-						 "FK CONSTRAINT", SECTION_POST_DATA,
-						 q->data, delq->data, NULL,
-						 NULL, 0,
-						 NULL, NULL);
+						 ARCHIVE_OPTS(.tag = tag,
+									  .namespace = tbinfo->dobj.namespace->dobj.name,
+									  .owner = tbinfo->rolname,
+									  .description = "FK CONSTRAINT",
+									  .section = SECTION_POST_DATA,
+									  .createStmt = q->data,
+									  .dropStmt = delq->data));
 	}
 	else if (coninfo->contype == 'c' && tbinfo)
 	{
@@ -16578,14 +16535,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 			if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-							 tag,
-							 tbinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tbinfo->rolname,
-							 "CHECK CONSTRAINT", SECTION_POST_DATA,
-							 q->data, delq->data, NULL,
-							 NULL, 0,
-							 NULL, NULL);
+							 ARCHIVE_OPTS(.tag = tag,
+										  .namespace = tbinfo->dobj.namespace->dobj.name,
+										  .owner = tbinfo->rolname,
+										  .description = "CHECK CONSTRAINT",
+										  .section = SECTION_POST_DATA,
+										  .createStmt = q->data,
+										  .dropStmt = delq->data));
 		}
 	}
 	else if (coninfo->contype == 'c' && tbinfo == NULL)
@@ -16611,14 +16567,13 @@ dumpConstraint(Archive *fout, ConstraintInfo *coninfo)
 
 			if (coninfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, coninfo->dobj.catId, coninfo->dobj.dumpId,
-							 tag,
-							 tyinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tyinfo->rolname,
-							 "CHECK CONSTRAINT", SECTION_POST_DATA,
-							 q->data, delq->data, NULL,
-							 NULL, 0,
-							 NULL, NULL);
+							 ARCHIVE_OPTS(.tag = tag,
+										  .namespace = tyinfo->dobj.namespace->dobj.name,
+										  .owner = tyinfo->rolname,
+										  .description = "CHECK CONSTRAINT",
+										  .section = SECTION_POST_DATA,
+										  .createStmt = q->data,
+										  .dropStmt = delq->data));
 		}
 	}
 	else
@@ -16885,14 +16840,13 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
 	if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tbinfo->dobj.catId, tbinfo->dobj.dumpId,
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "SEQUENCE", SECTION_PRE_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "SEQUENCE",
+								  .section = SECTION_PRE_DATA,
+								  .createStmt = query->data,
+								  .dropStmt = delqry->data));
 
 	/*
 	 * If the sequence is owned by a table column, emit the ALTER for it as a
@@ -16926,14 +16880,14 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 
 			if (tbinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 				ArchiveEntry(fout, nilCatalogId, createDumpId(),
-							 tbinfo->dobj.name,
-							 tbinfo->dobj.namespace->dobj.name,
-							 NULL,
-							 tbinfo->rolname,
-							 "SEQUENCE OWNED BY", SECTION_PRE_DATA,
-							 query->data, "", NULL,
-							 &(tbinfo->dobj.dumpId), 1,
-							 NULL, NULL);
+							 ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+										  .namespace = tbinfo->dobj.namespace->dobj.name,
+										  .owner = tbinfo->rolname,
+										  .description = "SEQUENCE OWNED BY",
+										  .section = SECTION_PRE_DATA,
+										  .createStmt = query->data,
+										  .deps = &(tbinfo->dobj.dumpId),
+										  .nDeps = 1));
 		}
 	}
 
@@ -16994,14 +16948,14 @@ dumpSequenceData(Archive *fout, TableDataInfo *tdinfo)
 
 	if (tdinfo->dobj.dump & DUMP_COMPONENT_DATA)
 		ArchiveEntry(fout, nilCatalogId, createDumpId(),
-					 tbinfo->dobj.name,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "SEQUENCE SET", SECTION_DATA,
-					 query->data, "", NULL,
-					 &(tbinfo->dobj.dumpId), 1,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tbinfo->dobj.name,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "SEQUENCE SET",
+								  .section = SECTION_DATA,
+								  .createStmt = query->data,
+								  .deps = &(tbinfo->dobj.dumpId),
+								  .nDeps = 1));
 
 	PQclear(res);
 
@@ -17193,14 +17147,13 @@ dumpTrigger(Archive *fout, TriggerInfo *tginfo)
 
 	if (tginfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, tginfo->dobj.catId, tginfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "TRIGGER", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "TRIGGER",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = query->data,
+								  .dropStmt = delqry->data));
 
 	if (tginfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, trigprefix->data, qtabname,
@@ -17282,12 +17235,12 @@ dumpEventTrigger(Archive *fout, EventTriggerInfo *evtinfo)
 
 	if (evtinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, evtinfo->dobj.catId, evtinfo->dobj.dumpId,
-					 evtinfo->dobj.name, NULL, NULL,
-					 evtinfo->evtowner,
-					 "EVENT TRIGGER", SECTION_POST_DATA,
-					 query->data, delqry->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = evtinfo->dobj.name,
+								  .owner = evtinfo->evtowner,
+								  .description = "EVENT TRIGGER",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = query->data,
+								  .dropStmt = delqry->data));
 
 	if (evtinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
 		dumpComment(fout, "EVENT TRIGGER", qevtname,
@@ -17440,14 +17393,13 @@ dumpRule(Archive *fout, RuleInfo *rinfo)
 
 	if (rinfo->dobj.dump & DUMP_COMPONENT_DEFINITION)
 		ArchiveEntry(fout, rinfo->dobj.catId, rinfo->dobj.dumpId,
-					 tag,
-					 tbinfo->dobj.namespace->dobj.name,
-					 NULL,
-					 tbinfo->rolname,
-					 "RULE", SECTION_POST_DATA,
-					 cmd->data, delcmd->data, NULL,
-					 NULL, 0,
-					 NULL, NULL);
+					 ARCHIVE_OPTS(.tag = tag,
+								  .namespace = tbinfo->dobj.namespace->dobj.name,
+								  .owner = tbinfo->rolname,
+								  .description = "RULE",
+								  .section = SECTION_POST_DATA,
+								  .createStmt = cmd->data,
+								  .dropStmt = delcmd->data));
 
 	/* Dump rule comments */
 	if (rinfo->dobj.dump & DUMP_COMPONENT_COMMENT)
-- 
2.11.0

#26Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Alvaro Herrera (#25)
Re: ArchiveEntry optional arguments refactoring

On 2019-Feb-01, Alvaro Herrera wrote:

... so this code

if (!ropt->noOwner)
sanitized_owner = replace_line_endings(te->owner);
else
sanitized_owner = pg_strdup("-");

can become
sanitized_owner = replace_line_endings(te->owner, true);

Sorry, there's a silly bug here because I picked the wrong example to
hand-type. The proposed pattern works fine for the schema cases, not
for this owner case. The owner case is correctly handled (AFAICT) in
the patch I posted. (Also for some reason I decided to go with "hyphen"
instead of "dash" in the argument name. Not sure if anybody cares
strongly about using the right terminology there (I don't know which it
is).

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services

#27Dmitry Dolgov
9erthalion6@gmail.com
In reply to: Alvaro Herrera (#26)
Re: ArchiveEntry optional arguments refactoring

On Fri, Feb 1, 2019 at 12:33 PM Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

pgindent didn't like your layout with two-space indents for the struct
members :-( I thought it was nice, but oh well. This means we can do
away with the newline at each callsite, and I didn't like the trailing
comma (and I have vague recollections that some old compilers might
complain about them too, though maybe we retired them already.)

Oh, ok. In fact I did this almost automatically without thinking too much (a
formatting habit from other languages), so if pgindent doesn't like it, then
fine.

* Use NULL as a default value where it was an empty string before (this
required few minor changes for some part of the code outside ArchiveEntry)

I would rename the function to sanitize_line() and put those comments there
(removing them from the callsites), then the new argument I suggest would not
be completely out of place.

Yes, sounds pretty reasonable for me.

(Also for some reason I decided to go with "hyphen" instead of "dash" in the
argument name. Not sure if anybody cares strongly about using the right
terminology there (I don't know which it is).

Just out of curiosity I did some search and could find few examples of using
both "dash" and "hyphen" across the code, but I guess indeed it doesn't really
matter.

#28Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Dmitry Dolgov (#27)
Re: ArchiveEntry optional arguments refactoring

On 2019-Feb-01, Dmitry Dolgov wrote:

On Fri, Feb 1, 2019 at 12:33 PM Alvaro Herrera <alvherre@2ndquadrant.com> wrote:

* Use NULL as a default value where it was an empty string before (this
required few minor changes for some part of the code outside ArchiveEntry)

I would rename the function to sanitize_line() and put those comments there
(removing them from the callsites), then the new argument I suggest would not
be completely out of place.

Yes, sounds pretty reasonable for me.

Thanks for looking -- pushed.

--
�lvaro Herrera https://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services