]> granicus.if.org Git - postgresql/blob - src/backend/access/common/printtup.c
heapattr functions now return a Datum, not char *.
[postgresql] / src / backend / access / common / printtup.c
1 /*-------------------------------------------------------------------------
2  *
3  * printtup.c--
4  *        Routines to print out tuples to the destination (binary or non-binary
5  *        portals, frontend/interactive backend, etc.).
6  *
7  * Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/access/common/printtup.c,v 1.18 1997/09/12 04:07:12 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15
16 #include <string.h>
17 #include <postgres.h>
18
19 #include <fmgr.h>
20 #include <access/heapam.h>
21 #include <access/printtup.h>
22 #include <catalog/pg_type.h>
23 #include <libpq/libpq.h>
24 #include <utils/syscache.h>
25
26 /* ----------------------------------------------------------------
27  *              printtup / debugtup support
28  * ----------------------------------------------------------------
29  */
30
31 /* ----------------
32  *              typtoout - used by printtup and debugtup
33  * ----------------
34  */
35 Oid
36 typtoout(Oid type)
37 {
38         HeapTuple       typeTuple;
39
40         typeTuple = SearchSysCacheTuple(TYPOID,
41                                                                         ObjectIdGetDatum(type),
42                                                                         0, 0, 0);
43
44         if (HeapTupleIsValid(typeTuple))
45                 return ((Oid)
46                                 ((TypeTupleForm) GETSTRUCT(typeTuple))->typoutput);
47
48         elog(WARN, "typtoout: Cache lookup of type %d failed", type);
49         return (InvalidOid);
50 }
51
52 Oid
53 gettypelem(Oid type)
54 {
55         HeapTuple       typeTuple;
56
57         typeTuple = SearchSysCacheTuple(TYPOID,
58                                                                         ObjectIdGetDatum(type),
59                                                                         0, 0, 0);
60
61         if (HeapTupleIsValid(typeTuple))
62                 return ((Oid)
63                                 ((TypeTupleForm) GETSTRUCT(typeTuple))->typelem);
64
65         elog(WARN, "typtoout: Cache lookup of type %d failed", type);
66         return (InvalidOid);
67 }
68
69 /* ----------------
70  *              printtup
71  * ----------------
72  */
73 void
74 printtup(HeapTuple tuple, TupleDesc typeinfo)
75 {
76         int                     i,
77                                 j,
78                                 k;
79         char       *outputstr;
80         Datum           attr;
81         bool            isnull;
82         Oid                     typoutput;
83
84         /* ----------------
85          *      tell the frontend to expect new tuple data
86          * ----------------
87          */
88         pq_putnchar("D", 1);
89
90         /* ----------------
91          *      send a bitmap of which attributes are null
92          * ----------------
93          */
94         j = 0;
95         k = 1 << 7;
96         for (i = 0; i < tuple->t_natts;)
97         {
98                 i++;                                    /* heap_getattr is a macro, so no
99                                                                  * increment */
100                 attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
101                 if (!isnull)
102                         j |= k;
103                 k >>= 1;
104                 if (!(i & 7))
105                 {
106                         pq_putint(j, 1);
107                         j = 0;
108                         k = 1 << 7;
109                 }
110         }
111         if (i & 7)
112                 pq_putint(j, 1);
113
114         /* ----------------
115          *      send the attributes of this tuple
116          * ----------------
117          */
118         for (i = 0; i < tuple->t_natts; ++i)
119         {
120                 attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
121                 typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
122
123                 if (!isnull && OidIsValid(typoutput))
124                 {
125                         outputstr = fmgr(typoutput, attr,
126                                                          gettypelem(typeinfo->attrs[i]->atttypid));
127                         pq_putint(strlen(outputstr) + 4, 4);
128                         pq_putnchar(outputstr, strlen(outputstr));
129                         pfree(outputstr);
130                 }
131         }
132 }
133
134 /* ----------------
135  *              printatt
136  * ----------------
137  */
138 static void
139 printatt(unsigned attributeId,
140                  AttributeTupleForm attributeP,
141                  char *value)
142 {
143         printf("\t%2d: %s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n",
144                    attributeId,
145                    attributeP->attname.data,
146                    value != NULL ? " = \"" : "",
147                    value != NULL ? value : "",
148                    value != NULL ? "\"" : "",
149                    (unsigned int) (attributeP->atttypid),
150                    attributeP->attlen,
151                    attributeP->attbyval ? 't' : 'f');
152 }
153
154 /* ----------------
155  *              showatts
156  * ----------------
157  */
158 void
159 showatts(char *name, TupleDesc tupleDesc)
160 {
161         int                     i;
162         int                     natts = tupleDesc->natts;
163         AttributeTupleForm *attinfo = tupleDesc->attrs;
164
165         puts(name);
166         for (i = 0; i < natts; ++i)
167                 printatt((unsigned) i + 1, attinfo[i], (char *) NULL);
168         printf("\t----\n");
169 }
170
171 /* ----------------
172  *              debugtup
173  * ----------------
174  */
175 void
176 debugtup(HeapTuple tuple, TupleDesc typeinfo)
177 {
178         register int i;
179         Datum       attr;
180         char       *value;
181         bool            isnull;
182         Oid                     typoutput;
183
184         for (i = 0; i < tuple->t_natts; ++i)
185         {
186                 attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
187                 typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
188
189                 if (!isnull && OidIsValid(typoutput))
190                 {
191                         value = fmgr(typoutput, attr,
192                                                  gettypelem(typeinfo->attrs[i]->atttypid));
193                         printatt((unsigned) i + 1, typeinfo->attrs[i], value);
194                         pfree(value);
195                 }
196         }
197         printf("\t----\n");
198 }
199
200 /* ----------------
201  *              printtup_internal
202  *              Protocol expects either T, D, C, E, or N.
203  *              We use a different data prefix, e.g. 'B' instead of 'D' to
204  *              indicate a tuple in internal (binary) form.
205  *
206  *              This is same as printtup, except we don't use the typout func.
207  * ----------------
208  */
209 void
210 printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
211 {
212         int                     i,
213                                 j,
214                                 k;
215         Datum           attr;
216         bool            isnull;
217
218         /* ----------------
219          *      tell the frontend to expect new tuple data
220          * ----------------
221          */
222         pq_putnchar("B", 1);
223
224         /* ----------------
225          *      send a bitmap of which attributes are null
226          * ----------------
227          */
228         j = 0;
229         k = 1 << 7;
230         for (i = 0; i < tuple->t_natts;)
231         {
232                 i++;                                    /* heap_getattr is a macro, so no
233                                                                  * increment */
234                 attr = heap_getattr(tuple, InvalidBuffer, i, typeinfo, &isnull);
235                 if (!isnull)
236                         j |= k;
237                 k >>= 1;
238                 if (!(i & 7))
239                 {
240                         pq_putint(j, 1);
241                         j = 0;
242                         k = 1 << 7;
243                 }
244         }
245         if (i & 7)
246                 pq_putint(j, 1);
247
248         /* ----------------
249          *      send the attributes of this tuple
250          * ----------------
251          */
252 #ifdef IPORTAL_DEBUG
253         fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts);
254 #endif
255         for (i = 0; i < tuple->t_natts; ++i)
256         {
257                 int32           len = typeinfo->attrs[i]->attlen;
258
259                 attr = heap_getattr(tuple, InvalidBuffer, i + 1, typeinfo, &isnull);
260                 if (!isnull)
261                 {
262                         /* # of bytes, and opaque data */
263                         if (len == -1)
264                         {
265                                 /* variable length, assume a varlena structure */
266                                 len = VARSIZE(attr) - VARHDRSZ;
267
268                                 pq_putint(len, sizeof(int32));
269                                 pq_putnchar(VARDATA(attr), len);
270 #ifdef IPORTAL_DEBUG
271                                 {
272                                         char       *d = VARDATA(attr);
273
274                                         fprintf(stderr, "length %d data %x%x%x%x\n",
275                                                         len, *d, *(d + 1), *(d + 2), *(d + 3));
276                                 }
277 #endif
278                         }
279                         else
280                         {
281                                 /* fixed size */
282                                 if (typeinfo->attrs[i]->attbyval)
283                                 {
284                                         int8            i8;
285                                         int16           i16;
286                                         int32           i32;
287
288                                         pq_putint(len, sizeof(int32));
289                                         switch (len)
290                                         {
291                                                 case sizeof(int8):
292                                                         i8 = DatumGetChar(attr);
293                                                         pq_putnchar((char *) &i8, len);
294                                                         break;
295                                                 case sizeof(int16):
296                                                         i16 = DatumGetInt16(attr);
297                                                         pq_putnchar((char *) &i16, len);
298                                                         break;
299                                                 case sizeof(int32):
300                                                         i32 = DatumGetInt32(attr);
301                                                         pq_putnchar((char *) &i32, len);
302                                                         break;
303                                         }
304 #ifdef IPORTAL_DEBUG
305                                         fprintf(stderr, "byval length %d data %d\n", len, attr);
306 #endif
307                                 }
308                                 else
309                                 {
310                                         pq_putint(len, sizeof(int32));
311                                         pq_putnchar(DatumGetPointer(attr), len);
312 #ifdef IPORTAL_DEBUG
313                                         fprintf(stderr, "byref length %d data %x\n", len,
314                                                                                                 DatumGetPointer(attr));
315 #endif
316                                 }
317                         }
318                 }
319         }
320 }