1
0
mirror of https://github.com/postgres/postgres.git synced 2025-11-10 17:42:29 +03:00

Add a "USING" clause to DELETE, which is equivalent to the FROM clause

in UPDATE. We also now issue a NOTICE if a query has _any_ implicit
range table entries -- in the past, we would only warn about implicit
RTEs in SELECTs with at least one explicit RTE.

As a result of the warning change, 25 of the regression tests had to
be updated. I also took the opportunity to remove some bogus whitespace
differences between some of the float4 and float8 variants. I believe
I have correctly updated all the platform-specific variants, but let
me know if that's not the case.

Original patch for DELETE ... USING from Euler Taveira de Oliveira,
reworked by Neil Conway.
This commit is contained in:
Neil Conway
2005-04-07 01:51:41 +00:00
parent be2f825d51
commit f5ab0a14ea
68 changed files with 393 additions and 234 deletions

View File

@@ -15,7 +15,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.300 2005/04/06 16:34:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.301 2005/04/07 01:51:38 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -1563,6 +1563,7 @@ _copyDeleteStmt(DeleteStmt *from)
COPY_NODE_FIELD(relation);
COPY_NODE_FIELD(whereClause);
COPY_NODE_FIELD(usingClause);
return newnode;
}

View File

@@ -18,7 +18,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.239 2005/04/06 16:34:05 tgl Exp $
* $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.240 2005/04/07 01:51:38 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -675,6 +675,7 @@ _equalDeleteStmt(DeleteStmt *a, DeleteStmt *b)
{
COMPARE_NODE_FIELD(relation);
COMPARE_NODE_FIELD(whereClause);
COMPARE_NODE_FIELD(usingClause);
return true;
}

View File

@@ -6,7 +6,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.317 2005/04/06 16:34:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.318 2005/04/07 01:51:38 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -479,6 +479,14 @@ transformDeleteStmt(ParseState *pstate, DeleteStmt *stmt)
qry->distinctClause = NIL;
/*
* The USING clause is non-standard SQL syntax, and is equivalent
* in functionality to the FROM list that can be specified for
* UPDATE. The USING keyword is used rather than FROM because FROM
* is already a keyword in the DELETE syntax.
*/
transformFromClause(pstate, stmt->usingClause);
/* fix where clause */
qual = transformWhereClause(pstate, stmt->whereClause, "WHERE");

View File

