mirror of https://github.com/postgres/postgres
If you create a DestReciver of type DestRemote and try to use it from a replication connection that is not bound to a specific daabase, or any other hypothetical type of backend that is not bound to a specific database, it will fail because it doesn't have a pg_proc catalog to look up properties of the types being printed. In general, that's an unavoidable problem, but we can hardwire the properties of a few builtin types in order to support utility commands. This new DestReceiver of type DestRemoteSimple does just that. Patch by me, reviewed by Michael Paquier. Discussion: http://postgr.es/m/CA+TgmobNo4qz06wHEmy9DszAre3dYx-WNhHSCbU9SAwf+9Ft6g@mail.gmail.compull/20/head
parent
7b4ac19982
commit
a84069d935
@ -0,0 +1,110 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* printsimple.c |
||||
* Routines to print out tuples containing only a limited range of |
||||
* builtin types without catalog access. This is intended for |
||||
* backends that don't have catalog access because they are not bound |
||||
* to a specific database, such as some walsender processes. It |
||||
* doesn't handle standalone backends or protocol versions other than |
||||
* 3.0, because we don't need such handling for current applications. |
||||
* |
||||
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* IDENTIFICATION |
||||
* src/backend/access/common/printsimple.c |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
#include "postgres.h" |
||||
|
||||
#include "access/printsimple.h" |
||||
#include "catalog/pg_type.h" |
||||
#include "fmgr.h" |
||||
#include "libpq/pqformat.h" |
||||
|
||||
/*
|
||||
* At startup time, send a RowDescription message. |
||||
*/ |
||||
void |
||||
printsimple_startup(DestReceiver *self, int operation, TupleDesc tupdesc) |
||||
{ |
||||
StringInfoData buf; |
||||
int i; |
||||
|
||||
pq_beginmessage(&buf, 'T'); /* RowDescription */ |
||||
pq_sendint(&buf, tupdesc->natts, 2); |
||||
|
||||
for (i = 0; i < tupdesc->natts; ++i) |
||||
{ |
||||
Form_pg_attribute attr = tupdesc->attrs[i]; |
||||
|
||||
pq_sendstring(&buf, NameStr(attr->attname)); |
||||
pq_sendint(&buf, 0, 4); /* table oid */ |
||||
pq_sendint(&buf, 0, 2); /* attnum */ |
||||
pq_sendint(&buf, (int) attr->atttypid, 4); |
||||
pq_sendint(&buf, attr->attlen, 2); |
||||
pq_sendint(&buf, attr->atttypmod, 4); |
||||
pq_sendint(&buf, 0, 2); /* format code */ |
||||
} |
||||
|
||||
pq_endmessage(&buf); |
||||
} |
||||
|
||||
/*
|
||||
* For each tuple, send a DataRow message. |
||||
*/ |
||||
bool |
||||
printsimple(TupleTableSlot *slot, DestReceiver *self) |
||||
{ |
||||
TupleDesc tupdesc = slot->tts_tupleDescriptor; |
||||
StringInfoData buf; |
||||
int i; |
||||
|
||||
/* Make sure the tuple is fully deconstructed */ |
||||
slot_getallattrs(slot); |
||||
|
||||
/* Prepare and send message */ |
||||
pq_beginmessage(&buf, 'D'); |
||||
pq_sendint(&buf, tupdesc->natts, 2); |
||||
|
||||
for (i = 0; i < tupdesc->natts; ++i) |
||||
{ |
||||
Form_pg_attribute attr = tupdesc->attrs[i]; |
||||
Datum value; |
||||
|
||||
if (slot->tts_isnull[i]) |
||||
{ |
||||
pq_sendint(&buf, -1, 4); |
||||
continue; |
||||
} |
||||
|
||||
value = slot->tts_values[i]; |
||||
|
||||
/*
|
||||
* We can't call the regular type output functions here because we |
||||
* might not have catalog access. Instead, we must hard-wire |
||||
* knowledge of the required types. |
||||
*/ |
||||
switch (attr->atttypid) |
||||
{ |
||||
case TEXTOID: |
||||
{ |
||||
text *t = DatumGetTextPP(value); |
||||
|
||||
pq_sendcountedtext(&buf, |
||||
VARDATA_ANY(t), |
||||
VARSIZE_ANY_EXHDR(t), |
||||
false); |
||||
} |
||||
break; |
||||
|
||||
default: |
||||
elog(ERROR, "unsupported type OID: %u", attr->atttypid); |
||||
} |
||||
} |
||||
|
||||
pq_endmessage(&buf); |
||||
|
||||
return true; |
||||
} |
||||
@ -0,0 +1,23 @@ |
||||
/*-------------------------------------------------------------------------
|
||||
* |
||||
* printsimple.h |
||||
* print simple tuples without catalog access |
||||
* |
||||
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group |
||||
* Portions Copyright (c) 1994, Regents of the University of California |
||||
* |
||||
* src/include/access/printsimple.h |
||||
* |
||||
*------------------------------------------------------------------------- |
||||
*/ |
||||
|
||||
#ifndef PRINTSIMPLE_H |
||||
#define PRINTSIMPLE_H |
||||
|
||||
#include "tcop/dest.h" |
||||
|
||||
extern bool printsimple(TupleTableSlot *slot, DestReceiver *self); |
||||
extern void printsimple_startup(DestReceiver *self, int operation, |
||||
TupleDesc tupdesc); |
||||
|
||||
#endif /* PRINTSIMPLE_H */ |
||||
Loading…
Reference in new issue