[PATCH] pg_dump: Sort overloaded functions in deterministic order

Started by Joel Jacobsonover 13 years ago11 messages
#1Joel Jacobson
joel@trustly.com
1 attachment(s)

I renamed the new element to DumpableObject from "proargs" to the more
general name "sortkey".

This way this element can be used by any object types in the future,
which might require sorting by additional information than type, namespace
and name.

Currently, it's only set for functions/aggregates though, its NULL for all
other object types.

I felt less ugly to add a new element with a general name than one specific
for functions.

I also moved the check to the last part of DOTypeNameCompare, just before
sorting by OIDs as a last resort.

Feedback on the implementation is welcomed.

If this can be achieved without adding a new element to DumpableObject,
it is of course much better, but I couldn't find a way of doing that.

Attachments:

pg_dump_deterministic_order_v2.patchapplication/octet-stream; name=pg_dump_deterministic_order_v2.patchDownload
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 1668,1673 **** makeTableDataInfo(TableInfo *tbinfo, bool oids)
--- 1668,1674 ----
  	tdinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
  	AssignDumpId(&tdinfo->dobj);
  	tdinfo->dobj.name = tbinfo->dobj.name;
+ 	tdinfo->dobj.sortkey = NULL;
  	tdinfo->dobj.namespace = tbinfo->dobj.namespace;
  	tdinfo->tdtable = tbinfo;
  	tdinfo->oids = oids;
***************
*** 2229,2234 **** getBlobs(Archive *fout)
--- 2230,2236 ----
  			AssignDumpId(&binfo[i].dobj);
  
  			binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, 0));
+ 			binfo[i].dobj.sortkey = NULL;
  			if (!PQgetisnull(res, i, 1))
  				binfo[i].rolname = pg_strdup(PQgetvalue(res, i, 1));
  			else
***************
*** 2659,2664 **** getNamespaces(Archive *fout, int *numNamespaces)
--- 2661,2667 ----
  		nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&nsinfo[i].dobj);
  		nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
+ 		nsinfo[i].dobj.sortkey = NULL;
  		nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));
  
***************
*** 2708,2713 **** findNamespace(Archive *fout, Oid nsoid, Oid objoid)
--- 2711,2717 ----
  		nsinfo = findNamespaceByOid(i);
  	}
  
+ 
  	if (nsinfo == NULL)
  		exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
  
***************
*** 2779,2784 **** getExtensions(Archive *fout, int *numExtensions)
--- 2783,2789 ----
  		extinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&extinfo[i].dobj);
  		extinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_extname));
+ 		extinfo[i].dobj.sortkey = NULL;
  		extinfo[i].namespace = pg_strdup(PQgetvalue(res, i, i_nspname));
  		extinfo[i].relocatable = *(PQgetvalue(res, i, i_extrelocatable)) == 't';
  		extinfo[i].extversion = pg_strdup(PQgetvalue(res, i, i_extversion));
***************
*** 2936,2941 **** getTypes(Archive *fout, int *numTypes)
--- 2941,2947 ----
  		tyinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&tyinfo[i].dobj);
  		tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname));
+ 		tyinfo[i].dobj.sortkey = NULL;
  		tyinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_typnamespace)),
***************
*** 2986,2991 **** getTypes(Archive *fout, int *numTypes)
--- 2992,2998 ----
  			stinfo->dobj.catId = nilCatalogId;
  			AssignDumpId(&stinfo->dobj);
  			stinfo->dobj.name = pg_strdup(tyinfo[i].dobj.name);
+ 			stinfo->dobj.sortkey = NULL;
  			stinfo->dobj.namespace = tyinfo[i].dobj.namespace;
  			stinfo->baseType = &(tyinfo[i]);
  			tyinfo[i].shellType = stinfo;
***************
*** 3140,3145 **** getOperators(Archive *fout, int *numOprs)
--- 3147,3153 ----
  		oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&oprinfo[i].dobj);
  		oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname));
+ 		oprinfo[i].dobj.sortkey = NULL;
  		oprinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_oprnamespace)),
***************
*** 3227,3232 **** getCollations(Archive *fout, int *numCollations)
--- 3235,3241 ----
  		collinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&collinfo[i].dobj);
  		collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname));
+ 		collinfo[i].dobj.sortkey = NULL;
  		collinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_collnamespace)),
***************
*** 3306,3311 **** getConversions(Archive *fout, int *numConversions)
--- 3315,3321 ----
  		convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&convinfo[i].dobj);
  		convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
+ 		convinfo[i].dobj.sortkey = NULL;
  		convinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_connamespace)),
***************
*** 3397,3402 **** getOpclasses(Archive *fout, int *numOpclasses)
--- 3407,3413 ----
  		opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&opcinfo[i].dobj);
  		opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname));
+ 		opcinfo[i].dobj.sortkey = NULL;
  		opcinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_opcnamespace)),
***************
*** 3485,3490 **** getOpfamilies(Archive *fout, int *numOpfamilies)
--- 3496,3502 ----
  		opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&opfinfo[i].dobj);
  		opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname));
+ 		opfinfo[i].dobj.sortkey = NULL;
  		opfinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_opfnamespace)),
***************
*** 3532,3537 **** getAggregates(Archive *fout, int *numAggs)
--- 3544,3550 ----
  	int			i_proargtypes;
  	int			i_rolname;
  	int			i_aggacl;
+ 	int			i_sortkey;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema(fout, "pg_catalog");
***************
*** 3547,3553 **** getAggregates(Archive *fout, int *numAggs)
  						  "pronamespace AS aggnamespace, "
  						  "pronargs, proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl "
  						  "FROM pg_proc p "
  						  "WHERE proisagg AND ("
  						  "pronamespace != "
--- 3560,3567 ----
  						  "pronamespace AS aggnamespace, "
  						  "pronargs, proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl, "
! 						  "pg_get_function_identity_arguments(oid) AS sortkey "
  						  "FROM pg_proc p "
  						  "WHERE proisagg AND ("
  						  "pronamespace != "
***************
*** 3570,3576 **** getAggregates(Archive *fout, int *numAggs)
  						  "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
  						  "proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl "
  						  "FROM pg_proc "
  						  "WHERE proisagg "
  						  "AND pronamespace != "
--- 3584,3591 ----
  						  "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
  						  "proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl, "
! 						  "''::text AS sortkey"
  						  "FROM pg_proc "
  						  "WHERE proisagg "
  						  "AND pronamespace != "
***************
*** 3584,3590 **** getAggregates(Archive *fout, int *numAggs)
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl "
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
--- 3599,3606 ----
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl, "
! 						  "''::text AS sortkey"
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
***************
*** 3599,3605 **** getAggregates(Archive *fout, int *numAggs)
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl "
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
--- 3615,3622 ----
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl, "
! 						  "''::text AS sortkey"
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
***************
*** 3621,3626 **** getAggregates(Archive *fout, int *numAggs)
--- 3638,3644 ----
  	i_proargtypes = PQfnumber(res, "proargtypes");
  	i_rolname = PQfnumber(res, "rolname");
  	i_aggacl = PQfnumber(res, "aggacl");
