Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 4dbcb3f

Browse files
committedMar 14, 2020
Restructure polymorphic-type resolution in funcapi.c.
resolve_polymorphic_tupdesc() and resolve_polymorphic_argtypes() failed to cover the case of having to resolve anyarray given only an anyrange input. The bug was masked if anyelement was also used (as either input or output), which probably helps account for our not having noticed. While looking at this I noticed that resolve_generic_type() would produce the wrong answer if asked to make that same resolution. ISTM that resolve_generic_type() is confusingly defined and overly complex, so rather than fix it, let's just make funcapi.c do the specific lookups it requires for itself. With this change, resolve_generic_type() is not used anywhere, so remove it in HEAD. In the back branches, leave it alone (complete with bug) just in case any external code is using it. While we're here, make some other refactoring adjustments in funcapi.c with an eye to upcoming future expansion of the set of polymorphic types: * Simplify quick-exit tests by adding an overall have_polymorphic_result flag. This is about a wash now but will be a win when there are more flags. * Reduce duplication of code between resolve_polymorphic_tupdesc() and resolve_polymorphic_argtypes(). * Don't bother to validate correct matching of anynonarray or anyenum; the parser should have done that, and even if it didn't, just doing "return false" here would lead to a very confusing, off-point error message. (Really, "return false" in these two functions should only occur if the call_expr isn't supplied or we can't obtain data type info from it.) * For the same reason, throw an elog rather than "return false" if we fail to resolve a polymorphic type. The bug's been there since we added anyrange, so back-patch to all supported branches. Discussion: https://postgr.es/m/6093.1584202130@sss.pgh.pa.us
1 parent e83daa7 commit 4dbcb3f

File tree

5 files changed

+216
-251
lines changed

5 files changed

+216
-251
lines changed
 

‎src/backend/parser/parse_coerce.c

Lines changed: 0 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
*/
1515
#include "postgres.h"
1616

17-
#include "access/htup_details.h"
1817
#include "catalog/pg_cast.h"
1918
#include "catalog/pg_class.h"
2019
#include "catalog/pg_inherits.h"
@@ -26,7 +25,6 @@
2625
#include "parser/parse_relation.h"
2726
#include "parser/parse_type.h"
2827
#include "utils/builtins.h"
29-
#include "utils/datum.h"
3028
#include "utils/lsyscache.h"
3129
#include "utils/syscache.h"
3230
#include "utils/typcache.h"
@@ -1968,108 +1966,6 @@ enforce_generic_type_consistency(const Oid *actual_arg_types,
19681966
return rettype;
19691967
}
19701968

1971-
/*
1972-
* resolve_generic_type()
1973-
* Deduce an individual actual datatype on the assumption that
1974-
* the rules for polymorphic types are being followed.
1975-
*
1976-
* declared_type is the declared datatype we want to resolve.
1977-
* context_actual_type is the actual input datatype to some argument
1978-
* that has declared datatype context_declared_type.
1979-
*
1980-
* If declared_type isn't polymorphic, we just return it. Otherwise,
1981-
* context_declared_type must be polymorphic, and we deduce the correct
1982-
* return type based on the relationship of the two polymorphic types.
1983-
*/
1984-
Oid
1985-
resolve_generic_type(Oid declared_type,
1986-
Oid context_actual_type,
1987-
Oid context_declared_type)
1988-
{
1989-
if (declared_type == ANYARRAYOID)
1990-
{
1991-
if (context_declared_type == ANYARRAYOID)
1992-
{
1993-
/*
1994-
* Use actual type, but it must be an array; or if it's a domain
1995-
* over array, use the base array type.
1996-
*/
1997-
Oid context_base_type = getBaseType(context_actual_type);
1998-
Oid array_typelem = get_element_type(context_base_type);
1999-
2000-
if (!OidIsValid(array_typelem))
2001-
ereport(ERROR,
2002-
(errcode(ERRCODE_DATATYPE_MISMATCH),
2003-
errmsg("argument declared %s is not an array but type %s",
2004-
"anyarray", format_type_be(context_base_type))));
2005-
return context_base_type;
2006-
}
2007-
else if (context_declared_type == ANYELEMENTOID ||
2008-
context_declared_type == ANYNONARRAYOID ||
2009-
context_declared_type == ANYENUMOID ||
2010-
context_declared_type == ANYRANGEOID)
2011-
{
2012-
/* Use the array type corresponding to actual type */
2013-
Oid array_typeid = get_array_type(context_actual_type);
2014-
2015-
if (!OidIsValid(array_typeid))
2016-
ereport(ERROR,
2017-
(errcode(ERRCODE_UNDEFINED_OBJECT),
2018-
errmsg("could not find array type for data type %s",
2019-
format_type_be(context_actual_type))));
2020-
return array_typeid;
2021-
}
2022-
}
2023-
else if (declared_type == ANYELEMENTOID ||
2024-
declared_type == ANYNONARRAYOID ||
2025-
declared_type == ANYENUMOID ||
2026-
declared_type == ANYRANGEOID)
2027-
{
2028-
if (context_declared_type == ANYARRAYOID)
2029-
{
2030-
/* Use the element type corresponding to actual type */
2031-
Oid context_base_type = getBaseType(context_actual_type);
2032-
Oid array_typelem = get_element_type(context_base_type);
2033-
2034-
if (!OidIsValid(array_typelem))
2035-
ereport(ERROR,
2036-
(errcode(ERRCODE_DATATYPE_MISMATCH),
2037-
errmsg("argument declared %s is not an array but type %s",
2038-
"anyarray", format_type_be(context_base_type))));
2039-
return array_typelem;
2040-
}
2041-
else if (context_declared_type == ANYRANGEOID)
2042-
{
2043-
/* Use the element type corresponding to actual type */
2044-
Oid context_base_type = getBaseType(context_actual_type);
2045-
Oid range_typelem = get_range_subtype(context_base_type);
2046-
2047-
if (!OidIsValid(range_typelem))
2048-
ereport(ERROR,
2049-
(errcode(ERRCODE_DATATYPE_MISMATCH),
2050-
errmsg("argument declared %s is not a range type but type %s",
2051-
"anyrange", format_type_be(context_base_type))));
2052-
return range_typelem;
2053-
}
2054-
else if (context_declared_type == ANYELEMENTOID ||
2055-
context_declared_type == ANYNONARRAYOID ||
2056-
context_declared_type == ANYENUMOID)
2057-
{
2058-
/* Use the actual type; it doesn't matter if array or not */
2059-
return context_actual_type;
2060-
}
2061-
}
2062-
else
2063-
{
2064-
/* declared_type isn't polymorphic, so return it as-is */
2065-
return declared_type;
2066-
}
2067-
/* If we get here, declared_type is polymorphic and context isn't */
2068-
/* NB: this is a calling-code logic error, not a user error */
2069-
elog(ERROR, "could not determine polymorphic type because context isn't polymorphic");
2070-
return InvalidOid; /* keep compiler quiet */
2071-
}
2072-
20731969

