8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -75,9 +75,6 @@ static const char *op_signature_string(List *op, char oprkind,
75
75
static void op_error (ParseState * pstate , List * op , char oprkind ,
76
76
Oid arg1 , Oid arg2 ,
77
77
FuncDetailCode fdresult , int location );
78
- static Expr * make_op_expr (ParseState * pstate , Operator op ,
79
- Node * ltree , Node * rtree ,
80
- Oid ltypeId , Oid rtypeId );
81
78
static bool make_oper_cache_key (OprCacheKey * key , List * opname ,
82
79
Oid ltypeId , Oid rtypeId );
83
80
static Oid find_oper_cache_entry (OprCacheKey * key );
@@ -913,7 +910,13 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
913
910
Oid ltypeId ,
914
911
rtypeId ;
915
912
Operator 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 ;
917
920
918
921
/* Select the operator */
919
922
if (rtree == NULL )
@@ -938,12 +941,72 @@ make_op(ParseState *pstate, List *opname, Node *ltree, Node *rtree,
938
941
tup = oper (pstate , opname , ltypeId , rtypeId , false, location );
939
942
}
940
943
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
+
941
957
/* 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 ;
943
1006
944
1007
ReleaseSysCache (tup );
945
1008
946
- return result ;
1009
+ return ( Expr * ) result ;
947
1010
}
948
1011
949
1012
/*
@@ -992,6 +1055,17 @@ make_scalar_array_op(ParseState *pstate, List *opname,
992
1055
tup = oper (pstate , opname , ltypeId , rtypeId , false, location );
993
1056
opform = (Form_pg_operator ) GETSTRUCT (tup );
994
1057
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
+
995
1069
args = list_make2 (ltree , rtree );
996
1070
actual_arg_types [0 ] = ltypeId ;
997
1071
actual_arg_types [1 ] = rtypeId ;
@@ -1062,78 +1136,6 @@ make_scalar_array_op(ParseState *pstate, List *opname,
1062
1136
return (Expr * ) result ;
1063
1137
}
1064
1138
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
-
1137
1139
1138
1140
/*
1139
1141
* Lookaside cache to speed operator lookup. Possibly this should be in
0 commit comments