@ -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 ;