src/bin/pg_dump/pg_dump.c
void
processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
					   int numExtensions)
{
	DumpOptions *dopt = fout->dopt;
	PQExpBuffer query;
	PGresult   *res;
	int			ntups,
				i;
	int			i_conrelid,
				i_confrelid;

	/* Nothing to do if no extensions */
	if (numExtensions == 0)
		return;

	/*
	 * Identify extension configuration tables and create TableDataInfo
	 * objects for them, ensuring their data will be dumped even though the
	 * tables themselves won't be.
	 *
	 * Note that we create TableDataInfo objects even in schemaOnly mode, ie,
	 * user data in a configuration table is treated like schema data. This
	 * seems appropriate since system data in a config table would get
	 * reloaded by CREATE EXTENSION.  If the extension is not listed in the
	 * list of extensions to be included, none of its data is dumped.
	 */
	for (i = 0; i < numExtensions; i++)
	{
		ExtensionInfo *curext = &(extinfo[i]);
		char	   *extconfig = curext->extconfig;
		char	   *extcondition = curext->extcondition;
		char	  **extconfigarray = NULL;
		char	  **extconditionarray = NULL;
		int			nconfigitems = 0;
		int			nconditionitems = 0;

		/*
		 * Check if this extension is listed as to include in the dump.  If
		 * not, any table data associated with it is discarded.
		 */
		if (extension_include_oids.head != NULL &&
			!simple_oid_list_member(&extension_include_oids,
									curext->dobj.catId.oid))
			continue;

		if (strlen(extconfig) != 0 || strlen(extcondition) != 0)
		{
			int			j;

			if (!parsePGArray(extconfig, &extconfigarray, &nconfigitems))
				fatal("could not parse %s array", "extconfig");
			if (!parsePGArray(extcondition, &extconditionarray, &nconditionitems))
				fatal("could not parse %s array", "extcondition");
			if (nconfigitems != nconditionitems)
				fatal("mismatched number of configurations and conditions for extension");

			for (j = 0; j < nconfigitems; j++)
			{
				TableInfo  *configtbl;
				Oid			configtbloid = atooid(extconfigarray[j]);
				bool		dumpobj =
				curext->dobj.dump & DUMP_COMPONENT_DEFINITION;

				configtbl = findTableByOid(configtbloid);
				if (configtbl == NULL)
					continue;

				/*
				 * Tables of not-to-be-dumped extensions shouldn't be dumped
				 * unless the table or its schema is explicitly included
				 */
				if (!(curext->dobj.dump & DUMP_COMPONENT_DEFINITION))
				{
					/* check table explicitly requested */
					if (table_include_oids.head != NULL &&
						simple_oid_list_member(&table_include_oids,
											   configtbloid))
						dumpobj = true;

					/* check table's schema explicitly requested */
					if (configtbl->dobj.namespace->dobj.dump &
						DUMP_COMPONENT_DATA)
						dumpobj = true;
				}

				/* check table excluded by an exclusion switch */
				if (table_exclude_oids.head != NULL &&
					simple_oid_list_member(&table_exclude_oids,
										   configtbloid))
					dumpobj = false;

				/* check schema excluded by an exclusion switch */
				if (simple_oid_list_member(&schema_exclude_oids,
										   configtbl->dobj.namespace->dobj.catId.oid))
					dumpobj = false;

				if (dumpobj)
				{
					makeTableDataInfo(dopt, configtbl);
					if (configtbl->dataObj != NULL)
					{
						if (strlen(extconditionarray[j]) > 0)
							configtbl->dataObj->filtercond = pg_strdup(extconditionarray[j]);
					}
				}
			}
		}
		if (extconfigarray)
			free(extconfigarray);
		if (extconditionarray)
			free(extconditionarray);
	}

	/*
	 * Now that all the TableDataInfo objects have been created for all the
	 * extensions, check their FK dependencies and register them to try and
	 * dump the data out in an order that they can be restored in.
	 *
	 * Note that this is not a problem for user tables as their FKs are
	 * recreated after the data has been loaded.
	 */

	query = createPQExpBuffer();

	printfPQExpBuffer(query,
					  "SELECT conrelid, confrelid "
					  "FROM pg_constraint "
					  "JOIN pg_depend ON (objid = confrelid) "
					  "WHERE contype = 'f' "
					  "AND refclassid = 'pg_extension'::regclass "
					  "AND classid = 'pg_class'::regclass;");

	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
	ntups = PQntuples(res);

	i_conrelid = PQfnumber(res, "conrelid");
	i_confrelid = PQfnumber(res, "confrelid");

	/* Now get the dependencies and register them */
	for (i = 0; i < ntups; i++)
	{
		Oid			conrelid,
					confrelid;
		TableInfo  *reftable,
				   *contable;

		conrelid = atooid(PQgetvalue(res, i, i_conrelid));
		confrelid = atooid(PQgetvalue(res, i, i_confrelid));
		contable = findTableByOid(conrelid);
		reftable = findTableByOid(confrelid);

		if (reftable == NULL ||
			reftable->dataObj == NULL ||
			contable == NULL ||
			contable->dataObj == NULL)
			continue;

		/*
		 * Make referencing TABLE_DATA object depend on the referenced table's
		 * TABLE_DATA object.
		 */
		addObjectDependency(&contable->dataObj->dobj,
							reftable->dataObj->dobj.dumpId);
	}
	PQclear(res);
	destroyPQExpBuffer(query);
}
/*
 * processExtensionTables --- deal with extension configuration tables
 *
 * There are two parts to this process:
 *
 * 1. Identify and create dump records for extension configuration tables.
 *
 *	  Extensions can mark tables as "configuration", which means that the user
 *	  is able and expected to modify those tables after the extension has been
 *	  loaded.  For these tables, we dump out only the data- the structure is
 *	  expected to be handled at CREATE EXTENSION time, including any indexes or
 *	  foreign keys, which brings us to-
 *
 * 2. Record FK dependencies between configuration tables.
 *
 *	  Due to the FKs being created at CREATE EXTENSION time and therefore before
 *	  the data is loaded, we have to work out what the best order for reloading
 *	  the data is, to avoid FK violations when the tables are restored.  This is
 *	  not perfect- we can't handle circular dependencies and if any exist they
 *	  will cause an invalid dump to be produced (though at least all of the data
 *	  is included for a user to manually restore).  This is currently documented
 *	  but perhaps we can provide a better solution in the future.
 */
