1313 * Portions Copyright (c) 1994, Regents of the University of California
1414 *
1515 * IDENTIFICATION
16- * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.112 2008/09/09 18:58:08 tgl Exp $
16+ * $PostgreSQL: pgsql/src/backend/catalog/namespace.c,v 1.113 2008/12/04 17:51:26 petere Exp $
1717 *
1818 *-------------------------------------------------------------------------
1919 */
@@ -571,6 +571,11 @@ TypeIsVisible(Oid typid)
571571 * If expand_variadic is false, variadic arguments are not treated specially,
572572 * and the returned nvargs will always be zero.
573573 *
574+ * If expand_variadic is true, functions with argument default values
575+ * will also be retrieved. If expand_variadic is false, default
576+ * values will not be taken into account and functions that do not
577+ * have exactly nargs arguments in total will not be considered.
578+ *
574579 * We search a single namespace if the function name is qualified, else
575580 * all namespaces in the search path. The return list will never contain
576581 * multiple entries with identical argument lists --- in the multiple-
@@ -621,13 +626,45 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
621626 int pathpos = 0 ;
622627 bool variadic ;
623628 Oid va_elem_type ;
629+ List * defaults = NIL ;
624630 FuncCandidateList newResult ;
625631
632+ /*
633+ * Check if function has some parameter defaults if some
634+ * parameters are missing.
635+ */
636+ if (pronargs > nargs && expand_variadic )
637+ {
638+ bool isnull ;
639+ Datum proargdefaults ;
640+ char * str ;
641+
642+ /* skip when not enough default expressions */
643+ if (nargs + procform -> pronargdefaults < pronargs )
644+ continue ;
645+
646+ proargdefaults = SysCacheGetAttr (PROCOID , proctup ,
647+ Anum_pg_proc_proargdefaults , & isnull );
648+ Assert (!isnull );
649+ str = TextDatumGetCString (proargdefaults );
650+ defaults = (List * ) stringToNode (str );
651+
652+ Assert (IsA (defaults , List ));
653+
654+ /*
655+ * If we don't have to use all default parameters, we skip
656+ * some cells from the left.
657+ */
658+ defaults = list_copy_tail (defaults , procform -> pronargdefaults - pronargs + nargs );
659+
660+ pfree (str );
661+ }
662+
626663 /*
627664 * Check if function is variadic, and get variadic element type if so.
628665 * If expand_variadic is false, we should just ignore variadic-ness.
629666 */
630- if (expand_variadic )
667+ if (pronargs <= nargs && expand_variadic )
631668 {
632669 va_elem_type = procform -> provariadic ;
633670 variadic = OidIsValid (va_elem_type );
@@ -638,11 +675,16 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
638675 variadic = false;
639676 }
640677
678+ Assert (!variadic || !defaults );
679+
641680 /* Ignore if it doesn't match requested argument count */
642681 if (nargs >= 0 &&
643- (variadic ? (pronargs > nargs ) : (pronargs != nargs )))
682+ (variadic ? (pronargs > nargs ) : (defaults ? ( pronargs < nargs ) : ( pronargs != nargs ) )))
644683 continue ;
645684
685+ Assert (!variadic || (pronargs <= nargs ));
686+ Assert (!defaults || (pronargs > nargs ));
687+
646688 if (OidIsValid (namespaceId ))
647689 {
648690 /* Consider only procs in specified namespace */
@@ -681,6 +723,7 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
681723 newResult -> pathpos = pathpos ;
682724 newResult -> oid = HeapTupleGetOid (proctup );
683725 newResult -> nargs = effective_nargs ;
726+ newResult -> argdefaults = defaults ;
684727 memcpy (newResult -> args , procform -> proargtypes .values ,
685728 pronargs * sizeof (Oid ));
686729 if (variadic )
@@ -695,6 +738,8 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
695738 else
696739 newResult -> nvargs = 0 ;
697740
741+ any_variadic = variadic || defaults ;
742+
698743 /*
699744 * Does it have the same arguments as something we already accepted?
700745 * If so, decide which one to keep. We can skip this check for the
@@ -704,6 +749,9 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
704749 */
705750 if (any_variadic || !OidIsValid (namespaceId ))
706751 {
752+ if (defaults )
753+ effective_nargs = nargs ;
754+
707755 /*
708756 * If we have an ordered list from SearchSysCacheList (the normal
709757 * case), then any conflicting proc must immediately adjoin this
@@ -733,11 +781,21 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
733781 prevResult ;
734782 prevResult = prevResult -> next )
735783 {
736- if (effective_nargs == prevResult -> nargs &&
737- memcmp (newResult -> args ,
738- prevResult -> args ,
739- effective_nargs * sizeof (Oid )) == 0 )
784+ if (!defaults )
785+ {
786+ if (effective_nargs == prevResult -> nargs &&
787+ memcmp (newResult -> args ,
788+ prevResult -> args ,
789+ effective_nargs * sizeof (Oid )) == 0 )
790+ break ;
791+ }
792+ else
793+ {
794+ if (memcmp (newResult -> args ,
795+ prevResult -> args ,
796+ effective_nargs * sizeof (Oid )) == 0 )
740797 break ;
798+ }
741799 }
742800 }
743801 if (prevResult )
@@ -777,13 +835,28 @@ FuncnameGetCandidates(List *names, int nargs, bool expand_variadic)
777835 pfree (newResult );
778836 continue ; /* keep previous result */
779837 }
838+
839+ if (defaults )
840+ {
841+ if (prevResult -> argdefaults != NIL )
842+ ereport (ERROR ,
843+ (errcode (ERRCODE_AMBIGUOUS_FUNCTION ),
844+ errmsg ("functions with parameter defaults %s and %s are ambiguous" ,
845+ func_signature_string (names , pronargs , procform -> proargtypes .values ),
846+ func_signature_string (names , prevResult -> nargs , prevResult -> args ))));
847+ /* else, previous result didn't have defaults */
848+ pfree (newResult );
849+ continue ; /* keep previous result */
850+ }
851+
780852 /* non-variadic can replace a previous variadic */
781853 Assert (prevResult -> nvargs > 0 );
782854 }
783855 /* replace previous result */
784856 prevResult -> pathpos = pathpos ;
785857 prevResult -> oid = newResult -> oid ;
786858 prevResult -> nvargs = newResult -> nvargs ;
859+ prevResult -> argdefaults = newResult -> argdefaults ;
787860 pfree (newResult );
788861 continue ; /* args are same, of course */
789862 }
0 commit comments