+ 	i_sortkey = PQfnumber(res, "sortkey");
  
  	for (i = 0; i < ntups; i++)
  	{
***************
*** 3629,3634 **** getAggregates(Archive *fout, int *numAggs)
--- 3647,3653 ----
  		agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&agginfo[i].aggfn.dobj);
  		agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, i_aggname));
+ 		agginfo[i].aggfn.dobj.sortkey = pg_strdup(PQgetvalue(res, i, i_sortkey));
  		agginfo[i].aggfn.dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_aggnamespace)),
***************
*** 3691,3696 **** getFuncs(Archive *fout, int *numFuncs)
--- 3710,3716 ----
  	int			i_proargtypes;
  	int			i_prorettype;
  	int			i_proacl;
+ 	int			i_sortkey;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema(fout, "pg_catalog");
***************
*** 3717,3723 **** getFuncs(Archive *fout, int *numFuncs)
  						  "SELECT tableoid, oid, proname, prolang, "
  						  "pronargs, proargtypes, prorettype, proacl, "
  						  "pronamespace, "
! 						  "(%s proowner) AS rolname "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
  						  "pronamespace != "
--- 3737,3744 ----
  						  "SELECT tableoid, oid, proname, prolang, "
  						  "pronargs, proargtypes, prorettype, proacl, "
  						  "pronamespace, "
! 						  "(%s proowner) AS rolname, "
! 						  "pg_get_function_identity_arguments(oid) AS sortkey "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
  						  "pronamespace != "
***************
*** 3745,3751 **** getFuncs(Archive *fout, int *numFuncs)
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname "
  						  "FROM pg_proc "
  						  "WHERE pg_proc.oid > '%u'::oid",
  						  username_subquery,
--- 3766,3773 ----
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname, "
! 						  "''::text AS sortkey"
  						  "FROM pg_proc "
  						  "WHERE pg_proc.oid > '%u'::oid",
  						  username_subquery,
***************
*** 3761,3767 **** getFuncs(Archive *fout, int *numFuncs)
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname "
  						  "FROM pg_proc "
  						  "where pg_proc.oid > '%u'::oid",
  						  username_subquery,
--- 3783,3790 ----
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname, "
! 						  "''::text AS sortkey"
  						  "FROM pg_proc "
  						  "where pg_proc.oid > '%u'::oid",
  						  username_subquery,
***************
*** 3786,3791 **** getFuncs(Archive *fout, int *numFuncs)
--- 3809,3815 ----
  	i_proargtypes = PQfnumber(res, "proargtypes");
  	i_prorettype = PQfnumber(res, "prorettype");
  	i_proacl = PQfnumber(res, "proacl");
+ 	i_sortkey = PQfnumber(res, "sortkey");
  
  	for (i = 0; i < ntups; i++)
  	{
***************
*** 3794,3799 **** getFuncs(Archive *fout, int *numFuncs)
--- 3818,3824 ----
  		finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&finfo[i].dobj);
  		finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname));
+ 		finfo[i].dobj.sortkey = pg_strdup(PQgetvalue(res, i, i_sortkey));
  		finfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_pronamespace)),
***************
*** 4250,4255 **** getTables(Archive *fout, int *numTables)
--- 4275,4281 ----
  		tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
  		AssignDumpId(&tblinfo[i].dobj);
  		tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname));
+ 		tblinfo[i].dobj.sortkey = NULL;
  		tblinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_relnamespace)),
***************
*** 4677,4682 **** getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
--- 4703,4709 ----
  			indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
  			AssignDumpId(&indxinfo[j].dobj);
  			indxinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_indexname));
+ 			indxinfo[j].dobj.sortkey = NULL;
  			indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
  			indxinfo[j].indextable = tbinfo;
  			indxinfo[j].indexdef = pg_strdup(PQgetvalue(res, j, i_indexdef));
***************
*** 4713,4718 **** getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
--- 4740,4746 ----
  				constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
  				AssignDumpId(&constrinfo[j].dobj);
  				constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
+ 				constrinfo[j].dobj.sortkey = NULL;
  				constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
  				constrinfo[j].contable = tbinfo;
  				constrinfo[j].condomain = NULL;
***************
*** 4821,4826 **** getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
--- 4849,4855 ----
  			constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
  			AssignDumpId(&constrinfo[j].dobj);
  			constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
+ 			constrinfo[j].dobj.sortkey = NULL;
  			constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
  			constrinfo[j].contable = tbinfo;
  			constrinfo[j].condomain = NULL;
***************
*** 4919,4924 **** getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
--- 4948,4954 ----
  		constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&constrinfo[i].dobj);
  		constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
+ 		constrinfo[i].dobj.sortkey = NULL;
  		constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
  		constrinfo[i].contable = NULL;
  		constrinfo[i].condomain = tyinfo;
***************
*** 5027,5032 **** getRules(Archive *fout, int *numRules)
--- 5057,5063 ----
  		ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&ruleinfo[i].dobj);
  		ruleinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_rulename));
+ 		ruleinfo[i].dobj.sortkey = NULL;
  		ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
  		ruleinfo[i].ruletable = findTableByOid(ruletableoid);
  		if (ruleinfo[i].ruletable == NULL)
***************
*** 5234,5239 **** getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
--- 5265,5271 ----
  			tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
  			AssignDumpId(&tginfo[j].dobj);
  			tginfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_tgname));
+ 			tginfo[j].dobj.sortkey = NULL;
  			tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
  			tginfo[j].tgtable = tbinfo;
  			tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
***************
*** 5413,5418 **** getProcLangs(Archive *fout, int *numProcLangs)
--- 5445,5451 ----
  		AssignDumpId(&planginfo[i].dobj);
  
  		planginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_lanname));
+ 		planginfo[i].dobj.sortkey = NULL;
  		planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
  		planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
  		if (i_laninline >= 0)
***************
*** 5550,5555 **** getCasts(Archive *fout, int *numCasts)
--- 5583,5589 ----
  			appendPQExpBuffer(&namebuf, "%s %s",
  							  sTypeInfo->dobj.name, tTypeInfo->dobj.name);
  		castinfo[i].dobj.name = namebuf.data;
+ 		castinfo[i].dobj.sortkey = NULL;
  
  		if (OidIsValid(castinfo[i].castfunc))
  		{
***************
*** 5924,5929 **** getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
--- 5958,5964 ----
  				attrdefs[j].adef_expr = pg_strdup(PQgetvalue(res, j, 3));
  
  				attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name);
+ 				attrdefs[j].dobj.sortkey = NULL;
  				attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
  
  				attrdefs[j].dobj.dump = tbinfo->dobj.dump;
