 doc/src/sgml/custom-scan.sgml | 25 +++++++++++++++++++++----
 src/backend/nodes/copyfuncs.c | 16 +++++++++++++++-
 src/backend/nodes/readfuncs.c | 22 +++++++++++++++++-----
 src/include/nodes/plannodes.h | 11 +++++++----
 4 files changed, 60 insertions(+), 14 deletions(-)

diff --git a/doc/src/sgml/custom-scan.sgml b/doc/src/sgml/custom-scan.sgml
index af0dd56..21a9ace 100644
--- a/doc/src/sgml/custom-scan.sgml
+++ b/doc/src/sgml/custom-scan.sgml
@@ -197,9 +197,11 @@ typedef struct CustomScan
    Plan trees must be able to be duplicated using <function>copyObject</>,
    serialized using <function>nodeToString</> and deserialized using
    <function>stringToNode</>.
+   <structname>CustomScan</> can be located on head of larger structure
+   to keep private fields of custom scan provider.
    Thus, if custom scan provider implements <function>TextOutCustomScan</>
    to dump its private fields its own way, it also has responsibility of
-   <function>TextReadCustomScan</> to clean out these tokens.
+   <function>TextReadCustomScan</> to reconstruct the private structure.
   </para>
   <para>
    Like any other fields, <structfield>methods</> pointer of the
@@ -251,16 +253,31 @@ void (*TextOutCustomScan) (StringInfo str,
 
    <para>
 <programlisting>
-void (*TextReadCustomScan)(CustomScan *node);
+CustomScan *(*TextReadCustomScan)(void);
 </programlisting>
-    Reads the private fields of supplied <structname>CustomScan</> node
-    generated by <function>TextOutCustomScan</> callback.
+    Allocate a <structname>CustomScan</> or larger structure embedding
+    <structname>CustomScan</>, and read its private fields generated by
+    <function>TextOutCustomScan</> callback.
     This callback is optional, however, must be implemented if custom
     scan provider makes additional output for support of plan-tree
     serialization and deserialization.
     This callback shall be invoked under <function>stringToNode</>
     context, so <function>pg_strtok</> will give the next token.
    </para>
+
+   <para>
+<programlisting>
+CustomScan *(*NodeCopyCustomScan)(const struct CustomScan *from);
+</programlisting>
+    Allocate a <structname>CustomScan</> or larger structure embedding
+    <structname>CustomScan</>, and copies its private fields from the
+    original node.
+    This callback is optional, however, must be implemented if custom
+    scan provider extends <structname>CustomScan</> structure to save
+    its private fields for safety of <function>copyObject</>.
+    The common fields are duplicated by the backend, so all extension
+    needs to focus on is its private fields, if exists.
+   </para>
   </sect2>
  </sect1>
 
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index c176ff9..ba58f3f 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -661,7 +661,21 @@ _copyForeignScan(const ForeignScan *from)
 static CustomScan *
 _copyCustomScan(const CustomScan *from)
 {
-	CustomScan *newnode = makeNode(CustomScan);
+	const CustomScanMethods *methods = from->methods;
+	CustomScan *newnode;
+
+	/*
+	 * If custom-scan provider extends CustomScan node to save its private
+	 * data, it is role of the provider to allocate a new node that includes
+	 * the private fields.
+	 */
+	if (!methods->NodeCopyCustomScan)
+		newnode = makeNode(CustomScan);
+	else
+	{
+		newnode = methods->NodeCopyCustomScan(from);
+		Assert(IsA(newnode, CustomScan));
+	}
 
 	/*
 	 * copy node superclass fields
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 8e6e3d6..8e99703 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -1812,11 +1812,14 @@ _readForeignScan(void)
 static CustomScan *
 _readCustomScan(void)
 {
-	READ_LOCALS(CustomScan);
+	READ_TEMP_LOCALS();
+	CustomScan	local_temp;
+	CustomScan *local_node = &local_temp;
 	char	   *library_name;
 	char	   *symbol_name;
 	const CustomScanMethods *methods;
 
+	NodeSetTag(local_node, T_CustomScan);
 	ReadCommonScan(&local_node->scan);
 
 	READ_UINT_FIELD(flags);
@@ -1842,11 +1845,20 @@ _readCustomScan(void)
 	local_node->methods = methods;
 
 	/*
-	 * Read custom fields if any. Number of tokens has to be equivalent
-	 * to the output of TextOutCustomScan
+	 * Then, read private data fields and reconstruct a struct that
+	 * contains CustomScan on its head, if any. Elsewhere, construct
+	 * usual CustomScan node.
 	 */
-	if (methods->TextReadCustomScan)
-		methods->TextReadCustomScan(local_node);
+	if (!methods->TextReadCustomScan)
+		local_node = makeNode(CustomScan);
+	else
+	{
+		local_node = methods->TextReadCustomScan();
+		Assert(IsA(local_node, CustomScan));
+	}
+	/* move the common field of CustomScan */
+	memcpy(local_node, &local_temp, offsetof(CustomScan, methods));
+	local_node->methods = methods;
 
 	READ_DONE();
 }
diff --git a/src/include/nodes/plannodes.h b/src/include/nodes/plannodes.h
index b3f90fb..908c029 100644
--- a/src/include/nodes/plannodes.h
+++ b/src/include/nodes/plannodes.h
@@ -542,9 +542,10 @@ typedef struct ForeignScan
  * custom_private, custom_scan_tlist, and custom_relids fields.  The
  * convention of setting scan.scanrelid to zero for joins applies as well.
  *
- * Note that since Plan trees can be copied, custom scan providers *must*
- * fit all plan data they need into those fields; embedding CustomScan in
- * a larger struct will not work.
+ * Note that Plan trees can be copied, displayed and read using node
+ * functions, thus, custom scan provider *must* support relevant callbacks
+ * if provider wants to embed CustomScan in a larger struct to save private
+ * fields.
  * ----------------
  */
 struct CustomScan;
@@ -562,7 +563,9 @@ typedef struct CustomScanMethods
 	void		(*TextOutCustomScan) (StringInfo str,
 											  const struct CustomScan *node);
 	/* Optional: read the private fields printed in special way */
-	void		(*TextReadCustomScan) (struct CustomScan *cscan);
+	struct CustomScan *(*TextReadCustomScan)(void);
+	/* Optional: copy the original including private fields */
+	struct CustomScan *(*NodeCopyCustomScan)(const struct CustomScan *from);
 } CustomScanMethods;
 
 #define INIT_CUSTOM_SCAN_METHODS(methods, name)							\
