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,
7575static void op_error (ParseState * pstate ,List * op ,char oprkind ,
7676Oid arg1 ,Oid arg2 ,
7777FuncDetailCode fdresult ,int location );
78- static Expr * make_op_expr (ParseState * pstate ,Operator op ,
79- Node * ltree ,Node * rtree ,
80- Oid ltypeId ,Oid rtypeId );
8178static bool make_oper_cache_key (OprCacheKey * key ,List * opname ,
8279Oid ltypeId ,Oid rtypeId );
8380static Oid find_oper_cache_entry (OprCacheKey * key );
@@ -913,7 +910,13 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
913910Oid ltypeId ,
914911rtypeId ;
915912Operator tup ;
916- Expr * result ;
913+ Form_pg_operator opform ;
914+ Oid actual_arg_types [2 ];
915+ Oid declared_arg_types [2 ];
916+ int nargs ;
917+ List * args ;
918+ Oid rettype ;
919+ OpExpr * result ;
917920
918921/* Select the operator */
919922if (rtree == NULL )
@@ -938,12 +941,72 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
938941tup = 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+ else if (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
9441007ReleaseSysCache (tup );
9451008
946- return result ;
1009+ return ( Expr * ) result ;
9471010}
9481011
9491012/*
@@ -992,6 +1055,17 @@ make_scalar_array_op(ParseState *pstate, List *opname,
9921055tup = oper (pstate ,opname ,ltypeId ,rtypeId , false,location );
9931056opform = (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+
9951069args = list_make2 (ltree ,rtree );
9961070actual_arg_types [0 ]= ltypeId ;
9971071actual_arg_types [1 ]= rtypeId ;
@@ -1062,78 +1136,6 @@ make_scalar_array_op(ParseState *pstate, List *opname,
10621136return (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- static Expr *
1073- make_op_expr (ParseState * pstate ,Operator op ,
1074- Node * ltree ,Node * rtree ,
1075- Oid ltypeId ,Oid rtypeId )
1076- {
1077- Form_pg_operator opform = (Form_pg_operator )GETSTRUCT (op );
1078- Oid actual_arg_types [2 ];
1079- Oid declared_arg_types [2 ];
1080- int nargs ;
1081- List * args ;
1082- Oid rettype ;
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- else if (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