***************
*** 6092,6097 **** getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
--- 6127,6133 ----
  				constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
  				AssignDumpId(&constrs[j].dobj);
  				constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, 2));
+ 				constrs[j].dobj.sortkey = NULL;
  				constrs[j].dobj.namespace = tbinfo->dobj.namespace;
  				constrs[j].contable = tbinfo;
  				constrs[j].condomain = NULL;
***************
*** 6232,6237 **** getTSParsers(Archive *fout, int *numTSParsers)
--- 6268,6274 ----
  		prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&prsinfo[i].dobj);
  		prsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_prsname));
+ 		prsinfo[i].dobj.sortkey = NULL;
  		prsinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_prsnamespace)),
***************
*** 6316,6321 **** getTSDictionaries(Archive *fout, int *numTSDicts)
--- 6353,6359 ----
  		dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&dictinfo[i].dobj);
  		dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname));
+ 		dictinfo[i].dobj.sortkey = NULL;
  		dictinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_dictnamespace)),
***************
*** 6397,6402 **** getTSTemplates(Archive *fout, int *numTSTemplates)
--- 6435,6441 ----
  		tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&tmplinfo[i].dobj);
  		tmplinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_tmplname));
+ 		tmplinfo[i].dobj.sortkey = NULL;
  		tmplinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_tmplnamespace)),
***************
*** 6475,6480 **** getTSConfigurations(Archive *fout, int *numTSConfigs)
--- 6514,6520 ----
  		cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&cfginfo[i].dobj);
  		cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname));
+ 		cfginfo[i].dobj.sortkey = NULL;
  		cfginfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_cfgnamespace)),
***************
*** 6581,6586 **** getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
--- 6621,6627 ----
  		fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&fdwinfo[i].dobj);
  		fdwinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_fdwname));
+ 		fdwinfo[i].dobj.sortkey = NULL;
  		fdwinfo[i].dobj.namespace = NULL;
  		fdwinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		fdwinfo[i].fdwhandler = pg_strdup(PQgetvalue(res, i, i_fdwhandler));
***************
*** 6670,6675 **** getForeignServers(Archive *fout, int *numForeignServers)
--- 6711,6717 ----
  		srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&srvinfo[i].dobj);
  		srvinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_srvname));
+ 		srvinfo[i].dobj.sortkey = NULL;
  		srvinfo[i].dobj.namespace = NULL;
  		srvinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
***************
*** 6754,6759 **** getDefaultACLs(Archive *fout, int *numDefaultACLs)
--- 6796,6802 ----
  		AssignDumpId(&daclinfo[i].dobj);
  		/* cheesy ... is it worth coming up with a better object name? */
  		daclinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_defaclobjtype));
+ 		daclinfo[i].dobj.sortkey = NULL;
  
  		if (nspid != InvalidOid)
  			daclinfo[i].dobj.namespace = findNamespace(fout, nspid,
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
***************
*** 135,140 **** typedef struct _dumpableObject
--- 135,141 ----
  	DumpId	   *dependencies;	/* dumpIds of objects this one depends on */
  	int			nDeps;			/* number of valid dependencies */
  	int			allocDeps;		/* allocated size of dependencies[] */
+ 	char	   *sortkey;		/* set to args for functions *
  } DumpableObject;
  
  typedef struct _namespaceInfo
*** a/src/bin/pg_dump/pg_dump_sort.c
--- b/src/bin/pg_dump/pg_dump_sort.c
***************
*** 215,220 **** DOTypeNameCompare(const void *p1, const void *p2)
--- 215,234 ----
  			return cmpval;
  	}
  
+ 	/*
+ 	 * Sort by sortkey.
+ 	 * This element is currently only set for functions to
+ 	 * the function identity arguments,
+ 	 * which allows sorting of overloaded functions
+ 	 * in a deterministic order.
+ 	 */
+ 	if (obj1->sortkey && obj2->sortkey)
+ 	{
+ 		cmpval = strcmp(obj1->sortkey, obj2->sortkey);
+ 		if (cmpval != 0)
+ 			return cmpval;
+ 	}
+ 
  	/* Usually shouldn't get here, but if we do, sort by OID */
  	return oidcmp(obj1->catId.oid, obj2->catId.oid);
  }
#2Joel Jacobson
joel@trustly.com
In reply to: Joel Jacobson (#1)
1 attachment(s)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

New version, made a typo in last one.

Attachments:

pg_dump_deterministic_order_v3.patchapplication/octet-stream; name=pg_dump_deterministic_order_v3.patchDownload
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 1668,1673 **** makeTableDataInfo(TableInfo *tbinfo, bool oids)
--- 1668,1674 ----
  	tdinfo->dobj.catId.oid = tbinfo->dobj.catId.oid;
  	AssignDumpId(&tdinfo->dobj);
  	tdinfo->dobj.name = tbinfo->dobj.name;
+ 	tdinfo->dobj.sortkey = NULL;
  	tdinfo->dobj.namespace = tbinfo->dobj.namespace;
  	tdinfo->tdtable = tbinfo;
  	tdinfo->oids = oids;
***************
*** 2229,2234 **** getBlobs(Archive *fout)
--- 2230,2236 ----
  			AssignDumpId(&binfo[i].dobj);
  
  			binfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, 0));
+ 			binfo[i].dobj.sortkey = NULL;
  			if (!PQgetisnull(res, i, 1))
  				binfo[i].rolname = pg_strdup(PQgetvalue(res, i, 1));
  			else
***************
*** 2659,2664 **** getNamespaces(Archive *fout, int *numNamespaces)
--- 2661,2667 ----
  		nsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&nsinfo[i].dobj);
  		nsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_nspname));
+ 		nsinfo[i].dobj.sortkey = NULL;
  		nsinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		nsinfo[i].nspacl = pg_strdup(PQgetvalue(res, i, i_nspacl));
  
***************
*** 2708,2713 **** findNamespace(Archive *fout, Oid nsoid, Oid objoid)
--- 2711,2717 ----
  		nsinfo = findNamespaceByOid(i);
  	}
  
+ 
  	if (nsinfo == NULL)
  		exit_horribly(NULL, "schema with OID %u does not exist\n", nsoid);
  
***************
*** 2779,2784 **** getExtensions(Archive *fout, int *numExtensions)
--- 2783,2789 ----
  		extinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&extinfo[i].dobj);
  		extinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_extname));
+ 		extinfo[i].dobj.sortkey = NULL;
  		extinfo[i].namespace = pg_strdup(PQgetvalue(res, i, i_nspname));
  		extinfo[i].relocatable = *(PQgetvalue(res, i, i_extrelocatable)) == 't';
  		extinfo[i].extversion = pg_strdup(PQgetvalue(res, i, i_extversion));
***************
*** 2936,2941 **** getTypes(Archive *fout, int *numTypes)
--- 2941,2947 ----
  		tyinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&tyinfo[i].dobj);
  		tyinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_typname));
