mirror of
https://github.com/postgres/postgres.git
synced 2025-06-27 23:21:58 +03:00
Add Oracle-compatible GREATEST and LEAST functions. Pavel Stehule
This commit is contained in:
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.179 2005/05/12 20:41:56 tgl Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/executor/execQual.c,v 1.180 2005/06/26 22:05:36 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -105,6 +105,9 @@ static Datum ExecEvalRow(RowExprState *rstate,
|
||||
static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
|
||||
ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
|
||||
ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
|
||||
ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone);
|
||||
@ -2247,6 +2250,63 @@ ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
|
||||
return (Datum) 0;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecEvalMinMax
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static Datum
|
||||
ExecEvalMinMax(MinMaxExprState *minmaxExpr, ExprContext *econtext,
|
||||
bool *isNull, ExprDoneCond *isDone)
|
||||
{
|
||||
Datum result = (Datum) 0;
|
||||
MinMaxOp op = ((MinMaxExpr *) minmaxExpr->xprstate.expr)->op;
|
||||
FunctionCallInfoData locfcinfo;
|
||||
ListCell *arg;
|
||||
|
||||
if (isDone)
|
||||
*isDone = ExprSingleResult;
|
||||
*isNull = true; /* until we get a result */
|
||||
|
||||
InitFunctionCallInfoData(locfcinfo, &minmaxExpr->cfunc, 2, NULL, NULL);
|
||||
locfcinfo.argnull[0] = false;
|
||||
locfcinfo.argnull[1] = false;
|
||||
|
||||
foreach(arg, minmaxExpr->args)
|
||||
{
|
||||
ExprState *e = (ExprState *) lfirst(arg);
|
||||
Datum value;
|
||||
bool valueIsNull;
|
||||
int32 cmpresult;
|
||||
|
||||
value = ExecEvalExpr(e, econtext, &valueIsNull, NULL);
|
||||
if (valueIsNull)
|
||||
continue; /* ignore NULL inputs */
|
||||
|
||||
if (*isNull)
|
||||
{
|
||||
/* first nonnull input, adopt value */
|
||||
result = value;
|
||||
*isNull = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* apply comparison function */
|
||||
locfcinfo.arg[0] = result;
|
||||
locfcinfo.arg[1] = value;
|
||||
locfcinfo.isnull = false;
|
||||
cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
|
||||
if (locfcinfo.isnull) /* probably should not happen */
|
||||
continue;
|
||||
if (cmpresult > 0 && op == IS_LEAST)
|
||||
result = value;
|
||||
else if (cmpresult < 0 && op == IS_GREATEST)
|
||||
result = value;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------
|
||||
* ExecEvalNullIf
|
||||
*
|
||||
@ -3206,6 +3266,36 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
||||
state = (ExprState *) cstate;
|
||||
}
|
||||
break;
|
||||
case T_MinMaxExpr:
|
||||
{
|
||||
MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
|
||||
MinMaxExprState *mstate = makeNode(MinMaxExprState);
|
||||
List *outlist = NIL;
|
||||
ListCell *l;
|
||||
TypeCacheEntry *typentry;
|
||||
|
||||
mstate->xprstate.evalfunc = (ExprStateEvalFunc) ExecEvalMinMax;
|
||||
foreach(l, minmaxexpr->args)
|
||||
{
|
||||
Expr *e = (Expr *) lfirst(l);
|
||||
ExprState *estate;
|
||||
|
||||
estate = ExecInitExpr(e, parent);
|
||||
outlist = lappend(outlist, estate);
|
||||
}
|
||||
mstate->args = outlist;
|
||||
/* Look up the btree comparison function for the datatype */
|
||||
typentry = lookup_type_cache(minmaxexpr->minmaxtype,
|
||||
TYPECACHE_CMP_PROC);
|
||||
if (!OidIsValid(typentry->cmp_proc))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_UNDEFINED_FUNCTION),
|
||||
errmsg("could not identify a comparison function for type %s",
|
||||
format_type_be(minmaxexpr->minmaxtype))));
|
||||
fmgr_info(typentry->cmp_proc, &(mstate->cfunc));
|
||||
state = (ExprState *) mstate;
|
||||
}
|
||||
break;
|
||||
case T_NullIfExpr:
|
||||
{
|
||||
NullIfExpr *nullifexpr = (NullIfExpr *) node;
|
||||
|
Reference in New Issue
Block a user