20741970
/* TypeCategory()
20751971
* Assign a category to the specified type OID.

‎src/backend/utils/fmgr/funcapi.c

Lines changed: 188 additions & 135 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include "catalog/pg_type.h"
2121
#include "funcapi.h"
2222
#include "nodes/nodeFuncs.h"
23-
#include "parser/parse_coerce.h"
2423
#include "utils/array.h"
2524
#include "utils/builtins.h"
2625
#include "utils/lsyscache.h"
@@ -31,12 +30,22 @@
3130
#include "utils/typcache.h"
3231

3332

33+
typedef struct polymorphic_actuals
34+
{
35+
Oid anyelement_type; /* anyelement mapping, if known */
36+
Oid anyarray_type; /* anyarray mapping, if known */
37+
Oid anyrange_type; /* anyrange mapping, if known */
38+
} polymorphic_actuals;
39+
3440
static void shutdown_MultiFuncCall(Datum arg);
3541
static TypeFuncClass internal_get_result_type(Oid funcid,
3642
Node *call_expr,
3743
ReturnSetInfo *rsinfo,
3844
Oid *resultTypeId,
3945
TupleDesc *resultTupleDesc);
46+
static void resolve_anyelement_from_others(polymorphic_actuals *actuals);
47+
static void resolve_anyarray_from_others(polymorphic_actuals *actuals);
48+
static void resolve_anyrange_from_others(polymorphic_actuals *actuals);
4049
static bool resolve_polymorphic_tupdesc(TupleDesc tupdesc,
4150
oidvector *declared_args,
4251
Node *call_expr);
@@ -455,26 +464,107 @@ get_expr_result_tupdesc(Node *expr, bool noError)
455464
return NULL;
456465
}
457466