+ 		tyinfo[i].dobj.sortkey = NULL;
  		tyinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_typnamespace)),
***************
*** 2986,2991 **** getTypes(Archive *fout, int *numTypes)
--- 2992,2998 ----
  			stinfo->dobj.catId = nilCatalogId;
  			AssignDumpId(&stinfo->dobj);
  			stinfo->dobj.name = pg_strdup(tyinfo[i].dobj.name);
+ 			stinfo->dobj.sortkey = NULL;
  			stinfo->dobj.namespace = tyinfo[i].dobj.namespace;
  			stinfo->baseType = &(tyinfo[i]);
  			tyinfo[i].shellType = stinfo;
***************
*** 3140,3145 **** getOperators(Archive *fout, int *numOprs)
--- 3147,3153 ----
  		oprinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&oprinfo[i].dobj);
  		oprinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_oprname));
+ 		oprinfo[i].dobj.sortkey = NULL;
  		oprinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_oprnamespace)),
***************
*** 3227,3232 **** getCollations(Archive *fout, int *numCollations)
--- 3235,3241 ----
  		collinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&collinfo[i].dobj);
  		collinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_collname));
+ 		collinfo[i].dobj.sortkey = NULL;
  		collinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_collnamespace)),
***************
*** 3306,3311 **** getConversions(Archive *fout, int *numConversions)
--- 3315,3321 ----
  		convinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&convinfo[i].dobj);
  		convinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
+ 		convinfo[i].dobj.sortkey = NULL;
  		convinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_connamespace)),
***************
*** 3397,3402 **** getOpclasses(Archive *fout, int *numOpclasses)
--- 3407,3413 ----
  		opcinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&opcinfo[i].dobj);
  		opcinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opcname));
+ 		opcinfo[i].dobj.sortkey = NULL;
  		opcinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_opcnamespace)),
***************
*** 3485,3490 **** getOpfamilies(Archive *fout, int *numOpfamilies)
--- 3496,3502 ----
  		opfinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&opfinfo[i].dobj);
  		opfinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_opfname));
+ 		opfinfo[i].dobj.sortkey = NULL;
  		opfinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_opfnamespace)),
***************
*** 3532,3537 **** getAggregates(Archive *fout, int *numAggs)
--- 3544,3550 ----
  	int			i_proargtypes;
  	int			i_rolname;
  	int			i_aggacl;
+ 	int			i_sortkey;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema(fout, "pg_catalog");
***************
*** 3547,3553 **** getAggregates(Archive *fout, int *numAggs)
  						  "pronamespace AS aggnamespace, "
  						  "pronargs, proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl "
  						  "FROM pg_proc p "
  						  "WHERE proisagg AND ("
  						  "pronamespace != "
--- 3560,3567 ----
  						  "pronamespace AS aggnamespace, "
  						  "pronargs, proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl, "
! 						  "pg_get_function_identity_arguments(oid) AS sortkey "
  						  "FROM pg_proc p "
  						  "WHERE proisagg AND ("
  						  "pronamespace != "
***************
*** 3570,3576 **** getAggregates(Archive *fout, int *numAggs)
  						  "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
  						  "proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl "
  						  "FROM pg_proc "
  						  "WHERE proisagg "
  						  "AND pronamespace != "
--- 3584,3591 ----
  						  "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
  						  "proargtypes, "
  						  "(%s proowner) AS rolname, "
! 						  "proacl AS aggacl, "
! 						  "''::text AS sortkey"
  						  "FROM pg_proc "
  						  "WHERE proisagg "
  						  "AND pronamespace != "
***************
*** 3584,3590 **** getAggregates(Archive *fout, int *numAggs)
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl "
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
--- 3599,3606 ----
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl, "
! 						  "''::text AS sortkey"
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
***************
*** 3599,3605 **** getAggregates(Archive *fout, int *numAggs)
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl "
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
--- 3615,3622 ----
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
  						  "(%s aggowner) AS rolname, "
! 						  "'{=X}' AS aggacl, "
! 						  "''::text AS sortkey"
  						  "FROM pg_aggregate "
  						  "where oid > '%u'::oid",
  						  username_subquery,
***************
*** 3621,3626 **** getAggregates(Archive *fout, int *numAggs)
--- 3638,3644 ----
  	i_proargtypes = PQfnumber(res, "proargtypes");
  	i_rolname = PQfnumber(res, "rolname");
  	i_aggacl = PQfnumber(res, "aggacl");
+ 	i_sortkey = PQfnumber(res, "sortkey");
  
  	for (i = 0; i < ntups; i++)
  	{
***************
*** 3629,3634 **** getAggregates(Archive *fout, int *numAggs)
--- 3647,3653 ----
  		agginfo[i].aggfn.dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&agginfo[i].aggfn.dobj);
  		agginfo[i].aggfn.dobj.name = pg_strdup(PQgetvalue(res, i, i_aggname));
+ 		agginfo[i].aggfn.dobj.sortkey = pg_strdup(PQgetvalue(res, i, i_sortkey));
  		agginfo[i].aggfn.dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_aggnamespace)),
***************
*** 3691,3696 **** getFuncs(Archive *fout, int *numFuncs)
--- 3710,3716 ----
  	int			i_proargtypes;
  	int			i_prorettype;
  	int			i_proacl;
+ 	int			i_sortkey;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema(fout, "pg_catalog");
***************
*** 3717,3723 **** getFuncs(Archive *fout, int *numFuncs)
  						  "SELECT tableoid, oid, proname, prolang, "
  						  "pronargs, proargtypes, prorettype, proacl, "
  						  "pronamespace, "
! 						  "(%s proowner) AS rolname "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
  						  "pronamespace != "
--- 3737,3744 ----
  						  "SELECT tableoid, oid, proname, prolang, "
  						  "pronargs, proargtypes, prorettype, proacl, "
  						  "pronamespace, "
! 						  "(%s proowner) AS rolname, "
! 						  "pg_get_function_identity_arguments(oid) AS sortkey "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
  						  "pronamespace != "
***************
*** 3745,3751 **** getFuncs(Archive *fout, int *numFuncs)
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname "
  						  "FROM pg_proc "
  						  "WHERE pg_proc.oid > '%u'::oid",
  						  username_subquery,
--- 3766,3773 ----
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname, "
! 						  "''::text AS sortkey"
  						  "FROM pg_proc "
  						  "WHERE pg_proc.oid > '%u'::oid",
  						  username_subquery,
***************
*** 3761,3767 **** getFuncs(Archive *fout, int *numFuncs)
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname "
  						  "FROM pg_proc "
  						  "where pg_proc.oid > '%u'::oid",
  						  username_subquery,
--- 3783,3790 ----
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
! 						  "(%s proowner) AS rolname, "
! 						  "''::text AS sortkey"
  						  "FROM pg_proc "
  						  "where pg_proc.oid > '%u'::oid",
  						  username_subquery,
