From c74257e9e0d31fd07e06c2e1c333ca21b1f3eace Mon Sep 17 00:00:00 2001
From: Philip Warner <pjw@rhyme.com.au>
Date: Fri, 15 Sep 2000 04:35:16 +0000
Subject: [PATCH] - Support for relkind = RELKIND_VIEW. - Use symbols for tests
 on relkind (ie. use RELKIND_VIEW, not 'v') - Fix bug in support for -b option
 (== --blobs). - Dump views as views (using 'create view'). - Remove
 'isViewRule' since we check the relkind when getting tables. - Now uses temp
 table 'pgdump_oid' rather than 'pg_dump_oid' (errors otherwise). - Added
 extra param for specifying handling of OID=0 and which typename to output. -
 Fixed bug in SQL scanner when SQL contained braces. (in rules) - Use
 format_type function wherever possible

---
 src/bin/pg_dump/common.c             |  35 ++-
 src/bin/pg_dump/pg_backup_archiver.h |   8 +-
 src/bin/pg_dump/pg_backup_db.c       |  11 +-
 src/bin/pg_dump/pg_dump.c            | 344 ++++++++++++---------------
 src/bin/pg_dump/pg_dump.h            |  19 +-
 5 files changed, 217 insertions(+), 200 deletions(-)

diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index d7cb9e488a5..8e1847b8d6a 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.45 2000/08/06 17:50:48 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/common.c,v 1.46 2000/09/15 04:35:16 pjw Exp $
  *
  * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
  *
@@ -16,6 +16,14 @@
  *	 - Added single. quote to twin single quote expansion for 'insert' string
  *	   mode.
  *
+ * Modifications 14-Sep-2000 - pjw@rhyme.com.au 
+ *	-	Added enum for findTypeByOid to specify how to handle OID and which 
+ *		string to return - formatted type, or base type. If the base type
+ *		is returned then fmtId is called on the string.
+ *
+ *		BEWARE: Since fmtId uses a static buffer, using 'useBaseTypeName' on more
+ *				than one call in a line will cause problems.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -50,17 +58,32 @@ static int	strInArray(const char *pattern, char **arr, int arr_size);
  */
 
 char *
-findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid)
+findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts)
 {
 	int			i;
 
-	if (strcmp(oid, "0") == 0)
-		return g_opaque_type;
+	if (strcmp(oid, "0") == 0) {
+
+		if ( (opts & zeroAsOpaque) != 0 ) {
+
+			return g_opaque_type;
+
+		} else if ( (opts & zeroAsAny) != 0 ) {
+
+			return "'any'";
+
+		}
+	}
 
 	for (i = 0; i < numTypes; i++)
 	{
-		if (strcmp(tinfo[i].oid, oid) == 0)
-			return tinfo[i].typname;
+		if (strcmp(tinfo[i].oid, oid) == 0) {
+			if ( (opts & useBaseTypeName) != 0 ) {
+				return fmtId(tinfo[i].typname, false);
+			} else {
+				return tinfo[i].typedefn;
+			}
+		}
 	}
 
 	/* should never get here */
diff --git a/src/bin/pg_dump/pg_backup_archiver.h b/src/bin/pg_dump/pg_backup_archiver.h
index 4ee00589d61..0abd9a77db6 100644
--- a/src/bin/pg_dump/pg_backup_archiver.h
+++ b/src/bin/pg_dump/pg_backup_archiver.h
@@ -20,7 +20,10 @@
  *
  * Modifications - 28-Jun-2000 - pjw@rhyme.com.au
  *
- *	Initial version. 
+ *		Initial version. 
+ *
+ * Modifications - 15-Sep-2000 - pjw@rhyme.com.au
+ *	-	Added braceDepth to sqlparseInfo to handle braces in rule definitions.
  *
  *-------------------------------------------------------------------------
  */
@@ -59,7 +62,7 @@ typedef z_stream *z_streamp;
 
 #define K_VERS_MAJOR 1
 #define K_VERS_MINOR 4 
-#define K_VERS_REV 11 
+#define K_VERS_REV 14 
 
 /* Data block types */
 #define BLK_DATA 1
@@ -124,6 +127,7 @@ typedef struct {
 	sqlparseState		state;
 	char				lastChar;
 	char				quoteChar;
+	int					braceDepth;
 } sqlparseInfo;
 
 typedef struct _archiveHandle {
diff --git a/src/bin/pg_dump/pg_backup_db.c b/src/bin/pg_dump/pg_backup_db.c
index bf6ccffc2a9..d606508a36a 100644
--- a/src/bin/pg_dump/pg_backup_db.c
+++ b/src/bin/pg_dump/pg_backup_db.c
@@ -483,7 +483,7 @@ int ExecuteSqlCommandBuf(ArchiveHandle* AH, void *qryv, int bufLen)
 
 				case SQL_SCAN: /* Default state == 0, set in _allocAH */
 
-					if (qry[pos] == ';')
+					if (qry[pos] == ';' && AH->sqlparse.braceDepth == 0)
 					{
 						/* Send It & reset the buffer */
 						/* fprintf(stderr, "    sending: '%s'\n\n", AH->sqlBuf->data); */
@@ -507,7 +507,16 @@ int ExecuteSqlCommandBuf(ArchiveHandle* AH, void *qryv, int bufLen)
 						else if (qry[pos] == '*' && AH->sqlparse.lastChar == '/')
 						{
 							AH->sqlparse.state = SQL_IN_EXT_COMMENT;
+						} 
+						else if ( qry[pos] == '(' )
+						{
+							AH->sqlparse.braceDepth++;
 						}
+						else if (qry[pos] == ')')
+						{
+							AH->sqlparse.braceDepth--;
+						}
+
 						AH->sqlparse.lastChar = qry[pos];
 					}
 
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 372ff9be4c8..ad3dc94ad69 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -22,7 +22,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.164 2000/09/12 04:15:58 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/bin/pg_dump/pg_dump.c,v 1.165 2000/09/15 04:35:16 pjw Exp $
  *
  * Modifications - 6/10/96 - dave@bensoft.com - version 1.13.dhb
  *
@@ -79,6 +79,14 @@
  *		Fixed minor bug in language dumping code: expbuffres were not being reset.
  *		Fixed version number initialization in _allocAH (pg_backup_archiver.c)
  *
+ * Modifications - 14-Sep-2000 - pjw@rhyme.com.au 
+ *		Use symbols for tests on relkind (ie. use RELKIND_VIEW, not 'v')
+ * 		Support for relkind = RELKIND_VIEW.
+ * 		Fix bug in support for -b option (== --blobs).
+ *		Dump views as views (using 'create view').
+ *		Remove 'isViewRule' since we check the relkind when getting tables.
+ *		Now uses temp table 'pgdump_oid' rather than 'pg_dump_oid' (errors otherwise).
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -124,7 +132,6 @@ static void clearTableInfo(TableInfo *, int);
 static void dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
 			TypeInfo *tinfo, int numTypes);
 static int	findLastBuiltinOid(void);
-static bool isViewRule(char *relname);
 static void setMaxOid(Archive *fout);
 
 static void AddAcl(char *aclbuf, const char *keyword);
@@ -175,6 +182,7 @@ help(const char *progname)
 #ifdef HAVE_GETOPT_LONG
 	puts(
 		"  -a, --data-only          dump out only the data, not the schema\n"
+		"  -b, --blobs				dump out blob data\n"
 	   	"  -c, --clean              clean (drop) schema prior to create\n"
 		"  -C, --create             output commands to create database\n"
 		"  -d, --inserts            dump data as INSERT, rather than COPY, commands\n"
@@ -200,6 +208,7 @@ help(const char *progname)
 #else
 	puts(
 		"  -a                       dump out only the data, no schema\n"
+		"  -b                       dump out blob data\n"
 		"  -c                       clean (drop) schema prior to create\n"
 		"  -C                       output commands to create database\n"
 		"  -d                       dump data as INSERT, rather than COPY, commands\n"
@@ -246,48 +255,6 @@ exit_nicely(PGconn *conn)
 }
 
 
-/*
- * isViewRule
- *				Determine if the relation is a VIEW
- *
- */
-static bool
-isViewRule(char *relname)
-{
-	PGresult   *res;
-	int			ntups;
-	char       rulename[NAMEDATALEN + 5];
-	PQExpBuffer query = createPQExpBuffer();
-
-	appendPQExpBuffer(query, "select relname from pg_class, pg_rewrite ");
-	appendPQExpBuffer(query, "where pg_class.oid = ev_class ");
-	appendPQExpBuffer(query, "and pg_rewrite.ev_type = '1' ");
-	snprintf(rulename,NAMEDATALEN + 5,"_RET%s",relname);
-#ifdef MULTIBYTE
-	int len;
-	len = pg_mbcliplen(rulename,strlen(rulename),NAMEDATALEN-1);
-	rulename[len] = '\0';
-#else
-	rulename[NAMEDATALEN-1] = '\0';
-#endif
-
-	appendPQExpBuffer(query, "and rulename = '%s'", rulename);
-
-	res = PQexec(g_conn, query->data);
-	if (!res ||
-		PQresultStatus(res) != PGRES_TUPLES_OK)
-	{
-		fprintf(stderr, "isViewRule(): SELECT failed.  Explanation from backend: '%s'.\n", 
-					PQerrorMessage(g_conn));
-		exit_nicely(g_conn);
-	}
-
-	ntups = PQntuples(res);
-
-	PQclear(res);
-	return ntups > 0 ? TRUE : FALSE;
-}
-
 #define COPYBUFSIZ		8192
 
 /*
@@ -602,7 +569,7 @@ dumpClasses(const TableInfo *tblinfo, const int numTables, Archive *fout,
 		const char *classname = tblinfo[i].relname;
 
 		/* Skip VIEW relations */
-		if (isViewRule(tblinfo[i].relname))
+		if (tblinfo[i].viewdef != NULL)
 			continue;
 
 		if (tblinfo[i].sequence)/* already dumped */
@@ -724,9 +691,9 @@ main(int argc, char **argv)
 	}
 
 #ifdef HAVE_GETOPT_LONG
-	while ((c = getopt_long(argc, argv, "acCdDf:F:h:inNoOp:sS:t:uvxzZ:V?", long_options, &optindex)) != -1)
+	while ((c = getopt_long(argc, argv, "abcCdDf:F:h:inNoOp:sS:t:uvxzZ:V?", long_options, &optindex)) != -1)
 #else
-	while ((c = getopt(argc, argv, "acCdDf:F:h:inNoOp:sS:t:uvxzZ:V?-")) != -1)
+	while ((c = getopt(argc, argv, "abcCdDf:F:h:inNoOp:sS:t:uvxzZ:V?-")) != -1)
 #endif
 
 	{
@@ -1097,12 +1064,13 @@ dumpBlobs(Archive *AH, char* junkOid, void *junkVal)
 		fprintf(stderr, "%s saving BLOBs\n", g_comment_start);
 
 	/* Cursor to get all BLOB tables */
-    appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT oid from pg_class where relkind = 'l'");
+    appendPQExpBuffer(oidQry, "Declare blobOid Cursor for SELECT oid from pg_class where relkind = '%c'", RELKIND_LOBJECT);
 
 	res = PQexec(g_conn, oidQry->data);
 	if (!res || PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		fprintf(stderr, "dumpBlobs(): Declare Cursor failed.  Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
+		fprintf(stderr, "dumpBlobs(): Declare Cursor failed.  Explanation from backend: '%s'.\n", 
+										PQerrorMessage(g_conn));
 		exit_nicely(g_conn);
 	}
 
@@ -1190,6 +1158,7 @@ getTypes(int *numTypes)
 	int			i_typrelid;
 	int			i_typbyval;
 	int			i_usename;
+	int			i_typedefn;
 
 	/* find all base types */
 
@@ -1204,7 +1173,9 @@ getTypes(int *numTypes)
 
 	appendPQExpBuffer(query, "SELECT pg_type.oid, typowner, typname, typlen, typprtlen, "
 		  "typinput, typoutput, typreceive, typsend, typelem, typdelim, "
-		 "typdefault, typrelid, typbyval, usename from pg_type, pg_user "
+		 "typdefault, typrelid, typbyval, usename, "
+		 "format_type(pg_type.oid, NULL) as typedefn "
+		 "from pg_type, pg_user "
 					  "where typowner = usesysid");
 
 	res = PQexec(g_conn, query->data);
@@ -1234,6 +1205,7 @@ getTypes(int *numTypes)
 	i_typrelid = PQfnumber(res, "typrelid");
 	i_typbyval = PQfnumber(res, "typbyval");
 	i_usename = PQfnumber(res, "usename");
+	i_typedefn = PQfnumber(res, "typedefn");
 
 	for (i = 0; i < ntups; i++)
 	{
@@ -1251,6 +1223,7 @@ getTypes(int *numTypes)
 		tinfo[i].typdefault = strdup(PQgetvalue(res, i, i_typdefault));
 		tinfo[i].typrelid = strdup(PQgetvalue(res, i, i_typrelid));
 		tinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
+		tinfo[i].typedefn = strdup(PQgetvalue(res, i, i_typedefn));
 
 		if (strcmp(PQgetvalue(res, i, i_typbyval), "f") == 0)
 			tinfo[i].passedbyvalue = 0;
@@ -1492,6 +1465,8 @@ clearTableInfo(TableInfo *tblinfo, int numTables)
 			free((int *) tblinfo[i].inhAttrs);
 		if (tblinfo[i].attnames)
 			free(tblinfo[i].attnames);
+		if (tblinfo[i].atttypedefns)
+			free(tblinfo[i].atttypedefns);
 		if (tblinfo[i].typnames)
 			free(tblinfo[i].typnames);
 		if (tblinfo[i].notnull)
@@ -1825,6 +1800,12 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 	int			i_relchecks;
 	int			i_reltriggers;
 	int			i_relhasindex;
+	int			i_viewdef;
+
+	char		relkindview[2];
+
+	relkindview[0] = RELKIND_VIEW;
+	relkindview[1] = '\0';
 
 	/*
 	 * find all the user-defined tables (no indices and no catalogs),
@@ -1832,17 +1813,18 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 	 * tables before the child tables when traversing the tblinfo*
 	 *
 	 * we ignore tables that are not type 'r' (ordinary relation) or 'S'
-	 * (sequence) --- in particular, Large Object relations (type 'l') are
-	 * ignored.
+	 * (sequence) or 'v' (view) --- in particular, Large Object 
+     * relations (type 'l') are ignored.
 	 */
 
 	appendPQExpBuffer(query,
 			   "SELECT pg_class.oid, relname, relkind, relacl, usename, "
-					  "relchecks, reltriggers, relhasindex "
+					  "relchecks, reltriggers, relhasindex, pg_get_viewdef(relname) as viewdef "
 					  "from pg_class, pg_user "
-					  "where relowner = usesysid and "
-				"(relkind = 'r' or relkind = 'S') and relname !~ '^pg_' "
-					  "order by oid");
+					  "where relowner = usesysid and relname !~ '^pg_' "
+					  "and relkind in ('%c', '%c', '%c') "
+					  "order by oid",
+				RELKIND_RELATION, RELKIND_SEQUENCE, RELKIND_VIEW);
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
@@ -1867,6 +1849,7 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 	i_relchecks = PQfnumber(res, "relchecks");
 	i_reltriggers = PQfnumber(res, "reltriggers");
 	i_relhasindex = PQfnumber(res, "relhasindex");
+	i_viewdef = PQfnumber(res, "viewdef");
 
 	for (i = 0; i < ntups; i++)
 	{
@@ -1877,6 +1860,11 @@ getTables(int *numTables, FuncInfo *finfo, int numFuncs)
 		tblinfo[i].usename = strdup(PQgetvalue(res, i, i_usename));
 		tblinfo[i].ncheck = atoi(PQgetvalue(res, i, i_relchecks));
 		tblinfo[i].ntrig = atoi(PQgetvalue(res, i, i_reltriggers));
+		if (strcmp(PQgetvalue(res, i, i_relkind), relkindview) == 0) {
+			tblinfo[i].viewdef = strdup(PQgetvalue(res, i, i_viewdef));
+		} else {
+			tblinfo[i].viewdef = NULL;
+		}
 
 		/*
 		 * Exclude inherited CHECKs from CHECK constraints total. If a
@@ -2361,6 +2349,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 	int			i_attnotnull;
 	int			i_atthasdef;
 	int			i_attoid;
+	int			i_atttypedefn;
 	PGresult   *res;
 	int			ntups;
 
@@ -2385,7 +2374,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 
 		resetPQExpBuffer(q);
 		appendPQExpBuffer(q, "SELECT a.oid as attoid, a.attnum, a.attname, t.typname, a.atttypmod, "
-						  "a.attnotnull, a.atthasdef "
+						  "a.attnotnull, a.atthasdef, format_type(a.atttypid, a.atttypmod) as atttypedefn "
 						  "from pg_attribute a, pg_type t "
 				   "where a.attrelid = '%s'::oid and a.atttypid = t.oid "
 						  "and a.attnum > 0 order by attnum",
@@ -2407,10 +2396,12 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		i_atttypmod = PQfnumber(res, "atttypmod");
 		i_attnotnull = PQfnumber(res, "attnotnull");
 		i_atthasdef = PQfnumber(res, "atthasdef");
+		i_atttypedefn = PQfnumber(res, "atttypedefn");
 
 		tblinfo[i].numatts = ntups;
 		tblinfo[i].attoids = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].attnames = (char **) malloc(ntups * sizeof(char *));
+		tblinfo[i].atttypedefns = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].typnames = (char **) malloc(ntups * sizeof(char *));
 		tblinfo[i].atttypmod = (int *) malloc(ntups * sizeof(int));
 		tblinfo[i].inhAttrs = (int *) malloc(ntups * sizeof(int));
@@ -2422,6 +2413,7 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		{
 			tblinfo[i].attoids[j] = strdup(PQgetvalue(res, j, i_attoid));
 			tblinfo[i].attnames[j] = strdup(PQgetvalue(res, j, i_attname));
+			tblinfo[i].atttypedefns[j] = strdup(PQgetvalue(res, j, i_atttypedefn));
 			tblinfo[i].typnames[j] = strdup(PQgetvalue(res, j, i_typname));
 			tblinfo[i].atttypmod[j] = atoi(PQgetvalue(res, j, i_atttypmod));
 			tblinfo[i].inhAttrs[j] = 0; /* this flag is set in
@@ -2503,8 +2495,8 @@ getIndices(int *numIndices)
 					"from pg_index i, pg_class t1, pg_class t2, pg_am a "
 				   "WHERE t1.oid = i.indexrelid and t2.oid = i.indrelid "
 					  "and t1.relam = a.oid and i.indexrelid > '%u'::oid "
-					  "and t2.relname !~ '^pg_' and t2.relkind != 'l' and not i.indisprimary",
-					  g_last_builtin_oid);
+					  "and t2.relname !~ '^pg_' and t2.relkind != '%c' and not i.indisprimary",
+					  g_last_builtin_oid, RELKIND_LOBJECT);
 
 	res = PQexec(g_conn, query->data);
 	if (!res ||
@@ -2720,7 +2712,7 @@ dumpTypes(Archive *fout, FuncInfo *finfo, int numFuncs,
 		{
 			char	   *elemType;
 
-			elemType = findTypeByOid(tinfo, numTypes, tinfo[i].typelem);
+			elemType = findTypeByOid(tinfo, numTypes, tinfo[i].typelem, zeroAsOpaque);
 
 			appendPQExpBuffer(q, ", element = %s, delimiter = '%s'",
 							  elemType, tinfo[i].typdelim);
@@ -2922,13 +2914,13 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
 	{
 		char			*typname;
 
-		typname = findTypeByOid(tinfo, numTypes, finfo[i].argtypes[j]);
-		appendPQExpBuffer(fn, "%s%s",
-							(j > 0) ? "," : "",
-							fmtId(typname, false));
+		typname = findTypeByOid(tinfo, numTypes, finfo[i].argtypes[j], zeroAsOpaque);
+		appendPQExpBuffer(fn, "%s%s", 
+							(j > 0) ? "," : "", 
+							typname);
 		appendPQExpBuffer(fnlist, "%s%s",
-							(j > 0) ? "," : "",
-							fmtId(typname, false));
+							(j > 0) ? "," : "", 
+							typname );
 	}
 	appendPQExpBuffer(fn, ")");
 
@@ -2939,7 +2931,7 @@ dumpOneFunc(Archive *fout, FuncInfo *finfo, int i,
 	appendPQExpBuffer(q, "CREATE FUNCTION %s ", fn->data );
 	appendPQExpBuffer(q, "RETURNS %s%s %s LANGUAGE '%s'",
 					  (finfo[i].retset) ? " SETOF " : "",
-					  fmtId(findTypeByOid(tinfo, numTypes, finfo[i].prorettype), false),
+					  findTypeByOid(tinfo, numTypes, finfo[i].prorettype, zeroAsOpaque),
 					  asPart->data, func_lang);
 
 	if (finfo[i].iscachable) /* OR in new attrs here */
@@ -3014,13 +3006,13 @@ dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators,
 			strcmp(oprinfo[i].oprkind, "b") == 0)
 		{
 			appendPQExpBuffer(leftarg, ",\n\tLEFTARG = %s ",
-							  fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft), false));
+								findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft, zeroAsOpaque) );
 		}
 		if (strcmp(oprinfo[i].oprkind, "l") == 0 ||
 			strcmp(oprinfo[i].oprkind, "b") == 0)
 		{
 			appendPQExpBuffer(rightarg, ",\n\tRIGHTARG = %s ",
-							  fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprright), false));
+							  findTypeByOid(tinfo, numTypes, oprinfo[i].oprright, zeroAsOpaque) );
 		}
 		if (!(strcmp(oprinfo[i].oprcom, "0") == 0))
 			appendPQExpBuffer(commutator, ",\n\tCOMMUTATOR = %s ",
@@ -3046,11 +3038,9 @@ dumpOprs(Archive *fout, OprInfo *oprinfo, int numOperators,
 
 		resetPQExpBuffer(delq);
 		appendPQExpBuffer(delq, "DROP OPERATOR %s (%s", oprinfo[i].oprname,
-				fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft),
-					  false));
+				findTypeByOid(tinfo, numTypes, oprinfo[i].oprleft, zeroAsOpaque) );
 		appendPQExpBuffer(delq, ", %s);\n",
-				fmtId(findTypeByOid(tinfo, numTypes, oprinfo[i].oprright),
-					 false));
+					findTypeByOid(tinfo, numTypes, oprinfo[i].oprright, zeroAsOpaque) );
 
 		resetPQExpBuffer(q);
 		appendPQExpBuffer(q,
@@ -3098,12 +3088,12 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 
 		appendPQExpBuffer(details,
 						  "BASETYPE = %s, ",
-						  fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype), false));
+						  findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsAny + useBaseTypeName));
 
 		appendPQExpBuffer(details,
 						  "SFUNC = %s, STYPE = %s",
 						  agginfo[i].aggtransfn,
-						  fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype), false));
+						  findTypeByOid(tinfo, numTypes, agginfo[i].aggtranstype, zeroAsOpaque + useBaseTypeName));
 
 		if (agginfo[i].agginitval)
 			appendPQExpBuffer(details, ", INITCOND = '%s'",
@@ -3115,7 +3105,7 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 
 		resetPQExpBuffer(aggSig);
 		appendPQExpBuffer(aggSig, "%s %s", agginfo[i].aggname,
-							fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype), false));
+							findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName));
 
 		resetPQExpBuffer(delq);
 		appendPQExpBuffer(delq, "DROP AGGREGATE %s;\n", aggSig->data);
@@ -3132,7 +3122,7 @@ dumpAggs(Archive *fout, AggInfo *agginfo, int numAggs,
 
 		resetPQExpBuffer(q);
 		appendPQExpBuffer(q, "AGGREGATE %s %s", agginfo[i].aggname,
-						  fmtId(findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype), false));
+						  findTypeByOid(tinfo, numTypes, agginfo[i].aggbasetype, zeroAsOpaque + useBaseTypeName));
 		dumpComment(fout, q->data, agginfo[i].oid);
 
 	}
@@ -3254,8 +3244,8 @@ dumpACL(Archive *fout, TableInfo tbinfo)
 		eqpos = strchr(tok, '=');
 		if (!eqpos)
 		{
-			fprintf(stderr, "Could not parse ACL list for '%s'...Exiting!\n",
-					tbinfo.relname);
+			fprintf(stderr, "Could not parse ACL list ('%s') for '%s'...Exiting!\n",
+					acls, tbinfo.relname);
 			exit_nicely(g_conn);
 		}
 
@@ -3324,9 +3314,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
 	char	  **parentRels;		/* list of names of parent relations */
 	int			numParents;
 	int			actual_atts;	/* number of attrs in this CREATE statment */
-	int32		tmp_typmod;
-	int			precision;
-	int			scale;
+	char	   *reltypename;
 
 	/* First - dump SEQUENCEs */
 	if (tablename)
