PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
tupconvert.c File Reference
#include "postgres.h"
#include "access/htup_details.h"
#include "access/tupconvert.h"
#include "utils/builtins.h"
Include dependency graph for tupconvert.c:

Go to the source code of this file.

Functions

TupleConversionMapconvert_tuples_by_position (TupleDesc indesc, TupleDesc outdesc, const char *msg)
 
TupleConversionMapconvert_tuples_by_name (TupleDesc indesc, TupleDesc outdesc, const char *msg)
 
AttrNumberconvert_tuples_by_name_map (TupleDesc indesc, TupleDesc outdesc, const char *msg)
 
HeapTuple do_convert_tuple (HeapTuple tuple, TupleConversionMap *map)
 
void free_conversion_map (TupleConversionMap *map)
 

Function Documentation

TupleConversionMap* convert_tuples_by_name ( TupleDesc  indesc,
TupleDesc  outdesc,
const char *  msg 
)

Definition at line 204 of file tupconvert.c.

References TupleConversionMap::attrMap, tupleDesc::attrs, convert_tuples_by_name_map(), i, TupleConversionMap::indesc, TupleConversionMap::inisnull, TupleConversionMap::invalues, tupleDesc::natts, NULL, TupleConversionMap::outdesc, TupleConversionMap::outisnull, TupleConversionMap::outvalues, palloc(), pfree(), and tupleDesc::tdhasoid.

Referenced by acquire_inherited_sample_rows(), ExecEvalConvertRowtype(), ExecSetupPartitionTupleRouting(), and RelationGetPartitionDispatchInfo().

207 {
208  TupleConversionMap *map;
209  AttrNumber *attrMap;
210  int n = outdesc->natts;
211  int i;
212  bool same;
213 
214  /* Verify compatibility and prepare attribute-number map */
215  attrMap = convert_tuples_by_name_map(indesc, outdesc, msg);
216 
217  /*
218  * Check to see if the map is one-to-one, in which case we need not do
219  * the tuple conversion. That's not enough though if either source or
220  * destination (tuples) contains OIDs; we'd need conversion in that case
221  * to inject the right OID into the tuple datum.
222  */
223  if (indesc->natts == outdesc->natts &&
224  !indesc->tdhasoid && !outdesc->tdhasoid)
225  {
226  same = true;
227  for (i = 0; i < n; i++)
228  {
229  if (attrMap[i] == (i + 1))
230  continue;
231 
232  /*
233  * If it's a dropped column and the corresponding input column is
234  * also dropped, we needn't convert. However, attlen and attalign
235  * must agree.
236  */
237  if (attrMap[i] == 0 &&
238  indesc->attrs[i]->attisdropped &&
239  indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen &&
240  indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign)
241  continue;
242 
243  same = false;
244  break;
245  }
246  }
247  else
248  same = false;
249 
250  if (same)
251  {
252  /* Runtime conversion is not needed */
253  pfree(attrMap);
254  return NULL;
255  }
256 
257  /* Prepare the map structure */
258  map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
259  map->indesc = indesc;
260  map->outdesc = outdesc;
261  map->attrMap = attrMap;
262  /* preallocate workspace for Datum arrays */
263  map->outvalues = (Datum *) palloc(n * sizeof(Datum));
264  map->outisnull = (bool *) palloc(n * sizeof(bool));
265  n = indesc->natts + 1; /* +1 for NULL */
266  map->invalues = (Datum *) palloc(n * sizeof(Datum));
267  map->inisnull = (bool *) palloc(n * sizeof(bool));
268  map->invalues[0] = (Datum) 0; /* set up the NULL entry */
269  map->inisnull[0] = true;
270 
271  return map;
272 }
AttrNumber * attrMap
Definition: tupconvert.h:25
TupleDesc indesc
Definition: tupconvert.h:23
TupleDesc outdesc
Definition: tupconvert.h:24
bool tdhasoid
Definition: tupdesc.h:79
Form_pg_attribute * attrs
Definition: tupdesc.h:74
int natts
Definition: tupdesc.h:73
void pfree(void *pointer)
Definition: mcxt.c:950
AttrNumber * convert_tuples_by_name_map(TupleDesc indesc, TupleDesc outdesc, const char *msg)
Definition: tupconvert.c:281
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
void * palloc(Size size)
Definition: mcxt.c:849
int i
int16 AttrNumber
Definition: attnum.h:21
AttrNumber* convert_tuples_by_name_map ( TupleDesc  indesc,
TupleDesc  outdesc,
const char *  msg 
)

