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:
@@ -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
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user