/src/postgres/src/backend/access/common/printsimple.c
Line | Count | Source |
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-2026, 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 "libpq/pqformat.h" |
24 | | #include "libpq/protocol.h" |
25 | | #include "utils/builtins.h" |
26 | | #include "varatt.h" |
27 | | |
28 | | /* |
29 | | * At startup time, send a RowDescription message. |
30 | | */ |
31 | | void |
32 | | printsimple_startup(DestReceiver *self, int operation, TupleDesc tupdesc) |
33 | 0 | { |
34 | 0 | StringInfoData buf; |
35 | 0 | int i; |
36 | |
|
37 | 0 | pq_beginmessage(&buf, PqMsg_RowDescription); |
38 | 0 | pq_sendint16(&buf, tupdesc->natts); |
39 | |
|
40 | 0 | for (i = 0; i < tupdesc->natts; ++i) |
41 | 0 | { |
42 | 0 | Form_pg_attribute attr = TupleDescAttr(tupdesc, i); |
43 | |
|
44 | 0 | pq_sendstring(&buf, NameStr(attr->attname)); |
45 | 0 | pq_sendint32(&buf, 0); /* table oid */ |
46 | 0 | pq_sendint16(&buf, 0); /* attnum */ |
47 | 0 | pq_sendint32(&buf, (int) attr->atttypid); |
48 | 0 | pq_sendint16(&buf, attr->attlen); |
49 | 0 | pq_sendint32(&buf, attr->atttypmod); |
50 | 0 | pq_sendint16(&buf, 0); /* format code */ |
51 | 0 | } |
52 | |
|
53 | 0 | pq_endmessage(&buf); |
54 | 0 | } |
55 | | |
56 | | /* |
57 | | * For each tuple, send a DataRow message. |
58 | | */ |
59 | | bool |
60 | | printsimple(TupleTableSlot *slot, DestReceiver *self) |
61 | 0 | { |
62 | 0 | TupleDesc tupdesc = slot->tts_tupleDescriptor; |
63 | 0 | StringInfoData buf; |
64 | 0 | int i; |
65 | | |
66 | | /* Make sure the tuple is fully deconstructed */ |
67 | 0 | slot_getallattrs(slot); |
68 | | |
69 | | /* Prepare and send message */ |
70 | 0 | pq_beginmessage(&buf, PqMsg_DataRow); |
71 | 0 | pq_sendint16(&buf, tupdesc->natts); |
72 | |
|
73 | 0 | for (i = 0; i < tupdesc->natts; ++i) |
74 | 0 | { |
75 | 0 | Form_pg_attribute attr = TupleDescAttr(tupdesc, i); |
76 | 0 | Datum value; |
77 | |
|
78 | 0 | if (slot->tts_isnull[i]) |
79 | 0 | { |
80 | 0 | pq_sendint32(&buf, -1); |
81 | 0 | continue; |
82 | 0 | } |
83 | | |
84 | 0 | value = slot->tts_values[i]; |
85 | | |
86 | | /* |
87 | | * We can't call the regular type output functions here because we |
88 | | * might not have catalog access. Instead, we must hard-wire |
89 | | * knowledge of the required types. |
90 | | */ |
91 | 0 | switch (attr->atttypid) |
92 | 0 | { |
93 | 0 | case TEXTOID: |
94 | 0 | { |
95 | 0 | text *t = DatumGetTextPP(value); |
96 | |
|
97 | 0 | pq_sendcountedtext(&buf, |
98 | 0 | VARDATA_ANY(t), |
99 | 0 | VARSIZE_ANY_EXHDR(t)); |
100 | 0 | } |
101 | 0 | break; |
102 | | |
103 | 0 | case INT4OID: |
104 | 0 | { |
105 | 0 | int32 num = DatumGetInt32(value); |
106 | 0 | char str[12]; /* sign, 10 digits and '\0' */ |
107 | 0 | int len; |
108 | |
|
109 | 0 | len = pg_ltoa(num, str); |
110 | 0 | pq_sendcountedtext(&buf, str, len); |
111 | 0 | } |
112 | 0 | break; |
113 | | |
114 | 0 | case INT8OID: |
115 | 0 | { |
116 | 0 | int64 num = DatumGetInt64(value); |
117 | 0 | char str[MAXINT8LEN + 1]; |
118 | 0 | int len; |
119 | |
|
120 | 0 | len = pg_lltoa(num, str); |
121 | 0 | pq_sendcountedtext(&buf, str, len); |
122 | 0 | } |
123 | 0 | break; |
124 | | |
125 | 0 | case OIDOID: |
126 | 0 | { |
127 | 0 | Oid num = DatumGetObjectId(value); |
128 | 0 | char str[10]; /* 10 digits */ |
129 | 0 | int len; |
130 | |
|
131 | 0 | len = pg_ultoa_n(num, str); |
132 | 0 | pq_sendcountedtext(&buf, str, len); |
133 | 0 | } |
134 | 0 | break; |
135 | | |
136 | 0 | default: |
137 | 0 | elog(ERROR, "unsupported type OID: %u", attr->atttypid); |
138 | 0 | } |
139 | 0 | } |
140 | | |
141 | 0 | pq_endmessage(&buf); |
142 | |
|
143 | | return true; |
144 | 0 | } |