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

Commit1ad7611

Browse files
committed
Issue explicit error messages for attempts to use "shell" operators in
ordinary expressions. This probably doesn't catch every single casewhere you might get "cache lookup failed for function 0" for use of ashell operator, but it will catch most. Per bug #4120 from Pedro Gimeno.This patch incidentally folds make_op_expr() into its sole remainingcaller --- the alternative was to give it yet more arguments, whichdidn't seem an improvement.
1 parentff673f5 commit1ad7611

File tree

1 file changed

+81
-79
lines changed

1 file changed

+81
-79
lines changed

‎src/backend/parser/parse_oper.c

Lines changed: 81 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.101 2008/01/11 18:39:41 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_oper.c,v 1.102 2008/04/22 01:34:34 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -75,9 +75,6 @@ static const char *op_signature_string(List *op, char oprkind,
7575
staticvoidop_error(ParseState*pstate,List*op,charoprkind,
7676
Oidarg1,Oidarg2,
7777
FuncDetailCodefdresult,intlocation);
78-
staticExpr*make_op_expr(ParseState*pstate,Operatorop,
79-
Node*ltree,Node*rtree,
80-
OidltypeId,OidrtypeId);
8178
staticboolmake_oper_cache_key(OprCacheKey*key,List*opname,
8279
OidltypeId,OidrtypeId);
8380
staticOidfind_oper_cache_entry(OprCacheKey*key);
@@ -913,7 +910,13 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
913910
OidltypeId,
914911
rtypeId;
915912
Operatortup;
916-
Expr*result;
913+
Form_pg_operatoropform;
914+
Oidactual_arg_types[2];
915+
Oiddeclared_arg_types[2];
916+
intnargs;
917+
List*args;
918+
Oidrettype;
919+
OpExpr*result;
917920

918921
/* Select the operator */
919922
if (rtree==NULL)
@@ -938,12 +941,72 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
938941
tup=oper(pstate,opname,ltypeId,rtypeId, false,location);
939942
}
940943

944+
opform= (Form_pg_operator)GETSTRUCT(tup);
945+
946+
/* Check it's not a shell */
947+
if (!RegProcedureIsValid(opform->oprcode))
948+
ereport(ERROR,
949+
(errcode(ERRCODE_UNDEFINED_FUNCTION),
950+
errmsg("operator is only a shell: %s",
951+
op_signature_string(opname,
952+
opform->oprkind,
953+
opform->oprleft,
954+
opform->oprright)),
955+
parser_errposition(pstate,location)));
956+
941957
/* Do typecasting and build the expression tree */
942-
result=make_op_expr(pstate,tup,ltree,rtree,ltypeId,rtypeId);
958+
if (rtree==NULL)
959+
{
960+
/* right operator */
961+
args=list_make1(ltree);
962+
actual_arg_types[0]=ltypeId;
963+
declared_arg_types[0]=opform->oprleft;
964+
nargs=1;
965+
}
966+
elseif (ltree==NULL)
967+
{
968+
/* left operator */
969+
args=list_make1(rtree);
970+
actual_arg_types[0]=rtypeId;
971+
declared_arg_types[0]=opform->oprright;
972+
nargs=1;
973+
}
974+
else
975+
{
976+
/* otherwise, binary operator */
977+
args=list_make2(ltree,rtree);
978+
actual_arg_types[0]=ltypeId;
979+
actual_arg_types[1]=rtypeId;
980+
declared_arg_types[0]=opform->oprleft;
981+
declared_arg_types[1]=opform->oprright;
982+
nargs=2;
983+
}
984+
985+
/*
986+
* enforce consistency with polymorphic argument and return types,
987+
* possibly adjusting return type or declared_arg_types (which will be
988+
* used as the cast destination by make_fn_arguments)
989+
*/
990+
rettype=enforce_generic_type_consistency(actual_arg_types,
991+
declared_arg_types,
992+
nargs,
993+
opform->oprresult,
994+
false);
995+
996+
/* perform the necessary typecasting of arguments */
997+
make_fn_arguments(pstate,args,actual_arg_types,declared_arg_types);
998+
999+
/* and build the expression node */
1000+
result=makeNode(OpExpr);
1001+
result->opno=oprid(tup);
1002+
result->opfuncid=opform->oprcode;
1003+
result->opresulttype=rettype;
1004+
result->opretset=get_func_retset(opform->oprcode);
1005+
result->args=args;
9431006

9441007
ReleaseSysCache(tup);
9451008

946-
returnresult;
1009+
return(Expr*)result;
9471010
}
9481011

9491012
/*
@@ -992,6 +1055,17 @@ make_scalar_array_op(ParseState *pstate, List *opname,
9921055
tup=oper(pstate,opname,ltypeId,rtypeId, false,location);
9931056
opform= (Form_pg_operator)GETSTRUCT(tup);
9941057

1058+
/* Check it's not a shell */
1059+
if (!RegProcedureIsValid(opform->oprcode))
1060+
ereport(ERROR,
1061+
(errcode(ERRCODE_UNDEFINED_FUNCTION),
1062+
errmsg("operator is only a shell: %s",
1063+
op_signature_string(opname,
1064+
opform->oprkind,
1065+
opform->oprleft,
1066+
opform->oprright)),
1067+
parser_errposition(pstate,location)));
1068+
9951069
args=list_make2(ltree,rtree);
9961070
actual_arg_types[0]=ltypeId;
9971071
actual_arg_types[1]=rtypeId;
@@ -1062,78 +1136,6 @@ make_scalar_array_op(ParseState *pstate, List *opname,
10621136
return (Expr*)result;
10631137
}
10641138

1065-
/*
1066-
* make_op_expr()
1067-
*Build operator expression using an already-looked-up operator.
1068-
*
1069-
* As with coerce_type, pstate may be NULL if no special unknown-Param
1070-
* processing is wanted.
1071-
*/
1072-
staticExpr*
1073-
make_op_expr(ParseState*pstate,Operatorop,
1074-
Node*ltree,Node*rtree,
1075-
OidltypeId,OidrtypeId)
1076-
{
1077-
Form_pg_operatoropform= (Form_pg_operator)GETSTRUCT(op);
1078-
Oidactual_arg_types[2];
1079-
Oiddeclared_arg_types[2];
1080-
intnargs;
1081-
List*args;
1082-
Oidrettype;
1083-
OpExpr*result;
1084-
1085-
if (rtree==NULL)
1086-
{
1087-
/* right operator */
1088-
args=list_make1(ltree);
1089-
actual_arg_types[0]=ltypeId;
1090-
declared_arg_types[0]=opform->oprleft;
1091-
nargs=1;
1092-
}
1093-
elseif (ltree==NULL)
1094-
{
1095-
/* left operator */
1096-
args=list_make1(rtree);
1097-
actual_arg_types[0]=rtypeId;
1098-
declared_arg_types[0]=opform->oprright;
1099-
nargs=1;
1100-
}
1101-
else
1102-
{
1103-
/* otherwise, binary operator */
1104-
args=list_make2(ltree,rtree);
1105-
actual_arg_types[0]=ltypeId;
1106-
actual_arg_types[1]=rtypeId;
1107-
declared_arg_types[0]=opform->oprleft;
1108-
declared_arg_types[1]=opform->oprright;
1109-
nargs=2;
1110-
}
1111-
1112-
/*
1113-
* enforce consistency with polymorphic argument and return types,
1114-
* possibly adjusting return type or declared_arg_types (which will be
1115-
* used as the cast destination by make_fn_arguments)
1116-
*/
1117-
rettype=enforce_generic_type_consistency(actual_arg_types,
1118-
declared_arg_types,
1119-
nargs,
1120-
opform->oprresult,
1121-
false);
1122-
1123-
/* perform the necessary typecasting of arguments */
1124-
make_fn_arguments(pstate,args,actual_arg_types,declared_arg_types);
1125-
1126-
/* and build the expression node */
1127-
result=makeNode(OpExpr);
1128-
result->opno=oprid(op);
1129-
result->opfuncid=opform->oprcode;
1130-
result->opresulttype=rettype;
1131-
result->opretset=get_func_retset(opform->oprcode);
1132-
result->args=args;
1133-
1134-
return (Expr*)result;
1135-
}
1136-
11371139

11381140
/*
11391141
* Lookaside cache to speed operator lookup. Possibly this should be in

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp