#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().
1.7.1