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
This commit is contained in:
Tom Lane 2021-07-06 18:10:11 -04:00
parent 5798ca5299
commit 955b3e0f92
4 changed files with 26 additions and 16 deletions

View File

@ -71,10 +71,17 @@ typedef struct CustomPath
<para>
<structfield>path</structfield> must be initialized as for any other path, including
the row-count estimate, start and total cost, and sort ordering provided
by this path. <structfield>flags</structfield> is a bit mask, which should include
by this path. <structfield>flags</structfield> is a bit mask, which
specifies whether the scan provider can support certain optional
capabilities. <structfield>flags</structfield> should include
<literal>CUSTOMPATH_SUPPORT_BACKWARD_SCAN</literal> if the custom path can support
a backward scan and <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</literal> if it
can support mark and restore. Both capabilities are optional.
a backward scan, <literal>CUSTOMPATH_SUPPORT_MARK_RESTORE</literal> if it
can support mark and restore,
and <literal>CUSTOMPATH_SUPPORT_PROJECTION</literal> if it can perform
projections. (If <literal>CUSTOMPATH_SUPPORT_PROJECTION</literal> 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 <structfield>custom_paths</structfield> is a list of <structname>Path</structname>
nodes used by this custom-path node; these will be transformed into
<structname>Plan</structname> nodes by planner.

View File

@ -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:

View File

@ -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:
/*

View File

@ -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