@@ -3359,121 +3347,94 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
 		if (!tablename || (!strcmp(tblinfo[i].relname, tablename)))
 		{
 
-			/* Skip VIEW relations */
-			
-			/* if (isViewRule(tblinfo[i].relname)) continue; */
-			
+			resetPQExpBuffer(delq);
+			resetPQExpBuffer(q);
 
-			parentRels = tblinfo[i].parentRels;
-			numParents = tblinfo[i].numParents;
+			/* Use the view definition if there is one */
+			if (tblinfo[i].viewdef != NULL)
+			{
+				reltypename = "VIEW";
 
-			resetPQExpBuffer(delq);
-			appendPQExpBuffer(delq, "DROP TABLE %s;\n", fmtId(tblinfo[i].relname, force_quotes));
+				appendPQExpBuffer(delq, "DROP VIEW %s;\n", fmtId(tblinfo[i].relname, force_quotes));
+				appendPQExpBuffer(q, "CREATE VIEW %s as %s", fmtId(tblinfo[i].relname, force_quotes), tblinfo[i].viewdef);
 
-			resetPQExpBuffer(q);
-			appendPQExpBuffer(q, "CREATE TABLE %s (\n\t", fmtId(tblinfo[i].relname, force_quotes));
-			actual_atts = 0;
-			for (j = 0; j < tblinfo[i].numatts; j++)
+			}
+			else
 			{
-				if (tblinfo[i].inhAttrs[j] == 0)
-				{
-					if (actual_atts > 0)
-						appendPQExpBuffer(q, ",\n\t");
-					appendPQExpBuffer(q, "%s ",
-							fmtId(tblinfo[i].attnames[j], force_quotes));
+				reltypename = "TABLE";
 
-					/* Show lengths on bpchar and varchar */
-					if (!strcmp(tblinfo[i].typnames[j], "bpchar"))
-					{
-						int			len = (tblinfo[i].atttypmod[j] - VARHDRSZ);
+				parentRels = tblinfo[i].parentRels;
+				numParents = tblinfo[i].numParents;
 
-						appendPQExpBuffer(q, "character");
-						if (len > 1)
-							appendPQExpBuffer(q, "(%d)",
-									 tblinfo[i].atttypmod[j] - VARHDRSZ);
-					}
-					else if (!strcmp(tblinfo[i].typnames[j], "varchar"))
-					{
-						appendPQExpBuffer(q, "character varying");
-						if (tblinfo[i].atttypmod[j] != -1)
-						{
-							appendPQExpBuffer(q, "(%d)",
-									 tblinfo[i].atttypmod[j] - VARHDRSZ);
-						}
-					}
-					else if (!strcmp(tblinfo[i].typnames[j], "numeric"))
-					{
-						appendPQExpBuffer(q, "numeric");
-						if (tblinfo[i].atttypmod[j] != -1)
-						{
-							tmp_typmod = tblinfo[i].atttypmod[j] - VARHDRSZ;
-							precision = (tmp_typmod >> 16) & 0xffff;
-							scale = tmp_typmod & 0xffff;
-							appendPQExpBuffer(q, "(%d,%d)",
-											  precision, scale);
-						}
-					}
+				appendPQExpBuffer(delq, "DROP TABLE %s;\n", fmtId(tblinfo[i].relname, force_quotes));
 
-					/*
-					 * char is an internal single-byte data type; Let's
-					 * make sure we force it through with quotes. - thomas
-					 * 1998-12-13
-					 */
-					else if (!strcmp(tblinfo[i].typnames[j], "char"))
-					{
-						appendPQExpBuffer(q, "%s",
-									fmtId(tblinfo[i].typnames[j], true));
-					}
-					else
+				appendPQExpBuffer(q, "CREATE TABLE %s (\n\t", fmtId(tblinfo[i].relname, force_quotes));
+				actual_atts = 0;
+				for (j = 0; j < tblinfo[i].numatts; j++)
+				{
+					/* Is this one of the table's own attrs ? */
+					if (tblinfo[i].inhAttrs[j] == 0)
 					{
-						appendPQExpBuffer(q, "%s",
-								   fmtId(tblinfo[i].typnames[j], false));
-					}
-					if (tblinfo[i].adef_expr[j] != NULL)
-						appendPQExpBuffer(q, " DEFAULT %s",
+						/* Format properly if not first attr */
+						if (actual_atts > 0)
+							appendPQExpBuffer(q, ",\n\t");
+
+						/* Attr name & type */
+						appendPQExpBuffer(q, "%s %s",
+							fmtId(tblinfo[i].attnames[j], force_quotes),
+							tblinfo[i].atttypedefns[j]);
+
+						/* Default value */
+						if (tblinfo[i].adef_expr[j] != NULL)
+							appendPQExpBuffer(q, " DEFAULT %s",
 										  tblinfo[i].adef_expr[j]);
-					if (tblinfo[i].notnull[j])
-						appendPQExpBuffer(q, " NOT NULL");
-					actual_atts++;
+
+						/* Not Null constraint */
+						if (tblinfo[i].notnull[j])
+							appendPQExpBuffer(q, " NOT NULL");
+
+						actual_atts++;
+					}
 				}
-			}
 
-			/* put the CONSTRAINTS inside the table def */
-			for (k = 0; k < tblinfo[i].ncheck; k++)
-			{
-				if (actual_atts + k > 0)
-					appendPQExpBuffer(q, ",\n\t");
-				appendPQExpBuffer(q, "%s",
+				/* put the CONSTRAINTS inside the table def */
+				for (k = 0; k < tblinfo[i].ncheck; k++)
+				{
+					if (actual_atts + k > 0)
+						appendPQExpBuffer(q, ",\n\t");
+
+					appendPQExpBuffer(q, "%s",
 								  tblinfo[i].check_expr[k]);
-			}
+				}
 
-			/* PRIMARY KEY */
-			if (tblinfo[i].primary_key)
-			{
-				if (actual_atts + tblinfo[i].ncheck > 0)
-					appendPQExpBuffer(q, ",\n\t");
-				appendPQExpBuffer(q, "PRIMARY KEY (%s)", tblinfo[i].primary_key);
-			}
+				/* PRIMARY KEY */
+				if (tblinfo[i].primary_key)
+				{
+					if (actual_atts + tblinfo[i].ncheck > 0)
+						appendPQExpBuffer(q, ",\n\t");
+					appendPQExpBuffer(q, "PRIMARY KEY (%s)", tblinfo[i].primary_key);
+				}
 
-			appendPQExpBuffer(q, "\n)");
+				appendPQExpBuffer(q, "\n)");
 
-			if (numParents > 0)
-			{
-				appendPQExpBuffer(q, "\ninherits (");
-				for (k = 0; k < numParents; k++)
+				if (numParents > 0)
 				{
-					appendPQExpBuffer(q, "%s%s",
+					appendPQExpBuffer(q, "\ninherits (");
+					for (k = 0; k < numParents; k++)
+					{
+						appendPQExpBuffer(q, "%s%s",
 									  (k > 0) ? ", " : "",
 									  fmtId(parentRels[k], force_quotes));
+					}
+					appendPQExpBuffer(q, ")");
 				}
-				appendPQExpBuffer(q, ")");
-			}
 
-			appendPQExpBuffer(q, ";\n");
+				appendPQExpBuffer(q, ";\n");
+			}
 
 			if (!dataOnly) {
-				ArchiveEntry(fout, tblinfo[i].oid, fmtId(tblinfo[i].relname, false),
-								"TABLE", NULL, q->data, delq->data, "", tblinfo[i].usename,
+					ArchiveEntry(fout, tblinfo[i].oid, fmtId(tblinfo[i].relname, false),
+								reltypename, NULL, q->data, delq->data, "", tblinfo[i].usename,
 								NULL, NULL);
 			}
 
@@ -3494,7 +3455,7 @@ dumpTables(Archive *fout, TableInfo *tblinfo, int numTables,
 			/* Dump Table Comments */
 
 			resetPQExpBuffer(q);
-			appendPQExpBuffer(q, "TABLE %s", fmtId(tblinfo[i].relname, force_quotes));
+			appendPQExpBuffer(q, "%s %s", reltypename, fmtId(tblinfo[i].relname, force_quotes));
 			dumpComment(fout, q->data, tblinfo[i].oid);
 
 		}
@@ -3756,20 +3717,20 @@ setMaxOid(Archive *fout)
 	char		sql[1024];
 	int		pos;
 
-	res = PQexec(g_conn, "CREATE TEMPORARY TABLE pg_dump_oid (dummy int4)");
+	res = PQexec(g_conn, "CREATE TEMPORARY TABLE pgdump_oid (dummy int4)");
 	if (!res ||
 		PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		fprintf(stderr, "Can not create pg_dump_oid table.  "
+		fprintf(stderr, "Can not create pgdump_oid table.  "
 					"Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
 		exit_nicely(g_conn);
 	}
 	PQclear(res);
-	res = PQexec(g_conn, "INSERT INTO pg_dump_oid VALUES (0)");
+	res = PQexec(g_conn, "INSERT INTO pgdump_oid VALUES (0)");
 	if (!res ||
 		PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		fprintf(stderr, "Can not insert into pg_dump_oid table.  "
+		fprintf(stderr, "Can not insert into pgdump_oid table.  "
 					"Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
 		exit_nicely(g_conn);
 	}
@@ -3780,11 +3741,11 @@ setMaxOid(Archive *fout)
 		exit_nicely(g_conn);
 	}
 	PQclear(res);
-	res = PQexec(g_conn, "DROP TABLE pg_dump_oid;");
+	res = PQexec(g_conn, "DROP TABLE pgdump_oid;");
 	if (!res ||
 		PQresultStatus(res) != PGRES_COMMAND_OK)
 	{
-		fprintf(stderr, "Can not drop pg_dump_oid table.  "
+		fprintf(stderr, "Can not drop pgdump_oid table.  "
 							"Explanation from backend: '%s'.\n", PQerrorMessage(g_conn));
 		exit_nicely(g_conn);
 	}
@@ -3792,11 +3753,11 @@ setMaxOid(Archive *fout)
 	if (g_verbose)
 		fprintf(stderr, "%s maximum system oid is %u %s\n",
 				g_comment_start, max_oid, g_comment_end);
-	pos = snprintf(sql, 1024, "CREATE TEMPORARY TABLE pg_dump_oid (dummy int4);\n");
-	pos = pos + snprintf(sql+pos, 1024-pos, "COPY pg_dump_oid WITH OIDS FROM stdin;\n");
+	pos = snprintf(sql, 1024, "CREATE TEMPORARY TABLE pgdump_oid (dummy int4);\n");
+	pos = pos + snprintf(sql+pos, 1024-pos, "COPY pgdump_oid WITH OIDS FROM stdin;\n");
 	pos = pos + snprintf(sql+pos, 1024-pos, "%-d\t0\n", max_oid);
 	pos = pos + snprintf(sql+pos, 1024-pos, "\\.\n");
-	pos = pos + snprintf(sql+pos, 1024-pos, "DROP TABLE pg_dump_oid;\n");
+	pos = pos + snprintf(sql+pos, 1024-pos, "DROP TABLE pgdump_oid;\n");
 
 	ArchiveEntry(fout, "0", "Max OID", "<Init>", NULL, sql, "", "", "", NULL, NULL);
 }
@@ -4015,13 +3976,18 @@ dumpRules(Archive *fout, const char *tablename,
 
 		/*
 		 * Get all rules defined for this table
+		 * We include pg_rules in the cross since it filters out
+		 * all view rules (pjw 15-Sep-2000).
 		 */
 		resetPQExpBuffer(query);
-		appendPQExpBuffer(query, "SELECT pg_get_ruledef(pg_rewrite.rulename) AS definition,"
-						  "pg_get_userbyid(pg_class.relowner) AS viewowner, "
-						  "pg_rewrite.oid, pg_rewrite.rulename FROM pg_rewrite, pg_class "
+		appendPQExpBuffer(query, "SELECT definition,"
+						  "   pg_get_userbyid(pg_class.relowner) AS viewowner, "
+						  "   pg_rewrite.oid, pg_rewrite.rulename "
+						  "FROM pg_rewrite, pg_class, pg_rules "
 						  "WHERE pg_class.relname = '%s' "
-						  "AND pg_rewrite.ev_class = pg_class.oid "
+						  "    AND pg_rewrite.ev_class = pg_class.oid "
+						  "    AND pg_rules.tablename = pg_class.relname "
+						  "    AND pg_rules.rulename = pg_rewrite.rulename "
 						  "ORDER BY pg_rewrite.oid",
 						  tblinfo[t].relname);
 		res = PQexec(g_conn, query->data);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index b687e42d6a8..728905cdcbe 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_dump.h,v 1.51 2000/08/07 12:32:54 pjw Exp $
+ * $Id: pg_dump.h,v 1.52 2000/09/15 04:35:16 pjw Exp $
  *
  * Modifications - 6/12/96 - dave@bensoft.com - version 1.13.dhb.2
  *
@@ -17,6 +17,12 @@
  * Modifications - 6/1/97 - igor@sba.miami.edu
  * - Added extern's for the functions that clear allocated memory
  *	 in pg_dump.c
+ *
+ * Modifications - 14-Sep-2000 - pjw@rhyme.com.au
+ *	- 	Added typedefn fields to typeinfo and relinfo
+ * 	- 	Added enum for findTypeByOid to allow special handling of
+ *		'0' OID.
+ *
  *-------------------------------------------------------------------------
  */
 
@@ -45,6 +51,7 @@ typedef struct _typeInfo
 	char	   *typdefault;
 	char	   *typrelid;
 	char	   *usename;
+	char	   *typedefn;
 	int			passedbyvalue;
 	int			isArray;
 } TypeInfo;
@@ -80,6 +87,7 @@ typedef struct _tableInfo
 	char	   *oid;
 	char	   *relname;
 	char	   *relacl;
+	char	   *viewdef;
 	bool		sequence;
 	int			numatts;		/* number of attributes */
 	int		   *inhAttrs;		/* an array of flags, one for each
@@ -87,6 +95,7 @@ typedef struct _tableInfo
 								 * attribute is an inherited attribute */
 	char	  **attnames;		/* the attribute names */
 	char	  **attoids;		/* oids of the various attributes */
+	char	  **atttypedefns;	/* formatted column type definitions */
 	char	  **typnames;		/* fill out attributes */
 	bool	   *notnull;		/* Not null constraints of an attribute */
 	char	  **adef_expr;		/* DEFAULT expressions */
@@ -197,7 +206,13 @@ extern void dumpSchemaIdx(Archive *fout,
 			  TableInfo *tblinfo,
 			  int numTables);
 
-extern char *findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid);
+typedef enum _OidOptions {
+	zeroAsOpaque = 1,
+	zeroAsAny = 2,
+    useBaseTypeName = 1024
+} OidOptions;
+
+extern char *findTypeByOid(TypeInfo *tinfo, int numTypes, const char *oid, OidOptions opts);
 extern char *findOprByOid(OprInfo *oprinfo, int numOprs, const char *oid);
 extern int	findFuncByName(FuncInfo *finfo, int numFuncs, const char *name);
 extern int	findTableByName(TableInfo *tbinfo, int numTables, const char *relname);
-- 
GitLab