#include "access/htup.h"
#include "access/tupdesc.h"
Go to the source code of this file.
Data Structures | |
struct | TupleConversionMap |
Typedefs | |
typedef struct TupleConversionMap | TupleConversionMap |
Functions | |
TupleConversionMap * | convert_tuples_by_position (TupleDesc indesc, TupleDesc outdesc, const char *msg) |
TupleConversionMap * | convert_tuples_by_name (TupleDesc indesc, TupleDesc outdesc, const char *msg) |
HeapTuple | do_convert_tuple (HeapTuple tuple, TupleConversionMap *map) |
void | free_conversion_map (TupleConversionMap *map) |
typedef struct TupleConversionMap TupleConversionMap |
TupleConversionMap* convert_tuples_by_name | ( | TupleDesc | indesc, | |
TupleDesc | outdesc, | |||
const char * | msg | |||
) |
Definition at line 203 of file tupconvert.c.
References _, TupleConversionMap::attrMap, tupleDesc::attrs, ereport, errcode(), errdetail(), errmsg_internal(), ERROR, format_type_be(), i, TupleConversionMap::indesc, TupleConversionMap::inisnull, TupleConversionMap::invalues, NameStr, tupleDesc::natts, TupleConversionMap::outdesc, TupleConversionMap::outisnull, TupleConversionMap::outvalues, palloc(), palloc0(), pfree(), and tupleDesc::tdtypeid.
Referenced by acquire_inherited_sample_rows(), and ExecEvalConvertRowtype().
{ TupleConversionMap *map; AttrNumber *attrMap; int n; int i; bool same; /* Verify compatibility and prepare attribute-number map */ n = outdesc->natts; attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber)); for (i = 0; i < n; i++) { Form_pg_attribute att = outdesc->attrs[i]; char *attname; Oid atttypid; int32 atttypmod; int j; if (att->attisdropped) continue; /* attrMap[i] is already 0 */ attname = NameStr(att->attname); atttypid = att->atttypid; atttypmod = att->atttypmod; for (j = 0; j < indesc->natts; j++) { att = indesc->attrs[j]; if (att->attisdropped) continue; if (strcmp(attname, NameStr(att->attname)) == 0) { /* Found it, check type */ if (atttypid != att->atttypid || atttypmod != att->atttypmod) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg_internal("%s", _(msg)), errdetail("Attribute \"%s\" of type %s does not match corresponding attribute of type %s.", attname, format_type_be(outdesc->tdtypeid), format_type_be(indesc->tdtypeid)))); attrMap[i] = (AttrNumber) (j + 1); break; } } if (attrMap[i] == 0) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg_internal("%s", _(msg)), errdetail("Attribute \"%s\" of type %s does not exist in type %s.", attname, format_type_be(outdesc->tdtypeid), format_type_be(indesc->tdtypeid)))); } /* * Check to see if the map is one-to-one and the tuple types are the same. * (We check the latter because if they're not, we want to do conversion * to inject the right OID into the tuple datum.) */ if (indesc->natts == outdesc->natts && indesc->tdtypeid == outdesc->tdtypeid) { same = true; for (i = 0; i < n; i++) { if (attrMap[i] == (i + 1)) continue; /* * If it's a dropped column and the corresponding input column is * also dropped, we needn't convert. However, attlen and attalign * must agree. */ if (attrMap[i] == 0 && indesc->attrs[i]->attisdropped && indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen && indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign) continue; same = false; break; } } else same = false; if (same) { /* Runtime conversion is not needed */ pfree(attrMap); return NULL; } /* Prepare the map structure */ map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap)); map->indesc = indesc; map->outdesc = outdesc; map->attrMap = attrMap; /* preallocate workspace for Datum arrays */ map->outvalues = (Datum *) palloc(n * sizeof(Datum)); map->outisnull = (bool *) palloc(n * sizeof(bool)); n = indesc->natts + 1; /* +1 for NULL */ map->invalues = (Datum *) palloc(n * sizeof(Datum)); map->inisnull = (bool *) palloc(n * sizeof(bool)); map->invalues[0] = (Datum) 0; /* set up the NULL entry */ map->inisnull[0] = true; return map; }
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, TupleConversionMap::outdesc, TupleConversionMap::outisnull, TupleConversionMap::outvalues, palloc(), palloc0(), pfree(), and tupleDesc::tdtypeid.
Referenced by exec_stmt_return_next(), exec_stmt_return_query(), plpgsql_exec_function(), and plpgsql_exec_trigger().
{ TupleConversionMap *map; AttrNumber *attrMap; int nincols; int noutcols; int n; int i; int j; bool same; /* Verify compatibility and prepare attribute-number map */ n = outdesc->natts; attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber)); j = 0; /* j is next physical input attribute */ nincols = noutcols = 0; /* these count non-dropped attributes */ same = true; for (i = 0; i < n; i++) { Form_pg_attribute att = outdesc->attrs[i]; Oid atttypid; int32 atttypmod; if (att->attisdropped) continue; /* attrMap[i] is already 0 */ noutcols++; atttypid = att->atttypid; atttypmod = att->atttypmod; for (; j < indesc->natts; j++) { att = indesc->attrs[j]; if (att->attisdropped) continue; nincols++; /* Found matching column, check type */ if (atttypid != att->atttypid || (atttypmod != att->atttypmod && atttypmod >= 0)) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg_internal("%s", _(msg)), errdetail("Returned type %s does not match expected type %s in column %d.", format_type_with_typemod(att->atttypid, att->atttypmod), format_type_with_typemod(atttypid, atttypmod), noutcols))); attrMap[i] = (AttrNumber) (j + 1); j++; break; } if (attrMap[i] == 0) same = false; /* we'll complain below */ } /* Check for unused input columns */ for (; j < indesc->natts; j++) { if (indesc->attrs[j]->attisdropped) continue; nincols++; same = false; /* we'll complain below */ } /* Report column count mismatch using the non-dropped-column counts */ if (!same) ereport(ERROR, (errcode(ERRCODE_DATATYPE_MISMATCH), errmsg_internal("%s", _(msg)), errdetail("Number of returned columns (%d) does not match " "expected column count (%d).", nincols, noutcols))); /* * Check to see if the map is one-to-one and the tuple types are the same. * (We check the latter because if they're not, we want to do conversion * to inject the right OID into the tuple datum.) */ if (indesc->natts == outdesc->natts && indesc->tdtypeid == outdesc->tdtypeid) { for (i = 0; i < n; i++) { if (attrMap[i] == (i + 1)) continue; /* * If it's a dropped column and the corresponding input column is * also dropped, we needn't convert. However, attlen and attalign * must agree. */ if (attrMap[i] == 0 && indesc->attrs[i]->attisdropped && indesc->attrs[i]->attlen == outdesc->attrs[i]->attlen && indesc->attrs[i]->attalign == outdesc->attrs[i]->attalign) continue; same = false; break; } } else same = false; if (same) { /* Runtime conversion is not needed */ pfree(attrMap); return NULL; } /* Prepare the map structure */ map = (TupleConversionMap *) palloc(sizeof(TupleConversionMap)); map->indesc = indesc; map->outdesc = outdesc; map->attrMap = attrMap; /* preallocate workspace for Datum arrays */ map->outvalues = (Datum *) palloc(n * sizeof(Datum)); map->outisnull = (bool *) palloc(n * sizeof(bool)); n = indesc->natts + 1; /* +1 for NULL */ map->invalues = (Datum *) palloc(n * sizeof(Datum)); map->inisnull = (bool *) palloc(n * sizeof(bool)); map->invalues[0] = (Datum) 0; /* set up the NULL entry */ map->inisnull[0] = true; return map; }
HeapTuple do_convert_tuple | ( | HeapTuple | tuple, | |
TupleConversionMap * | map | |||
) |
Definition at line 319 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(), exec_stmt_return_next(), exec_stmt_return_query(), ExecEvalConvertRowtype(), plpgsql_exec_function(), and plpgsql_exec_trigger().
{ AttrNumber *attrMap = map->attrMap; Datum *invalues = map->invalues; bool *inisnull = map->inisnull; Datum *outvalues = map->outvalues; bool *outisnull = map->outisnull; int outnatts = map->outdesc->natts; int i; /* * Extract all the values of the old tuple, offsetting the arrays so that * invalues[0] is left NULL and invalues[1] is the first source attribute; * this exactly matches the numbering convention in attrMap. */ heap_deform_tuple(tuple, map->indesc, invalues + 1, inisnull + 1); /* * Transpose into proper fields of the new tuple. */ for (i = 0; i < outnatts; i++) { int j = attrMap[i]; outvalues[i] = invalues[j]; outisnull[i] = inisnull[j]; } /* * Now form the new tuple. */ return heap_form_tuple(map->outdesc, outvalues, outisnull); }
void free_conversion_map | ( | TupleConversionMap * | map | ) |
Definition at line 357 of file tupconvert.c.
References TupleConversionMap::attrMap, TupleConversionMap::inisnull, TupleConversionMap::invalues, TupleConversionMap::outisnull, TupleConversionMap::outvalues, and pfree().
Referenced by acquire_inherited_sample_rows(), exec_stmt_return_next(), and exec_stmt_return_query().