]> granicus.if.org Git - postgresql/commitdiff
Better solution to the problem of labeling whole-row Datums that are
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 19 Oct 2005 22:30:30 +0000 (22:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 19 Oct 2005 22:30:30 +0000 (22:30 +0000)
generated from subquery outputs: use the type info stored in the Var
itself.  To avoid making ExecEvalVar and slot_getattr more complex
and slower, I split out the whole-row case into a separate ExecEval routine.

src/backend/access/common/heaptuple.c
src/backend/executor/execQual.c

index fc0a85d2ddd8424dafe1f319b54a0dbaee6f7f14..5551f744bb21f4843d8a35a6425f39bed37666c1 100644 (file)
@@ -16,7 +16,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.101 2005/10/19 18:18:32 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/common/heaptuple.c,v 1.102 2005/10/19 22:30:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -27,7 +27,6 @@
 #include "access/tuptoaster.h"
 #include "catalog/pg_type.h"
 #include "executor/tuptable.h"
-#include "utils/typcache.h"
 
 
 /* ----------------------------------------------------------------
@@ -595,38 +594,6 @@ heap_getsysattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
                case TableOidAttributeNumber:
                        result = ObjectIdGetDatum(tup->t_tableOid);
                        break;
-
-                       /*
-                        * If the attribute number is 0, then we are supposed to return
-                        * the entire tuple as a row-type Datum.  (Using zero for this
-                        * purpose is unclean since it risks confusion with "invalid attr"
-                        * result codes, but it's not worth changing now.)
-                        *
-                        * We have to make a copy of the tuple so we can safely insert the
-                        * Datum overhead fields, which are not set in on-disk tuples.
-                        *
-                        * It's possible that the passed tupleDesc is a record type that
-                        * hasn't been "blessed" yet, so cover that case.
-                        */
-               case InvalidAttrNumber:
-                       {
-                               HeapTupleHeader dtup;
-
-                               if (tupleDesc->tdtypeid == RECORDOID &&
-                                       tupleDesc->tdtypmod < 0)
-                                       assign_record_type_typmod(tupleDesc);
-
-                               dtup = (HeapTupleHeader) palloc(tup->t_len);
-                               memcpy((char *) dtup, (char *) tup->t_data, tup->t_len);
-
-                               HeapTupleHeaderSetDatumLength(dtup, tup->t_len);
-                               HeapTupleHeaderSetTypeId(dtup, tupleDesc->tdtypeid);
-                               HeapTupleHeaderSetTypMod(dtup, tupleDesc->tdtypmod);
-
-                               result = PointerGetDatum(dtup);
-                       }
-                       break;
-
                default:
                        elog(ERROR, "invalid attnum: %d", attnum);
                        result = 0;                     /* keep compiler quiet */
index 5a270469061d1fc906252c3c51807896d49d8f9b..4ee9a4ca622bb19f232de0514f6a698162644d73 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.182 2005/10/19 18:18:33 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.183 2005/10/19 22:30:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -64,6 +64,8 @@ static Datum ExecEvalAggref(AggrefExprState *aggref,
                           bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
                        bool *isNull, ExprDoneCond *isDone);
+static Datum ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
+                       bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalConst(ExprState *exprstate, ExprContext *econtext,
                          bool *isNull, ExprDoneCond *isDone);
 static Datum ExecEvalParam(ExprState *exprstate, ExprContext *econtext,
@@ -448,9 +450,9 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
        /*
         * Get the slot and attribute number we want
         *
-        * The asserts check that references to system attributes only appear at the
-        * level of a relation scan; at higher levels, system attributes must be
-        * treated as ordinary variables (since we no longer have access to the
+        * The asserts check that references to system attributes only appear at
+        * the level of a relation scan; at higher levels, system attributes must
+        * be treated as ordinary variables (since we no longer have access to the
         * original tuple).
         */
        attnum = variable->varattno;
@@ -505,6 +507,77 @@ ExecEvalVar(ExprState *exprstate, ExprContext *econtext,
        return slot_getattr(slot, attnum, isNull);
 }
 
+/* ----------------------------------------------------------------
+ *             ExecEvalWholeRowVar
+ *
+ *             Returns a Datum for a whole-row variable.
+ *
+ *             This could be folded into ExecEvalVar, but we make it a separate
+ *             routine so as not to slow down ExecEvalVar with tests for this
+ *             uncommon case.
+ * ----------------------------------------------------------------
+ */
+static Datum
+ExecEvalWholeRowVar(ExprState *exprstate, ExprContext *econtext,
+                                       bool *isNull, ExprDoneCond *isDone)
+{
+       Var                *variable = (Var *) exprstate->expr;
+       TupleTableSlot *slot;
+       HeapTuple       tuple;
+       TupleDesc       tupleDesc;
+       HeapTupleHeader dtuple;
+
+       if (isDone)
+               *isDone = ExprSingleResult;
+       *isNull = false;
+
+       Assert(variable->varattno == InvalidAttrNumber);
+
+       /*
+        * Whole-row Vars can only appear at the level of a relation scan,
+        * never in a join.
+        */
+       Assert(variable->varno != INNER);
+       Assert(variable->varno != OUTER);
+       slot = econtext->ecxt_scantuple;
+
+       tuple = slot->tts_tuple;
+       tupleDesc = slot->tts_tupleDescriptor;
+
+       /*
+        * We have to make a copy of the tuple so we can safely insert the
+        * Datum overhead fields, which are not set in on-disk tuples.
+        */
+       dtuple = (HeapTupleHeader) palloc(tuple->t_len);
+       memcpy((char *) dtuple, (char *) tuple->t_data, tuple->t_len);
+
+       HeapTupleHeaderSetDatumLength(dtuple, tuple->t_len);
+
+       /*
+        * If the Var identifies a named composite type, label the tuple
+        * with that type; otherwise use what is in the tupleDesc.
+        *
+        * It's likely that the slot's tupleDesc is a record type; if so,
+        * make sure it's been "blessed", so that the Datum can be interpreted
+        * later.
+        */
+       if (variable->vartype != RECORDOID)
+       {
+               HeapTupleHeaderSetTypeId(dtuple, variable->vartype);
+               HeapTupleHeaderSetTypMod(dtuple, variable->vartypmod);
+       }
+       else
+       {
+               if (tupleDesc->tdtypeid == RECORDOID &&
+                       tupleDesc->tdtypmod < 0)
+                       assign_record_type_typmod(tupleDesc);
+               HeapTupleHeaderSetTypeId(dtuple, tupleDesc->tdtypeid);
+               HeapTupleHeaderSetTypMod(dtuple, tupleDesc->tdtypmod);
+       }
+
+       return PointerGetDatum(dtuple);
+}
+
 /* ----------------------------------------------------------------
  *             ExecEvalConst
  *
@@ -2841,8 +2914,15 @@ ExecInitExpr(Expr *node, PlanState *parent)
        switch (nodeTag(node))
        {
                case T_Var:
-                       state = (ExprState *) makeNode(ExprState);
-                       state->evalfunc = ExecEvalVar;
+                       {
+                               Var        *var = (Var *) node;
+
+                               state = (ExprState *) makeNode(ExprState);
+                               if (var->varattno != InvalidAttrNumber)
+                                       state->evalfunc = ExecEvalVar;
+                               else
+                                       state->evalfunc = ExecEvalWholeRowVar;
+                       }
                        break;
                case T_Const:
                        state = (ExprState *) makeNode(ExprState);