***************
*** 3786,3791 **** getFuncs(Archive *fout, int *numFuncs)
--- 3809,3815 ----
  	i_proargtypes = PQfnumber(res, "proargtypes");
  	i_prorettype = PQfnumber(res, "prorettype");
  	i_proacl = PQfnumber(res, "proacl");
+ 	i_sortkey = PQfnumber(res, "sortkey");
  
  	for (i = 0; i < ntups; i++)
  	{
***************
*** 3794,3799 **** getFuncs(Archive *fout, int *numFuncs)
--- 3818,3824 ----
  		finfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&finfo[i].dobj);
  		finfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_proname));
+ 		finfo[i].dobj.sortkey = pg_strdup(PQgetvalue(res, i, i_sortkey));
  		finfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_pronamespace)),
***************
*** 4250,4255 **** getTables(Archive *fout, int *numTables)
--- 4275,4281 ----
  		tblinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_reloid));
  		AssignDumpId(&tblinfo[i].dobj);
  		tblinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_relname));
+ 		tblinfo[i].dobj.sortkey = NULL;
  		tblinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_relnamespace)),
***************
*** 4677,4682 **** getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
--- 4703,4709 ----
  			indxinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
  			AssignDumpId(&indxinfo[j].dobj);
  			indxinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_indexname));
+ 			indxinfo[j].dobj.sortkey = NULL;
  			indxinfo[j].dobj.namespace = tbinfo->dobj.namespace;
  			indxinfo[j].indextable = tbinfo;
  			indxinfo[j].indexdef = pg_strdup(PQgetvalue(res, j, i_indexdef));
***************
*** 4713,4718 **** getIndexes(Archive *fout, TableInfo tblinfo[], int numTables)
--- 4740,4746 ----
  				constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
  				AssignDumpId(&constrinfo[j].dobj);
  				constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
+ 				constrinfo[j].dobj.sortkey = NULL;
  				constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
  				constrinfo[j].contable = tbinfo;
  				constrinfo[j].condomain = NULL;
***************
*** 4821,4826 **** getConstraints(Archive *fout, TableInfo tblinfo[], int numTables)
--- 4849,4855 ----
  			constrinfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_conoid));
  			AssignDumpId(&constrinfo[j].dobj);
  			constrinfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_conname));
+ 			constrinfo[j].dobj.sortkey = NULL;
  			constrinfo[j].dobj.namespace = tbinfo->dobj.namespace;
  			constrinfo[j].contable = tbinfo;
  			constrinfo[j].condomain = NULL;
***************
*** 4919,4924 **** getDomainConstraints(Archive *fout, TypeInfo *tyinfo)
--- 4948,4954 ----
  		constrinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&constrinfo[i].dobj);
  		constrinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_conname));
+ 		constrinfo[i].dobj.sortkey = NULL;
  		constrinfo[i].dobj.namespace = tyinfo->dobj.namespace;
  		constrinfo[i].contable = NULL;
  		constrinfo[i].condomain = tyinfo;
***************
*** 5027,5032 **** getRules(Archive *fout, int *numRules)
--- 5057,5063 ----
  		ruleinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&ruleinfo[i].dobj);
  		ruleinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_rulename));
+ 		ruleinfo[i].dobj.sortkey = NULL;
  		ruletableoid = atooid(PQgetvalue(res, i, i_ruletable));
  		ruleinfo[i].ruletable = findTableByOid(ruletableoid);
  		if (ruleinfo[i].ruletable == NULL)
***************
*** 5234,5239 **** getTriggers(Archive *fout, TableInfo tblinfo[], int numTables)
--- 5265,5271 ----
  			tginfo[j].dobj.catId.oid = atooid(PQgetvalue(res, j, i_oid));
  			AssignDumpId(&tginfo[j].dobj);
  			tginfo[j].dobj.name = pg_strdup(PQgetvalue(res, j, i_tgname));
+ 			tginfo[j].dobj.sortkey = NULL;
  			tginfo[j].dobj.namespace = tbinfo->dobj.namespace;
  			tginfo[j].tgtable = tbinfo;
  			tginfo[j].tgenabled = *(PQgetvalue(res, j, i_tgenabled));
***************
*** 5413,5418 **** getProcLangs(Archive *fout, int *numProcLangs)
--- 5445,5451 ----
  		AssignDumpId(&planginfo[i].dobj);
  
  		planginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_lanname));
+ 		planginfo[i].dobj.sortkey = NULL;
  		planginfo[i].lanpltrusted = *(PQgetvalue(res, i, i_lanpltrusted)) == 't';
  		planginfo[i].lanplcallfoid = atooid(PQgetvalue(res, i, i_lanplcallfoid));
  		if (i_laninline >= 0)
***************
*** 5550,5555 **** getCasts(Archive *fout, int *numCasts)
--- 5583,5589 ----
  			appendPQExpBuffer(&namebuf, "%s %s",
  							  sTypeInfo->dobj.name, tTypeInfo->dobj.name);
  		castinfo[i].dobj.name = namebuf.data;
+ 		castinfo[i].dobj.sortkey = NULL;
  
  		if (OidIsValid(castinfo[i].castfunc))
  		{
***************
*** 5924,5929 **** getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
--- 5958,5964 ----
  				attrdefs[j].adef_expr = pg_strdup(PQgetvalue(res, j, 3));
  
  				attrdefs[j].dobj.name = pg_strdup(tbinfo->dobj.name);
+ 				attrdefs[j].dobj.sortkey = NULL;
  				attrdefs[j].dobj.namespace = tbinfo->dobj.namespace;
  
  				attrdefs[j].dobj.dump = tbinfo->dobj.dump;
***************
*** 6092,6097 **** getTableAttrs(Archive *fout, TableInfo *tblinfo, int numTables)
--- 6127,6133 ----
  				constrs[j].dobj.catId.oid = atooid(PQgetvalue(res, j, 1));
  				AssignDumpId(&constrs[j].dobj);
  				constrs[j].dobj.name = pg_strdup(PQgetvalue(res, j, 2));
+ 				constrs[j].dobj.sortkey = NULL;
  				constrs[j].dobj.namespace = tbinfo->dobj.namespace;
  				constrs[j].contable = tbinfo;
  				constrs[j].condomain = NULL;
***************
*** 6232,6237 **** getTSParsers(Archive *fout, int *numTSParsers)
--- 6268,6274 ----
  		prsinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&prsinfo[i].dobj);
  		prsinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_prsname));
+ 		prsinfo[i].dobj.sortkey = NULL;
  		prsinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_prsnamespace)),
***************
*** 6316,6321 **** getTSDictionaries(Archive *fout, int *numTSDicts)
--- 6353,6359 ----
  		dictinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&dictinfo[i].dobj);
  		dictinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_dictname));
+ 		dictinfo[i].dobj.sortkey = NULL;
  		dictinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_dictnamespace)),