deal with extension configuration tables
There are two parts to this process.

1. Identify and create dump records for extension configuration tables.

Extensions can mark tables as "configuration", which means that the user
is able and expected to modify those tables after the extension has been
loaded.  For these tables, we dump out only the data- the structure is
expected to be handled at CREATE EXTENSION time, including any indexes or
foreign keys, which brings us to

2. Record FK dependencies between configuration tables.

Due to the FKs being created at CREATE EXTENSION time and therefore before
the data is loaded, we have to work out what the best order for reloading
the data is, to avoid FK violations when the tables are restored.  This is
not perfect- we can't handle circular dependencies and if any exist they
will cause an invalid dump to be produced (though at least all of the data
is included for a user to manually restore).  This is currently documented
but perhaps we can provide a better solution in the future.
deal with extension configuration tables There are two parts to this process . 1 . Identify and create dump records for extension configuration tables . Extensions can mark tables as " configuration " which means that the user is able and expected to modify those tables after the extension has been loaded . For these tables we dump out only the data - the structure is expected to be handled at CREATE EXTENSION time including any indexes or foreign keys which brings us to 2 . Record FK dependencies between configuration tables . Due to the FKs being created at CREATE EXTENSION time and therefore before the data is loaded we have to work out what the best order for reloading the data is to avoid FK violations when the tables are restored . This is not perfect - we can ' t handle circular dependencies and if any exist they will cause an invalid dump to be produced ( though at least all of the data is included for a user to manually restore ) . This is currently documented but perhaps we can provide a better solution in the future .
void
processExtensionTables(Archive *fout, ExtensionInfo extinfo[],
					   int numExtensions)
{
	DumpOptions *dopt = fout->dopt;
	PQExpBuffer query;
	PGresult   *res;
	int			ntups,
				i;
	int			i_conrelid,
				i_confrelid;
	if (numExtensions == 0)
		return;
	for (i = 0; i < numExtensions; i++)
	{
		ExtensionInfo *curext = &(extinfo[i]);
		char	   *extconfig = curext->extconfig;
		char	   *extcondition = curext->extcondition;
		char	  **extconfigarray = NULL;
		char	  **extconditionarray = NULL;
		int			nconfigitems = 0;
		int			nconditionitems = 0;
		if (extension_include_oids.head != NULL &&
			!simple_oid_list_member(&extension_include_oids,
									curext->dobj.catId.oid))
			continue;
		if (strlen(extconfig) != 0 || strlen(extcondition) != 0)
		{
			int			j;
			if (!parsePGArray(extconfig, &extconfigarray, &nconfigitems))
				fatal("could not parse %s array", "extconfig");
			if (!parsePGArray(extcondition, &extconditionarray, &nconditionitems))
				fatal("could not parse %s array", "extcondition");
			if (nconfigitems != nconditionitems)
				fatal("mismatched number of configurations and conditions for extension");
			for (j = 0; j < nconfigitems; j++)
			{
				TableInfo  *configtbl;
				Oid			configtbloid = atooid(extconfigarray[j]);
				bool		dumpobj =
				curext->dobj.dump & DUMP_COMPONENT_DEFINITION;
				configtbl = findTableByOid(configtbloid);
				if (configtbl == NULL)
					continue;
				if (!(curext->dobj.dump & DUMP_COMPONENT_DEFINITION))
				{
					if (table_include_oids.head != NULL &&
						simple_oid_list_member(&table_include_oids,
											   configtbloid))
						dumpobj = true;
					if (configtbl->dobj.namespace->dobj.dump &
						DUMP_COMPONENT_DATA)
						dumpobj = true;
				}
				if (table_exclude_oids.head != NULL &&
					simple_oid_list_member(&table_exclude_oids,
										   configtbloid))
					dumpobj = false;
				if (simple_oid_list_member(&schema_exclude_oids,
										   configtbl->dobj.namespace->dobj.catId.oid))
					dumpobj = false;
				if (dumpobj)
				{
					makeTableDataInfo(dopt, configtbl);
					if (configtbl->dataObj != NULL)
					{
						if (strlen(extconditionarray[j]) > 0)
							configtbl->dataObj->filtercond = pg_strdup(extconditionarray[j]);
					}
				}
			}
		}
		if (extconfigarray)
			free(extconfigarray);
		if (extconditionarray)
			free(extconditionarray);
	}
	query = createPQExpBuffer();
	printfPQExpBuffer(query,
					  "SELECT conrelid, confrelid "
					  "FROM pg_constraint "
					  "JOIN pg_depend ON (objid = confrelid) "
					  "WHERE contype = 'f' "
					  "AND refclassid = 'pg_extension'::regclass "
					  "AND classid = 'pg_class'::regclass;");
	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
	ntups = PQntuples(res);
	i_conrelid = PQfnumber(res, "conrelid");
	i_confrelid = PQfnumber(res, "confrelid");
	for (i = 0; i < ntups; i++)
	{
		Oid			conrelid,
					confrelid;
		TableInfo  *reftable,
				   *contable;
		conrelid = atooid(PQgetvalue(res, i, i_conrelid));
		confrelid = atooid(PQgetvalue(res, i, i_confrelid));
		contable = findTableByOid(conrelid);
		reftable = findTableByOid(confrelid);
		if (reftable == NULL ||
			reftable->dataObj == NULL ||
			contable == NULL ||
			contable->dataObj == NULL)
			continue;
		addObjectDependency(&contable->dataObj->dobj,
							reftable->dataObj->dobj.dumpId);
	}
	PQclear(res);
	destroyPQExpBuffer(query);
}
void processExtensionTables ( Archive * fout , ExtensionInfo extinfo [ ] , int numExtensions ) { DumpOptions * dopt = fout -> dopt ; PQExpBuffer query ; PGresult * res ; int ntups , i ; int i_conrelid , i_confrelid ; if ( numExtensions == 0 ) return ; for ( i = 0 ; i < numExtensions ; i ++ ) { ExtensionInfo * curext = & ( extinfo [ i ] ) ; char * extconfig = curext -> extconfig ; char * extcondition = curext -> extcondition ; char * * extconfigarray = NULL ; char * * extconditionarray = NULL ; int nconfigitems = 0 ; int nconditionitems = 0 ; if ( extension_include_oids . head != NULL && ! simple_oid_list_member ( & extension_include_oids , curext -> dobj . catId . oid ) ) continue ; if ( strlen ( extconfig ) != 0 || strlen ( extcondition ) != 0 ) { int j ; if ( ! parsePGArray ( extconfig , & extconfigarray , & nconfigitems ) ) fatal ( " " , " " ) ; if ( ! parsePGArray ( extcondition , & extconditionarray , & nconditionitems ) ) fatal ( " " , " " ) ; if ( nconfigitems != nconditionitems ) fatal ( " " ) ; for ( j = 0 ; j < nconfigitems ; j ++ ) { TableInfo * configtbl ; Oid configtbloid = atooid ( extconfigarray [ j ] ) ; bool dumpobj = curext -> dobj . dump & DUMP_COMPONENT_DEFINITION ; configtbl = findTableByOid ( configtbloid ) ; if ( configtbl == NULL ) continue ; if ( ! ( curext -> dobj . dump & DUMP_COMPONENT_DEFINITION ) ) { if ( table_include_oids . head != NULL && simple_oid_list_member ( & table_include_oids , configtbloid ) ) dumpobj = true ; if ( configtbl -> dobj . namespace -> dobj . dump & DUMP_COMPONENT_DATA ) dumpobj = true ; } if ( table_exclude_oids . head != NULL && simple_oid_list_member ( & table_exclude_oids , configtbloid ) ) dumpobj = false ; if ( simple_oid_list_member ( & schema_exclude_oids , configtbl -> dobj . namespace -> dobj . catId . oid ) ) dumpobj = false ; if ( dumpobj ) { makeTableDataInfo ( dopt , configtbl ) ; if ( configtbl -> dataObj != NULL ) { if ( strlen ( extconditionarray [ j ] ) > 0 ) configtbl -> dataObj -> filtercond = pg_strdup ( extconditionarray [ j ] ) ; } } } } if ( extconfigarray ) free ( extconfigarray ) ; if ( extconditionarray ) free ( extconditionarray ) ; } query = createPQExpBuffer ( ) ; printfPQExpBuffer ( query , " " " " " " " " " " " " ) ; res = ExecuteSqlQuery ( fout , query -> data , PGRES_TUPLES_OK ) ; ntups = PQntuples ( res ) ; i_conrelid = PQfnumber ( res , " " ) ; i_confrelid = PQfnumber ( res , " " ) ; for ( i = 0 ; i < ntups ; i ++ ) { Oid conrelid , confrelid ; TableInfo * reftable , * contable ; conrelid = atooid ( PQgetvalue ( res , i , i_conrelid ) ) ; confrelid = atooid ( PQgetvalue ( res , i , i_confrelid ) ) ; contable = findTableByOid ( conrelid ) ; reftable = findTableByOid ( confrelid ) ; if ( reftable == NULL || reftable -> dataObj == NULL || contable == NULL || contable -> dataObj == NULL ) continue ; addObjectDependency ( & contable -> dataObj -> dobj , reftable -> dataObj -> dobj . dumpId ) ; } PQclear ( res ) ; destroyPQExpBuffer ( query ) ; }
processExtensionTables --- deal with extension configuration tables
 There are two parts to this process:
