From 74c1723fc8dca2d70576ef2f0a66f4a7c99c173a Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Wed, 23 Nov 2011 00:03:22 -0500
Subject: [PATCH] Remove user-selectable ANALYZE option for range types.

It's not clear that a per-datatype typanalyze function would be any more
useful than a generic typanalyze for ranges.  What *is* clear is that
letting unprivileged users select typanalyze functions is a crash risk or
worse.  So remove the option from CREATE TYPE AS RANGE, and instead put in
a generic typanalyze function for ranges.  The generic function does
nothing as yet, but hopefully we'll improve that before 9.2 release.
---
 doc/src/sgml/ref/create_type.sgml  |  7 -------
 src/backend/commands/typecmds.c    | 18 +-----------------
 src/backend/utils/adt/rangetypes.c | 17 +++++++++++++++++
 src/bin/pg_dump/pg_dump.c          | 14 +++++---------
 src/include/catalog/catversion.h   |  2 +-
 src/include/catalog/pg_proc.h      |  3 +++
 src/include/catalog/pg_type.h      | 12 ++++++------
 src/include/utils/rangetypes.h     |  3 +++
 8 files changed, 36 insertions(+), 40 deletions(-)

diff --git a/doc/src/sgml/ref/create_type.sgml b/doc/src/sgml/ref/create_type.sgml
index 808990feb77..1bf8cd95460 100644
--- a/doc/src/sgml/ref/create_type.sgml
+++ b/doc/src/sgml/ref/create_type.sgml
@@ -33,7 +33,6 @@ CREATE TYPE <replaceable class="parameter">name</replaceable> AS RANGE (
     [ , COLLATION = <replaceable class="parameter">collation</replaceable> ]
     [ , CANONICAL = <replaceable class="parameter">canonical_function</replaceable> ]
     [ , SUBTYPE_DIFF = <replaceable class="parameter">subtype_diff_function</replaceable> ]
-    [ , ANALYZE = <replaceable class="parameter">analyze_function</replaceable> ]
 )
 
 CREATE TYPE <replaceable class="parameter">name</replaceable> (
@@ -167,12 +166,6 @@ CREATE TYPE <replaceable class="parameter">name</replaceable>
     that is, its result should be positive whenever its first argument is
     greater than its second according to the sort ordering.
    </para>
-
-   <para>
-    The optional <replaceable class="parameter">analyze</replaceable>
-    function performs type-specific statistics collection for columns of the
-    range type.  This is defined the same as for base types; see below.
-   </para>
   </refsect2>
 
   <refsect2>
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 1516a2aba4f..ee75600a12c 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -1225,12 +1225,10 @@ DefineRange(CreateRangeStmt *stmt)
 	List	   *rangeCollationName = NIL;
 	List	   *rangeCanonicalName = NIL;
 	List	   *rangeSubtypeDiffName = NIL;
-	List	   *rangeAnalyzeName = NIL;
 	Oid			rangeSubOpclass;
 	Oid			rangeCollation;
 	regproc		rangeCanonical;
 	regproc		rangeSubtypeDiff;
-	regproc		rangeAnalyze;
 	int16		subtyplen;
 	bool		subtypbyval;
 	char		subtypalign;
@@ -1326,14 +1324,6 @@ DefineRange(CreateRangeStmt *stmt)
 						 errmsg("conflicting or redundant options")));
 			rangeSubtypeDiffName = defGetQualifiedName(defel);
 		}