***************
*** 6397,6402 **** getTSTemplates(Archive *fout, int *numTSTemplates)
--- 6435,6441 ----
  		tmplinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&tmplinfo[i].dobj);
  		tmplinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_tmplname));
+ 		tmplinfo[i].dobj.sortkey = NULL;
  		tmplinfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_tmplnamespace)),
***************
*** 6475,6480 **** getTSConfigurations(Archive *fout, int *numTSConfigs)
--- 6514,6520 ----
  		cfginfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&cfginfo[i].dobj);
  		cfginfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_cfgname));
+ 		cfginfo[i].dobj.sortkey = NULL;
  		cfginfo[i].dobj.namespace =
  			findNamespace(fout,
  						  atooid(PQgetvalue(res, i, i_cfgnamespace)),
***************
*** 6581,6586 **** getForeignDataWrappers(Archive *fout, int *numForeignDataWrappers)
--- 6621,6627 ----
  		fdwinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&fdwinfo[i].dobj);
  		fdwinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_fdwname));
+ 		fdwinfo[i].dobj.sortkey = NULL;
  		fdwinfo[i].dobj.namespace = NULL;
  		fdwinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		fdwinfo[i].fdwhandler = pg_strdup(PQgetvalue(res, i, i_fdwhandler));
***************
*** 6670,6675 **** getForeignServers(Archive *fout, int *numForeignServers)
--- 6711,6717 ----
  		srvinfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
  		AssignDumpId(&srvinfo[i].dobj);
  		srvinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_srvname));
+ 		srvinfo[i].dobj.sortkey = NULL;
  		srvinfo[i].dobj.namespace = NULL;
  		srvinfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		srvinfo[i].srvfdw = atooid(PQgetvalue(res, i, i_srvfdw));
***************
*** 6754,6759 **** getDefaultACLs(Archive *fout, int *numDefaultACLs)
--- 6796,6802 ----
  		AssignDumpId(&daclinfo[i].dobj);
  		/* cheesy ... is it worth coming up with a better object name? */
  		daclinfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_defaclobjtype));
+ 		daclinfo[i].dobj.sortkey = NULL;
  
  		if (nspid != InvalidOid)
  			daclinfo[i].dobj.namespace = findNamespace(fout, nspid,
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
***************
*** 135,140 **** typedef struct _dumpableObject
--- 135,141 ----
  	DumpId	   *dependencies;	/* dumpIds of objects this one depends on */
  	int			nDeps;			/* number of valid dependencies */
  	int			allocDeps;		/* allocated size of dependencies[] */
+ 	char	   *sortkey;		/* set to args for functions */
  } DumpableObject;
  
  typedef struct _namespaceInfo
*** a/src/bin/pg_dump/pg_dump_sort.c
--- b/src/bin/pg_dump/pg_dump_sort.c
***************
*** 215,220 **** DOTypeNameCompare(const void *p1, const void *p2)
--- 215,234 ----
  			return cmpval;
  	}
  
+ 	/*
+ 	 * Sort by sortkey.
+ 	 * This element is currently only set for functions to
+ 	 * the function identity arguments,
+ 	 * which allows sorting of overloaded functions
+ 	 * in a deterministic order.
+ 	 */
+ 	if (obj1->sortkey && obj2->sortkey)
+ 	{
+ 		cmpval = strcmp(obj1->sortkey, obj2->sortkey);
+ 		if (cmpval != 0)
+ 			return cmpval;
+ 	}
+ 
  	/* Usually shouldn't get here, but if we do, sort by OID */
  	return oidcmp(obj1->catId.oid, obj2->catId.oid);
  }
#3Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joel Jacobson (#2)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

Joel Jacobson <joel@trustly.com> writes:

New version, made a typo in last one.

I'm not particularly happy with the idea of adding a sortkey field to
DumpableObject as such, when most object types don't need it. That just
bloats the code and pg_dump's memory consumption. It would be better to
modify the already-existing object-type-specific special cases in
DOTypeNameCompare to take additional information into account as needed.

BTW, I see no reason to be adding extra calls of
pg_get_function_identity_arguments. What is wrong with the funcsig or
aggsig strings that the code already computes?

regards, tom lane

