PostgreSQL Source Code  git master
test_decoding.c File Reference
#include "postgres.h"
#include "catalog/pg_type.h"
#include "replication/logical.h"
#include "replication/origin.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
Include dependency graph for test_decoding.c:

Go to the source code of this file.

Data Structures

struct  TestDecodingData
 
struct  TestDecodingTxnData
 

Functions

void _PG_init (void)
 
void _PG_output_plugin_init (OutputPluginCallbacks *cb)
 
static void pg_decode_startup (LogicalDecodingContext *ctx, OutputPluginOptions *opt, bool is_init)
 
static void pg_decode_shutdown (LogicalDecodingContext *ctx)
 
static void pg_decode_begin_txn (LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
 
static void pg_output_begin (LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)
 
static void pg_decode_commit_txn (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)
 
static void pg_decode_change (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, Relation rel, ReorderBufferChange *change)
 
static void pg_decode_truncate (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change)
 
static bool pg_decode_filter (LogicalDecodingContext *ctx, RepOriginId origin_id)
 
static void pg_decode_message (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, const char *prefix, Size sz, const char *message)
 
static void pg_decode_stream_start (LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
 
static void pg_output_stream_start (LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)
 
static void pg_decode_stream_stop (LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
 
static void pg_decode_stream_abort (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr abort_lsn)
 
static void pg_decode_stream_commit (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)
 
static void pg_decode_stream_change (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change)
 
static void pg_decode_stream_message (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, const char *prefix, Size sz, const char *message)
 
static void pg_decode_stream_truncate (LogicalDecodingContext *ctx, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change)
 
static void print_literal (StringInfo s, Oid typid, char *outputstr)
 
static void tuple_to_stringinfo (StringInfo s, TupleDesc tupdesc, HeapTuple tuple, bool skip_nulls)
 

Variables

 PG_MODULE_MAGIC
 

Function Documentation

◆ _PG_init()

void _PG_init ( void  )

Definition at line 107 of file test_decoding.c.

108 {
109  /* other plugins can perform things here */
110 }

◆ _PG_output_plugin_init()

void _PG_output_plugin_init ( OutputPluginCallbacks cb)

Definition at line 114 of file test_decoding.c.

References AssertVariableIsOfType, OutputPluginCallbacks::begin_cb, OutputPluginCallbacks::change_cb, OutputPluginCallbacks::commit_cb, OutputPluginCallbacks::filter_by_origin_cb, OutputPluginCallbacks::message_cb, pg_decode_begin_txn(), pg_decode_change(), pg_decode_commit_txn(), pg_decode_filter(), pg_decode_message(), pg_decode_shutdown(), pg_decode_startup(), pg_decode_stream_abort(), pg_decode_stream_change(), pg_decode_stream_commit(), pg_decode_stream_message(), pg_decode_stream_start(), pg_decode_stream_stop(), pg_decode_stream_truncate(), pg_decode_truncate(), OutputPluginCallbacks::shutdown_cb, OutputPluginCallbacks::startup_cb, OutputPluginCallbacks::stream_abort_cb, OutputPluginCallbacks::stream_change_cb, OutputPluginCallbacks::stream_commit_cb, OutputPluginCallbacks::stream_message_cb, OutputPluginCallbacks::stream_start_cb, OutputPluginCallbacks::stream_stop_cb, OutputPluginCallbacks::stream_truncate_cb, and OutputPluginCallbacks::truncate_cb.

115 {
117 
133 }
LogicalDecodeTruncateCB truncate_cb
static void pg_decode_shutdown(LogicalDecodingContext *ctx)
static void pg_decode_stream_abort(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr abort_lsn)
static bool pg_decode_filter(LogicalDecodingContext *ctx, RepOriginId origin_id)
static void pg_decode_begin_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
LogicalDecodeMessageCB message_cb
LogicalDecodeStreamMessageCB stream_message_cb
static void pg_decode_stream_commit(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)
LogicalDecodeStreamAbortCB stream_abort_cb
static void pg_decode_stream_start(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
static void pg_decode_stream_truncate(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change)
LogicalDecodeCommitCB commit_cb
static void pg_decode_stream_stop(LogicalDecodingContext *ctx, ReorderBufferTXN *txn)
void(* LogicalOutputPluginInit)(struct OutputPluginCallbacks *cb)
Definition: output_plugin.h:36
static void pg_decode_stream_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, const char *prefix, Size sz, const char *message)
static void pg_decode_message(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr message_lsn, bool transactional, const char *prefix, Size sz, const char *message)
static void pg_decode_truncate(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, int nrelations, Relation relations[], ReorderBufferChange *change)
static void pg_decode_commit_txn(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, XLogRecPtr commit_lsn)
LogicalDecodeChangeCB change_cb
LogicalDecodeStreamTruncateCB stream_truncate_cb
static void pg_decode_startup(LogicalDecodingContext *ctx, OutputPluginOptions *opt, bool is_init)
static void pg_decode_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, Relation rel, ReorderBufferChange *change)
LogicalDecodeShutdownCB shutdown_cb
LogicalDecodeStreamCommitCB stream_commit_cb
LogicalDecodeStartupCB startup_cb
static void pg_decode_stream_change(LogicalDecodingContext *ctx, ReorderBufferTXN *txn, Relation relation, ReorderBufferChange *change)
LogicalDecodeStreamStartCB stream_start_cb
LogicalDecodeBeginCB begin_cb
LogicalDecodeStreamStopCB stream_stop_cb
LogicalDecodeFilterByOriginCB filter_by_origin_cb
LogicalDecodeStreamChangeCB stream_change_cb
void _PG_output_plugin_init(OutputPluginCallbacks *cb)
#define AssertVariableIsOfType(varname, typename)
Definition: c.h:959

◆ pg_decode_begin_txn()

static void pg_decode_begin_txn ( LogicalDecodingContext ctx,
ReorderBufferTXN txn 
)
static

Definition at line 269 of file test_decoding.c.

References LogicalDecodingContext::context, MemoryContextAllocZero(), LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, pg_output_begin(), TestDecodingData::skip_empty_xacts, and TestDecodingTxnData::xact_wrote_changes.

Referenced by _PG_output_plugin_init().

270 {
272  TestDecodingTxnData *txndata =
274 
275  txndata->xact_wrote_changes = false;
276  txn->output_plugin_private = txndata;
277 
278  if (data->skip_empty_xacts)
279  return;
280 
281  pg_output_begin(ctx, data, txn, true);
282 }
void * output_plugin_private
Definition: logical.h:75
MemoryContext context
Definition: logical.h:35
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
static void pg_output_begin(LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)
void * output_plugin_private

◆ pg_decode_change()

static void pg_decode_change ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
Relation  rel,
ReorderBufferChange change 
)
static

Definition at line 464 of file test_decoding.c.

References ReorderBufferChange::action, appendStringInfoChar(), appendStringInfoString(), Assert, TestDecodingData::context, ReorderBufferChange::data, get_namespace_name(), get_rel_name(), get_rel_namespace(), MemoryContextReset(), MemoryContextSwitchTo(), NameStr, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pg_output_begin(), quote_qualified_identifier(), RelationGetDescr, RelationGetForm, RelationGetRelid, REORDER_BUFFER_CHANGE_DELETE, REORDER_BUFFER_CHANGE_INSERT, REORDER_BUFFER_CHANGE_UPDATE, TestDecodingData::skip_empty_xacts, ReorderBufferChange::tp, tuple_to_stringinfo(), and TestDecodingTxnData::xact_wrote_changes.

Referenced by _PG_output_plugin_init().

466 {
467  TestDecodingData *data;
468  TestDecodingTxnData *txndata;
469  Form_pg_class class_form;
470  TupleDesc tupdesc;
471  MemoryContext old;
472 
473  data = ctx->output_plugin_private;
474  txndata = txn->output_plugin_private;
475 
476  /* output BEGIN if we haven't yet */
477  if (data->skip_empty_xacts && !txndata->xact_wrote_changes)
478  {
479  pg_output_begin(ctx, data, txn, false);
480  }
481  txndata->xact_wrote_changes = true;
482 
483  class_form = RelationGetForm(relation);
484  tupdesc = RelationGetDescr(relation);
485 
486  /* Avoid leaking memory by using and resetting our own context */
487  old = MemoryContextSwitchTo(data->context);
488 
489  OutputPluginPrepareWrite(ctx, true);
490 
491  appendStringInfoString(ctx->out, "table ");
494  class_form->relrewrite ?
495  get_rel_name(class_form->relrewrite) :
496  NameStr(class_form->relname)));
497  appendStringInfoChar(ctx->out, ':');
498 
499  switch (change->action)
500  {
502  appendStringInfoString(ctx->out, " INSERT:");
503  if (change->data.tp.newtuple == NULL)
504  appendStringInfoString(ctx->out, " (no-tuple-data)");
505  else
506  tuple_to_stringinfo(ctx->out, tupdesc,
507  &change->data.tp.newtuple->tuple,
508  false);
509  break;
511  appendStringInfoString(ctx->out, " UPDATE:");
512  if (change->data.tp.oldtuple != NULL)
513  {
514  appendStringInfoString(ctx->out, " old-key:");
515  tuple_to_stringinfo(ctx->out, tupdesc,
516  &change->data.tp.oldtuple->tuple,
517  true);
518  appendStringInfoString(ctx->out, " new-tuple:");
519  }
520 
521  if (change->data.tp.newtuple == NULL)
522  appendStringInfoString(ctx->out, " (no-tuple-data)");
523  else
524  tuple_to_stringinfo(ctx->out, tupdesc,
525  &change->data.tp.newtuple->tuple,
526  false);
527  break;
529  appendStringInfoString(ctx->out, " DELETE:");
530 
531  /* if there was no PK, we only know that a delete happened */
532  if (change->data.tp.oldtuple == NULL)
533  appendStringInfoString(ctx->out, " (no-tuple-data)");
534  /* In DELETE, only the replica identity is present; display that */
535  else
536  tuple_to_stringinfo(ctx->out, tupdesc,
537  &change->data.tp.oldtuple->tuple,
538  true);
539  break;
540  default:
541  Assert(false);
542  }
543 
546 
547  OutputPluginWrite(ctx, true);
548 }
static void tuple_to_stringinfo(StringInfo s, TupleDesc tupdesc, HeapTuple tuple, bool skip_nulls)
#define RelationGetDescr(relation)
Definition: rel.h:483
#define RelationGetForm(relation)
Definition: rel.h:451
Oid get_rel_namespace(Oid relid)
Definition: lsyscache.c:1869
union ReorderBufferChange::@98 data
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void * output_plugin_private
Definition: logical.h:75
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:137
enum ReorderBufferChangeType action
Definition: reorderbuffer.h:84
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11018
MemoryContext context
Definition: test_decoding.c:33
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
#define Assert(condition)
Definition: c.h:800
static void pg_output_begin(LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)
FormData_pg_class * Form_pg_class
Definition: pg_class.h:153
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
struct ReorderBufferChange::@98::@99 tp
#define NameStr(name)
Definition: c.h:677
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1845
void * output_plugin_private
#define RelationGetRelid(relation)
Definition: rel.h:457

