mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 00:03:57 -04:00 
			
		
		
		
	Rework pg_dump namespace search criteria so that dumping of user objects
having names conflicting with system objects will work --- the search path is now user-schema, pg_catalog rather than implicitly the other way around. Note this requires being careful to explicitly qualify references to system names whenever pg_catalog is not first in the search path. Also, add support for dumping ACLs of schemas.
This commit is contained in:
		
							parent
							
								
									5a8ab29adf
								
							
						
					
					
						commit
						36a1e732a6
					
				| @ -15,7 +15,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.46 2002/05/10 22:36:26 tgl Exp $ | ||||
|  *		$Header: /cvsroot/pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.47 2002/05/28 22:26:56 tgl Exp $ | ||||
|  * | ||||
|  * Modifications - 28-Jun-2000 - pjw@rhyme.com.au | ||||
|  * | ||||
| @ -2097,17 +2097,23 @@ _reconnectAsOwner(ArchiveHandle *AH, const char *dbname, TocEntry *te) | ||||
| static void | ||||
| _selectOutputSchema(ArchiveHandle *AH, const char *schemaName) | ||||
| { | ||||
| 	PQExpBuffer qry; | ||||
| 
 | ||||
| 	if (!schemaName || *schemaName == '\0' || | ||||
| 		strcmp(AH->currSchema, schemaName) == 0) | ||||
| 		return;					/* no need to do anything */ | ||||
| 
 | ||||
| 	qry = createPQExpBuffer(); | ||||
| 
 | ||||
| 	appendPQExpBuffer(qry, "SET search_path = %s", | ||||
| 					  fmtId(schemaName, false)); | ||||
| 	if (strcmp(schemaName, "pg_catalog") != 0) | ||||
| 		appendPQExpBuffer(qry, ", pg_catalog"); | ||||
| 
 | ||||
| 	if (RestoringToDB(AH)) | ||||
| 	{ | ||||
| 		PQExpBuffer qry = createPQExpBuffer(); | ||||
| 		PGresult   *res; | ||||
| 
 | ||||
| 		appendPQExpBuffer(qry, "SET search_path = %s;", | ||||
| 						  fmtId(schemaName, false)); | ||||
| 		res = PQexec(AH->connection, qry->data); | ||||
| 
 | ||||
| 		if (!res || PQresultStatus(res) != PGRES_COMMAND_OK) | ||||
| @ -2115,15 +2121,15 @@ _selectOutputSchema(ArchiveHandle *AH, const char *schemaName) | ||||
| 						 schemaName, PQerrorMessage(AH->connection)); | ||||
| 
 | ||||
| 		PQclear(res); | ||||
| 		destroyPQExpBuffer(qry); | ||||
| 	} | ||||
| 	else | ||||
| 		ahprintf(AH, "SET search_path = %s;\n\n", | ||||
| 				 fmtId(schemaName, false)); | ||||
| 		ahprintf(AH, "%s;\n\n", qry->data); | ||||
| 
 | ||||
| 	if (AH->currSchema) | ||||
| 		free(AH->currSchema); | ||||
| 	AH->currSchema = strdup(schemaName); | ||||
| 
 | ||||
| 	destroyPQExpBuffer(qry); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -22,7 +22,7 @@ | ||||
|  * | ||||
|  * | ||||
|  * IDENTIFICATION | ||||
|  *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.264 2002/05/22 17:21:00 petere Exp $ | ||||
|  *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.265 2002/05/28 22:26:56 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -1779,7 +1779,7 @@ getAggregates(int *numAggs) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT pg_proc.oid, proname as aggname, " | ||||
| 						  "pronamespace as aggnamespace, " | ||||
| 						  "proargtypes[0]::regtype as aggbasetype, " | ||||
| 						  "proargtypes[0] as aggbasetype, " | ||||
| 						  "(select usename from pg_user where proowner = usesysid) as usename, " | ||||
| 						  "proacl as aggacl " | ||||
| 						  "FROM pg_proc " | ||||
| @ -1791,10 +1791,9 @@ getAggregates(int *numAggs) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT pg_aggregate.oid, aggname, " | ||||
| 						  "0::oid as aggnamespace, " | ||||
| 						  "CASE WHEN aggbasetype = 0 THEN '-' " | ||||
| 						  "ELSE format_type(aggbasetype, NULL) END as aggbasetype, " | ||||
| 						  "aggbasetype, " | ||||
| 						  "(select usename from pg_user where aggowner = usesysid) as usename, " | ||||
| 						  "cast('{=X}' as aclitem[]) as aggacl " | ||||
| 						  "'{=X}' as aggacl " | ||||
| 						  "from pg_aggregate " | ||||
| 						  "where oid > '%u'::oid", | ||||
| 						  g_last_builtin_oid); | ||||
| @ -1833,6 +1832,7 @@ getAggregates(int *numAggs) | ||||
| 			write_msg(NULL, "WARNING: owner of aggregate function \"%s\" appears to be invalid\n", | ||||
| 					  agginfo[i].aggname); | ||||
| 		agginfo[i].aggacl = strdup(PQgetvalue(res, i, i_aggacl)); | ||||
| 		agginfo[i].fmtbasetype = NULL; /* computed when it's dumped */ | ||||
| 	} | ||||
| 
 | ||||