Definition at line 281 of file tupconvert.c.

References _, tupleDesc::attrs, ereport, errcode(), errdetail(), errmsg_internal(), ERROR, format_type_be(), i, NameStr, tupleDesc::natts, palloc0(), and tupleDesc::tdtypeid.

Referenced by ATPrepAlterColumnType(), convert_tuples_by_name(), and map_partition_varattnos().

284 {
285  AttrNumber *attrMap;
286  int n;
287  int i;
288 
289  n = outdesc->natts;
290  attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
291  for (i = 0; i < n; i++)
292  {
293  Form_pg_attribute att = outdesc->attrs[i];
294  char *attname;
295  Oid atttypid;
296  int32 atttypmod;
297  int j;
298 
299  if (att->attisdropped)
300  continue; /* attrMap[i] is already 0 */
301  attname = NameStr(att->attname);
302  atttypid = att->atttypid;
303  atttypmod = att->atttypmod;
304  for (j = 0; j < indesc->natts; j++)
305  {
306  att = indesc->attrs[j];
307  if (att->attisdropped)
308  continue;
309  if (strcmp(attname, NameStr(att->attname)) == 0)
310  {
311  /* Found it, check type */
312  if (atttypid != att->atttypid || atttypmod != att->atttypmod)
313  ereport(ERROR,
314  (errcode(ERRCODE_DATATYPE_MISMATCH),
315  errmsg_internal("%s", _(msg)),
316  errdetail("Attribute \"%s\" of type %s does not match corresponding attribute of type %s.",
317  attname,
318  format_type_be(outdesc->tdtypeid),
319  format_type_be(indesc->tdtypeid))));
320  attrMap[i] = (AttrNumber) (j + 1);
321  break;
322  }
323  }
324  if (attrMap[i] == 0)
325  ereport(ERROR,
326  (errcode(ERRCODE_DATATYPE_MISMATCH),
327  errmsg_internal("%s", _(msg)),
328  errdetail("Attribute \"%s\" of type %s does not exist in type %s.",
329  attname,
330  format_type_be(outdesc->tdtypeid),
331  format_type_be(indesc->tdtypeid))));
332  }
333 
334  return attrMap;
335 }
Oid tdtypeid
Definition: tupdesc.h:77
Form_pg_attribute * attrs
Definition: tupdesc.h:74
int errcode(int sqlerrcode)
Definition: elog.c:575
char * format_type_be(Oid type_oid)
Definition: format_type.c:94
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
signed int int32
Definition: c.h:256
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define ereport(elevel, rest)
Definition: elog.h:122
void * palloc0(Size size)
Definition: mcxt.c:878
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
int i
#define NameStr(name)
Definition: c.h:499
int16 AttrNumber
Definition: attnum.h:21
#define _(x)
Definition: elog.c:84
TupleConversionMap* convert_tuples_by_position ( TupleDesc  indesc,
TupleDesc  outdesc,
const char *  msg 
)

Definition at line 66 of file tupconvert.c.

References _, TupleConversionMap::attrMap, tupleDesc::attrs, ereport, errcode(), errdetail(), errmsg_internal(), ERROR, format_type_with_typemod(), i, TupleConversionMap::indesc, TupleConversionMap::inisnull, TupleConversionMap::invalues, tupleDesc::natts, NULL, TupleConversionMap::outdesc, TupleConversionMap::outisnull, TupleConversionMap::outvalues, palloc(), palloc0(), pfree(), and tupleDesc::tdhasoid.

Referenced by exec_stmt_return_next(), exec_stmt_return_query(), plpgsql_exec_function(), and plpgsql_exec_trigger().

