Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit03b0a58

Browse files
committed
Consider interpreting a function call as a trivial (binary-compatible)
type coercion after failing to find an exact match in pg_proc, but beforeconsidering interpretations that involve a function call with one ormore argument type coercions. This avoids surprises wherein what lookslike a type coercion is interpreted as coercing to some third type andthen to the destination type, as in Dave Blasby's bug report of 3-Oct-01.See subsequent discussion in pghackers.
1 parent1ca0874 commit03b0a58

File tree

4 files changed

+119
-84
lines changed

4 files changed

+119
-84
lines changed

‎doc/src/sgml/typeconv.sgml

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,17 @@ this step.)
458458
</para></step>
459459
<step performance="required">
460460
<para>
461+
If no exact match appears in the catalog, see whether the function call appears
462+
to be a trivial type coercion request. This happens if the function call
463+
has just one argument and the function name is the same as the (internal)
464+
name of some data type. Furthermore, the function argument must be either
465+
an unknown-type literal or a type that is binary-compatible with the named
466+
data type. When these conditions are met, the function argument is coerced
467+
to the named data type without any explicit function call.
468+
</para>
469+
</step>
470+
<step performance="required">
471+
<para>
461472
Look for the best match.
462473
</para>
463474
<substeps>
@@ -519,17 +530,6 @@ then fail.
519530
</step>
520531
</substeps>
521532
</step>
522-
<step performance="required">
523-
<para>
524-
If no best match could be identified, see whether the function call appears
525-
to be a trivial type coercion request. This happens if the function call
526-
has just one argument and the function name is the same as the (internal)
527-
name of some data type. Furthermore, the function argument must be either
528-
an unknown-type literal or a type that is binary-compatible with the named
529-
data type. When these conditions are met, the function argument is coerced
530-
to the named data type.
531-
</para>
532-
</step>
533533
</procedure>
534534

535535
<bridgehead renderas="sect2">Examples</bridgehead>

