>From 05c0d9b859b59c9ef85ed24b3b83df3104ffcef6 Mon Sep 17 00:00:00 2001
From: Andres Freund <andres@anarazel.de>
Date: Thu, 24 Apr 2014 02:01:07 +0200
Subject: [PATCH] Fix pg_proc entries with mismatching
 proargtypes/proallargtypes.

Also add a regression test to prevent further corrupted entries.
---
 src/include/catalog/pg_proc.h            |  4 ++--
 src/test/regress/expected/opr_sanity.out | 25 +++++++++++++++++++++++++
 src/test/regress/sql/opr_sanity.sql      | 22 ++++++++++++++++++++++
 3 files changed, 49 insertions(+), 2 deletions(-)

diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index c77c036..0df3994 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -1775,7 +1775,7 @@ DATA(insert OID = 1576 (  setval			PGNSP PGUID 12 1 0 0 0 f f f f t f v 2 0 20 "
 DESCR("set sequence value");
 DATA(insert OID = 1765 (  setval			PGNSP PGUID 12 1 0 0 0 f f f f t f v 3 0 20 "2205 20 16" _null_ _null_ _null_ _null_ setval3_oid _null_ _null_ _null_ ));
 DESCR("set sequence value and is_called status");
-DATA(insert OID = 3078 (  pg_sequence_parameters	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2249 "26" "{23,20,20,20,20,16}" "{i,o,o,o,o,o}" "{sequence_oid,start_value,minimum_value,maximum_value,increment,cycle_option}" _null_ pg_sequence_parameters _null_ _null_ _null_));
+DATA(insert OID = 3078 (  pg_sequence_parameters	PGNSP PGUID 12 1 0 0 0 f f f f t f s 1 0 2249 "26" "{26,20,20,20,20,16}" "{i,o,o,o,o,o}" "{sequence_oid,start_value,minimum_value,maximum_value,increment,cycle_option}" _null_ pg_sequence_parameters _null_ _null_ _null_));
 DESCR("sequence parameters, for use by information schema");
 
 DATA(insert OID = 1579 (  varbit_in			PGNSP PGUID 12 1 0 0 0 f f f f t f i 3 0 1562 "2275 26 23" _null_ _null_ _null_ _null_ varbit_in _null_ _null_ _null_ ));
@@ -2981,7 +2981,7 @@ DESCR("view members of a multixactid");
 DATA(insert OID = 3537 (  pg_describe_object		PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 25 "26 26 23" _null_ _null_ _null_ _null_ pg_describe_object _null_ _null_ _null_ ));
 DESCR("get identification of SQL object");
 
-DATA(insert OID = 3839 (  pg_identify_object		PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 2249 "26 26 23" "{26,23,23,25,25,25,25}" "{i,i,i,o,o,o,o}" "{classid,objid,subobjid,type,schema,name,identity}" _null_ pg_identify_object _null_ _null_ _null_ ));
+DATA(insert OID = 3839 (  pg_identify_object		PGNSP PGUID 12 1 0 0 0 f f f f t f s 3 0 2249 "26 26 23" "{26,26,23,25,25,25,25}" "{i,i,i,o,o,o,o}" "{classid,objid,subobjid,type,schema,name,identity}" _null_ pg_identify_object _null_ _null_ _null_ ));
 DESCR("get machine-parseable identification of SQL object");
 
 DATA(insert OID = 2079 (  pg_table_is_visible		PGNSP PGUID 12 10 0 0 0 f f f f t f s 1 0 16 "26" _null_ _null_ _null_ _null_ pg_table_is_visible _null_ _null_ _null_ ));
diff --git a/src/test/regress/expected/opr_sanity.out b/src/test/regress/expected/opr_sanity.out
index b2d671a..7ae7b38 100644
--- a/src/test/regress/expected/opr_sanity.out
+++ b/src/test/regress/expected/opr_sanity.out
@@ -332,6 +332,31 @@ WHERE proargmodes IS NOT NULL AND proargnames IS NOT NULL AND
 -----+---------
 (0 rows)
 
+-- Check for mismatching proargtypes/proallargtypes
+SELECT *
+FROM (
+    SELECT
+        oid,
+        oid::regprocedure,
+        -- plain arrays, not oidvector, please
+        ARRAY(SELECT unnest(proargtypes)) proargtypes,
+        proallargtypes,
+        ARRAY( -- remove output parameters from proallargtypes
+            SELECT proallargtypes[i]
+            FROM generate_series(1, array_length(proargmodes, 1)) g(i)
+            WHERE proargmodes[i] IN ('i', 'b', 'v')
+        ) filtered_allargtypes,
+        proargmodes
+    FROM pg_proc
+    WHERE proallargtypes IS NOT NULL
+    ) sensible_pgproc
+WHERE
+    proargtypes <> filtered_allargtypes
+;
+ oid | oid | proargtypes | proallargtypes | filtered_allargtypes | proargmodes 
+-----+-----+-------------+----------------+----------------------+-------------
+(0 rows)
+
 -- Check for protransform functions with the wrong signature
 SELECT p1.oid, p1.proname, p2.oid, p2.proname
 FROM pg_proc AS p1, pg_proc AS p2
diff --git a/src/test/regress/sql/opr_sanity.sql b/src/test/regress/sql/opr_sanity.sql
index dc1acb9..3276472 100644
--- a/src/test/regress/sql/opr_sanity.sql
+++ b/src/test/regress/sql/opr_sanity.sql
@@ -258,6 +258,28 @@ FROM pg_proc as p1
 WHERE proargmodes IS NOT NULL AND proargnames IS NOT NULL AND
     array_length(proargmodes,1) <> array_length(proargnames,1);
 
+-- Check for mismatching proargtypes/proallargtypes
+SELECT *
+FROM (
+    SELECT
+        oid,
+        oid::regprocedure,
+        -- plain arrays, not oidvector, please
+        ARRAY(SELECT unnest(proargtypes)) proargtypes,
+        proallargtypes,
+        ARRAY( -- remove output parameters from proallargtypes
+            SELECT proallargtypes[i]
+            FROM generate_series(1, array_length(proargmodes, 1)) g(i)
+            WHERE proargmodes[i] IN ('i', 'b', 'v')
+        ) filtered_allargtypes,
+        proargmodes
+    FROM pg_proc
+    WHERE proallargtypes IS NOT NULL
+    ) sensible_pgproc
+WHERE
+    proargtypes <> filtered_allargtypes
+;
+
 -- Check for protransform functions with the wrong signature
 SELECT p1.oid, p1.proname, p2.oid, p2.proname
 FROM pg_proc AS p1, pg_proc AS p2
-- 
1.8.5.rc2.dirty