#4Joel Jacobson
joel@trustly.com
In reply to: Tom Lane (#3)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

I agree, good suggestion, I just didn't know how to implement it without a
new field. I'll make a new attempt to get it right.

On Thursday, July 5, 2012, Tom Lane wrote:

Show quoted text

Joel Jacobson <joel@trustly.com <javascript:;>> writes:

New version, made a typo in last one.

I'm not particularly happy with the idea of adding a sortkey field to
DumpableObject as such, when most object types don't need it. That just
bloats the code and pg_dump's memory consumption. It would be better to
modify the already-existing object-type-specific special cases in
DOTypeNameCompare to take additional information into account as needed.

BTW, I see no reason to be adding extra calls of
pg_get_function_identity_arguments. What is wrong with the funcsig or
aggsig strings that the code already computes?

regards, tom lane

#5Tom Lane
tgl@sss.pgh.pa.us
In reply to: Joel Jacobson (#4)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

Joel Jacobson <joel@trustly.com> writes:

I agree, good suggestion, I just didn't know how to implement it without a
new field. I'll make a new attempt to get it right.

You may in fact need a new field --- I'm just saying it should be in the
object-type-specific struct, eg FuncInfo, not DumpableObject.

regards, tom lane

#6Joel Jacobson
joel@trustly.com
In reply to: Tom Lane (#5)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

Roger that. I'm on it.

On Thursday, July 5, 2012, Tom Lane wrote:

Show quoted text

Joel Jacobson <joel@trustly.com <javascript:;>> writes:
You may in fact need a new field --- I'm just saying it should be in the
object-type-specific struct, eg FuncInfo, not DumpableObject.

regards, tom lane

#7Joel Jacobson
joel@trustly.com
In reply to: Tom Lane (#5)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

On Thu, Jul 5, 2012 at 10:33 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

You may in fact need a new field --- I'm just saying it should be in the
object-type-specific struct, eg FuncInfo, not DumpableObject.

I suggest adding char *funcsig to FuncInfo, and moving the "funcsig =
format_function_arguments(finfo, funciargs)" code from dumpFunc to getFuncs.

Because dumpFunc is called after sortDumpableObjectsByTypeName, setting
funcsig in the FuncInfo struct in dumpFunc would't work, as it needs to be
available when entering sortDumpableObjectsByTypeName.

What do you think?

#8Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Joel Jacobson (#7)
1 attachment(s)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

Joel Jacobson wrote:

On Thu, Jul 5, 2012 at 10:33 PM, Tom Lane <tgl@sss.pgh.pa.us> wrote:

You may in fact need a new field --- I'm just saying it should be in the
object-type-specific struct, eg FuncInfo, not DumpableObject.

I suggest adding char *funcsig to FuncInfo, and moving the "funcsig =
format_function_arguments(finfo, funciargs)" code from dumpFunc to getFuncs.

Because dumpFunc is called after sortDumpableObjectsByTypeName, setting
funcsig in the FuncInfo struct in dumpFunc would't work, as it needs to be
available when entering sortDumpableObjectsByTypeName.

Uh, the patch you posted keeps the pg_get_function_identity_arguments
call in dumpFunc, but there is now also a new one in getFuncs. Do we
need to remove the second one?

Here's an updated patch for your consideration. I was about to push
this when I noticed the above. The only change here is that the extra
code that tests for new remoteVersions in the second "else if" branch of
getFuncs and getAggregates has been removed, since it cannot ever be
reached.

(I tested the new pg_dump with 8.2 and HEAD and also verified it passes
pg_upgrade's "make check". I didn't test with other server versions.)

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services

Attachments:

pg_dump_deterministic_order_v6.patchtext/x-diff; charset=us-asciiDownload
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
***************
*** 3534,3539 **** getAggregates(Archive *fout, int *numAggs)
--- 3534,3540 ----
  	int			i_proargtypes;
  	int			i_rolname;
  	int			i_aggacl;
+ 	int			i_proiargs;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema(fout, "pg_catalog");
***************
*** 3543,3553 **** getAggregates(Archive *fout, int *numAggs)
  	 * rationale behind the filtering logic.
  	 */
  
! 	if (fout->remoteVersion >= 80200)
  	{
  		appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
  						  "pronamespace AS aggnamespace, "
  						  "pronargs, proargtypes, "
  						  "(%s proowner) AS rolname, "
  						  "proacl AS aggacl "
  						  "FROM pg_proc p "
--- 3544,3555 ----
  	 * rationale behind the filtering logic.
  	 */
  
! 	if (fout->remoteVersion >= 80400)
  	{
  		appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
  						  "pronamespace AS aggnamespace, "
  						  "pronargs, proargtypes, "
+ 						  "pg_catalog.pg_get_function_identity_arguments(oid) AS proiargs,"
  						  "(%s proowner) AS rolname, "
  						  "proacl AS aggacl "
  						  "FROM pg_proc p "
***************
*** 3565,3576 **** getAggregates(Archive *fout, int *numAggs)
--- 3567,3594 ----
  							  "deptype = 'e')");
  		appendPQExpBuffer(query, ")");
  	}
+ 	else if (fout->remoteVersion >= 80200)
+ 	{
+ 		appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
+ 						  "pronamespace AS aggnamespace, "
+ 						  "pronargs, proargtypes, "
+ 						  "NULL::text AS proiargs,"
+ 						  "(%s proowner) AS rolname, "
+ 						  "proacl AS aggacl "
+ 						  "FROM pg_proc p "
+ 						  "WHERE proisagg AND ("
+ 						  "pronamespace != "
+ 						  "(SELECT oid FROM pg_namespace "
+ 						  "WHERE nspname = 'pg_catalog'))",
+ 						  username_subquery);
+ 	}
  	else if (fout->remoteVersion >= 70300)
  	{
  		appendPQExpBuffer(query, "SELECT tableoid, oid, proname AS aggname, "
  						  "pronamespace AS aggnamespace, "
  						  "CASE WHEN proargtypes[0] = 'pg_catalog.\"any\"'::pg_catalog.regtype THEN 0 ELSE 1 END AS pronargs, "
  						  "proargtypes, "
+ 						  "NULL::text AS proiargs, "
  						  "(%s proowner) AS rolname, "
  						  "proacl AS aggacl "
  						  "FROM pg_proc "
***************
*** 3585,3590 **** getAggregates(Archive *fout, int *numAggs)
--- 3603,3609 ----
  						  "0::oid AS aggnamespace, "
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
+ 						  "NULL::text AS proiargs, "
  						  "(%s aggowner) AS rolname, "
  						  "'{=X}' AS aggacl "
  						  "FROM pg_aggregate "
***************
*** 3600,3605 **** getAggregates(Archive *fout, int *numAggs)
--- 3619,3625 ----
  						  "0::oid AS aggnamespace, "
  				  "CASE WHEN aggbasetype = 0 THEN 0 ELSE 1 END AS pronargs, "
  						  "aggbasetype AS proargtypes, "
+ 						  "NULL::text AS proiargs, "
  						  "(%s aggowner) AS rolname, "
  						  "'{=X}' AS aggacl "
  						  "FROM pg_aggregate "
***************
*** 3623,3628 **** getAggregates(Archive *fout, int *numAggs)
--- 3643,3649 ----
  	i_proargtypes = PQfnumber(res, "proargtypes");
  	i_rolname = PQfnumber(res, "rolname");
  	i_aggacl = PQfnumber(res, "aggacl");
+ 	i_proiargs = PQfnumber(res, "proiargs");
  
  	for (i = 0; i < ntups; i++)
  	{
***************
*** 3642,3647 **** getAggregates(Archive *fout, int *numAggs)
--- 3663,3669 ----
  		agginfo[i].aggfn.lang = InvalidOid;		/* not currently interesting */
  		agginfo[i].aggfn.prorettype = InvalidOid;		/* not saved */
  		agginfo[i].aggfn.proacl = pg_strdup(PQgetvalue(res, i, i_aggacl));
+ 		agginfo[i].aggfn.proiargs = pg_strdup(PQgetvalue(res, i, i_proiargs));
  		agginfo[i].aggfn.nargs = atoi(PQgetvalue(res, i, i_pronargs));
  		if (agginfo[i].aggfn.nargs == 0)
  			agginfo[i].aggfn.argtypes = NULL;
***************
*** 3693,3698 **** getFuncs(Archive *fout, int *numFuncs)
--- 3715,3721 ----
  	int			i_proargtypes;
  	int			i_prorettype;
  	int			i_proacl;
+ 	int			i_proiargs;
  
  	/* Make sure we are in proper schema */
  	selectSourceSchema(fout, "pg_catalog");
***************
*** 3713,3724 **** getFuncs(Archive *fout, int *numFuncs)
  	 * doesn't have; otherwise we might not get creation ordering correct.
  	 */
  
! 	if (fout->remoteVersion >= 70300)
  	{
  		appendPQExpBuffer(query,
  						  "SELECT tableoid, oid, proname, prolang, "
  						  "pronargs, proargtypes, prorettype, proacl, "
  						  "pronamespace, "
  						  "(%s proowner) AS rolname "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
--- 3736,3748 ----
  	 * doesn't have; otherwise we might not get creation ordering correct.
  	 */
  
! 	if (fout->remoteVersion >= 80400)
  	{
  		appendPQExpBuffer(query,
  						  "SELECT tableoid, oid, proname, prolang, "
  						  "pronargs, proargtypes, prorettype, proacl, "
  						  "pronamespace, "
+ 						  "pg_catalog.pg_get_function_identity_arguments(oid) AS proiargs,"
  						  "(%s proowner) AS rolname "
  						  "FROM pg_proc p "
  						  "WHERE NOT proisagg AND ("
***************
*** 3740,3745 **** getFuncs(Archive *fout, int *numFuncs)
--- 3764,3784 ----
  							  "deptype = 'e')");
  		appendPQExpBuffer(query, ")");
  	}
+ 	else if (fout->remoteVersion >= 70300)
+ 	{
+ 		appendPQExpBuffer(query,
+ 						  "SELECT tableoid, oid, proname, prolang, "
+ 						  "pronargs, proargtypes, prorettype, proacl, "
+ 						  "pronamespace, "
+ 						  "NULL::text AS proiargs,"
+ 						  "(%s proowner) AS rolname "
+ 						  "FROM pg_proc p "
+ 						  "WHERE NOT proisagg AND ("
+ 						  "pronamespace != "
+ 						  "(SELECT oid FROM pg_namespace "
+ 						  "WHERE nspname = 'pg_catalog'))",
+ 						  username_subquery);
+ 	}
  	else if (fout->remoteVersion >= 70100)
  	{
  		appendPQExpBuffer(query,
***************
*** 3747,3752 **** getFuncs(Archive *fout, int *numFuncs)
--- 3786,3792 ----
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
+ 						  "NULL::text AS proiargs,"
  						  "(%s proowner) AS rolname "
  						  "FROM pg_proc "
  						  "WHERE pg_proc.oid > '%u'::oid",
***************
*** 3763,3768 **** getFuncs(Archive *fout, int *numFuncs)
--- 3803,3809 ----
  						  "pronargs, proargtypes, prorettype, "
  						  "'{=X}' AS proacl, "
  						  "0::oid AS pronamespace, "
+ 						  "NULL::text AS proiargs,"
  						  "(%s proowner) AS rolname "
  						  "FROM pg_proc "
  						  "where pg_proc.oid > '%u'::oid",
***************
*** 3788,3793 **** getFuncs(Archive *fout, int *numFuncs)
--- 3829,3835 ----
  	i_proargtypes = PQfnumber(res, "proargtypes");
  	i_prorettype = PQfnumber(res, "prorettype");
  	i_proacl = PQfnumber(res, "proacl");
+ 	i_proiargs = PQfnumber(res, "proiargs");
  
  	for (i = 0; i < ntups; i++)
  	{
***************
*** 3803,3808 **** getFuncs(Archive *fout, int *numFuncs)
--- 3845,3851 ----
  		finfo[i].rolname = pg_strdup(PQgetvalue(res, i, i_rolname));
  		finfo[i].lang = atooid(PQgetvalue(res, i, i_prolang));
  		finfo[i].prorettype = atooid(PQgetvalue(res, i, i_prorettype));
+ 		finfo[i].proiargs = pg_strdup(PQgetvalue(res, i, i_proiargs));
  		finfo[i].proacl = pg_strdup(PQgetvalue(res, i, i_proacl));
  		finfo[i].nargs = atoi(PQgetvalue(res, i, i_pronargs));
  		if (finfo[i].nargs == 0)
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
***************
*** 193,198 **** typedef struct _funcInfo
--- 193,199 ----
  	Oid		   *argtypes;
  	Oid			prorettype;
  	char	   *proacl;
+ 	char	   *proiargs;
  } FuncInfo;
  
  /* AggInfo is a superset of FuncInfo */
*** a/src/bin/pg_dump/pg_dump_sort.c
--- b/src/bin/pg_dump/pg_dump_sort.c
***************
*** 198,203 **** DOTypeNameCompare(const void *p1, const void *p2)
--- 198,206 ----
  		cmpval = fobj1->nargs - fobj2->nargs;
  		if (cmpval != 0)
  			return cmpval;
+ 		cmpval = strcmp(fobj1->proiargs, fobj2->proiargs);
+ 		if (cmpval != 0)
+ 			return cmpval;
  	}
  	else if (obj1->objType == DO_OPERATOR)
  	{
#9Joachim Wieland
joe@mcknight.de
In reply to: Alvaro Herrera (#8)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

On Wed, Oct 17, 2012 at 5:43 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

(I tested the new pg_dump with 8.2 and HEAD and also verified it passes
pg_upgrade's "make check". I didn't test with other server versions.)

I also tested against 8.3 and 8.4 since 8.4 is the version that
introduced pg_get_function_identity_arguments. The included testcase
fails on 8.3 and succeeds on 8.4 (pg_dump succeeds in both cases of
course but it's only ordered deterministically in 8.4+).

#10Joel Jacobson
joel@trustly.com
In reply to: Alvaro Herrera (#8)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

On Wed, Oct 17, 2012 at 11:43 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Uh, the patch you posted keeps the pg_get_function_identity_arguments
call in dumpFunc, but there is now also a new one in getFuncs. Do we
need to remove the second one?

It could be done, but unfortunately we cannot use the value computed
in dumpFunc(),
because getFuncs() is called before dumpFunc().

The patch currently only affects getFuncs(), it doesn't touch dumpFunc().

What could be done is to keep the changes in getFuncs(), and also
change dumpFunc()
to use the value computed in getFuncs(), but I think the gain is small
in relation
to the complexity of changing dumpFunc(), as we would still need to
make the two other
function calls in the SQL query in dumpFunc() to pg_get_function_arguments() and
pg_get_function_result().

Here's an updated patch for your consideration. I was about to push
this when I noticed the above. The only change here is that the extra
code that tests for new remoteVersions in the second "else if" branch of
getFuncs and getAggregates has been removed, since it cannot ever be
reached.

Looks really good.

#11Alvaro Herrera
alvherre@2ndquadrant.com
In reply to: Joel Jacobson (#10)
Re: [PATCH] pg_dump: Sort overloaded functions in deterministic order

Joel Jacobson wrote:

On Wed, Oct 17, 2012 at 11:43 PM, Alvaro Herrera
<alvherre@2ndquadrant.com> wrote:

Uh, the patch you posted keeps the pg_get_function_identity_arguments
call in dumpFunc, but there is now also a new one in getFuncs. Do we
need to remove the second one?

It could be done, but unfortunately we cannot use the value computed
in dumpFunc(),
because getFuncs() is called before dumpFunc().

Right, I got that from the discussion.

What could be done is to keep the changes in getFuncs(), and also
change dumpFunc()
to use the value computed in getFuncs(), but I think the gain is small
in relation
to the complexity of changing dumpFunc(), as we would still need to
make the two other
function calls in the SQL query in dumpFunc() to pg_get_function_arguments() and
pg_get_function_result().

Changing pg_dump is complex enough whatever the change, yes. I have not
touched this.

Here's an updated patch for your consideration. I was about to push
this when I noticed the above. The only change here is that the extra
code that tests for new remoteVersions in the second "else if" branch of
getFuncs and getAggregates has been removed, since it cannot ever be
reached.

Looks really good.

Thanks, pushed it.

--
Álvaro Herrera http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Training & Services