‎src/backend/commands/indexcmds.c

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.57 2001/08/21 16:36:02 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/indexcmds.c,v 1.58 2001/10/04 22:06:46 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -240,6 +240,7 @@ FuncIndexArgs(IndexInfo *indexInfo,
240240
List*arglist;
241241
intnargs=0;
242242
inti;
243+
FuncDetailCodefdresult;
243244
Oidfuncid;
244245
Oidrettype;
245246
boolretset;
@@ -282,9 +283,18 @@ FuncIndexArgs(IndexInfo *indexInfo,
282283
* that. So, check to make sure that the selected function has
283284
* exact-match or binary-compatible input types.
284285
*/
285-
if (!func_get_detail(funcIndex->name,nargs,argTypes,
286-
&funcid,&rettype,&retset,&true_typeids))
287-
func_error("DefineIndex",funcIndex->name,nargs,argTypes,NULL);
286+
fdresult=func_get_detail(funcIndex->name,funcIndex->args,
287+
nargs,argTypes,
288+
&funcid,&rettype,&retset,
289+
&true_typeids);
290+
if (fdresult!=FUNCDETAIL_NORMAL)
291+
{
292+
if (fdresult==FUNCDETAIL_COERCION)
293+
elog(ERROR,"DefineIndex: functional index must use a real function, not a type coercion"
294+
"\n\tTry specifying the index opclass you want to use, instead");
295+
else
296+
func_error("DefineIndex",funcIndex->name,nargs,argTypes,NULL);
297+
}
288298

289299
if (retset)
290300
elog(ERROR,"DefineIndex: cannot index on a function returning a set");

‎src/backend/parser/parse_func.c

Lines changed: 80 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.110 2001/08/09 18:28:18 petere Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/parser/parse_func.c,v 1.111 2001/10/04 22:06:46 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -427,12 +427,7 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
427427
}
428428

429429
/*
430-
* func_get_detail looks up the function in the catalogs, does
431-
* disambiguation for polymorphic functions, handles inheritance, and
432-
* returns the funcid and type and set or singleton status of the
433-
* function's return value. it also returns the true argument types
434-
* to the function. if func_get_detail returns true, the function
435-
* exists.otherwise, there was an error.
430+
* Is it a set, or a function?
436431
*/
437432
if (attisset)
438433
{/* we know all of these fields already */
@@ -454,61 +449,29 @@ ParseFuncOrColumn(ParseState *pstate, char *funcname, List *fargs,
454449
}
455450
else
456451
{
457-
boolexists;
452+
FuncDetailCodefdresult;
458453

459-
exists=func_get_detail(funcname,nargs,oid_array,&funcid,
460-
&rettype,&retset,&true_oid_array);
461-
if (!exists)
454+
/*
455+
* func_get_detail looks up the function in the catalogs, does
456+
* disambiguation for polymorphic functions, handles inheritance, and
457+
* returns the funcid and type and set or singleton status of the
458+
* function's return value. it also returns the true argument types
459+
* to the function.
460+
*/
461+
fdresult=func_get_detail(funcname,fargs,nargs,oid_array,
462+
&funcid,&rettype,&retset,
463+
&true_oid_array);
464+
if (fdresult==FUNCDETAIL_COERCION)
462465
{
463-
464466
/*
465-
* If we can't find a function (or can't find a unique
466-
* function), see if this is really a type-coercion request:
467-
* single-argument function call where the function name is a
468-
* type name. If so, and if we can do the coercion trivially,
469-
* just go ahead and do it without requiring there to be a
470-
* real function for it.
471-
*
472-
* "Trivial" coercions are ones that involve binary-compatible
473-
* types and ones that are coercing a previously-unknown-type
474-
* literal constant to a specific type.
475-
*
476-
* DO NOT try to generalize this code to nontrivial coercions,
477-
* because you'll just set up an infinite recursion between
478-
* this routine and coerce_type! We have already failed to
479-
* find a suitable "real" coercion function, so we have to
480-
* fail unless this is a coercion that coerce_type can handle
481-
* by itself. Make sure this code stays in sync with what
482-
* coerce_type does!
467+
* We can do it as a trivial coercion.
468+
* coerce_type can handle these cases, so why duplicate code...
483469
*/
484-
if (nargs==1)
485-
{
486-
OidtargetType;
487-
488-
targetType=GetSysCacheOid(TYPENAME,
489-
PointerGetDatum(funcname),
490-
0,0,0);
491-
if (OidIsValid(targetType))
492-
{
493-
OidsourceType=oid_array[0];
494-
Node*arg1=lfirst(fargs);
495-
496-
if ((sourceType==UNKNOWNOID&&IsA(arg1,Const))||
497-
sourceType==targetType||
498-
IS_BINARY_COMPATIBLE(sourceType,targetType))
499-
{
500-
501-
/*
502-
* Ah-hah, we can do it as a trivial coercion.
503-
* coerce_type can handle these cases, so why
504-
* duplicate code...
505-
*/
506-
returncoerce_type(pstate,arg1,
507-
sourceType,targetType,-1);
508-
}
509-
}
510-
}
511-
470+
returncoerce_type(pstate,lfirst(fargs),
471+
oid_array[0],rettype,-1);
472+
}
473+
if (fdresult!=FUNCDETAIL_NORMAL)
474+
{
512475
/*
513476
* Oops. Time to die.
514477
*
@@ -1130,26 +1093,29 @@ func_select_candidate(int nargs,
11301093

11311094

11321095
/* func_get_detail()
1096+
*
11331097
* Find the named function in the system catalogs.
11341098
*
11351099
* Attempt to find the named function in the system catalogs with
11361100
*arguments exactly as specified, so that the normal case
11371101
*(exact match) is as quick as possible.
11381102
*
11391103
* If an exact match isn't found:
1140-
*1) get a vector of all possible input arg type arrays constructed
1104+
* 1) check for possible interpretation as a trivial type coercion
1105+
*2) get a vector of all possible input arg type arrays constructed
11411106
* from the superclasses of the original input arg types
1142-
*2) get a list of all possible argument type arrays to the function
1107+
*3) get a list of all possible argument type arrays to the function
11431108
* with given name and number of arguments
1144-
*3) for each input arg type array from vector #1:
1109+
*4) for each input arg type array from vector #1:
11451110
* a) find how many of the function arg type arrays from list #2
11461111
*it can be coerced to
11471112
* b) if the answer is one, we have our function
11481113
* c) if the answer is more than one, attempt to resolve the conflict
11491114
* d) if the answer is zero, try the next array from vector #1
11501115
*/
1151-
bool
1116+
FuncDetailCode
11521117
func_get_detail(char*funcname,
1118+
List*fargs,
11531119
intnargs,
11541120
Oid*argtypes,
11551121
Oid*funcid,/* return value */
@@ -1158,6 +1124,7 @@ func_get_detail(char *funcname,
11581124
Oid**true_typeids)/* return value */
11591125
{
11601126
HeapTupleftup;
1127+
CandidateListfunction_typeids;
11611128

11621129
/* attempt to find with arguments exactly as specified... */
11631130
ftup=SearchSysCache(PROCNAME,
@@ -1173,12 +1140,59 @@ func_get_detail(char *funcname,
11731140
}
11741141
else
11751142
{
1143+
/*
1144+
* If we didn't find an exact match, next consider the possibility
1145+
* that this is really a type-coercion request: a single-argument
1146+
* function call where the function name is a type name. If so,
1147+
* and if we can do the coercion trivially (no run-time function
1148+
* call needed), then go ahead and treat the "function call" as
1149+
* a coercion. This interpretation needs to be given higher
1150+
* priority than interpretations involving a type coercion followed
1151+
* by a function call, otherwise we can produce surprising results.
1152+
* For example, we want "text(varchar)" to be interpreted as a
1153+
* trivial coercion, not as "text(name(varchar))" which the code
1154+
* below this point is entirely capable of selecting.
1155+
*
1156+
* "Trivial" coercions are ones that involve binary-compatible
1157+
* types and ones that are coercing a previously-unknown-type
1158+
* literal constant to a specific type.
1159+
*
1160+
* NB: it's important that this code stays in sync with what
1161+
* coerce_type can do, because the caller will try to apply
1162+
* coerce_type if we return FUNCDETAIL_COERCION. If we return
1163+
* that result for something coerce_type can't handle, we'll
1164+
* cause infinite recursion between this module and coerce_type!
1165+
*/
1166+
if (nargs==1)
1167+
{
1168+
OidtargetType;
1169+
1170+
targetType=GetSysCacheOid(TYPENAME,
1171+
PointerGetDatum(funcname),
1172+
0,0,0);
1173+
if (OidIsValid(targetType))
1174+
{
1175+
OidsourceType=argtypes[0];
1176+
Node*arg1=lfirst(fargs);
1177+
1178+
if ((sourceType==UNKNOWNOID&&IsA(arg1,Const))||
1179+
sourceType==targetType||
1180+
IS_BINARY_COMPATIBLE(sourceType,targetType))
1181+
{
1182+
/* Yup, it's a type coercion */
1183+
*funcid=InvalidOid;
1184+
*rettype=targetType;
1185+
*retset= false;
1186+
*true_typeids=argtypes;
1187+
returnFUNCDETAIL_COERCION;
1188+
}
1189+
}
1190+
}
11761191

11771192
/*
11781193
* didn't find an exact match, so now try to match up
11791194
* candidates...
11801195
*/
1181-
CandidateListfunction_typeids;
11821196

11831197
function_typeids=func_get_candidates(funcname,nargs);
11841198

@@ -1268,9 +1282,10 @@ func_get_detail(char *funcname,
12681282
*rettype=pform->prorettype;
12691283
*retset=pform->proretset;
12701284
ReleaseSysCache(ftup);
1271-
returntrue;
1285+
returnFUNCDETAIL_NORMAL;
12721286
}
1273-
return false;
1287+
1288+
returnFUNCDETAIL_NOTFOUND;
12741289
}/* func_get_detail() */
12751290

12761291
/*

‎src/include/parser/parse_func.h

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $Id: parse_func.h,v 1.31 2001/05/19 00:33:20 momjian Exp $
10+
* $Id: parse_func.h,v 1.32 2001/10/04 22:06:46 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -38,16 +38,26 @@ typedef struct _CandidateList
3838
struct_CandidateList*next;
3939
}*CandidateList;
4040

41+
/* Result codes for func_get_detail */
42+
typedefenum
43+
{
44+
FUNCDETAIL_NOTFOUND,/* no suitable interpretation */
45+
FUNCDETAIL_NORMAL,/* found a matching function */
46+
FUNCDETAIL_COERCION/* it's a type coercion request */
47+
}FuncDetailCode;
48+
49+
4150
externNode*ParseNestedFuncOrColumn(ParseState*pstate,Attr*attr,
4251
intprecedence);
4352
externNode*ParseFuncOrColumn(ParseState*pstate,
4453
char*funcname,List*fargs,
4554
boolagg_star,boolagg_distinct,
4655
intprecedence);
4756

48-
externboolfunc_get_detail(char*funcname,intnargs,Oid*argtypes,
49-
Oid*funcid,Oid*rettype,
50-
bool*retset,Oid**true_typeids);
57+
externFuncDetailCodefunc_get_detail(char*funcname,List*fargs,
58+
intnargs,Oid*argtypes,
59+
Oid*funcid,Oid*rettype,
60+
bool*retset,Oid**true_typeids);
5161

5262
externbooltypeInheritsFrom(OidsubclassTypeId,OidsuperclassTypeId);
5363

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp