mirror of
https://github.com/postgres/postgres.git
synced 2025-12-22 17:42:17 +03:00
@@ -14,7 +14,7 @@ override CPPFLAGS := -I. -I$(srcdir) $(CPPFLAGS)
|
||||
|
||||
OBJS= analyze.o gram.o scan.o parser.o \
|
||||
parse_agg.o parse_clause.o parse_coerce.o parse_collate.o parse_cte.o \
|
||||
parse_enr.o parse_expr.o parse_func.o parse_merge.o parse_node.o parse_oper.o \
|
||||
parse_enr.o parse_expr.o parse_func.o parse_node.o parse_oper.o \
|
||||
parse_param.o parse_relation.o parse_target.o parse_type.o \
|
||||
parse_utilcmd.o scansup.o
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
#include "parser/parse_cte.h"
|
||||
#include "parser/parse_expr.h"
|
||||
#include "parser/parse_func.h"
|
||||
#include "parser/parse_merge.h"
|
||||
#include "parser/parse_oper.h"
|
||||
#include "parser/parse_param.h"
|
||||
#include "parser/parse_relation.h"
|
||||
@@ -54,6 +53,9 @@ post_parse_analyze_hook_type post_parse_analyze_hook = NULL;
|
||||
static Query *transformOptionalSelectInto(ParseState *pstate, Node *parseTree);
|
||||
static Query *transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt);
|
||||
static Query *transformInsertStmt(ParseState *pstate, InsertStmt *stmt);
|
||||
static List *transformInsertRow(ParseState *pstate, List *exprlist,
|
||||
List *stmtcols, List *icolumns, List *attrnos,
|
||||
bool strip_indirection);
|
||||
static OnConflictExpr *transformOnConflictClause(ParseState *pstate,
|
||||
OnConflictClause *onConflictClause);
|
||||
static int count_rowexpr_columns(ParseState *pstate, Node *expr);
|
||||
@@ -66,6 +68,8 @@ static void determineRecursiveColTypes(ParseState *pstate,
|
||||
Node *larg, List *nrtargetlist);
|
||||
static Query *transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt);
|
||||
static List *transformReturningList(ParseState *pstate, List *returningList);
|
||||
static List *transformUpdateTargetList(ParseState *pstate,
|
||||
List *targetList);
|
||||
static Query *transformDeclareCursorStmt(ParseState *pstate,
|
||||
DeclareCursorStmt *stmt);
|
||||
static Query *transformExplainStmt(ParseState *pstate,
|
||||
@@ -263,7 +267,6 @@ transformStmt(ParseState *pstate, Node *parseTree)
|
||||
case T_InsertStmt:
|
||||
case T_UpdateStmt:
|
||||
case T_DeleteStmt:
|
||||
case T_MergeStmt:
|
||||
(void) test_raw_expression_coverage(parseTree, NULL);
|
||||
break;
|
||||
default:
|
||||
@@ -288,10 +291,6 @@ transformStmt(ParseState *pstate, Node *parseTree)
|
||||
result = transformUpdateStmt(pstate, (UpdateStmt *) parseTree);
|
||||
break;
|
||||
|
||||
case T_MergeStmt:
|
||||
result = transformMergeStmt(pstate, (MergeStmt *) parseTree);
|
||||
break;
|
||||
|
||||
case T_SelectStmt:
|
||||
{
|
||||
SelectStmt *n = (SelectStmt *) parseTree;
|
||||
@@ -367,7 +366,6 @@ analyze_requires_snapshot(RawStmt *parseTree)
|
||||
case T_InsertStmt:
|
||||
case T_DeleteStmt:
|
||||
case T_UpdateStmt:
|
||||
case T_MergeStmt:
|
||||
case T_SelectStmt:
|
||||
result = true;
|
||||
break;
|
||||
@@ -898,7 +896,7 @@ transformInsertStmt(ParseState *pstate, InsertStmt *stmt)
|
||||
* attrnos: integer column numbers (must be same length as icolumns)
|
||||
* strip_indirection: if true, remove any field/array assignment nodes
|
||||
*/
|
||||
List *
|
||||
static List *
|
||||
transformInsertRow(ParseState *pstate, List *exprlist,
|
||||
List *stmtcols, List *icolumns, List *attrnos,
|
||||
bool strip_indirection)
|
||||
@@ -2262,9 +2260,9 @@ transformUpdateStmt(ParseState *pstate, UpdateStmt *stmt)
|
||||
|
||||
/*
|
||||
* transformUpdateTargetList -
|
||||
* handle SET clause in UPDATE/MERGE/INSERT ... ON CONFLICT UPDATE
|
||||
* handle SET clause in UPDATE/INSERT ... ON CONFLICT UPDATE
|
||||
*/
|
||||
List *
|
||||
static List *
|
||||
transformUpdateTargetList(ParseState *pstate, List *origTlist)
|
||||
{
|
||||
List *tlist = NIL;
|
||||
|
||||
@@ -282,7 +282,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
||||
CreateMatViewStmt RefreshMatViewStmt CreateAmStmt
|
||||
CreatePublicationStmt AlterPublicationStmt
|
||||
CreateSubscriptionStmt AlterSubscriptionStmt DropSubscriptionStmt
|
||||
MergeStmt
|
||||
|
||||
%type <node> select_no_parens select_with_parens select_clause
|
||||
simple_select values_clause
|
||||
@@ -585,10 +584,6 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
||||
%type <list> hash_partbound partbound_datum_list range_datum_list
|
||||
%type <defelt> hash_partbound_elem
|
||||
|
||||
%type <node> merge_when_clause opt_and_condition
|
||||
%type <list> merge_when_list
|
||||
%type <node> merge_update merge_delete merge_insert
|
||||
|
||||
/*
|
||||
* Non-keyword token types. These are hard-wired into the "flex" lexer.
|
||||
* They must be listed first so that their numeric codes do not depend on
|
||||
@@ -656,8 +651,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
|
||||
LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
|
||||
LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOCKED LOGGED
|
||||
|
||||
MAPPING MATCH MATCHED MATERIALIZED MAXVALUE MERGE METHOD
|
||||
MINUTE_P MINVALUE MODE MONTH_P MOVE
|
||||
MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
|
||||
|
||||
NAME_P NAMES NATIONAL NATURAL NCHAR NEW NEXT NO NONE
|
||||
NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
|
||||
@@ -926,7 +920,6 @@ stmt :
|
||||
| RefreshMatViewStmt
|
||||
| LoadStmt
|
||||
| LockStmt
|
||||
| MergeStmt
|
||||
| NotifyStmt
|
||||
| PrepareStmt
|
||||
| ReassignOwnedStmt
|
||||
@@ -10667,7 +10660,6 @@ ExplainableStmt:
|
||||
| InsertStmt
|
||||
| UpdateStmt
|
||||
| DeleteStmt
|
||||
| MergeStmt
|
||||
| DeclareCursorStmt
|
||||
| CreateAsStmt
|
||||
| CreateMatViewStmt
|
||||
@@ -10730,7 +10722,6 @@ PreparableStmt:
|
||||
| InsertStmt
|
||||
| UpdateStmt
|
||||
| DeleteStmt /* by default all are $$=$1 */
|
||||
| MergeStmt
|
||||
;
|
||||
|
||||
/*****************************************************************************
|
||||
@@ -11097,151 +11088,6 @@ set_target_list:
|
||||
;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERY:
|
||||
* MERGE STATEMENTS
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
MergeStmt:
|
||||
MERGE INTO relation_expr_opt_alias
|
||||
USING table_ref
|
||||
ON a_expr
|
||||
merge_when_list
|
||||
{
|
||||
MergeStmt *m = makeNode(MergeStmt);
|
||||
|
||||
m->relation = $3;
|
||||
m->source_relation = $5;
|
||||
m->join_condition = $7;
|
||||
m->mergeActionList = $8;
|
||||
|
||||
$$ = (Node *)m;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
merge_when_list:
|
||||
merge_when_clause { $$ = list_make1($1); }
|
||||
| merge_when_list merge_when_clause { $$ = lappend($1,$2); }
|
||||
;
|
||||
|
||||
merge_when_clause:
|
||||
WHEN MATCHED opt_and_condition THEN merge_update
|
||||
{
|
||||
MergeAction *m = makeNode(MergeAction);
|
||||
|
||||
m->matched = true;
|
||||
m->commandType = CMD_UPDATE;
|
||||
m->condition = $3;
|
||||
m->stmt = $5;
|
||||
|
||||
$$ = (Node *)m;
|
||||
}
|
||||
| WHEN MATCHED opt_and_condition THEN merge_delete
|
||||
{
|
||||
MergeAction *m = makeNode(MergeAction);
|
||||
|
||||
m->matched = true;
|
||||
m->commandType = CMD_DELETE;
|
||||
m->condition = $3;
|
||||
m->stmt = $5;
|
||||
|
||||
$$ = (Node *)m;
|
||||
}
|
||||
| WHEN NOT MATCHED opt_and_condition THEN merge_insert
|
||||
{
|
||||
MergeAction *m = makeNode(MergeAction);
|
||||
|
||||
m->matched = false;
|
||||
m->commandType = CMD_INSERT;
|
||||
m->condition = $4;
|
||||
m->stmt = $6;
|
||||
|
||||
$$ = (Node *)m;
|
||||
}
|
||||
| WHEN NOT MATCHED opt_and_condition THEN DO NOTHING
|
||||
{
|
||||
MergeAction *m = makeNode(MergeAction);
|
||||
|
||||
m->matched = false;
|
||||
m->commandType = CMD_NOTHING;
|
||||
m->condition = $4;
|
||||
m->stmt = NULL;
|
||||
|
||||
$$ = (Node *)m;
|
||||
}
|
||||
;
|
||||
|
||||
opt_and_condition:
|
||||
AND a_expr { $$ = $2; }
|
||||
| { $$ = NULL; }
|
||||
;
|
||||
|
||||
merge_delete:
|
||||
DELETE_P
|
||||
{
|
||||
DeleteStmt *n = makeNode(DeleteStmt);
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
merge_update:
|
||||
UPDATE SET set_clause_list
|
||||
{
|
||||
UpdateStmt *n = makeNode(UpdateStmt);
|
||||
n->targetList = $3;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
merge_insert:
|
||||
INSERT values_clause
|
||||
{
|
||||
InsertStmt *n = makeNode(InsertStmt);
|
||||
n->cols = NIL;
|
||||
n->selectStmt = $2;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| INSERT OVERRIDING override_kind VALUE_P values_clause
|
||||
{
|
||||
InsertStmt *n = makeNode(InsertStmt);
|
||||
n->cols = NIL;
|
||||
n->override = $3;
|
||||
n->selectStmt = $5;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| INSERT '(' insert_column_list ')' values_clause
|
||||
{
|
||||
InsertStmt *n = makeNode(InsertStmt);
|
||||
n->cols = $3;
|
||||
n->selectStmt = $5;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| INSERT '(' insert_column_list ')' OVERRIDING override_kind VALUE_P values_clause
|
||||
{
|
||||
InsertStmt *n = makeNode(InsertStmt);
|
||||
n->cols = $3;
|
||||
n->override = $6;
|
||||
n->selectStmt = $8;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
| INSERT DEFAULT VALUES
|
||||
{
|
||||
InsertStmt *n = makeNode(InsertStmt);
|
||||
n->cols = NIL;
|
||||
n->selectStmt = NULL;
|
||||
|
||||
$$ = (Node *)n;
|
||||
}
|
||||
;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* QUERY:
|
||||
@@ -15242,10 +15088,8 @@ unreserved_keyword:
|
||||
| LOGGED
|
||||
| MAPPING
|
||||
| MATCH
|
||||
| MATCHED
|
||||
| MATERIALIZED
|
||||
| MAXVALUE
|
||||
| MERGE
|
||||
| METHOD
|
||||
| MINUTE_P
|
||||
| MINVALUE
|
||||
|
||||
@@ -455,13 +455,6 @@ check_agglevels_and_constraints(ParseState *pstate, Node *expr)
|
||||
case EXPR_KIND_VALUES_SINGLE:
|
||||
errkind = true;
|
||||
break;
|
||||
case EXPR_KIND_MERGE_WHEN_AND:
|
||||
if (isAgg)
|
||||
err = _("aggregate functions are not allowed in WHEN AND conditions");
|
||||
else
|
||||
err = _("grouping operations are not allowed in WHEN AND conditions");
|
||||
|
||||
break;
|
||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||
case EXPR_KIND_DOMAIN_CHECK:
|
||||
if (isAgg)
|
||||
@@ -880,9 +873,6 @@ transformWindowFuncCall(ParseState *pstate, WindowFunc *wfunc,
|
||||
case EXPR_KIND_VALUES_SINGLE:
|
||||
errkind = true;
|
||||
break;
|
||||
case EXPR_KIND_MERGE_WHEN_AND:
|
||||
err = _("window functions are not allowed in WHEN AND conditions");
|
||||
break;
|
||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||
case EXPR_KIND_DOMAIN_CHECK:
|
||||
err = _("window functions are not allowed in check constraints");
|
||||
|
||||
@@ -76,6 +76,9 @@ static RangeTblEntry *transformRangeTableFunc(ParseState *pstate,
|
||||
RangeTableFunc *t);
|
||||
static TableSampleClause *transformRangeTableSample(ParseState *pstate,
|
||||
RangeTableSample *rts);
|
||||
static Node *transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
RangeTblEntry **top_rte, int *top_rti,
|
||||
List **namespace);
|
||||
static Node *buildMergedJoinVar(ParseState *pstate, JoinType jointype,
|
||||
Var *l_colvar, Var *r_colvar);
|
||||
static ParseNamespaceItem *makeNamespaceItem(RangeTblEntry *rte,
|
||||
@@ -136,7 +139,6 @@ transformFromClause(ParseState *pstate, List *frmList)
|
||||
n = transformFromClauseItem(pstate, n,
|
||||
&rte,
|
||||
&rtindex,
|
||||
NULL, NULL,
|
||||
&namespace);
|
||||
|
||||
checkNameSpaceConflicts(pstate, pstate->p_namespace, namespace);
|
||||
@@ -1094,20 +1096,13 @@ getRTEForSpecialRelationTypes(ParseState *pstate, RangeVar *rv)
|
||||
*
|
||||
* *top_rti: receives the rangetable index of top_rte. (Ditto.)
|
||||
*
|
||||
* *right_rte: receives the RTE corresponding to the right side of the
|
||||
* jointree. Only MERGE really needs to know about this and only MERGE passes a
|
||||
* non-NULL pointer.
|
||||
*
|
||||
* *right_rti: receives the rangetable index of the right_rte.
|
||||
*
|
||||
* *namespace: receives a List of ParseNamespaceItems for the RTEs exposed
|
||||
* as table/column names by this item. (The lateral_only flags in these items
|
||||
* are indeterminate and should be explicitly set by the caller before use.)
|
||||
*/
|
||||
Node *
|
||||
static Node *
|
||||
transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
RangeTblEntry **top_rte, int *top_rti,
|
||||
RangeTblEntry **right_rte, int *right_rti,
|
||||
List **namespace)
|
||||
{
|
||||
if (IsA(n, RangeVar))
|
||||
@@ -1199,7 +1194,7 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
|
||||
/* Recursively transform the contained relation */
|
||||
rel = transformFromClauseItem(pstate, rts->relation,
|
||||
top_rte, top_rti, NULL, NULL, namespace);
|
||||
top_rte, top_rti, namespace);
|
||||
/* Currently, grammar could only return a RangeVar as contained rel */
|
||||
rtr = castNode(RangeTblRef, rel);
|
||||
rte = rt_fetch(rtr->rtindex, pstate->p_rtable);
|
||||
@@ -1227,7 +1222,6 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
List *l_namespace,
|
||||
*r_namespace,
|
||||
*my_namespace,
|
||||
*save_namespace,
|
||||
*l_colnames,
|
||||
*r_colnames,
|
||||
*res_colnames,
|
||||
@@ -1246,7 +1240,6 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
j->larg = transformFromClauseItem(pstate, j->larg,
|
||||
&l_rte,
|
||||
&l_rtindex,
|
||||
NULL, NULL,
|
||||
&l_namespace);
|
||||
|
||||
/*
|
||||
@@ -1270,34 +1263,12 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
sv_namespace_length = list_length(pstate->p_namespace);
|
||||
pstate->p_namespace = list_concat(pstate->p_namespace, l_namespace);
|
||||
|
||||
/*
|
||||
* If we are running MERGE, don't make the other RTEs visible while
|
||||
* parsing the source relation. It mustn't see them.
|
||||
*
|
||||
* Currently, only MERGE passes non-NULL value for right_rte, so we
|
||||
* can safely deduce if we're running MERGE or not by just looking at
|
||||
* the right_rte. If that ever changes, we should look at other means
|
||||
* to find that.
|
||||
*/
|
||||
if (right_rte)
|
||||
{
|
||||
save_namespace = pstate->p_namespace;
|
||||
pstate->p_namespace = NIL;
|
||||
}
|
||||
|
||||
/* And now we can process the RHS */
|
||||
j->rarg = transformFromClauseItem(pstate, j->rarg,
|
||||
&r_rte,
|
||||
&r_rtindex,
|
||||
NULL, NULL,
|
||||
&r_namespace);
|
||||
|
||||
/*
|
||||
* And now restore the namespace again so that join-quals can see it.
|
||||
*/
|
||||
if (right_rte)
|
||||
pstate->p_namespace = save_namespace;
|
||||
|
||||
/* Remove the left-side RTEs from the namespace list again */
|
||||
pstate->p_namespace = list_truncate(pstate->p_namespace,
|
||||
sv_namespace_length);
|
||||
@@ -1324,12 +1295,6 @@ transformFromClauseItem(ParseState *pstate, Node *n,
|
||||
expandRTE(r_rte, r_rtindex, 0, -1, false,
|
||||
&r_colnames, &r_colvars);
|
||||
|
||||
if (right_rte)
|
||||
*right_rte = r_rte;
|
||||
|
||||
if (right_rti)
|
||||
*right_rti = r_rtindex;
|
||||
|
||||
/*
|
||||
* Natural join does not explicitly specify columns; must generate
|
||||
* columns to join. Need to run through the list of columns from each
|
||||
|
||||
@@ -485,7 +485,6 @@ assign_collations_walker(Node *node, assign_collations_context *context)
|
||||
case T_FromExpr:
|
||||
case T_OnConflictExpr:
|
||||
case T_SortGroupClause:
|
||||
case T_MergeAction:
|
||||
(void) expression_tree_walker(node,
|
||||
assign_collations_walker,
|
||||
(void *) &loccontext);
|
||||
|
||||
@@ -1818,7 +1818,6 @@ transformSubLink(ParseState *pstate, SubLink *sublink)
|
||||
case EXPR_KIND_RETURNING:
|
||||
case EXPR_KIND_VALUES:
|
||||
case EXPR_KIND_VALUES_SINGLE:
|
||||
case EXPR_KIND_MERGE_WHEN_AND:
|
||||
/* okay */
|
||||
break;
|
||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||
@@ -3476,8 +3475,6 @@ ParseExprKindName(ParseExprKind exprKind)
|
||||
return "PARTITION BY";
|
||||
case EXPR_KIND_CALL_ARGUMENT:
|
||||
return "CALL";
|
||||
case EXPR_KIND_MERGE_WHEN_AND:
|
||||
return "MERGE WHEN AND";
|
||||
|
||||
/*
|
||||
* There is intentionally no default: case here, so that the
|
||||
|
||||
@@ -2277,9 +2277,6 @@ check_srf_call_placement(ParseState *pstate, Node *last_srf, int location)
|
||||
/* okay, since we process this like a SELECT tlist */
|
||||
pstate->p_hasTargetSRFs = true;
|
||||
break;
|
||||
case EXPR_KIND_MERGE_WHEN_AND:
|
||||
err = _("set-returning functions are not allowed in WHEN AND conditions");
|
||||
break;
|
||||
case EXPR_KIND_CHECK_CONSTRAINT:
|
||||
case EXPR_KIND_DOMAIN_CHECK:
|
||||
err = _("set-returning functions are not allowed in check constraints");
|
||||
|
||||
@@ -728,16 +728,6 @@ scanRTEForColumn(ParseState *pstate, RangeTblEntry *rte, const char *colname,
|
||||
colname),
|
||||
parser_errposition(pstate, location)));
|
||||
|
||||
/* In MERGE WHEN AND condition, no system column is allowed except tableOid or OID */
|
||||
if (pstate->p_expr_kind == EXPR_KIND_MERGE_WHEN_AND &&
|
||||
attnum < InvalidAttrNumber &&
|
||||
!(attnum == TableOidAttributeNumber || attnum == ObjectIdAttributeNumber))
|
||||
ereport(ERROR,
|
||||
(errcode(ERRCODE_INVALID_COLUMN_REFERENCE),
|
||||
errmsg("system column \"%s\" reference in WHEN AND condition is invalid",
|
||||
colname),
|
||||
parser_errposition(pstate, location)));
|
||||
|
||||
if (attnum != InvalidAttrNumber)
|
||||
{
|
||||
/* now check to see if column actually is defined */
|
||||
|
||||
Reference in New Issue
Block a user