From 44611f6e6d2cd11ac2c6dc1f41c13a98ec633f08 Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Fri, 5 Mar 2004 01:53:59 +0000
Subject: [PATCH] libpq's query to get the OIDs of large-object support
 functions was not schema-safe.  Make it so, and improve the internal support
 for knowledge of server version.

---
 src/interfaces/libpq/fe-exec.c      | 24 ++++++++++++++---
 src/interfaces/libpq/fe-lobj.c      | 40 +++++++++++++++++++++--------
 src/interfaces/libpq/fe-protocol2.c | 11 +++++---
 src/interfaces/libpq/libpq-int.h    |  4 +--
 4 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c
index eae1b764abb..d2ad75bb23b 100644
--- a/src/interfaces/libpq/fe-exec.c
+++ b/src/interfaces/libpq/fe-exec.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.156 2003/12/28 17:29:41 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-exec.c,v 1.157 2004/03/05 01:53:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -609,12 +609,28 @@ pqSaveParameterStatus(PGconn *conn, const char *name, const char *value)
 
 	/*
 	 * Special hacks: remember client_encoding as a numeric value, and
-	 * remember at least the first few bytes of server version.
+	 * convert server version to a numeric form as well.
 	 */
 	if (strcmp(name, "client_encoding") == 0)
 		conn->client_encoding = pg_char_to_encoding(value);
-	if (strcmp(name, "server_version") == 0)
-		StrNCpy(conn->sversion, value, sizeof(conn->sversion));
+	else if (strcmp(name, "server_version") == 0)
+	{
+		int			cnt;
+		int			vmaj,
+					vmin,
+					vrev;
+
+		cnt = sscanf(value, "%d.%d.%d", &vmaj, &vmin, &vrev);
+
+		if (cnt < 2)
+			conn->sversion = 0;			/* unknown */
+		else
+		{
+			if (cnt == 2)
+				vrev = 0;
+			conn->sversion = (100 * vmaj + vmin) * 100 + vrev;
+		}
+	}
 }
 
 
diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c
index 16d4970d9eb..e9ef61358ac 100644
--- a/src/interfaces/libpq/fe-lobj.c
+++ b/src/interfaces/libpq/fe-lobj.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.47 2004/01/26 22:35:32 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-lobj.c,v 1.48 2004/03/05 01:53:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -534,6 +534,7 @@ lo_initialize(PGconn *conn)
 	PGresult   *res;
 	PGlobjfuncs *lobjfuncs;
 	int			n;
+	const char *query;
 	const char *fname;
 	Oid			foid;
 
@@ -550,17 +551,34 @@ lo_initialize(PGconn *conn)
 	MemSet((char *) lobjfuncs, 0, sizeof(PGlobjfuncs));
 
 	/*
-	 * Execute the query to get all the functions at once
+	 * Execute the query to get all the functions at once.  In 7.3 and later
+	 * we need to be schema-safe.
 	 */
-	res = PQexec(conn, "select proname, oid from pg_proc	\
-			where proname = 'lo_open'	\
-		   or proname = 'lo_close'	\
-		   or proname = 'lo_creat'	\
-		   or proname = 'lo_unlink'	\
-		   or proname = 'lo_lseek'	\
-		   or proname = 'lo_tell'	\
-		   or proname = 'loread'	\
-		   or proname = 'lowrite'");
+	if (conn->sversion >= 70300)
+		query = "select proname, oid from pg_catalog.pg_proc "
+			"where proname in ("
+			"'lo_open', "
+			"'lo_close', "
+			"'lo_creat', "
+			"'lo_unlink', "
+			"'lo_lseek', "
+			"'lo_tell', "
+			"'loread', "
+			"'lowrite') "
+			"and pronamespace = (select oid from pg_catalog.pg_namespace "
+			"where nspname = 'pg_catalog')";
+	else
+		query = "select proname, oid from pg_proc "
+			"where proname = 'lo_open' "
+			"or proname = 'lo_close' "
+			"or proname = 'lo_creat' "
+			"or proname = 'lo_unlink' "
+			"or proname = 'lo_lseek' "
+			"or proname = 'lo_tell' "
+			"or proname = 'loread' "
+			"or proname = 'lowrite'";
+
+	res = PQexec(conn, query);
 	if (res == NULL)
 	{
 		free(lobjfuncs);
diff --git a/src/interfaces/libpq/fe-protocol2.c b/src/interfaces/libpq/fe-protocol2.c
index 8c214fa8e92..369481b3386 100644
--- a/src/interfaces/libpq/fe-protocol2.c
+++ b/src/interfaces/libpq/fe-protocol2.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol2.c,v 1.9 2003/11/29 19:52:12 pgsql Exp $
+ *	  $PostgreSQL: pgsql/src/interfaces/libpq/fe-protocol2.c,v 1.10 2004/03/05 01:53:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -178,7 +178,9 @@ pqSetenvPoll(PGconn *conn)
 					 * default in a 7.3 server.
 					 *
 					 * Note: version() exists in all
-					 * protocol-2.0-supporting backends.
+					 * protocol-2.0-supporting backends.  In 7.3 it would
+					 * be safer to write pg_catalog.version(), but we can't
+					 * do that without causing problems on older versions.
 					 */
 					if (!PQsendQuery(conn, "begin; select version(); end"))
 						goto error_return;
@@ -258,8 +260,9 @@ pqSetenvPoll(PGconn *conn)
 					 * in 7.3 servers where we need to prevent
 					 * autocommit-off from starting a transaction anyway.
 					 */
-					if (strncmp(conn->sversion, "7.3", 3) == 0)
-						query = "begin; select pg_client_encoding(); end";
+					if (conn->sversion >= 70300 &&
+						conn->sversion < 70400)
+						query = "begin; select pg_catalog.pg_client_encoding(); end";
 					else
 						query = "select pg_client_encoding()";
 					if (!PQsendQuery(conn, query))
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 97cd55eaa8a..f2acf2af20a 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.84 2004/01/09 02:02:43 momjian Exp $
+ * $PostgreSQL: pgsql/src/interfaces/libpq/libpq-int.h,v 1.85 2004/03/05 01:53:59 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -280,7 +280,7 @@ struct pg_conn
 	SockAddr	laddr;			/* Local address */
 	SockAddr	raddr;			/* Remote address */
 	ProtocolVersion pversion;	/* FE/BE protocol version in use */
-	char		sversion[8];	/* The first few bytes of server version */
+	int			sversion;		/* server version, e.g. 70401 for 7.4.1 */
 
 	/* Transient state needed while establishing connection */
 	struct addrinfo *addrlist;	/* list of possible backend addresses */
-- 
GitLab