@@ -11,7 +11,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.486 2005/03/31 22:46:11 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.487 2005/04/07 01:51:38 neilc Exp $
*
* HISTORY
* AUTHOR DATE MAJOR EVENT
@@ -229,7 +229,7 @@ static void doNegateFloat(Value *v);
transaction_mode_list_or_empty
TableFuncElementList
prep_type_clause prep_type_list
execute_param_clause
execute_param_clause using_clause
%type <range> into_clause OptTempTableName
@@ -4734,15 +4734,21 @@ insert_column_item:
*
*****************************************************************************/
DeleteStmt: DELETE_P FROM relation_expr where_clause
DeleteStmt: DELETE_P FROM relation_expr using_clause where_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
n->relation = $3;
n->whereClause = $4;
n->usingClause = $4;
n->whereClause = $5;
$$ = (Node *)n;
}
;
using_clause:
USING from_list { $$ = $2; }
| /*EMPTY*/ { $$ = NIL; }
;
LockStmt: LOCK_P opt_table qualified_name_list opt_lock opt_nowait
{
LockStmt *n = makeNode(LockStmt);

View File

@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.104 2005/04/06 16:34:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/parser/parse_relation.c,v 1.105 2005/04/07 01:51:39 neilc Exp $
*
*-------------------------------------------------------------------------
*/
@@ -596,6 +596,7 @@ colNameToVar(ParseState *pstate, char *colname, bool localonly)
RangeTblEntry *rte = rt_fetch(varno, pstate->p_rtable);
/* joins are always inFromCl, so no need to check */
Assert(rte->inFromCl);
/* use orig_pstate here to get the right sublevels_up */
newresult = scanRTEForColumn(orig_pstate, rte, colname);
@@ -1966,17 +1967,12 @@ attnumTypeId(Relation rd, int attid)
/*
* Generate a warning or error about an implicit RTE, if appropriate.
*
* If ADD_MISSING_FROM is not enabled, raise an error.
*
* Our current theory on warnings is that we should allow "SELECT foo.*"
* but warn about a mixture of explicit and implicit RTEs.
* If ADD_MISSING_FROM is not enabled, raise an error. Otherwise, emit
* a warning.
*/
static void
warnAutoRange(ParseState *pstate, RangeVar *relation)
{
bool foundInFromCl = false;
ListCell *temp;
if (!add_missing_from)
{
if (pstate->parentParseState != NULL)
@@ -1990,19 +1986,9 @@ warnAutoRange(ParseState *pstate, RangeVar *relation)
errmsg("missing FROM-clause entry for table \"%s\"",
relation->relname)));
}
foreach(temp, pstate->p_rtable)
{
RangeTblEntry *rte = lfirst(temp);
if (rte->inFromCl)
{
foundInFromCl = true;
break;
}
}
if (foundInFromCl)
else
{
/* just issue a warning */
if (pstate->parentParseState != NULL)
ereport(NOTICE,
(errcode(ERRCODE_UNDEFINED_TABLE),

View File

@@ -3,7 +3,7 @@
* back to source text
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.190 2005/04/06 16:34:06 tgl Exp $
* $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.191 2005/04/07 01:51:39 neilc Exp $
*
* This software is copyrighted by Jan Wieck - Hamburg.
*
@@ -199,7 +199,8 @@ static void get_func_expr(FuncExpr *expr, deparse_context *context,
static void get_agg_expr(Aggref *aggref, deparse_context *context);
static void get_const_expr(Const *constval, deparse_context *context);
static void get_sublink_expr(SubLink *sublink, deparse_context *context);
static void get_from_clause(Query *query, deparse_context *context);
static void get_from_clause(Query *query, const char *prefix,
deparse_context *context);
static void get_from_clause_item(Node *jtnode, Query *query,
deparse_context *context);
static void get_from_clause_alias(Alias *alias, int varno,
@@ -2020,7 +2021,7 @@ get_basic_select_query(Query *query, deparse_context *context,
}
/* Add the FROM clause if needed */
get_from_clause(query, context);
get_from_clause(query, " FROM ", context);
/* Add the WHERE clause if given */
if (query->jointree->quals != NULL)
@@ -2325,7 +2326,7 @@ get_update_query_def(Query *query, deparse_context *context)
}
/* Add the FROM clause if needed */
get_from_clause(query, context);
get_from_clause(query, " FROM ", context);
/* Finally add a WHERE clause if given */
if (query->jointree->quals != NULL)
@@ -2361,6 +2362,9 @@ get_delete_query_def(Query *query, deparse_context *context)
only_marker(rte),
generate_relation_name(rte->relid));
/* Add the USING clause if given */
get_from_clause(query, " USING ", context);
/* Add a WHERE clause if given */
if (query->jointree->quals != NULL)
{
@@ -3805,10 +3809,14 @@ get_sublink_expr(SubLink *sublink, deparse_context *context)
/* ----------
* get_from_clause - Parse back a FROM clause
*
* "prefix" is the keyword that denotes the start of the list of FROM
* elements. It is FROM when used to parse back SELECT and UPDATE, but
* is USING when parsing back DELETE.
* ----------
*/
static void
get_from_clause(Query *query, deparse_context *context)
get_from_clause(Query *query, const char *prefix, deparse_context *context)
{
StringInfo buf = context->buf;
bool first = true;
@@ -3840,7 +3848,7 @@ get_from_clause(Query *query, deparse_context *context)
if (first)
{
appendContextKeyword(context, " FROM ",
appendContextKeyword(context, prefix,
-PRETTYINDENT_STD, PRETTYINDENT_STD, 2);
first = false;
}