Skip to content

Commit a84069d

Browse files
committed
Add a new DestReceiver for printing tuples without catalog access.
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.com
1 parent 7b4ac19 commit a84069d

File tree

5 files changed

+148
-2
lines changed

5 files changed

+148
-2
lines changed

src/backend/access/common/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ subdir = src/backend/access/common
1212
top_builddir = ../../../..
1313
include $(top_builddir)/src/Makefile.global
1414

15-
OBJS = heaptuple.o indextuple.o printtup.o reloptions.o scankey.o \
16-
tupconvert.o tupdesc.o
15+
OBJS = heaptuple.o indextuple.o printsimple.o printtup.o reloptions.o \
16+
scankey.o tupconvert.o tupdesc.o
1717

1818
include $(top_srcdir)/src/backend/common.mk
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* printsimple.c
4+
* Routines to print out tuples containing only a limited range of
5+
* builtin types without catalog access. This is intended for
6+
* backends that don't have catalog access because they are not bound
7+
* to a specific database, such as some walsender processes. It
8+
* doesn't handle standalone backends or protocol versions other than
9+
* 3.0, because we don't need such handling for current applications.
10+
*
11+
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
12+
* Portions Copyright (c) 1994, Regents of the University of California
13+
*
14+
* IDENTIFICATION
15+
* src/backend/access/common/printsimple.c
16+
*
17+
*-------------------------------------------------------------------------
18+
*/
19+
#include "postgres.h"
20+
21+
#include "access/printsimple.h"
22+
#include "catalog/pg_type.h"
23+
#include "fmgr.h"
24+
#include "libpq/pqformat.h"
25+
26+
/*
27+
* At startup time, send a RowDescription message.
28+
*/
29+
void
30+
printsimple_startup(DestReceiver *self, int operation, TupleDesc tupdesc)
31+
{
32+
StringInfoData buf;
33+
int i;
34+
35+
pq_beginmessage(&buf, 'T'); /* RowDescription */
36+
pq_sendint(&buf, tupdesc->natts, 2);
37+
38+
for (i = 0; i < tupdesc->natts; ++i)
39+
{
40+
Form_pg_attribute attr = tupdesc->attrs[i];
41+
42+
pq_sendstring(&buf, NameStr(attr->attname));
43+
pq_sendint(&buf, 0, 4); /* table oid */
44+
pq_sendint(&buf, 0, 2); /* attnum */
45+
pq_sendint(&buf, (int) attr->atttypid, 4);
46+
pq_sendint(&buf, attr->attlen, 2);
47+
pq_sendint(&buf, attr->atttypmod, 4);
48+
pq_sendint(&buf, 0, 2); /* format code */
49+
}
50+
51+
pq_endmessage(&buf);
52+
}
53+
54+
/*
55+
* For each tuple, send a DataRow message.
56+
*/
57+
bool
58+
printsimple(TupleTableSlot *slot, DestReceiver *self)
59+
{
60+
TupleDesc tupdesc = slot->tts_tupleDescriptor;
61+
StringInfoData buf;
62+
int i;
63+
64+
/* Make sure the tuple is fully deconstructed */
65+
slot_getallattrs(slot);
66+
67+
/* Prepare and send message */
68+
pq_beginmessage(&buf, 'D');
69+
pq_sendint(&buf, tupdesc->natts, 2);
70+
71+
for (i = 0; i < tupdesc->natts; ++i)
72+
{
73+
Form_pg_attribute attr = tupdesc->attrs[i];
74+
Datum value;
75+
76+
if (slot->tts_isnull[i])
77+
{
78+
pq_sendint(&buf, -1, 4);
79+
continue;
80+
}
81+
82+
value = slot->tts_values[i];
83+
84+
/*
85+
* We can't call the regular type output functions here because we
86+
* might not have catalog access. Instead, we must hard-wire
87+
* knowledge of the required types.
88+
*/
89+
switch (attr->atttypid)
90+
{
91+
case TEXTOID:
92+
{
93+
text *t = DatumGetTextPP(value);
94+
95+
pq_sendcountedtext(&buf,
96+
VARDATA_ANY(t),
97+
VARSIZE_ANY_EXHDR(t),
98+
false);
99+
}
100+
break;
101+
102+
default:
103+
elog(ERROR, "unsupported type OID: %u", attr->atttypid);
104+
}
105+
}
106+
107+
pq_endmessage(&buf);
108+
109+
return true;
110+
}

src/backend/tcop/dest.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828

2929
#include "postgres.h"
3030

31+
#include "access/printsimple.h"
3132
#include "access/printtup.h"
3233
#include "access/xact.h"
3334
#include "commands/copy.h"
@@ -76,6 +77,11 @@ static DestReceiver debugtupDR = {
7677
DestDebug
7778
};
7879

80+
static DestReceiver printsimpleDR = {
81+
printsimple, printsimple_startup, donothingCleanup, donothingCleanup,
82+
DestRemoteSimple
83+
};
84+
7985
static DestReceiver spi_printtupDR = {
8086
spi_printtup, spi_dest_startup, donothingCleanup, donothingCleanup,
8187
DestSPI
@@ -108,6 +114,9 @@ CreateDestReceiver(CommandDest dest)
108114
case DestRemoteExecute:
109115
return printtup_create_DR(dest);
110116

117+
case DestRemoteSimple:
118+
return &printsimpleDR;
119+
111120
case DestNone:
112121
return &donothingDR;
113122

@@ -151,6 +160,7 @@ EndCommand(const char *commandTag, CommandDest dest)
151160
{
152161
case DestRemote:
153162
case DestRemoteExecute:
163+
case DestRemoteSimple:
154164

155165
/*
156166
* We assume the commandTag is plain ASCII and therefore requires
@@ -191,6 +201,7 @@ NullCommand(CommandDest dest)
191201
{
192202
case DestRemote:
193203
case DestRemoteExecute:
204+
case DestRemoteSimple:
194205

195206
/*
196207
* tell the fe that we saw an empty query string. In protocols
@@ -233,6 +244,7 @@ ReadyForQuery(CommandDest dest)
233244
{
234245
case DestRemote:
235246
case DestRemoteExecute:
247+
case DestRemoteSimple:
236248
if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
237249
{
238250
StringInfoData buf;

src/include/access/printsimple.h

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*-------------------------------------------------------------------------
2+
*
3+
* printsimple.h
4+
* print simple tuples without catalog access
5+
*
6+
* Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7+
* Portions Copyright (c) 1994, Regents of the University of California
8+
*
9+
* src/include/access/printsimple.h
10+
*
11+
*-------------------------------------------------------------------------
12+
*/
13+
14+
#ifndef PRINTSIMPLE_H
15+
#define PRINTSIMPLE_H
16+
17+
#include "tcop/dest.h"
18+
19+
extern bool printsimple(TupleTableSlot *slot, DestReceiver *self);
20+
extern void printsimple_startup(DestReceiver *self, int operation,
21+
TupleDesc tupdesc);
22+
23+
#endif /* PRINTSIMPLE_H */

src/include/tcop/dest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ typedef enum
8989
DestDebug, /* results go to debugging output */
9090
DestRemote, /* results sent to frontend process */
9191
DestRemoteExecute, /* sent to frontend, in Execute command */
92+
DestRemoteSimple, /* sent to frontend, w/no catalog access */
9293
DestSPI, /* results sent to SPI manager */
9394
DestTuplestore, /* results sent to Tuplestore */
9495
DestIntoRel, /* results sent to relation (SELECT INTO) */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy