From 955b3e0f9269639fb916cee3dea37aee50b82df0 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Tue, 6 Jul 2021 18:10:11 -0400 Subject: [PATCH] Allow CustomScan providers to say whether they support projections. Previously, all CustomScan providers had to support projections, but there may be cases where this is inconvenient. Add a flag bit to say if it's supported. Important item for the release notes: this is non-backwards-compatible since the default is now to assume that CustomScan providers can't project, instead of assuming that they can. It's fail-soft, but could result in visible performance penalties due to adding unnecessary Result nodes. Sven Klemm, reviewed by Aleksander Alekseev; some cosmetic fiddling by me. Discussion: https://postgr.es/m/CAMCrgp1kyakOz6c8aKhNDJXjhQ1dEjEnp+6KNT3KxPrjNtsrDg@mail.gmail.com --- doc/src/sgml/custom-scan.sgml | 13 ++++++++++--- src/backend/executor/execAmi.c | 17 +++++------------ src/backend/optimizer/plan/createplan.c | 8 ++++++++ src/include/nodes/extensible.h | 4 +++- 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml index 239ba29de7..93d96f2f56 100644 --- a/doc/src/sgml/custom-scan.sgml +++ b/doc/src/sgml/custom-scan.sgml @@ -71,10 +71,17 @@ typedef struct CustomPath path must be initialized as for any other path, including the row-count estimate, start and total cost, and sort ordering provided - by this path. flags is a bit mask, which should include + by this path. flags is a bit mask, which + specifies whether the scan provider can support certain optional + capabilities. flags should include CUSTOMPATH_SUPPORT_BACKWARD_SCAN if the custom path can support - a backward scan and CUSTOMPATH_SUPPORT_MARK_RESTORE if it - can support mark and restore. Both capabilities are optional. + a backward scan, CUSTOMPATH_SUPPORT_MARK_RESTORE if it + can support mark and restore, + and CUSTOMPATH_SUPPORT_PROJECTION if it can perform + projections. (If CUSTOMPATH_SUPPORT_PROJECTION is not + set, the scan node will only be asked to produce Vars of the scanned + relation; while if that flag is set, the scan node must be able to + evaluate scalar expressions over these Vars.) An optional custom_paths is a list of Path nodes used by this custom-path node; these will be transformed into Plan nodes by planner. diff --git a/src/backend/executor/execAmi.c b/src/backend/executor/execAmi.c index 10f0b349b5..522b1c2086 100644 --- a/src/backend/executor/execAmi.c +++ b/src/backend/executor/execAmi.c @@ -438,13 +438,10 @@ ExecSupportsMarkRestore(Path *pathnode) return true; case T_CustomScan: - { - CustomPath *customPath = castNode(CustomPath, pathnode); + if (castNode(CustomPath, pathnode)->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE) + return true; + return false; - if (customPath->flags & CUSTOMPATH_SUPPORT_MARK_RESTORE) - return true; - return false; - } case T_Result: /* @@ -567,12 +564,8 @@ ExecSupportsBackwardScan(Plan *node) return ExecSupportsBackwardScan(((SubqueryScan *) node)->subplan); case T_CustomScan: - { - uint32 flags = ((CustomScan *) node)->flags; - - if (flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) - return true; - } + if (((CustomScan *) node)->flags & CUSTOMPATH_SUPPORT_BACKWARD_SCAN) + return true; return false; case T_SeqScan: diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 439e6b6426..c13da7a879 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -7046,6 +7046,10 @@ is_projection_capable_path(Path *path) case T_MergeAppend: case T_RecursiveUnion: return false; + case T_CustomScan: + if (castNode(CustomPath, path)->flags & CUSTOMPATH_SUPPORT_PROJECTION) + return true; + return false; case T_Append: /* @@ -7092,6 +7096,10 @@ is_projection_capable_plan(Plan *plan) case T_MergeAppend: case T_RecursiveUnion: return false; + case T_CustomScan: + if (((CustomScan *) plan)->flags & CUSTOMPATH_SUPPORT_PROJECTION) + return true; + return false; case T_ProjectSet: /* diff --git a/src/include/nodes/extensible.h b/src/include/nodes/extensible.h index 9e425e5651..cc9b7e9928 100644 --- a/src/include/nodes/extensible.h +++ b/src/include/nodes/extensible.h @@ -76,10 +76,12 @@ extern const ExtensibleNodeMethods *GetExtensibleNodeMethods(const char *name, /* * Flags for custom paths, indicating what capabilities the resulting scan - * will have. + * will have. The flags fields of CustomPath and CustomScan nodes are + * bitmasks of these flags. */ #define CUSTOMPATH_SUPPORT_BACKWARD_SCAN 0x0001 #define CUSTOMPATH_SUPPORT_MARK_RESTORE 0x0002 +#define CUSTOMPATH_SUPPORT_PROJECTION 0x0004 /* * Custom path methods. Mostly, we just need to know how to convert a