| 	PQclear(res); | ||||
| @ -1890,7 +1890,7 @@ getFuncs(int *numFuncs) | ||||
| 		appendPQExpBuffer(query, | ||||
| 						  "SELECT pg_proc.oid, proname, prolang, " | ||||
| 						  "pronargs, proargtypes, prorettype, " | ||||
| 						  "cast('{=X}' as aclitem[]) as proacl, " | ||||
| 						  "'{=X}' as proacl, " | ||||
| 						  "0::oid as pronamespace, " | ||||
| 						  "(select usename from pg_user where proowner = usesysid) as usename " | ||||
| 						  "FROM pg_proc " | ||||
| @ -2290,7 +2290,18 @@ getTableAttrs(TableInfo *tblinfo, int numTables) | ||||
| 
 | ||||
| 		resetPQExpBuffer(q); | ||||
| 
 | ||||
| 		if (g_fout->remoteVersion >= 70100) | ||||
| 		if (g_fout->remoteVersion >= 70300) | ||||
| 		{ | ||||
| 			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, " | ||||
| 							  "attnotnull, atthasdef, " | ||||
| 							  "pg_catalog.format_type(atttypid,atttypmod) as atttypname " | ||||
| 							  "from pg_catalog.pg_attribute a " | ||||
| 							  "where attrelid = '%s'::pg_catalog.oid " | ||||
| 							  "and attnum > 0::pg_catalog.int2 " | ||||
| 							  "order by attrelid, attnum", | ||||
| 							  tblinfo[i].oid); | ||||
| 		} | ||||
| 		else if (g_fout->remoteVersion >= 70100) | ||||
| 		{ | ||||
| 			appendPQExpBuffer(q, "SELECT attnum, attname, atttypmod, " | ||||
| 							  "attnotnull, atthasdef, " | ||||
| @ -2367,7 +2378,15 @@ getTableAttrs(TableInfo *tblinfo, int numTables) | ||||
| 						  tblinfo[i].relname); | ||||
| 
 | ||||
| 			resetPQExpBuffer(q); | ||||
| 			if (g_fout->remoteVersion >= 70200) | ||||
| 			if (g_fout->remoteVersion >= 70300) | ||||
| 			{ | ||||
| 				appendPQExpBuffer(q, "SELECT adnum, " | ||||
| 								  "pg_catalog.pg_get_expr(adbin, adrelid) AS adsrc " | ||||
| 								  "FROM pg_catalog.pg_attrdef " | ||||
| 								  "WHERE adrelid = '%s'::pg_catalog.oid", | ||||
| 								  tblinfo[i].oid); | ||||
| 			} | ||||
| 			else if (g_fout->remoteVersion >= 70200) | ||||
| 			{ | ||||
| 				appendPQExpBuffer(q, "SELECT adnum, " | ||||
| 								  "pg_get_expr(adbin, adrelid) AS adsrc " | ||||
| @ -2452,8 +2471,8 @@ dumpComment(Archive *fout, const char *target, | ||||
| 	if (fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT description FROM pg_catalog.pg_description " | ||||
| 						  "WHERE objoid = '%s'::oid and classoid = " | ||||
| 						  "'pg_catalog.%s'::regclass " | ||||
| 						  "WHERE objoid = '%s'::pg_catalog.oid and classoid = " | ||||
| 						  "'pg_catalog.%s'::pg_catalog.regclass " | ||||
| 						  "and objsubid = %d", | ||||
| 						  oid, classname, subid); | ||||
| 	} | ||||
| @ -2537,8 +2556,8 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, | ||||
| 	if (fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT description, objsubid FROM pg_catalog.pg_description " | ||||
| 						  "WHERE objoid = '%s'::oid and classoid = " | ||||
| 						  "'pg_catalog.pg_class'::regclass " | ||||
| 						  "WHERE objoid = '%s'::pg_catalog.oid and classoid = " | ||||
| 						  "'pg_catalog.pg_class'::pg_catalog.regclass " | ||||
| 						  "ORDER BY objoid, classoid, objsubid", | ||||
| 						  tbinfo->oid); | ||||
| 	} | ||||
| @ -2622,9 +2641,7 @@ dumpTableComment(Archive *fout, TableInfo *tbinfo, | ||||
|  * dumpDBComment -- | ||||
|  * | ||||
|  * This routine is used to dump any comments associated with the | ||||
|  * database to which we are currently connected. If the user chose | ||||
|  * to dump the schema of the database, then this is the first | ||||
|  * statement issued. | ||||
|  * database to which we are currently connected. | ||||
|  */ | ||||
| void | ||||
| dumpDBComment(Archive *fout) | ||||
| @ -2677,45 +2694,63 @@ dumpNamespaces(Archive *fout, NamespaceInfo *nsinfo, int numNamespaces) | ||||
| 	PQExpBuffer q = createPQExpBuffer(); | ||||
| 	PQExpBuffer delq = createPQExpBuffer(); | ||||
| 	int			i; | ||||
| 	char	   *qnspname; | ||||
| 
 | ||||
| 	for (i = 0; i < numNamespaces; i++) | ||||
| 	{ | ||||
| 		NamespaceInfo *nspinfo = &nsinfo[i]; | ||||
| 
 | ||||
| 		/* skip if not to be dumped */ | ||||
| 		if (!nsinfo[i].dump) | ||||
| 		if (!nspinfo->dump) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* don't dump dummy namespace from pre-7.3 source */ | ||||
| 		if (strlen(nsinfo[i].nspname) == 0) | ||||
| 		if (strlen(nspinfo->nspname) == 0) | ||||
| 			continue; | ||||
| 
 | ||||
| 		/* quick hack: don't dump CREATE SCHEMA for public namespace */ | ||||
| 		/* XXX need a better idea */ | ||||
| 		if (strcmp(nsinfo[i].nspname, "public") == 0) | ||||
| 			continue; | ||||
| 		qnspname = strdup(fmtId(nspinfo->nspname, force_quotes)); | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * If it's the PUBLIC namespace, don't emit a CREATE SCHEMA | ||||
| 		 * record for it, since we expect PUBLIC to exist already in | ||||
| 		 * the destination database.  And emit ACL info only if the ACL | ||||
| 		 * isn't the standard value for PUBLIC. | ||||
| 		 */ | ||||
| 		if (strcmp(nspinfo->nspname, "public") == 0) | ||||
| 		{ | ||||
| 			if (!aclsSkip && strcmp(nspinfo->nspacl, "{=UC}") != 0) | ||||
| 				dumpACL(fout, "SCHEMA", qnspname, NULL, | ||||
| 						nspinfo->usename, nspinfo->nspacl, | ||||
| 						nspinfo->oid); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			resetPQExpBuffer(q); | ||||
| 			resetPQExpBuffer(delq); | ||||
| 
 | ||||
| #ifdef NOTYET					/* suppress till DROP SCHEMA works */ | ||||
| 		appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", | ||||
| 						  fmtId(nsinfo[i].nspname, force_quotes)); | ||||
| #endif | ||||
| 			appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname); | ||||
| 
 | ||||
| 		appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", | ||||
| 						  fmtId(nsinfo[i].nspname, force_quotes)); | ||||
| 			appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname); | ||||
| 
 | ||||
| 		ArchiveEntry(fout, nsinfo[i].oid, nsinfo[i].nspname, | ||||
| 			ArchiveEntry(fout, nspinfo->oid, nspinfo->nspname, | ||||
| 						 NULL, | ||||
| 					 nsinfo[i].usename, "SCHEMA", NULL, | ||||
| 						 nspinfo->usename, "SCHEMA", NULL, | ||||
| 						 q->data, delq->data, NULL, NULL, NULL); | ||||
| 
 | ||||
| 			/*** Dump Schema Comments ***/ | ||||
| 			resetPQExpBuffer(q); | ||||
| 		appendPQExpBuffer(q, "SCHEMA %s", | ||||
| 						  fmtId(nsinfo[i].nspname, force_quotes)); | ||||
| 			appendPQExpBuffer(q, "SCHEMA %s", qnspname); | ||||
| 			dumpComment(fout, q->data, | ||||
| 					NULL, nsinfo[i].usename, | ||||
| 					nsinfo[i].oid, "pg_namespace", 0, NULL); | ||||
| 						NULL, nspinfo->usename, | ||||
| 						nspinfo->oid, "pg_namespace", 0, NULL); | ||||
| 
 | ||||
| 			if (!aclsSkip) | ||||
| 				dumpACL(fout, "SCHEMA", qnspname, NULL, | ||||
| 						nspinfo->usename, nspinfo->nspacl, | ||||
| 						nspinfo->oid); | ||||
| 		} | ||||
| 
 | ||||
| 		free(qnspname); | ||||
| 	} | ||||
| 
 | ||||
| 	destroyPQExpBuffer(q); | ||||
| @ -2762,7 +2797,21 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo, | ||||
| 	selectSourceSchema(tinfo->typnamespace->nspname); | ||||
| 
 | ||||
| 	/* Fetch type-specific details */ | ||||
| 	if (fout->remoteVersion >= 70100) | ||||
| 	if (fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT typlen, typprtlen, " | ||||
| 						  "typinput, typoutput, typreceive, typsend, " | ||||
| 						  "typinput::pg_catalog.oid as typinputoid, " | ||||
| 						  "typoutput::pg_catalog.oid as typoutputoid, " | ||||
| 						  "typreceive::pg_catalog.oid as typreceiveoid, " | ||||
| 						  "typsend::pg_catalog.oid as typsendoid, " | ||||
| 						  "typdelim, typdefault, typbyval, typalign, " | ||||
| 						  "typstorage " | ||||
| 						  "FROM pg_catalog.pg_type " | ||||
| 						  "WHERE oid = '%s'::pg_catalog.oid", | ||||
| 						  tinfo->oid); | ||||
| 	} | ||||
| 	else if (fout->remoteVersion >= 70100) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT typlen, typprtlen, " | ||||
| 						  "typinput, typoutput, typreceive, typsend, " | ||||
| @ -2823,7 +2872,7 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo, | ||||
| 	if (PQgetisnull(res, 0, PQfnumber(res, "typdefault"))) | ||||
| 		typdefault = NULL; | ||||
| 	else | ||||
| 		typdefault = strdup(PQgetvalue(res, 0, PQfnumber(res, "typdefault"))); | ||||
| 		typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault")); | ||||
| 	typbyval = PQgetvalue(res, 0, PQfnumber(res, "typbyval")); | ||||
| 	typalign = PQgetvalue(res, 0, PQfnumber(res, "typalign")); | ||||
| 	typstorage = PQgetvalue(res, 0, PQfnumber(res, "typstorage")); | ||||
| @ -2856,7 +2905,10 @@ dumpOneBaseType(Archive *fout, TypeInfo *tinfo, | ||||
| 			(*deps)[depIdx++] = strdup(typsendoid); | ||||
| 	} | ||||
| 
 | ||||
| 	appendPQExpBuffer(delq, "DROP TYPE %s;\n", | ||||
| 	/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 	appendPQExpBuffer(delq, "DROP TYPE %s.", | ||||
| 					  fmtId(tinfo->typnamespace->nspname, force_quotes)); | ||||
| 	appendPQExpBuffer(delq, "%s;\n", | ||||
| 					  fmtId(tinfo->typname, force_quotes)); | ||||
| 
 | ||||
| 	appendPQExpBuffer(q, | ||||
| @ -2977,11 +3029,12 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo) | ||||
| 	selectSourceSchema(tinfo->typnamespace->nspname); | ||||
| 
 | ||||
| 	/* Fetch domain specific details */ | ||||
| 	/* We assume here that remoteVersion must be at least 70300 */ | ||||
| 	appendPQExpBuffer(query, "SELECT typnotnull, " | ||||
| 					  "format_type(typbasetype, typtypmod) as typdefn, " | ||||
| 					  "pg_catalog.format_type(typbasetype, typtypmod) as typdefn, " | ||||
| 					  "typdefault, typbasetype " | ||||
| 					  "FROM pg_type " | ||||
| 					  "WHERE oid = '%s'::oid", | ||||
| 					  "FROM pg_catalog.pg_type " | ||||
| 					  "WHERE oid = '%s'::pg_catalog.oid", | ||||
| 					  tinfo->oid); | ||||
| 
 | ||||
| 	res = PQexec(g_conn, query->data); | ||||
| @ -3006,11 +3059,13 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo) | ||||
| 	if (PQgetisnull(res, 0, PQfnumber(res, "typdefault"))) | ||||
| 		typdefault = NULL; | ||||
| 	else | ||||
| 		typdefault = strdup(PQgetvalue(res, 0, PQfnumber(res, "typdefault"))); | ||||
| 		typdefault = PQgetvalue(res, 0, PQfnumber(res, "typdefault")); | ||||
| 	typbasetype = PQgetvalue(res, 0, PQfnumber(res, "typbasetype")); | ||||
| 
 | ||||
| 	/* Command to drop the old copy */ | ||||
| 	appendPQExpBuffer(delq, "DROP DOMAIN %s RESTRICT;\n", | ||||
| 	/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 	appendPQExpBuffer(delq, "DROP DOMAIN %s.", | ||||
| 					  fmtId(tinfo->typnamespace->nspname, force_quotes)); | ||||
| 	appendPQExpBuffer(delq, "%s RESTRICT;\n", | ||||
| 					  fmtId(tinfo->typname, force_quotes)); | ||||
| 
 | ||||
| 	appendPQExpBuffer(q, | ||||
| @ -3025,11 +3080,7 @@ dumpOneDomain(Archive *fout, TypeInfo *tinfo) | ||||
| 		appendPQExpBuffer(q, " NOT NULL"); | ||||
| 
 | ||||
| 	if (typdefault) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(q, | ||||
| 						  " DEFAULT %s", | ||||
| 						  typdefault); | ||||
| 	} | ||||
| 		appendPQExpBuffer(q, " DEFAULT %s", typdefault); | ||||
| 
 | ||||
| 	appendPQExpBuffer(q, ";\n"); | ||||
| 
 | ||||
| @ -3206,7 +3257,8 @@ dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs) | ||||
| 
 | ||||
| 		(*deps)[depIdx++] = strdup(lanplcallfoid); | ||||
| 
 | ||||
| 		appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n", fmtId(lanname, force_quotes)); | ||||
| 		appendPQExpBuffer(delqry, "DROP PROCEDURAL LANGUAGE %s;\n", | ||||
| 						  fmtId(lanname, force_quotes)); | ||||
| 
 | ||||
| 		appendPQExpBuffer(defqry, "CREATE %sPROCEDURAL LANGUAGE %s", | ||||
| 						  (PQgetvalue(res, i, i_lanpltrusted)[0] == 't') ? | ||||
| @ -3216,7 +3268,13 @@ dumpProcLangs(Archive *fout, FuncInfo finfo[], int numFuncs) | ||||
| 						  fmtId(finfo[fidx].proname, force_quotes)); | ||||
| 		if (strcmp(lanvalidator, "0")!=0) | ||||
| 		{ | ||||
| 			appendPQExpBuffer(defqry, " VALIDATOR %s", | ||||
| 			appendPQExpBuffer(defqry, " VALIDATOR "); | ||||
| 			/* Cope with possibility that validator is in different schema */ | ||||
| 			if (finfo[vidx].pronamespace != finfo[fidx].pronamespace) | ||||
| 				appendPQExpBuffer(defqry, "%s.", | ||||
| 								  fmtId(finfo[vidx].pronamespace->nspname, | ||||
| 										force_quotes)); | ||||
| 			appendPQExpBuffer(defqry, "%s", | ||||
| 							  fmtId(finfo[vidx].proname, force_quotes)); | ||||
| 			(*deps)[depIdx++] = strdup(lanvalidator); | ||||
| 		} | ||||
| @ -3266,7 +3324,12 @@ dumpFuncs(Archive *fout, FuncInfo finfo[], int numFuncs) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * format_function_signature: generate function name and argument list | ||||
|  * | ||||
|  * The argument type names are qualified if needed.  The function name | ||||
|  * is never qualified. | ||||
|  */ | ||||
| static char * | ||||
| format_function_signature(FuncInfo *finfo) | ||||
| { | ||||
| @ -3340,9 +3403,9 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo) | ||||
| 		appendPQExpBuffer(query, | ||||
| 						  "SELECT proretset, prosrc, probin, " | ||||
| 						  "provolatile, proimplicit, proisstrict, prosecdef, " | ||||
| 						  "(SELECT lanname FROM pg_language WHERE oid = prolang) as lanname " | ||||
| 						  "FROM pg_proc " | ||||
| 						  "WHERE oid = '%s'::oid", | ||||
| 						  "(SELECT lanname FROM pg_catalog.pg_language WHERE oid = prolang) as lanname " | ||||
| 						  "FROM pg_catalog.pg_proc " | ||||
| 						  "WHERE oid = '%s'::pg_catalog.oid", | ||||
| 						  finfo->oid); | ||||
| 	} | ||||
| 	else if (g_fout->remoteVersion >= 70100) | ||||
| @ -3424,7 +3487,10 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo) | ||||
| 
 | ||||