◆ pg_decode_commit_txn()

static void pg_decode_commit_txn ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
XLogRecPtr  commit_lsn 
)
static

Definition at line 297 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), ReorderBufferTXN::commit_time, TestDecodingData::include_timestamp, TestDecodingData::include_xids, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pfree(), TestDecodingData::skip_empty_xacts, timestamptz_to_str(), TestDecodingTxnData::xact_wrote_changes, and ReorderBufferTXN::xid.

Referenced by _PG_output_plugin_init().

299 {
302  bool xact_wrote_changes = txndata->xact_wrote_changes;
303 
304  pfree(txndata);
305  txn->output_plugin_private = NULL;
306 
307  if (data->skip_empty_xacts && !xact_wrote_changes)
308  return;
309 
310  OutputPluginPrepareWrite(ctx, true);
311  if (data->include_xids)
312  appendStringInfo(ctx->out, "COMMIT %u", txn->xid);
313  else
314  appendStringInfoString(ctx->out, "COMMIT");
315 
316  if (data->include_timestamp)
317  appendStringInfo(ctx->out, " (at %s)",
319 
320  OutputPluginWrite(ctx, true);
321 }
TimestampTz commit_time
void * output_plugin_private
Definition: logical.h:75
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void * output_plugin_private
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1772

◆ pg_decode_filter()

static bool pg_decode_filter ( LogicalDecodingContext ctx,
RepOriginId  origin_id 
)
static

Definition at line 324 of file test_decoding.c.

References InvalidRepOriginId, TestDecodingData::only_local, and LogicalDecodingContext::output_plugin_private.

Referenced by _PG_output_plugin_init().

326 {
328 
329  if (data->only_local && origin_id != InvalidRepOriginId)
330  return true;
331  return false;
332 }
void * output_plugin_private
Definition: logical.h:75
#define InvalidRepOriginId
Definition: origin.h:33

◆ pg_decode_message()

static void pg_decode_message ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
XLogRecPtr  message_lsn,
bool  transactional,
const char *  prefix,
Size  sz,
const char *  message 
)
static

Definition at line 606 of file test_decoding.c.

References appendBinaryStringInfo(), appendStringInfo(), LogicalDecodingContext::out, OutputPluginPrepareWrite(), and OutputPluginWrite().

Referenced by _PG_output_plugin_init().

609 {
610  OutputPluginPrepareWrite(ctx, true);
611  appendStringInfo(ctx->out, "message: transactional: %d prefix: %s, sz: %zu content:",
612  transactional, prefix, sz);
613  appendBinaryStringInfo(ctx->out, message, sz);
614  OutputPluginWrite(ctx, true);
615 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ pg_decode_shutdown()

static void pg_decode_shutdown ( LogicalDecodingContext ctx)
static

Definition at line 259 of file test_decoding.c.

References TestDecodingData::context, MemoryContextDelete(), and LogicalDecodingContext::output_plugin_private.

Referenced by _PG_output_plugin_init().

260 {
262 
263  /* cleanup our own resources via memory context reset */
265 }
void MemoryContextDelete(MemoryContext context)
Definition: mcxt.c:212
void * output_plugin_private
Definition: logical.h:75
MemoryContext context
Definition: test_decoding.c:33

◆ pg_decode_startup()

static void pg_decode_startup ( LogicalDecodingContext ctx,
OutputPluginOptions opt,
bool  is_init 
)
static

Definition at line 138 of file test_decoding.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, DefElem::arg, Assert, TestDecodingData::context, LogicalDecodingContext::context, DefElem::defname, ereport, errcode(), errmsg(), ERROR, TestDecodingData::include_timestamp, TestDecodingData::include_xids, IsA, lfirst, TestDecodingData::only_local, OUTPUT_PLUGIN_BINARY_OUTPUT, LogicalDecodingContext::output_plugin_options, LogicalDecodingContext::output_plugin_private, OUTPUT_PLUGIN_TEXTUAL_OUTPUT, OutputPluginOptions::output_type, palloc0(), parse_bool(), OutputPluginOptions::receive_rewrites, TestDecodingData::skip_empty_xacts, LogicalDecodingContext::streaming, and strVal.

Referenced by _PG_output_plugin_init().

140 {
141  ListCell *option;
142  TestDecodingData *data;
143  bool enable_streaming = false;
144 
145  data = palloc0(sizeof(TestDecodingData));
147  "text conversion context",
149  data->include_xids = true;
150  data->include_timestamp = false;
151  data->skip_empty_xacts = false;
152  data->only_local = false;
153 
154  ctx->output_plugin_private = data;
155 
157  opt->receive_rewrites = false;
158 
159  foreach(option, ctx->output_plugin_options)
160  {
161  DefElem *elem = lfirst(option);
162 
163  Assert(elem->arg == NULL || IsA(elem->arg, String));
164 
165  if (strcmp(elem->defname, "include-xids") == 0)
166  {
167  /* if option does not provide a value, it means its value is true */
168  if (elem->arg == NULL)
169  data->include_xids = true;
170  else if (!parse_bool(strVal(elem->arg), &data->include_xids))
171  ereport(ERROR,
172  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
173  errmsg("could not parse value \"%s\" for parameter \"%s\"",
174  strVal(elem->arg), elem->defname)));
175  }
176  else if (strcmp(elem->defname, "include-timestamp") == 0)
177  {
178  if (elem->arg == NULL)
179  data->include_timestamp = true;
180  else if (!parse_bool(strVal(elem->arg), &data->include_timestamp))
181  ereport(ERROR,
182  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
183  errmsg("could not parse value \"%s\" for parameter \"%s\"",
184  strVal(elem->arg), elem->defname)));
185  }
186  else if (strcmp(elem->defname, "force-binary") == 0)
187  {
188  bool force_binary;
189 
190  if (elem->arg == NULL)
191  continue;
192  else if (!parse_bool(strVal(elem->arg), &force_binary))
193  ereport(ERROR,
194  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
195  errmsg("could not parse value \"%s\" for parameter \"%s\"",
196  strVal(elem->arg), elem->defname)));
197 
198  if (force_binary)
200  }
201  else if (strcmp(elem->defname, "skip-empty-xacts") == 0)
202  {
203 
204  if (elem->arg == NULL)
205  data->skip_empty_xacts = true;
206  else if (!parse_bool(strVal(elem->arg), &data->skip_empty_xacts))
207  ereport(ERROR,
208  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
209  errmsg("could not parse value \"%s\" for parameter \"%s\"",
210  strVal(elem->arg), elem->defname)));
211  }
212  else if (strcmp(elem->defname, "only-local") == 0)
213  {
214 
215  if (elem->arg == NULL)
216  data->only_local = true;
217  else if (!parse_bool(strVal(elem->arg), &data->only_local))
218  ereport(ERROR,
219  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
220  errmsg("could not parse value \"%s\" for parameter \"%s\"",
221  strVal(elem->arg), elem->defname)));
222  }
223  else if (strcmp(elem->defname, "include-rewrites") == 0)
224  {
225 
226  if (elem->arg == NULL)
227  continue;
228  else if (!parse_bool(strVal(elem->arg), &opt->receive_rewrites))
229  ereport(ERROR,
230  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
231  errmsg("could not parse value \"%s\" for parameter \"%s\"",
232  strVal(elem->arg), elem->defname)));
233  }
234  else if (strcmp(elem->defname, "stream-changes") == 0)
235  {
236  if (elem->arg == NULL)
237  continue;
238  else if (!parse_bool(strVal(elem->arg), &enable_streaming))
239  ereport(ERROR,
240  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
241  errmsg("could not parse value \"%s\" for parameter \"%s\"",
242  strVal(elem->arg), elem->defname)));
243  }
244  else
245  {
246  ereport(ERROR,
247  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
248  errmsg("option \"%s\" = \"%s\" is unknown",
249  elem->defname,
250  elem->arg ? strVal(elem->arg) : "(null)")));
251  }
252  }
253 
254  ctx->streaming &= enable_streaming;
255 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:578
#define AllocSetContextCreate
Definition: memutils.h:170
#define strVal(v)
Definition: value.h:54
int errcode(int sqlerrcode)
Definition: elog.c:691
void * output_plugin_private
Definition: logical.h:75
MemoryContext context
Definition: logical.h:35
List * output_plugin_options
Definition: logical.h:58
bool parse_bool(const char *value, bool *result)
Definition: bool.c:30
OutputPluginOutputType output_type
Definition: output_plugin.h:28
#define ERROR
Definition: elog.h:43
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:192
Node * arg
Definition: parsenodes.h:734
MemoryContext context
Definition: test_decoding.c:33
void * palloc0(Size size)
Definition: mcxt.c:981
#define ereport(elevel,...)
Definition: elog.h:155
#define Assert(condition)
Definition: c.h:800
#define lfirst(lc)
Definition: pg_list.h:169
int errmsg(const char *fmt,...)
Definition: elog.c:902
char * defname
Definition: parsenodes.h:733

◆ pg_decode_stream_abort()

static void pg_decode_stream_abort ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
XLogRecPtr  abort_lsn 
)
static

Definition at line 671 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), Assert, TestDecodingData::include_xids, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pfree(), TestDecodingData::skip_empty_xacts, ReorderBufferTXN::toptxn, TestDecodingTxnData::xact_wrote_changes, and ReorderBufferTXN::xid.

Referenced by _PG_output_plugin_init().

674 {
676 
677  /*
678  * stream abort can be sent for an individual subtransaction but we
679  * maintain the output_plugin_private only under the toptxn so if this is
680  * not the toptxn then fetch the toptxn.
681  */
682  ReorderBufferTXN *toptxn = txn->toptxn ? txn->toptxn : txn;
683  TestDecodingTxnData *txndata = toptxn->output_plugin_private;
684  bool xact_wrote_changes = txndata->xact_wrote_changes;
685 
686  if (txn->toptxn == NULL)
687  {
688  Assert(txn->output_plugin_private != NULL);
689  pfree(txndata);
690  txn->output_plugin_private = NULL;
691  }
692 
693  if (data->skip_empty_xacts && !xact_wrote_changes)
694  return;
695 
696  OutputPluginPrepareWrite(ctx, true);
697  if (data->include_xids)
698  appendStringInfo(ctx->out, "aborting streamed (sub)transaction TXN %u", txn->xid);
699  else
700  appendStringInfoString(ctx->out, "aborting streamed (sub)transaction");
701  OutputPluginWrite(ctx, true);
702 }
void * output_plugin_private
Definition: logical.h:75
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
struct ReorderBufferTXN * toptxn
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
#define Assert(condition)
Definition: c.h:800
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void * output_plugin_private

◆ pg_decode_stream_change()

static void pg_decode_stream_change ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
Relation  relation,
ReorderBufferChange change 
)
static

Definition at line 739 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), TestDecodingData::include_xids, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pg_output_stream_start(), TestDecodingData::skip_empty_xacts, TestDecodingTxnData::stream_wrote_changes, TestDecodingTxnData::xact_wrote_changes, and ReorderBufferTXN::xid.

Referenced by _PG_output_plugin_init().

743 {
746 
747  /* output stream start if we haven't yet */
748  if (data->skip_empty_xacts && !txndata->stream_wrote_changes)
749  {
750  pg_output_stream_start(ctx, data, txn, false);
751  }
752  txndata->xact_wrote_changes = txndata->stream_wrote_changes = true;
753 
754  OutputPluginPrepareWrite(ctx, true);
755  if (data->include_xids)
756  appendStringInfo(ctx->out, "streaming change for TXN %u", txn->xid);
757  else
758  appendStringInfoString(ctx->out, "streaming change for transaction");
759  OutputPluginWrite(ctx, true);
760 }
void * output_plugin_private
Definition: logical.h:75
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void * output_plugin_private
static void pg_output_stream_start(LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)

◆ pg_decode_stream_commit()

static void pg_decode_stream_commit ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
XLogRecPtr  commit_lsn 
)
static

Definition at line 705 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), ReorderBufferTXN::commit_time, TestDecodingData::include_timestamp, TestDecodingData::include_xids, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pfree(), TestDecodingData::skip_empty_xacts, timestamptz_to_str(), TestDecodingTxnData::xact_wrote_changes, and ReorderBufferTXN::xid.

Referenced by _PG_output_plugin_init().

708 {
711  bool xact_wrote_changes = txndata->xact_wrote_changes;
712 
713  pfree(txndata);
714  txn->output_plugin_private = NULL;
715 
716  if (data->skip_empty_xacts && !xact_wrote_changes)
717  return;
718 
719  OutputPluginPrepareWrite(ctx, true);
720 
721  if (data->include_xids)
722  appendStringInfo(ctx->out, "committing streamed transaction TXN %u", txn->xid);
723  else
724  appendStringInfoString(ctx->out, "committing streamed transaction");
725 
726  if (data->include_timestamp)
727  appendStringInfo(ctx->out, " (at %s)",
729 
730  OutputPluginWrite(ctx, true);
731 }
TimestampTz commit_time
void * output_plugin_private
Definition: logical.h:75
void pfree(void *pointer)
Definition: mcxt.c:1057
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void * output_plugin_private
const char * timestamptz_to_str(TimestampTz t)
Definition: timestamp.c:1772

◆ pg_decode_stream_message()

static void pg_decode_stream_message ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
XLogRecPtr  message_lsn,
bool  transactional,
const char *  prefix,
Size  sz,
const char *  message 
)
static

Definition at line 768 of file test_decoding.c.

References appendBinaryStringInfo(), appendStringInfo(), LogicalDecodingContext::out, OutputPluginPrepareWrite(), and OutputPluginWrite().

Referenced by _PG_output_plugin_init().

771 {
772  OutputPluginPrepareWrite(ctx, true);
773 
774  if (transactional)
775  {
776  appendStringInfo(ctx->out, "streaming message: transactional: %d prefix: %s, sz: %zu",
777  transactional, prefix, sz);
778  }
779  else
780  {
781  appendStringInfo(ctx->out, "streaming message: transactional: %d prefix: %s, sz: %zu content:",
782  transactional, prefix, sz);
783  appendBinaryStringInfo(ctx->out, message, sz);
784  }
785 
786  OutputPluginWrite(ctx, true);
787 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ pg_decode_stream_start()

static void pg_decode_stream_start ( LogicalDecodingContext ctx,
ReorderBufferTXN txn 
)
static

Definition at line 618 of file test_decoding.c.

References LogicalDecodingContext::context, MemoryContextAllocZero(), LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, pg_output_stream_start(), TestDecodingData::skip_empty_xacts, TestDecodingTxnData::stream_wrote_changes, and TestDecodingTxnData::xact_wrote_changes.

Referenced by _PG_output_plugin_init().

620 {
623 
624  /*
625  * Allocate the txn plugin data for the first stream in the transaction.
626  */
627  if (txndata == NULL)
628  {
629  txndata =
631  txndata->xact_wrote_changes = false;
632  txn->output_plugin_private = txndata;
633  }
634 
635  txndata->stream_wrote_changes = false;
636  if (data->skip_empty_xacts)
637  return;
638  pg_output_stream_start(ctx, data, txn, true);
639 }
void * output_plugin_private
Definition: logical.h:75
MemoryContext context
Definition: logical.h:35
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
void * output_plugin_private
static void pg_output_stream_start(LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)

◆ pg_decode_stream_stop()

static void pg_decode_stream_stop ( LogicalDecodingContext ctx,
ReorderBufferTXN txn 
)
static

Definition at line 653 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), TestDecodingData::include_xids, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), TestDecodingData::skip_empty_xacts, TestDecodingTxnData::stream_wrote_changes, and ReorderBufferTXN::xid.

Referenced by _PG_output_plugin_init().

655 {
658 
659  if (data->skip_empty_xacts && !txndata->stream_wrote_changes)
660  return;
661 
662  OutputPluginPrepareWrite(ctx, true);
663  if (data->include_xids)
664  appendStringInfo(ctx->out, "closing a streamed block for transaction TXN %u", txn->xid);
665  else
666  appendStringInfoString(ctx->out, "closing a streamed block for transaction");
667  OutputPluginWrite(ctx, true);
668 }
void * output_plugin_private
Definition: logical.h:75
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void * output_plugin_private

◆ pg_decode_stream_truncate()

static void pg_decode_stream_truncate ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
int  nrelations,
Relation  relations[],
ReorderBufferChange change 
)
static

Definition at line 794 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), TestDecodingData::include_xids, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pg_output_stream_start(), TestDecodingData::skip_empty_xacts, TestDecodingTxnData::stream_wrote_changes, TestDecodingTxnData::xact_wrote_changes, and ReorderBufferTXN::xid.

Referenced by _PG_output_plugin_init().

797 {
800 
801  if (data->skip_empty_xacts && !txndata->stream_wrote_changes)
802  {
803  pg_output_stream_start(ctx, data, txn, false);
804  }
805  txndata->xact_wrote_changes = txndata->stream_wrote_changes = true;
806 
807  OutputPluginPrepareWrite(ctx, true);
808  if (data->include_xids)
809  appendStringInfo(ctx->out, "streaming truncate for TXN %u", txn->xid);
810  else
811  appendStringInfoString(ctx->out, "streaming truncate for transaction");
812  OutputPluginWrite(ctx, true);
813 }
void * output_plugin_private
Definition: logical.h:75
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70
void * output_plugin_private
static void pg_output_stream_start(LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)

◆ pg_decode_truncate()

static void pg_decode_truncate ( LogicalDecodingContext ctx,
ReorderBufferTXN txn,
int  nrelations,
Relation  relations[],
ReorderBufferChange change 
)
static

Definition at line 551 of file test_decoding.c.

References appendStringInfoString(), TestDecodingData::context, ReorderBufferChange::data, get_namespace_name(), i, MemoryContextReset(), MemoryContextSwitchTo(), NameStr, LogicalDecodingContext::out, LogicalDecodingContext::output_plugin_private, ReorderBufferTXN::output_plugin_private, OutputPluginPrepareWrite(), OutputPluginWrite(), pg_output_begin(), quote_qualified_identifier(), TestDecodingData::skip_empty_xacts, ReorderBufferChange::truncate, and TestDecodingTxnData::xact_wrote_changes.

Referenced by _PG_output_plugin_init().

553 {
554  TestDecodingData *data;
555  TestDecodingTxnData *txndata;
556  MemoryContext old;
557  int i;
558 
559  data = ctx->output_plugin_private;
560  txndata = txn->output_plugin_private;
561 
562  /* output BEGIN if we haven't yet */
563  if (data->skip_empty_xacts && !txndata->xact_wrote_changes)
564  {
565  pg_output_begin(ctx, data, txn, false);
566  }
567  txndata->xact_wrote_changes = true;
568 
569  /* Avoid leaking memory by using and resetting our own context */
570  old = MemoryContextSwitchTo(data->context);
571 
572  OutputPluginPrepareWrite(ctx, true);
573 
574  appendStringInfoString(ctx->out, "table ");
575 
576  for (i = 0; i < nrelations; i++)
577  {
578  if (i > 0)
579  appendStringInfoString(ctx->out, ", ");
580 
582  quote_qualified_identifier(get_namespace_name(relations[i]->rd_rel->relnamespace),
583  NameStr(relations[i]->rd_rel->relname)));
584  }
585 
586  appendStringInfoString(ctx->out, ": TRUNCATE:");
587 
588  if (change->data.truncate.restart_seqs
589  || change->data.truncate.cascade)
590  {
591  if (change->data.truncate.restart_seqs)
592  appendStringInfoString(ctx->out, " restart_seqs");
593  if (change->data.truncate.cascade)
594  appendStringInfoString(ctx->out, " cascade");
595  }
596  else
597  appendStringInfoString(ctx->out, " (no-flags)");
598 
601 
602  OutputPluginWrite(ctx, true);
603 }
union ReorderBufferChange::@98 data
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void * output_plugin_private
Definition: logical.h:75
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:137
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
char * get_namespace_name(Oid nspid)
Definition: lsyscache.c:3196
char * quote_qualified_identifier(const char *qualifier, const char *ident)
Definition: ruleutils.c:11018
MemoryContext context
Definition: test_decoding.c:33
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
static void pg_output_begin(LogicalDecodingContext *ctx, TestDecodingData *data, ReorderBufferTXN *txn, bool last_write)
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
struct ReorderBufferChange::@98::@100 truncate
StringInfo out
Definition: logical.h:70
int i
#define NameStr(name)
Definition: c.h:677
void * output_plugin_private

◆ pg_output_begin()

static void pg_output_begin ( LogicalDecodingContext ctx,
TestDecodingData data,
ReorderBufferTXN txn,
bool  last_write 
)
static

Definition at line 285 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), TestDecodingData::include_xids, LogicalDecodingContext::out, OutputPluginPrepareWrite(), OutputPluginWrite(), and ReorderBufferTXN::xid.

Referenced by pg_decode_begin_txn(), pg_decode_change(), and pg_decode_truncate().

286 {
287  OutputPluginPrepareWrite(ctx, last_write);
288  if (data->include_xids)
289  appendStringInfo(ctx->out, "BEGIN %u", txn->xid);
290  else
291  appendStringInfoString(ctx->out, "BEGIN");
292  OutputPluginWrite(ctx, last_write);
293 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70

◆ pg_output_stream_start()

static void pg_output_stream_start ( LogicalDecodingContext ctx,
TestDecodingData data,
ReorderBufferTXN txn,
bool  last_write 
)
static

Definition at line 642 of file test_decoding.c.

References appendStringInfo(), appendStringInfoString(), TestDecodingData::include_xids, LogicalDecodingContext::out, OutputPluginPrepareWrite(), OutputPluginWrite(), and ReorderBufferTXN::xid.

Referenced by pg_decode_stream_change(), pg_decode_stream_start(), and pg_decode_stream_truncate().

643 {
644  OutputPluginPrepareWrite(ctx, last_write);
645  if (data->include_xids)
646  appendStringInfo(ctx->out, "opening a streamed block for transaction TXN %u", txn->xid);
647  else
648  appendStringInfoString(ctx->out, "opening a streamed block for transaction");
649  OutputPluginWrite(ctx, last_write);
650 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
TransactionId xid
void OutputPluginPrepareWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:585
void OutputPluginWrite(struct LogicalDecodingContext *ctx, bool last_write)
Definition: logical.c:598
StringInfo out
Definition: logical.h:70

◆ print_literal()

static void print_literal ( StringInfo  s,
Oid  typid,
char *  outputstr 
)
static

Definition at line 342 of file test_decoding.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), and SQL_STR_DOUBLE.

Referenced by tuple_to_stringinfo().

343 {
344  const char *valptr;
345 
346  switch (typid)
347  {
348  case INT2OID:
349  case INT4OID:
350  case INT8OID:
351  case OIDOID:
352  case FLOAT4OID:
353  case FLOAT8OID:
354  case NUMERICOID:
355  /* NB: We don't care about Inf, NaN et al. */
356  appendStringInfoString(s, outputstr);
357  break;
358 
359  case BITOID:
360  case VARBITOID:
361  appendStringInfo(s, "B'%s'", outputstr);
362  break;
363 
364  case BOOLOID:
365  if (strcmp(outputstr, "t") == 0)
366  appendStringInfoString(s, "true");
367  else
368  appendStringInfoString(s, "false");
369  break;
370 
371  default:
372  appendStringInfoChar(s, '\'');
373  for (valptr = outputstr; *valptr; valptr++)
374  {
375  char ch = *valptr;
376 
377  if (SQL_STR_DOUBLE(ch, false))
378  appendStringInfoChar(s, ch);
379  appendStringInfoChar(s, ch);
380  }
381  appendStringInfoChar(s, '\'');
382  break;
383  }
384 }
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define SQL_STR_DOUBLE(ch, escape_backslash)
Definition: c.h:1160

◆ tuple_to_stringinfo()

static void tuple_to_stringinfo ( StringInfo  s,
TupleDesc  tupdesc,
HeapTuple  tuple,
bool  skip_nulls 
)
static

Definition at line 388 of file test_decoding.c.

References appendStringInfoChar(), appendStringInfoString(), format_type_be(), getTypeOutputInfo(), heap_getattr, NameStr, TupleDescData::natts, OidOutputFunctionCall(), PG_DETOAST_DATUM, PointerGetDatum, print_literal(), quote_identifier(), TupleDescAttr, val, and VARATT_IS_EXTERNAL_ONDISK.

Referenced by pg_decode_change().

389 {
390  int natt;
391 
392  /* print all columns individually */
393  for (natt = 0; natt < tupdesc->natts; natt++)
394  {
395  Form_pg_attribute attr; /* the attribute itself */
396  Oid typid; /* type of current attribute */
397  Oid typoutput; /* output function */
398  bool typisvarlena;
399  Datum origval; /* possibly toasted Datum */
400  bool isnull; /* column is null? */
401 
402  attr = TupleDescAttr(tupdesc, natt);
403 
404  /*
405  * don't print dropped columns, we can't be sure everything is
406  * available for them
407  */
408  if (attr->attisdropped)
409  continue;
410 
411  /*
412  * Don't print system columns, oid will already have been printed if
413  * present.
414  */
415  if (attr->attnum < 0)
416  continue;
417 
418  typid = attr->atttypid;
419 
420  /* get Datum from tuple */
421  origval = heap_getattr(tuple, natt + 1, tupdesc, &isnull);
422 
423  if (isnull && skip_nulls)
424  continue;
425 
426  /* print attribute name */
427  appendStringInfoChar(s, ' ');
428  appendStringInfoString(s, quote_identifier(NameStr(attr->attname)));
429 
430  /* print attribute type */
431  appendStringInfoChar(s, '[');
433  appendStringInfoChar(s, ']');
434 
435  /* query output function */
436  getTypeOutputInfo(typid,
437  &typoutput, &typisvarlena);
438 
439  /* print separator */
440  appendStringInfoChar(s, ':');
441 
442  /* print data */
443  if (isnull)
444  appendStringInfoString(s, "null");
445  else if (typisvarlena && VARATT_IS_EXTERNAL_ONDISK(origval))
446  appendStringInfoString(s, "unchanged-toast-datum");
447  else if (!typisvarlena)
448  print_literal(s, typid,
449  OidOutputFunctionCall(typoutput, origval));
450  else
451  {
452  Datum val; /* definitely detoasted Datum */
453 
454  val = PointerGetDatum(PG_DETOAST_DATUM(origval));
455  print_literal(s, typid, OidOutputFunctionCall(typoutput, val));
456  }
457  }
458 }
#define VARATT_IS_EXTERNAL_ONDISK(PTR)
Definition: postgres.h:314
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2789
const char * quote_identifier(const char *ident)
Definition: ruleutils.c:10934
#define PointerGetDatum(X)
Definition: postgres.h:556
#define TupleDescAttr(tupdesc, i)
Definition: tupdesc.h:92
char * format_type_be(Oid type_oid)
Definition: format_type.c:339
unsigned int Oid
Definition: postgres_ext.h:31
static void print_literal(StringInfo s, Oid typid, char *outputstr)
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:193
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188
#define heap_getattr(tup, attnum, tupleDesc, isnull)
Definition: htup_details.h:762
uintptr_t Datum
Definition: postgres.h:367
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1657
#define NameStr(name)
Definition: c.h:677
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
long val
Definition: informix.c:664

Variable Documentation

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 25 of file test_decoding.c.