|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.215 2007/02/27 23:48:07 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.216 2007/03/27 23:21:08 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -145,6 +145,9 @@ static Datum ExecEvalFieldStore(FieldStoreState *fstate,
|
145 | 145 | static Datum ExecEvalRelabelType(GenericExprState *exprstate,
|
146 | 146 | ExprContext *econtext,
|
147 | 147 | bool *isNull, ExprDoneCond *isDone);
|
| 148 | +static Datum ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate, |
| 149 | + ExprContext *econtext, |
| 150 | + bool *isNull, ExprDoneCond *isDone); |
148 | 151 |
|
149 | 152 |
|
150 | 153 | /* ----------------------------------------------------------------
|
@@ -3501,6 +3504,83 @@ ExecEvalRelabelType(GenericExprState *exprstate,
|
3501 | 3504 | return ExecEvalExpr(exprstate->arg, econtext, isNull, isDone);
|
3502 | 3505 | }
|
3503 | 3506 |
|
| 3507 | +/* ---------------------------------------------------------------- |
| 3508 | + * ExecEvalArrayCoerceExpr |
| 3509 | + * |
| 3510 | + * Evaluate an ArrayCoerceExpr node. |
| 3511 | + * ---------------------------------------------------------------- |
| 3512 | + */ |
| 3513 | +static Datum |
| 3514 | +ExecEvalArrayCoerceExpr(ArrayCoerceExprState *astate, |
| 3515 | + ExprContext *econtext, |
| 3516 | + bool *isNull, ExprDoneCond *isDone) |
| 3517 | +{ |
| 3518 | + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) astate->xprstate.expr; |
| 3519 | + Datum result; |
| 3520 | + ArrayType *array; |
| 3521 | + FunctionCallInfoData locfcinfo; |
| 3522 | + |
| 3523 | + result = ExecEvalExpr(astate->arg, econtext, isNull, isDone); |
| 3524 | + |
| 3525 | + if (isDone && *isDone == ExprEndResult) |
| 3526 | + return result; /* nothing to do */ |
| 3527 | + if (*isNull) |
| 3528 | + return result; /* nothing to do */ |
| 3529 | + |
| 3530 | + /* |
| 3531 | + * If it's binary-compatible, modify the element type in the array header, |
| 3532 | + * but otherwise leave the array as we received it. |
| 3533 | + */ |
| 3534 | + if (!OidIsValid(acoerce->elemfuncid)) |
| 3535 | + { |
| 3536 | + /* Detoast input array if necessary, and copy in any case */ |
| 3537 | + array = DatumGetArrayTypePCopy(result); |
| 3538 | + ARR_ELEMTYPE(array) = astate->resultelemtype; |
| 3539 | + PG_RETURN_ARRAYTYPE_P(array); |
| 3540 | + } |
| 3541 | + |
| 3542 | + /* Detoast input array if necessary, but don't make a useless copy */ |
| 3543 | + array = DatumGetArrayTypeP(result); |
| 3544 | + |
| 3545 | + /* Initialize function cache if first time through */ |
| 3546 | + if (astate->elemfunc.fn_oid == InvalidOid) |
| 3547 | + { |
| 3548 | + AclResult aclresult; |
| 3549 | + |
| 3550 | + /* Check permission to call function */ |
| 3551 | + aclresult = pg_proc_aclcheck(acoerce->elemfuncid, GetUserId(), |
| 3552 | + ACL_EXECUTE); |
| 3553 | + if (aclresult != ACLCHECK_OK) |
| 3554 | + aclcheck_error(aclresult, ACL_KIND_PROC, |
| 3555 | + get_func_name(acoerce->elemfuncid)); |
| 3556 | + |
| 3557 | + /* Set up the primary fmgr lookup information */ |
| 3558 | + fmgr_info_cxt(acoerce->elemfuncid, &(astate->elemfunc), |
| 3559 | + econtext->ecxt_per_query_memory); |
| 3560 | + |
| 3561 | + /* Initialize additional info */ |
| 3562 | + astate->elemfunc.fn_expr = (Node *) acoerce; |
| 3563 | + } |
| 3564 | + |
| 3565 | + /* |
| 3566 | + * Use array_map to apply the function to each array element. |
| 3567 | + * |
| 3568 | + * We pass on the desttypmod and isExplicit flags whether or not the |
| 3569 | + * function wants them. |
| 3570 | + */ |
| 3571 | + InitFunctionCallInfoData(locfcinfo, &(astate->elemfunc), 3, |
| 3572 | + NULL, NULL); |
| 3573 | + locfcinfo.arg[0] = PointerGetDatum(array); |
| 3574 | + locfcinfo.arg[1] = Int32GetDatum(acoerce->resulttypmod); |
| 3575 | + locfcinfo.arg[2] = BoolGetDatum(acoerce->isExplicit); |
| 3576 | + locfcinfo.argnull[0] = false; |
| 3577 | + locfcinfo.argnull[1] = false; |
| 3578 | + locfcinfo.argnull[2] = false; |
| 3579 | + |
| 3580 | + return array_map(&locfcinfo, ARR_ELEMTYPE(array), astate->resultelemtype, |
| 3581 | + astate->amstate); |
| 3582 | +} |
| 3583 | + |
3504 | 3584 |
|
3505 | 3585 | /*
|
3506 | 3586 | * ExecEvalExprSwitchContext
|
@@ -3770,6 +3850,26 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
3770 | 3850 | state = (ExprState *) gstate;
|
3771 | 3851 | }
|
3772 | 3852 | break;
|
| 3853 | + case T_ArrayCoerceExpr: |
| 3854 | + { |
| 3855 | + ArrayCoerceExpr *acoerce = (ArrayCoerceExpr *) node; |
| 3856 | + ArrayCoerceExprState *astate = makeNode(ArrayCoerceExprState); |
| 3857 | + |
| 3858 | + astate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalArrayCoerceExpr; |
| 3859 | + astate->arg = ExecInitExpr(acoerce->arg, parent); |
| 3860 | + astate->resultelemtype = get_element_type(acoerce->resulttype); |
| 3861 | + if (astate->resultelemtype == InvalidOid) |
| 3862 | + ereport(ERROR, |
| 3863 | + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), |
| 3864 | + errmsg("target type is not an array"))); |
| 3865 | + /* Arrays over domains aren't supported yet */ |
| 3866 | + Assert(getBaseType(astate->resultelemtype) == |
| 3867 | + astate->resultelemtype); |
| 3868 | + astate->elemfunc.fn_oid = InvalidOid; /* not initialized */ |
| 3869 | + astate->amstate = (ArrayMapState *) palloc0(sizeof(ArrayMapState)); |
| 3870 | + state = (ExprState *) astate; |
| 3871 | + } |
| 3872 | + break; |
3773 | 3873 | case T_ConvertRowtypeExpr:
|
3774 | 3874 | {
|
3775 | 3875 | ConvertRowtypeExpr *convert = (ConvertRowtypeExpr *) node;
|
|
0 commit comments