summaryrefslogtreecommitdiff
path: root/src/include/nodes/primnodes.h
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2014-06-18 13:22:25 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2014-06-18 13:22:34 -0400
commit8f889b1083f38f4f5b3bd3512008a3f60e939244 (patch)
tree68c2e242c88245ea0d3b9329e1e27c78a8e70eaf /src/include/nodes/primnodes.h
parent230ba02d855de7fac31bfb6af25ebd4ae052640b (diff)
downloadpostgresql-8f889b1083f38f4f5b3bd3512008a3f60e939244.tar.gz
Implement UPDATE tab SET (col1,col2,...) = (SELECT ...), ...
This SQL-standard feature allows a sub-SELECT yielding multiple columns (but only one row) to be used to compute the new values of several columns to be updated. While the same results can be had with an independent sub-SELECT per column, such a workaround can require a great deal of duplicated computation. The standard actually says that the source for a multi-column assignment could be any row-valued expression. The implementation used here is tightly tied to our existing sub-SELECT support and can't handle other cases; the Bison grammar would have some issues with them too. However, I don't feel too bad about this since other cases can be converted into sub-SELECTs. For instance, "SET (a,b,c) = row_valued_function(x)" could be written "SET (a,b,c) = (SELECT * FROM row_valued_function(x))".
Diffstat (limited to 'src/include/nodes/primnodes.h')
-rw-r--r--src/include/nodes/primnodes.h38
1 files changed, 28 insertions, 10 deletions
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index db8e87f0d0..6d9f3d95ee 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -198,17 +198,25 @@ typedef struct Const
* `paramid' field. (This type of Param is converted to
* PARAM_EXEC during planning.)
*
- * Note: currently, paramtypmod is valid for PARAM_SUBLINK Params, and for
- * PARAM_EXEC Params generated from them; it is always -1 for PARAM_EXTERN
- * params, since the APIs that supply values for such parameters don't carry
- * any typmod info.
+ * PARAM_MULTIEXPR: Like PARAM_SUBLINK, the parameter represents an
+ * output column of a SubLink node's sub-select, but here, the
+ * SubLink is always a MULTIEXPR SubLink. The high-order 16 bits
+ * of the `paramid' field contain the SubLink's subLinkId, and
+ * the low-order 16 bits contain the column number. (This type
+ * of Param is also converted to PARAM_EXEC during planning.)
+ *
+ * Note: currently, paramtypmod is always -1 for PARAM_EXTERN params, since
+ * the APIs that supply values for such parameters don't carry any typmod
+ * info. It is valid in other types of Params, if they represent expressions
+ * with determinable typmod.
* ----------------
*/
typedef enum ParamKind
{
PARAM_EXTERN,
PARAM_EXEC,
- PARAM_SUBLINK
+ PARAM_SUBLINK,
+ PARAM_MULTIEXPR
} ParamKind;
typedef struct Param
@@ -485,14 +493,16 @@ typedef struct BoolExpr
* ANY_SUBLINK (lefthand) op ANY (SELECT ...)
* ROWCOMPARE_SUBLINK (lefthand) op (SELECT ...)
* EXPR_SUBLINK (SELECT with single targetlist item ...)
+ * MULTIEXPR_SUBLINK (SELECT with multiple targetlist items ...)
* ARRAY_SUBLINK ARRAY(SELECT with single targetlist item ...)
* CTE_SUBLINK WITH query (never actually part of an expression)
* For ALL, ANY, and ROWCOMPARE, the lefthand is a list of expressions of the
* same length as the subselect's targetlist. ROWCOMPARE will *always* have
* a list with more than one entry; if the subselect has just one target
* then the parser will create an EXPR_SUBLINK instead (and any operator
- * above the subselect will be represented separately). Note that both
- * ROWCOMPARE and EXPR require the subselect to deliver only one row.
+ * above the subselect will be represented separately).
+ * ROWCOMPARE, EXPR, and MULTIEXPR require the subselect to deliver at most
+ * one row (if it returns no rows, the result is NULL).
* ALL, ANY, and ROWCOMPARE require the combining operators to deliver boolean
* results. ALL and ANY combine the per-row results using AND and OR
* semantics respectively.
@@ -511,8 +521,14 @@ typedef struct BoolExpr
* output columns of the subselect. And subselect is transformed to a Query.
* This is the representation seen in saved rules and in the rewriter.
*
- * In EXISTS, EXPR, and ARRAY SubLinks, testexpr and operName are unused and
- * are always null.
+ * In EXISTS, EXPR, MULTIEXPR, and ARRAY SubLinks, testexpr and operName
+ * are unused and are always null.
+ *
+ * subLinkId is currently used only for MULTIEXPR SubLinks, and is zero in
+ * other SubLinks. This number identifies different multiple-assignment
+ * subqueries within an UPDATE statement's SET list. It is unique only
+ * within a particular targetlist. The output column(s) of the MULTIEXPR
+ * are referenced by PARAM_MULTIEXPR Params appearing elsewhere in the tlist.
*
* The CTE_SUBLINK case never occurs in actual SubLink nodes, but it is used
* in SubPlans generated for WITH subqueries.
@@ -524,6 +540,7 @@ typedef enum SubLinkType
ANY_SUBLINK,
ROWCOMPARE_SUBLINK,
EXPR_SUBLINK,
+ MULTIEXPR_SUBLINK,
ARRAY_SUBLINK,
CTE_SUBLINK /* for SubPlans only */
} SubLinkType;
@@ -533,9 +550,10 @@ typedef struct SubLink
{
Expr xpr;
SubLinkType subLinkType; /* see above */
+ int subLinkId; /* ID (1..n); 0 if not MULTIEXPR */
Node *testexpr; /* outer-query test for ALL/ANY/ROWCOMPARE */
List *operName; /* originally specified operator name */
- Node *subselect; /* subselect as Query* or parsetree */
+ Node *subselect; /* subselect as Query* or raw parsetree */
int location; /* token location, or -1 if unknown */
} SubLink;