69 {
70  TupleConversionMap *map;
71  AttrNumber *attrMap;
72  int nincols;
73  int noutcols;
74  int n;
75  int i;
76  int j;
77  bool same;
78 
79  /* Verify compatibility and prepare attribute-number map */
80  n = outdesc->natts;
81  attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
82  j = 0; /* j is next physical input attribute */
83  nincols = noutcols = 0; /* these count non-dropped attributes */
84  same = true;
85  for (i = 0; i < n; i++)
86  {
87  Form_pg_attribute att = outdesc->attrs[i];
88  Oid atttypid;
89  int32 atttypmod;
90 
91  if (att->attisdropped)
92  continue; /* attrMap[i] is already 0 */
93  noutcols++;
94  atttypid = att->atttypid;
95  atttypmod = att->atttypmod;
96  for (; j < indesc->natts; j++)
97  {
98  att = indesc->attrs[j];
99  if (att->attisdropped)
100  continue;
101  nincols++;
102  /* Found matching column, check type */
103  if (atttypid != att->atttypid ||
104  (atttypmod != att->atttypmod && atttypmod >= 0))
105  ereport(ERROR,
106  (errcode(ERRCODE_DATATYPE_MISMATCH),
107  errmsg_internal("%s", _(msg)),
108  errdetail("Returned type %s does not match expected type %s in column %d.",
109  format_type_with_typemod(att->atttypid,
110  att->atttypmod),
111  format_type_with_typemod(atttypid,
112  atttypmod),
113  noutcols)));
114  attrMap[i] = (AttrNumber) (j + 1);
115  j++;
116  break;
117  }
118  if (attrMap[i] == 0)
119  same = false; /* we'll complain below */
120  }
121 
122  /* Check for unused input columns */
123  for (; j < indesc->natts; j++)
124  {
125  if (indesc->attrs[j]->attisdropped)
126  continue;
127  nincols++;
128  same = false; /* we'll complain below */
129  }
130 
131  /* Report column count mismatch using the non-dropped-column counts */
132  if (!same)
133  ereport(ERROR,
134  (errcode(ERRCODE_DATATYPE_MISMATCH),
135  errmsg_internal("%s", _(msg)),
136  errdetail("Number of returned columns (%d) does not match "
137  "expected column count (%d).",
138  nincols, noutcols)));
139 
140  /*
141  * Check to see if the map is one-to-one, in which case we need not do
142  * the tuple conversion. That's not enough though if either source or
143  * destination (tuples) contains OIDs; we'd need conversion in that case
144  * to inject the right OID into the tuple datum.
145  */
146  if (indesc->natts == outdesc->natts &&
147  !indesc->tdhasoid && !outdesc->tdhasoid)
148  {
149  for (i = 0; i < n; i++)
150  {
151  if (attrMap[i] == (i + 1))
152  continue;
153 
154  /*
155  * If it's a dropped column and the corresponding input column is
156  * also dropped, we needn't convert. However, attlen and attalign
157  * must agree.
158  */
159  if (attrMap[i] == 0 &&
160  indesc->attrs[i]->attisdropped &&
161  indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen &&
162  indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign)
163  continue;
164 
165  same = false;
166  break;
167  }
168  }
169  else
170  same = false;
171 
172  if (same)
173  {
174  /* Runtime conversion is not needed */
175  pfree(attrMap);
176  return NULL;
177  }
178 
179  /* Prepare the map structure */
180  map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap));
181  map->indesc = indesc;
182  map->outdesc = outdesc;
183  map->attrMap = attrMap;
184  /* preallocate workspace for Datum arrays */
185  map->outvalues = (Datum *) palloc(n * sizeof(Datum));
186  map->outisnull = (bool *) palloc(n * sizeof(bool));
187  n = indesc->natts + 1; /* +1 for NULL */
188  map->invalues = (Datum *) palloc(n * sizeof(Datum));
189  map->inisnull = (bool *) palloc(n * sizeof(bool));
190  map->invalues[0] = (Datum) 0; /* set up the NULL entry */
191  map->inisnull[0] = true;
192 
193  return map;
194 }
AttrNumber * attrMap
Definition: tupconvert.h:25
TupleDesc indesc
Definition: tupconvert.h:23
TupleDesc outdesc
Definition: tupconvert.h:24
bool tdhasoid
Definition: tupdesc.h:79
Form_pg_attribute * attrs
Definition: tupdesc.h:74
int errcode(int sqlerrcode)
Definition: elog.c:575
unsigned int Oid
Definition: postgres_ext.h:31
int natts
Definition: tupdesc.h:73
signed int int32
Definition: c.h:256
void pfree(void *pointer)
Definition: mcxt.c:950
#define ERROR
Definition: elog.h:43
int errdetail(const char *fmt,...)
Definition: elog.c:873
FormData_pg_attribute * Form_pg_attribute
Definition: pg_attribute.h:184
#define ereport(elevel, rest)
Definition: elog.h:122
char * format_type_with_typemod(Oid type_oid, int32 typemod)
Definition: format_type.c:113
void * palloc0(Size size)
Definition: mcxt.c:878
uintptr_t Datum
Definition: postgres.h:372
int errmsg_internal(const char *fmt,...)
Definition: elog.c:827
#define NULL
Definition: c.h:229
void * palloc(Size size)
Definition: mcxt.c:849
int i
int16 AttrNumber
Definition: attnum.h:21
#define _(x)
Definition: elog.c:84
HeapTuple do_convert_tuple ( HeapTuple  tuple,
TupleConversionMap map 
)

