@@ -91,7 +91,7 @@ ProcedureCreate(const char *procedureName,
9191 int parameterCount ;
9292 int allParamCount ;
9393 Oid * allParams ;
94- char * modes = NULL ;
94+ char * paramModes = NULL ;
9595 bool genericInParam = false;
9696 bool genericOutParam = false;
9797 bool anyrangeInParam = false;
@@ -130,6 +130,7 @@ ProcedureCreate(const char *procedureName,
130130 FUNC_MAX_ARGS )));
131131 /* note: the above is correct, we do NOT count output arguments */
132132
133+ /* Deconstruct array inputs */
133134 if (allParameterTypes != PointerGetDatum (NULL ))
134135 {
135136 /*
@@ -169,28 +170,27 @@ ProcedureCreate(const char *procedureName,
169170 ARR_HASNULL (modesArray ) ||
170171 ARR_ELEMTYPE (modesArray ) != CHAROID )
171172 elog (ERROR , "parameterModes is not a 1-D char array" );
172- modes = (char * ) ARR_DATA_PTR (modesArray );
173+ paramModes = (char * ) ARR_DATA_PTR (modesArray );
173174 }
174175
175-
176176 /*
177- * Do not allow polymorphic return type unless at least one input argument
178- * is polymorphic. Also, do not allow return type INTERNAL unless at
179- * least one input argument is INTERNAL.
177+ * Detect whether we have polymorphic or INTERNAL arguments. The first
178+ * loop checks input arguments, the second output arguments.
180179 */
181180 for (i = 0 ; i < parameterCount ; i ++ )
182181 {
183182 switch (parameterTypes -> values [i ])
184183 {
185- case ANYRANGEOID :
186- anyrangeInParam = true;
187- /* FALL THROUGH */
188184 case ANYARRAYOID :
189185 case ANYELEMENTOID :
190186 case ANYNONARRAYOID :
191187 case ANYENUMOID :
192188 genericInParam = true;
193189 break ;
190+ case ANYRANGEOID :
191+ genericInParam = true;
192+ anyrangeInParam = true;
193+ break ;
194194 case INTERNALOID :
195195 internalInParam = true;
196196 break ;
@@ -201,30 +201,37 @@ ProcedureCreate(const char *procedureName,
201201 {
202202 for (i = 0 ; i < allParamCount ; i ++ )
203203 {
204- if (modes == NULL ||
205- (modes [i ] != PROARGMODE_OUT &&
206- modes [i ] != PROARGMODE_INOUT &&
207- modes [i ] != PROARGMODE_TABLE ))
208- continue ;
204+ if (paramModes == NULL ||
205+ paramModes [i ] == PROARGMODE_IN ||
206+ paramModes [i ] == PROARGMODE_VARIADIC )
207+ continue ; /* ignore input-only params */
209208
210209 switch (allParams [i ])
211210 {
212- case ANYRANGEOID :
213- anyrangeOutParam = true;
214- /* FALL THROUGH */
215211 case ANYARRAYOID :
216212 case ANYELEMENTOID :
217213 case ANYNONARRAYOID :
218214 case ANYENUMOID :
219215 genericOutParam = true;
220216 break ;
217+ case ANYRANGEOID :
218+ genericOutParam = true;
219+ anyrangeOutParam = true;
220+ break ;
221221 case INTERNALOID :
222222 internalOutParam = true;
223223 break ;
224224 }
225225 }
226226 }
227227
228+ /*
229+ * Do not allow polymorphic return type unless at least one input argument
230+ * is polymorphic. ANYRANGE return type is even stricter: must have an
231+ * ANYRANGE input (since we can't deduce the specific range type from
232+ * ANYELEMENT). Also, do not allow return type INTERNAL unless at least
233+ * one input argument is INTERNAL.
234+ */
228235 if ((IsPolymorphicType (returnType ) || genericOutParam )
229236 && !genericInParam )
230237 ereport (ERROR ,
@@ -259,7 +266,7 @@ ProcedureCreate(const char *procedureName,
259266 procedureName ,
260267 format_type_be (parameterTypes -> values [0 ]))));
261268
262- if (modes != NULL )
269+ if (paramModes != NULL )
263270 {
264271 /*
265272 * Only the last input parameter can be variadic; if it is, save its
@@ -268,7 +275,7 @@ ProcedureCreate(const char *procedureName,
268275 */
269276 for (i = 0 ; i < allParamCount ; i ++ )
270277 {
271- switch (modes [i ])
278+ switch (paramModes [i ])
272279 {
273280 case PROARGMODE_IN :
274281 case PROARGMODE_INOUT :
@@ -298,7 +305,7 @@ ProcedureCreate(const char *procedureName,
298305 }
299306 break ;
300307 default :
301- elog (ERROR , "invalid parameter mode '%c'" , modes [i ]);
308+ elog (ERROR , "invalid parameter mode '%c'" , paramModes [i ]);
302309 break ;
303310 }
304311 }
0 commit comments