467+
/*
468+
* Resolve actual type of ANYELEMENT from other polymorphic inputs
469+
*
470+
* Note: the error cases here and in the sibling functions below are not
471+
* really user-facing; they could only occur if the function signature is
472+
* incorrect or the parser failed to enforce consistency of the actual
473+
* argument types. Hence, we don't sweat too much over the error messages.
474+
*/
475+
static void
476+
resolve_anyelement_from_others(polymorphic_actuals *actuals)
477+
{
478+
if (OidIsValid(actuals->anyarray_type))
479+
{
480+
/* Use the element type corresponding to actual type */
481+
Oid array_base_type = getBaseType(actuals->anyarray_type);
482+
Oid array_typelem = get_element_type(array_base_type);
483+
484+
if (!OidIsValid(array_typelem))
485+
ereport(ERROR,
486+
(errcode(ERRCODE_DATATYPE_MISMATCH),
487+
errmsg("argument declared %s is not an array but type %s",
488+
"anyarray",
489+
format_type_be(array_base_type))));
490+
actuals->anyelement_type = array_typelem;
491+
}
492+
else if (OidIsValid(actuals->anyrange_type))
493+
{
494+
/* Use the element type corresponding to actual type */
495+
Oid range_base_type = getBaseType(actuals->anyrange_type);
496+
Oid range_typelem = get_range_subtype(range_base_type);
497+
498+
if (!OidIsValid(range_typelem))
499+
ereport(ERROR,
500+
(errcode(ERRCODE_DATATYPE_MISMATCH),
501+
errmsg("argument declared %s is not a range type but type %s",
502+
"anyrange",
503+
format_type_be(range_base_type))));
504+
actuals->anyelement_type = range_typelem;
505+
}
506+
else
507+
elog(ERROR, "could not determine polymorphic type");
508+
}
509+
510+
/*
511+
* Resolve actual type of ANYARRAY from other polymorphic inputs
512+
*/
513+
static void
514+
resolve_anyarray_from_others(polymorphic_actuals *actuals)
515+
{
516+
/* If we don't know ANYELEMENT, resolve that first */
517+
if (!OidIsValid(actuals->anyelement_type))
518+
resolve_anyelement_from_others(actuals);
519+
520+
if (OidIsValid(actuals->anyelement_type))
521+
{
522+
/* Use the array type corresponding to actual type */
523+
Oid array_typeid = get_array_type(actuals->anyelement_type);
524+
525+
if (!OidIsValid(array_typeid))
526+
ereport(ERROR,
527+
(errcode(ERRCODE_UNDEFINED_OBJECT),
528+
errmsg("could not find array type for data type %s",
529+
format_type_be(actuals->anyelement_type))));
530+
actuals->anyarray_type = array_typeid;
531+
}
532+
else
533+
elog(ERROR, "could not determine polymorphic type");
534+
}
535+
536+
/*
537+
* Resolve actual type of ANYRANGE from other polymorphic inputs
538+
*/
539+
static void
540+
resolve_anyrange_from_others(polymorphic_actuals *actuals)
541+
{
542+
/*
543+
* We can't deduce a range type from other polymorphic inputs, because
544+
* there may be multiple range types with the same subtype.
545+
*/
546+
elog(ERROR, "could not determine polymorphic type");
547+
}
548+
458549
/*
459550
* Given the result tuple descriptor for a function with OUT parameters,
460-
* replace any polymorphic columns (ANYELEMENT etc) with correct data types
461-
* deduced from the input arguments. Returns true if able to deduce all types,
462-
* false if not.
551+
* replace any polymorphic column types (ANYELEMENT etc) in the tupdesc
552+
* with concrete data types deduced from the input arguments.
553+
* declared_args is an oidvector of the function's declared input arg types
554+
* (showing which are polymorphic), and call_expr is the call expression.
555+
* Returns true if able to deduce all types, false if not.
463556
*/
464557
static bool
465558
resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
466559
Node *call_expr)
467560
{
468561
int natts = tupdesc->natts;
469562
int nargs = declared_args->dim1;
563+
bool have_polymorphic_result = false;
470564
bool have_anyelement_result = false;
471565
bool have_anyarray_result = false;
472566
bool have_anyrange_result = false;
473-
bool have_anynonarray = false;
474-
bool have_anyenum = false;
475-
Oid anyelement_type = InvalidOid;
476-
Oid anyarray_type = InvalidOid;
477-
Oid anyrange_type = InvalidOid;
567+
polymorphic_actuals poly_actuals;
478568
Oid anycollation = InvalidOid;
479569
int i;
480570

@@ -484,28 +574,24 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
484574
switch (TupleDescAttr(tupdesc, i)->atttypid)
485575
{
486576
case ANYELEMENTOID:
577+
case ANYNONARRAYOID:
578+
case ANYENUMOID:
579+
have_polymorphic_result = true;
487580
have_anyelement_result = true;
488581
break;
489582
case ANYARRAYOID:
583+
have_polymorphic_result = true;
490584
have_anyarray_result = true;
491585
break;
492-
case ANYNONARRAYOID:
493-
have_anyelement_result = true;
494-
have_anynonarray = true;
495-
break;
496-
case ANYENUMOID:
497-
have_anyelement_result = true;
498-
have_anyenum = true;
499-
break;
500586
case ANYRANGEOID:
587+
have_polymorphic_result = true;
501588
have_anyrange_result = true;
502589
break;
503590
default:
504591
break;
505592
}
506593
}
507-
if (!have_anyelement_result && !have_anyarray_result &&
508-
!have_anyrange_result)
594+
if (!have_polymorphic_result)
509595
return true;
510596

511597
/*
@@ -515,84 +601,66 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
515601
if (!call_expr)
516602
return false; /* no hope */
517603

604+
memset(&poly_actuals, 0, sizeof(poly_actuals));
605+
518606
for (i = 0; i < nargs; i++)
519607
{
520608
switch (declared_args->values[i])
521609
{
522610
case ANYELEMENTOID:
523611
case ANYNONARRAYOID:
524612
case ANYENUMOID:
525-
if (!OidIsValid(anyelement_type))
526-
anyelement_type = get_call_expr_argtype(call_expr, i);
613+
if (!OidIsValid(poly_actuals.anyelement_type))
614+
{
615+
poly_actuals.anyelement_type =
616+
get_call_expr_argtype(call_expr, i);
617+
if (!OidIsValid(poly_actuals.anyelement_type))
618+
return false;
619+
}
527620
break;
528621
case ANYARRAYOID:
529-
if (!OidIsValid(anyarray_type))
530-
anyarray_type = get_call_expr_argtype(call_expr, i);
622+
if (!OidIsValid(poly_actuals.anyarray_type))
623+
{
624+
poly_actuals.anyarray_type =
625+
get_call_expr_argtype(call_expr, i);
626+
if (!OidIsValid(poly_actuals.anyarray_type))
627+
return false;
628+
}
531629
break;
532630
case ANYRANGEOID:
533-
if (!OidIsValid(anyrange_type))
534-
anyrange_type = get_call_expr_argtype(call_expr, i);
631+
if (!OidIsValid(poly_actuals.anyrange_type))
632+
{
633+
poly_actuals.anyrange_type =
634+
get_call_expr_argtype(call_expr, i);
635+
if (!OidIsValid(poly_actuals.anyrange_type))
636+
return false;
637+
}
535638
break;
536639
default:
537640
break;
538641
}
539642
}
540643

541-
/* If nothing found, parser messed up */
542-
if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type) &&
543-
!OidIsValid(anyrange_type))
544-
return false;
545-
546644
/* If needed, deduce one polymorphic type from others */
547-
if (have_anyelement_result && !OidIsValid(anyelement_type))
548-
{
549-
if (OidIsValid(anyarray_type))
550-
anyelement_type = resolve_generic_type(ANYELEMENTOID,
551-
anyarray_type,
552-
ANYARRAYOID);
553-
if (OidIsValid(anyrange_type))
554-
{
555-
Oid subtype = resolve_generic_type(ANYELEMENTOID,
556-
anyrange_type,
557-
ANYRANGEOID);
558-
559-
/* check for inconsistent array and range results */
560-
if (OidIsValid(anyelement_type) && anyelement_type != subtype)
561-
return false;
562-
anyelement_type = subtype;
563-
}
564-
}
565-
566-
if (have_anyarray_result && !OidIsValid(anyarray_type))
567-
anyarray_type = resolve_generic_type(ANYARRAYOID,
568-
anyelement_type,
569-
ANYELEMENTOID);
570-
571-
/*
572-
* We can't deduce a range type from other polymorphic inputs, because
573-
* there may be multiple range types for the same subtype.
574-
*/
575-
if (have_anyrange_result && !OidIsValid(anyrange_type))
576-
return false;
645+
if (have_anyelement_result && !OidIsValid(poly_actuals.anyelement_type))
646+
resolve_anyelement_from_others(&poly_actuals);
577647

578-
/* Enforce ANYNONARRAY if needed */
579-
if (have_anynonarray && type_is_array(anyelement_type))
580-
return false;
648+
if (have_anyarray_result && !OidIsValid(poly_actuals.anyarray_type))
649+
resolve_anyarray_from_others(&poly_actuals);
581650

582-
/* Enforce ANYENUM if needed */
583-
if (have_anyenum && !type_is_enum(anyelement_type))
584-
return false;
651+
if (have_anyrange_result && !OidIsValid(poly_actuals.anyrange_type))
652+
resolve_anyrange_from_others(&poly_actuals);
585653

586654
/*
587655
* Identify the collation to use for polymorphic OUT parameters. (It'll
588656
* necessarily be the same for both anyelement and anyarray.) Note that
589657
* range types are not collatable, so any possible internal collation of a
590658
* range type is not considered here.
591659
*/
592-
if (OidIsValid(anyelement_type))
593-
anycollation = get_typcollation(anyelement_type);
594-
else if (OidIsValid(anyarray_type))
595-
anycollation = get_typcollation(anyarray_type);
660+
if (OidIsValid(poly_actuals.anyelement_type))
661+
anycollation = get_typcollation(poly_actuals.anyelement_type);
662+
else if (OidIsValid(poly_actuals.anyarray_type))
663+
anycollation = get_typcollation(poly_actuals.anyarray_type);
596664

