diff options
Diffstat (limited to 'src/backend/parser/analyze.c')
-rw-r--r-- | src/backend/parser/analyze.c | 138 |
1 files changed, 33 insertions, 105 deletions
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 93ef724ffff..6c3d89a14f6 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -368,7 +368,8 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) */ transformFromClause(pstate, stmt->usingClause); - qual = transformWhereClause(pstate, stmt->whereClause, "WHERE"); + qual = transformWhereClause(pstate, stmt->whereClause, + EXPR_KIND_WHERE, "WHERE"); qry->returningList = transformReturningList(pstate, stmt->returningList); @@ -378,8 +379,6 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt) qry->hasSubLinks = pstate->p_hasSubLinks; qry->hasWindowFuncs = pstate->p_hasWindowFuncs; - if (pstate->p_hasWindowFuncs) - parseCheckWindowFuncs(pstate, qry); qry->hasAggs = pstate->p_hasAggs; if (pstate->p_hasAggs) parseCheckAggregates(pstate, qry); @@ -597,7 +596,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) List *sublist = (List *) lfirst(lc); /* Do basic expression transformation (same as a ROW() expr) */ - sublist = transformExpressionList(pstate, sublist); + sublist = transformExpressionList(pstate, sublist, EXPR_KIND_VALUES); /* * All the sublists must be the same length, *after* @@ -680,16 +679,11 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) } else { - /*---------- - * Process INSERT ... VALUES with a single VALUES sublist. - * We treat this separately for efficiency and for historical - * compatibility --- specifically, allowing table references, - * such as - * INSERT INTO foo VALUES(bar.*) - * - * The sublist is just computed directly as the Query's targetlist, - * with no VALUES RTE. So it works just like SELECT without FROM. - *---------- + /* + * Process INSERT ... VALUES with a single VALUES sublist. We treat + * this case separately for efficiency. The sublist is just computed + * directly as the Query's targetlist, with no VALUES RTE. So it + * works just like a SELECT without any FROM. */ List *valuesLists = selectStmt->valuesLists; @@ -698,7 +692,8 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) /* Do basic expression transformation (same as a ROW() expr) */ exprList = transformExpressionList(pstate, - (List *) linitial(valuesLists)); + (List *) linitial(valuesLists), + EXPR_KIND_VALUES); /* Prepare row for assignment to target table */ exprList = transformInsertRow(pstate, exprList, @@ -758,19 +753,6 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt) qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); qry->hasSubLinks = pstate->p_hasSubLinks; - /* aggregates not allowed (but subselects are okay) */ - if (pstate->p_hasAggs) - ereport(ERROR, - (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in VALUES"), - parser_errposition(pstate, - locate_agg_of_level((Node *) qry, 0)))); - if (pstate->p_hasWindowFuncs) - ereport(ERROR, - (errcode(ERRCODE_WINDOWING_ERROR), - errmsg("cannot use window function in VALUES"), - parser_errposition(pstate, - locate_windowfunc((Node *) qry)))); assign_query_collations(pstate, qry); @@ -845,6 +827,7 @@ transformInsertRow(ParseState *pstate, List *exprlist, Assert(IsA(col, ResTarget)); expr = transformAssignedExpr(pstate, expr, + EXPR_KIND_INSERT_TARGET, col->name, lfirst_int(attnos), col->indirection, @@ -945,19 +928,19 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) transformFromClause(pstate, stmt->fromClause); /* transform targetlist */ - qry->targetList = transformTargetList(pstate, stmt->targetList); + qry->targetList = transformTargetList(pstate, stmt->targetList, + EXPR_KIND_SELECT_TARGET); /* mark column origins */ markTargetListOrigins(pstate, qry->targetList); /* transform WHERE */ - qual = transformWhereClause(pstate, stmt->whereClause, "WHERE"); + qual = transformWhereClause(pstate, stmt->whereClause, + EXPR_KIND_WHERE, "WHERE"); - /* - * Initial processing of HAVING clause is just like WHERE clause. - */ + /* initial processing of HAVING clause is much like WHERE clause */ qry->havingQual = transformWhereClause(pstate, stmt->havingClause, - "HAVING"); + EXPR_KIND_HAVING, "HAVING"); /* * Transform sorting/grouping stuff. Do ORDER BY first because both @@ -968,6 +951,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) qry->sortClause = transformSortClause(pstate, stmt->sortClause, &qry->targetList, + EXPR_KIND_ORDER_BY, true /* fix unknowns */ , false /* allow SQL92 rules */ ); @@ -975,6 +959,7 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) stmt->groupClause, &qry->targetList, qry->sortClause, + EXPR_KIND_GROUP_BY, false /* allow SQL92 rules */ ); if (stmt->distinctClause == NIL) @@ -1003,9 +988,9 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) /* transform LIMIT */ qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset, - "OFFSET"); + EXPR_KIND_OFFSET, "OFFSET"); qry->limitCount = transformLimitClause(pstate, stmt->limitCount, - "LIMIT"); + EXPR_KIND_LIMIT, "LIMIT"); /* transform window clauses after we have seen all window functions */ qry->windowClause = transformWindowDefinitions(pstate, @@ -1017,8 +1002,6 @@ transformSelectStmt(ParseState *pstate, SelectStmt *stmt) qry->hasSubLinks = pstate->p_hasSubLinks; qry->hasWindowFuncs = pstate->p_hasWindowFuncs; - if (pstate->p_hasWindowFuncs) - parseCheckWindowFuncs(pstate, qry); qry->hasAggs = pstate->p_hasAggs; if (pstate->p_hasAggs || qry->groupClause || qry->havingQual) parseCheckAggregates(pstate, qry); @@ -1090,7 +1073,7 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) List *sublist = (List *) lfirst(lc); /* Do basic expression transformation (same as a ROW() expr) */ - sublist = transformExpressionList(pstate, sublist); + sublist = transformExpressionList(pstate, sublist, EXPR_KIND_VALUES); /* * All the sublists must be the same length, *after* transformation @@ -1217,13 +1200,14 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) qry->sortClause = transformSortClause(pstate, stmt->sortClause, &qry->targetList, + EXPR_KIND_ORDER_BY, true /* fix unknowns */ , false /* allow SQL92 rules */ ); qry->limitOffset = transformLimitClause(pstate, stmt->limitOffset, - "OFFSET"); + EXPR_KIND_OFFSET, "OFFSET"); qry->limitCount = transformLimitClause(pstate, stmt->limitCount, - "LIMIT"); + EXPR_KIND_LIMIT, "LIMIT"); if (stmt->lockingClause) ereport(ERROR, @@ -1249,19 +1233,6 @@ transformValuesClause(ParseState *pstate, SelectStmt *stmt) qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); qry->hasSubLinks = pstate->p_hasSubLinks; - /* aggregates not allowed (but subselects are okay) */ - if (pstate->p_hasAggs) - ereport(ERROR, - (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in VALUES"), - parser_errposition(pstate, - locate_agg_of_level((Node *) exprsLists, 0)))); - if (pstate->p_hasWindowFuncs) - ereport(ERROR, - (errcode(ERRCODE_WINDOWING_ERROR), - errmsg("cannot use window function in VALUES"), - parser_errposition(pstate, - locate_windowfunc((Node *) exprsLists)))); assign_query_collations(pstate, qry); @@ -1460,6 +1431,7 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) qry->sortClause = transformSortClause(pstate, sortClause, &qry->targetList, + EXPR_KIND_ORDER_BY, false /* no unknowns expected */ , false /* allow SQL92 rules */ ); @@ -1477,17 +1449,15 @@ transformSetOperationStmt(ParseState *pstate, SelectStmt *stmt) exprLocation(list_nth(qry->targetList, tllen))))); qry->limitOffset = transformLimitClause(pstate, limitOffset, - "OFFSET"); + EXPR_KIND_OFFSET, "OFFSET"); qry->limitCount = transformLimitClause(pstate, limitCount, - "LIMIT"); + EXPR_KIND_LIMIT, "LIMIT"); qry->rtable = pstate->p_rtable; qry->jointree = makeFromExpr(pstate->p_joinlist, NULL); qry->hasSubLinks = pstate->p_hasSubLinks; qry->hasWindowFuncs = pstate->p_hasWindowFuncs; - if (pstate->p_hasWindowFuncs) - parseCheckWindowFuncs(pstate, qry); qry->hasAggs = pstate->p_hasAggs; if (pstate->p_hasAggs || qry->groupClause || qry->havingQual) parseCheckAggregates(pstate, qry); @@ -1937,9 +1907,11 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) */ transformFromClause(pstate, stmt->fromClause); - qry->targetList = transformTargetList(pstate, stmt->targetList); + qry->targetList = transformTargetList(pstate, stmt->targetList, + EXPR_KIND_UPDATE_SOURCE); - qual = transformWhereClause(pstate, stmt->whereClause, "WHERE"); + qual = transformWhereClause(pstate, stmt->whereClause, + EXPR_KIND_WHERE, "WHERE"); qry->returningList = transformReturningList(pstate, stmt->returningList); @@ -1949,24 +1921,6 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt) qry->hasSubLinks = pstate->p_hasSubLinks; /* - * Top-level aggregates are simply disallowed in UPDATE, per spec. (From - * an implementation point of view, this is forced because the implicit - * ctid reference would otherwise be an ungrouped variable.) - */ - if (pstate->p_hasAggs) - ereport(ERROR, - (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in UPDATE"), - parser_errposition(pstate, - locate_agg_of_level((Node *) qry, 0)))); - if (pstate->p_hasWindowFuncs) - ereport(ERROR, - (errcode(ERRCODE_WINDOWING_ERROR), - errmsg("cannot use window function in UPDATE"), - parser_errposition(pstate, - locate_windowfunc((Node *) qry)))); - - /* * Now we are done with SELECT-like processing, and can get on with * transforming the target list to match the UPDATE target columns. */ @@ -2040,8 +1994,6 @@ transformReturningList(ParseState *pstate, List *returningList) { List *rlist; int save_next_resno; - bool save_hasAggs; - bool save_hasWindowFuncs; if (returningList == NIL) return NIL; /* nothing to do */ @@ -2054,38 +2006,14 @@ transformReturningList(ParseState *pstate, List *returningList) save_next_resno = pstate->p_next_resno; pstate->p_next_resno = 1; - /* save other state so that we can detect disallowed stuff */ - save_hasAggs = pstate->p_hasAggs; - pstate->p_hasAggs = false; - save_hasWindowFuncs = pstate->p_hasWindowFuncs; - pstate->p_hasWindowFuncs = false; - /* transform RETURNING identically to a SELECT targetlist */ - rlist = transformTargetList(pstate, returningList); - - /* check for disallowed stuff */ - - /* aggregates not allowed (but subselects are okay) */ - if (pstate->p_hasAggs) - ereport(ERROR, - (errcode(ERRCODE_GROUPING_ERROR), - errmsg("cannot use aggregate function in RETURNING"), - parser_errposition(pstate, - locate_agg_of_level((Node *) rlist, 0)))); - if (pstate->p_hasWindowFuncs) - ereport(ERROR, - (errcode(ERRCODE_WINDOWING_ERROR), - errmsg("cannot use window function in RETURNING"), - parser_errposition(pstate, - locate_windowfunc((Node *) rlist)))); + rlist = transformTargetList(pstate, returningList, EXPR_KIND_RETURNING); /* mark column origins */ markTargetListOrigins(pstate, rlist); /* restore state */ pstate->p_next_resno = save_next_resno; - pstate->p_hasAggs = save_hasAggs; - pstate->p_hasWindowFuncs = save_hasWindowFuncs; return rlist; } |