Definition at line 341 of file tupconvert.c.

References TupleConversionMap::attrMap, heap_deform_tuple(), heap_form_tuple(), i, TupleConversionMap::indesc, TupleConversionMap::inisnull, TupleConversionMap::invalues, tupleDesc::natts, TupleConversionMap::outdesc, TupleConversionMap::outisnull, and TupleConversionMap::outvalues.

Referenced by acquire_inherited_sample_rows(), CopyFrom(), exec_stmt_return_next(), exec_stmt_return_query(), ExecEvalConvertRowtype(), ExecInsert(), get_partition_for_tuple(), plpgsql_exec_function(), and plpgsql_exec_trigger().

342 {
343  AttrNumber *attrMap = map->attrMap;
344  Datum *invalues = map->invalues;
345  bool *inisnull = map->inisnull;
346  Datum *outvalues = map->outvalues;
347  bool *outisnull = map->outisnull;
348  int outnatts = map->outdesc->natts;
349  int i;
350 
351  /*
352  * Extract all the values of the old tuple, offsetting the arrays so that
353  * invalues[0] is left NULL and invalues[1] is the first source attribute;
354  * this exactly matches the numbering convention in attrMap.
355  */
356  heap_deform_tuple(tuple, map->indesc, invalues + 1, inisnull + 1);
357 
358  /*
359  * Transpose into proper fields of the new tuple.
360  */
361  for (i = 0; i < outnatts; i++)
362  {
363  int j = attrMap[i];
364 
365  outvalues[i] = invalues[j];
366  outisnull[i] = inisnull[j];
367  }
368 
369  /*
370  * Now form the new tuple.
371  */
372  return heap_form_tuple(map->outdesc, outvalues, outisnull);
373 }
AttrNumber * attrMap
Definition: tupconvert.h:25
TupleDesc indesc
Definition: tupconvert.h:23
TupleDesc outdesc
Definition: tupconvert.h:24
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:692
int natts
Definition: tupdesc.h:73
uintptr_t Datum
Definition: postgres.h:372
void heap_deform_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *values, bool *isnull)
Definition: heaptuple.c:935
int i
int16 AttrNumber
Definition: attnum.h:21
void free_conversion_map ( TupleConversionMap map)

Definition at line 379 of file tupconvert.c.

References TupleConversionMap::attrMap, TupleConversionMap::inisnull, TupleConversionMap::invalues, TupleConversionMap::outisnull, TupleConversionMap::outvalues, and pfree().

Referenced by acquire_inherited_sample_rows().

380 {
381  /* indesc and outdesc are not ours to free */
382  pfree(map->attrMap);
383  pfree(map->invalues);
384  pfree(map->inisnull);
385  pfree(map->outvalues);
386  pfree(map->outisnull);
387  pfree(map);
388 }
AttrNumber * attrMap
Definition: tupconvert.h:25
void pfree(void *pointer)
Definition: mcxt.c:950