Add Oracle-compatible GREATEST and LEAST functions. Pavel Stehule
This commit is contained in:
parent
d395aecffa
commit
943b396245
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.259 2005/06/24 20:53:29 tgl Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.260 2005/06/26 22:05:35 tgl Exp $
|
||||||
PostgreSQL documentation
|
PostgreSQL documentation
|
||||||
-->
|
-->
|
||||||
|
|
||||||
@ -6901,6 +6901,39 @@ SELECT NULLIF(value, '(none)') ...
|
|||||||
|
|
||||||
</sect2>
|
</sect2>
|
||||||
|
|
||||||
|
<sect2>
|
||||||
|
<title><literal>GREATEST</literal> and <literal>LEAST</literal></title>
|
||||||
|
|
||||||
|
<indexterm>
|
||||||
|
<primary>GREATEST</primary>
|
||||||
|
</indexterm>
|
||||||
|
<indexterm>
|
||||||
|
<primary>LEAST</primary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<synopsis>
|
||||||
|
<function>GREATEST</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
|
||||||
|
</synopsis>
|
||||||
|
<synopsis>
|
||||||
|
<function>LEAST</function>(<replaceable>value</replaceable> <optional>, ...</optional>)
|
||||||
|
</synopsis>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The <function>GREATEST</> and <function>LEAST</> functions select the
|
||||||
|
largest or smallest value from a list of any number of expressions.
|
||||||
|
The expressions must all be convertible to a common data type, which
|
||||||
|
will be the type of the result
|
||||||
|
(see <xref linkend="typeconv-union-case"> for details). NULL values
|
||||||
|
in the list are ignored. The result will be NULL only if all the
|
||||||
|
expressions evaluate to NULL.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Note that <function>GREATEST</> and <function>LEAST</> are not in
|
||||||
|
the SQL standard, but are a common extension.
|
||||||
|
</para>
|
||||||
|
</sect2>
|
||||||
|
|
||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<!--
|
<!--
|
||||||
$PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.43 2004/12/23 23:07:38 tgl Exp $
|
$PostgreSQL: pgsql/doc/src/sgml/typeconv.sgml,v 1.44 2005/06/26 22:05:36 tgl Exp $
|
||||||
-->
|
-->
|
||||||
|
|
||||||
<chapter Id="typeconv">
|
<chapter Id="typeconv">
|
||||||
@ -120,7 +120,7 @@ with, and perhaps converted to, the types of the target columns.
|
|||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry>
|
<varlistentry>
|
||||||
<term>
|
<term>
|
||||||
<literal>UNION</literal>, <literal>CASE</literal>, and <literal>ARRAY</literal> constructs
|
<literal>UNION</literal>, <literal>CASE</literal>, and related constructs
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
@ -129,7 +129,8 @@ must appear in a single set of columns, the types of the results of each
|
|||||||
<command>SELECT</> clause must be matched up and converted to a uniform set.
|
<command>SELECT</> clause must be matched up and converted to a uniform set.
|
||||||
Similarly, the result expressions of a <literal>CASE</> construct must be
|
Similarly, the result expressions of a <literal>CASE</> construct must be
|
||||||
converted to a common type so that the <literal>CASE</> expression as a whole
|
converted to a common type so that the <literal>CASE</> expression as a whole
|
||||||
has a known output type. The same holds for <literal>ARRAY</> constructs.
|
has a known output type. The same holds for <literal>ARRAY</> constructs,
|
||||||
|
and for the <function>GREATEST</> and <function>LEAST</> functions.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@ -782,7 +783,7 @@ padding spaces.
|
|||||||
</sect1>
|
</sect1>
|
||||||
|
|
||||||
<sect1 id="typeconv-union-case">
|
<sect1 id="typeconv-union-case">
|
||||||
<title><literal>UNION</literal>, <literal>CASE</literal>, and <literal>ARRAY</literal> Constructs</title>
|
<title><literal>UNION</literal>, <literal>CASE</literal>, and Related Constructs</title>
|
||||||
|
|
||||||
<indexterm zone="typeconv-union-case">
|
<indexterm zone="typeconv-union-case">
|
||||||
<primary>UNION</primary>
|
<primary>UNION</primary>
|
||||||
@ -799,20 +800,31 @@ padding spaces.
|
|||||||
<secondary>determination of result type</secondary>
|
<secondary>determination of result type</secondary>
|
||||||
</indexterm>
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm zone="typeconv-union-case">
|
||||||
|
<primary>GREATEST</primary>
|
||||||
|
<secondary>determination of result type</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
|
<indexterm zone="typeconv-union-case">
|
||||||
|
<primary>LEAST</primary>
|
||||||
|
<secondary>determination of result type</secondary>
|
||||||
|
</indexterm>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
SQL <literal>UNION</> constructs must match up possibly dissimilar
|
SQL <literal>UNION</> constructs must match up possibly dissimilar
|
||||||
types to become a single result set. The resolution algorithm is
|
types to become a single result set. The resolution algorithm is
|
||||||
applied separately to each output column of a union query. The
|
applied separately to each output column of a union query. The
|
||||||
<literal>INTERSECT</> and <literal>EXCEPT</> constructs resolve
|
<literal>INTERSECT</> and <literal>EXCEPT</> constructs resolve
|
||||||
dissimilar types in the same way as <literal>UNION</>. The
|
dissimilar types in the same way as <literal>UNION</>. The
|
||||||
<literal>CASE</> and <literal>ARRAY</> constructs use the identical
|
<literal>CASE</>, <literal>ARRAY</>, <function>GREATEST</> and
|
||||||
|
<function>LEAST</> constructs use the identical
|
||||||
algorithm to match up their component expressions and select a result
|
algorithm to match up their component expressions and select a result
|
||||||
data type.
|
data type.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
<procedure>
|
<procedure>
|
||||||
<title><literal>UNION</literal>, <literal>CASE</literal>, and
|
<title>Type Resolution for <literal>UNION</literal>, <literal>CASE</literal>,
|
||||||
<literal>ARRAY</literal> Type Resolution</title>
|
and Related Constructs</title>
|
||||||
|
|
||||||
<step performance="required">
|
<step performance="required">
|
||||||
<para>
|
<para>
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* 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,
|
static Datum ExecEvalCoalesce(CoalesceExprState *coalesceExpr,
|
||||||
ExprContext *econtext,
|
ExprContext *econtext,
|
||||||
bool *isNull, ExprDoneCond *isDone);
|
bool *isNull, ExprDoneCond *isDone);
|
||||||
|
static Datum ExecEvalMinMax(MinMaxExprState *minmaxExpr,
|
||||||
|
ExprContext *econtext,
|
||||||
|
bool *isNull, ExprDoneCond *isDone);
|
||||||
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
|
static Datum ExecEvalNullIf(FuncExprState *nullIfExpr,
|
||||||
ExprContext *econtext,
|
ExprContext *econtext,
|
||||||
bool *isNull, ExprDoneCond *isDone);
|
bool *isNull, ExprDoneCond *isDone);
|
||||||
@ -2247,6 +2250,63 @@ ExecEvalCoalesce(CoalesceExprState *coalesceExpr, ExprContext *econtext,
|
|||||||
return (Datum) 0;
|
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
|
* ExecEvalNullIf
|
||||||
*
|
*
|
||||||
@ -3206,6 +3266,36 @@ ExecInitExpr(Expr *node, PlanState *parent)
|
|||||||
state = (ExprState *) cstate;
|
state = (ExprState *) cstate;
|
||||||
}
|
}
|
||||||
break;
|
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:
|
case T_NullIfExpr:
|
||||||
{
|
{
|
||||||
NullIfExpr *nullifexpr = (NullIfExpr *) node;
|
NullIfExpr *nullifexpr = (NullIfExpr *) node;
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.308 2005/06/22 21:14:29 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.309 2005/06/26 22:05:37 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1047,6 +1047,21 @@ _copyCoalesceExpr(CoalesceExpr *from)
|
|||||||
return newnode;
|
return newnode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _copyMinMaxExpr
|
||||||
|
*/
|
||||||
|
static MinMaxExpr *
|
||||||
|
_copyMinMaxExpr(MinMaxExpr *from)
|
||||||
|
{
|
||||||
|
MinMaxExpr *newnode = makeNode(MinMaxExpr);
|
||||||
|
|
||||||
|
COPY_SCALAR_FIELD(minmaxtype);
|
||||||
|
COPY_SCALAR_FIELD(op);
|
||||||
|
COPY_NODE_FIELD(args);
|
||||||
|
|
||||||
|
return newnode;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _copyNullIfExpr (same as OpExpr)
|
* _copyNullIfExpr (same as OpExpr)
|
||||||
*/
|
*/
|
||||||
@ -2805,6 +2820,9 @@ copyObject(void *from)
|
|||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
retval = _copyCoalesceExpr(from);
|
retval = _copyCoalesceExpr(from);
|
||||||
break;
|
break;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
retval = _copyMinMaxExpr(from);
|
||||||
|
break;
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
retval = _copyNullIfExpr(from);
|
retval = _copyNullIfExpr(from);
|
||||||
break;
|
break;
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.245 2005/06/22 21:14:29 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.246 2005/06/26 22:05:37 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -450,6 +450,16 @@ _equalCoalesceExpr(CoalesceExpr *a, CoalesceExpr *b)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
_equalMinMaxExpr(MinMaxExpr *a, MinMaxExpr *b)
|
||||||
|
{
|
||||||
|
COMPARE_SCALAR_FIELD(minmaxtype);
|
||||||
|
COMPARE_SCALAR_FIELD(op);
|
||||||
|
COMPARE_NODE_FIELD(args);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
|
_equalNullIfExpr(NullIfExpr *a, NullIfExpr *b)
|
||||||
{
|
{
|
||||||
@ -1868,6 +1878,9 @@ equal(void *a, void *b)
|
|||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
retval = _equalCoalesceExpr(a, b);
|
retval = _equalCoalesceExpr(a, b);
|
||||||
break;
|
break;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
retval = _equalMinMaxExpr(a, b);
|
||||||
|
break;
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
retval = _equalNullIfExpr(a, b);
|
retval = _equalNullIfExpr(a, b);
|
||||||
break;
|
break;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.255 2005/06/09 04:18:58 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.256 2005/06/26 22:05:37 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Every node type that can appear in stored rules' parsetrees *must*
|
* Every node type that can appear in stored rules' parsetrees *must*
|
||||||
@ -864,6 +864,16 @@ _outCoalesceExpr(StringInfo str, CoalesceExpr *node)
|
|||||||
WRITE_NODE_FIELD(args);
|
WRITE_NODE_FIELD(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_outMinMaxExpr(StringInfo str, MinMaxExpr *node)
|
||||||
|
{
|
||||||
|
WRITE_NODE_TYPE("MINMAX");
|
||||||
|
|
||||||
|
WRITE_OID_FIELD(minmaxtype);
|
||||||
|
WRITE_ENUM_FIELD(op, MinMaxOp);
|
||||||
|
WRITE_NODE_FIELD(args);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
_outNullIfExpr(StringInfo str, NullIfExpr *node)
|
_outNullIfExpr(StringInfo str, NullIfExpr *node)
|
||||||
{
|
{
|
||||||
@ -1896,6 +1906,9 @@ _outNode(StringInfo str, void *obj)
|
|||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
_outCoalesceExpr(str, obj);
|
_outCoalesceExpr(str, obj);
|
||||||
break;
|
break;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
_outMinMaxExpr(str, obj);
|
||||||
|
break;
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
_outNullIfExpr(str, obj);
|
_outNullIfExpr(str, obj);
|
||||||
break;
|
break;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.178 2005/06/05 22:32:54 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/nodes/readfuncs.c,v 1.179 2005/06/26 22:05:37 tgl Exp $
|
||||||
*
|
*
|
||||||
* NOTES
|
* NOTES
|
||||||
* Path and Plan nodes do not have any readfuncs support, because we
|
* Path and Plan nodes do not have any readfuncs support, because we
|
||||||
@ -658,6 +658,21 @@ _readCoalesceExpr(void)
|
|||||||
READ_DONE();
|
READ_DONE();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* _readMinMaxExpr
|
||||||
|
*/
|
||||||
|
static MinMaxExpr *
|
||||||
|
_readMinMaxExpr(void)
|
||||||
|
{
|
||||||
|
READ_LOCALS(MinMaxExpr);
|
||||||
|
|
||||||
|
READ_OID_FIELD(minmaxtype);
|
||||||
|
READ_ENUM_FIELD(op, MinMaxOp);
|
||||||
|
READ_NODE_FIELD(args);
|
||||||
|
|
||||||
|
READ_DONE();
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* _readNullIfExpr
|
* _readNullIfExpr
|
||||||
*/
|
*/
|
||||||
@ -982,6 +997,8 @@ parseNodeString(void)
|
|||||||
return_value = _readRowExpr();
|
return_value = _readRowExpr();
|
||||||
else if (MATCH("COALESCE", 8))
|
else if (MATCH("COALESCE", 8))
|
||||||
return_value = _readCoalesceExpr();
|
return_value = _readCoalesceExpr();
|
||||||
|
else if (MATCH("MINMAX", 6))
|
||||||
|
return_value = _readMinMaxExpr();
|
||||||
else if (MATCH("NULLIFEXPR", 10))
|
else if (MATCH("NULLIFEXPR", 10))
|
||||||
return_value = _readNullIfExpr();
|
return_value = _readNullIfExpr();
|
||||||
else if (MATCH("NULLTEST", 8))
|
else if (MATCH("NULLTEST", 8))
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.198 2005/06/05 22:32:56 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/optimizer/util/clauses.c,v 1.199 2005/06/26 22:05:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -542,6 +542,8 @@ expression_returns_set_walker(Node *node, void *context)
|
|||||||
return false;
|
return false;
|
||||||
if (IsA(node, CoalesceExpr))
|
if (IsA(node, CoalesceExpr))
|
||||||
return false;
|
return false;
|
||||||
|
if (IsA(node, MinMaxExpr))
|
||||||
|
return false;
|
||||||
if (IsA(node, NullIfExpr))
|
if (IsA(node, NullIfExpr))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -847,6 +849,8 @@ contain_nonstrict_functions_walker(Node *node, void *context)
|
|||||||
return true;
|
return true;
|
||||||
if (IsA(node, CoalesceExpr))
|
if (IsA(node, CoalesceExpr))
|
||||||
return true;
|
return true;
|
||||||
|
if (IsA(node, MinMaxExpr))
|
||||||
|
return true;
|
||||||
if (IsA(node, NullIfExpr))
|
if (IsA(node, NullIfExpr))
|
||||||
return true;
|
return true;
|
||||||
if (IsA(node, NullTest))
|
if (IsA(node, NullTest))
|
||||||
@ -1685,7 +1689,7 @@ eval_const_expressions_mutator(Node *node,
|
|||||||
newargs = lappend(newargs, newcasewhen);
|
newargs = lappend(newargs, newcasewhen);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Found a TRUE condition, so none of the remaining alternatives
|
* Found a TRUE condition, so none of the remaining alternatives
|
||||||
* can be reached. We treat the result as the default result.
|
* can be reached. We treat the result as the default result.
|
||||||
@ -2932,6 +2936,8 @@ expression_tree_walker(Node *node,
|
|||||||
return walker(((RowExpr *) node)->args, context);
|
return walker(((RowExpr *) node)->args, context);
|
||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
return walker(((CoalesceExpr *) node)->args, context);
|
return walker(((CoalesceExpr *) node)->args, context);
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
return walker(((MinMaxExpr *) node)->args, context);
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
return walker(((NullIfExpr *) node)->args, context);
|
return walker(((NullIfExpr *) node)->args, context);
|
||||||
case T_NullTest:
|
case T_NullTest:
|
||||||
@ -3392,6 +3398,16 @@ expression_tree_mutator(Node *node,
|
|||||||
return (Node *) newnode;
|
return (Node *) newnode;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
{
|
||||||
|
MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
|
||||||
|
MinMaxExpr *newnode;
|
||||||
|
|
||||||
|
FLATCOPY(newnode, minmaxexpr, MinMaxExpr);
|
||||||
|
MUTATE(newnode->args, minmaxexpr->args, List *);
|
||||||
|
return (Node *) newnode;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
{
|
{
|
||||||
NullIfExpr *expr = (NullIfExpr *) node;
|
NullIfExpr *expr = (NullIfExpr *) node;
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.497 2005/06/24 14:28:06 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.498 2005/06/26 22:05:38 tgl Exp $
|
||||||
*
|
*
|
||||||
* HISTORY
|
* HISTORY
|
||||||
* AUTHOR DATE MAJOR EVENT
|
* AUTHOR DATE MAJOR EVENT
|
||||||
@ -360,7 +360,7 @@ static void doNegateFloat(Value *v);
|
|||||||
FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
|
FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
|
||||||
FREEZE FROM FULL FUNCTION
|
FREEZE FROM FULL FUNCTION
|
||||||
|
|
||||||
GLOBAL GRANT GROUP_P
|
GLOBAL GRANT GREATEST GROUP_P
|
||||||
|
|
||||||
HANDLER HAVING HEADER HOLD HOUR_P
|
HANDLER HAVING HEADER HOLD HOUR_P
|
||||||
|
|
||||||
@ -373,8 +373,8 @@ static void doNegateFloat(Value *v);
|
|||||||
|
|
||||||
KEY
|
KEY
|
||||||
|
|
||||||
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT
|
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL
|
||||||
LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
|
LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
|
||||||
LOCK_P
|
LOCK_P
|
||||||
|
|
||||||
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
|
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
|
||||||
@ -1154,7 +1154,7 @@ AlterTableStmt:
|
|||||||
AlterTableStmt *n = makeNode(AlterTableStmt);
|
AlterTableStmt *n = makeNode(AlterTableStmt);
|
||||||
n->relation = $3;
|
n->relation = $3;
|
||||||
n->cmds = $4;
|
n->cmds = $4;
|
||||||
n->relkind = OBJECT_TABLE;
|
n->relkind = OBJECT_TABLE;
|
||||||
$$ = (Node *)n;
|
$$ = (Node *)n;
|
||||||
}
|
}
|
||||||
| ALTER INDEX relation_expr alter_rel_cmds
|
| ALTER INDEX relation_expr alter_rel_cmds
|
||||||
@ -3821,7 +3821,7 @@ opt_column: COLUMN { $$ = COLUMN; }
|
|||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
*
|
*
|
||||||
* ALTER THING name OWNER TO newname.
|
* ALTER THING name OWNER TO newname.
|
||||||
*
|
*
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
@ -6373,7 +6373,7 @@ a_expr: c_expr { $$ = $1; }
|
|||||||
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)),
|
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $6)),
|
||||||
(Node *) makeA_Expr(AEXPR_AND, NIL,
|
(Node *) makeA_Expr(AEXPR_AND, NIL,
|
||||||
(Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6),
|
(Node *) makeSimpleA_Expr(AEXPR_OP, ">=", $1, $6),
|
||||||
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4)));
|
(Node *) makeSimpleA_Expr(AEXPR_OP, "<=", $1, $4)));
|
||||||
}
|
}
|
||||||
| a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
|
| a_expr NOT BETWEEN SYMMETRIC b_expr AND b_expr %prec BETWEEN
|
||||||
{
|
{
|
||||||
@ -6383,7 +6383,7 @@ a_expr: c_expr { $$ = $1; }
|
|||||||
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)),
|
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)),
|
||||||
(Node *) makeA_Expr(AEXPR_OR, NIL,
|
(Node *) makeA_Expr(AEXPR_OR, NIL,
|
||||||
(Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7),
|
(Node *) makeSimpleA_Expr(AEXPR_OP, "<", $1, $7),
|
||||||
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5)));
|
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $5)));
|
||||||
}
|
}
|
||||||
| a_expr IN_P in_expr
|
| a_expr IN_P in_expr
|
||||||
{
|
{
|
||||||
@ -7065,6 +7065,20 @@ func_expr: func_name '(' ')'
|
|||||||
c->args = $3;
|
c->args = $3;
|
||||||
$$ = (Node *)c;
|
$$ = (Node *)c;
|
||||||
}
|
}
|
||||||
|
| GREATEST '(' expr_list ')'
|
||||||
|
{
|
||||||
|
MinMaxExpr *v = makeNode(MinMaxExpr);
|
||||||
|
v->args = $3;
|
||||||
|
v->op = IS_GREATEST;
|
||||||
|
$$ = (Node *)v;
|
||||||
|
}
|
||||||
|
| LEAST '(' expr_list ')'
|
||||||
|
{
|
||||||
|
MinMaxExpr *v = makeNode(MinMaxExpr);
|
||||||
|
v->args = $3;
|
||||||
|
v->op = IS_LEAST;
|
||||||
|
$$ = (Node *)v;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -7944,10 +7958,12 @@ col_name_keyword:
|
|||||||
| EXISTS
|
| EXISTS
|
||||||
| EXTRACT
|
| EXTRACT
|
||||||
| FLOAT_P
|
| FLOAT_P
|
||||||
|
| GREATEST
|
||||||
| INOUT
|
| INOUT
|
||||||
| INT_P
|
| INT_P
|
||||||
| INTEGER
|
| INTEGER
|
||||||
| INTERVAL
|
| INTERVAL
|
||||||
|
| LEAST
|
||||||
| NATIONAL
|
| NATIONAL
|
||||||
| NCHAR
|
| NCHAR
|
||||||
| NONE
|
| NONE
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.158 2005/06/22 21:14:30 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.159 2005/06/26 22:05:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -146,6 +146,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||||||
{"function", FUNCTION},
|
{"function", FUNCTION},
|
||||||
{"global", GLOBAL},
|
{"global", GLOBAL},
|
||||||
{"grant", GRANT},
|
{"grant", GRANT},
|
||||||
|
{"greatest", GREATEST},
|
||||||
{"group", GROUP_P},
|
{"group", GROUP_P},
|
||||||
{"handler", HANDLER},
|
{"handler", HANDLER},
|
||||||
{"having", HAVING},
|
{"having", HAVING},
|
||||||
@ -184,6 +185,7 @@ static const ScanKeyword ScanKeywords[] = {
|
|||||||
{"large", LARGE_P},
|
{"large", LARGE_P},
|
||||||
{"last", LAST_P},
|
{"last", LAST_P},
|
||||||
{"leading", LEADING},
|
{"leading", LEADING},
|
||||||
|
{"least", LEAST},
|
||||||
{"left", LEFT},
|
{"left", LEFT},
|
||||||
{"level", LEVEL},
|
{"level", LEVEL},
|
||||||
{"like", LIKE},
|
{"like", LIKE},
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.183 2005/06/04 20:56:13 momjian Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.184 2005/06/26 22:05:39 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -53,6 +53,7 @@ static Node *transformSubLink(ParseState *pstate, SubLink *sublink);
|
|||||||
static Node *transformArrayExpr(ParseState *pstate, ArrayExpr *a);
|
static Node *transformArrayExpr(ParseState *pstate, ArrayExpr *a);
|
||||||
static Node *transformRowExpr(ParseState *pstate, RowExpr *r);
|
static Node *transformRowExpr(ParseState *pstate, RowExpr *r);
|
||||||
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
|
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
|
||||||
|
static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
|
||||||
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
|
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
|
||||||
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
|
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
|
||||||
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
|
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
|
||||||
@ -209,6 +210,10 @@ transformExpr(ParseState *pstate, Node *expr)
|
|||||||
result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr);
|
result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
|
||||||
|
break;
|
||||||
|
|
||||||
case T_NullTest:
|
case T_NullTest:
|
||||||
{
|
{
|
||||||
NullTest *n = (NullTest *) expr;
|
NullTest *n = (NullTest *) expr;
|
||||||
@ -1229,6 +1234,44 @@ transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
|
|||||||
return (Node *) newc;
|
return (Node *) newc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Node *
|
||||||
|
transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m)
|
||||||
|
{
|
||||||
|
MinMaxExpr *newm = makeNode(MinMaxExpr);
|
||||||
|
List *newargs = NIL;
|
||||||
|
List *newcoercedargs = NIL;
|
||||||
|
List *typeids = NIL;
|
||||||
|
ListCell *args;
|
||||||
|
|
||||||
|
newm->op = m->op;
|
||||||
|
foreach(args, m->args)
|
||||||
|
{
|
||||||
|
Node *e = (Node *) lfirst(args);
|
||||||
|
Node *newe;
|
||||||
|
|
||||||
|
newe = transformExpr(pstate, e);
|
||||||
|
newargs = lappend(newargs, newe);
|
||||||
|
typeids = lappend_oid(typeids, exprType(newe));
|
||||||
|
}
|
||||||
|
|
||||||
|
newm->minmaxtype = select_common_type(typeids, "GREATEST/LEAST");
|
||||||
|
|
||||||
|
/* Convert arguments if necessary */
|
||||||
|
foreach(args, newargs)
|
||||||
|
{
|
||||||
|
Node *e = (Node *) lfirst(args);
|
||||||
|
Node *newe;
|
||||||
|
|
||||||
|
newe = coerce_to_common_type(pstate, e,
|
||||||
|
newm->minmaxtype,
|
||||||
|
"GREATEST/LEAST");
|
||||||
|
newcoercedargs = lappend(newcoercedargs, newe);
|
||||||
|
}
|
||||||
|
|
||||||
|
newm->args = newcoercedargs;
|
||||||
|
return (Node *) newm;
|
||||||
|
}
|
||||||
|
|
||||||
static Node *
|
static Node *
|
||||||
transformBooleanTest(ParseState *pstate, BooleanTest *b)
|
transformBooleanTest(ParseState *pstate, BooleanTest *b)
|
||||||
{
|
{
|
||||||
@ -1503,6 +1546,9 @@ exprType(Node *expr)
|
|||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
type = ((CoalesceExpr *) expr)->coalescetype;
|
type = ((CoalesceExpr *) expr)->coalescetype;
|
||||||
break;
|
break;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
type = ((MinMaxExpr *) expr)->minmaxtype;
|
||||||
|
break;
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
|
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
|
||||||
break;
|
break;
|
||||||
@ -1637,6 +1683,30 @@ exprTypmod(Node *expr)
|
|||||||
return typmod;
|
return typmod;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* If all the alternatives agree on type/typmod, return
|
||||||
|
* that typmod, else use -1
|
||||||
|
*/
|
||||||
|
MinMaxExpr *mexpr = (MinMaxExpr *) expr;
|
||||||
|
Oid minmaxtype = mexpr->minmaxtype;
|
||||||
|
int32 typmod;
|
||||||
|
ListCell *arg;
|
||||||
|
|
||||||
|
typmod = exprTypmod((Node *) linitial(mexpr->args));
|
||||||
|
foreach(arg, mexpr->args)
|
||||||
|
{
|
||||||
|
Node *e = (Node *) lfirst(arg);
|
||||||
|
|
||||||
|
if (exprType(e) != minmaxtype)
|
||||||
|
return -1;
|
||||||
|
if (exprTypmod(e) != typmod)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
return typmod;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
{
|
{
|
||||||
NullIfExpr *nexpr = (NullIfExpr *) expr;
|
NullIfExpr *nexpr = (NullIfExpr *) expr;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.136 2005/06/05 00:38:10 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/parser/parse_target.c,v 1.137 2005/06/26 22:05:40 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -1123,6 +1123,18 @@ FigureColnameInternal(Node *node, char **name)
|
|||||||
/* make coalesce() act like a regular function */
|
/* make coalesce() act like a regular function */
|
||||||
*name = "coalesce";
|
*name = "coalesce";
|
||||||
return 2;
|
return 2;
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
/* make greatest/least act like a regular function */
|
||||||
|
switch (((MinMaxExpr*) node)->op)
|
||||||
|
{
|
||||||
|
case IS_GREATEST:
|
||||||
|
*name = "greatest";
|
||||||
|
return 2;
|
||||||
|
case IS_LEAST:
|
||||||
|
*name = "least";
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* back to source text
|
* back to source text
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.200 2005/06/05 00:38:10 tgl Exp $
|
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.201 2005/06/26 22:05:40 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -2781,6 +2781,7 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
|||||||
case T_ArrayExpr:
|
case T_ArrayExpr:
|
||||||
case T_RowExpr:
|
case T_RowExpr:
|
||||||
case T_CoalesceExpr:
|
case T_CoalesceExpr:
|
||||||
|
case T_MinMaxExpr:
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
case T_Aggref:
|
case T_Aggref:
|
||||||
case T_FuncExpr:
|
case T_FuncExpr:
|
||||||
@ -2886,10 +2887,11 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
|||||||
case T_BoolExpr: /* lower precedence */
|
case T_BoolExpr: /* lower precedence */
|
||||||
case T_ArrayRef: /* other separators */
|
case T_ArrayRef: /* other separators */
|
||||||
case T_ArrayExpr: /* other separators */
|
case T_ArrayExpr: /* other separators */
|
||||||
case T_RowExpr: /* other separators */
|
case T_RowExpr: /* other separators */
|
||||||
case T_CoalesceExpr: /* own parentheses */
|
case T_CoalesceExpr: /* own parentheses */
|
||||||
|
case T_MinMaxExpr: /* own parentheses */
|
||||||
case T_NullIfExpr: /* other separators */
|
case T_NullIfExpr: /* other separators */
|
||||||
case T_Aggref: /* own parentheses */
|
case T_Aggref: /* own parentheses */
|
||||||
case T_CaseExpr: /* other separators */
|
case T_CaseExpr: /* other separators */
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@ -2933,10 +2935,11 @@ isSimpleNode(Node *node, Node *parentNode, int prettyFlags)
|
|||||||
}
|
}
|
||||||
case T_ArrayRef: /* other separators */
|
case T_ArrayRef: /* other separators */
|
||||||
case T_ArrayExpr: /* other separators */
|
case T_ArrayExpr: /* other separators */
|
||||||
case T_RowExpr: /* other separators */
|
case T_RowExpr: /* other separators */
|
||||||
case T_CoalesceExpr: /* own parentheses */
|
case T_CoalesceExpr: /* own parentheses */
|
||||||
|
case T_MinMaxExpr: /* own parentheses */
|
||||||
case T_NullIfExpr: /* other separators */
|
case T_NullIfExpr: /* other separators */
|
||||||
case T_Aggref: /* own parentheses */
|
case T_Aggref: /* own parentheses */
|
||||||
case T_CaseExpr: /* other separators */
|
case T_CaseExpr: /* other separators */
|
||||||
return true;
|
return true;
|
||||||
default:
|
default:
|
||||||
@ -3491,6 +3494,24 @@ get_rule_expr(Node *node, deparse_context *context,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
{
|
||||||
|
MinMaxExpr *minmaxexpr = (MinMaxExpr *) node;
|
||||||
|
|
||||||
|
switch (minmaxexpr->op)
|
||||||
|
{
|
||||||
|
case IS_GREATEST:
|
||||||
|
appendStringInfo(buf, "GREATEST(");
|
||||||
|
break;
|
||||||
|
case IS_LEAST:
|
||||||
|
appendStringInfo(buf, "LEAST(");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
get_rule_expr((Node *) minmaxexpr->args, context, true);
|
||||||
|
appendStringInfoChar(buf, ')');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
{
|
{
|
||||||
NullIfExpr *nullifexpr = (NullIfExpr *) node;
|
NullIfExpr *nullifexpr = (NullIfExpr *) node;
|
||||||
@ -4109,7 +4130,7 @@ get_from_clause_item(Node *jtnode, Query *query, deparse_context *context)
|
|||||||
bool need_paren_on_right;
|
bool need_paren_on_right;
|
||||||
|
|
||||||
need_paren_on_right = PRETTY_PAREN(context) &&
|
need_paren_on_right = PRETTY_PAREN(context) &&
|
||||||
!IsA(j->rarg, RangeTblRef) &&
|
!IsA(j->rarg, RangeTblRef) &&
|
||||||
!(IsA(j->rarg, JoinExpr) && ((JoinExpr*) j->rarg)->alias != NULL);
|
!(IsA(j->rarg, JoinExpr) && ((JoinExpr*) j->rarg)->alias != NULL);
|
||||||
|
|
||||||
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
if (!PRETTY_PAREN(context) || j->alias != NULL)
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.135 2005/06/20 18:37:02 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.136 2005/06/26 22:05:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -673,6 +673,17 @@ typedef struct CoalesceExprState
|
|||||||
List *args; /* the arguments */
|
List *args; /* the arguments */
|
||||||
} CoalesceExprState;
|
} CoalesceExprState;
|
||||||
|
|
||||||
|
/* ----------------
|
||||||
|
* MinMaxExprState node
|
||||||
|
* ----------------
|
||||||
|
*/
|
||||||
|
typedef struct MinMaxExprState
|
||||||
|
{
|
||||||
|
ExprState xprstate;
|
||||||
|
List *args; /* the arguments */
|
||||||
|
FmgrInfo cfunc; /* lookup info for comparison func */
|
||||||
|
} MinMaxExprState;
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* CoerceToDomainState node
|
* CoerceToDomainState node
|
||||||
* ----------------
|
* ----------------
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.170 2005/06/09 04:19:00 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.171 2005/06/26 22:05:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -126,6 +126,7 @@ typedef enum NodeTag
|
|||||||
T_ArrayExpr,
|
T_ArrayExpr,
|
||||||
T_RowExpr,
|
T_RowExpr,
|
||||||
T_CoalesceExpr,
|
T_CoalesceExpr,
|
||||||
|
T_MinMaxExpr,
|
||||||
T_NullIfExpr,
|
T_NullIfExpr,
|
||||||
T_NullTest,
|
T_NullTest,
|
||||||
T_BooleanTest,
|
T_BooleanTest,
|
||||||
@ -159,6 +160,7 @@ typedef enum NodeTag
|
|||||||
T_ArrayExprState,
|
T_ArrayExprState,
|
||||||
T_RowExprState,
|
T_RowExprState,
|
||||||
T_CoalesceExprState,
|
T_CoalesceExprState,
|
||||||
|
T_MinMaxExprState,
|
||||||
T_CoerceToDomainState,
|
T_CoerceToDomainState,
|
||||||
T_DomainConstraintState,
|
T_DomainConstraintState,
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
|
||||||
* Portions Copyright (c) 1994, Regents of the University of California
|
* Portions Copyright (c) 1994, Regents of the University of California
|
||||||
*
|
*
|
||||||
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.107 2005/04/06 16:34:07 tgl Exp $
|
* $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.108 2005/06/26 22:05:41 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -657,6 +657,23 @@ typedef struct CoalesceExpr
|
|||||||
List *args; /* the arguments */
|
List *args; /* the arguments */
|
||||||
} CoalesceExpr;
|
} CoalesceExpr;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MinMaxExpr - a GREATEST or LEAST function
|
||||||
|
*/
|
||||||
|
typedef enum MinMaxOp
|
||||||
|
{
|
||||||
|
IS_GREATEST,
|
||||||
|
IS_LEAST
|
||||||
|
} MinMaxOp;
|
||||||
|
|
||||||
|
typedef struct MinMaxExpr
|
||||||
|
{
|
||||||
|
Expr xpr;
|
||||||
|
Oid minmaxtype; /* common type of arguments and result */
|
||||||
|
MinMaxOp op; /* function to execute */
|
||||||
|
List *args; /* the arguments */
|
||||||
|
} MinMaxExpr;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NullIfExpr - a NULLIF expression
|
* NullIfExpr - a NULLIF expression
|
||||||
*
|
*
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
* procedural language
|
* procedural language
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.148 2005/06/22 07:28:47 neilc Exp $
|
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.149 2005/06/26 22:05:42 tgl Exp $
|
||||||
*
|
*
|
||||||
* This software is copyrighted by Jan Wieck - Hamburg.
|
* This software is copyrighted by Jan Wieck - Hamburg.
|
||||||
*
|
*
|
||||||
@ -4296,6 +4296,16 @@ exec_simple_check_node(Node *node)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case T_MinMaxExpr:
|
||||||
|
{
|
||||||
|
MinMaxExpr *expr = (MinMaxExpr *) node;
|
||||||
|
|
||||||
|
if (!exec_simple_check_node((Node *) expr->args))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
case T_NullIfExpr:
|
case T_NullIfExpr:
|
||||||
{
|
{
|
||||||
NullIfExpr *expr = (NullIfExpr *) node;
|
NullIfExpr *expr = (NullIfExpr *) node;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user