mirror of
https://github.com/postgres/postgres.git
synced 2025-07-17 06:41:09 +03:00
Fixed wrong hasAggs when aggregate columns of view aren't
selected. Disabled ability of defining DISTINCT or ORDER BY on views. Jan
This commit is contained in:
@ -7,7 +7,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.27 1999/05/10 00:45:30 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteDefine.c,v 1.28 1999/05/12 17:04:46 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -317,6 +317,18 @@ DefineQueryRewrite(RuleStmt *stmt)
|
|||||||
if (query->limitOffset != NULL || query->limitCount != NULL)
|
if (query->limitOffset != NULL || query->limitCount != NULL)
|
||||||
elog(ERROR, "LIMIT clause not supported in views");
|
elog(ERROR, "LIMIT clause not supported in views");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DISTINCT on view is not supported
|
||||||
|
*/
|
||||||
|
if (query->uniqueFlag != NULL)
|
||||||
|
elog(ERROR, "DISTINCT not supported in views");
|
||||||
|
|
||||||
|
/*
|
||||||
|
* ORDER BY in view is not supported
|
||||||
|
*/
|
||||||
|
if (query->sortClause != NIL)
|
||||||
|
elog(ERROR, "ORDER BY not supported in views");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* ... and finally the rule must be named _RETviewname.
|
* ... and finally the rule must be named _RETviewname.
|
||||||
*/
|
*/
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.39 1999/05/12 15:01:53 wieck Exp $
|
* $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.40 1999/05/12 17:04:47 wieck Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
@ -59,6 +59,7 @@ static void modifyAggrefChangeVarnodes(Node **nodePtr, int rt_index, int new_ind
|
|||||||
static void modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr);
|
static void modifyAggrefDropQual(Node **nodePtr, Node *orignode, Expr *expr);
|
||||||
static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree);
|
static SubLink *modifyAggrefMakeSublink(Expr *origexp, Query *parsetree);
|
||||||
static void modifyAggrefQual(Node **nodePtr, Query *parsetree);
|
static void modifyAggrefQual(Node **nodePtr, Query *parsetree);
|
||||||
|
static bool checkQueryHasAggs(Node *node);
|
||||||
static Query *fireRIRrules(Query *parsetree);
|
static Query *fireRIRrules(Query *parsetree);
|
||||||
|
|
||||||
|
|
||||||
@ -1272,6 +1273,126 @@ modifyAggrefQual(Node **nodePtr, Query *parsetree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checkQueryHasAggs -
|
||||||
|
* Queries marked hasAggs might not have them any longer after
|
||||||
|
* rewriting. Check it.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
checkQueryHasAggs(Node *node)
|
||||||
|
{
|
||||||
|
if (node == NULL)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
switch(nodeTag(node)) {
|
||||||
|
case T_TargetEntry:
|
||||||
|
{
|
||||||
|
TargetEntry *tle = (TargetEntry *)node;
|
||||||
|
|
||||||
|
return checkQueryHasAggs((Node *)(tle->expr));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Aggref:
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
case T_Expr:
|
||||||
|
{
|
||||||
|
Expr *exp = (Expr *)node;
|
||||||
|
|
||||||
|
return checkQueryHasAggs((Node *)(exp->args));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Iter:
|
||||||
|
{
|
||||||
|
Iter *iter = (Iter *)node;
|
||||||
|
|
||||||
|
return checkQueryHasAggs((Node *)(iter->iterexpr));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_ArrayRef:
|
||||||
|
{
|
||||||
|
ArrayRef *ref = (ArrayRef *)node;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(ref->refupperindexpr)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(ref->reflowerindexpr)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(ref->refexpr)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(ref->refassgnexpr)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_Var:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case T_Param:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case T_Const:
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
case T_List:
|
||||||
|
{
|
||||||
|
List *l;
|
||||||
|
|
||||||
|
foreach (l, (List *)node) {
|
||||||
|
if (checkQueryHasAggs((Node *)lfirst(l)))
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_CaseExpr:
|
||||||
|
{
|
||||||
|
CaseExpr *exp = (CaseExpr *)node;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(exp->args)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(exp->defresult)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case T_CaseWhen:
|
||||||
|
{
|
||||||
|
CaseWhen *when = (CaseWhen *)node;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(when->expr)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
if (checkQueryHasAggs((Node *)(when->result)))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
elog(NOTICE, "unknown node tag %d in checkQueryHasAggs()", nodeTag(node));
|
||||||
|
elog(NOTICE, "Node is: %s", nodeToString(node));
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static Node *
|
static Node *
|
||||||
FindMatchingTLEntry(List *tlist, char *e_attname)
|
FindMatchingTLEntry(List *tlist, char *e_attname)
|
||||||
{
|
{
|
||||||
@ -2574,8 +2695,17 @@ BasicQueryRewrite(Query *parsetree)
|
|||||||
* Apply all the RIR rules on each query
|
* Apply all the RIR rules on each query
|
||||||
*/
|
*/
|
||||||
foreach (l, querylist) {
|
foreach (l, querylist) {
|
||||||
query = (Query *)lfirst(l);
|
query = fireRIRrules((Query *)lfirst(l));
|
||||||
results = lappend(results, fireRIRrules(query));
|
/*
|
||||||
|
* If the query was marked having aggregates, check if
|
||||||
|
* this is still true after rewriting. This check must get
|
||||||
|
* expanded when someday aggregates can appear somewhere
|
||||||
|
* else than in the targetlist or the having qual.
|
||||||
|
*/
|
||||||
|
if (query->hasAggs)
|
||||||
|
query->hasAggs = checkQueryHasAggs((Node *)(query->targetList))
|
||||||
|
| checkQueryHasAggs((Node *)(query->havingQual));
|
||||||
|
results = lappend(results, query);
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user