← Back to Overview

src/backend/executor/execExpr.c

Coverage: 37/37 lines (100.0%)
Total Lines
37
modified
Covered
37
100.0%
Uncovered
0
0.0%
Keyboard navigation
ExecInitExprRec() lines 919-2754
Modified Lines Coverage: 37/37 lines (100.0%)
LineHitsSourceCommit
919 - ExecInitExprRec(Expr *node, ExprState *state, -
920 - Datum *resv, bool *resnull) -
921 - { -
922 - ExprEvalStep scratch = {0}; -
923 - -
924 - /* Guard against stack overflow due to overly complex expressions */ -
925 - check_stack_depth(); -
926 - -
927 - /* Step's output location is always what the caller gave us */ -
928 - Assert(resv != NULL && resnull != NULL); -
929 - scratch.resvalue = resv; -
930 - scratch.resnull = resnull; -
931 - -
932 - /* cases should be ordered as they are in enum NodeTag */ -
933 - switch (nodeTag(node)) -
934 - { -
935 - case T_Var: -
936 - { -
937 - Var *variable = (Var *) node; -
938 - -
939 - if (variable->varattno == InvalidAttrNumber) -
940 - { -
941 - /* whole-row Var */ -
942 - ExecInitWholeRowVar(&scratch, variable, state); -
943 - } -
944 - else if (variable->varattno <= 0) -
945 - { -
946 - /* system column */ -
947 - scratch.d.var.attnum = variable->varattno; -
948 - scratch.d.var.vartype = variable->vartype; -
949 - scratch.d.var.varreturningtype = variable->varreturningtype; -
950 - switch (variable->varno) -
951 - { -
952 - case INNER_VAR: -
953 - scratch.opcode = EEOP_INNER_SYSVAR; -
954 - break; -
955 - case OUTER_VAR: -
956 - scratch.opcode = EEOP_OUTER_SYSVAR; -
957 - break; -
958 - -
959 - /* INDEX_VAR is handled by default case */ -
960 - -
961 - default: -
962 - switch (variable->varreturningtype) -
963 - { -
964 - case VAR_RETURNING_DEFAULT: -
965 - scratch.opcode = EEOP_SCAN_SYSVAR; -
966 - break; -
967 - case VAR_RETURNING_OLD: -
968 - scratch.opcode = EEOP_OLD_SYSVAR; -
969 - state->flags |= EEO_FLAG_HAS_OLD; -
970 - break; -
971 - case VAR_RETURNING_NEW: -
972 - scratch.opcode = EEOP_NEW_SYSVAR; -
973 - state->flags |= EEO_FLAG_HAS_NEW; -
974 - break; -
975 - } -
976 - break; -
977 - } -
978 - } -
979 - else -
980 - { -
981 - /* regular user column */ -
982 - scratch.d.var.attnum = variable->varattno - 1; -
983 - scratch.d.var.vartype = variable->vartype; -
984 - scratch.d.var.varreturningtype = variable->varreturningtype; -
985 - switch (variable->varno) -
986 - { -
987 - case INNER_VAR: -
988 - scratch.opcode = EEOP_INNER_VAR; -
989 - break; -
990 - case OUTER_VAR: -
991 - scratch.opcode = EEOP_OUTER_VAR; -
992 - break; -
993 - -
994 - /* INDEX_VAR is handled by default case */ -
995 - -
996 - default: -
997 - switch (variable->varreturningtype) -
998 - { -
999 - case VAR_RETURNING_DEFAULT: -
1000 - scratch.opcode = EEOP_SCAN_VAR; -
1001 - break; -
1002 - case VAR_RETURNING_OLD: -
1003 - scratch.opcode = EEOP_OLD_VAR; -
1004 - state->flags |= EEO_FLAG_HAS_OLD; -
1005 - break; -
1006 - case VAR_RETURNING_NEW: -
1007 - scratch.opcode = EEOP_NEW_VAR; -
1008 - state->flags |= EEO_FLAG_HAS_NEW; -
1009 - break; -
1010 - } -
1011 - break; -
1012 - } -
1013 - } -
1014 - -
1015 - ExprEvalPushStep(state, &scratch); -
1016 - break; -
1017 - } -
1018 - -
1019 - case T_Const: -
1020 - { -
1021 - Const *con = (Const *) node; -
1022 - -
1023 - scratch.opcode = EEOP_CONST; -
1024 - scratch.d.constval.value = con->constvalue; -
1025 - scratch.d.constval.isnull = con->constisnull; -
1026 - -
1027 - ExprEvalPushStep(state, &scratch); -
1028 - break; -
1029 - } -
1030 - -
1031 - case T_Param: -
1032 - { -
1033 - Param *param = (Param *) node; -
1034 - ParamListInfo params; -
1035 - -
1036 - switch (param->paramkind) -
1037 - { -
1038 - case PARAM_EXEC: -
1039 - scratch.opcode = EEOP_PARAM_EXEC; -
1040 - scratch.d.param.paramid = param->paramid; -
1041 - scratch.d.param.paramtype = param->paramtype; -
1042 - ExprEvalPushStep(state, &scratch); -
1043 - break; -
1044 - case PARAM_EXTERN: -
1045 - -
1046 - /* -
1047 - * If we have a relevant ParamCompileHook, use it; -
1048 - * otherwise compile a standard EEOP_PARAM_EXTERN -
1049 - * step. ext_params, if supplied, takes precedence -
1050 - * over info from the parent node's EState (if any). -
1051 - */ -
1052 - if (state->ext_params) -
1053 - params = state->ext_params; -
1054 - else if (state->parent && -
1055 - state->parent->state) -
1056 - params = state->parent->state->es_param_list_info; -
1057 - else -
1058 - params = NULL; -
1059 - if (params && params->paramCompile) -
1060 - { -
1061 - params->paramCompile(params, param, state, -
1062 - resv, resnull); -
1063 - } -
1064 - else -
1065 - { -
1066 - scratch.opcode = EEOP_PARAM_EXTERN; -
1067 - scratch.d.param.paramid = param->paramid; -
1068 - scratch.d.param.paramtype = param->paramtype; -
1069 - ExprEvalPushStep(state, &scratch); -
1070 - } -
1071 - break; -
1072 - default: -
1073 - elog(ERROR, "unrecognized paramkind: %d", -
1074 - (int) param->paramkind); -
1075 - break; -
1076 - } -
1077 - break; -
1078 - } -
1079 - -
1080 - case T_Aggref: -
1081 - { -
1082 - Aggref *aggref = (Aggref *) node; -
1083 - -
1084 - scratch.opcode = EEOP_AGGREF; -
1085 - scratch.d.aggref.aggno = aggref->aggno; -
1086 - -
1087 - if (state->parent && IsA(state->parent, AggState)) -
1088 - { -
1089 - AggState *aggstate = (AggState *) state->parent; -
1090 - -
1091 - aggstate->aggs = lappend(aggstate->aggs, aggref); -
1092 - } -
1093 - else -
1094 - { -
1095 - /* planner messed up */ -
1096 - elog(ERROR, "Aggref found in non-Agg plan node"); -
1097 - } -
1098 - -
1099 - ExprEvalPushStep(state, &scratch); -
1100 - break; -
1101 - } -
1102 - -
1103 - case T_GroupingFunc: -
1104 - { -
1105 - GroupingFunc *grp_node = (GroupingFunc *) node; -
1106 - Agg *agg; -
1107 - -
1108 - if (!state->parent || !IsA(state->parent, AggState) || -
1109 - !IsA(state->parent->plan, Agg)) -
1110 - elog(ERROR, "GroupingFunc found in non-Agg plan node"); -
1111 - -
1112 - scratch.opcode = EEOP_GROUPING_FUNC; -
1113 - -
1114 - agg = (Agg *) (state->parent->plan); -
1115 - -
1116 - if (agg->groupingSets) -
1117 - scratch.d.grouping_func.clauses = grp_node->cols; -
1118 - else -
1119 - scratch.d.grouping_func.clauses = NIL; -
1120 - -
1121 - ExprEvalPushStep(state, &scratch); -
1122 - break; -
1123 - } -
1124 - -
1125 - case T_WindowFunc: -
1126 - { -
1127 - WindowFunc *wfunc = (WindowFunc *) node; -
1128 - WindowFuncExprState *wfstate = makeNode(WindowFuncExprState); -
1129 - -
1130 - wfstate->wfunc = wfunc; -
1131 - -
1132 - if (state->parent && IsA(state->parent, WindowAggState)) -
1133 - { -
1134 - WindowAggState *winstate = (WindowAggState *) state->parent; -
1135 - int nfuncs; -
1136 - -
1137 - winstate->funcs = lappend(winstate->funcs, wfstate); -
1138 - nfuncs = ++winstate->numfuncs; -
1139 - if (wfunc->winagg) -
1140 - winstate->numaggs++; -
1141 - -
1142 - /* for now initialize agg using old style expressions */ -
1143 - wfstate->args = ExecInitExprList(wfunc->args, -
1144 - state->parent); -
1145 - wfstate->aggfilter = ExecInitExpr(wfunc->aggfilter, -
1146 - state->parent); -
1147 - -
1148 - /* -
1149 - * Complain if the windowfunc's arguments contain any -
1150 - * windowfuncs; nested window functions are semantically -
1151 - * nonsensical. (This should have been caught earlier, -
1152 - * but we defend against it here anyway.) -
1153 - */ -
1154 - if (nfuncs != winstate->numfuncs) -
1155 - ereport(ERROR, -
1156 - (errcode(ERRCODE_WINDOWING_ERROR), -
1157 - errmsg("window function calls cannot be nested"))); -
1158 - } -
1159 - else -
1160 - { -
1161 - /* planner messed up */ -
1162 - elog(ERROR, "WindowFunc found in non-WindowAgg plan node"); -
1163 - } -
1164 - -
1165 - scratch.opcode = EEOP_WINDOW_FUNC; -
1166 - scratch.d.window_func.wfstate = wfstate; -
1167 - ExprEvalPushStep(state, &scratch); -
1168 - break; -
1169 - } -
1170 - -
1171 - case T_MergeSupportFunc: -
1172 - { -
1173 - /* must be in a MERGE, else something messed up */ -
1174 - if (!state->parent || -
1175 - !IsA(state->parent, ModifyTableState) || -
1176 - ((ModifyTableState *) state->parent)->operation != CMD_MERGE) -
1177 - elog(ERROR, "MergeSupportFunc found in non-merge plan node"); -
1178 - -
1179 - scratch.opcode = EEOP_MERGE_SUPPORT_FUNC; -
1180 - ExprEvalPushStep(state, &scratch); -
1181 - break; -
1182 - } -
1183 - -
1184 - case T_SubscriptingRef: -
1185 - { -
1186 - SubscriptingRef *sbsref = (SubscriptingRef *) node; -
1187 - -
1188 - ExecInitSubscriptingRef(&scratch, sbsref, state, resv, resnull); -
1189 - break; -
1190 - } -
1191 - -
1192 1028 case T_RPRNavExpr: 24cfb8dRow pattern recognition patch (executor and commands).
1193 - { 24cfb8dRow pattern recognition patch (executor and commands).
1194 - /* 24cfb8dRow pattern recognition patch (executor and commands).
1195 - * RPR navigation functions (PREV/NEXT/FIRST/LAST) are 24cfb8dRow pattern recognition patch (executor and commands).
1196 - * compiled into EEOP_RPR_NAV_SET / EEOP_RPR_NAV_RESTORE 24cfb8dRow pattern recognition patch (executor and commands).
1197 - * opcodes instead of a normal function call. The SET opcode 24cfb8dRow pattern recognition patch (executor and commands).
1198 - * swaps ecxt_outertuple to the target row, the argument 24cfb8dRow pattern recognition patch (executor and commands).
1199 - * expression is compiled normally (reads from the swapped 24cfb8dRow pattern recognition patch (executor and commands).
1200 - * slot), and the RESTORE opcode restores the original slot. 24cfb8dRow pattern recognition patch (executor and commands).
1201 - * 24cfb8dRow pattern recognition patch (executor and commands).
1202 - * Default offset when offset_arg is NULL: PREV/NEXT: 1 24cfb8dRow pattern recognition patch (executor and commands).
1203 - * (physical offset from currentpos) FIRST/LAST: 0 (logical 24cfb8dRow pattern recognition patch (executor and commands).
1204 - * offset from match boundary) 24cfb8dRow pattern recognition patch (executor and commands).
1205 - */ 24cfb8dRow pattern recognition patch (executor and commands).
1206 1028 RPRNavExpr *nav = (RPRNavExpr *) node; 24cfb8dRow pattern recognition patch (executor and commands).
1207 1028 WindowAggState *winstate; 24cfb8dRow pattern recognition patch (executor and commands).
1208 - 24cfb8dRow pattern recognition patch (executor and commands).
1209 1028 Assert(state->parent && IsA(state->parent, WindowAggState)); 24cfb8dRow pattern recognition patch (executor and commands).
1210 1028 winstate = (WindowAggState *) state->parent; 24cfb8dRow pattern recognition patch (executor and commands).
1211 - 24cfb8dRow pattern recognition patch (executor and commands).
1212 - /* Emit SET opcode: swap slot to target row */ 24cfb8dRow pattern recognition patch (executor and commands).
1213 1028 scratch.opcode = EEOP_RPR_NAV_SET; 24cfb8dRow pattern recognition patch (executor and commands).
1214 1028 scratch.d.rpr_nav.winstate = winstate; 24cfb8dRow pattern recognition patch (executor and commands).
1215 1028 scratch.d.rpr_nav.kind = nav->kind; 24cfb8dRow pattern recognition patch (executor and commands).
1216 - 24cfb8dRow pattern recognition patch (executor and commands).
1217 1028 if (nav->kind >= RPR_NAV_PREV_FIRST) 24cfb8dRow pattern recognition patch (executor and commands).
1218 - { 24cfb8dRow pattern recognition patch (executor and commands).
1219 - /* 24cfb8dRow pattern recognition patch (executor and commands).
1220 - * Compound navigation: allocate array of 2 for inner [0] 24cfb8dRow pattern recognition patch (executor and commands).
1221 - * and outer [1] offsets. 24cfb8dRow pattern recognition patch (executor and commands).
1222 - */ 24cfb8dRow pattern recognition patch (executor and commands).
1223 136 Datum *offset_values = palloc_array(Datum, 2); 24cfb8dRow pattern recognition patch (executor and commands).
1224 136 bool *offset_isnulls = palloc_array(bool, 2); 24cfb8dRow pattern recognition patch (executor and commands).
1225 - 24cfb8dRow pattern recognition patch (executor and commands).
1226 - /* Inner offset (default 0 for FIRST/LAST) */ 24cfb8dRow pattern recognition patch (executor and commands).
1227 136 if (nav->offset_arg != NULL) 24cfb8dRow pattern recognition patch (executor and commands).
1228 64 ExecInitExprRec(nav->offset_arg, state, 24cfb8dRow pattern recognition patch (executor and commands).
1229 - &offset_values[0], &offset_isnulls[0]); 24cfb8dRow pattern recognition patch (executor and commands).
1230 - else 24cfb8dRow pattern recognition patch (executor and commands).
1231 - { 24cfb8dRow pattern recognition patch (executor and commands).
1232 72 offset_values[0] = Int64GetDatum(0); 24cfb8dRow pattern recognition patch (executor and commands).
1233 72 offset_isnulls[0] = false; 24cfb8dRow pattern recognition patch (executor and commands).
1234 - } 24cfb8dRow pattern recognition patch (executor and commands).
1235 - 24cfb8dRow pattern recognition patch (executor and commands).
1236 - /* Outer offset (default 1 for PREV/NEXT) */ 24cfb8dRow pattern recognition patch (executor and commands).
1237 136 if (nav->compound_offset_arg != NULL) 24cfb8dRow pattern recognition patch (executor and commands).
1238 128 ExecInitExprRec(nav->compound_offset_arg, state, 24cfb8dRow pattern recognition patch (executor and commands).
1239 - &offset_values[1], &offset_isnulls[1]); 24cfb8dRow pattern recognition patch (executor and commands).
1240 - else 24cfb8dRow pattern recognition patch (executor and commands).
1241 - { 24cfb8dRow pattern recognition patch (executor and commands).
1242 8 offset_values[1] = Int64GetDatum(1); 24cfb8dRow pattern recognition patch (executor and commands).
1243 8 offset_isnulls[1] = false; 24cfb8dRow pattern recognition patch (executor and commands).
1244 - } 24cfb8dRow pattern recognition patch (executor and commands).
1245 - 24cfb8dRow pattern recognition patch (executor and commands).
1246 136 scratch.d.rpr_nav.offset_value = offset_values; 24cfb8dRow pattern recognition patch (executor and commands).
1247 136 scratch.d.rpr_nav.offset_isnull = offset_isnulls; 24cfb8dRow pattern recognition patch (executor and commands).
1248 - } 24cfb8dRow pattern recognition patch (executor and commands).
1249 892 else if (nav->offset_arg != NULL) 24cfb8dRow pattern recognition patch (executor and commands).
1250 - { 24cfb8dRow pattern recognition patch (executor and commands).
1251 - /* Simple navigation with explicit offset */ 24cfb8dRow pattern recognition patch (executor and commands).
1252 192 Datum *offset_value = palloc_object(Datum); 24cfb8dRow pattern recognition patch (executor and commands).
1253 192 bool *offset_isnull = palloc_object(bool); 24cfb8dRow pattern recognition patch (executor and commands).
1254 - 24cfb8dRow pattern recognition patch (executor and commands).
1255 192 ExecInitExprRec(nav->offset_arg, state, 24cfb8dRow pattern recognition patch (executor and commands).
1256 - offset_value, offset_isnull); 24cfb8dRow pattern recognition patch (executor and commands).
1257 192 scratch.d.rpr_nav.offset_value = offset_value; 24cfb8dRow pattern recognition patch (executor and commands).
1258 192 scratch.d.rpr_nav.offset_isnull = offset_isnull; 24cfb8dRow pattern recognition patch (executor and commands).
1259 - } 24cfb8dRow pattern recognition patch (executor and commands).
1260 - else 24cfb8dRow pattern recognition patch (executor and commands).
1261 - { 24cfb8dRow pattern recognition patch (executor and commands).
1262 - /* Simple navigation with default offset */ 24cfb8dRow pattern recognition patch (executor and commands).
1263 700 scratch.d.rpr_nav.offset_value = NULL; 24cfb8dRow pattern recognition patch (executor and commands).
1264 700 scratch.d.rpr_nav.offset_isnull = NULL; 24cfb8dRow pattern recognition patch (executor and commands).
1265 - } 24cfb8dRow pattern recognition patch (executor and commands).
1266 - 24cfb8dRow pattern recognition patch (executor and commands).
1267 1028 ExprEvalPushStep(state, &scratch); 24cfb8dRow pattern recognition patch (executor and commands).
1268 - 24cfb8dRow pattern recognition patch (executor and commands).
1269 - /* Compile the argument expression normally */ 24cfb8dRow pattern recognition patch (executor and commands).
1270 1028 ExecInitExprRec(nav->arg, state, resv, resnull); 24cfb8dRow pattern recognition patch (executor and commands).
1271 - 24cfb8dRow pattern recognition patch (executor and commands).
1272 - /* Emit RESTORE opcode: restore original slot */ 24cfb8dRow pattern recognition patch (executor and commands).
1273 1028 scratch.opcode = EEOP_RPR_NAV_RESTORE; 24cfb8dRow pattern recognition patch (executor and commands).
1274 1028 scratch.resvalue = resv; 24cfb8dRow pattern recognition patch (executor and commands).
1275 1028 scratch.resnull = resnull; 24cfb8dRow pattern recognition patch (executor and commands).
1276 1028 scratch.d.rpr_nav.winstate = winstate; 24cfb8dRow pattern recognition patch (executor and commands).
1277 1028 get_typlenbyval(nav->resulttype, 24cfb8dRow pattern recognition patch (executor and commands).
1278 - &scratch.d.rpr_nav.resulttyplen, 24cfb8dRow pattern recognition patch (executor and commands).
1279 - &scratch.d.rpr_nav.resulttypbyval); 24cfb8dRow pattern recognition patch (executor and commands).
1280 1028 ExprEvalPushStep(state, &scratch); 24cfb8dRow pattern recognition patch (executor and commands).
1281 - break; 24cfb8dRow pattern recognition patch (executor and commands).
1282 - } 24cfb8dRow pattern recognition patch (executor and commands).
1283 - 24cfb8dRow pattern recognition patch (executor and commands).
1284 - case T_FuncExpr: -
1285 - { -
1286 - FuncExpr *func = (FuncExpr *) node; -
1287 - -
1288 - ExecInitFunc(&scratch, node, -
1289 - func->args, func->funcid, func->inputcollid, -
1290 - state); -
1291 - ExprEvalPushStep(state, &scratch); -
1292 - break; -
1293 - } -
1294 - -
1295 - case T_OpExpr: -
1296 - { -
1297 - OpExpr *op = (OpExpr *) node; -
1298 - -
1299 - ExecInitFunc(&scratch, node, -
1300 - op->args, op->opfuncid, op->inputcollid, -
1301 - state); -
1302 - ExprEvalPushStep(state, &scratch); -
1303 - break; -
1304 - } -
1305 - -
1306 - case T_DistinctExpr: -
1307 - { -
1308 - DistinctExpr *op = (DistinctExpr *) node; -
1309 - -
1310 - ExecInitFunc(&scratch, node, -
1311 - op->args, op->opfuncid, op->inputcollid, -
1312 - state); -
1313 - -
1314 - /* -
1315 - * Change opcode of call instruction to EEOP_DISTINCT. -
1316 - * -
1317 - * XXX: historically we've not called the function usage -
1318 - * pgstat infrastructure - that seems inconsistent given that -
1319 - * we do so for normal function *and* operator evaluation. If -
1320 - * we decided to do that here, we'd probably want separate -
1321 - * opcodes for FUSAGE or not. -
1322 - */ -
1323 - scratch.opcode = EEOP_DISTINCT; -
1324 - ExprEvalPushStep(state, &scratch); -
1325 - break; -
1326 - } -
1327 - -
1328 - case T_NullIfExpr: -
1329 - { -
1330 - NullIfExpr *op = (NullIfExpr *) node; -
1331 - -
1332 - ExecInitFunc(&scratch, node, -
1333 - op->args, op->opfuncid, op->inputcollid, -
1334 - state); -
1335 - -
1336 - /* -
1337 - * If first argument is of varlena type, we'll need to ensure -
1338 - * that the value passed to the comparison function is a -
1339 - * read-only pointer. -
1340 - */ -
1341 - scratch.d.func.make_ro = -
1342 - (get_typlen(exprType((Node *) linitial(op->args))) == -1); -
1343 - -
1344 - /* -
1345 - * Change opcode of call instruction to EEOP_NULLIF. -
1346 - * -
1347 - * XXX: historically we've not called the function usage -
1348 - * pgstat infrastructure - that seems inconsistent given that -
1349 - * we do so for normal function *and* operator evaluation. If -
1350 - * we decided to do that here, we'd probably want separate -
1351 - * opcodes for FUSAGE or not. -
1352 - */ -
1353 - scratch.opcode = EEOP_NULLIF; -
1354 - ExprEvalPushStep(state, &scratch); -
1355 - break; -
1356 - } -
1357 - -
1358 - case T_ScalarArrayOpExpr: -
1359 - { -
1360 - ScalarArrayOpExpr *opexpr = (ScalarArrayOpExpr *) node; -
1361 - Expr *scalararg; -
1362 - Expr *arrayarg; -
1363 - FmgrInfo *finfo; -
1364 - FunctionCallInfo fcinfo; -
1365 - AclResult aclresult; -
1366 - Oid cmpfuncid; -
1367 - -
1368 - /* -
1369 - * Select the correct comparison function. When we do hashed -
1370 - * NOT IN clauses, the opfuncid will be the inequality -
1371 - * comparison function and negfuncid will be set to equality. -
1372 - * We need to use the equality function for hash probes. -
1373 - */ -
1374 - if (OidIsValid(opexpr->negfuncid)) -
1375 - { -
1376 - Assert(OidIsValid(opexpr->hashfuncid)); -
1377 - cmpfuncid = opexpr->negfuncid; -
1378 - } -
1379 - else -
1380 - cmpfuncid = opexpr->opfuncid; -
1381 - -
1382 - Assert(list_length(opexpr->args) == 2); -
1383 - scalararg = (Expr *) linitial(opexpr->args); -
1384 - arrayarg = (Expr *) lsecond(opexpr->args); -
1385 - -
1386 - /* Check permission to call function */ -
1387 - aclresult = object_aclcheck(ProcedureRelationId, cmpfuncid, -
1388 - GetUserId(), -
1389 - ACL_EXECUTE); -
1390 - if (aclresult != ACLCHECK_OK) -
1391 - aclcheck_error(aclresult, OBJECT_FUNCTION, -
1392 - get_func_name(cmpfuncid)); -
1393 - InvokeFunctionExecuteHook(cmpfuncid); -
1394 - -
1395 - if (OidIsValid(opexpr->hashfuncid)) -
1396 - { -
1397 - aclresult = object_aclcheck(ProcedureRelationId, opexpr->hashfuncid, -
1398 - GetUserId(), -
1399 - ACL_EXECUTE); -
1400 - if (aclresult != ACLCHECK_OK) -
1401 - aclcheck_error(aclresult, OBJECT_FUNCTION, -
1402 - get_func_name(opexpr->hashfuncid)); -
1403 - InvokeFunctionExecuteHook(opexpr->hashfuncid); -
1404 - } -
1405 - -
1406 - /* Set up the primary fmgr lookup information */ -
1407 - finfo = palloc0_object(FmgrInfo); -
1408 - fcinfo = palloc0(SizeForFunctionCallInfo(2)); -
1409 - fmgr_info(cmpfuncid, finfo); -
1410 - fmgr_info_set_expr((Node *) node, finfo); -
1411 - InitFunctionCallInfoData(*fcinfo, finfo, 2, -
1412 - opexpr->inputcollid, NULL, NULL); -
1413 - -
1414 - /* -
1415 - * If hashfuncid is set, we create a EEOP_HASHED_SCALARARRAYOP -
1416 - * step instead of a EEOP_SCALARARRAYOP. This provides much -
1417 - * faster lookup performance than the normal linear search -
1418 - * when the number of items in the array is anything but very -
1419 - * small. -
1420 - */ -
1421 - if (OidIsValid(opexpr->hashfuncid)) -
1422 - { -
1423 - /* Evaluate scalar directly into left function argument */ -
1424 - ExecInitExprRec(scalararg, state, -
1425 - &fcinfo->args[0].value, &fcinfo->args[0].isnull); -
1426 - -
1427 - /* -
1428 - * Evaluate array argument into our return value. There's -
1429 - * no danger in that, because the return value is -
1430 - * guaranteed to be overwritten by -
1431 - * EEOP_HASHED_SCALARARRAYOP, and will not be passed to -
1432 - * any other expression. -
1433 - */ -
1434 - ExecInitExprRec(arrayarg, state, resv, resnull); -
1435 - -
1436 - /* And perform the operation */ -
1437 - scratch.opcode = EEOP_HASHED_SCALARARRAYOP; -
1438 - scratch.d.hashedscalararrayop.inclause = opexpr->useOr; -
1439 - scratch.d.hashedscalararrayop.finfo = finfo; -
1440 - scratch.d.hashedscalararrayop.fcinfo_data = fcinfo; -
1441 - scratch.d.hashedscalararrayop.saop = opexpr; -
1442 - -
1443 - -
1444 - ExprEvalPushStep(state, &scratch); -
1445 - } -
1446 - else -
1447 - { -
1448 - /* Evaluate scalar directly into left function argument */ -
1449 - ExecInitExprRec(scalararg, state, -
1450 - &fcinfo->args[0].value, -
1451 - &fcinfo->args[0].isnull); -
1452 - -
1453 - /* -
1454 - * Evaluate array argument into our return value. There's -
1455 - * no danger in that, because the return value is -
1456 - * guaranteed to be overwritten by EEOP_SCALARARRAYOP, and -
1457 - * will not be passed to any other expression. -
1458 - */ -
1459 - ExecInitExprRec(arrayarg, state, resv, resnull); -
1460 - -
1461 - /* And perform the operation */ -
1462 - scratch.opcode = EEOP_SCALARARRAYOP; -
1463 - scratch.d.scalararrayop.element_type = InvalidOid; -
1464 - scratch.d.scalararrayop.useOr = opexpr->useOr; -
1465 - scratch.d.scalararrayop.finfo = finfo; -
1466 - scratch.d.scalararrayop.fcinfo_data = fcinfo; -
1467 - scratch.d.scalararrayop.fn_addr = finfo->fn_addr; -
1468 - ExprEvalPushStep(state, &scratch); -
1469 - } -
1470 - break; -
1471 - } -
1472 - -
1473 - case T_BoolExpr: -
1474 - { -
1475 - BoolExpr *boolexpr = (BoolExpr *) node; -
1476 - int nargs = list_length(boolexpr->args); -
1477 - List *adjust_jumps = NIL; -
1478 - int off; -
1479 - ListCell *lc; -
1480 - -
1481 - /* allocate scratch memory used by all steps of AND/OR */ -
1482 - if (boolexpr->boolop != NOT_EXPR) -
1483 - scratch.d.boolexpr.anynull = palloc_object(bool); -
1484 - -
1485 - /* -
1486 - * For each argument evaluate the argument itself, then -
1487 - * perform the bool operation's appropriate handling. -
1488 - * -
1489 - * We can evaluate each argument into our result area, since -
1490 - * the short-circuiting logic means we only need to remember -
1491 - * previous NULL values. -
1492 - * -
1493 - * AND/OR is split into separate STEP_FIRST (one) / STEP (zero -
1494 - * or more) / STEP_LAST (one) steps, as each of those has to -
1495 - * perform different work. The FIRST/LAST split is valid -
1496 - * because AND/OR have at least two arguments. -
1497 - */ -
1498 - off = 0; -
1499 - foreach(lc, boolexpr->args) -
1500 - { -
1501 - Expr *arg = (Expr *) lfirst(lc); -
1502 - -
1503 - /* Evaluate argument into our output variable */ -
1504 - ExecInitExprRec(arg, state, resv, resnull); -
1505 - -
1506 - /* Perform the appropriate step type */ -
1507 - switch (boolexpr->boolop) -
1508 - { -
1509 - case AND_EXPR: -
1510 - Assert(nargs >= 2); -
1511 - -
1512 - if (off == 0) -
1513 - scratch.opcode = EEOP_BOOL_AND_STEP_FIRST; -
1514 - else if (off + 1 == nargs) -
1515 - scratch.opcode = EEOP_BOOL_AND_STEP_LAST; -
1516 - else -
1517 - scratch.opcode = EEOP_BOOL_AND_STEP; -
1518 - break; -
1519 - case OR_EXPR: -
1520 - Assert(nargs >= 2); -
1521 - -
1522 - if (off == 0) -
1523 - scratch.opcode = EEOP_BOOL_OR_STEP_FIRST; -
1524 - else if (off + 1 == nargs) -
1525 - scratch.opcode = EEOP_BOOL_OR_STEP_LAST; -
1526 - else -
1527 - scratch.opcode = EEOP_BOOL_OR_STEP; -
1528 - break; -
1529 - case NOT_EXPR: -
1530 - Assert(nargs == 1); -
1531 - -
1532 - scratch.opcode = EEOP_BOOL_NOT_STEP; -
1533 - break; -
1534 - default: -
1535 - elog(ERROR, "unrecognized boolop: %d", -
1536 - (int) boolexpr->boolop); -
1537 - break; -
1538 - } -
1539 - -
1540 - scratch.d.boolexpr.jumpdone = -1; -
1541 - ExprEvalPushStep(state, &scratch); -
1542 - adjust_jumps = lappend_int(adjust_jumps, -
1543 - state->steps_len - 1); -
1544 - off++; -
1545 - } -
1546 - -
1547 - /* adjust jump targets */ -
1548 - foreach(lc, adjust_jumps) -
1549 - { -
1550 - ExprEvalStep *as = &state->steps[lfirst_int(lc)]; -
1551 - -
1552 - Assert(as->d.boolexpr.jumpdone == -1); -
1553 - as->d.boolexpr.jumpdone = state->steps_len; -
1554 - } -
1555 - -
1556 - break; -
1557 - } -
1558 - -
1559 - case T_SubPlan: -
1560 - { -
1561 - SubPlan *subplan = (SubPlan *) node; -
1562 - -
1563 - /* -
1564 - * Real execution of a MULTIEXPR SubPlan has already been -
1565 - * done. What we have to do here is return a dummy NULL record -
1566 - * value in case this targetlist element is assigned -
1567 - * someplace. -
1568 - */ -
1569 - if (subplan->subLinkType == MULTIEXPR_SUBLINK) -
1570 - { -
1571 - scratch.opcode = EEOP_CONST; -
1572 - scratch.d.constval.value = (Datum) 0; -
1573 - scratch.d.constval.isnull = true; -
1574 - ExprEvalPushStep(state, &scratch); -
1575 - break; -
1576 - } -
1577 - -
1578 - ExecInitSubPlanExpr(subplan, state, resv, resnull); -
1579 - break; -
1580 - } -
1581 - -
1582 - case T_FieldSelect: -
1583 - { -
1584 - FieldSelect *fselect = (FieldSelect *) node; -
1585 - -
1586 - /* evaluate row/record argument into result area */ -
1587 - ExecInitExprRec(fselect->arg, state, resv, resnull); -
1588 - -
1589 - /* and extract field */ -
1590 - scratch.opcode = EEOP_FIELDSELECT; -
1591 - scratch.d.fieldselect.fieldnum = fselect->fieldnum; -
1592 - scratch.d.fieldselect.resulttype = fselect->resulttype; -
1593 - scratch.d.fieldselect.rowcache.cacheptr = NULL; -
1594 - -
1595 - ExprEvalPushStep(state, &scratch); -
1596 - break; -
1597 - } -
1598 - -
1599 - case T_FieldStore: -
1600 - { -
1601 - FieldStore *fstore = (FieldStore *) node; -
1602 - TupleDesc tupDesc; -
1603 - ExprEvalRowtypeCache *rowcachep; -
1604 - Datum *values; -
1605 - bool *nulls; -
1606 - int ncolumns; -
1607 - ListCell *l1, -
1608 - *l2; -
1609 - -
1610 - /* find out the number of columns in the composite type */ -
1611 - tupDesc = lookup_rowtype_tupdesc(fstore->resulttype, -1); -
1612 - ncolumns = tupDesc->natts; -
1613 - ReleaseTupleDesc(tupDesc); -
1614 - -
1615 - /* create workspace for column values */ -
1616 - values = palloc_array(Datum, ncolumns); -
1617 - nulls = palloc_array(bool, ncolumns); -
1618 - -
1619 - /* create shared composite-type-lookup cache struct */ -
1620 - rowcachep = palloc_object(ExprEvalRowtypeCache); -
1621 - rowcachep->cacheptr = NULL; -
1622 - -
1623 - /* emit code to evaluate the composite input value */ -
1624 - ExecInitExprRec(fstore->arg, state, resv, resnull); -
1625 - -
1626 - /* next, deform the input tuple into our workspace */ -
1627 - scratch.opcode = EEOP_FIELDSTORE_DEFORM; -
1628 - scratch.d.fieldstore.fstore = fstore; -
1629 - scratch.d.fieldstore.rowcache = rowcachep; -
1630 - scratch.d.fieldstore.values = values; -
1631 - scratch.d.fieldstore.nulls = nulls; -
1632 - scratch.d.fieldstore.ncolumns = ncolumns; -
1633 - ExprEvalPushStep(state, &scratch); -
1634 - -
1635 - /* evaluate new field values, store in workspace columns */ -
1636 - forboth(l1, fstore->newvals, l2, fstore->fieldnums) -
1637 - { -
1638 - Expr *e = (Expr *) lfirst(l1); -
1639 - AttrNumber fieldnum = lfirst_int(l2); -
1640 - Datum *save_innermost_caseval; -
1641 - bool *save_innermost_casenull; -
1642 - -
1643 - if (fieldnum <= 0 || fieldnum > ncolumns) -
1644 - elog(ERROR, "field number %d is out of range in FieldStore", -
1645 - fieldnum); -
1646 - -
1647 - /* -
1648 - * Use the CaseTestExpr mechanism to pass down the old -
1649 - * value of the field being replaced; this is needed in -
1650 - * case the newval is itself a FieldStore or -
1651 - * SubscriptingRef that has to obtain and modify the old -
1652 - * value. It's safe to reuse the CASE mechanism because -
1653 - * there cannot be a CASE between here and where the value -
1654 - * would be needed, and a field assignment can't be within -
1655 - * a CASE either. (So saving and restoring -
1656 - * innermost_caseval is just paranoia, but let's do it -
1657 - * anyway.) -
1658 - * -
1659 - * Another non-obvious point is that it's safe to use the -
1660 - * field's values[]/nulls[] entries as both the caseval -
1661 - * source and the result address for this subexpression. -
1662 - * That's okay only because (1) both FieldStore and -
1663 - * SubscriptingRef evaluate their arg or refexpr inputs -
1664 - * first, and (2) any such CaseTestExpr is directly the -
1665 - * arg or refexpr input. So any read of the caseval will -
1666 - * occur before there's a chance to overwrite it. Also, -
1667 - * if multiple entries in the newvals/fieldnums lists -
1668 - * target the same field, they'll effectively be applied -
1669 - * left-to-right which is what we want. -
1670 - */ -
1671 - save_innermost_caseval = state->innermost_caseval; -
1672 - save_innermost_casenull = state->innermost_casenull; -
1673 - state->innermost_caseval = &values[fieldnum - 1]; -
1674 - state->innermost_casenull = &nulls[fieldnum - 1]; -
1675 - -
1676 - ExecInitExprRec(e, state, -
1677 - &values[fieldnum - 1], -
1678 - &nulls[fieldnum - 1]); -
1679 - -
1680 - state->innermost_caseval = save_innermost_caseval; -
1681 - state->innermost_casenull = save_innermost_casenull; -
1682 - } -
1683 - -
1684 - /* finally, form result tuple */ -
1685 - scratch.opcode = EEOP_FIELDSTORE_FORM; -
1686 - scratch.d.fieldstore.fstore = fstore; -
1687 - scratch.d.fieldstore.rowcache = rowcachep; -
1688 - scratch.d.fieldstore.values = values; -
1689 - scratch.d.fieldstore.nulls = nulls; -
1690 - scratch.d.fieldstore.ncolumns = ncolumns; -
1691 - ExprEvalPushStep(state, &scratch); -
1692 - break; -
1693 - } -
1694 - -
1695 - case T_RelabelType: -
1696 - { -
1697 - /* relabel doesn't need to do anything at runtime */ -
1698 - RelabelType *relabel = (RelabelType *) node; -
1699 - -
1700 - ExecInitExprRec(relabel->arg, state, resv, resnull); -
1701 - break; -
1702 - } -
1703 - -
1704 - case T_CoerceViaIO: -
1705 - { -
1706 - CoerceViaIO *iocoerce = (CoerceViaIO *) node; -
1707 - Oid iofunc; -
1708 - bool typisvarlena; -
1709 - Oid typioparam; -
1710 - FunctionCallInfo fcinfo_in; -
1711 - -
1712 - /* evaluate argument into step's result area */ -
1713 - ExecInitExprRec(iocoerce->arg, state, resv, resnull); -
1714 - -
1715 - /* -
1716 - * Prepare both output and input function calls, to be -
1717 - * evaluated inside a single evaluation step for speed - this -
1718 - * can be a very common operation. -
1719 - * -
1720 - * We don't check permissions here as a type's input/output -
1721 - * function are assumed to be executable by everyone. -
1722 - */ -
1723 - if (state->escontext == NULL) -
1724 - scratch.opcode = EEOP_IOCOERCE; -
1725 - else -
1726 - scratch.opcode = EEOP_IOCOERCE_SAFE; -
1727 - -
1728 - /* lookup the source type's output function */ -
1729 - scratch.d.iocoerce.finfo_out = palloc0_object(FmgrInfo); -
1730 - scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfo(1)); -
1731 - -
1732 - getTypeOutputInfo(exprType((Node *) iocoerce->arg), -
1733 - &iofunc, &typisvarlena); -
1734 - fmgr_info(iofunc, scratch.d.iocoerce.finfo_out); -
1735 - fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_out); -
1736 - InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_out, -
1737 - scratch.d.iocoerce.finfo_out, -
1738 - 1, InvalidOid, NULL, NULL); -
1739 - -
1740 - /* lookup the result type's input function */ -
1741 - scratch.d.iocoerce.finfo_in = palloc0_object(FmgrInfo); -
1742 - scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfo(3)); -
1743 - -
1744 - getTypeInputInfo(iocoerce->resulttype, -
1745 - &iofunc, &typioparam); -
1746 - fmgr_info(iofunc, scratch.d.iocoerce.finfo_in); -
1747 - fmgr_info_set_expr((Node *) node, scratch.d.iocoerce.finfo_in); -
1748 - InitFunctionCallInfoData(*scratch.d.iocoerce.fcinfo_data_in, -
1749 - scratch.d.iocoerce.finfo_in, -
1750 - 3, InvalidOid, NULL, NULL); -
1751 - -
1752 - /* -
1753 - * We can preload the second and third arguments for the input -
1754 - * function, since they're constants. -
1755 - */ -
1756 - fcinfo_in = scratch.d.iocoerce.fcinfo_data_in; -
1757 - fcinfo_in->args[1].value = ObjectIdGetDatum(typioparam); -
1758 - fcinfo_in->args[1].isnull = false; -
1759 - fcinfo_in->args[2].value = Int32GetDatum(-1); -
1760 - fcinfo_in->args[2].isnull = false; -
1761 - -
1762 - fcinfo_in->context = (Node *) state->escontext; -
1763 - -
1764 - ExprEvalPushStep(state, &scratch); -
1765 - break; -
1766 - } -
1767 - -
1768 - case T_ArrayCoerceExpr: -
1769 - { -
1770 - ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; -
1771 - Oid resultelemtype; -
1772 - ExprState *elemstate; -
1773 - -
1774 - /* evaluate argument into step's result area */ -
1775 - ExecInitExprRec(acoerce->arg, state, resv, resnull); -
1776 - -
1777 - resultelemtype = get_element_type(acoerce->resulttype); -
1778 - if (!OidIsValid(resultelemtype)) -
1779 - ereport(ERROR, -
1780 - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), -
1781 - errmsg("target type is not an array"))); -
1782 - -
1783 - /* -
1784 - * Construct a sub-expression for the per-element expression; -
1785 - * but don't ready it until after we check it for triviality. -
1786 - * We assume it hasn't any Var references, but does have a -
1787 - * CaseTestExpr representing the source array element values. -
1788 - */ -
1789 - elemstate = makeNode(ExprState); -
1790 - elemstate->expr = acoerce->elemexpr; -
1791 - elemstate->parent = state->parent; -
1792 - elemstate->ext_params = state->ext_params; -
1793 - -
1794 - elemstate->innermost_caseval = palloc_object(Datum); -
1795 - elemstate->innermost_casenull = palloc_object(bool); -
1796 - -
1797 - ExecInitExprRec(acoerce->elemexpr, elemstate, -
1798 - &elemstate->resvalue, &elemstate->resnull); -
1799 - -
1800 - if (elemstate->steps_len == 1 && -
1801 - elemstate->steps[0].opcode == EEOP_CASE_TESTVAL) -
1802 - { -
1803 - /* Trivial, so we need no per-element work at runtime */ -
1804 - elemstate = NULL; -
1805 - } -
1806 - else -
1807 - { -
1808 - /* Not trivial, so append a DONE step */ -
1809 - scratch.opcode = EEOP_DONE_RETURN; -
1810 - ExprEvalPushStep(elemstate, &scratch); -
1811 - /* and ready the subexpression */ -
1812 - ExecReadyExpr(elemstate); -
1813 - } -
1814 - -
1815 - scratch.opcode = EEOP_ARRAYCOERCE; -
1816 - scratch.d.arraycoerce.elemexprstate = elemstate; -
1817 - scratch.d.arraycoerce.resultelemtype = resultelemtype; -
1818 - -
1819 - if (elemstate) -
1820 - { -
1821 - /* Set up workspace for array_map */ -
1822 - scratch.d.arraycoerce.amstate = palloc0_object(ArrayMapState); -
1823 - } -
1824 - else -
1825 - { -
1826 - /* Don't need workspace if there's no subexpression */ -
1827 - scratch.d.arraycoerce.amstate = NULL; -
1828 - } -
1829 - -
1830 - ExprEvalPushStep(state, &scratch); -
1831 - break; -
1832 - } -
1833 - -
1834 - case T_ConvertRowtypeExpr: -
1835 - { -
1836 - ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node; -
1837 - ExprEvalRowtypeCache *rowcachep; -
1838 - -
1839 - /* cache structs must be out-of-line for space reasons */ -
1840 - rowcachep = palloc(2 * sizeof(ExprEvalRowtypeCache)); -
1841 - rowcachep[0].cacheptr = NULL; -
1842 - rowcachep[1].cacheptr = NULL; -
1843 - -
1844 - /* evaluate argument into step's result area */ -
1845 - ExecInitExprRec(convert->arg, state, resv, resnull); -
1846 - -
1847 - /* and push conversion step */ -
1848 - scratch.opcode = EEOP_CONVERT_ROWTYPE; -
1849 - scratch.d.convert_rowtype.inputtype = -
1850 - exprType((Node *) convert->arg); -
1851 - scratch.d.convert_rowtype.outputtype = convert->resulttype; -
1852 - scratch.d.convert_rowtype.incache = &rowcachep[0]; -
1853 - scratch.d.convert_rowtype.outcache = &rowcachep[1]; -
1854 - scratch.d.convert_rowtype.map = NULL; -
1855 - -
1856 - ExprEvalPushStep(state, &scratch); -
1857 - break; -
1858 - } -
1859 - -
1860 - /* note that CaseWhen expressions are handled within this block */ -
1861 - case T_CaseExpr: -
1862 - { -
1863 - CaseExpr *caseExpr = (CaseExpr *) node; -
1864 - List *adjust_jumps = NIL; -
1865 - Datum *caseval = NULL; -
1866 - bool *casenull = NULL; -
1867 - ListCell *lc; -
1868 - -
1869 - /* -
1870 - * If there's a test expression, we have to evaluate it and -
1871 - * save the value where the CaseTestExpr placeholders can find -
1872 - * it. -
1873 - */ -
1874 - if (caseExpr->arg != NULL) -
1875 - { -
1876 - /* Evaluate testexpr into caseval/casenull workspace */ -
1877 - caseval = palloc_object(Datum); -
1878 - casenull = palloc_object(bool); -
1879 - -
1880 - ExecInitExprRec(caseExpr->arg, state, -
1881 - caseval, casenull); -
1882 - -
1883 - /* -
1884 - * Since value might be read multiple times, force to R/O -
1885 - * - but only if it could be an expanded datum. -
1886 - */ -
1887 - if (get_typlen(exprType((Node *) caseExpr->arg)) == -1) -
1888 - { -
1889 - /* change caseval in-place */ -
1890 - scratch.opcode = EEOP_MAKE_READONLY; -
1891 - scratch.resvalue = caseval; -
1892 - scratch.resnull = casenull; -
1893 - scratch.d.make_readonly.value = caseval; -
1894 - scratch.d.make_readonly.isnull = casenull; -
1895 - ExprEvalPushStep(state, &scratch); -
1896 - /* restore normal settings of scratch fields */ -
1897 - scratch.resvalue = resv; -
1898 - scratch.resnull = resnull; -
1899 - } -
1900 - } -
1901 - -
1902 - /* -
1903 - * Prepare to evaluate each of the WHEN clauses in turn; as -
1904 - * soon as one is true we return the value of the -
1905 - * corresponding THEN clause. If none are true then we return -
1906 - * the value of the ELSE clause, or NULL if there is none. -
1907 - */ -
1908 - foreach(lc, caseExpr->args) -
1909 - { -
1910 - CaseWhen *when = (CaseWhen *) lfirst(lc); -
1911 - Datum *save_innermost_caseval; -
1912 - bool *save_innermost_casenull; -
1913 - int whenstep; -
1914 - -
1915 - /* -
1916 - * Make testexpr result available to CaseTestExpr nodes -
1917 - * within the condition. We must save and restore prior -
1918 - * setting of innermost_caseval fields, in case this node -
1919 - * is itself within a larger CASE. -
1920 - * -
1921 - * If there's no test expression, we don't actually need -
1922 - * to save and restore these fields; but it's less code to -
1923 - * just do so unconditionally. -
1924 - */ -
1925 - save_innermost_caseval = state->innermost_caseval; -
1926 - save_innermost_casenull = state->innermost_casenull; -
1927 - state->innermost_caseval = caseval; -
1928 - state->innermost_casenull = casenull; -
1929 - -
1930 - /* evaluate condition into CASE's result variables */ -
1931 - ExecInitExprRec(when->expr, state, resv, resnull); -
1932 - -
1933 - state->innermost_caseval = save_innermost_caseval; -
1934 - state->innermost_casenull = save_innermost_casenull; -
1935 - -
1936 - /* If WHEN result isn't true, jump to next CASE arm */ -
1937 - scratch.opcode = EEOP_JUMP_IF_NOT_TRUE; -
1938 - scratch.d.jump.jumpdone = -1; /* computed later */ -
1939 - ExprEvalPushStep(state, &scratch); -
1940 - whenstep = state->steps_len - 1; -
1941 - -
1942 - /* -
1943 - * If WHEN result is true, evaluate THEN result, storing -
1944 - * it into the CASE's result variables. -
1945 - */ -
1946 - ExecInitExprRec(when->result, state, resv, resnull); -
1947 - -
1948 - /* Emit JUMP step to jump to end of CASE's code */ -
1949 - scratch.opcode = EEOP_JUMP; -
1950 - scratch.d.jump.jumpdone = -1; /* computed later */ -
1951 - ExprEvalPushStep(state, &scratch); -
1952 - -
1953 - /* -
1954 - * Don't know address for that jump yet, compute once the -
1955 - * whole CASE expression is built. -
1956 - */ -
1957 - adjust_jumps = lappend_int(adjust_jumps, -
1958 - state->steps_len - 1); -
1959 - -
1960 - /* -
1961 - * But we can set WHEN test's jump target now, to make it -
1962 - * jump to the next WHEN subexpression or the ELSE. -
1963 - */ -
1964 - state->steps[whenstep].d.jump.jumpdone = state->steps_len; -
1965 - } -
1966 - -
1967 - /* transformCaseExpr always adds a default */ -
1968 - Assert(caseExpr->defresult); -
1969 - -
1970 - /* evaluate ELSE expr into CASE's result variables */ -
1971 - ExecInitExprRec(caseExpr->defresult, state, -
1972 - resv, resnull); -
1973 - -
1974 - /* adjust jump targets */ -
1975 - foreach(lc, adjust_jumps) -
1976 - { -
1977 - ExprEvalStep *as = &state->steps[lfirst_int(lc)]; -
1978 - -
1979 - Assert(as->opcode == EEOP_JUMP); -
1980 - Assert(as->d.jump.jumpdone == -1); -
1981 - as->d.jump.jumpdone = state->steps_len; -
1982 - } -
1983 - -
1984 - break; -
1985 - } -
1986 - -
1987 - case T_CaseTestExpr: -
1988 - { -
1989 - /* -
1990 - * Read from location identified by innermost_caseval. Note -
1991 - * that innermost_caseval could be NULL, if this node isn't -
1992 - * actually within a CaseExpr, ArrayCoerceExpr, etc structure. -
1993 - * That can happen because some parts of the system abuse -
1994 - * CaseTestExpr to cause a read of a value externally supplied -
1995 - * in econtext->caseValue_datum. We'll take care of that by -
1996 - * generating a specialized operation. -
1997 - */ -
1998 - if (state->innermost_caseval == NULL) -
1999 - scratch.opcode = EEOP_CASE_TESTVAL_EXT; -
2000 - else -
2001 - { -
2002 - scratch.opcode = EEOP_CASE_TESTVAL; -
2003 - scratch.d.casetest.value = state->innermost_caseval; -
2004 - scratch.d.casetest.isnull = state->innermost_casenull; -
2005 - } -
2006 - ExprEvalPushStep(state, &scratch); -
2007 - break; -
2008 - } -
2009 - -
2010 - case T_ArrayExpr: -
2011 - { -
2012 - ArrayExpr *arrayexpr = (ArrayExpr *) node; -
2013 - int nelems = list_length(arrayexpr->elements); -
2014 - ListCell *lc; -
2015 - int elemoff; -
2016 - -
2017 - /* -
2018 - * Evaluate by computing each element, and then forming the -
2019 - * array. Elements are computed into scratch arrays -
2020 - * associated with the ARRAYEXPR step. -
2021 - */ -
2022 - scratch.opcode = EEOP_ARRAYEXPR; -
2023 - scratch.d.arrayexpr.elemvalues = -
2024 - palloc_array(Datum, nelems); -
2025 - scratch.d.arrayexpr.elemnulls = -
2026 - palloc_array(bool, nelems); -
2027 - scratch.d.arrayexpr.nelems = nelems; -
2028 - -
2029 - /* fill remaining fields of step */ -
2030 - scratch.d.arrayexpr.multidims = arrayexpr->multidims; -
2031 - scratch.d.arrayexpr.elemtype = arrayexpr->element_typeid; -
2032 - -
2033 - /* do one-time catalog lookup for type info */ -
2034 - get_typlenbyvalalign(arrayexpr->element_typeid, -
2035 - &scratch.d.arrayexpr.elemlength, -
2036 - &scratch.d.arrayexpr.elembyval, -
2037 - &scratch.d.arrayexpr.elemalign); -
2038 - -
2039 - /* prepare to evaluate all arguments */ -
2040 - elemoff = 0; -
2041 - foreach(lc, arrayexpr->elements) -
2042 - { -
2043 - Expr *e = (Expr *) lfirst(lc); -
2044 - -
2045 - ExecInitExprRec(e, state, -
2046 - &scratch.d.arrayexpr.elemvalues[elemoff], -
2047 - &scratch.d.arrayexpr.elemnulls[elemoff]); -
2048 - elemoff++; -
2049 - } -
2050 - -
2051 - /* and then collect all into an array */ -
2052 - ExprEvalPushStep(state, &scratch); -
2053 - break; -
2054 - } -
2055 - -
2056 - case T_RowExpr: -
2057 - { -
2058 - RowExpr *rowexpr = (RowExpr *) node; -
2059 - int nelems = list_length(rowexpr->args); -
2060 - TupleDesc tupdesc; -
2061 - int i; -
2062 - ListCell *l; -
2063 - -
2064 - /* Build tupdesc to describe result tuples */ -
2065 - if (rowexpr->row_typeid == RECORDOID) -
2066 - { -
2067 - /* generic record, use types of given expressions */ -
2068 - tupdesc = ExecTypeFromExprList(rowexpr->args); -
2069 - /* ... but adopt RowExpr's column aliases */ -
2070 - ExecTypeSetColNames(tupdesc, rowexpr->colnames); -
2071 - /* Bless the tupdesc so it can be looked up later */ -
2072 - BlessTupleDesc(tupdesc); -
2073 - } -
2074 - else -
2075 - { -
2076 - /* it's been cast to a named type, use that */ -
2077 - tupdesc = lookup_rowtype_tupdesc_copy(rowexpr->row_typeid, -1); -
2078 - } -
2079 - -
2080 - /* -
2081 - * In the named-type case, the tupdesc could have more columns -
2082 - * than are in the args list, since the type might have had -
2083 - * columns added since the ROW() was parsed. We want those -
2084 - * extra columns to go to nulls, so we make sure that the -
2085 - * workspace arrays are large enough and then initialize any -
2086 - * extra columns to read as NULLs. -
2087 - */ -
2088 - Assert(nelems <= tupdesc->natts); -
2089 - nelems = Max(nelems, tupdesc->natts); -
2090 - -
2091 - /* -
2092 - * Evaluate by first building datums for each field, and then -
2093 - * a final step forming the composite datum. -
2094 - */ -
2095 - scratch.opcode = EEOP_ROW; -
2096 - scratch.d.row.tupdesc = tupdesc; -
2097 - -
2098 - /* space for the individual field datums */ -
2099 - scratch.d.row.elemvalues = -
2100 - palloc_array(Datum, nelems); -
2101 - scratch.d.row.elemnulls = -
2102 - palloc_array(bool, nelems); -
2103 - /* as explained above, make sure any extra columns are null */ -
2104 - memset(scratch.d.row.elemnulls, true, sizeof(bool) * nelems); -
2105 - -
2106 - /* Set up evaluation, skipping any deleted columns */ -
2107 - i = 0; -
2108 - foreach(l, rowexpr->args) -
2109 - { -
2110 - Form_pg_attribute att = TupleDescAttr(tupdesc, i); -
2111 - Expr *e = (Expr *) lfirst(l); -
2112 - -
2113 - if (!att->attisdropped) -
2114 - { -
2115 - /* -
2116 - * Guard against ALTER COLUMN TYPE on rowtype since -
2117 - * the RowExpr was created. XXX should we check -
2118 - * typmod too? Not sure we can be sure it'll be the -
2119 - * same. -
2120 - */ -
2121 - if (exprType((Node *) e) != att->atttypid) -
2122 - ereport(ERROR, -
2123 - (errcode(ERRCODE_DATATYPE_MISMATCH), -
2124 - errmsg("ROW() column has type %s instead of type %s", -
2125 - format_type_be(exprType((Node *) e)), -
2126 - format_type_be(att->atttypid)))); -
2127 - } -
2128 - else -
2129 - { -
2130 - /* -
2131 - * Ignore original expression and insert a NULL. We -
2132 - * don't really care what type of NULL it is, so -
2133 - * always make an int4 NULL. -
2134 - */ -
2135 - e = (Expr *) makeNullConst(INT4OID, -1, InvalidOid); -
2136 - } -
2137 - -
2138 - /* Evaluate column expr into appropriate workspace slot */ -
2139 - ExecInitExprRec(e, state, -
2140 - &scratch.d.row.elemvalues[i], -
2141 - &scratch.d.row.elemnulls[i]); -
2142 - i++; -
2143 - } -
2144 - -
2145 - /* And finally build the row value */ -
2146 - ExprEvalPushStep(state, &scratch); -
2147 - break; -
2148 - } -
2149 - -
2150 - case T_RowCompareExpr: -
2151 - { -
2152 - RowCompareExpr *rcexpr = (RowCompareExpr *) node; -
2153 - int nopers = list_length(rcexpr->opnos); -
2154 - List *adjust_jumps = NIL; -
2155 - ListCell *l_left_expr, -
2156 - *l_right_expr, -
2157 - *l_opno, -
2158 - *l_opfamily, -
2159 - *l_inputcollid; -
2160 - ListCell *lc; -
2161 - -
2162 - /* -
2163 - * Iterate over each field, prepare comparisons. To handle -
2164 - * NULL results, prepare jumps to after the expression. If a -
2165 - * comparison yields a != 0 result, jump to the final step. -
2166 - */ -
2167 - Assert(list_length(rcexpr->largs) == nopers); -
2168 - Assert(list_length(rcexpr->rargs) == nopers); -
2169 - Assert(list_length(rcexpr->opfamilies) == nopers); -
2170 - Assert(list_length(rcexpr->inputcollids) == nopers); -
2171 - -
2172 - forfive(l_left_expr, rcexpr->largs, -
2173 - l_right_expr, rcexpr->rargs, -
2174 - l_opno, rcexpr->opnos, -
2175 - l_opfamily, rcexpr->opfamilies, -
2176 - l_inputcollid, rcexpr->inputcollids) -
2177 - { -
2178 - Expr *left_expr = (Expr *) lfirst(l_left_expr); -
2179 - Expr *right_expr = (Expr *) lfirst(l_right_expr); -
2180 - Oid opno = lfirst_oid(l_opno); -
2181 - Oid opfamily = lfirst_oid(l_opfamily); -
2182 - Oid inputcollid = lfirst_oid(l_inputcollid); -
2183 - int strategy; -
2184 - Oid lefttype; -
2185 - Oid righttype; -
2186 - Oid proc; -
2187 - FmgrInfo *finfo; -
2188 - FunctionCallInfo fcinfo; -
2189 - -
2190 - get_op_opfamily_properties(opno, opfamily, false, -
2191 - &strategy, -
2192 - &lefttype, -
2193 - &righttype); -
2194 - proc = get_opfamily_proc(opfamily, -
2195 - lefttype, -
2196 - righttype, -
2197 - BTORDER_PROC); -
2198 - if (!OidIsValid(proc)) -
2199 - elog(ERROR, "missing support function %d(%u,%u) in opfamily %u", -
2200 - BTORDER_PROC, lefttype, righttype, opfamily); -
2201 - -
2202 - /* Set up the primary fmgr lookup information */ -
2203 - finfo = palloc0_object(FmgrInfo); -
2204 - fcinfo = palloc0(SizeForFunctionCallInfo(2)); -
2205 - fmgr_info(proc, finfo); -
2206 - fmgr_info_set_expr((Node *) node, finfo); -
2207 - InitFunctionCallInfoData(*fcinfo, finfo, 2, -
2208 - inputcollid, NULL, NULL); -
2209 - -
2210 - /* -
2211 - * If we enforced permissions checks on index support -
2212 - * functions, we'd need to make a check here. But the -
2213 - * index support machinery doesn't do that, and thus -
2214 - * neither does this code. -
2215 - */ -
2216 - -
2217 - /* evaluate left and right args directly into fcinfo */ -
2218 - ExecInitExprRec(left_expr, state, -
2219 - &fcinfo->args[0].value, &fcinfo->args[0].isnull); -
2220 - ExecInitExprRec(right_expr, state, -
2221 - &fcinfo->args[1].value, &fcinfo->args[1].isnull); -
2222 - -
2223 - scratch.opcode = EEOP_ROWCOMPARE_STEP; -
2224 - scratch.d.rowcompare_step.finfo = finfo; -
2225 - scratch.d.rowcompare_step.fcinfo_data = fcinfo; -
2226 - scratch.d.rowcompare_step.fn_addr = finfo->fn_addr; -
2227 - /* jump targets filled below */ -
2228 - scratch.d.rowcompare_step.jumpnull = -1; -
2229 - scratch.d.rowcompare_step.jumpdone = -1; -
2230 - -
2231 - ExprEvalPushStep(state, &scratch); -
2232 - adjust_jumps = lappend_int(adjust_jumps, -
2233 - state->steps_len - 1); -
2234 - } -
2235 - -
2236 - /* -
2237 - * We could have a zero-column rowtype, in which case the rows -
2238 - * necessarily compare equal. -
2239 - */ -
2240 - if (nopers == 0) -
2241 - { -
2242 - scratch.opcode = EEOP_CONST; -
2243 - scratch.d.constval.value = Int32GetDatum(0); -
2244 - scratch.d.constval.isnull = false; -
2245 - ExprEvalPushStep(state, &scratch); -
2246 - } -
2247 - -
2248 - /* Finally, examine the last comparison result */ -
2249 - scratch.opcode = EEOP_ROWCOMPARE_FINAL; -
2250 - scratch.d.rowcompare_final.cmptype = rcexpr->cmptype; -
2251 - ExprEvalPushStep(state, &scratch); -
2252 - -
2253 - /* adjust jump targets */ -
2254 - foreach(lc, adjust_jumps) -
2255 - { -
2256 - ExprEvalStep *as = &state->steps[lfirst_int(lc)]; -
2257 - -
2258 - Assert(as->opcode == EEOP_ROWCOMPARE_STEP); -
2259 - Assert(as->d.rowcompare_step.jumpdone == -1); -
2260 - Assert(as->d.rowcompare_step.jumpnull == -1); -
2261 - -
2262 - /* jump to comparison evaluation */ -
2263 - as->d.rowcompare_step.jumpdone = state->steps_len - 1; -
2264 - /* jump to the following expression */ -
2265 - as->d.rowcompare_step.jumpnull = state->steps_len; -
2266 - } -
2267 - -
2268 - break; -
2269 - } -
2270 - -
2271 - case T_CoalesceExpr: -
2272 - { -
2273 - CoalesceExpr *coalesce = (CoalesceExpr *) node; -
2274 - List *adjust_jumps = NIL; -
2275 - ListCell *lc; -
2276 - -
2277 - /* We assume there's at least one arg */ -
2278 - Assert(coalesce->args != NIL); -
2279 - -
2280 - /* -
2281 - * Prepare evaluation of all coalesced arguments, after each -
2282 - * one push a step that short-circuits if not null. -
2283 - */ -
2284 - foreach(lc, coalesce->args) -
2285 - { -
2286 - Expr *e = (Expr *) lfirst(lc); -
2287 - -
2288 - /* evaluate argument, directly into result datum */ -
2289 - ExecInitExprRec(e, state, resv, resnull); -
2290 - -
2291 - /* if it's not null, skip to end of COALESCE expr */ -
2292 - scratch.opcode = EEOP_JUMP_IF_NOT_NULL; -
2293 - scratch.d.jump.jumpdone = -1; /* adjust later */ -
2294 - ExprEvalPushStep(state, &scratch); -
2295 - -
2296 - adjust_jumps = lappend_int(adjust_jumps, -
2297 - state->steps_len - 1); -
2298 - } -
2299 - -
2300 - /* -
2301 - * No need to add a constant NULL return - we only can get to -
2302 - * the end of the expression if a NULL already is being -
2303 - * returned. -
2304 - */ -
2305 - -
2306 - /* adjust jump targets */ -
2307 - foreach(lc, adjust_jumps) -
2308 - { -
2309 - ExprEvalStep *as = &state->steps[lfirst_int(lc)]; -
2310 - -
2311 - Assert(as->opcode == EEOP_JUMP_IF_NOT_NULL); -
2312 - Assert(as->d.jump.jumpdone == -1); -
2313 - as->d.jump.jumpdone = state->steps_len; -
2314 - } -
2315 - -
2316 - break; -
2317 - } -
2318 - -
2319 - case T_MinMaxExpr: -
2320 - { -
2321 - MinMaxExpr *minmaxexpr = (MinMaxExpr *) node; -
2322 - int nelems = list_length(minmaxexpr->args); -
2323 - TypeCacheEntry *typentry; -
2324 - FmgrInfo *finfo; -
2325 - FunctionCallInfo fcinfo; -
2326 - ListCell *lc; -
2327 - int off; -
2328 - -
2329 - /* Look up the btree comparison function for the datatype */ -
2330 - typentry = lookup_type_cache(minmaxexpr->minmaxtype, -
2331 - TYPECACHE_CMP_PROC); -
2332 - if (!OidIsValid(typentry->cmp_proc)) -
2333 - ereport(ERROR, -
2334 - (errcode(ERRCODE_UNDEFINED_FUNCTION), -
2335 - errmsg("could not identify a comparison function for type %s", -
2336 - format_type_be(minmaxexpr->minmaxtype)))); -
2337 - -
2338 - /* -
2339 - * If we enforced permissions checks on index support -
2340 - * functions, we'd need to make a check here. But the index -
2341 - * support machinery doesn't do that, and thus neither does -
2342 - * this code. -
2343 - */ -
2344 - -
2345 - /* Perform function lookup */ -
2346 - finfo = palloc0_object(FmgrInfo); -
2347 - fcinfo = palloc0(SizeForFunctionCallInfo(2)); -
2348 - fmgr_info(typentry->cmp_proc, finfo); -
2349 - fmgr_info_set_expr((Node *) node, finfo); -
2350 - InitFunctionCallInfoData(*fcinfo, finfo, 2, -
2351 - minmaxexpr->inputcollid, NULL, NULL); -
2352 - -
2353 - scratch.opcode = EEOP_MINMAX; -
2354 - /* allocate space to store arguments */ -
2355 - scratch.d.minmax.values = palloc_array(Datum, nelems); -
2356 - scratch.d.minmax.nulls = palloc_array(bool, nelems); -
2357 - scratch.d.minmax.nelems = nelems; -
2358 - -
2359 - scratch.d.minmax.op = minmaxexpr->op; -
2360 - scratch.d.minmax.finfo = finfo; -
2361 - scratch.d.minmax.fcinfo_data = fcinfo; -
2362 - -
2363 - /* evaluate expressions into minmax->values/nulls */ -
2364 - off = 0; -
2365 - foreach(lc, minmaxexpr->args) -
2366 - { -
2367 - Expr *e = (Expr *) lfirst(lc); -
2368 - -
2369 - ExecInitExprRec(e, state, -
2370 - &scratch.d.minmax.values[off], -
2371 - &scratch.d.minmax.nulls[off]); -
2372 - off++; -
2373 - } -
2374 - -
2375 - /* and push the final comparison */ -
2376 - ExprEvalPushStep(state, &scratch); -
2377 - break; -
2378 - } -
2379 - -
2380 - case T_SQLValueFunction: -
2381 - { -
2382 - SQLValueFunction *svf = (SQLValueFunction *) node; -
2383 - -
2384 - scratch.opcode = EEOP_SQLVALUEFUNCTION; -
2385 - scratch.d.sqlvaluefunction.svf = svf; -
2386 - -
2387 - ExprEvalPushStep(state, &scratch); -
2388 - break; -
2389 - } -
2390 - -
2391 - case T_XmlExpr: -
2392 - { -
2393 - XmlExpr *xexpr = (XmlExpr *) node; -
2394 - int nnamed = list_length(xexpr->named_args); -
2395 - int nargs = list_length(xexpr->args); -
2396 - int off; -
2397 - ListCell *arg; -
2398 - -
2399 - scratch.opcode = EEOP_XMLEXPR; -
2400 - scratch.d.xmlexpr.xexpr = xexpr; -
2401 - -
2402 - /* allocate space for storing all the arguments */ -
2403 - if (nnamed) -
2404 - { -
2405 - scratch.d.xmlexpr.named_argvalue = palloc_array(Datum, nnamed); -
2406 - scratch.d.xmlexpr.named_argnull = palloc_array(bool, nnamed); -
2407 - } -
2408 - else -
2409 - { -
2410 - scratch.d.xmlexpr.named_argvalue = NULL; -
2411 - scratch.d.xmlexpr.named_argnull = NULL; -
2412 - } -
2413 - -
2414 - if (nargs) -
2415 - { -
2416 - scratch.d.xmlexpr.argvalue = palloc_array(Datum, nargs); -
2417 - scratch.d.xmlexpr.argnull = palloc_array(bool, nargs); -
2418 - } -
2419 - else -
2420 - { -
2421 - scratch.d.xmlexpr.argvalue = NULL; -
2422 - scratch.d.xmlexpr.argnull = NULL; -
2423 - } -
2424 - -
2425 - /* prepare argument execution */ -
2426 - off = 0; -
2427 - foreach(arg, xexpr->named_args) -
2428 - { -
2429 - Expr *e = (Expr *) lfirst(arg); -
2430 - -
2431 - ExecInitExprRec(e, state, -
2432 - &scratch.d.xmlexpr.named_argvalue[off], -
2433 - &scratch.d.xmlexpr.named_argnull[off]); -
2434 - off++; -
2435 - } -
2436 - -
2437 - off = 0; -
2438 - foreach(arg, xexpr->args) -
2439 - { -
2440 - Expr *e = (Expr *) lfirst(arg); -
2441 - -
2442 - ExecInitExprRec(e, state, -
2443 - &scratch.d.xmlexpr.argvalue[off], -
2444 - &scratch.d.xmlexpr.argnull[off]); -
2445 - off++; -
2446 - } -
2447 - -
2448 - /* and evaluate the actual XML expression */ -
2449 - ExprEvalPushStep(state, &scratch); -
2450 - break; -
2451 - } -
2452 - -
2453 - case T_JsonValueExpr: -
2454 - { -
2455 - JsonValueExpr *jve = (JsonValueExpr *) node; -
2456 - -
2457 - Assert(jve->raw_expr != NULL); -
2458 - ExecInitExprRec(jve->raw_expr, state, resv, resnull); -
2459 - Assert(jve->formatted_expr != NULL); -
2460 - ExecInitExprRec(jve->formatted_expr, state, resv, resnull); -
2461 - break; -
2462 - } -
2463 - -
2464 - case T_JsonConstructorExpr: -
2465 - { -
2466 - JsonConstructorExpr *ctor = (JsonConstructorExpr *) node; -
2467 - List *args = ctor->args; -
2468 - ListCell *lc; -
2469 - int nargs = list_length(args); -
2470 - int argno = 0; -
2471 - -
2472 - if (ctor->func) -
2473 - { -
2474 - ExecInitExprRec(ctor->func, state, resv, resnull); -
2475 - } -
2476 - else if ((ctor->type == JSCTOR_JSON_PARSE && !ctor->unique) || -
2477 - ctor->type == JSCTOR_JSON_SERIALIZE) -
2478 - { -
2479 - /* Use the value of the first argument as result */ -
2480 - ExecInitExprRec(linitial(args), state, resv, resnull); -
2481 - } -
2482 - else -
2483 - { -
2484 - JsonConstructorExprState *jcstate; -
2485 - -
2486 - jcstate = palloc0_object(JsonConstructorExprState); -
2487 - -
2488 - scratch.opcode = EEOP_JSON_CONSTRUCTOR; -
2489 - scratch.d.json_constructor.jcstate = jcstate; -
2490 - -
2491 - jcstate->constructor = ctor; -
2492 - jcstate->arg_values = palloc_array(Datum, nargs); -
2493 - jcstate->arg_nulls = palloc_array(bool, nargs); -
2494 - jcstate->arg_types = palloc_array(Oid, nargs); -
2495 - jcstate->nargs = nargs; -
2496 - -
2497 - foreach(lc, args) -
2498 - { -
2499 - Expr *arg = (Expr *) lfirst(lc); -
2500 - -
2501 - jcstate->arg_types[argno] = exprType((Node *) arg); -
2502 - -
2503 - if (IsA(arg, Const)) -
2504 - { -
2505 - /* Don't evaluate const arguments every round */ -
2506 - Const *con = (Const *) arg; -
2507 - -
2508 - jcstate->arg_values[argno] = con->constvalue; -
2509 - jcstate->arg_nulls[argno] = con->constisnull; -
2510 - } -
2511 - else -
2512 - { -
2513 - ExecInitExprRec(arg, state, -
2514 - &jcstate->arg_values[argno], -
2515 - &jcstate->arg_nulls[argno]); -
2516 - } -
2517 - argno++; -
2518 - } -
2519 - -
2520 - /* prepare type cache for datum_to_json[b]() */ -
2521 - if (ctor->type == JSCTOR_JSON_SCALAR) -
2522 - { -
2523 - bool is_jsonb = -
2524 - ctor->returning->format->format_type == JS_FORMAT_JSONB; -
2525 - -
2526 - jcstate->arg_type_cache = -
2527 - palloc(sizeof(*jcstate->arg_type_cache) * nargs); -
2528 - -
2529 - for (int i = 0; i < nargs; i++) -
2530 - { -
2531 - JsonTypeCategory category; -
2532 - Oid outfuncid; -
2533 - Oid typid = jcstate->arg_types[i]; -
2534 - -
2535 - json_categorize_type(typid, is_jsonb, -
2536 - &category, &outfuncid); -
2537 - -
2538 - jcstate->arg_type_cache[i].outfuncid = outfuncid; -
2539 - jcstate->arg_type_cache[i].category = (int) category; -
2540 - } -
2541 - } -
2542 - -
2543 - ExprEvalPushStep(state, &scratch); -
2544 - } -
2545 - -
2546 - if (ctor->coercion) -
2547 - { -
2548 - Datum *innermost_caseval = state->innermost_caseval; -
2549 - bool *innermost_isnull = state->innermost_casenull; -
2550 - -
2551 - state->innermost_caseval = resv; -
2552 - state->innermost_casenull = resnull; -
2553 - -
2554 - ExecInitExprRec(ctor->coercion, state, resv, resnull); -
2555 - -
2556 - state->innermost_caseval = innermost_caseval; -
2557 - state->innermost_casenull = innermost_isnull; -
2558 - } -
2559 - } -
2560 - break; -
2561 - -
2562 - case T_JsonIsPredicate: -
2563 - { -
2564 - JsonIsPredicate *pred = (JsonIsPredicate *) node; -
2565 - -
2566 - ExecInitExprRec((Expr *) pred->expr, state, resv, resnull); -
2567 - -
2568 - scratch.opcode = EEOP_IS_JSON; -
2569 - scratch.d.is_json.pred = pred; -
2570 - -
2571 - ExprEvalPushStep(state, &scratch); -
2572 - break; -
2573 - } -
2574 - -
2575 - case T_JsonExpr: -
2576 - { -
2577 - JsonExpr *jsexpr = castNode(JsonExpr, node); -
2578 - -
2579 - /* -
2580 - * No need to initialize a full JsonExprState For -
2581 - * JSON_TABLE(), because the upstream caller tfuncFetchRows() -
2582 - * is only interested in the value of formatted_expr. -
2583 - */ -
2584 - if (jsexpr->op == JSON_TABLE_OP) -
2585 - ExecInitExprRec((Expr *) jsexpr->formatted_expr, state, -
2586 - resv, resnull); -
2587 - else -
2588 - ExecInitJsonExpr(jsexpr, state, resv, resnull, &scratch); -
2589 - break; -
2590 - } -
2591 - -
2592 - case T_NullTest: -
2593 - { -
2594 - NullTest *ntest = (NullTest *) node; -
2595 - -
2596 - if (ntest->nulltesttype == IS_NULL) -
2597 - { -
2598 - if (ntest->argisrow) -
2599 - scratch.opcode = EEOP_NULLTEST_ROWISNULL; -
2600 - else -
2601 - scratch.opcode = EEOP_NULLTEST_ISNULL; -
2602 - } -
2603 - else if (ntest->nulltesttype == IS_NOT_NULL) -
2604 - { -
2605 - if (ntest->argisrow) -
2606 - scratch.opcode = EEOP_NULLTEST_ROWISNOTNULL; -
2607 - else -
2608 - scratch.opcode = EEOP_NULLTEST_ISNOTNULL; -
2609 - } -
2610 - else -
2611 - { -
2612 - elog(ERROR, "unrecognized nulltesttype: %d", -
2613 - (int) ntest->nulltesttype); -
2614 - } -
2615 - /* initialize cache in case it's a row test */ -
2616 - scratch.d.nulltest_row.rowcache.cacheptr = NULL; -
2617 - -
2618 - /* first evaluate argument into result variable */ -
2619 - ExecInitExprRec(ntest->arg, state, -
2620 - resv, resnull); -
2621 - -
2622 - /* then push the test of that argument */ -
2623 - ExprEvalPushStep(state, &scratch); -
2624 - break; -
2625 - } -
2626 - -
2627 - case T_BooleanTest: -
2628 - { -
2629 - BooleanTest *btest = (BooleanTest *) node; -
2630 - -
2631 - /* -
2632 - * Evaluate argument, directly into result datum. That's ok, -
2633 - * because resv/resnull is definitely not used anywhere else, -
2634 - * and will get overwritten by the below EEOP_BOOLTEST_IS_* -
2635 - * step. -
2636 - */ -
2637 - ExecInitExprRec(btest->arg, state, resv, resnull); -
2638 - -
2639 - switch (btest->booltesttype) -
2640 - { -
2641 - case IS_TRUE: -
2642 - scratch.opcode = EEOP_BOOLTEST_IS_TRUE; -
2643 - break; -
2644 - case IS_NOT_TRUE: -
2645 - scratch.opcode = EEOP_BOOLTEST_IS_NOT_TRUE; -
2646 - break; -
2647 - case IS_FALSE: -
2648 - scratch.opcode = EEOP_BOOLTEST_IS_FALSE; -
2649 - break; -
2650 - case IS_NOT_FALSE: -
2651 - scratch.opcode = EEOP_BOOLTEST_IS_NOT_FALSE; -
2652 - break; -
2653 - case IS_UNKNOWN: -
2654 - /* Same as scalar IS NULL test */ -
2655 - scratch.opcode = EEOP_NULLTEST_ISNULL; -
2656 - break; -
2657 - case IS_NOT_UNKNOWN: -
2658 - /* Same as scalar IS NOT NULL test */ -
2659 - scratch.opcode = EEOP_NULLTEST_ISNOTNULL; -
2660 - break; -
2661 - default: -
2662 - elog(ERROR, "unrecognized booltesttype: %d", -
2663 - (int) btest->booltesttype); -
2664 - } -
2665 - -
2666 - ExprEvalPushStep(state, &scratch); -
2667 - break; -
2668 - } -
2669 - -
2670 - case T_CoerceToDomain: -
2671 - { -
2672 - CoerceToDomain *ctest = (CoerceToDomain *) node; -
2673 - -
2674 - ExecInitCoerceToDomain(&scratch, ctest, state, -
2675 - resv, resnull); -
2676 - break; -
2677 - } -
2678 - -
2679 - case T_CoerceToDomainValue: -
2680 - { -
2681 - /* -
2682 - * Read from location identified by innermost_domainval. Note -
2683 - * that innermost_domainval could be NULL, if we're compiling -
2684 - * a standalone domain check rather than one embedded in a -
2685 - * larger expression. In that case we must read from -
2686 - * econtext->domainValue_datum. We'll take care of that by -
2687 - * generating a specialized operation. -
2688 - */ -
2689 - if (state->innermost_domainval == NULL) -
2690 - scratch.opcode = EEOP_DOMAIN_TESTVAL_EXT; -
2691 - else -
2692 - { -
2693 - scratch.opcode = EEOP_DOMAIN_TESTVAL; -
2694 - /* we share instruction union variant with case testval */ -
2695 - scratch.d.casetest.value = state->innermost_domainval; -
2696 - scratch.d.casetest.isnull = state->innermost_domainnull; -
2697 - } -
2698 - ExprEvalPushStep(state, &scratch); -
2699 - break; -
2700 - } -
2701 - -
2702 - case T_CurrentOfExpr: -
2703 - { -
2704 - scratch.opcode = EEOP_CURRENTOFEXPR; -
2705 - ExprEvalPushStep(state, &scratch); -
2706 - break; -
2707 - } -
2708 - -
2709 - case T_NextValueExpr: -
2710 - { -
2711 - NextValueExpr *nve = (NextValueExpr *) node; -
2712 - -
2713 - scratch.opcode = EEOP_NEXTVALUEEXPR; -
2714 - scratch.d.nextvalueexpr.seqid = nve->seqid; -
2715 - scratch.d.nextvalueexpr.seqtypid = nve->typeId; -
2716 - -
2717 - ExprEvalPushStep(state, &scratch); -
2718 - break; -
2719 - } -
2720 - -
2721 - case T_ReturningExpr: -
2722 - { -
2723 - ReturningExpr *rexpr = (ReturningExpr *) node; -
2724 - int retstep; -
2725 - -
2726 - /* Skip expression evaluation if OLD/NEW row doesn't exist */ -
2727 - scratch.opcode = EEOP_RETURNINGEXPR; -
2728 - scratch.d.returningexpr.nullflag = rexpr->retold ? -
2729 - EEO_FLAG_OLD_IS_NULL : EEO_FLAG_NEW_IS_NULL; -
2730 - scratch.d.returningexpr.jumpdone = -1; /* set below */ -
2731 - ExprEvalPushStep(state, &scratch); -
2732 - retstep = state->steps_len - 1; -
2733 - -
2734 - /* Steps to evaluate expression to return */ -
2735 - ExecInitExprRec(rexpr->retexpr, state, resv, resnull); -
2736 - -
2737 - /* Jump target used if OLD/NEW row doesn't exist */ -
2738 - state->steps[retstep].d.returningexpr.jumpdone = state->steps_len; -
2739 - -
2740 - /* Update ExprState flags */ -
2741 - if (rexpr->retold) -
2742 - state->flags |= EEO_FLAG_HAS_OLD; -
2743 - else -
2744 - state->flags |= EEO_FLAG_HAS_NEW; -
2745 - -
2746 - break; -
2747 - } -
2748 - -
2749 - default: -
2750 - elog(ERROR, "unrecognized node type: %d", -
2751 - (int) nodeTag(node)); -
2752 - break; -
2753 - } -
2754 - } -