20
20
#include "catalog/pg_type.h"
21
21
#include "funcapi.h"
22
22
#include "nodes/nodeFuncs.h"
23
- #include "parser/parse_coerce.h"
24
23
#include "utils/array.h"
25
24
#include "utils/builtins.h"
26
25
#include "utils/lsyscache.h"
31
30
#include "utils/typcache.h"
32
31
33
32
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
+
34
40
static void shutdown_MultiFuncCall (Datum arg );
35
41
static TypeFuncClass internal_get_result_type (Oid funcid ,
36
42
Node * call_expr ,
37
43
ReturnSetInfo * rsinfo ,
38
44
Oid * resultTypeId ,
39
45
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 );
40
49
static bool resolve_polymorphic_tupdesc (TupleDesc tupdesc ,
41
50
oidvector * declared_args ,
42
51
Node * call_expr );
@@ -455,26 +464,107 @@ get_expr_result_tupdesc(Node *expr, bool noError)
455
464
return NULL ;
456
465
}
457
466
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
+
458
549
/*
459
550
* 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.
463
556
*/
464
557
static bool
465
558
resolve_polymorphic_tupdesc (TupleDesc tupdesc , oidvector * declared_args ,
466
559
Node * call_expr )
467
560
{
468
561
int natts = tupdesc -> natts ;
469
562
int nargs = declared_args -> dim1 ;
563
+ bool have_polymorphic_result = false;
470
564
bool have_anyelement_result = false;
471
565
bool have_anyarray_result = false;
472
566
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 ;
478
568
Oid anycollation = InvalidOid ;
479
569
int i ;
480
570
@@ -484,28 +574,24 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
484
574
switch (TupleDescAttr (tupdesc , i )-> atttypid )
485
575
{
486
576
case ANYELEMENTOID :
577
+ case ANYNONARRAYOID :
578
+ case ANYENUMOID :
579
+ have_polymorphic_result = true;
487
580
have_anyelement_result = true;
488
581
break ;
489
582
case ANYARRAYOID :
583
+ have_polymorphic_result = true;
490
584
have_anyarray_result = true;
491
585
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 ;
500
586
case ANYRANGEOID :
587
+ have_polymorphic_result = true;
501
588
have_anyrange_result = true;
502
589
break ;
503
590
default :
504
591
break ;
505
592
}
506
593
}
507
- if (!have_anyelement_result && !have_anyarray_result &&
508
- !have_anyrange_result )
594
+ if (!have_polymorphic_result )
509
595
return true;
510
596
511
597
/*
@@ -515,84 +601,66 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
515
601
if (!call_expr )
516
602
return false; /* no hope */
517
603
604
+ memset (& poly_actuals , 0 , sizeof (poly_actuals ));
605
+
518
606
for (i = 0 ; i < nargs ; i ++ )
519
607
{
520
608
switch (declared_args -> values [i ])
521
609
{
522
610
case ANYELEMENTOID :
523
611
case ANYNONARRAYOID :
524
612
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
+ }
527
620
break ;
528
621
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
+ }
531
629
break ;
532
630
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
+ }
535
638
break ;
536
639
default :
537
640
break ;
538
641
}
539
642
}
540
643
541
- /* If nothing found, parser messed up */
542
- if (!OidIsValid (anyelement_type ) && !OidIsValid (anyarray_type ) &&
543
- !OidIsValid (anyrange_type ))
544
- return false;
545
-
546
644
/* 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 );
577
647
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 );
581
650
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 );
585
653
586
654
/*
587
655
* Identify the collation to use for polymorphic OUT parameters. (It'll
588
656
* necessarily be the same for both anyelement and anyarray.) Note that
589
657
* range types are not collatable, so any possible internal collation of a
590
658
* range type is not considered here.
591
659
*/
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 );
596
664
597
665
if (OidIsValid (anycollation ))
598
666
{
@@ -619,23 +687,23 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
619
687
case ANYENUMOID :
620
688
TupleDescInitEntry (tupdesc , i + 1 ,
621
689
NameStr (att -> attname ),
622
- anyelement_type ,
690
+ poly_actuals . anyelement_type ,
623
691
-1 ,
624
692
0 );
625
693
TupleDescInitEntryCollation (tupdesc , i + 1 , anycollation );
626
694
break ;
627
695
case ANYARRAYOID :
628
696
TupleDescInitEntry (tupdesc , i + 1 ,
629
697
NameStr (att -> attname ),
630
- anyarray_type ,
698
+ poly_actuals . anyarray_type ,
631
699
-1 ,
632
700
0 );
633
701
TupleDescInitEntryCollation (tupdesc , i + 1 , anycollation );
634
702
break ;
635
703
case ANYRANGEOID :
636
704
TupleDescInitEntry (tupdesc , i + 1 ,
637
705
NameStr (att -> attname ),
638
- anyrange_type ,
706
+ poly_actuals . anyrange_type ,
639
707
-1 ,
640
708
0 );
641
709
/* no collation should be attached to a range type */
@@ -650,27 +718,33 @@ resolve_polymorphic_tupdesc(TupleDesc tupdesc, oidvector *declared_args,
650
718
651
719
/*
652
720
* 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
+ *
655
725
* This is the same logic as resolve_polymorphic_tupdesc, but with a different
656
- * argument representation.
726
+ * argument representation, and slightly different output responsibilities .
657
727
*
658
728
* argmodes may be NULL, in which case all arguments are assumed to be IN mode.
659
729
*/
660
730
bool
661
731
resolve_polymorphic_argtypes (int numargs , Oid * argtypes , char * argmodes ,
662
732
Node * call_expr )
663
733
{
734
+ bool have_polymorphic_result = false;
664
735
bool have_anyelement_result = false;
665
736
bool have_anyarray_result = false;
666
737
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 ;
670
739
int inargno ;
671
740
int i ;
672
741
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 ));
674
748
inargno = 0 ;
675
749
for (i = 0 ; i < numargs ; i ++ )
676
750
{
@@ -682,47 +756,56 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
682
756
case ANYNONARRAYOID :
683
757
case ANYENUMOID :
684
758
if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE )
759
+ {
760
+ have_polymorphic_result = true;
685
761
have_anyelement_result = true;
762
+ }
686
763
else
687
764
{
688
- if (!OidIsValid (anyelement_type ))
765
+ if (!OidIsValid (poly_actuals . anyelement_type ))
689
766
{
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 ))
693
770
return false;
694
771
}
695
- argtypes [i ] = anyelement_type ;
772
+ argtypes [i ] = poly_actuals . anyelement_type ;
696
773
}
697
774
break ;
698
775
case ANYARRAYOID :
699
776
if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE )
777
+ {
778
+ have_polymorphic_result = true;
700
779
have_anyarray_result = true;
780
+ }
701
781
else
702
782
{
703
- if (!OidIsValid (anyarray_type ))
783
+ if (!OidIsValid (poly_actuals . anyarray_type ))
704
784
{
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 ))
708
788
return false;
709
789
}
710
- argtypes [i ] = anyarray_type ;
790
+ argtypes [i ] = poly_actuals . anyarray_type ;
711
791
}
712
792
break ;
713
793
case ANYRANGEOID :
714
794
if (argmode == PROARGMODE_OUT || argmode == PROARGMODE_TABLE )
795
+ {
796
+ have_polymorphic_result = true;
715
797
have_anyrange_result = true;
798
+ }
716
799
else
717
800
{
718
- if (!OidIsValid (anyrange_type ))
801
+ if (!OidIsValid (poly_actuals . anyrange_type ))
719
802
{
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 ))
723
806
return false;
724
807
}
725
- argtypes [i ] = anyrange_type ;
808
+ argtypes [i ] = poly_actuals . anyrange_type ;
726
809
}
727
810
break ;
728
811
default :
@@ -733,48 +816,18 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
733
816
}
734
817
735
818
/* Done? */
736
- if (!have_anyelement_result && !have_anyarray_result &&
737
- !have_anyrange_result )
819
+ if (!have_polymorphic_result )
738
820
return true;
739
821
740
- /* If no input polymorphics, parser messed up */
741
- if (!OidIsValid (anyelement_type ) && !OidIsValid (anyarray_type ) &&
742
- !OidIsValid (anyrange_type ))
743
- return false;
744
-
745
822
/* 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 );
769
825
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 );
776
828
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 );
778
831
779
832
/* And finally replace the output column types as needed */
780
833
for (i = 0 ; i < numargs ; i ++ )
@@ -784,13 +837,13 @@ resolve_polymorphic_argtypes(int numargs, Oid *argtypes, char *argmodes,
784
837
case ANYELEMENTOID :
785
838
case ANYNONARRAYOID :
786
839
case ANYENUMOID :
787
- argtypes [i ] = anyelement_type ;
840
+ argtypes [i ] = poly_actuals . anyelement_type ;
788
841
break ;
789
842
case ANYARRAYOID :
790
- argtypes [i ] = anyarray_type ;
843
+ argtypes [i ] = poly_actuals . anyarray_type ;
791
844
break ;
792
845
case ANYRANGEOID :
793
- argtypes [i ] = anyrange_type ;
846
+ argtypes [i ] = poly_actuals . anyrange_type ;
794
847
break ;
795
848
default :
796
849
break ;
0 commit comments