processExtensionTables --- deal with extension configuration tables There are two parts to this process :
/* Nothing to do if no extensions */ /*
	 * Identify extension configuration tables and create TableDataInfo
	 * objects for them, ensuring their data will be dumped even though the
	 * tables themselves won't be.
	 *
	 * Note that we create TableDataInfo objects even in schemaOnly mode, ie,
	 * user data in a configuration table is treated like schema data. This
	 * seems appropriate since system data in a config table would get
	 * reloaded by CREATE EXTENSION.  If the extension is not listed in the
	 * list of extensions to be included, none of its data is dumped.
	 */ /*
		 * Check if this extension is listed as to include in the dump.  If
		 * not, any table data associated with it is discarded.
		 */ /*
				 * Tables of not-to-be-dumped extensions shouldn't be dumped
				 * unless the table or its schema is explicitly included
				 */ /* check table explicitly requested */ /* check table's schema explicitly requested */ /* check table excluded by an exclusion switch */ /* check schema excluded by an exclusion switch */ /*
	 * Now that all the TableDataInfo objects have been created for all the
	 * extensions, check their FK dependencies and register them to try and
	 * dump the data out in an order that they can be restored in.
	 *
	 * Note that this is not a problem for user tables as their FKs are
	 * recreated after the data has been loaded.
	 */ /* Now get the dependencies and register them */ /*
		 * Make referencing TABLE_DATA object depend on the referenced table's
		 * TABLE_DATA object.
		 */