mirror of
https://github.com/postgres/postgres.git
synced 2026-01-27 21:43:08 +03:00
Commit 83ea6c540 added support for virtual generated columns that are
computed on read. All Var nodes in the query that reference virtual
generated columns must be replaced with the corresponding generation
expressions. Currently, this replacement occurs in the rewriter.
However, this approach has several issues. If a Var referencing a
virtual generated column has any varnullingrels, those varnullingrels
need to be propagated into the generation expression. Failing to do
so can lead to "wrong varnullingrels" errors and improper outer-join
removal.
Additionally, if such a Var comes from the nullable side of an outer
join, we may need to wrap the generation expression in a
PlaceHolderVar to ensure that it is evaluated at the right place and
hence is forced to null when the outer join should do so. In certain
cases, such as when the query uses grouping sets, we also need a
PlaceHolderVar for anything that is not a simple Var to isolate
subexpressions. Failure to do so can result in incorrect results.
To fix these issues, this patch expands the virtual generated columns
in the planner rather than in the rewriter, and leverages the
pullup_replace_vars architecture to avoid code duplication. The
generation expressions will be correctly marked with nullingrel bits
and wrapped in PlaceHolderVars when needed by the pullup_replace_vars
callback function. This requires handling the OLD/NEW RETURNING list
Vars in pullup_replace_vars_callback, as it may now deal with Vars
referencing the result relation instead of a subquery.
The "wrong varnullingrels" error was reported by Alexander Lakhin.
The incorrect result issue and the improper outer-join removal issue
were reported by Richard Guo.
Author: Richard Guo <guofenglinux@gmail.com>
Author: Dean Rasheed <dean.a.rasheed@gmail.com>
Reviewed-by: Jian He <jian.universality@gmail.com>
Discussion: https://postgr.es/m/75eb1a6f-d59f-42e6-8a78-124ee808cda7@gmail.com
59 lines
1.7 KiB
C
59 lines
1.7 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* prep.h
|
|
* prototypes for files in optimizer/prep/
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/optimizer/prep.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef PREP_H
|
|
#define PREP_H
|
|
|
|
#include "nodes/pathnodes.h"
|
|
#include "nodes/plannodes.h"
|
|
|
|
|
|
/*
|
|
* prototypes for prepjointree.c
|
|
*/
|
|
extern void transform_MERGE_to_join(Query *parse);
|
|
extern void replace_empty_jointree(Query *parse);
|
|
extern void pull_up_sublinks(PlannerInfo *root);
|
|
extern void preprocess_function_rtes(PlannerInfo *root);
|
|
extern Query *expand_virtual_generated_columns(PlannerInfo *root);
|
|
extern void pull_up_subqueries(PlannerInfo *root);
|
|
extern void flatten_simple_union_all(PlannerInfo *root);
|
|
extern void reduce_outer_joins(PlannerInfo *root);
|
|
extern void remove_useless_result_rtes(PlannerInfo *root);
|
|
extern Relids get_relids_in_jointree(Node *jtnode, bool include_outer_joins,
|
|
bool include_inner_joins);
|
|
extern Relids get_relids_for_join(Query *query, int joinrelid);
|
|
|
|
/*
|
|
* prototypes for preptlist.c
|
|
*/
|
|
extern void preprocess_targetlist(PlannerInfo *root);
|
|
|
|
extern List *extract_update_targetlist_colnos(List *tlist);
|
|
|
|
extern PlanRowMark *get_plan_rowmark(List *rowmarks, Index rtindex);
|
|
|
|
/*
|
|
* prototypes for prepagg.c
|
|
*/
|
|
extern void get_agg_clause_costs(PlannerInfo *root, AggSplit aggsplit,
|
|
AggClauseCosts *costs);
|
|
extern void preprocess_aggrefs(PlannerInfo *root, Node *clause);
|
|
|
|
/*
|
|
* prototypes for prepunion.c
|
|
*/
|
|
extern RelOptInfo *plan_set_operations(PlannerInfo *root);
|
|
|
|
#endif /* PREP_H */
|