aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/execQual.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor/execQual.c')
-rw-r--r--src/backend/executor/execQual.c139
1 files changed, 137 insertions, 2 deletions
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 086df146420..9aec0965610 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.169 2004/09/22 17:41:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.170 2004/12/11 23:26:29 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -87,6 +87,9 @@ static Datum ExecEvalOr(BoolExprState *orExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCase(CaseExprState *caseExpr, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone);
static Datum ExecEvalCaseTestExpr(ExprState *exprstate,
@@ -428,7 +431,8 @@ ExecEvalAggref(AggrefExprState *aggref, ExprContext *econtext,
*
* Returns a Datum whose value is the value of a range
* variable with respect to given expression context.
- * ---------------------------------------------------------------- */
+ * ----------------------------------------------------------------
+ */
static Datum
ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
bool *isNull, ExprDoneCond *isDone)
@@ -1844,6 +1848,75 @@ ExecEvalAnd(BoolExprState *andExpr, ExprContext *econtext,
return BoolGetDatum(!AnyNull);
}
+/* ----------------------------------------------------------------
+ * ExecEvalConvertRowtype
+ *
+ * Evaluate a rowtype coercion operation. This may require
+ * rearranging field positions.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalConvertRowtype(ConvertRowtypeExprState *cstate,
+ ExprContext *econtext,
+ bool *isNull, ExprDoneCond *isDone)
+{
+ HeapTuple result;
+ Datum tupDatum;
+ HeapTupleHeader tuple;
+ HeapTupleData tmptup;
+ AttrNumber *attrMap = cstate->attrMap;
+ Datum *invalues = cstate->invalues;
+ char *innulls = cstate->innulls;
+ Datum *outvalues = cstate->outvalues;
+ char *outnulls = cstate->outnulls;
+ int i;
+ int outnatts = cstate->outdesc->natts;
+
+ tupDatum = ExecEvalExpr(cstate->arg, econtext, isNull, isDone);
+
+ /* this test covers the isDone exception too: */
+ if (*isNull)
+ return tupDatum;
+
+ tuple = DatumGetHeapTupleHeader(tupDatum);
+
+ Assert(HeapTupleHeaderGetTypeId(tuple) == cstate->indesc->tdtypeid);
+ Assert(HeapTupleHeaderGetTypMod(tuple) == cstate->indesc->tdtypmod);
+
+ /*
+ * heap_deformtuple needs a HeapTuple not a bare HeapTupleHeader.
+ */
+ tmptup.t_len = HeapTupleHeaderGetDatumLength(tuple);
+ tmptup.t_data = tuple;
+
+ /*
+ * Extract all the values of the old tuple, offsetting the arrays
+ * so that invalues[0] is NULL and invalues[1] is the first
+ * source attribute; this exactly matches the numbering convention
+ * in attrMap.
+ */
+ heap_deformtuple(&tmptup, cstate->indesc, invalues + 1, innulls + 1);
+ invalues[0] = (Datum) 0;
+ innulls[0] = 'n';
+
+ /*
+ * Transpose into proper fields of the new tuple.
+ */
+ for (i = 0; i < outnatts; i++)
+ {
+ int j = attrMap[i];
+
+ outvalues[i] = invalues[j];
+ outnulls[i] = innulls[j];
+ }
+
+ /*
+ * Now form the new tuple.
+ */
+ result = heap_formtuple(cstate->outdesc, outvalues, outnulls);
+
+ return HeapTupleGetDatum(result);
+}
/* ----------------------------------------------------------------
* ExecEvalCase
@@ -2969,6 +3042,68 @@ ExecInitExpr(Expr *node, PlanState *parent)
state = (ExprState *) gstate;
}
break;
+ case T_ConvertRowtypeExpr:
+ {
+ ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
+ ConvertRowtypeExprState *cstate = makeNode(ConvertRowtypeExprState);
+ int i;
+ int n;
+
+ cstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalConvertRowtype;
+ cstate->arg = ExecInitExpr(convert->arg, parent);
+ /* save copies of needed tuple descriptors */
+ cstate->indesc = lookup_rowtype_tupdesc(exprType((Node *) convert->arg), -1);
+ cstate->indesc = CreateTupleDescCopy(cstate->indesc);
+ cstate->outdesc = lookup_rowtype_tupdesc(convert->resulttype, -1);
+ cstate->outdesc = CreateTupleDescCopy(cstate->outdesc);
+ /* prepare map from old to new attribute numbers */
+ n = cstate->outdesc->natts;
+ cstate->attrMap = (AttrNumber *) palloc0(n * sizeof(AttrNumber));
+ for (i = 0; i < n; i++)
+ {
+ Form_pg_attribute att = cstate->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 < cstate->indesc->natts; j++)
+ {
+ att = cstate->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)
+ elog(ERROR, "attribute \"%s\" of type %s does not match corresponding attribute of type %s",
+ attname,
+ format_type_be(cstate->indesc->tdtypeid),
+ format_type_be(cstate->outdesc->tdtypeid));
+ cstate->attrMap[i] = (AttrNumber) (j + 1);
+ break;
+ }
+ }
+ if (cstate->attrMap[i] == 0)
+ elog(ERROR, "attribute \"%s\" of type %s does not exist",
+ attname,
+ format_type_be(cstate->indesc->tdtypeid));
+ }
+ /* preallocate workspace for Datum arrays */
+ n = cstate->indesc->natts + 1; /* +1 for NULL */
+ cstate->invalues = (Datum *) palloc(n * sizeof(Datum));
+ cstate->innulls = (char *) palloc(n * sizeof(char));
+ n = cstate->outdesc->natts;
+ cstate->outvalues = (Datum *) palloc(n * sizeof(Datum));
+ cstate->outnulls = (char *) palloc(n * sizeof(char));
+ state = (ExprState *) cstate;
+ }
+ break;
case T_CaseExpr:
{
CaseExpr *caseexpr = (CaseExpr *) node;