34{
39 bool throw = true;
42 const char *result = "<unset>";
43 bool timeout_specified = false;
44 bool no_throw_specified = false;
45 bool mode_specified = false;
46
47
50
52 {
53 if (strcmp(defel->defname, "mode") == 0)
54 {
55 char *mode_str;
56
57 if (mode_specified)
59 mode_specified = true;
60
62
71 else
73 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
74 errmsg(
"unrecognized value for %s option \"%s\": \"%s\"",
75 "WAIT", defel->defname, mode_str),
77 }
78 else if (strcmp(defel->defname, "timeout") == 0)
79 {
80 char *timeout_str;
81 const char *hintmsg;
82 double result;
83
84 if (timeout_specified)
86 timeout_specified = true;
87
89
91 {
93 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
94 errmsg(
"invalid timeout value: \"%s\"", timeout_str),
95 hintmsg ?
errhint(
"%s",
_(hintmsg)) : 0);
96 }
97
98
99
100
101
102
103 result = rint(result);
104
105
108 errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
109 errmsg(
"timeout value is out of range"));
110
111 if (result < 0)
113 errcode(ERRCODE_INVALID_PARAMETER_VALUE),
114 errmsg(
"timeout cannot be negative"));
115
116 timeout = (
int64) result;
117 }
118 else if (strcmp(defel->defname, "no_throw") == 0)
119 {
120 if (no_throw_specified)
122
123 no_throw_specified = true;
124
126 }
127 else
128 {
131 errmsg(
"option \"%s\" not recognized",
132 defel->defname),
134 }
135 }
136
137
138
139
140
141
142
143
144
145
146
147
148
151
152
153
154
155
157
158
161 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
162 errmsg(
"WAIT FOR must be called without an active or registered snapshot"),
163 errdetail(
"WAIT FOR cannot be executed from a function or procedure, nor within a transaction with an isolation level higher than READ COMMITTED."));
164
165
166
167
168
170
171
172
173
174
176 {
179 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
180 errmsg(
"recovery is in progress"),
181 errhint(
"Waiting for primary_flush can only be done on a primary server. "
182 "Use standby_flush mode on a standby server.")));
183 }
184
185
186 waitLSNResult =
WaitForLSN(lsnType, lsn, timeout);
187
188
189
190
191 switch (waitLSNResult)
192 {
194
195 result = "success";
196 break;
197
199 if (throw)
200 {
202
203 switch (lsnType)
204 {
207 errcode(ERRCODE_QUERY_CANCELED),
208 errmsg(
"timed out while waiting for target LSN %X/%08X to be replayed; current standby_replay LSN %X/%08X",
211 break;
212
215 errcode(ERRCODE_QUERY_CANCELED),
216 errmsg(
"timed out while waiting for target LSN %X/%08X to be written; current standby_write LSN %X/%08X",
219 break;
220
223 errcode(ERRCODE_QUERY_CANCELED),
224 errmsg(
"timed out while waiting for target LSN %X/%08X to be flushed; current standby_flush LSN %X/%08X",
227 break;
228
231 errcode(ERRCODE_QUERY_CANCELED),
232 errmsg(
"timed out while waiting for target LSN %X/%08X to be flushed; current primary_flush LSN %X/%08X",
235 break;
236
237 default:
238 elog(
ERROR,
"unexpected wait LSN type %d", lsnType);
240 }
241 }
242 else
243 result = "timeout";
244 break;
245
247 if (throw)
248 {
250 {
252
253 switch (lsnType)
254 {
257 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
258 errmsg(
"recovery is not in progress"),
259 errdetail(
"Recovery ended before target LSN %X/%08X was replayed; last standby_replay LSN %X/%08X.",
262 break;
263
266 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
267 errmsg(
"recovery is not in progress"),
268 errdetail(
"Recovery ended before target LSN %X/%08X was written; last standby_write LSN %X/%08X.",
271 break;
272
275 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
276 errmsg(
"recovery is not in progress"),
277 errdetail(
"Recovery ended before target LSN %X/%08X was flushed; last standby_flush LSN %X/%08X.",
280 break;
281
282 default:
283 elog(
ERROR,
"unexpected wait LSN type %d", lsnType);
285 }
286 }
287 else
288 {
289 switch (lsnType)
290 {
293 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
294 errmsg(
"recovery is not in progress"),
295 errhint(
"Waiting for the standby_replay LSN can only be executed during recovery."));
296 break;
297
300 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
301 errmsg(
"recovery is not in progress"),
302 errhint(
"Waiting for the standby_write LSN can only be executed during recovery."));
303 break;
304
307 errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
308 errmsg(
"recovery is not in progress"),
309 errhint(
"Waiting for the standby_flush LSN can only be executed during recovery."));
310 break;
311
312 default:
313 elog(
ERROR,
"unexpected wait LSN type %d", lsnType);
315 }
316 }
317 }
318 else
319 result = "not in recovery";
320 break;
321 }
322
323
325
326
328
329
331
333}
#define FLOAT8_FITS_IN_INT64(num)
char * defGetString(DefElem *def)
bool defGetBoolean(DefElem *def)
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
const TupleTableSlotOps TTSOpsVirtual
void end_tup_output(TupOutputState *tstate)
TupOutputState * begin_tup_output_tupdesc(DestReceiver *dest, TupleDesc tupdesc, const TupleTableSlotOps *tts_ops)
#define do_text_output_oneline(tstate, str_to_emit)
#define DirectFunctionCall1(func, arg1)
bool parse_real(const char *value, double *result, int flags, const char **hintmsg)
Assert(PointerIsAligned(start, uint64))
int parser_errposition(ParseState *pstate, int location)
#define foreach_node(type, var, lst)
Datum pg_lsn_in(PG_FUNCTION_ARGS)
static XLogRecPtr DatumGetLSN(Datum X)
int pg_strcasecmp(const char *s1, const char *s2)
static Datum CStringGetDatum(const char *X)
bool ActiveSnapshotSet(void)
bool HaveRegisteredOrActiveSnapshot(void)
void PopActiveSnapshot(void)
void InvalidateCatalogSnapshot(void)
#define InvalidTransactionId
TupleDesc WaitStmtResultDesc(WaitStmt *stmt)
bool RecoveryInProgress(void)
#define LSN_FORMAT_ARGS(lsn)
bool PromoteIsTriggered(void)
XLogRecPtr GetCurrentLSNForWaitType(WaitLSNType lsnType)
WaitLSNResult WaitForLSN(WaitLSNType lsnType, XLogRecPtr targetLSN, int64 timeout)
@ WAIT_LSN_RESULT_NOT_IN_RECOVERY
@ WAIT_LSN_RESULT_TIMEOUT
@ WAIT_LSN_RESULT_SUCCESS
@ WAIT_LSN_TYPE_PRIMARY_FLUSH
@ WAIT_LSN_TYPE_STANDBY_REPLAY
@ WAIT_LSN_TYPE_STANDBY_FLUSH
@ WAIT_LSN_TYPE_STANDBY_WRITE