| 	funcsig = format_function_signature(finfo); | ||||
| 
 | ||||
| 	appendPQExpBuffer(delqry, "DROP FUNCTION %s;\n", funcsig); | ||||
| 	/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 	appendPQExpBuffer(delqry, "DROP FUNCTION %s.%s;\n", | ||||
| 					  fmtId(finfo->pronamespace->nspname, force_quotes), | ||||
| 					  funcsig); | ||||
| 
 | ||||
| 	rettypename = getFormattedTypeName(finfo->prorettype, zeroAsOpaque); | ||||
| 
 | ||||
| @ -3561,15 +3627,21 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo, | ||||
| 
 | ||||
| 	if (g_fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT oprkind, oprcode::regprocedure, " | ||||
| 						  "oprleft::regtype, oprright::regtype, " | ||||
| 						  "oprcom::regoperator, oprnegate::regoperator, " | ||||
| 						  "oprrest::regprocedure, oprjoin::regprocedure, " | ||||
| 		appendPQExpBuffer(query, "SELECT oprkind, " | ||||
| 						  "oprcode::pg_catalog.regprocedure, " | ||||
| 						  "oprleft::pg_catalog.regtype, " | ||||
| 						  "oprright::pg_catalog.regtype, " | ||||
| 						  "oprcom::pg_catalog.regoperator, " | ||||
| 						  "oprnegate::pg_catalog.regoperator, " | ||||
| 						  "oprrest::pg_catalog.regprocedure, " | ||||
| 						  "oprjoin::pg_catalog.regprocedure, " | ||||
| 						  "oprcanhash, " | ||||
| 						  "oprlsortop::regoperator, oprrsortop::regoperator, " | ||||
| 						  "oprltcmpop::regoperator, oprgtcmpop::regoperator " | ||||
| 						  "from pg_operator " | ||||
| 						  "where oid = '%s'::oid", | ||||
| 						  "oprlsortop::pg_catalog.regoperator, " | ||||
| 						  "oprrsortop::pg_catalog.regoperator, " | ||||
| 						  "oprltcmpop::pg_catalog.regoperator, " | ||||
| 						  "oprgtcmpop::pg_catalog.regoperator " | ||||
| 						  "from pg_catalog.pg_operator " | ||||
| 						  "where oid = '%s'::pg_catalog.oid", | ||||
| 						  oprinfo->oid); | ||||
| 	} | ||||
| 	else if (g_fout->remoteVersion >= 70100) | ||||
| @ -3717,7 +3789,9 @@ dumpOneOpr(Archive *fout, OprInfo *oprinfo, | ||||
| 	if (name) | ||||
| 		appendPQExpBuffer(details, ",\n\tGTCMP = %s ", name); | ||||
| 
 | ||||
| 	appendPQExpBuffer(delq, "DROP OPERATOR %s;\n", | ||||
| 	/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 	appendPQExpBuffer(delq, "DROP OPERATOR %s.%s;\n", | ||||
| 					  fmtId(oprinfo->oprnamespace->nspname, force_quotes), | ||||
| 					  oprid->data); | ||||
| 
 | ||||
| 	appendPQExpBuffer(q, "CREATE OPERATOR %s (%s);\n", | ||||
| @ -3856,6 +3930,12 @@ dumpAggs(Archive *fout, AggInfo agginfo[], int numAggs) | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /*
 | ||||
|  * format_aggregate_signature: generate aggregate name and argument list | ||||
|  * | ||||
|  * The argument type names are qualified if needed.  The aggregate name | ||||
|  * is never qualified. | ||||
|  */ | ||||
| static char * | ||||
| format_aggregate_signature(AggInfo *agginfo, Archive *fout) | ||||
| { | ||||
| @ -3866,15 +3946,15 @@ format_aggregate_signature(AggInfo *agginfo, Archive *fout) | ||||
| 	appendPQExpBuffer(&buf, "%s", | ||||
| 					  fmtId(agginfo->aggname, force_quotes)); | ||||
| 
 | ||||
| 	anybasetype = (strcmp(agginfo->aggbasetype, "-") == 0); | ||||
| 	anybasetype = (strcmp(agginfo->aggbasetype, "0") == 0); | ||||
| 
 | ||||
| 	/* If using regtype or format_type, name is already quoted */ | ||||
| 	/* If using regtype or format_type, fmtbasetype is already quoted */ | ||||
| 	if (fout->remoteVersion >= 70100) | ||||
| 	{ | ||||
| 		if (anybasetype) | ||||
| 			appendPQExpBuffer(&buf, "(*)"); | ||||
| 		else | ||||
| 			appendPQExpBuffer(&buf, "(%s)", agginfo->aggbasetype); | ||||
| 			appendPQExpBuffer(&buf, "(%s)", agginfo->fmtbasetype); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @ -3882,7 +3962,7 @@ format_aggregate_signature(AggInfo *agginfo, Archive *fout) | ||||
| 			appendPQExpBuffer(&buf, "(*)"); | ||||
| 		else | ||||
| 			appendPQExpBuffer(&buf, "(%s)", | ||||
| 							  fmtId(agginfo->aggbasetype, force_quotes)); | ||||
| 							  fmtId(agginfo->fmtbasetype, force_quotes)); | ||||
| 	} | ||||
| 
 | ||||
| 	return buf.data; | ||||
| @ -3919,6 +3999,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 	int			i_aggfinalfn; | ||||
| 	int			i_aggtranstype; | ||||
| 	int			i_agginitval; | ||||
| 	int			i_fmtbasetype; | ||||
| 	int			i_convertok; | ||||
| 	const char *aggtransfn; | ||||
| 	const char *aggfinalfn; | ||||
| @ -3934,19 +4015,23 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 	if (g_fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT aggtransfn, " | ||||
| 						  "aggfinalfn, aggtranstype::regtype, " | ||||
| 						  "aggfinalfn, aggtranstype::pg_catalog.regtype, " | ||||
| 						  "agginitval, " | ||||
| 						  "proargtypes[0]::pg_catalog.regtype as fmtbasetype, " | ||||
| 						  "'t'::boolean as convertok " | ||||
| 						  "from pg_aggregate a, pg_proc p " | ||||
| 						  "from pg_catalog.pg_aggregate a, pg_catalog.pg_proc p " | ||||
| 						  "where a.aggfnoid = p.oid " | ||||
| 						  "and p.oid = '%s'::oid", | ||||
| 						  "and p.oid = '%s'::pg_catalog.oid", | ||||
| 						  agginfo->oid); | ||||
| 	} | ||||
| 	else if (g_fout->remoteVersion >= 70100) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT aggtransfn, aggfinalfn, " | ||||
| 						  "format_type(aggtranstype, NULL) as aggtranstype, " | ||||
| 						  "agginitval, 't'::boolean as convertok " | ||||
| 						  "agginitval, " | ||||
| 						  "CASE WHEN aggbasetype = 0 THEN '-' " | ||||
| 						  "ELSE format_type(aggbasetype, NULL) END as fmtbasetype, " | ||||
| 						  "'t'::boolean as convertok " | ||||
| 						  "from pg_aggregate " | ||||
| 						  "where oid = '%s'::oid", | ||||
| 						  agginfo->oid); | ||||
| @ -3957,6 +4042,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 						  "aggfinalfn, " | ||||
| 						  "(select typname from pg_type where oid = aggtranstype1) as aggtranstype, " | ||||
| 						  "agginitval1 as agginitval, " | ||||
| 						  "(select typname from pg_type where oid = aggbasetype) as fmtbasetype, " | ||||
| 						  "(aggtransfn2 = 0 and aggtranstype2 = 0 and agginitval2 is null) as convertok " | ||||
| 						  "from pg_aggregate " | ||||
| 						  "where oid = '%s'::oid", | ||||
| @ -3985,12 +4071,15 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 	i_aggfinalfn = PQfnumber(res, "aggfinalfn"); | ||||
| 	i_aggtranstype = PQfnumber(res, "aggtranstype"); | ||||
| 	i_agginitval = PQfnumber(res, "agginitval"); | ||||
| 	i_fmtbasetype = PQfnumber(res, "fmtbasetype"); | ||||
| 	i_convertok = PQfnumber(res, "convertok"); | ||||
| 
 | ||||
| 	aggtransfn = PQgetvalue(res, 0, i_aggtransfn); | ||||
| 	aggfinalfn = PQgetvalue(res, 0, i_aggfinalfn); | ||||
| 	aggtranstype = PQgetvalue(res, 0, i_aggtranstype); | ||||
| 	agginitval = PQgetvalue(res, 0, i_agginitval); | ||||
| 	/* we save fmtbasetype so that dumpAggACL can use it later */ | ||||
| 	agginfo->fmtbasetype = strdup(PQgetvalue(res, 0, i_fmtbasetype)); | ||||
| 	convertok = (PQgetvalue(res, 0, i_convertok)[0] == 't'); | ||||
| 
 | ||||
| 	aggSig = format_aggregate_signature(agginfo, g_fout); | ||||
| @ -4010,13 +4099,13 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	anybasetype = (strcmp(agginfo->aggbasetype, "-") == 0); | ||||
| 	anybasetype = (strcmp(agginfo->aggbasetype, "0") == 0); | ||||
| 
 | ||||
| 	if (g_fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		/* If using 7.3's regproc or regtype, data is already quoted */ | ||||
| 		appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s", | ||||
| 						  anybasetype ? "'any'" : agginfo->aggbasetype, | ||||
| 						  anybasetype ? "'any'" : agginfo->fmtbasetype, | ||||
| 						  aggtransfn, | ||||
| 						  aggtranstype); | ||||
| 	} | ||||
| @ -4024,7 +4113,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 	{ | ||||
| 		/* format_type quotes, regproc does not */ | ||||
| 		appendPQExpBuffer(details, "BASETYPE = %s, SFUNC = %s, STYPE = %s", | ||||
| 						  anybasetype ? "'any'" : agginfo->aggbasetype, | ||||
| 						  anybasetype ? "'any'" : agginfo->fmtbasetype, | ||||
| 						  fmtId(aggtransfn, force_quotes), | ||||
| 						  aggtranstype); | ||||
| 	} | ||||
| @ -4033,7 +4122,7 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 		/* need quotes all around */ | ||||
| 		appendPQExpBuffer(details, "BASETYPE = %s, ", | ||||
| 						  anybasetype ? "'any'" : | ||||
| 						  fmtId(agginfo->aggbasetype, force_quotes)); | ||||
| 						  fmtId(agginfo->fmtbasetype, force_quotes)); | ||||
| 		appendPQExpBuffer(details, "SFUNC = %s, ", | ||||
| 						  fmtId(aggtransfn, force_quotes)); | ||||
| 		appendPQExpBuffer(details, "STYPE = %s", | ||||
| @ -4052,7 +4141,10 @@ dumpOneAgg(Archive *fout, AggInfo *agginfo) | ||||
| 						  aggfinalfn); | ||||
| 	} | ||||
| 
 | ||||
| 	appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig); | ||||
| 	/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 	appendPQExpBuffer(delq, "DROP AGGREGATE %s.%s;\n", | ||||
| 					  fmtId(agginfo->aggnamespace->nspname, force_quotes), | ||||
| 					  aggSig); | ||||
| 
 | ||||
| 	appendPQExpBuffer(q, "CREATE AGGREGATE %s ( %s );\n", | ||||
| 					  fmtId(agginfo->aggname, force_quotes), | ||||
| @ -4152,6 +4244,11 @@ GetPrivileges(Archive *AH, const char *s, const char *type) | ||||
| 	{ | ||||
| 		CONVERT_PRIV('U', "USAGE"); | ||||
| 	} | ||||
| 	else if (strcmp(type, "SCHEMA")==0) | ||||
| 	{ | ||||
| 		CONVERT_PRIV('C', "CREATE"); | ||||
| 		CONVERT_PRIV('U', "USAGE"); | ||||
| 	} | ||||
| 	else | ||||
| 		abort(); | ||||
| 
 | ||||
| @ -4167,13 +4264,13 @@ GetPrivileges(Archive *AH, const char *s, const char *type) | ||||
| /*
 | ||||
|  * Write out grant/revoke information | ||||
|  * | ||||
|  * 'type' must be TABLE, FUNCTION, or LANGUAGE.  'name' is the | ||||
|  * 'type' must be TABLE, FUNCTION, LANGUAGE, or SCHEMA.  'name' is the | ||||
|  * formatted name of the object.  Must be quoted etc. already. | ||||
|  * 'nspname' is the namespace the object is in.  'usename' is the | ||||
|  * owner, NULL if there is no owner (for languages).  'acls' is the | ||||
|  * string read out of the fooacl system catalog field; it will be | ||||
|  * parsed here.  'objoid' is the OID of the object for purposes of | ||||
|  * ordering. | ||||
|  * 'nspname' is the namespace the object is in (NULL if none). | ||||
|  * 'usename' is the owner, NULL if there is no owner (for languages). | ||||
|  * 'acls' is the string read out of the fooacl system catalog field; | ||||
|  * it will be parsed here. | ||||
|  * 'objoid' is the OID of the object for purposes of ordering. | ||||
|  */ | ||||
| static void | ||||
| dumpACL(Archive *fout, const char *type, const char *name, | ||||
| @ -4188,7 +4285,7 @@ dumpACL(Archive *fout, const char *type, const char *name, | ||||
| 	bool		found_owner_privs = false; | ||||
| 
 | ||||
| 	if (strlen(acls) == 0) | ||||
| 		return;					/* table has default permissions */ | ||||
| 		return;					/* object has default permissions */ | ||||
| 
 | ||||
| 	sql = createPQExpBuffer(); | ||||
| 
 | ||||
| @ -4218,8 +4315,7 @@ dumpACL(Archive *fout, const char *type, const char *name, | ||||
| 		*eqpos = '\0';			/* it's ok to clobber aclbuf */ | ||||
| 
 | ||||
| 		/*
 | ||||
| 		 * Parse the privileges (right-hand side).	Skip if there are | ||||
| 		 * none. | ||||
| 		 * Parse the privileges (right-hand side). | ||||
| 		 */ | ||||
| 		priv = GetPrivileges(fout, eqpos + 1, type); | ||||
| 
 | ||||
| @ -4262,6 +4358,23 @@ dumpACL(Archive *fout, const char *type, const char *name, | ||||
| 					appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes)); | ||||
| 			} | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/* No privileges.  Issue explicit REVOKE for safety. */ | ||||
| 			appendPQExpBuffer(sql, "REVOKE ALL ON %s %s FROM ", | ||||
| 							  type, name); | ||||
| 			if (eqpos == tok) | ||||
| 			{ | ||||
| 				/* Empty left-hand side means "PUBLIC" */ | ||||
| 				appendPQExpBuffer(sql, "PUBLIC;\n"); | ||||
| 			} | ||||
| 			else if (strncmp(tok, "group ", strlen("group ")) == 0) | ||||
| 				appendPQExpBuffer(sql, "GROUP %s;\n", | ||||
| 								  fmtId(tok + strlen("group "), | ||||
| 										force_quotes)); | ||||
| 			else | ||||
| 				appendPQExpBuffer(sql, "%s;\n", fmtId(tok, force_quotes)); | ||||
| 		} | ||||
| 		free(priv); | ||||
| 	} | ||||
| 
 | ||||
| @ -4275,11 +4388,10 @@ dumpACL(Archive *fout, const char *type, const char *name, | ||||
| 		appendPQExpBuffer(sql, "%s;\n", fmtId(usename, force_quotes)); | ||||
| 	} | ||||
| 
 | ||||
| 	free(aclbuf); | ||||
| 
 | ||||
| 	ArchiveEntry(fout, objoid, name, nspname, usename ? usename : "", | ||||
| 				 "ACL", NULL, sql->data, "", NULL, NULL, NULL); | ||||
| 
 | ||||
| 	free(aclbuf); | ||||
| 	destroyPQExpBuffer(sql); | ||||
| } | ||||
| 
 | ||||
| @ -4373,10 +4485,10 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo) | ||||
| 		if (g_fout->remoteVersion >= 70300) | ||||
| 		{ | ||||
| 			/* Beginning in 7.3, viewname is not unique; use OID */ | ||||
| 			appendPQExpBuffer(query, "SELECT pg_get_viewdef(ev_class) as viewdef, " | ||||
| 			appendPQExpBuffer(query, "SELECT pg_catalog.pg_get_viewdef(ev_class) as viewdef, " | ||||
| 							  "oid as view_oid" | ||||
| 							  " from pg_rewrite where" | ||||
| 							  " ev_class = '%s'::oid and" | ||||
| 							  " from pg_catalog.pg_rewrite where" | ||||
| 							  " ev_class = '%s'::pg_catalog.oid and" | ||||
| 							  " rulename = '_RETURN';", | ||||
| 							  tbinfo->oid); | ||||
| 		} | ||||
| @ -4430,8 +4542,12 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo) | ||||
| 		/* Save it for use by dumpACL, too */ | ||||
| 		tbinfo->viewoid = objoid; | ||||
| 
 | ||||
| 		appendPQExpBuffer(delq, "DROP VIEW %s;\n", | ||||
| 		/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 		appendPQExpBuffer(delq, "DROP VIEW %s.", | ||||
| 						  fmtId(tbinfo->relnamespace->nspname, force_quotes)); | ||||
| 		appendPQExpBuffer(delq, "%s;\n", | ||||
| 						  fmtId(tbinfo->relname, force_quotes)); | ||||
| 
 | ||||
| 		appendPQExpBuffer(q, "CREATE VIEW %s AS %s\n", | ||||
| 						  fmtId(tbinfo->relname, force_quotes), viewdef); | ||||
| 
 | ||||
| @ -4466,7 +4582,10 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo) | ||||
| 		numParents = tbinfo->numParents; | ||||
| 		parentIndexes = tbinfo->parentIndexes; | ||||
| 
 | ||||
