{"kind": "plan", "major": "18", "item": {"slug": "recursive-union", "name": "Recursive Union", "name_zh": "RecursiveUnion", "category": "Combination", "summary": "Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables.", "aliases": ["Recursive Union", "RecursiveUnion", "T_RecursiveUnion"], "content_hash": "644b31619c32148a2975b5d3f69bf1cb22484977db35fe1c5f2f7ee32bd431fb", "versions": {"10": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "01b05e8d64377338e2db2885568ccf521facba826fbb2a841d5536a7f6a49e3e", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "dcf45a15db0b6fce8d77783138557f9fcb956b5c45dceac9ec734c2990f8cb97", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=10", "label": "EXPLAIN"}, {"url": "/docs/10/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/10/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=10", "label": "work_mem"}], "release": {"ref": "PostgreSQL 10.23 source archive", "label": "10.23", "major": "10", "channel": "historical", "revision": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9", "source_url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "line": 912, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:912", "sha256": "a785298532047cfeda969e78c3597a343dc1c56d61ba85830b0f16a02a14b5a1", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "cea76648bb38ae55f18f989768bee1a4ee025691ceea0f86bccb29dcdc166acc", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "01b05e8d64377338e2db2885568ccf521facba826fbb2a841d5536a7f6a49e3e", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "d562c321108844798cd234303fffb618f13d4ee3f3a5ac79bfd963b077e47c22", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}, {"url": "https://ftp.postgresql.org/pub/source/v10.23/postgresql-10.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "dcf45a15db0b6fce8d77783138557f9fcb956b5c45dceac9ec734c2990f8cb97", "archive_sha256": "94a4b2528372458e5662c18d406629266667c437198160a18cdfd2c4a4d6eee9"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "11": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "629f26d49096e84125f6bd83ddaa189cd0945229ab7357c744d2dc9051a0b7c5", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "2891704a2b38e4f4c52cce4604f1cad8b83781217697c4cddd6d3d99ddc14fce", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=11", "label": "EXPLAIN"}, {"url": "/docs/11/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/11/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=11", "label": "work_mem"}], "release": {"ref": "PostgreSQL 11.22 source archive", "label": "11.22", "major": "11", "channel": "historical", "revision": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0", "source_url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "line": 1037, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1037", "sha256": "9df8400c1a4377179572ceb916d6020fca4e2760f74bf416d77ed97476523bbd", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "95ef4d4a5df4c29f14af9763fae2c530449bdacdf3853d9ff297adf1fed6153b", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "629f26d49096e84125f6bd83ddaa189cd0945229ab7357c744d2dc9051a0b7c5", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "5e0511194183800e8d6eb293fd4b40639c7d3118e2d199c8e7865ba4fa4cf67f", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}, {"url": "https://ftp.postgresql.org/pub/source/v11.22/postgresql-11.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "2891704a2b38e4f4c52cce4604f1cad8b83781217697c4cddd6d3d99ddc14fce", "archive_sha256": "2cb7c97d7a0d7278851bbc9c61f467b69c094c72b81740b751108e7892ebe1f0"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "12": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "43e465f94085eb2f6df02e38f5e3347909a878cb22ce21f730a1d0c60f4357f4", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "44cccd98d659272f5c8f3ff6adffb1f6cc911acd13a3cfafc74cc7841318f929", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=12", "label": "EXPLAIN"}, {"url": "/docs/12/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/12/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=12", "label": "work_mem"}], "release": {"ref": "PostgreSQL 12.22 source archive", "label": "12.22", "major": "12", "channel": "historical", "revision": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b", "source_url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "line": 1108, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1108", "sha256": "d02ea84fdaa201de5d9360645a9f24bfbd2c31f7d45a639e09560ac0e6b6471d", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "311b17379fe54e3f342fe5ad41c43afbdfa1b844978db2bb2eb22b82520d3256", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "43e465f94085eb2f6df02e38f5e3347909a878cb22ce21f730a1d0c60f4357f4", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "b0c4a0aeb48660ce06e5e700d5529ca9066fd16682bd15783d6e71b5420b07b0", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}, {"url": "https://ftp.postgresql.org/pub/source/v12.22/postgresql-12.22.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "44cccd98d659272f5c8f3ff6adffb1f6cc911acd13a3cfafc74cc7841318f929", "archive_sha256": "8df3c0474782589d3c6f374b5133b1bd14d168086edbc13c6e72e67dd4527a3b"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "13": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "4c890bc0389b519e50d3452ce9e15bf0d028b9eb32f5dfe0d6ffdc3a58009fb0", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "4cba6490949d7dd9338b8499fcbb489e84cfd6cda9b98599512eb40bfbde6f9d", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=13", "label": "EXPLAIN"}, {"url": "/docs/13/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/13/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=13", "label": "work_mem"}], "release": {"ref": "PostgreSQL 13.23 source archive", "label": "13.23", "major": "13", "channel": "historical", "revision": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6", "source_url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 1166, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1166", "sha256": "541713e0e7f1c9cc352c2b6028964d440c19d2678a4463000094c24a88c1e730", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "line": 189, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:189", "sha256": "d085ee99acfa00587e6ade3a1d9f8108a0566beedbbee3f54a50c9fc0cc2e875", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "4c890bc0389b519e50d3452ce9e15bf0d028b9eb32f5dfe0d6ffdc3a58009fb0", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "dcb296833777b02008c4b6bae8e8f7c6423b7ffba21f36702597c9d596d039ab", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}, {"url": "https://ftp.postgresql.org/pub/source/v13.23/postgresql-13.23.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "4cba6490949d7dd9338b8499fcbb489e84cfd6cda9b98599512eb40bfbde6f9d", "archive_sha256": "6ec3c82726af92b7dec873fa1cdf881eca92a4219787dfad05acb6b10e041fd6"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "14": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1fa4a12d45ae59b313d2c449ea1e7564f3c986c5f4b2b391e9b0b01e6038c716", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "833cff27e0a2c863b9e897cd3bf4127df1b3e3a9b976694f3323a1c1a466d9b2", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=14", "label": "EXPLAIN"}, {"url": "/docs/14/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/14/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=14", "label": "work_mem"}], "release": {"ref": "PostgreSQL 14.24 source archive", "label": "14.24", "major": "14", "channel": "stable", "revision": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897", "source_url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 1202, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1202", "sha256": "e091be4e2a083b8dea39ccd09beedede22c1716ef974da66c214a44f48be8c41", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "72da1c5ad457f1d92a39ab73531701794df858419e3b89d6e6cb7079634e68fa", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1fa4a12d45ae59b313d2c449ea1e7564f3c986c5f4b2b391e9b0b01e6038c716", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "302f51a16b570dba7ec4e7bc045f7df5800d21630280354d1a24025f3baec75d", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}, {"url": "https://ftp.postgresql.org/pub/source/v14.24/postgresql-14.24.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "833cff27e0a2c863b9e897cd3bf4127df1b3e3a9b976694f3323a1c1a466d9b2", "archive_sha256": "a7fa7ed3d558172355f51406097a7bd4f6b473be80f311ef7cda96bf383d8897"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "15": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1021c1580f1046f9f297f35520c208f6707e14f05ab8596ba23d7ecf7e814846", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "37be0ffb18c97558ea6fe6e1e0072564026b231edb9edf0a29faf27f13827aab", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=15", "label": "EXPLAIN"}, {"url": "/docs/15/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/15/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=15", "label": "work_mem"}], "release": {"ref": "PostgreSQL 15.19 source archive", "label": "15.19", "major": "15", "channel": "stable", "revision": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89", "source_url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 1205, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1205", "sha256": "bb3b442d0f1b098aa8707335250102f027a596cd94117308bd16d1d36b258f5c", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "19836c50a272741a4eac653541e655437c2e00710a541e5348d6a277d0669d7c", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "1021c1580f1046f9f297f35520c208f6707e14f05ab8596ba23d7ecf7e814846", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "fb4a4c8165495299131173680bc02a950d88e1ff610231fd97997bc0c9afc1d7", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}, {"url": "https://ftp.postgresql.org/pub/source/v15.19/postgresql-15.19.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "37be0ffb18c97558ea6fe6e1e0072564026b231edb9edf0a29faf27f13827aab", "archive_sha256": "e1a64a87a46b825b88c082e4518161a47aab53c45694964f8ba1df28f7859f89"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "16": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "8528ec1bbb53dfcd43f842e34dcd9307dbae5d299b6cd55aaefc39ef57e9ace8", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "a990669858f1847ac83b5e1e65cf5515fe05ea0ad45ff64dd9347ba4f2110e62", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=16", "label": "EXPLAIN"}, {"url": "/docs/16/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/16/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=16", "label": "work_mem"}], "release": {"ref": "PostgreSQL 16.15 source archive", "label": "16.15", "major": "16", "channel": "stable", "revision": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed", "source_url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 1238, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1238", "sha256": "8e017f0116dbea471339b40c37a667cc9f95039e7e0329c783e5e8ce194de7e1", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "e48c08e555f8cb4e4bb43df516c4b8906ce9bc374b2a745d98a1fc8c22cc5099", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "8528ec1bbb53dfcd43f842e34dcd9307dbae5d299b6cd55aaefc39ef57e9ace8", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "97db47353db76326b874589a5ad0a04501cc74cd72e237e7bd956e7472c41f1f", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}, {"url": "https://ftp.postgresql.org/pub/source/v16.15/postgresql-16.15.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "a990669858f1847ac83b5e1e65cf5515fe05ea0ad45ff64dd9347ba4f2110e62", "archive_sha256": "c1575341fa7bd40f5274ea465b34390f4dc64cdd0770af327005caaeb9f6b7ed"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "17": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "f03122d0aba6181ea442d719d6ba99f851c5eefe4b9c255ecf1b1e3636e0efe1", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "0d4316ed2d09288c2e3be15be1ce01b88622354bcd571ac7ebc45aa9319b90e7", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=17", "label": "EXPLAIN"}, {"url": "/docs/17/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/17/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=17", "label": "work_mem"}], "release": {"ref": "PostgreSQL 17.11 source archive", "label": "17.11", "major": "17", "channel": "stable", "revision": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979", "source_url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 1427, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1427", "sha256": "741251b1a3b6d269a52a673d42eb63b02e13a5872db7b359b137086ab21b63c8", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "a77576e158b94cb01fa8c5174ba133004eabdd727660323f8afc66c8d2e757b8", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "f03122d0aba6181ea442d719d6ba99f851c5eefe4b9c255ecf1b1e3636e0efe1", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "d390dd69e2d3f5085beb42b33e46ff0676a2959b916a12b82118a7e545f8e562", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}, {"url": "https://ftp.postgresql.org/pub/source/v17.11/postgresql-17.11.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "0d4316ed2d09288c2e3be15be1ce01b88622354bcd571ac7ebc45aa9319b90e7", "archive_sha256": "dd27f2b3c59e73ed14aa3324901242bf69a032a6347805f274e6260322d42979"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2", "If hashing, we need a per-tuple memory context for comparisons, and a longer-lived context to store the hash table. The table can't just be kept in the per-query context because we want to be able to throw it away when rescanning."]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "18": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=18", "label": "EXPLAIN"}, {"url": "/docs/18/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/18/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=18", "label": "work_mem"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 1412, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1412", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "19": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "cda3af245b88d079a32616b4cc5316913d349ba3acaab5fc1fd8aec479cc51ee", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=19", "label": "EXPLAIN"}, {"url": "/docs/19/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/19/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=19", "label": "work_mem"}], "release": {"ref": "PostgreSQL 19beta4 source archive", "label": "19beta4", "major": "19", "channel": "preview", "revision": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86", "source_url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 1424, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1424", "sha256": "8b115b1c194a4b54ae630209a741e293b1df49a9052f10b2de9ca092a48998e3", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "5e39b2037bed672da55104229ecc32da5abde44c26bcad01479edcfa044d09ed", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "1c65d5d6b6c81c71531685843647869bcae630779d815a5036b06e070c6c06c7", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}, {"url": "https://ftp.postgresql.org/pub/source/v19beta4/postgresql-19beta4.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "cda3af245b88d079a32616b4cc5316913d349ba3acaab5fc1fd8aec479cc51ee", "archive_sha256": "83157ee9c599d03b2f7a3d73ef3a56ec24e0e79cc2b3501a64d1364f56398c86"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "20": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "46a50e4790274348dfdc6e24f63ae12809d38e639d19378c01d6daff55e61644", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=20", "label": "EXPLAIN"}, {"url": "/docs/devel/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/devel/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=20", "label": "work_mem"}], "release": {"ref": "PostgreSQL 20devel source archive", "label": "20devel", "major": "20", "channel": "devel", "revision": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41", "source_url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "source_snapshot_utc": "26-Sep-2026 20:22"}, "sources": [{"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 1424, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1424", "sha256": "13402758013520451539427b5993db06d463ca11c4e2d4cc5444e82367688077", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "5e39b2037bed672da55104229ecc32da5abde44c26bcad01479edcfa044d09ed", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "cbf92a385bb3319cba428433949e6a53d240a6ea67faa183a318d31313737c4b", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "7a94ed1652f0d74d50c39971d1cd3e8051dbc0d6058f31b6de71a433ca343521", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}, {"url": "https://ftp.postgresql.org/pub/snapshot/dev/postgresql-snapshot.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "46a50e4790274348dfdc6e24f63ae12809d38e639d19378c01d6daff55e61644", "archive_sha256": "4d3346909b201ac1648232cf290462a7070c119326f56196f1f0253ed80fae41"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}}}, "snapshot": {"facts": [{"label": "Core node tag", "value": "T_RecursiveUnion"}, {"label": "Structured EXPLAIN Node Type", "value": "Recursive Union"}, {"label": "Inputs", "value": "Non-recursive and recursive child plans"}, {"label": "Output", "value": "Recursive query tuples"}, {"label": "Executor initializer", "value": "ExecInitRecursiveUnion"}, {"label": "Memory mechanism", "value": "tuplestore"}], "memory": {"evidence": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "mechanism": "tuplestore", "description": "This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node.", "source_notes": []}, "tables": [{"key": "explain-labels", "rows": [{"label": "Recursive Union", "identity": "Recursive Union"}], "title": "EXPLAIN labels in this source build", "columns": [{"key": "label", "label": "Text-format label"}, {"key": "identity", "label": "Structured node identity"}]}], "related": [{"url": "/wiki/sql/explain/?v=18", "label": "EXPLAIN"}, {"url": "/docs/18/using-explain.html", "label": "Using EXPLAIN"}, {"url": "/docs/18/parallel-plans.html", "label": "Parallel plans"}, {"url": "/wiki/guc/work_mem/?v=18", "label": "work_mem"}], "release": {"ref": "PostgreSQL 18.6 source archive", "label": "18.6", "major": "18", "channel": "stable", "revision": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f", "source_url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "source_snapshot_utc": ""}, "sources": [{"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 1412, "path": "src/backend/commands/explain.c", "label": "src/backend/commands/explain.c:1412", "sha256": "34c86d6070224a0e981efef51f79101d6d505e5874f1684ace183034bab14bb4", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "line": 191, "path": "src/backend/executor/execProcnode.c", "label": "src/backend/executor/execProcnode.c:191", "sha256": "f8a06a3f539077249b20664b2812433db6d7bd12b2c0ca633525db43d06f112a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/executor/nodeRecursiveunion.c", "label": "src/backend/executor/nodeRecursiveunion.c", "sha256": "315c2d4d0a7a1ddf362ad19357cb62c7615592d2f51aaee87d313b4fe0d9536a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/include/nodes/plannodes.h", "label": "src/include/nodes/plannodes.h", "sha256": "52422b327a8049fbbb20d8b96008a0fc0a6fafa60f7eff3c695d5b2e83830120", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}, {"url": "https://ftp.postgresql.org/pub/source/v18.6/postgresql-18.6.tar.bz2", "path": "src/backend/utils/sort/tuplestore.c", "label": "src/backend/utils/sort/tuplestore.c", "sha256": "27a85416bafed557006c705ab5d0c5dce3d3c1702812bb54d136f2ac4c41055a", "archive_sha256": "555610c24d53e4316da5b7d3fc25c279d96856d5e0e23ee308c328c5fa881d9f"}], "node_tag": "T_RecursiveUnion", "sections": [{"title": "EXPLAIN names and attributes", "paragraphs": ["Structured formats use the Node Type above. Text-format spellings can also include operation, strategy, join type, scan direction or aggregation-stage attributes.", "Text names recorded by this source: Recursive Union.", "Parallel-aware and parallel-safe are different plan properties. A node running inside a parallel worker is not necessarily a parallel-aware node."]}, {"title": "Memory and temporary storage", "paragraphs": ["This node creates a tuplestore with work_mem. The tuplestore can move stored tuples to temporary files; this does not make work_mem a cap on every allocation made by the node."]}, {"title": "Parallel execution and instrumentation", "paragraphs": ["The source callbacks below can coordinate execution or collect worker instrumentation. Their presence is not a blanket claim that this node supports a shared parallel scan or shared state.", "Callbacks in this build: none extracted from this node implementation."]}, {"title": "Executor implementation notes", "paragraphs": ["nodeRecursiveunion.c routines to handle RecursiveUnion nodes.", "To implement UNION (without ALL), we need a hashtable that stores tuples already seen. The hash key is computed from the grouping columns.", "If both child plans deliver the same fixed tuple slot type, we can tell BuildTupleHashTable to expect that slot type as input. Otherwise, we'll pass NULL denoting that any slot type is possible.", "Scans the recursive query sequentially and returns the next qualifying tuple.", "2.1 WT := RT 2.2 while WT is not empty repeat 2.3 to 2.6. if WT is empty returns RT 2.3 replace the name of recursive term with WT 2.4 evaluate the recursive term and store into WT 2.5 append WT to RT 2.6 go back to 2.2"]}, {"code": "case T_RecursiveUnion:\n\t\t\tpname = sname = \"Recursive Union\";\n\t\t\tbreak;", "title": "EXPLAIN identity in core source"}], "strategies": [], "description": ["Executes the non-recursive and recursive terms of a recursive union using working and intermediate tables."], "evidence_kind": "source and documentation", "explain_names": ["Recursive Union"], "partial_modes": [], "comparison_data": {"node_tag": "T_RecursiveUnion", "strategies": [], "text_names": ["Recursive Union"], "initializer": "ExecInitRecursiveUnion", "partial_modes": [], "memory_mechanism": "tuplestore", "parallel_callbacks": []}, "comparison_hash": "483291c3112fd1d9f34701a541efd658b64074aa0300e044d5e96c65ca8e9023", "explain_prefixes": ["Parallel", "Async"], "runtime_verified": false, "source_inventory": {"explain": "src/backend/commands/explain.c", "executor": "src/backend/executor/execProcnode.c", "implementation": "src/backend/executor/nodeRecursiveunion.c"}, "parallel_callbacks": []}, "comparison": {"left": "17", "right": "18", "status": "unchanged", "diff": ""}}