Coverage Report

Created: 2026-08-13 07:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/postgres/src/backend/executor/execAsync.c
Line
Count
Source
1
/*-------------------------------------------------------------------------
2
 *
3
 * execAsync.c
4
 *    Support routines for asynchronous execution
5
 *
6
 * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
7
 * Portions Copyright (c) 1994, Regents of the University of California
8
 *
9
 * IDENTIFICATION
10
 *    src/backend/executor/execAsync.c
11
 *
12
 *-------------------------------------------------------------------------
13
 */
14
15
#include "postgres.h"
16
17
#include "executor/execAsync.h"
18
#include "executor/executor.h"
19
#include "executor/instrument.h"
20
#include "executor/nodeAppend.h"
21
#include "executor/nodeForeignscan.h"
22
23
/*
24
 * Asynchronously request a tuple from a designed async-capable node.
25
 */
26
void
27
ExecAsyncRequest(AsyncRequest *areq)
28
0
{
29
0
  if (areq->requestee->chgParam != NULL) /* something changed? */
30
0
    ExecReScan(areq->requestee); /* let ReScan handle this */
31
32
  /* must provide our own instrumentation support */
33
0
  if (areq->requestee->instrument)
34
0
    InstrStartNode(areq->requestee->instrument);
35
36
0
  switch (nodeTag(areq->requestee))
37
0
  {
38
0
    case T_ForeignScanState:
39
0
      ExecAsyncForeignScanRequest(areq);
40
0
      break;
41
0
    default:
42
      /* If the node doesn't support async, caller messed up. */
43
0
      elog(ERROR, "unrecognized node type: %d",
44
0
         (int) nodeTag(areq->requestee));
45
0
  }
46
47
0
  ExecAsyncResponse(areq);
48
49
  /* must provide our own instrumentation support */
50
0
  if (areq->requestee->instrument)
51
0
    InstrStopNode(areq->requestee->instrument,
52
0
            TupIsNull(areq->result) ? 0.0 : 1.0);
53
0
}
54
55
/*
56
 * Give the asynchronous node a chance to configure the file descriptor event
57
 * for which it wishes to wait.  We expect the node-type specific callback to
58
 * make a single call of the following form:
59
 *
60
 * AddWaitEventToSet(set, WL_SOCKET_READABLE, fd, NULL, areq);
61
 */
62
void
63
ExecAsyncConfigureWait(AsyncRequest *areq)
64
0
{
65
  /* must provide our own instrumentation support */
66
0
  if (areq->requestee->instrument)
67
0
    InstrStartNode(areq->requestee->instrument);
68
69
0
  switch (nodeTag(areq->requestee))
70
0
  {
71
0
    case T_ForeignScanState:
72
0
      ExecAsyncForeignScanConfigureWait(areq);
73
0
      break;
74
0
    default:
75
      /* If the node doesn't support async, caller messed up. */
76
0
      elog(ERROR, "unrecognized node type: %d",
77
0
         (int) nodeTag(areq->requestee));
78
0
  }
79
80
  /* must provide our own instrumentation support */
81
0
  if (areq->requestee->instrument)
82
0
    InstrStopNode(areq->requestee->instrument, 0.0);
83
0
}
84
85
/*
86
 * Call the asynchronous node back when a relevant event has occurred.
87
 */
88
void
89
ExecAsyncNotify(AsyncRequest *areq)
90
0
{
91
  /* must provide our own instrumentation support */
92
0
  if (areq->requestee->instrument)
93
0
    InstrStartNode(areq->requestee->instrument);
94
95
0
  switch (nodeTag(areq->requestee))
96
0
  {
97
0
    case T_ForeignScanState:
98
0
      ExecAsyncForeignScanNotify(areq);
99
0
      break;
100
0
    default:
101
      /* If the node doesn't support async, caller messed up. */
102
0
      elog(ERROR, "unrecognized node type: %d",
103
0
         (int) nodeTag(areq->requestee));
104
0
  }
105
106
0
  ExecAsyncResponse(areq);
107
108
  /* must provide our own instrumentation support */
109
0
  if (areq->requestee->instrument)
110
0
    InstrStopNode(areq->requestee->instrument,
111
0
            TupIsNull(areq->result) ? 0.0 : 1.0);
112
0
}
113
114
/*
115
 * Call the requestor back when an asynchronous node has produced a result.
116
 */
117
void
118
ExecAsyncResponse(AsyncRequest *areq)
119
0
{
120
0
  switch (nodeTag(areq->requestor))
121
0
  {
122
0
    case T_AppendState:
123
0
      ExecAsyncAppendResponse(areq);
124
0
      break;
125
0
    default:
126
      /* If the node doesn't support async, caller messed up. */
127
0
      elog(ERROR, "unrecognized node type: %d",
128
0
         (int) nodeTag(areq->requestor));
129
0
  }
130
0
}
131
132
/*
133
 * A requestee node should call this function to deliver the tuple to its
134
 * requestor node.  The requestee node can call this from its ExecAsyncRequest
135
 * or ExecAsyncNotify callback.
136
 */
137
void
138
ExecAsyncRequestDone(AsyncRequest *areq, TupleTableSlot *result)
139
0
{
140
0
  areq->request_complete = true;
141
0
  areq->result = result;
142
0
}
143
144
/*
145
 * A requestee node should call this function to indicate that it is pending
146
 * for a callback.  The requestee node can call this from its ExecAsyncRequest
147
 * or ExecAsyncNotify callback.
148
 */
149
void
150
ExecAsyncRequestPending(AsyncRequest *areq)
151
0
{
152
0
  areq->callback_pending = true;
153
0
  areq->request_complete = false;
154
  areq->result = NULL;
155
0
}