with_on_dml3.patch
text/x-patch
Filename: with_on_dml3.patch
Type: text/x-patch
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: context
| File | + | − |
|---|---|---|
| src/backend/nodes/copyfuncs.c | 2 | 0 |
| src/backend/nodes/equalfuncs.c | 2 | 0 |
| src/backend/parser/analyze.c | 16 | 1 |
| src/backend/parser/gram.y | 20 | 12 |
| src/backend/utils/adt/ruleutils.c | 6 | 0 |
| src/include/nodes/parsenodes.h | 2 | 0 |
| src/test/regress/expected/with.out | 77 | 2 |
| src/test/regress/sql/with.sql | 27 | 3 |
Index: src/backend/nodes/copyfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v
retrieving revision 1.461
diff -c -r1.461 copyfuncs.c
*** src/backend/nodes/copyfuncs.c 12 Feb 2010 17:33:20 -0000 1.461
--- src/backend/nodes/copyfuncs.c 13 Feb 2010 00:49:41 -0000
***************
*** 2279,2284 ****
--- 2279,2285 ----
COPY_NODE_FIELD(usingClause);
COPY_NODE_FIELD(whereClause);
COPY_NODE_FIELD(returningList);
+ COPY_NODE_FIELD(withClause);
return newnode;
}
***************
*** 2293,2298 ****
--- 2294,2300 ----
COPY_NODE_FIELD(whereClause);
COPY_NODE_FIELD(fromClause);
COPY_NODE_FIELD(returningList);
+ COPY_NODE_FIELD(withClause);
return newnode;
}
Index: src/backend/nodes/equalfuncs.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v
retrieving revision 1.382
diff -c -r1.382 equalfuncs.c
*** src/backend/nodes/equalfuncs.c 12 Feb 2010 17:33:20 -0000 1.382
--- src/backend/nodes/equalfuncs.c 13 Feb 2010 00:49:41 -0000
***************
*** 899,904 ****
--- 899,905 ----
COMPARE_NODE_FIELD(usingClause);
COMPARE_NODE_FIELD(whereClause);
COMPARE_NODE_FIELD(returningList);
+ COMPARE_NODE_FIELD(withClause);
return true;
}
***************
*** 911,916 ****
--- 912,918 ----
COMPARE_NODE_FIELD(whereClause);
COMPARE_NODE_FIELD(fromClause);
COMPARE_NODE_FIELD(returningList);
+ COMPARE_NODE_FIELD(withClause);
return true;
}
Index: src/backend/parser/analyze.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/analyze.c,v
retrieving revision 1.401
diff -c -r1.401 analyze.c
*** src/backend/parser/analyze.c 12 Feb 2010 22:48:56 -0000 1.401
--- src/backend/parser/analyze.c 13 Feb 2010 00:49:41 -0000
***************
*** 282,287 ****
--- 282,294 ----
qry->commandType = CMD_DELETE;
+ /* process the WITH clause independently of all else */
+ if (stmt->withClause)
+ {
+ qry->hasRecursive = stmt->withClause->recursive;
+ qry->cteList = transformWithClause(pstate, stmt->withClause);
+ }
+
/* set up range table with just the result rel */
qry->resultRelation = setTargetTable(pstate, stmt->relation,
interpretInhOption(stmt->relation->inhOpt),
***************
*** 380,386 ****
* Must get write lock on INSERT target table before scanning SELECT, else
* we will grab the wrong kind of initial lock if the target table is also
* mentioned in the SELECT part. Note that the target table is not added
! * to the joinlist or namespace.
*/
qry->resultRelation = setTargetTable(pstate, stmt->relation,
false, false, ACL_INSERT);
--- 387,394 ----
* Must get write lock on INSERT target table before scanning SELECT, else
* we will grab the wrong kind of initial lock if the target table is also
* mentioned in the SELECT part. Note that the target table is not added
! * to the joinlist or namespace (and hence it won't affect processing
! * of the contained statement).
*/
qry->resultRelation = setTargetTable(pstate, stmt->relation,
false, false, ACL_INSERT);
***************
*** 1730,1735 ****
--- 1738,1750 ----
qry->commandType = CMD_UPDATE;
pstate->p_is_update = true;
+ /* process the WITH clause independently of all else */
+ if (stmt->withClause)
+ {
+ qry->hasRecursive = stmt->withClause->recursive;
+ qry->cteList = transformWithClause(pstate, stmt->withClause);
+ }
+
qry->resultRelation = setTargetTable(pstate, stmt->relation,
interpretInhOption(stmt->relation->inhOpt),
true,
Index: src/backend/parser/gram.y
===================================================================
RCS file: /cvsroot/pgsql/src/backend/parser/gram.y,v
retrieving revision 2.708
diff -c -r2.708 gram.y
*** src/backend/parser/gram.y 12 Feb 2010 17:33:20 -0000 2.708
--- src/backend/parser/gram.y 13 Feb 2010 00:49:41 -0000
***************
*** 429,435 ****
%type <boolean> xml_whitespace_option
%type <node> common_table_expr
! %type <with> with_clause
%type <list> cte_list
%type <list> window_clause window_definition_list opt_partition_clause
--- 429,435 ----
%type <boolean> xml_whitespace_option
%type <node> common_table_expr
! %type <with> with_clause opt_with_clause
%type <list> cte_list
%type <list> window_clause window_definition_list opt_partition_clause
***************
*** 7141,7154 ****
*
*****************************************************************************/
! DeleteStmt: DELETE_P FROM relation_expr_opt_alias
using_clause where_or_current_clause returning_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
! n->relation = $3;
! n->usingClause = $4;
! n->whereClause = $5;
! n->returningList = $6;
$$ = (Node *)n;
}
;
--- 7141,7155 ----
*
*****************************************************************************/
! DeleteStmt: opt_with_clause DELETE_P FROM relation_expr_opt_alias
using_clause where_or_current_clause returning_clause
{
DeleteStmt *n = makeNode(DeleteStmt);
! n->relation = $4;
! n->usingClause = $5;
! n->whereClause = $6;
! n->returningList = $7;
! n->withClause = $1;
$$ = (Node *)n;
}
;
***************
*** 7203,7220 ****
*
*****************************************************************************/
! UpdateStmt: UPDATE relation_expr_opt_alias
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
! n->relation = $2;
! n->targetList = $4;
! n->fromClause = $5;
! n->whereClause = $6;
! n->returningList = $7;
$$ = (Node *)n;
}
;
--- 7204,7222 ----
*
*****************************************************************************/
! UpdateStmt: opt_with_clause UPDATE relation_expr_opt_alias
SET set_clause_list
from_clause
where_or_current_clause
returning_clause
{
UpdateStmt *n = makeNode(UpdateStmt);
! n->relation = $3;
! n->targetList = $5;
! n->fromClause = $6;
! n->whereClause = $7;
! n->returningList = $8;
! n->withClause = $1;
$$ = (Node *)n;
}
;
***************
*** 7556,7561 ****
--- 7558,7569 ----
}
;
+ opt_with_clause:
+ with_clause { $$ = $1; }
+ | /*EMPTY*/ { $$ = NULL; }
+ ;
+
+
into_clause:
INTO OptTempTableName
{
Index: src/backend/utils/adt/ruleutils.c
===================================================================
RCS file: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v
retrieving revision 1.321
diff -c -r1.321 ruleutils.c
*** src/backend/utils/adt/ruleutils.c 12 Feb 2010 17:33:20 -0000 1.321
--- src/backend/utils/adt/ruleutils.c 13 Feb 2010 00:49:42 -0000
***************
*** 3351,3356 ****
--- 3351,3359 ----
RangeTblEntry *rte;
ListCell *l;
+ /* Insert the WITH clause if given */
+ get_with_clause(query, context);
+
/*
* Start the query with UPDATE relname SET
*/
***************
*** 3432,3437 ****
--- 3435,3443 ----
StringInfo buf = context->buf;
RangeTblEntry *rte;
+ /* Insert the WITH clause if given */
+ get_with_clause(query, context);
+
/*
* Start the query with DELETE FROM relname
*/
Index: src/include/nodes/parsenodes.h
===================================================================
RCS file: /cvsroot/pgsql/src/include/nodes/parsenodes.h,v
retrieving revision 1.429
diff -c -r1.429 parsenodes.h
*** src/include/nodes/parsenodes.h 12 Feb 2010 17:33:20 -0000 1.429
--- src/include/nodes/parsenodes.h 13 Feb 2010 00:49:42 -0000
***************
*** 906,911 ****
--- 906,912 ----
List *usingClause; /* optional using clause for more tables */
Node *whereClause; /* qualifications */
List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
} DeleteStmt;
/* ----------------------
***************
*** 920,925 ****
--- 921,927 ----
Node *whereClause; /* qualifications */
List *fromClause; /* optional from clause for more tables */
List *returningList; /* list of expressions to return */
+ WithClause *withClause; /* WITH clause */
} UpdateStmt;
/* ----------------------
Index: src/test/regress/expected/with.out
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/expected/with.out,v
retrieving revision 1.13
diff -c -r1.13 with.out
*** src/test/regress/expected/with.out 22 Nov 2009 05:20:41 -0000 1.13
--- src/test/regress/expected/with.out 13 Feb 2010 00:49:42 -0000
***************
*** 738,743 ****
--- 738,820 ----
(54 rows)
--
+ -- WITH on top of a DML statement
+ --
+ CREATE TEMPORARY TABLE y (a INTEGER);
+ INSERT INTO y SELECT generate_series(1, 10);
+ INSERT INTO y
+ WITH t AS (
+ SELECT a FROM y
+ )
+ SELECT a+20 FROM t RETURNING *;
+ a
+ ----
+ 21
+ 22
+ 23
+ 24
+ 25
+ 26
+ 27
+ 28
+ 29
+ 30
+ (10 rows)
+
+ WITH t AS (
+ SELECT a FROM y
+ )
+ UPDATE y SET a = y.a-10 FROM t WHERE y.a > 20 AND t.a = y.a RETURNING y.a;
+ a
+ ----
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ (10 rows)
+
+ WITH RECURSIVE t(a) AS (
+ SELECT 11
+ UNION ALL
+ SELECT a+1 FROM t WHERE a < 50
+ )
+ DELETE FROM y USING t WHERE t.a = y.a RETURNING y.a;
+ a
+ ----
+ 11
+ 12
+ 13
+ 14
+ 15
+ 16
+ 17
+ 18
+ 19
+ 20
+ (10 rows)
+
+ SELECT * FROM y;
+ a
+ ----
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+ (10 rows)
+
+ --
-- error cases
--
-- INTERSECT
***************
*** 774,781 ****
ERROR: recursive reference to query "x" must not appear within its non-recursive term
LINE 1: WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
^
- CREATE TEMPORARY TABLE y (a INTEGER);
- INSERT INTO y SELECT generate_series(1, 10);
-- LEFT JOIN
WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
UNION ALL
--- 851,856 ----
Index: src/test/regress/sql/with.sql
===================================================================
RCS file: /cvsroot/pgsql/src/test/regress/sql/with.sql,v
retrieving revision 1.11
diff -c -r1.11 with.sql
*** src/test/regress/sql/with.sql 9 Sep 2009 03:32:52 -0000 1.11
--- src/test/regress/sql/with.sql 13 Feb 2010 00:49:42 -0000
***************
*** 339,344 ****
--- 339,371 ----
SELECT * FROM z;
--
+ -- WITH on top of a DML statement
+ --
+
+ CREATE TEMPORARY TABLE y (a INTEGER);
+ INSERT INTO y SELECT generate_series(1, 10);
+
+ INSERT INTO y
+ WITH t AS (
+ SELECT a FROM y
+ )
+ SELECT a+20 FROM t RETURNING *;
+
+ WITH t AS (
+ SELECT a FROM y
+ )
+ UPDATE y SET a = y.a-10 FROM t WHERE y.a > 20 AND t.a = y.a RETURNING y.a;
+
+ WITH RECURSIVE t(a) AS (
+ SELECT 11
+ UNION ALL
+ SELECT a+1 FROM t WHERE a < 50
+ )
+ DELETE FROM y USING t WHERE t.a = y.a RETURNING y.a;
+
+ SELECT * FROM y;
+
+ --
-- error cases
--
***************
*** 364,372 ****
WITH RECURSIVE x(n) AS (SELECT n FROM x UNION ALL SELECT 1)
SELECT * FROM x;
- CREATE TEMPORARY TABLE y (a INTEGER);
- INSERT INTO y SELECT generate_series(1, 10);
-
-- LEFT JOIN
WITH RECURSIVE x(n) AS (SELECT a FROM y WHERE a = 1
--- 391,396 ----