1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-09 06:21:09 +03:00

Add Oracle-compatible GREATEST and LEAST functions. Pavel Stehule

This commit is contained in:
Tom Lane
2005-06-26 22:05:42 +00:00
parent d395aecffa
commit 943b396245
17 changed files with 409 additions and 36 deletions

View File

@@ -11,7 +11,7 @@
*
*
* 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
* AUTHOR DATE MAJOR EVENT
@@ -360,7 +360,7 @@ static void doNegateFloat(Value *v);
FALSE_P FETCH FIRST_P FLOAT_P FOR FORCE FOREIGN FORWARD
FREEZE FROM FULL FUNCTION
GLOBAL GRANT GROUP_P
GLOBAL GRANT GREATEST GROUP_P
HANDLER HAVING HEADER HOLD HOUR_P
@@ -373,8 +373,8 @@ static void doNegateFloat(Value *v);
KEY
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEFT LEVEL LIKE LIMIT
LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
LANCOMPILER LANGUAGE LARGE_P LAST_P LEADING LEAST LEFT LEVEL
LIKE LIMIT LISTEN LOAD LOCAL LOCALTIME LOCALTIMESTAMP LOCATION
LOCK_P
MATCH MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
@@ -1154,7 +1154,7 @@ AlterTableStmt:
AlterTableStmt *n = makeNode(AlterTableStmt);
n->relation = $3;
n->cmds = $4;
n->relkind = OBJECT_TABLE;
n->relkind = OBJECT_TABLE;
$$ = (Node *)n;
}
| 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 *) makeA_Expr(AEXPR_AND, NIL,
(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
{
@@ -6383,7 +6383,7 @@ a_expr: c_expr { $$ = $1; }
(Node *) makeSimpleA_Expr(AEXPR_OP, ">", $1, $7)),
(Node *) makeA_Expr(AEXPR_OR, NIL,
(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
{
@@ -7065,6 +7065,20 @@ func_expr: func_name '(' ')'
c->args = $3;
$$ = (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
| EXTRACT
| FLOAT_P
| GREATEST
| INOUT
| INT_P
| INTEGER
| INTERVAL
| LEAST
| NATIONAL
| NCHAR
| NONE

View File

@@ -8,7 +8,7 @@
*
*
* 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},
{"global", GLOBAL},
{"grant", GRANT},
{"greatest", GREATEST},
{"group", GROUP_P},
{"handler", HANDLER},
{"having", HAVING},
@@ -184,6 +185,7 @@ static const ScanKeyword ScanKeywords[] = {
{"large", LARGE_P},
{"last", LAST_P},
{"leading", LEADING},
{"least", LEAST},
{"left", LEFT},
{"level", LEVEL},
{"like", LIKE},

View File

@@ -8,7 +8,7 @@
*
*
* 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 *transformRowExpr(ParseState *pstate, RowExpr *r);
static Node *transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c);
static Node *transformMinMaxExpr(ParseState *pstate, MinMaxExpr *m);
static Node *transformBooleanTest(ParseState *pstate, BooleanTest *b);
static Node *transformColumnRef(ParseState *pstate, ColumnRef *cref);
static Node *transformWholeRowRef(ParseState *pstate, char *schemaname,
@@ -209,6 +210,10 @@ transformExpr(ParseState *pstate, Node *expr)
result = transformCoalesceExpr(pstate, (CoalesceExpr *) expr);
break;
case T_MinMaxExpr:
result = transformMinMaxExpr(pstate, (MinMaxExpr *) expr);
break;
case T_NullTest:
{
NullTest *n = (NullTest *) expr;
@@ -1229,6 +1234,44 @@ transformCoalesceExpr(ParseState *pstate, CoalesceExpr *c)
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 *
transformBooleanTest(ParseState *pstate, BooleanTest *b)
{
@@ -1503,6 +1546,9 @@ exprType(Node *expr)
case T_CoalesceExpr:
type = ((CoalesceExpr *) expr)->coalescetype;
break;
case T_MinMaxExpr:
type = ((MinMaxExpr *) expr)->minmaxtype;
break;
case T_NullIfExpr:
type = exprType((Node *) linitial(((NullIfExpr *) expr)->args));
break;
@@ -1637,6 +1683,30 @@ exprTypmod(Node *expr)
return typmod;
}
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:
{
NullIfExpr *nexpr = (NullIfExpr *) expr;

View File

@@ -8,7 +8,7 @@
*
*
* 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 */
*name = "coalesce";
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:
break;
}