diff --git a/contrib/pg_stat_statements/pg_stat_statements.c b/contrib/pg_stat_statements/pg_stat_statements.c index 799242b..2e61edf 100644 --- a/contrib/pg_stat_statements/pg_stat_statements.c +++ b/contrib/pg_stat_statements/pg_stat_statements.c @@ -2250,6 +2250,9 @@ JumbleRangeTable(pgssJumbleState *jstate, List *rtable) APP_JUMB_STRING(rte->ctename); APP_JUMB(rte->ctelevelsup); break; + case RTE_TUPLESTORE: + APP_JUMB_STRING(rte->tsrname); + break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) rte->rtekind); break; @@ -2638,6 +2641,13 @@ JumbleExpr(pgssJumbleState *jstate, Node *node) JumbleQuery(jstate, (Query *) cte->ctequery); } break; + case T_TuplestoreRelation: + { + TuplestoreRelation *tsr = (TuplestoreRelation *) node; + + APP_JUMB_STRING(tsr->name); + } + break; case T_SetOperationStmt: { SetOperationStmt *setop = (SetOperationStmt *) node; diff --git a/src/backend/commands/explain.c b/src/backend/commands/explain.c index 781a736..de31026 100644 --- a/src/backend/commands/explain.c +++ b/src/backend/commands/explain.c @@ -717,6 +717,7 @@ ExplainPreScanNode(PlanState *planstate, Bitmapset **rels_used) case T_FunctionScan: case T_ValuesScan: case T_CteScan: + case T_TuplestoreScan: case T_WorkTableScan: case T_ForeignScan: *rels_used = bms_add_member(*rels_used, @@ -930,6 +931,9 @@ ExplainNode(PlanState *planstate, List *ancestors, case T_CteScan: pname = sname = "CTE Scan"; break; + case T_TuplestoreScan: + pname = sname = "Tuplestore Scan"; + break; case T_WorkTableScan: pname = sname = "WorkTable Scan"; break; @@ -1300,6 +1304,7 @@ ExplainNode(PlanState *planstate, List *ancestors, case T_SeqScan: case T_ValuesScan: case T_CteScan: + case T_TuplestoreScan: case T_WorkTableScan: case T_SubqueryScan: show_scan_qual(plan->qual, "Filter", planstate, ancestors, es); @@ -2160,6 +2165,11 @@ ExplainTargetRel(Plan *plan, Index rti, ExplainState *es) objectname = rte->ctename; objecttag = "CTE Name"; break; + case T_TuplestoreScan: + Assert(rte->rtekind == RTE_TUPLESTORE); + objectname = rte->tsrname; + objecttag = "Tuplestore Name"; + break; case T_WorkTableScan: /* Assert it's on a self-reference CTE */ Assert(rte->rtekind == RTE_CTE); diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c index 93f3905..255348b 100644 --- a/src/backend/nodes/outfuncs.c +++ b/src/backend/nodes/outfuncs.c @@ -2442,6 +2442,13 @@ _outRangeTblEntry(StringInfo str, const RangeTblEntry *node) WRITE_NODE_FIELD(ctecoltypmods); WRITE_NODE_FIELD(ctecolcollations); break; + case RTE_TUPLESTORE: + WRITE_STRING_FIELD(tsrname); + WRITE_OID_FIELD(relid); + WRITE_NODE_FIELD(ctecoltypes); + WRITE_NODE_FIELD(ctecoltypmods); + WRITE_NODE_FIELD(ctecolcollations); + break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) node->rtekind); break; diff --git a/src/backend/nodes/print.c b/src/backend/nodes/print.c index 9f7f322..e11a116 100644 --- a/src/backend/nodes/print.c +++ b/src/backend/nodes/print.c @@ -287,6 +287,10 @@ print_rt(const List *rtable) printf("%d\t%s\t[cte]", i, rte->eref->aliasname); break; + case RTE_TUPLESTORE: + printf("%d\t%s\t[tuplestore]", + i, rte->eref->aliasname); + break; default: printf("%d\t%s\t[unknown rtekind]", i, rte->eref->aliasname); diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c index 69d9989..bcaeeb0 100644 --- a/src/backend/nodes/readfuncs.c +++ b/src/backend/nodes/readfuncs.c @@ -1240,6 +1240,13 @@ _readRangeTblEntry(void) READ_NODE_FIELD(ctecoltypmods); READ_NODE_FIELD(ctecolcollations); break; + case RTE_TUPLESTORE: + READ_STRING_FIELD(tsrname); + READ_OID_FIELD(relid); + READ_NODE_FIELD(ctecoltypes); + READ_NODE_FIELD(ctecoltypmods); + READ_NODE_FIELD(ctecolcollations); + break; default: elog(ERROR, "unrecognized RTE kind: %d", (int) local_node->rtekind); diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index fb6c44c..518691a 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -2473,6 +2473,15 @@ transformLockingClause(ParseState *pstate, Query *qry, LockingClause *lc, LCS_asString(lc->strength)), parser_errposition(pstate, thisrel->location))); break; + case RTE_TUPLESTORE: + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + /*------ + translator: %s is a SQL row locking clause such as FOR UPDATE */ + errmsg("%s cannot be applied to a tuplestore", + LCS_asString(lc->strength)), + parser_errposition(pstate, thisrel->location))); + break; default: elog(ERROR, "unrecognized RTE type: %d", (int) rte->rtekind); diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c index bd8cbff..a30b43e 100644 --- a/src/backend/parser/parse_relation.c +++ b/src/backend/parser/parse_relation.c @@ -2180,6 +2180,7 @@ expandRTE(RangeTblEntry *rte, int rtindex, int sublevels_up, } break; case RTE_CTE: + case RTE_TUPLESTORE: { ListCell *aliasp_item = list_head(rte->eref->colnames); ListCell *lct; @@ -2654,6 +2655,16 @@ get_rte_attribute_is_dropped(RangeTblEntry *rte, AttrNumber attnum) /* Subselect, Values, CTE RTEs never have dropped columns */ result = false; break; + case RTE_TUPLESTORE: + { + Tsr tsr; + + Assert(rte->tsrname); + tsr = get_visible_tuplestore(rte->tsrname); + Assert(tsr); + result = tsr->tupdesc->attrs[attnum - 1]->attisdropped; + } + break; case RTE_JOIN: { /*