已合并
fix: 修复 EXPLAIN VERBOSE 反解析被优化掉的 RECORD 子查询时报错 #9621
zjj_sc创建于 8月24日
fix: 修复 EXPLAIN VERBOSE 反解析被优化掉的 RECORD 子查询时报错 #9621
已合并
共 5 个文件变更+49-16
| @@ -9312,19 +9312,23 @@ static const char* get_name_for_var_field(Var* var, int fieldno, int levelsup, d | |||
| 9312 | /* | 9312 | /* |
| 9313 | * We're deparsing a Plan tree so we don't have complete | 9313 | * We're deparsing a Plan tree so we don't have complete |
| 9314 | * RTE entries (in particular, rte->subquery is NULL). But | 9314 | * RTE entries (in particular, rte->subquery is NULL). But |
| 9315 | - * the only place we'd see a Var directly referencing a | 9315 | + * the only place we'd normally see a Var directly |
| 9316 | - * SUBQUERY RTE is in a SubqueryScan plan node, and we can | 9316 | + * referencing a SUBQUERY RTE is in a SubqueryScan plan |
| 9317 | - * look into the child plan's tlist instead. | 9317 | + * node, and we can look into the child plan's tlist |
| 9318 | + * instead. An exception occurs if the subquery was proven | ||
| 9319 | + * empty and optimized away: then we'd find such a Var in | ||
| 9320 | + * a childless Result node, and there's nothing in the plan | ||
| 9321 | + * tree that would let us figure out what it had originally | ||
| 9322 | + * referenced. In that case, fall back on printing "fN", | ||
| 9323 | + * analogously to the default column names for RowExprs. | ||
| 9318 | */ | 9324 | */ |
| 9319 | TargetEntry* tle = NULL; | 9325 | TargetEntry* tle = NULL; |
| 9320 | deparse_namespace save_dpns; | 9326 | deparse_namespace save_dpns; |
| 9321 | const char* result = NULL; | 9327 | const char* result = NULL; |
| 9322 | 9328 | ||
| 9323 | - if (dpns->inner_planstate == NULL) | 9329 | + if (dpns->inner_planstate == NULL) { |
| 9324 | - ereport(ERROR, | 9330 | + return psprintf("f%d", fieldno); |
| 9325 | - (errmodule(MOD_OPT), | 9331 | + } |
| 9326 | - (errcode(ERRCODE_UNEXPECTED_NODE_STATE), | ||
| 9327 | - errmsg("failed to find plan for subquery %s", rte->eref->aliasname)))); | ||
| 9328 | tle = get_tle_by_resno(dpns->inner_tlist, attnum); | 9332 | tle = get_tle_by_resno(dpns->inner_tlist, attnum); |
| 9329 | if (tle == NULL) | 9333 | if (tle == NULL) |
| 9330 | ereport(ERROR, | 9334 | ereport(ERROR, |
| @@ -9427,19 +9431,19 @@ static const char* get_name_for_var_field(Var* var, int fieldno, int levelsup, d | |||
| 9427 | } else { | 9431 | } else { |
| 9428 | /* | 9432 | /* |
| 9429 | * We're deparsing a Plan tree so we don't have a CTE | 9433 | * We're deparsing a Plan tree so we don't have a CTE |
| 9430 | - * list. But the only place we'd see a Var directly | 9434 | + * list. But the only place we'd normally see a Var |
| 9431 | - * referencing a CTE RTE is in a CteScan plan node, and we | 9435 | + * directly referencing a CTE RTE is in a CteScan plan |
| 9432 | - * can look into the subplan's tlist instead. | 9436 | + * node, and we can look into the subplan's tlist instead. |
| 9437 | + * As above, this can fail if the CTE has been proven | ||
| 9438 | + * empty, in which case fall back to "fN". | ||
| 9433 | */ | 9439 | */ |
| 9434 | TargetEntry* tle = NULL; | 9440 | TargetEntry* tle = NULL; |
| 9435 | deparse_namespace save_dpns; | 9441 | deparse_namespace save_dpns; |
| 9436 | const char* result = NULL; | 9442 | const char* result = NULL; |
| 9437 | 9443 | ||
| 9438 | - if (dpns->inner_planstate == NULL) | 9444 | + if (dpns->inner_planstate == NULL) { |
| 9439 | - ereport(ERROR, | 9445 | + return psprintf("f%d", fieldno); |
| 9440 | - (errmodule(MOD_OPT), | 9446 | + } |
| 9441 | - (errcode(ERRCODE_UNEXPECTED_NODE_STATE), | ||
| 9442 | - errmsg("failed to find plan for CTE %s", rte->eref->aliasname)))); | ||
| 9443 | tle = get_tle_by_resno(dpns->inner_tlist, attnum); | 9447 | tle = get_tle_by_resno(dpns->inner_tlist, attnum); |
| 9444 | if (tle == NULL) | 9448 | if (tle == NULL) |
| 9445 | ereport(ERROR, | 9449 | ereport(ERROR, |
| @@ -0,0 +1,14 @@ | |||
| 1 | +-- | ||
| 2 | +-- Check deparsing of a RECORD field when its subquery plan was optimized | ||
| 3 | +-- away as a proven-dummy relation (PostgreSQL bug #18576). | ||
| 4 | +-- | ||
| 5 | +\pset format unaligned | ||
| 6 | +explain (verbose, costs off) | ||
| 7 | +select ordinal_position | ||
| 8 | +from information_schema.parameters | ||
| 9 | +where specific_name = null; | ||
| 10 | +QUERY PLAN | ||
| 11 | +Result | ||
| 12 | + Output: ((ss.x).f2)::information_schema.cardinal_number | ||
| 13 | + One-Time Filter: false | ||
| 14 | +(3 rows) | ||
| @@ -829,3 +829,6 @@ test: wlm_memory_trace | |||
| 829 | 829 | ||
| 830 | # test remotetype=coordinator trust bypass security | 830 | # test remotetype=coordinator trust bypass security |
| 831 | test: remotetype_trust_security | 831 | test: remotetype_trust_security |
| 832 | + | ||
| 833 | +# RECORD field deparsing for proven-dummy subqueries | ||
| 834 | +test: ruleutils_record | ||
| @@ -1191,3 +1191,6 @@ test: remotetype_trust_security | |||
| 1191 | 1191 | ||
| 1192 | # test create force view | 1192 | # test create force view |
| 1193 | test: create_force_view | 1193 | test: create_force_view |
| 1194 | + | ||
| 1195 | +# RECORD field deparsing for proven-dummy subqueries | ||
| 1196 | +test: ruleutils_record | ||
| @@ -0,0 +1,9 @@ | |||
| 1 | +-- | ||
| 2 | +-- Check deparsing of a RECORD field when its subquery plan was optimized | ||
| 3 | +-- away as a proven-dummy relation (PostgreSQL bug #18576). | ||
| 4 | +-- | ||
| 5 | +\pset format unaligned | ||
| 6 | +explain (verbose, costs off) | ||
| 7 | +select ordinal_position | ||
| 8 | +from information_schema.parameters | ||
| 9 | +where specific_name = null; | ||
【检视意见】 这个用例加到src/test/regress/parallel_schedule0A、0B、0C其中一个,目前加到这俩都不会在门禁上跑 【修改建议】 加到parallel_schedule0A、0B、0C其中一个