From 40cad8b66f468d627781704781f6f1877548e73a Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 25 Apr 1999 19:27:47 +0000
Subject: [PATCH] My first cut at libpq revision didn't handle MULTIBYTE
 correctly, but I think it's OK now...

---
 src/backend/access/common/printtup.c | 27 ++-------
 src/backend/commands/async.c         |  4 +-
 src/backend/libpq/pqformat.c         | 88 +++++++++++++---------------
 src/backend/tcop/dest.c              |  5 +-
 src/include/libpq/pqformat.h         |  7 +--
 5 files changed, 53 insertions(+), 78 deletions(-)

diff --git a/src/backend/access/common/printtup.c b/src/backend/access/common/printtup.c
index 5ce4830ebd4..0d2aeeecd1c 100644
--- a/src/backend/access/common/printtup.c
+++ b/src/backend/access/common/printtup.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.43 1999/04/25 03:19:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.44 1999/04/25 19:27:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,10 +25,6 @@
 #include "libpq/pqformat.h"
 #include "utils/syscache.h"
 
-#ifdef MULTIBYTE
-#include "mb/pg_wchar.h"
-#endif
-
 static void printtup_setup(DestReceiver* self, TupleDesc typeinfo);
 static void printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self);
 static void printtup_cleanup(DestReceiver* self);
@@ -157,14 +153,10 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
 	StringInfoData buf;
 	int			i,
 				j,
-				k,
-				outputlen;
+				k;
 	char	   *outputstr;
 	Datum		attr;
 	bool		isnull;
-#ifdef MULTIBYTE
-	unsigned char *p;
-#endif
 
 	/* Set or update my derived attribute info, if needed */
 	if (myState->attrinfo != typeinfo ||
@@ -213,24 +205,13 @@ printtup(HeapTuple tuple, TupleDesc typeinfo, DestReceiver* self)
 		{
 			outputstr = (char *) (*fmgr_faddr(&thisState->finfo))
 				(attr, thisState->typelem, typeinfo->attrs[i]->atttypmod);
-#ifdef MULTIBYTE
-			p = pg_server_to_client(outputstr, strlen(outputstr));
-			outputlen = strlen(p);
-			pq_sendint(&buf, outputlen + VARHDRSZ, VARHDRSZ);
-			pq_sendbytes(&buf, p, outputlen);
-#else
-			outputlen = strlen(outputstr);
-			pq_sendint(&buf, outputlen + VARHDRSZ, VARHDRSZ);
-			pq_sendbytes(&buf, outputstr, outputlen);
-#endif
+			pq_sendcountedtext(&buf, outputstr, strlen(outputstr));
 			pfree(outputstr);
 		}
 		else
 		{
 			outputstr = "<unprintable>";
-			outputlen = strlen(outputstr);
-			pq_sendint(&buf, outputlen + VARHDRSZ, VARHDRSZ);
-			pq_sendbytes(&buf, outputstr, outputlen);
+			pq_sendcountedtext(&buf, outputstr, strlen(outputstr));
 		}
 	}
 
diff --git a/src/backend/commands/async.c b/src/backend/commands/async.c
index 3d5cf92f7d1..fb1c116bc47 100644
--- a/src/backend/commands/async.c
+++ b/src/backend/commands/async.c
@@ -6,7 +6,7 @@
  * Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.45 1999/04/25 03:19:08 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/async.c,v 1.46 1999/04/25 19:27:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -803,7 +803,7 @@ NotifyMyFrontEnd(char *relname, int32 listenerPID)
 		pq_beginmessage(&buf);
 		pq_sendbyte(&buf, 'A');
 		pq_sendint(&buf, listenerPID, sizeof(int32));
-		pq_sendstring(&buf, relname, strlen(relname));
+		pq_sendstring(&buf, relname);
 		pq_endmessage(&buf);
 		/* NOTE: we do not do pq_flush() here.  For a self-notify, it will
 		 * happen at the end of the transaction, and for incoming notifies
diff --git a/src/backend/libpq/pqformat.c b/src/backend/libpq/pqformat.c
index 06f55d648bc..ad6f045a944 100644
--- a/src/backend/libpq/pqformat.c
+++ b/src/backend/libpq/pqformat.c
@@ -15,7 +15,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- *  $Id: pqformat.c,v 1.1 1999/04/25 03:19:22 tgl Exp $
+ *  $Id: pqformat.c,v 1.2 1999/04/25 19:27:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,7 +26,7 @@
  *		pq_sendbyte		- append a raw byte to a StringInfo buffer
  *		pq_sendint		- append a binary integer to a StringInfo buffer
  *		pq_sendbytes	- append raw data to a StringInfo buffer
- *		pq_sendtext		- append a text string (with MULTIBYTE conversion)
+ *		pq_sendcountedtext - append a text string (with MULTIBYTE conversion)
  *		pq_sendstring	- append a null-terminated text string (with MULTIBYTE)
  *		pq_endmessage	- send the completed message to the frontend
  * Note: it is also possible to append data to the StringInfo buffer using
@@ -36,9 +36,8 @@
  * Message input:
  *		pq_getint		- get an integer from connection
  *		pq_getstr		- get a null terminated string from connection
- *		pq_getnchar		- get n characters from connection, and null-terminate
- * pq_getstr and pq_getnchar perform MULTIBYTE conversion on the collected
- * string.  Use the raw pqcomm.c routines pq_getstring and pq_getbytes
+ * pq_getstr performs MULTIBYTE conversion on the collected string.
+ * Use the raw pqcomm.c routines pq_getstring or pq_getbytes
  * to fetch data without conversion.
  */
 #include "postgres.h"
@@ -48,6 +47,7 @@
 #ifdef MULTIBYTE
 #include "mb/pg_wchar.h"
 #endif
+#include <string.h>
 #ifdef HAVE_ENDIAN_H
 #include <endian.h>
 #endif
@@ -110,36 +110,49 @@ pq_sendbytes(StringInfo buf, const char *data, int datalen)
 }
 
 /* --------------------------------
- *		pq_sendtext		- append a text string (with MULTIBYTE conversion)
+ *		pq_sendcountedtext - append a text string (with MULTIBYTE conversion)
  *
- * NB: passed text string must be null-terminated, even though we expect
- * the caller to hand us the length (this is just because the caller
- * usually knows the length anyway).  In this routine, the data sent to
- * the frontend is NOT null-terminated.
+ * The data sent to the frontend by this routine is a 4-byte count field
+ * (the count includes itself, by convention) followed by the string.
+ * The passed text string need not be null-terminated, and the data sent
+ * to the frontend isn't either.
  * --------------------------------
  */
 void
-pq_sendtext(StringInfo buf, const char *str, int slen)
+pq_sendcountedtext(StringInfo buf, const char *str, int slen)
 {
 #ifdef MULTIBYTE
-	str = (const char *) pg_server_to_client(str, slen);
+	const char *p;
+	p = (const char *) pg_server_to_client((unsigned char *) str, slen);
+	if (p != str)				/* actual conversion has been done? */
+	{
+		str = p;
+		slen = strlen(str);
+	}
 #endif
+	pq_sendint(buf, slen + 4, 4);
 	appendBinaryStringInfo(buf, str, slen);
 }
 
 /* --------------------------------
  *		pq_sendstring	- append a null-terminated text string (with MULTIBYTE)
  *
- * NB: passed text string must be null-terminated, even though we expect
- * the caller to hand us the length (this is just because the caller
- * usually knows the length anyway).
+ * NB: passed text string must be null-terminated, and so is the data
+ * sent to the frontend.
  * --------------------------------
  */
 void