-		else if (pg_strcasecmp(defel->defname, "analyze") == 0)
-		{
-			if (rangeAnalyzeName != NIL)
-				ereport(ERROR,
-						(errcode(ERRCODE_SYNTAX_ERROR),
-						 errmsg("conflicting or redundant options")));
-			rangeAnalyzeName = defGetQualifiedName(defel);
-		}
 		else
 			ereport(ERROR,
 					(errcode(ERRCODE_SYNTAX_ERROR),
@@ -1386,12 +1376,6 @@ DefineRange(CreateRangeStmt *stmt)
 	else
 		rangeSubtypeDiff = InvalidOid;
 
-	if (rangeAnalyzeName != NIL)
-		rangeAnalyze = findTypeAnalyzeFunction(rangeAnalyzeName,
-											   typoid);
-	else
-		rangeAnalyze = InvalidOid;
-
 	get_typlenbyvalalign(rangeSubtype,
 						 &subtyplen, &subtypbyval, &subtypalign);
 
@@ -1420,7 +1404,7 @@ DefineRange(CreateRangeStmt *stmt)
 				   F_RANGE_SEND,	/* send procedure */
 				   InvalidOid,	/* typmodin procedure - none */
 				   InvalidOid,	/* typmodout procedure - none */
-				   rangeAnalyze,	/* analyze procedure */
+				   F_RANGE_TYPANALYZE,	/* analyze procedure */
 				   InvalidOid,	/* element type ID - none */
 				   false,		/* this is not an array type */
 				   rangeArrayOid,		/* array type we are about to create */
diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c
index 3326cb17c89..4b27d4317fb 100644
--- a/src/backend/utils/adt/rangetypes.c
+++ b/src/backend/utils/adt/rangetypes.c
@@ -1135,6 +1135,23 @@ hash_range(PG_FUNCTION_ARGS)
 	PG_RETURN_INT32(result);
 }
 
+/* ANALYZE support */
+
+/* typanalyze function for range datatypes */
+Datum
+range_typanalyze(PG_FUNCTION_ARGS)
+{
+	/*
+	 * For the moment, just punt and don't analyze range columns.  If we
+	 * get close to release without having a better answer, we could
+	 * consider letting std_typanalyze do what it can ... but those stats
+	 * are probably next door to useless for most activity with range
+	 * columns, so it's not clear it's worth gathering them.
+	 */
+	PG_RETURN_BOOL(false);
+}
+
+
 /*
  *----------------------------------------------------------
  * CANONICAL FUNCTIONS
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index 41114ac4da9..644637c9c6c 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -7482,11 +7482,11 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
 					  "opc.opcdefault, "
 					  "CASE WHEN rngcollation = st.typcollation THEN 0 "
 					  "     ELSE rngcollation END AS collation, "
-					  "rngcanonical, rngsubdiff, t.typanalyze "
-					  "FROM pg_catalog.pg_type t, pg_catalog.pg_type st, "
-					  "     pg_catalog.pg_opclass opc, pg_catalog.pg_range r "
-					  "WHERE t.oid = rngtypid AND st.oid = rngsubtype AND "
-					  "      opc.oid = rngsubopc AND rngtypid = '%u'",
+					  "rngcanonical, rngsubdiff "
+					  "FROM pg_catalog.pg_range r, pg_catalog.pg_type st, "
+					  "     pg_catalog.pg_opclass opc "
+					  "WHERE st.oid = rngsubtype AND opc.oid = rngsubopc AND "
+					  "rngtypid = '%u'",
 					  tyinfo->dobj.catId.oid);
 
 	res = PQexec(g_conn, query->data);
@@ -7552,10 +7552,6 @@ dumpRangeType(Archive *fout, TypeInfo *tyinfo)
 	if (strcmp(procname, "-") != 0)
 		appendPQExpBuffer(q, ",\n    subtype_diff = %s", procname);
 
-	procname = PQgetvalue(res, 0, PQfnumber(res, "typanalyze"));
-	if (strcmp(procname, "-") != 0)
-		appendPQExpBuffer(q, ",\n    analyze = %s", procname);
-
 	appendPQExpBuffer(q, "\n);\n");
 
 	appendPQExpBuffer(labelq, "TYPE %s", fmtId(tyinfo->dobj.name));
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 0dbc06cc9a9..02f60939bfe 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	201111222
+#define CATALOG_VERSION_NO	201111231
 
 #endif
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index b78af82bf53..28e53b7b7c3 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4413,6 +4413,9 @@ DATA(insert OID = 3881 (  range_gist_same		PGNSP PGUID 12 1 0 0 0 f f f t f i 3
 DESCR("GiST support");
 DATA(insert OID = 3902 (  hash_range		 	PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 23 "3831" _null_ _null_ _null_ _null_ hash_range _null_ _null_ _null_ ));
 DESCR("hash a range");
+DATA(insert OID = 3916 (  range_typanalyze		PGNSP PGUID 12 1 0 0 0 f f f t f s 1 0 16 "2281" _null_ _null_ _null_ _null_ range_typanalyze _null_ _null_ _null_ ));
+DESCR("range typanalyze");
+
 DATA(insert OID = 3914 (  int4range_canonical		   PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 3904 "3904" _null_ _null_ _null_ _null_ int4range_canonical _null_ _null_ _null_ ));
 DESCR("convert an int4 range to canonical form");
 DATA(insert OID = 3928 (  int8range_canonical		   PGNSP PGUID 12 1 0 0 0 f f f t f i 1 0 3926 "3926" _null_ _null_ _null_ _null_ int8range_canonical _null_ _null_ _null_ ));
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index f2a32507908..406241a0dad 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -593,23 +593,23 @@ DESCR("txid snapshot");
 DATA(insert OID = 2949 ( _txid_snapshot PGNSP PGUID -1 f b A f t \054 0 2970 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 0 _null_ _null_ ));
 
 /* range types */
-DATA(insert OID = 3904 ( int4range		PGNSP PGUID  -1 f r R f t \054 0 0 3905 range_in range_out range_recv range_send - - - i x f 0 -1 0 0 _null_ _null_ ));
+DATA(insert OID = 3904 ( int4range		PGNSP PGUID  -1 f r R f t \054 0 0 3905 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 _null_ _null_ ));
 DESCR("range of integers");
 #define INT4RANGEOID		3904
 DATA(insert OID = 3905 ( _int4range		PGNSP PGUID  -1 f b A f t \054 0 3904 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 0 _null_ _null_ ));
-DATA(insert OID = 3906 ( numrange		PGNSP PGUID  -1 f r R f t \054 0 0 3907 range_in range_out range_recv range_send - - - i x f 0 -1 0 0 _null_ _null_ ));
+DATA(insert OID = 3906 ( numrange		PGNSP PGUID  -1 f r R f t \054 0 0 3907 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 _null_ _null_ ));
 DESCR("range of numerics");
 DATA(insert OID = 3907 ( _numrange		PGNSP PGUID  -1 f b A f t \054 0 3906 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 0 _null_ _null_ ));
-DATA(insert OID = 3908 ( tsrange		PGNSP PGUID  -1 f r R f t \054 0 0 3909 range_in range_out range_recv range_send - - - d x f 0 -1 0 0 _null_ _null_ ));
+DATA(insert OID = 3908 ( tsrange		PGNSP PGUID  -1 f r R f t \054 0 0 3909 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 _null_ _null_ ));
 DESCR("range of timestamps without time zone");
 DATA(insert OID = 3909 ( _tsrange		PGNSP PGUID  -1 f b A f t \054 0 3908 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 0 _null_ _null_ ));
-DATA(insert OID = 3910 ( tstzrange		PGNSP PGUID  -1 f r R f t \054 0 0 3911 range_in range_out range_recv range_send - - - d x f 0 -1 0 0 _null_ _null_ ));
+DATA(insert OID = 3910 ( tstzrange		PGNSP PGUID  -1 f r R f t \054 0 0 3911 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 _null_ _null_ ));
 DESCR("range of timestamps with time zone");
 DATA(insert OID = 3911 ( _tstzrange		PGNSP PGUID  -1 f b A f t \054 0 3910 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 0 _null_ _null_ ));
-DATA(insert OID = 3912 ( daterange		PGNSP PGUID  -1 f r R f t \054 0 0 3913 range_in range_out range_recv range_send - - - i x f 0 -1 0 0 _null_ _null_ ));
+DATA(insert OID = 3912 ( daterange		PGNSP PGUID  -1 f r R f t \054 0 0 3913 range_in range_out range_recv range_send - - range_typanalyze i x f 0 -1 0 0 _null_ _null_ ));
 DESCR("range of dates");
 DATA(insert OID = 3913 ( _daterange		PGNSP PGUID  -1 f b A f t \054 0 3912 0 array_in array_out array_recv array_send - - - i x f 0 -1 0 0 _null_ _null_ ));
-DATA(insert OID = 3926 ( int8range		PGNSP PGUID  -1 f r R f t \054 0 0 3927 range_in range_out range_recv range_send - - - d x f 0 -1 0 0 _null_ _null_ ));
+DATA(insert OID = 3926 ( int8range		PGNSP PGUID  -1 f r R f t \054 0 0 3927 range_in range_out range_recv range_send - - range_typanalyze d x f 0 -1 0 0 _null_ _null_ ));
 DESCR("range of bigints");
 DATA(insert OID = 3927 ( _int8range		PGNSP PGUID  -1 f b A f t \054 0 3926 0 array_in array_out array_recv array_send - - - d x f 0 -1 0 0 _null_ _null_ ));
 
diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h
index 17915504f93..c9a6834e6db 100644
--- a/src/include/utils/rangetypes.h
+++ b/src/include/utils/rangetypes.h
@@ -127,6 +127,9 @@ extern Datum range_gt(PG_FUNCTION_ARGS);
 /* Hash support */
 extern Datum hash_range(PG_FUNCTION_ARGS);
 
+/* ANALYZE support */
+extern Datum range_typanalyze(PG_FUNCTION_ARGS);
+
 /* Canonical functions */
 extern Datum int4range_canonical(PG_FUNCTION_ARGS);
 extern Datum int8range_canonical(PG_FUNCTION_ARGS);
-- 
GitLab