From 3d726290c0b32ec1368ed5ba95d98bfb65214db6 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <peter_e@gmx.net>
Date: Wed, 24 Apr 2002 05:24:00 +0000
Subject: [PATCH] Remove traces of NAMEDATALEN and INDEX_MAX_KEYS from psql. 
 Build buffers dynamically with PQExpBuffer.

---
 src/bin/psql/command.c  |  10 +-
 src/bin/psql/copy.c     |  50 ++--
 src/bin/psql/describe.c | 525 ++++++++++++++++++++--------------------
 3 files changed, 292 insertions(+), 293 deletions(-)

diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index a0d4a5ca1a4..eceecd7d26a 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.71 2002/03/27 19:16:13 petere Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/command.c,v 1.72 2002/04/24 05:24:00 petere Exp $
  */
 #include "postgres_fe.h"
 #include "command.h"
@@ -1433,14 +1433,16 @@ bool
 test_superuser(const char *username)
 {
 	PGresult   *res;
-	char		buf[64 + NAMEDATALEN];
+	PQExpBufferData buf;
 	bool		answer;
 
 	if (!username)
 		return false;
 
-	sprintf(buf, "SELECT usesuper FROM pg_user WHERE usename = '%.*s'", NAMEDATALEN, username);
-	res = PSQLexec(buf);
+	initPQExpBuffer(&buf);
+	printfPQExpBuffer(&buf, "SELECT usesuper FROM pg_user WHERE usename = '%s'", username);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 
 	answer =
 		(PQntuples(res) > 0 && PQnfields(res) > 0
diff --git a/src/bin/psql/copy.c b/src/bin/psql/copy.c
index e374e698eba..52c0c0e4010 100644
--- a/src/bin/psql/copy.c
+++ b/src/bin/psql/copy.c
@@ -3,7 +3,7 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.20 2002/02/23 21:46:03 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/copy.c,v 1.21 2002/04/24 05:24:00 petere Exp $
  */
 #include "postgres_fe.h"
 #include "copy.h"
@@ -19,6 +19,7 @@
 #endif
 
 #include "libpq-fe.h"
+#include "pqexpbuffer.h"
 #include "pqsignal.h"
 
 #include "settings.h"
@@ -229,12 +230,12 @@ parse_slash_copy(const char *args)
 bool
 do_copy(const char *args)
 {
-	char		query[128 + NAMEDATALEN];
+	PQExpBufferData query;
 	FILE	   *copystream;
 	struct copy_options *options;
 	PGresult   *result;
 	bool		success;
-  struct stat st;
+	struct stat st;
 
 	/* parse options */
 	options = parse_slash_copy(args);
@@ -242,35 +243,27 @@ do_copy(const char *args)
 	if (!options)
 		return false;
 
-	strcpy(query, "COPY ");
+	initPQExpBuffer(&query);
+
+	printfPQExpBuffer(&query, "COPY ");
 	if (options->binary)
-		strcat(query, "BINARY ");
+		appendPQExpBuffer(&query, "BINARY ");
 
-	strcat(query, "\"");
-	strncat(query, options->table, NAMEDATALEN);
-	strcat(query, "\" ");
+	appendPQExpBuffer(&query, "\"%s\" ", options->table);
 	if (options->oids)
-		strcat(query, "WITH OIDS ");
+		appendPQExpBuffer(&query, "WITH OIDS ");
 
 	if (options->from)
-		strcat(query, "FROM STDIN");
+		appendPQExpBuffer(&query, "FROM STDIN");
 	else
-		strcat(query, "TO STDOUT");
+		appendPQExpBuffer(&query, "TO STDOUT");
 
 
 	if (options->delim)
-	{
-		strcat(query, " USING DELIMITERS '");
-		strcat(query, options->delim);
-		strcat(query, "'");
-	}
+		appendPQExpBuffer(&query, " USING DELIMITERS '%s'", options->delim);
 
 	if (options->null)
-	{
-		strcat(query, " WITH NULL AS '");
-		strcat(query, options->null);
-		strcat(query, "'");
-	}
+		appendPQExpBuffer(&query, " WITH NULL AS '%s'", options->null);
 
 	if (options->from)
 	{
@@ -294,17 +287,20 @@ do_copy(const char *args)
 		free_copy_options(options);
 		return false;
 	}
-  /* make sure the specified file is not a directory */
-  fstat(fileno(copystream),&st);
-  if( S_ISDIR(st.st_mode) ){
-    fclose(copystream);
+
+	/* make sure the specified file is not a directory */
+	fstat(fileno(copystream), &st);
+	if( S_ISDIR(st.st_mode) )
+	{
+		fclose(copystream);
 		psql_error("%s: cannot COPY TO/FROM a directory\n",
 				   options->file);
 		free_copy_options(options);
 		return false;
-  }
+	}
   
-	result = PSQLexec(query);
+	result = PSQLexec(query.data);
+	termPQExpBuffer(&query);
 
 	switch (PQresultStatus(result))
 	{
diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c
index 92fb6ed3a9f..bb40d9b893f 100644
--- a/src/bin/psql/describe.c
+++ b/src/bin/psql/describe.c
@@ -3,12 +3,13 @@
  *
  * Copyright 2000 by PostgreSQL Global Development Group
  *
- * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.50 2002/04/19 23:13:54 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/bin/psql/describe.c,v 1.51 2002/04/24 05:24:00 petere Exp $
  */
 #include "postgres_fe.h"
 #include "describe.h"
 
 #include "libpq-fe.h"
+#include "pqexpbuffer.h"
 
 #include "common.h"
 #include "settings.h"
@@ -26,10 +27,6 @@
  *----------------
  */
 
-/* the maximal size of regular expression we'll accept here */
-/* (it is safe to just change this here) */
-#define REGEXP_CUTOFF (10 * NAMEDATALEN)
-
 
 /* \da
  * takes an optional regexp to match specific aggregates by name
@@ -37,15 +34,17 @@
 bool
 describeAggregates(const char *name)
 {
-	char		buf[384 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
+	initPQExpBuffer(&buf);
+
 	/*
 	 * There are two kinds of aggregates: ones that work on particular
 	 * types and ones that work on all (denoted by input type = 0)
 	 */
-	snprintf(buf, sizeof(buf),
+	printfPQExpBuffer(&buf,
 			 "SELECT p.proname AS \"%s\",\n"
 			 "  CASE p.proargtypes[0]\n"
 			 "    WHEN 0 THEN CAST('%s' AS text)\n"
@@ -58,15 +57,12 @@ describeAggregates(const char *name)
 			 _("Data type"), _("Description"));
 
 	if (name)
-	{
-		strcat(buf, "  AND p.proname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
+		appendPQExpBuffer(&buf, "  AND p.proname ~ '^%s'\n", name);
 
-	strcat(buf, "ORDER BY 1, 2;");
+	appendPQExpBuffer(&buf, "ORDER BY 1, 2;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -86,15 +82,17 @@ describeAggregates(const char *name)
 bool
 describeFunctions(const char *name, bool verbose)
 {
-	char		buf[384 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
+	initPQExpBuffer(&buf);
+
 	/*
 	 * we skip in/out funcs by excluding functions that take some
 	 * arguments, but have no types defined for those arguments
 	 */
-	snprintf(buf, sizeof(buf),
+	printfPQExpBuffer(&buf,
 			 "SELECT format_type(p.prorettype, NULL) as \"%s\",\n"
 			 "  p.proname as \"%s\",\n"
 			 "  oidvectortypes(p.proargtypes) as \"%s\"",
@@ -102,7 +100,7 @@ describeFunctions(const char *name, bool verbose)
 			 _("Argument data types"));
 
 	if (verbose)
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+		appendPQExpBuffer(&buf,
 				 ",\n  u.usename as \"%s\",\n"
 				 "  l.lanname as \"%s\",\n"
 				 "  p.prosrc as \"%s\",\n"
@@ -111,24 +109,21 @@ describeFunctions(const char *name, bool verbose)
 				 _("Source code"), _("Description"));
 
 	if (!verbose)
-		strcat(buf,
+		appendPQExpBuffer(&buf,
 			   "\nFROM pg_proc p\n"
 			   "WHERE p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
 	else
-		strcat(buf,
+		appendPQExpBuffer(&buf,
 			   "\nFROM pg_proc p,  pg_language l, pg_user u\n"
 			   "WHERE p.prolang = l.oid AND p.proowner = u.usesysid\n"
 			   "  AND p.prorettype <> 0 AND (pronargs = 0 OR oidvectortypes(p.proargtypes) <> '') AND NOT p.proisagg\n");
 
 	if (name)
-	{
-		strcat(buf, "  AND p.proname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-	strcat(buf, "ORDER BY 2, 1, 3;");
+		appendPQExpBuffer(&buf, "  AND p.proname ~ '^%s'\n", name);
+	appendPQExpBuffer(&buf, "ORDER BY 2, 1, 3;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -150,22 +145,24 @@ describeFunctions(const char *name, bool verbose)
 bool
 describeTypes(const char *name, bool verbose)
 {
-	char		buf[384 + 2 * REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	snprintf(buf, sizeof(buf),
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
 			 "SELECT format_type(t.oid, NULL) AS \"%s\",\n",
 			 _("Name"));
 	if (verbose)
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+		appendPQExpBuffer(&buf,
 				 "  t.typname AS \"%s\",\n"
 				 "  CASE WHEN t.typlen = -1\n"
 				 "    THEN CAST('var' AS text)\n"
 				 "    ELSE CAST(t.typlen AS text)\n"
 				 "  END AS \"%s\",\n",
 				 _("Internal name"), _("Size"));
-	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+	appendPQExpBuffer(&buf,
 			 "  obj_description(t.oid, 'pg_type') as \"%s\"\n",
 			 _("Description"));
 
@@ -173,20 +170,16 @@ describeTypes(const char *name, bool verbose)
 	 * do not include array types (start with underscore), do not include
 	 * user relations (typrelid!=0)
 	 */
-	strcat(buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
+	appendPQExpBuffer(&buf, "FROM pg_type t\nWHERE t.typrelid = 0 AND t.typname !~ '^_.*'\n");
 
 	if (name)
-	{
 		/* accept either internal or external type name */
-		strcat(buf, "  AND (format_type(t.oid, NULL) ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "' OR t.typname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "')\n");
-	}
-	strcat(buf, "ORDER BY 1;");
+		appendPQExpBuffer(&buf, "  AND (format_type(t.oid, NULL) ~ '^%s' OR t.typname ~ '^%s')\n", name, name);
 
-	res = PSQLexec(buf);
+	appendPQExpBuffer(&buf, "ORDER BY 1;");
+
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -206,11 +199,13 @@ describeTypes(const char *name, bool verbose)
 bool
 describeOperators(const char *name)
 {
-	char		buf[384 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	snprintf(buf, sizeof(buf),
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
 			 "SELECT o.oprname AS \"%s\",\n"
 			 "  CASE WHEN o.oprkind='l' THEN NULL ELSE format_type(o.oprleft, NULL) END AS \"%s\",\n"
 			 "  CASE WHEN o.oprkind='r' THEN NULL ELSE format_type(o.oprright, NULL) END AS \"%s\",\n"
@@ -220,15 +215,12 @@ describeOperators(const char *name)
 			 _("Name"), _("Left arg type"), _("Right arg type"),
 			 _("Result type"), _("Description"));
 	if (name)
-	{
-		strcat(buf, "WHERE o.oprname = '");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
+		appendPQExpBuffer(&buf, "WHERE o.oprname = '%s'\n", name);
 
-	strcat(buf, "ORDER BY 1, 2, 3, 4;");
+	appendPQExpBuffer(&buf, "ORDER BY 1, 2, 3, 4;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -251,27 +243,30 @@ bool
 listAllDbs(bool desc)
 {
 	PGresult   *res;
-	char		buf[1024];
+	PQExpBufferData buf;
 	printQueryOpt myopt = pset.popt;
 
-	snprintf(buf, sizeof(buf),
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
 			 "SELECT d.datname as \"%s\",\n"
 			 "       u.usename as \"%s\"",
 			 _("Name"), _("Owner"));
 #ifdef MULTIBYTE
-	snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+	appendPQExpBuffer(&buf,
 			 ",\n       pg_encoding_to_char(d.encoding) as \"%s\"",
 			 _("Encoding"));
 #endif
 	if (desc)
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+		appendPQExpBuffer(&buf,
 			 ",\n       obj_description(d.oid, 'pg_database') as \"%s\"",
 				 _("Description"));
-	strcat(buf,
+	appendPQExpBuffer(&buf,
 	"\nFROM pg_database d LEFT JOIN pg_user u ON d.datdba = u.usesysid\n"
 		   "ORDER BY 1;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -292,12 +287,14 @@ listAllDbs(bool desc)
 bool
 permissionsList(const char *name)
 {
-	char		buf[256 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
+	initPQExpBuffer(&buf);
+
 	/* Currently, we ignore indexes since they have no meaningful rights */
-	snprintf(buf, sizeof(buf),
+	printfPQExpBuffer(&buf,
 			 "SELECT relname as \"%s\",\n"
 			 "       relacl as \"%s\"\n"
 			 "FROM   pg_class\n"
@@ -305,23 +302,23 @@ permissionsList(const char *name)
 			 "       relname NOT LIKE 'pg$_%%' ESCAPE '$'\n",
 			 _("Table"), _("Access privileges"));
 	if (name)
-	{
-		strcat(buf, "  AND relname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-	strcat(buf, "ORDER BY 1;");
+		appendPQExpBuffer(&buf, "  AND relname ~ '^%s'\n", name);
+	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
 	if (!res)
+	{
+		termPQExpBuffer(&buf);
 		return false;
+	}
 
 	myopt.nullPrint = NULL;
-	sprintf(buf, _("Access privileges for database \"%s\""), PQdb(pset.db));
-	myopt.title = buf;
+	printfPQExpBuffer(&buf, _("Access privileges for database \"%s\""), PQdb(pset.db));
+	myopt.title = buf.data;
 
 	printQuery(res, &myopt, pset.queryFout);
 
+	termPQExpBuffer(&buf);
 	PQclear(res);
 	return true;
 }
@@ -339,11 +336,13 @@ permissionsList(const char *name)
 bool
 objectDescription(const char *object)
 {
-	char		descbuf[2048 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	snprintf(descbuf, sizeof(descbuf),
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
 			 "SELECT DISTINCT tt.name AS \"%s\", tt.object AS \"%s\", d.description AS \"%s\"\n"
 			 "FROM (\n"
 
@@ -407,15 +406,11 @@ objectDescription(const char *object)
 		);
 
 	if (object)
-	{
-		strcat(descbuf, "  AND tt.name ~ '^");
-		strncat(descbuf, object, REGEXP_CUTOFF);
-		strcat(descbuf, "'\n");
-	}
-	strcat(descbuf, "ORDER BY 1;");
-
+		appendPQExpBuffer(&buf, "  AND tt.name ~ '^%s'\n", object);
+	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
-	res = PSQLexec(descbuf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -457,17 +452,17 @@ xmalloc(size_t size)
 bool
 describeTableDetails(const char *name, bool desc)
 {
-	char		buf[512 + INDEX_MAX_KEYS * NAMEDATALEN];
+	PQExpBufferData buf;
 	PGresult   *res = NULL;
 	printTableOpt myopt = pset.popt.topt;
 	int			i;
 	const char *view_def = NULL;
 	const char *headers[5];
 	char	  **cells = NULL;
-	char	   *title = NULL;
 	char	  **footers = NULL;
 	char	  **ptr;
-	unsigned int cols;
+	PQExpBufferData title;
+	unsigned int cols = 0;
 	struct
 	{
 		bool		hasindex;
@@ -476,26 +471,21 @@ describeTableDetails(const char *name, bool desc)
 		int16		triggers;
 		bool		hasrules;
 	}			tableinfo;
-	bool		error = false;
+	bool		retval;
 
-	/* truncate table name */
-	if (strlen(name) > NAMEDATALEN)
-	{
-		char	   *my_name = xmalloc(NAMEDATALEN + 1);
+	retval = false;
 
-		strncpy(my_name, name, NAMEDATALEN);
-		my_name[NAMEDATALEN] = '\0';
-		name = my_name;
-	}
+	initPQExpBuffer(&buf);
+	initPQExpBuffer(&title);
 
 	/* Get general table info */
-	sprintf(buf,
-	 "SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
-			"FROM pg_class WHERE relname='%s'",
-			name);
-	res = PSQLexec(buf);
+	printfPQExpBuffer(&buf,
+					  "SELECT relhasindex, relkind, relchecks, reltriggers, relhasrules\n"
+					  "FROM pg_class WHERE relname='%s'",
+					  name);
+	res = PSQLexec(buf.data);
 	if (!res)
-		return false;
+		goto error_return;
 
 	/* Did we get anything? */
 	if (PQntuples(res) == 0)
@@ -503,7 +493,8 @@ describeTableDetails(const char *name, bool desc)
 		if (!QUIET())
 			fprintf(stderr, _("Did not find any relation named \"%s\".\n"), name);
 		PQclear(res);
-		return false;
+		res = NULL;
+		goto error_return;
 	}
 
 	/* FIXME: check for null pointers here? */
@@ -536,38 +527,36 @@ describeTableDetails(const char *name, bool desc)
 
 	/* Get column info (index requires additional checks) */
 	if (tableinfo.relkind == 'i')
-		strcpy(buf, "SELECT\n  CASE i.indproc WHEN ('-'::regproc) THEN a.attname\n  ELSE SUBSTR(pg_get_indexdef(attrelid),\n  POSITION('(' in pg_get_indexdef(attrelid)))\n  END, ");
+		printfPQExpBuffer(&buf, "SELECT\n  CASE i.indproc WHEN ('-'::regproc) THEN a.attname\n  ELSE SUBSTR(pg_get_indexdef(attrelid),\n  POSITION('(' in pg_get_indexdef(attrelid)))\n  END, ");
 	else
-		strcpy(buf, "SELECT a.attname, ");
-	strcat(buf, "format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
+		printfPQExpBuffer(&buf, "SELECT a.attname, ");
+	appendPQExpBuffer(&buf, "format_type(a.atttypid, a.atttypmod), a.attnotnull, a.atthasdef, a.attnum");
 	if (desc)
-		strcat(buf, ", col_description(a.attrelid, a.attnum)");
-	strcat(buf, "\nFROM pg_class c, pg_attribute a");
+		appendPQExpBuffer(&buf, ", col_description(a.attrelid, a.attnum)");
+	appendPQExpBuffer(&buf, "\nFROM pg_class c, pg_attribute a");
 	if (tableinfo.relkind == 'i')
-		strcat(buf, ", pg_index i");
-	strcat(buf, "\nWHERE c.relname = '");
-	strncat(buf, name, NAMEDATALEN);
-	strcat(buf, "'\n  AND a.attnum > 0 AND a.attrelid = c.oid");
+		appendPQExpBuffer(&buf, ", pg_index i");
+	appendPQExpBuffer(&buf, "\nWHERE c.relname = '%s'\n  AND a.attnum > 0 AND a.attrelid = c.oid", name);
 	if (tableinfo.relkind == 'i')
-		strcat(buf, " AND a.attrelid = i.indexrelid");
-	strcat(buf, "\nORDER BY a.attnum");
+		appendPQExpBuffer(&buf, " AND a.attrelid = i.indexrelid");
+	appendPQExpBuffer(&buf, "\nORDER BY a.attnum");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
 	if (!res)
-		return false;
+		goto error_return;
 
 	/* Check if table is a view */
 	if (tableinfo.hasrules)
 	{
 		PGresult   *result;
 
-		sprintf(buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
-		result = PSQLexec(buf);
+		printfPQExpBuffer(&buf, "SELECT definition FROM pg_views WHERE viewname = '%s'", name);
+		result = PSQLexec(buf.data);
 		if (!result)
 		{
 			PQclear(res);
 			PQclear(result);
-			return false;
+			goto error_return;
 		}
 
 		if (PQntuples(result) > 0)
@@ -603,56 +592,50 @@ describeTableDetails(const char *name, bool desc)
 			{
 				PGresult   *result;
 
-				sprintf(buf, "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
-						"WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
-						name, PQgetvalue(res, i, 4));
-
-				result = PSQLexec(buf);
-				if (!result)
-					error = true;
-				else
-				{
-					if (cells[i * cols + 2][0])
-						strcat(cells[i * cols + 2], " ");
-					strcat(cells[i * cols + 2], "default ");
-					strcat(cells[i * cols + 2], PQgetvalue(result, 0, 0));
-					PQclear(result);
-				}
+				printfPQExpBuffer(&buf,
+								  "SELECT substring(d.adsrc for 128) FROM pg_attrdef d, pg_class c\n"
+								  "WHERE c.relname = '%s' AND c.oid = d.adrelid AND d.adnum = %s",
+								  name, PQgetvalue(res, i, 4));
+
+				result = PSQLexec(buf.data);
+
+				if (cells[i * cols + 2][0])
+					strcat(cells[i * cols + 2], " ");
+				strcat(cells[i * cols + 2], "default ");
+				strcat(cells[i * cols + 2], result ? PQgetvalue(result, 0, 0) : "?");
+
+				PQclear(result);
 			}
 		}
 
-		if (error)
-			break;
-
 		/* Description */
 		if (desc)
 			cells[i * cols + cols - 1] = PQgetvalue(res, i, 5);
 	}
 
 	/* Make title */
-	title = xmalloc(32 + NAMEDATALEN);
 	switch (tableinfo.relkind)
 	{
 		case 'r':
-			snprintf(title, 32 + NAMEDATALEN, _("Table \"%s\""), name);
+			printfPQExpBuffer(&title, _("Table \"%s\""), name);
 			break;
 		case 'v':
-			snprintf(title, 32 + NAMEDATALEN, _("View \"%s\""), name);
+			printfPQExpBuffer(&title, _("View \"%s\""), name);
 			break;
 		case 'S':
-			snprintf(title, 32 + NAMEDATALEN, _("Sequence \"%s\""), name);
+			printfPQExpBuffer(&title, _("Sequence \"%s\""), name);
 			break;
 		case 'i':
-			snprintf(title, 32 + NAMEDATALEN, _("Index \"%s\""), name);
+			printfPQExpBuffer(&title, _("Index \"%s\""), name);
 			break;
 		case 's':
-			snprintf(title, 32 + NAMEDATALEN, _("Special relation \"%s\""), name);
+			printfPQExpBuffer(&title, _("Special relation \"%s\""), name);
 			break;
 		case 't':
-			snprintf(title, 32 + NAMEDATALEN, _("TOAST table \"%s\""), name);
+			printfPQExpBuffer(&title, _("TOAST table \"%s\""), name);
 			break;
 		default:
-			snprintf(title, 32 + NAMEDATALEN, _("?%c? \"%s\""), tableinfo.relkind, name);
+			printfPQExpBuffer(&title, _("?%c? \"%s\""), tableinfo.relkind, name);
 			break;
 	}
 
@@ -661,16 +644,22 @@ describeTableDetails(const char *name, bool desc)
 	{
 		/* Footer information about an index */
 		PGresult   *result;
-		sprintf(buf, "SELECT i.indisunique, i.indisprimary, a.amname, c2.relname,\n"
-				"pg_get_expr(i.indpred,i.indrelid)\n"
-				"FROM pg_index i, pg_class c, pg_class c2, pg_am a\n"
-				"WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid\n"
-				"AND i.indrelid = c2.oid",
-				name);
-
-		result = PSQLexec(buf);
-		if (!result || PQntuples(result) != 1)
-			error = true;
+		printfPQExpBuffer(&buf,
+						  "SELECT i.indisunique, i.indisprimary, a.amname, c2.relname,\n"
+						  "pg_get_expr(i.indpred,i.indrelid)\n"
+						  "FROM pg_index i, pg_class c, pg_class c2, pg_am a\n"
+						  "WHERE i.indexrelid = c.oid AND c.relname = '%s' AND c.relam = a.oid\n"
+						  "AND i.indrelid = c2.oid",
+						  name);
+
+		result = PSQLexec(buf.data);
+		if (!result)
+			goto error_return;
+		else if (PQntuples(result) != 1)
+		{
+			PQclear(result);
+			goto error_return;
+		}
 		else
 		{
 			char	   *indisunique = PQgetvalue(result, 0, 0);
@@ -699,17 +688,17 @@ describeTableDetails(const char *name, bool desc)
 		int			count_footers = 0;
 
 		/* count rules */
-		if (!error && tableinfo.hasrules)
+		if (tableinfo.hasrules)
 		{
-			sprintf(buf,
+			printfPQExpBuffer(&buf,
 					"SELECT r.rulename\n"
 					"FROM pg_rewrite r, pg_class c\n"
 					"WHERE c.relname = '%s' AND c.oid = r.ev_class\n"
 					"AND r.rulename != '_RETURN'",
 					name);
-			result = PSQLexec(buf);
+			result = PSQLexec(buf.data);
 			if (!result)
-				error = true;
+				goto error_return;
 			else
 				rule_count = PQntuples(result);
 		}
@@ -727,13 +716,13 @@ describeTableDetails(const char *name, bool desc)
 			char	   *s = _("Rules");
 
 			if (i == 0)
-				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result, i, 0));
+				printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result, i, 0));
 			else
-				snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result, i, 0));
+				printfPQExpBuffer(&buf, "%*s  %s", (int) strlen(s), "", PQgetvalue(result, i, 0));
 			if (i < rule_count - 1)
-				strcat(buf, ",");
+				appendPQExpBuffer(&buf, ",");
 
-			footers[count_footers++] = xstrdup(buf);
+			footers[count_footers++] = xstrdup(buf.data);
 		}
 		PQclear(result);
 
@@ -754,62 +743,64 @@ describeTableDetails(const char *name, bool desc)
 		int			count_footers = 0;
 
 		/* count indexes */
-		if (!error && tableinfo.hasindex)
+		if (tableinfo.hasindex)
 		{
-			sprintf(buf, "SELECT c2.relname, i.indisprimary, i.indisunique,\n"
+			printfPQExpBuffer(&buf,
+					"SELECT c2.relname, i.indisprimary, i.indisunique,\n"
 					"SUBSTR(pg_get_indexdef(i.indexrelid),\n"
 					"POSITION('USING ' IN pg_get_indexdef(i.indexrelid))+5)\n"
 					"FROM pg_class c, pg_class c2, pg_index i\n"
 					"WHERE c.relname = '%s' AND c.oid = i.indrelid AND i.indexrelid = c2.oid\n"
 					"ORDER BY i.indisprimary DESC, i.indisunique DESC, c2.relname",
 					name);
-			result1 = PSQLexec(buf);
+			result1 = PSQLexec(buf.data);
 			if (!result1)
-				error = true;
+				goto error_return;
 			else
 				index_count = PQntuples(result1);
 		}
 
 		/* count table (and column) constraints */
-		if (!error && tableinfo.checks)
+		if (tableinfo.checks)
 		{
-			sprintf(buf, "SELECT rcsrc, rcname\n"
+			printfPQExpBuffer(&buf,
+					"SELECT rcsrc, rcname\n"
 					"FROM pg_relcheck r, pg_class c\n"
 					"WHERE c.relname='%s' AND c.oid = r.rcrelid",
 					name);
-			result2 = PSQLexec(buf);
+			result2 = PSQLexec(buf.data);
 			if (!result2)
-				error = true;
+				goto error_return;
 			else
 				constr_count = PQntuples(result2);
 		}
 
 		/* count rules */
-		if (!error && tableinfo.hasrules)
+		if (tableinfo.hasrules)
 		{
-			sprintf(buf,
+			printfPQExpBuffer(&buf,
 					"SELECT r.rulename\n"
 					"FROM pg_rewrite r, pg_class c\n"
 					"WHERE c.relname='%s' AND c.oid = r.ev_class",
 					name);
-			result3 = PSQLexec(buf);
+			result3 = PSQLexec(buf.data);
 			if (!result3)
-				error = true;
+				goto error_return;
 			else
 				rule_count = PQntuples(result3);
 		}
 
 		/* count triggers */
-		if (!error && tableinfo.triggers)
+		if (tableinfo.triggers)
 		{
-			sprintf(buf,
+			printfPQExpBuffer(&buf,
 					"SELECT t.tgname\n"
 					"FROM pg_trigger t, pg_class c\n"
 					"WHERE c.relname='%s' AND c.oid = t.tgrelid",
 					name);
-			result4 = PSQLexec(buf);
+			result4 = PSQLexec(buf.data);
 			if (!result4)
-				error = true;
+				goto error_return;
 			else
 				trigger_count = PQntuples(result4);
 		}
@@ -823,21 +814,25 @@ describeTableDetails(const char *name, bool desc)
 			char	   *s = _("Indexes");
 	
 			if (i == 0)
-				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result1, i, 0));
+				printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result1, i, 0));
 			else
-				snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result1, i, 0));
+				printfPQExpBuffer(&buf, "%*s  %s", (int) strlen(s), "", PQgetvalue(result1, i, 0));
 
 			/* Label as primary key or unique (but not both) */
-			strcat(buf, strcmp(PQgetvalue(result1,i,1),"t") == 0 ? 
-				   _(" primary key") : strcmp(PQgetvalue(result1,i,2),"t") == 0 ? _(" unique") : "");
+			appendPQExpBuffer(&buf,
+							  strcmp(PQgetvalue(result1,i,1),"t") == 0
+							  ? _(" primary key") :
+							  (strcmp(PQgetvalue(result1,i,2),"t") == 0
+							   ? _(" unique")
+							   : ""));
 
 			/* Everything after "USING" is echoed verbatim */
-			strcat(buf, PQgetvalue(result1,i,3));
+			appendPQExpBuffer(&buf, "%s", PQgetvalue(result1,i,3));
 
 			if (i < index_count - 1)
-				strcat(buf, ",");
+				appendPQExpBuffer(&buf, ",");
 
-			footers[count_footers++] = xstrdup(buf);
+			footers[count_footers++] = xstrdup(buf.data);
 		}
 
 
@@ -847,12 +842,16 @@ describeTableDetails(const char *name, bool desc)
 			char	   *s = _("Check constraints");
 
 			if (i == 0)
-				snprintf(buf, sizeof(buf), _("%s: \"%s\" %s"), s,
-				   PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
+				printfPQExpBuffer(&buf, _("%s: \"%s\" %s"),
+								  s,
+								  PQgetvalue(result2, i, 1),
+								  PQgetvalue(result2, i, 0));
 			else
-				snprintf(buf, sizeof(buf), _("%*s  \"%s\" %s"), (int) strlen(s), "",
-				   PQgetvalue(result2, i, 1), PQgetvalue(result2, i, 0));
-			footers[count_footers++] = xstrdup(buf);
+				printfPQExpBuffer(&buf, _("%*s  \"%s\" %s"),
+								  (int) strlen(s), "",
+								  PQgetvalue(result2, i, 1),
+								  PQgetvalue(result2, i, 0));
+			footers[count_footers++] = xstrdup(buf.data);
 		}
 
 		/* print rules */
@@ -861,13 +860,13 @@ describeTableDetails(const char *name, bool desc)
 			char	   *s = _("Rules");
 
 			if (i == 0)
-				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result3, i, 0));
+				printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result3, i, 0));
 			else
-				snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result3, i, 0));
+				printfPQExpBuffer(&buf, "%*s  %s", (int) strlen(s), "", PQgetvalue(result3, i, 0));
 			if (i < rule_count - 1)
-				strcat(buf, ",");
+				appendPQExpBuffer(&buf, ",");
 
-			footers[count_footers++] = xstrdup(buf);
+			footers[count_footers++] = xstrdup(buf.data);
 		}
 
 		/* print triggers */
@@ -876,13 +875,13 @@ describeTableDetails(const char *name, bool desc)
 			char	   *s = _("Triggers");
 
 			if (i == 0)
-				snprintf(buf, sizeof(buf), "%s: %s", s, PQgetvalue(result4, i, 0));
+				printfPQExpBuffer(&buf, "%s: %s", s, PQgetvalue(result4, i, 0));
 			else
-				snprintf(buf, sizeof(buf), "%*s  %s", (int) strlen(s), "", PQgetvalue(result4, i, 0));
+				printfPQExpBuffer(&buf, "%*s  %s", (int) strlen(s), "", PQgetvalue(result4, i, 0));
 			if (i < trigger_count - 1)
-				strcat(buf, ",");
+				appendPQExpBuffer(&buf, ",");
 
-			footers[count_footers++] = xstrdup(buf);
+			footers[count_footers++] = xstrdup(buf.data);
 		}
 
 		/* end of list marker */
@@ -894,28 +893,37 @@ describeTableDetails(const char *name, bool desc)
 		PQclear(result4);
 	}
 
-	if (!error)
-		printTable(title, headers,
-				   (const char **) cells, (const char **) footers,
-				   "llll", &myopt, pset.queryFout);
+	printTable(title.data, headers,
+			   (const char **) cells, (const char **) footers,
+			   "llll", &myopt, pset.queryFout);
+
+	retval = true;
+
+error_return:
 
 	/* clean up */
-	free(title);
+	termPQExpBuffer(&buf);
+	termPQExpBuffer(&title);
 
-	for (i = 0; i < PQntuples(res); i++)
+	if (cells)
 	{
-		if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
-			free(cells[i * cols + 2]);
+		for (i = 0; i < PQntuples(res); i++)
+			if (tableinfo.relkind == 'r' || tableinfo.relkind == 'v')
+				free(cells[i * cols + 2]);
+		free(cells);
 	}
-	free(cells);
 
-	for (ptr = footers; footers && *ptr; ptr++)
-		free(*ptr);
-	free(footers);
+	if (footers)
+	{
+		for (ptr = footers; *ptr; ptr++)
+			free(*ptr);
+		free(footers);
+	}
 
-	PQclear(res);
+	if (res)
+		PQclear(res);
 
-	return !error;
+	return retval;
 }
 
 
@@ -925,18 +933,19 @@ describeTableDetails(const char *name, bool desc)
  * Describes users, possibly based on a simplistic prefix search on the
  * argument.
  */
-
 bool
 describeUsers(const char *name)
 {
-	char		buf[384 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	snprintf(buf, sizeof(buf),
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
 			 "SELECT u.usename AS \"%s\",\n"
 			 "  u.usesysid AS \"%s\",\n"
-	 "  CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text)\n"
+			 "  CASE WHEN u.usesuper AND u.usecreatedb THEN CAST('%s' AS text)\n"
 			 "       WHEN u.usesuper THEN CAST('%s' AS text)\n"
 			 "       WHEN u.usecreatedb THEN CAST('%s' AS text)\n"
 			 "       ELSE CAST('' AS text)\n"
@@ -947,14 +956,11 @@ describeUsers(const char *name)
 			 _("superuser"), _("create database"),
 			 _("Attributes"));
 	if (name)
-	{
-		strcat(buf, "WHERE u.usename ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-	strcat(buf, "ORDER BY 1;");
+		appendPQExpBuffer(&buf, "WHERE u.usename ~ '^%s'\n", name);
+	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -994,17 +1000,16 @@ listTables(const char *infotype, const char *name, bool desc)
 	bool		showSeq = strchr(infotype, 's') != NULL;
 	bool		showSystem = strchr(infotype, 'S') != NULL;
 
-	char		buf[3072 + 8 * REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
 	if (showSystem && !(showSeq || showIndexes || showViews || showTables))
 		showTables = showViews = showSeq = true;
 
+	initPQExpBuffer(&buf);
 
-	buf[0] = '\0';
-
-	snprintf(buf, sizeof(buf),
+	printfPQExpBuffer(&buf,
 			 "SELECT c.relname as \"%s\",\n"
 			 "  CASE c.relkind WHEN 'r' THEN '%s' WHEN 'v' THEN '%s' WHEN 'i' THEN '%s' WHEN 'S' THEN '%s' WHEN 's' THEN '%s' END as \"%s\",\n"
 			 "  u.usename as \"%s\"",
@@ -1012,50 +1017,47 @@ listTables(const char *infotype, const char *name, bool desc)
 			 _("special"), _("Type"), _("Owner"));
 
 	if (desc)
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
+		appendPQExpBuffer(&buf,
 				 ",\n  obj_description(c.oid, 'pg_class') as \"%s\"",
 				 _("Description"));
-    if (showIndexes) {
-		snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf),
-				 ",\n c2.relname as \"%s\"",
-				 _("Table"));
-		strcat(buf, "\nFROM pg_class c, pg_class c2, pg_index i, pg_user u\n"
-			   "WHERE c.relowner = u.usesysid\n"
-			   "AND i.indrelid = c2.oid AND i.indexrelid = c.oid\n");
-	}
-	else {
-		strcat(buf, "\nFROM pg_class c, pg_user u\n"
-			   "WHERE c.relowner = u.usesysid\n");
-	}
-	strcat(buf, "AND c.relkind IN (");
+    if (showIndexes)
+		appendPQExpBuffer(&buf,
+						  ",\n c2.relname as \"%s\""
+						  "\nFROM pg_class c, pg_class c2, pg_index i, pg_user u\n"
+						  "WHERE c.relowner = u.usesysid\n"
+						  "AND i.indrelid = c2.oid AND i.indexrelid = c.oid\n",
+						  _("Table"));
+	else
+		appendPQExpBuffer(&buf,
+						  "\nFROM pg_class c, pg_user u\n"
+						  "WHERE c.relowner = u.usesysid\n");
+
+	appendPQExpBuffer(&buf, "AND c.relkind IN (");
 	if (showTables)
-		strcat(buf, "'r',");
+		appendPQExpBuffer(&buf, "'r',");
 	if (showViews)
-		strcat(buf, "'v',");
+		appendPQExpBuffer(&buf, "'v',");
 	if (showIndexes)
-		strcat(buf, "'i',");
+		appendPQExpBuffer(&buf, "'i',");
 	if (showSeq)
-		strcat(buf, "'S',");
+		appendPQExpBuffer(&buf, "'S',");
 	if (showSystem && showTables)
-		strcat(buf, "'s',");
-	strcat(buf, "''");			/* dummy */
-	strcat(buf, ")\n");
+		appendPQExpBuffer(&buf, "'s',");
+	appendPQExpBuffer(&buf, "''");			/* dummy */
+	appendPQExpBuffer(&buf, ")\n");
 
 	if (showSystem)
-		strcat(buf, "  AND c.relname ~ '^pg_'\n");
+		appendPQExpBuffer(&buf, "  AND c.relname ~ '^pg_'\n");
 	else
-		strcat(buf, "  AND c.relname !~ '^pg_'\n");
+		appendPQExpBuffer(&buf, "  AND c.relname !~ '^pg_'\n");
 
 	if (name)
-	{
-		strcat(buf, "  AND c.relname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
+		appendPQExpBuffer(&buf, "  AND c.relname ~ '^%s'\n", name);
 
-	strcat(buf, "ORDER BY 1;");
+	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
@@ -1078,23 +1080,25 @@ listTables(const char *infotype, const char *name, bool desc)
 	return true;
 }
 
+
 /*
  * \dD [domain]
  *
  * Describes domains, possibly based on a simplistic prefix search on the
  * argument.
  */
-
 bool
 listDomains(const char *name)
 {
-	char		buf[512 + REGEXP_CUTOFF];
+	PQExpBufferData buf;
 	PGresult   *res;
 	printQueryOpt myopt = pset.popt;
 
-	snprintf(buf, sizeof(buf),
+	initPQExpBuffer(&buf);
+
+	printfPQExpBuffer(&buf,
 		 "SELECT t.typname as \"%s\",\n"
-		 "       format_type( t.typbasetype, t.typtypmod) as \"%s\",\n"
+		 "       format_type(t.typbasetype, t.typtypmod) as \"%s\",\n"
 		 "       CASE WHEN t.typnotnull AND t.typdefault IS NOT NULL THEN 'not null default '||t.typdefault\n"
 		 "            WHEN t.typnotnull AND t.typdefault IS NULL THEN 'not null'\n"
 		 "            WHEN NOT t.typnotnull AND t.typdefault IS NOT NULL THEN 'default '||t.typdefault\n"
@@ -1106,19 +1110,16 @@ listDomains(const char *name)
 		 _("Type"),
 		 _("Modifier"));
 	if (name)
-	{
-		strcat(buf, "AND t.typname ~ '^");
-		strncat(buf, name, REGEXP_CUTOFF);
-		strcat(buf, "'\n");
-	}
-	strcat(buf, "ORDER BY 1;");
+		appendPQExpBuffer(&buf, "AND t.typname ~ '^%s'\n", name);
+	appendPQExpBuffer(&buf, "ORDER BY 1;");
 
-	res = PSQLexec(buf);
+	res = PSQLexec(buf.data);
+	termPQExpBuffer(&buf);
 	if (!res)
 		return false;
 
 	myopt.nullPrint = NULL;
-	myopt.title = _("List of database domains");
+	myopt.title = _("List of domains");
 
 	printQuery(res, &myopt, pset.queryFout);
 
-- 
GitLab