-pq_sendstring(StringInfo buf, const char *str, int slen)
+pq_sendstring(StringInfo buf, const char *str)
 {
+	int slen = strlen(str);
 #ifdef MULTIBYTE
-	str = (const char *) pg_server_to_client(str, slen);
+	const char *p;
+	p = (const char *) pg_server_to_client((unsigned char *) str, slen);
+	if (p != str)				/* actual conversion has been done? */
+	{
+		str = p;
+		slen = strlen(str);
+	}
 #endif
 	appendBinaryStringInfo(buf, str, slen+1);
 }
@@ -258,35 +271,18 @@ pq_getstr(char *s, int maxlen)
 	c = pq_getstring(s, maxlen);
 
 #ifdef MULTIBYTE
-	p = (char*) pg_client_to_server((unsigned char *) s, maxlen);
-	if (s != p)					/* actual conversion has been done? */
-		strcpy(s, p);
-#endif
-
-	return c;
-}
-
-/* --------------------------------
- *		pq_getnchar - get n characters from connection, and null-terminate
- *
- *		returns 0 if OK, EOF if trouble
- * --------------------------------
- */
-int
-pq_getnchar(char *s, int len)
-{
-	int			c;
-#ifdef MULTIBYTE
-	char	   *p;
-#endif
-
-	c = pq_getbytes(s, len);
-	s[len] = '\0';
-
-#ifdef MULTIBYTE
-	p = (char*) pg_client_to_server((unsigned char *) s, len+1);
-	if (s != p)					/* actual conversion has been done? */
-		strcpy(s, p);
+	p = (char*) pg_client_to_server((unsigned char *) s, strlen(s));
+	if (p != s)					/* actual conversion has been done? */
+	{
+		int newlen = strlen(p);
+		if (newlen < maxlen)
+			strcpy(s, p);
+		else
+		{
+			strncpy(s, p, maxlen);
+			s[maxlen-1] = '\0';
+		}
+	}
 #endif
 
 	return c;
diff --git a/src/backend/tcop/dest.c b/src/backend/tcop/dest.c
index d6f29aa8afc..26e04f5f855 100644
--- a/src/backend/tcop/dest.c
+++ b/src/backend/tcop/dest.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.26 1999/04/25 03:19:09 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/dest.c,v 1.27 1999/04/25 19:27:45 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -155,8 +155,7 @@ BeginCommand(char *pname,
 
 				for (i = 0; i < natts; ++i)
 				{
-					pq_sendstring(&buf, attrs[i]->attname.data,
-								  strlen(attrs[i]->attname.data));
+					pq_sendstring(&buf, attrs[i]->attname.data);
 					pq_sendint(&buf, (int) attrs[i]->atttypid,
 							   sizeof(attrs[i]->atttypid));
 					pq_sendint(&buf, attrs[i]->attlen,
diff --git a/src/include/libpq/pqformat.h b/src/include/libpq/pqformat.h
index 2fe48539a2d..6404583a103 100644
--- a/src/include/libpq/pqformat.h
+++ b/src/include/libpq/pqformat.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pqformat.h,v 1.1 1999/04/25 03:19:14 tgl Exp $
+ * $Id: pqformat.h,v 1.2 1999/04/25 19:27:47 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,13 +19,12 @@
 
 extern void	pq_sendbyte(StringInfo buf, int byt);
 extern void	pq_sendbytes(StringInfo buf, const char *data, int datalen);
-extern void	pq_sendtext(StringInfo buf, const char *str, int slen);
-extern void	pq_sendstring(StringInfo buf, const char *str, int slen);
+extern void	pq_sendcountedtext(StringInfo buf, const char *str, int slen);
+extern void	pq_sendstring(StringInfo buf, const char *str);
 extern void	pq_sendint(StringInfo buf, int i, int b);
 extern void	pq_endmessage(StringInfo buf);
 
 extern int	pq_getint(int *result, int b);
 extern int	pq_getstr(char *s, int maxlen);
-extern int	pq_getnchar(char *s, int len);
 
 #endif	 /* PQFORMAT_H */
-- 
GitLab