/Users/deen/code/yugabyte-db/src/postgres/src/backend/tcop/dest.c
Line | Count | Source (jump to first uncovered line) |
1 | | /*------------------------------------------------------------------------- |
2 | | * |
3 | | * dest.c |
4 | | * support for communication destinations |
5 | | * |
6 | | * |
7 | | * Portions Copyright (c) 1996-2018, PostgreSQL Global Development Group |
8 | | * Portions Copyright (c) 1994, Regents of the University of California |
9 | | * |
10 | | * IDENTIFICATION |
11 | | * src/backend/tcop/dest.c |
12 | | * |
13 | | *------------------------------------------------------------------------- |
14 | | */ |
15 | | /* |
16 | | * INTERFACE ROUTINES |
17 | | * BeginCommand - initialize the destination at start of command |
18 | | * CreateDestReceiver - create tuple receiver object for destination |
19 | | * EndCommand - clean up the destination at end of command |
20 | | * NullCommand - tell dest that an empty query string was recognized |
21 | | * ReadyForQuery - tell dest that we are ready for a new query |
22 | | * |
23 | | * NOTES |
24 | | * These routines do the appropriate work before and after |
25 | | * tuples are returned by a query to keep the backend and the |
26 | | * "destination" portals synchronized. |
27 | | */ |
28 | | |
29 | | #include "postgres.h" |
30 | | |
31 | | #include "access/printsimple.h" |
32 | | #include "access/printtup.h" |
33 | | #include "access/xact.h" |
34 | | #include "commands/copy.h" |
35 | | #include "commands/createas.h" |
36 | | #include "commands/matview.h" |
37 | | #include "executor/functions.h" |
38 | | #include "executor/tqueue.h" |
39 | | #include "executor/tstoreReceiver.h" |
40 | | #include "libpq/libpq.h" |
41 | | #include "libpq/pqformat.h" |
42 | | #include "utils/portal.h" |
43 | | |
44 | | |
45 | | /* ---------------- |
46 | | * dummy DestReceiver functions |
47 | | * ---------------- |
48 | | */ |
49 | | static bool |
50 | | donothingReceive(TupleTableSlot *slot, DestReceiver *self) |
51 | 4.82M | { |
52 | 4.82M | return true; |
53 | 4.82M | } |
54 | | |
55 | | static void |
56 | | donothingStartup(DestReceiver *self, int operation, TupleDesc typeinfo) |
57 | 643 | { |
58 | 643 | } |
59 | | |
60 | | static void |
61 | | donothingCleanup(DestReceiver *self) |
62 | 22.4k | { |
63 | | /* this is used for both shutdown and destroy methods */ |
64 | 22.4k | } |
65 | | |
66 | | /* ---------------- |
67 | | * static DestReceiver structs for dest types needing no local state |
68 | | * ---------------- |
69 | | */ |
70 | | static DestReceiver donothingDR = { |
71 | | donothingReceive, donothingStartup, donothingCleanup, donothingCleanup, |
72 | | DestNone |
73 | | }; |
74 | | |
75 | | static DestReceiver debugtupDR = { |
76 | | debugtup, debugStartup, donothingCleanup, donothingCleanup, |
77 | | DestDebug |
78 | | }; |
79 | | |
80 | | static DestReceiver printsimpleDR = { |
81 | | printsimple, printsimple_startup, donothingCleanup, donothingCleanup, |
82 | | DestRemoteSimple |
83 | | }; |
84 | | |
85 | | static DestReceiver spi_printtupDR = { |
86 | | spi_printtup, spi_dest_startup, donothingCleanup, donothingCleanup, |
87 | | DestSPI |
88 | | }; |
89 | | |
90 | | /* Globally available receiver for DestNone */ |
91 | | DestReceiver *None_Receiver = &donothingDR; |
92 | | |
93 | | |
94 | | /* ---------------- |
95 | | * BeginCommand - initialize the destination at start of command |
96 | | * ---------------- |
97 | | */ |
98 | | void |
99 | | BeginCommand(const char *commandTag, CommandDest dest) |
100 | 678k | { |
101 | | /* Nothing to do at present */ |
102 | 678k | } |
103 | | |
104 | | /* ---------------- |
105 | | * CreateDestReceiver - return appropriate receiver function set for dest |
106 | | * ---------------- |
107 | | */ |
108 | | DestReceiver * |
109 | | CreateDestReceiver(CommandDest dest) |
110 | 769k | { |
111 | 769k | switch (dest) |
112 | 769k | { |
113 | 144k | case DestRemote: |
114 | 675k | case DestRemoteExecute: |
115 | 675k | return printtup_create_DR(dest); |
116 | | |
117 | 0 | case DestRemoteSimple: |
118 | 0 | return &printsimpleDR; |
119 | | |
120 | 101 | case DestNone: |
121 | 101 | return &donothingDR; |
122 | | |
123 | 1.02k | case DestDebug: |
124 | 1.02k | return &debugtupDR; |
125 | | |
126 | 76.4k | case DestSPI: |
127 | 76.4k | return &spi_printtupDR; |
128 | | |
129 | 11.8k | case DestTuplestore: |
130 | 11.8k | return CreateTuplestoreDestReceiver(); |
131 | | |
132 | 0 | case DestIntoRel: |
133 | 0 | return CreateIntoRelDestReceiver(NULL); |
134 | | |
135 | 46 | case DestCopyOut: |
136 | 46 | return CreateCopyDestReceiver(); |
137 | | |
138 | 4.62k | case DestSQLFunction: |
139 | 4.62k | return CreateSQLFunctionDestReceiver(); |
140 | | |
141 | 0 | case DestTransientRel: |
142 | 0 | return CreateTransientRelDestReceiver(InvalidOid); |
143 | | |
144 | 0 | case DestTupleQueue: |
145 | 0 | return CreateTupleQueueDestReceiver(NULL); |
146 | 769k | } |
147 | | |
148 | | /* should never get here */ |
149 | 0 | return &donothingDR; |
150 | 769k | } |
151 | | |
152 | | /* ---------------- |
153 | | * EndCommand - clean up the destination at end of command |
154 | | * ---------------- |
155 | | */ |
156 | | void |
157 | | EndCommand(const char *commandTag, CommandDest dest) |
158 | 563k | { |
159 | 563k | switch (dest) |
160 | 563k | { |
161 | 123k | case DestRemote: |
162 | 562k | case DestRemoteExecute: |
163 | 562k | case DestRemoteSimple: |
164 | | |
165 | | /* |
166 | | * We assume the commandTag is plain ASCII and therefore requires |
167 | | * no encoding conversion. |
168 | | */ |
169 | 562k | pq_putmessage('C', commandTag, strlen(commandTag) + 1); |
170 | 562k | break; |
171 | | |
172 | 0 | case DestNone: |
173 | 1.02k | case DestDebug: |
174 | 1.02k | case DestSPI: |
175 | 1.02k | case DestTuplestore: |
176 | 1.02k | case DestIntoRel: |
177 | 1.02k | case DestCopyOut: |
178 | 1.02k | case DestSQLFunction: |
179 | 1.02k | case DestTransientRel: |
180 | 1.02k | case DestTupleQueue: |
181 | 1.02k | break; |
182 | 563k | } |
183 | 563k | } |
184 | | |
185 | | /* ---------------- |
186 | | * NullCommand - tell dest that an empty query string was recognized |
187 | | * |
188 | | * In FE/BE protocol version 1.0, this hack is necessary to support |
189 | | * libpq's crufty way of determining whether a multiple-command |
190 | | * query string is done. In protocol 2.0 it's probably not really |
191 | | * necessary to distinguish empty queries anymore, but we still do it |
192 | | * for backwards compatibility with 1.0. In protocol 3.0 it has some |
193 | | * use again, since it ensures that there will be a recognizable end |
194 | | * to the response to an Execute message. |
195 | | * ---------------- |
196 | | */ |
197 | | void |
198 | | NullCommand(CommandDest dest) |
199 | 64 | { |
200 | 64 | switch (dest) |
201 | 64 | { |
202 | 10 | case DestRemote: |
203 | 64 | case DestRemoteExecute: |
204 | 64 | case DestRemoteSimple: |
205 | | |
206 | | /* |
207 | | * tell the fe that we saw an empty query string. In protocols |
208 | | * before 3.0 this has a useless empty-string message body. |
209 | | */ |
210 | 64 | if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) |
211 | 64 | pq_putemptymessage('I'); |
212 | 0 | else |
213 | 0 | pq_putmessage('I', "", 1); |
214 | 64 | break; |
215 | | |
216 | 0 | case DestNone: |
217 | 0 | case DestDebug: |
218 | 0 | case DestSPI: |
219 | 0 | case DestTuplestore: |
220 | 0 | case DestIntoRel: |
221 | 0 | case DestCopyOut: |
222 | 0 | case DestSQLFunction: |
223 | 0 | case DestTransientRel: |
224 | 0 | case DestTupleQueue: |
225 | 0 | break; |
226 | 64 | } |
227 | 64 | } |
228 | | |
229 | | /* ---------------- |
230 | | * ReadyForQuery - tell dest that we are ready for a new query |
231 | | * |
232 | | * The ReadyForQuery message is sent so that the FE can tell when |
233 | | * we are done processing a query string. |
234 | | * In versions 3.0 and up, it also carries a transaction state indicator. |
235 | | * |
236 | | * Note that by flushing the stdio buffer here, we can avoid doing it |
237 | | * most other places and thus reduce the number of separate packets sent. |
238 | | * ---------------- |
239 | | */ |
240 | | void |
241 | | ReadyForQuery(CommandDest dest) |
242 | 588k | { |
243 | 588k | switch (dest) |
244 | 588k | { |
245 | 587k | case DestRemote: |
246 | 587k | case DestRemoteExecute: |
247 | 587k | case DestRemoteSimple: |
248 | 587k | if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3) |
249 | 587k | { |
250 | 587k | StringInfoData buf; |
251 | | |
252 | 587k | pq_beginmessage(&buf, 'Z'); |
253 | 587k | pq_sendbyte(&buf, TransactionBlockStatusCode()); |
254 | 587k | pq_endmessage(&buf); |
255 | 587k | } |
256 | 25 | else |
257 | 25 | pq_putemptymessage('Z'); |
258 | | /* Flush output at end of cycle in any case. */ |
259 | 587k | pq_flush(); |
260 | 587k | break; |
261 | | |
262 | 0 | case DestNone: |
263 | 824 | case DestDebug: |
264 | 824 | case DestSPI: |
265 | 824 | case DestTuplestore: |
266 | 824 | case DestIntoRel: |
267 | 824 | case DestCopyOut: |
268 | 824 | case DestSQLFunction: |
269 | 824 | case DestTransientRel: |
270 | 824 | case DestTupleQueue: |
271 | 824 | break; |
272 | 588k | } |
273 | 588k | } |