* Evaluate a FieldSelect node. * * Source record is in step's result variable. */
| 3107 | * Source record is in step's result variable. |
| 3108 | */ |
| 3109 | void |
| 3110 | ExecEvalFieldSelect(ExprState *state, ExprEvalStep *op, ExprContext *econtext) |
| 3111 | { |
| 3112 | AttrNumber fieldnum = op->d.fieldselect.fieldnum; |
| 3113 | Datum tupDatum; |
| 3114 | HeapTupleHeader tuple; |
| 3115 | Oid tupType; |
| 3116 | int32 tupTypmod; |
| 3117 | TupleDesc tupDesc; |
| 3118 | Form_pg_attribute attr; |
| 3119 | HeapTupleData tmptup; |
| 3120 | |
| 3121 | /* NULL record -> NULL result */ |
| 3122 | if (*op->resnull) |
| 3123 | return; |
| 3124 | |
| 3125 | tupDatum = *op->resvalue; |
| 3126 | |
| 3127 | /* We can special-case expanded records for speed */ |
| 3128 | if (VARATT_IS_EXTERNAL_EXPANDED(DatumGetPointer(tupDatum))) |
| 3129 | { |
| 3130 | ExpandedRecordHeader *erh = (ExpandedRecordHeader *) DatumGetEOHP(tupDatum); |
| 3131 | |
| 3132 | Assert(erh->er_magic == ER_MAGIC); |
| 3133 | |
| 3134 | /* Extract record's TupleDesc */ |
| 3135 | tupDesc = expanded_record_get_tupdesc(erh); |
| 3136 | |
| 3137 | /* |
| 3138 | * Find field's attr record. Note we don't support system columns |
| 3139 | * here: a datum tuple doesn't have valid values for most of the |
| 3140 | * interesting system columns anyway. |
| 3141 | */ |
| 3142 | if (fieldnum <= 0) /* should never happen */ |
| 3143 | elog(ERROR, "unsupported reference to system column %d in FieldSelect", |
| 3144 | fieldnum); |
| 3145 | if (fieldnum > tupDesc->natts) /* should never happen */ |
| 3146 | elog(ERROR, "attribute number %d exceeds number of columns %d", |
| 3147 | fieldnum, tupDesc->natts); |
| 3148 | attr = TupleDescAttr(tupDesc, fieldnum - 1); |
| 3149 | |
| 3150 | /* Check for dropped column, and force a NULL result if so */ |
| 3151 | if (attr->attisdropped) |
| 3152 | { |
| 3153 | *op->resnull = true; |
| 3154 | return; |
| 3155 | } |
| 3156 | |
| 3157 | /* Check for type mismatch --- possible after ALTER COLUMN TYPE? */ |
| 3158 | /* As in CheckVarSlotCompatibility, we should but can't check typmod */ |
| 3159 | if (op->d.fieldselect.resulttype != attr->atttypid) |
| 3160 | ereport(ERROR, |
| 3161 | (errcode(ERRCODE_DATATYPE_MISMATCH), |
| 3162 | errmsg("attribute %d has wrong type", fieldnum), |
| 3163 | errdetail("Table has type %s, but query expects %s.", |
| 3164 | format_type_be(attr->atttypid), |
| 3165 | format_type_be(op->d.fieldselect.resulttype)))); |
| 3166 |
no test coverage detected