597665
if (OidIsValid(anycollation))
598666
{
@@ -619,23 +687,23 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
619687
case ANYENUMOID:
620688
TupleDescInitEntry(tupdesc, i + 1,
621689
NameStr(att->attname),
622-
anyelement_type,
690+
poly_actuals.anyelement_type,
623691
-1,
624692
0);
625693
TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
626694
break;
627695
case ANYARRAYOID:
628696
TupleDescInitEntry(tupdesc, i + 1,
629697
NameStr(att->attname),
630-
anyarray_type,
698+
poly_actuals.anyarray_type,
631699
-1,
632700
0);
633701
TupleDescInitEntryCollation(tupdesc, i + 1, anycollation);
634702
break;
635703
case ANYRANGEOID:
636704
TupleDescInitEntry(tupdesc, i + 1,
637705
NameStr(att->attname),
638-
anyrange_type,
706+
poly_actuals.anyrange_type,
639707
-1,
640708
0);
641709
/* no collation should be attached to a range type */
@@ -650,27 +718,33 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
650718

651719
/*
652720
* Given the declared argument types and modes for a function, replace any
653-
* polymorphic types (ANYELEMENT etc) with correct data types deduced from the
654-
* input arguments. Returns true if able to deduce all types, false if not.
721+
* polymorphic types (ANYELEMENT etc) in argtypes[] with concrete data types
722+
* deduced from the input arguments found in call_expr.
723+
* Returns true if able to deduce all types, false if not.
724+
*
655725
* This is the same logic as resolve_polymorphic_tupdesc, but with a different
656-
* argument representation.
726+
* argument representation, and slightly different output responsibilities.
657727
*
658728
* argmodes may be NULL, in which case all arguments are assumed to be IN mode.
659729
*/
660730
bool
661731
resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
662732
Node *call_expr)
663733
{
734+
bool have_polymorphic_result = false;
664735
bool have_anyelement_result = false;
665736
bool have_anyarray_result = false;
666737
bool have_anyrange_result = false;
667-
Oid anyelement_type = InvalidOid;
668-
Oid anyarray_type = InvalidOid;
669-
Oid anyrange_type = InvalidOid;
738+
polymorphic_actuals poly_actuals;
670739
int inargno;
671740
int i;
672741

673-
/* First pass: resolve polymorphic inputs, check for outputs */
742+
/*
743+
* First pass: resolve polymorphic inputs, check for outputs. As in
744+
* resolve_polymorphic_tupdesc, we rely on the parser to have enforced
745+
* type consistency.
746+
*/
747+
memset(&poly_actuals, 0, sizeof(poly_actuals));
674748
inargno = 0;
675749
for (i = 0; i < numargs; i++)
676750
{
@@ -682,47 +756,56 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
682756
case ANYNONARRAYOID:
683757
case ANYENUMOID:
684758
if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
759+
{
760+
have_polymorphic_result = true;
685761
have_anyelement_result = true;
762+
}
686763
else
687764
{
688-
if (!OidIsValid(anyelement_type))
765+
if (!OidIsValid(poly_actuals.anyelement_type))
689766
{
690-
anyelement_type = get_call_expr_argtype(call_expr,
691-
inargno);
692-
if (!OidIsValid(anyelement_type))
767+
poly_actuals.anyelement_type =
768+
get_call_expr_argtype(call_expr, inargno);
769+
if (!OidIsValid(poly_actuals.anyelement_type))
693770
return false;
694771
}
695-
argtypes[i] = anyelement_type;
772+
argtypes[i] = poly_actuals.anyelement_type;
696773
}
697774
break;
698775
case ANYARRAYOID:
699776
if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
777+
{
778+
have_polymorphic_result = true;
700779
have_anyarray_result = true;
780+
}
701781
else
702782
{
703-
if (!OidIsValid(anyarray_type))
783+
if (!OidIsValid(poly_actuals.anyarray_type))
704784
{
705-
anyarray_type = get_call_expr_argtype(call_expr,
706-
inargno);
707-
if (!OidIsValid(anyarray_type))
785+
poly_actuals.anyarray_type =
786+
get_call_expr_argtype(call_expr, inargno);
787+
if (!OidIsValid(poly_actuals.anyarray_type))
708788
return false;
709789
}
710-
argtypes[i] = anyarray_type;
790+
argtypes[i] = poly_actuals.anyarray_type;
711791
}
712792
break;
713793
case ANYRANGEOID:
714794
if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE)
795+
{
796+
have_polymorphic_result = true;
715797
have_anyrange_result = true;
798+
}
716799
else
717800
{
718-
if (!OidIsValid(anyrange_type))
801+
if (!OidIsValid(poly_actuals.anyrange_type))
719802
{
720-
anyrange_type = get_call_expr_argtype(call_expr,
721-
inargno);
722-
if (!OidIsValid(anyrange_type))
803+
poly_actuals.anyrange_type =
804+
get_call_expr_argtype(call_expr, inargno);
805+
if (!OidIsValid(poly_actuals.anyrange_type))
723806
return false;
724807
}
725-
argtypes[i] = anyrange_type;
808+
argtypes[i] = poly_actuals.anyrange_type;
726809
}
727810
break;
728811
default:
@@ -733,48 +816,18 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
733816
}
734817

735818
/* Done? */
736-
if (!have_anyelement_result && !have_anyarray_result &&
737-
!have_anyrange_result)
819+
if (!have_polymorphic_result)
738820
return true;
739821

740-
/* If no input polymorphics, parser messed up */
741-
if (!OidIsValid(anyelement_type) && !OidIsValid(anyarray_type) &&
742-
!OidIsValid(anyrange_type))
743-
return false;
744-
745822
/* If needed, deduce one polymorphic type from others */
746-
if (have_anyelement_result && !OidIsValid(anyelement_type))
747-
{
748-
if (OidIsValid(anyarray_type))
749-
anyelement_type = resolve_generic_type(ANYELEMENTOID,
750-
anyarray_type,
751-
ANYARRAYOID);
752-
if (OidIsValid(anyrange_type))
753-
{
754-
Oid subtype = resolve_generic_type(ANYELEMENTOID,
755-
anyrange_type,
756-
ANYRANGEOID);
757-
758-
/* check for inconsistent array and range results */
759-
if (OidIsValid(anyelement_type) && anyelement_type != subtype)
760-
return false;
761-
anyelement_type = subtype;
762-
}
763-
}
764-
765-
if (have_anyarray_result && !OidIsValid(anyarray_type))
766-
anyarray_type = resolve_generic_type(ANYARRAYOID,
767-
anyelement_type,
768-
ANYELEMENTOID);
823+
if (have_anyelement_result && !OidIsValid(poly_actuals.anyelement_type))
824+
resolve_anyelement_from_others(&poly_actuals);
769825

770-
/*
771-
* We can't deduce a range type from other polymorphic inputs, because
772-
* there may be multiple range types for the same subtype.
773-
*/
774-
if (have_anyrange_result && !OidIsValid(anyrange_type))
775-
return false;
826+
if (have_anyarray_result && !OidIsValid(poly_actuals.anyarray_type))
827+
resolve_anyarray_from_others(&poly_actuals);
776828

777-
/* XXX do we need to enforce ANYNONARRAY or ANYENUM here? I think not */
829+
if (have_anyrange_result && !OidIsValid(poly_actuals.anyrange_type))
830+
resolve_anyrange_from_others(&poly_actuals);
778831

779832
/* And finally replace the output column types as needed */
780833
for (i = 0; i < numargs; i++)
@@ -784,13 +837,13 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
784837
case ANYELEMENTOID:
785838
case ANYNONARRAYOID:
786839
case ANYENUMOID:
787-
argtypes[i] = anyelement_type;
840+
argtypes[i] = poly_actuals.anyelement_type;
788841
break;
789842
case ANYARRAYOID:
790-
argtypes[i] = anyarray_type;
843+
argtypes[i] = poly_actuals.anyarray_type;
791844
break;
792845
case ANYRANGEOID:
793-
argtypes[i] = anyrange_type;
846+
argtypes[i] = poly_actuals.anyrange_type;
794847
break;
795848
default:
796849
break;

‎src/include/parser/parse_coerce.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,6 @@ extern Oid enforce_generic_type_consistency(const Oid *actual_arg_types,
7979
int nargs,
8080
Oid rettype,
8181
bool allow_poly);
82-
extern Oid resolve_generic_type(Oid declared_type,
83-
Oid context_actual_type,
84-
Oid context_declared_type);
8582

8683
extern CoercionPathType find_coercion_pathway(Oid targetTypeId,
8784
Oid sourceTypeId,

‎src/test/regress/expected/rangetypes.out

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,15 @@ select * from outparam_succeed(int4range(1,2));
14901490
[1,2) | foo
14911491
(1 row)
14921492

1493+
create function outparam2_succeed(r anyrange, out lu anyarray, out ul anyarray)
1494+
as $$ select array[lower($1), upper($1)], array[upper($1), lower($1)] $$
1495+
language sql;
1496+
select * from outparam2_succeed(int4range(1,11));
1497+
lu | ul
1498+
--------+--------
1499+
{1,11} | {11,1}
1500+
(1 row)
1501+
14931502
create function inoutparam_succeed(out i anyelement, inout r anyrange)
14941503
as $$ select upper($1), $1 $$ language sql;
14951504
select * from inoutparam_succeed(int4range(1,2));
@@ -1498,12 +1507,14 @@ select * from inoutparam_succeed(int4range(1,2));
14981507
2 | [1,2)
14991508
(1 row)
15001509

1501-
create function table_succeed(i anyelement, r anyrange) returns table(i anyelement, r anyrange)
1502-
as $$ select $1, $2 $$ language sql;
1503-
select * from table_succeed(123, int4range(1,11));
1504-
i | r
1505-
-----+--------
1506-
123 | [1,11)
1510+
create function table_succeed(r anyrange)
1511+
returns table(l anyelement, u anyelement)
1512+
as $$ select lower($1), upper($1) $$
1513+
language sql;
1514+
select * from table_succeed(int4range(1,11));
1515+
l | u
1516+
---+----
1517+
1 | 11
15071518
(1 row)
15081519

15091520
-- should fail

‎src/test/regress/sql/rangetypes.sql

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -517,15 +517,23 @@ create function outparam_succeed(i anyrange, out r anyrange, out t text)
517517

518518
select * from outparam_succeed(int4range(1,2));
519519

520+
create function outparam2_succeed(r anyrange, out lu anyarray, out ul anyarray)
521+
as $$ select array[lower($1), upper($1)], array[upper($1), lower($1)] $$
522+
language sql;
523+
524+
select * from outparam2_succeed(int4range(1,11));
525+
520526
create function inoutparam_succeed(out i anyelement, inout r anyrange)
521527
as $$ select upper($1), $1 $$ language sql;
522528

523529
select * from inoutparam_succeed(int4range(1,2));
524530

525-
create function table_succeed(i anyelement, r anyrange) returns table(i anyelement, r anyrange)
526-
as $$ select $1, $2 $$ language sql;
531+
create function table_succeed(r anyrange)
532+
returns table(l anyelement, u anyelement)
533+
as $$ select lower($1), upper($1) $$
534+
language sql;
527535

528-
select * from table_succeed(123, int4range(1,11));
536+
select * from table_succeed(int4range(1,11));
529537

530538
-- should fail
531539
create function outparam_fail(i anyelement, out r anyrange, out t text)

0 commit comments

Comments
 (0)
Please sign in to comment.