]> granicus.if.org Git - postgresql/blob - src/backend/access/common/printtup.c
Pass attypmod through to executor by adding to Var and Resdom.
[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.24 1998/02/10 04:00: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(ERROR, "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(ERROR, "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, 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, 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                                                                                 (int)typeinfo->attrs[i]->atttypmod);
128                         pq_putint(strlen(outputstr) + VARHDRSZ, VARHDRSZ);
129                         pq_putnchar(outputstr, strlen(outputstr));
130                         pfree(outputstr);
131                 }
132         }
133 }
134
135 /* ----------------
136  *              printatt
137  * ----------------
138  */
139 static void
140 printatt(unsigned attributeId,
141                  AttributeTupleForm attributeP,
142                  char *value)
143 {
144         printf("\t%2d: %s%s%s%s\t(typeid = %u, len = %d, byval = %c)\n",
145                    attributeId,
146                    attributeP->attname.data,
147                    value != NULL ? " = \"" : "",
148                    value != NULL ? value : "",
149                    value != NULL ? "\"" : "",
150                    (unsigned int) (attributeP->atttypid),
151                    attributeP->attlen,
152                    attributeP->attbyval ? 't' : 'f');
153 }
154
155 /* ----------------
156  *              showatts
157  * ----------------
158  */
159 void
160 showatts(char *name, TupleDesc tupleDesc)
161 {
162         int                     i;
163         int                     natts = tupleDesc->natts;
164         AttributeTupleForm *attinfo = tupleDesc->attrs;
165
166         puts(name);
167         for (i = 0; i < natts; ++i)
168                 printatt((unsigned) i + 1, attinfo[i], (char *) NULL);
169         printf("\t----\n");
170 }
171
172 /* ----------------
173  *              debugtup
174  * ----------------
175  */
176 void
177 debugtup(HeapTuple tuple, TupleDesc typeinfo)
178 {
179         register int i;
180         Datum       attr;
181         char       *value;
182         bool            isnull;
183         Oid                     typoutput;
184
185         for (i = 0; i < tuple->t_natts; ++i)
186         {
187                 attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
188                 typoutput = typtoout((Oid) typeinfo->attrs[i]->atttypid);
189
190                 if (!isnull && OidIsValid(typoutput))
191                 {
192                         value = fmgr(typoutput, attr,
193                                                  gettypelem(typeinfo->attrs[i]->atttypid),
194                                                            (int)typeinfo->attrs[i]->atttypmod);
195                         printatt((unsigned) i + 1, typeinfo->attrs[i], value);
196                         pfree(value);
197                 }
198         }
199         printf("\t----\n");
200 }
201
202 /* ----------------
203  *              printtup_internal
204  *              Protocol expects either T, D, C, E, or N.
205  *              We use a different data prefix, e.g. 'B' instead of 'D' to
206  *              indicate a tuple in internal (binary) form.
207  *
208  *              This is same as printtup, except we don't use the typout func.
209  * ----------------
210  */
211 void
212 printtup_internal(HeapTuple tuple, TupleDesc typeinfo)
213 {
214         int                     i,
215                                 j,
216                                 k;
217         Datum           attr;
218         bool            isnull;
219
220         /* ----------------
221          *      tell the frontend to expect new tuple data
222          * ----------------
223          */
224         pq_putnchar("B", 1);
225
226         /* ----------------
227          *      send a bitmap of which attributes are null
228          * ----------------
229          */
230         j = 0;
231         k = 1 << 7;
232         for (i = 0; i < tuple->t_natts;)
233         {
234                 i++;                                    /* heap_getattr is a macro, so no
235                                                                  * increment */
236                 attr = heap_getattr(tuple, i, typeinfo, &isnull);
237                 if (!isnull)
238                         j |= k;
239                 k >>= 1;
240                 if (!(i & 7))
241                 {
242                         pq_putint(j, 1);
243                         j = 0;
244                         k = 1 << 7;
245                 }
246         }
247         if (i & 7)
248                 pq_putint(j, 1);
249
250         /* ----------------
251          *      send the attributes of this tuple
252          * ----------------
253          */
254 #ifdef IPORTAL_DEBUG
255         fprintf(stderr, "sending tuple with %d atts\n", tuple->t_natts);
256 #endif
257         for (i = 0; i < tuple->t_natts; ++i)
258         {
259                 int32           len = typeinfo->attrs[i]->attlen;
260
261                 attr = heap_getattr(tuple, i + 1, typeinfo, &isnull);
262                 if (!isnull)
263                 {
264                         /* # of bytes, and opaque data */
265                         if (len == -1)
266                         {
267                                 /* variable length, assume a varlena structure */
268                                 len = VARSIZE(attr) - VARHDRSZ;
269
270                                 pq_putint(len, VARHDRSZ);
271                                 pq_putnchar(VARDATA(attr), len);
272 #ifdef IPORTAL_DEBUG
273                                 {
274                                         char       *d = VARDATA(attr);
275
276                                         fprintf(stderr, "length %d data %x%x%x%x\n",
277                                                         len, *d, *(d + 1), *(d + 2), *(d + 3));
278                                 }
279 #endif
280                         }
281                         else
282                         {
283                                 /* fixed size */
284                                 if (typeinfo->attrs[i]->attbyval)
285                                 {
286                                         int8            i8;
287                                         int16           i16;
288                                         int32           i32;
289
290                                         pq_putint(len, sizeof(int32));
291                                         switch (len)
292                                         {
293                                                 case sizeof(int8):
294                                                         i8 = DatumGetChar(attr);
295                                                         pq_putnchar((char *) &i8, len);
296                                                         break;
297                                                 case sizeof(int16):
298                                                         i16 = DatumGetInt16(attr);
299                                                         pq_putnchar((char *) &i16, len);
300                                                         break;
301                                                 case sizeof(int32):
302                                                         i32 = DatumGetInt32(attr);
303                                                         pq_putnchar((char *) &i32, len);
304                                                         break;
305                                         }
306 #ifdef IPORTAL_DEBUG
307                                         fprintf(stderr, "byval length %d data %d\n", len, attr);
308 #endif
309                                 }
310                                 else
311                                 {
312                                         pq_putint(len, sizeof(int32));
313                                         pq_putnchar(DatumGetPointer(attr), len);
314 #ifdef IPORTAL_DEBUG
315                                         fprintf(stderr, "byref length %d data %x\n", len,
316                                                                                                 DatumGetPointer(attr));
317 #endif
318                                 }
319                         }
320                 }
321         }
322 }