| 		appendPQExpBuffer(delq, "DROP TABLE %s;\n", | ||||
| 		/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 		appendPQExpBuffer(delq, "DROP TABLE %s.", | ||||
| 						  fmtId(tbinfo->relnamespace->nspname, force_quotes)); | ||||
| 		appendPQExpBuffer(delq, "%s;\n", | ||||
| 						  fmtId(tbinfo->relname, force_quotes)); | ||||
| 
 | ||||
| 		appendPQExpBuffer(q, "CREATE TABLE %s (\n\t", | ||||
| @ -4524,18 +4643,37 @@ dumpOneTable(Archive *fout, TableInfo *tbinfo, TableInfo *g_tblinfo) | ||||
| 						  tbinfo->relname); | ||||
| 
 | ||||
| 			resetPQExpBuffer(query); | ||||
| 			appendPQExpBuffer(query, "SELECT rcname, rcsrc from pg_relcheck " | ||||
| 			if (g_fout->remoteVersion >= 70300) | ||||
| 				appendPQExpBuffer(query, "SELECT rcname, rcsrc" | ||||
| 								  " from pg_catalog.pg_relcheck c1" | ||||
| 								  " where rcrelid = '%s'::pg_catalog.oid " | ||||
| 								  "   and not exists " | ||||
| 								  "  (select 1 from " | ||||
| 								  "    pg_catalog.pg_relcheck c2, " | ||||
| 								  "    pg_catalog.pg_inherits i " | ||||
| 								  "    where i.inhrelid = c1.rcrelid " | ||||
| 								  "      and (c2.rcname = c1.rcname " | ||||
| 								  "          or (c2.rcname[0] = '$' " | ||||
| 								  "              and c1.rcname[0] = '$')" | ||||
| 								  "          )" | ||||
| 								  "      and c2.rcsrc = c1.rcsrc " | ||||
| 								  "      and c2.rcrelid = i.inhparent) " | ||||
| 								  " order by rcname ", | ||||
| 								  tbinfo->oid); | ||||
| 			else | ||||
| 				appendPQExpBuffer(query, "SELECT rcname, rcsrc" | ||||
| 								  " from pg_relcheck c1" | ||||
| 								  " where rcrelid = '%s'::oid " | ||||
| 								  "   and not exists " | ||||
| 							  "  (select 1 from pg_relcheck as c, " | ||||
| 							  "    pg_inherits as i " | ||||
| 							  "    where i.inhrelid = pg_relcheck.rcrelid " | ||||
| 							  "      and (c.rcname = pg_relcheck.rcname " | ||||
| 							  "          or (c.rcname[0] = '$' " | ||||
| 							  "              and pg_relcheck.rcname[0] = '$')" | ||||
| 								  "  (select 1 from pg_relcheck c2, " | ||||
| 								  "    pg_inherits i " | ||||
| 								  "    where i.inhrelid = c1.rcrelid " | ||||
| 								  "      and (c2.rcname = c1.rcname " | ||||
| 								  "          or (c2.rcname[0] = '$' " | ||||
| 								  "              and c1.rcname[0] = '$')" | ||||
| 								  "          )" | ||||
| 							  "      and c.rcsrc = pg_relcheck.rcsrc " | ||||
| 							  "      and c.rcrelid = i.inhparent) " | ||||
| 								  "      and c2.rcsrc = c1.rcsrc " | ||||
| 								  "      and c2.rcrelid = i.inhparent) " | ||||
| 								  " order by rcname ", | ||||
| 								  tbinfo->oid); | ||||
| 			res2 = PQexec(g_conn, query->data); | ||||
| @ -4694,6 +4832,20 @@ dumpIndexes(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
| 		selectSourceSchema(tbinfo->relnamespace->nspname); | ||||
| 
 | ||||
| 		resetPQExpBuffer(query); | ||||
| 		if (g_fout->remoteVersion >= 70300) | ||||
| 			appendPQExpBuffer(query, | ||||
| 							  "SELECT i.indexrelid as indexreloid, " | ||||
| 							  "t.relname as indexrelname, " | ||||
| 							  "pg_catalog.pg_get_indexdef(i.indexrelid) as indexdef, " | ||||
| 							  "i.indisprimary, i.indkey, " | ||||
| 							  "t.relnatts as indnkeys " | ||||
| 							  "FROM pg_catalog.pg_index i, " | ||||
| 							  "pg_catalog.pg_class t " | ||||
| 							  "WHERE t.oid = i.indexrelid " | ||||
| 							  "AND i.indrelid = '%s'::pg_catalog.oid " | ||||
| 							  "ORDER BY indexrelname", | ||||
| 							  tbinfo->oid); | ||||
| 		else | ||||
| 			appendPQExpBuffer(query, | ||||
| 							  "SELECT i.indexrelid as indexreloid, " | ||||
| 							  "t.relname as indexrelname, " | ||||
| @ -4779,7 +4931,10 @@ dumpIndexes(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
| 				/* Plain secondary index */ | ||||
| 				appendPQExpBuffer(q, "%s;\n", indexdef); | ||||
| 
 | ||||
| 				appendPQExpBuffer(delq, "DROP INDEX %s;\n", | ||||
| 				/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 				appendPQExpBuffer(delq, "DROP INDEX %s.", | ||||
| 								  fmtId(tbinfo->relnamespace->nspname, force_quotes)); | ||||
| 				appendPQExpBuffer(delq, "%s;\n", | ||||
| 								  fmtId(indexrelname, force_quotes)); | ||||
| 
 | ||||
| 				ArchiveEntry(fout, indexreloid, | ||||
| @ -4821,7 +4976,7 @@ setMaxOid(Archive *fout) | ||||
| 	Oid			max_oid; | ||||
| 	char		sql[1024]; | ||||
| 
 | ||||
| 	res = PQexec(g_conn, "CREATE TEMPORARY TABLE pgdump_oid (dummy int4)"); | ||||
| 	res = PQexec(g_conn, "CREATE TEMPORARY TABLE pgdump_oid (dummy integer)"); | ||||
| 	if (!res || | ||||
| 		PQresultStatus(res) != PGRES_COMMAND_OK) | ||||
| 	{ | ||||
| @ -4854,7 +5009,7 @@ setMaxOid(Archive *fout) | ||||
| 	if (g_verbose) | ||||
| 		write_msg(NULL, "maximum system oid is %u\n", max_oid); | ||||
| 	snprintf(sql, 1024, | ||||
| 			 "CREATE TEMPORARY TABLE pgdump_oid (dummy int4);\n" | ||||
| 			 "CREATE TEMPORARY TABLE pgdump_oid (dummy integer);\n" | ||||
| 			 "COPY pgdump_oid WITH OIDS FROM stdin;\n" | ||||
| 			 "%u\t0\n" | ||||
| 			 "\\.\n" | ||||
| @ -5014,7 +5169,11 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo, | ||||
| 	if (!dataOnly) | ||||
| 	{ | ||||
| 		resetPQExpBuffer(delqry); | ||||
| 		appendPQExpBuffer(delqry, "DROP SEQUENCE %s;\n", | ||||
| 
 | ||||
| 		/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 		appendPQExpBuffer(delqry, "DROP SEQUENCE %s.", | ||||
| 						  fmtId(tbinfo->relnamespace->nspname, force_quotes)); | ||||
| 		appendPQExpBuffer(delqry, "%s;\n", | ||||
| 						  fmtId(tbinfo->relname, force_quotes)); | ||||
| 
 | ||||
| 		resetPQExpBuffer(query); | ||||
| @ -5036,7 +5195,7 @@ dumpOneSequence(Archive *fout, TableInfo *tbinfo, | ||||
| 	if (!schemaOnly) | ||||
| 	{ | ||||
| 		resetPQExpBuffer(query); | ||||
| 		appendPQExpBuffer(query, "SELECT setval ("); | ||||
| 		appendPQExpBuffer(query, "SELECT pg_catalog.setval ("); | ||||
| 		formatStringLiteral(query, fmtId(tbinfo->relname, force_quotes), CONV_ALL); | ||||
| 		appendPQExpBuffer(query, ", %s, %s);\n", | ||||
| 						  last, (called ? "true" : "false")); | ||||
| @ -5106,13 +5265,14 @@ dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
| 		if (g_fout->remoteVersion >= 70300) | ||||
| 		{ | ||||
| 			appendPQExpBuffer(query, | ||||
| 							  "SELECT tgname, tgfoid::regproc as tgfname, " | ||||
| 							  "SELECT tgname, " | ||||
| 							  "tgfoid::pg_catalog.regproc as tgfname, " | ||||
| 							  "tgtype, tgnargs, tgargs, " | ||||
| 							  "tgisconstraint, tgconstrname, tgdeferrable, " | ||||
| 							  "tgconstrrelid, tginitdeferred, oid, " | ||||
| 							  "tgconstrrelid::regclass as tgconstrrelname " | ||||
| 							  "from pg_trigger " | ||||
| 							  "where tgrelid = '%s'::oid", | ||||
| 							  "tgconstrrelid::pg_catalog.regclass as tgconstrrelname " | ||||
| 							  "from pg_catalog.pg_trigger " | ||||
| 							  "where tgrelid = '%s'::pg_catalog.oid", | ||||
| 							  tbinfo->oid); | ||||
| 		} | ||||
| 		else | ||||
| @ -5186,9 +5346,12 @@ dumpTriggers(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
| 				tginitdeferred = 1; | ||||
| 
 | ||||
| 			resetPQExpBuffer(delqry); | ||||
| 			/* DROP must be fully qualified in case same name appears in pg_catalog */ | ||||
| 			appendPQExpBuffer(delqry, "DROP TRIGGER %s ", | ||||
| 							  fmtId(tgname, force_quotes)); | ||||
| 			appendPQExpBuffer(delqry, "ON %s;\n", | ||||
| 			appendPQExpBuffer(delqry, "ON %s.", | ||||
| 							  fmtId(tbinfo->relnamespace->nspname, force_quotes)); | ||||
| 			appendPQExpBuffer(delqry, "%s;\n", | ||||
| 							  fmtId(tbinfo->relname, force_quotes)); | ||||
| 
 | ||||
| 			resetPQExpBuffer(query); | ||||
| @ -5370,7 +5533,18 @@ dumpRules(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
| 		 */ | ||||
| 		resetPQExpBuffer(query); | ||||
| 
 | ||||
| 		if (g_fout->remoteVersion < 70300) | ||||
| 		if (g_fout->remoteVersion >= 70300) | ||||
| 		{ | ||||
| 			appendPQExpBuffer(query, | ||||
| 							  "SELECT pg_catalog.pg_get_ruledef(oid) AS definition," | ||||
| 							  " oid, rulename " | ||||
| 							  "FROM pg_catalog.pg_rewrite " | ||||
| 							  "WHERE ev_class = '%s'::pg_catalog.oid " | ||||
| 							  "AND rulename != '_RETURN' " | ||||
| 							  "ORDER BY oid", | ||||
| 							  tbinfo->oid); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			/*
 | ||||
| 			 * We include pg_rules in the cross since it filters out all view | ||||
| @ -5387,17 +5561,6 @@ dumpRules(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
| 							  "    AND pg_rules.rulename = pg_rewrite.rulename " | ||||
| 							  "ORDER BY pg_rewrite.oid"); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			appendPQExpBuffer(query, | ||||
| 							  "SELECT pg_get_ruledef(oid) AS definition," | ||||
| 							  " oid, rulename " | ||||
| 							  "FROM pg_rewrite " | ||||
| 							  "WHERE ev_class = '%s'::oid " | ||||
| 							  "AND rulename != '_RETURN' " | ||||
| 							  "ORDER BY oid", | ||||
| 							  tbinfo->oid); | ||||
| 		} | ||||
| 
 | ||||
| 		res = PQexec(g_conn, query->data); | ||||
| 		if (!res || | ||||
| @ -5450,9 +5613,13 @@ dumpRules(Archive *fout, TableInfo *tblinfo, int numTables) | ||||
|  * selectSourceSchema - make the specified schema the active search path | ||||
|  * in the source database. | ||||
|  * | ||||
|  * NB: pg_catalog is implicitly searched before the specified schema; | ||||
|  * so system names are never qualified, and user names are only qualified | ||||
|  * if they are cross-schema references or duplicate system names. | ||||
|  * NB: pg_catalog is explicitly searched after the specified schema; | ||||
|  * so user names are only qualified if they are cross-schema references, | ||||
|  * and system names are only qualified if they conflict with a user name | ||||
|  * in the current schema. | ||||
|  * | ||||
|  * Whenever the selected schema is not pg_catalog, be careful to qualify | ||||
|  * references to system catalogs and types in our emitted commands! | ||||
|  */ | ||||
| static void | ||||
| selectSourceSchema(const char *schemaName) | ||||
| @ -5474,6 +5641,8 @@ selectSourceSchema(const char *schemaName) | ||||
| 	query = createPQExpBuffer(); | ||||
| 	appendPQExpBuffer(query, "SET search_path = %s", | ||||
| 					  fmtId(schemaName, force_quotes)); | ||||
| 	if (strcmp(schemaName, "pg_catalog") != 0) | ||||
| 		appendPQExpBuffer(query, ", pg_catalog"); | ||||
| 	res = PQexec(g_conn, query->data); | ||||
| 	if (!res || | ||||
| 		PQresultStatus(res) != PGRES_COMMAND_OK) | ||||
| @ -5518,7 +5687,12 @@ getFormattedTypeName(const char *oid, OidOptions opts) | ||||
| 	} | ||||
| 
 | ||||
| 	query = createPQExpBuffer(); | ||||
| 	if (g_fout->remoteVersion >= 70100) | ||||
| 	if (g_fout->remoteVersion >= 70300) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT pg_catalog.format_type('%s'::pg_catalog.oid, NULL)", | ||||
| 						  oid); | ||||
| 	} | ||||
| 	else if (g_fout->remoteVersion >= 70100) | ||||
| 	{ | ||||
| 		appendPQExpBuffer(query, "SELECT format_type('%s'::oid, NULL)", | ||||
| 						  oid); | ||||
| @ -5549,7 +5723,16 @@ getFormattedTypeName(const char *oid, OidOptions opts) | ||||
| 		exit_nicely(); | ||||
| 	} | ||||
| 
 | ||||
| 	if (g_fout->remoteVersion >= 70100) | ||||
| 	{ | ||||
| 		/* already quoted */ | ||||
| 		result = strdup(PQgetvalue(res, 0, 0)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		/* may need to quote it */ | ||||
| 		result = strdup(fmtId(PQgetvalue(res, 0, 0), false)); | ||||
| 	} | ||||
| 
 | ||||
| 	PQclear(res); | ||||
| 	destroyPQExpBuffer(query); | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group | ||||
|  * Portions Copyright (c) 1994, Regents of the University of California | ||||
|  * | ||||
|  * $Id: pg_dump.h,v 1.86 2002/05/19 10:08:25 petere Exp $ | ||||
|  * $Id: pg_dump.h,v 1.87 2002/05/28 22:26:57 tgl Exp $ | ||||
|  * | ||||
|  *------------------------------------------------------------------------- | ||||
|  */ | ||||
| @ -70,10 +70,11 @@ typedef struct _aggInfo | ||||
| { | ||||
| 	char	   *oid; | ||||
| 	char	   *aggname; | ||||
| 	char	   *aggbasetype; | ||||
| 	char	   *aggbasetype;	/* OID */ | ||||
| 	NamespaceInfo *aggnamespace;	/* link to containing namespace */ | ||||
| 	char	   *usename; | ||||
| 	char	   *aggacl; | ||||
| 	char	   *fmtbasetype;	/* formatted type name */ | ||||
| } AggInfo; | ||||
| 
 | ||||
| typedef struct _oprInfo | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user