summaryrefslogtreecommitdiff
path: root/src/include
diff options
context:
space:
mode:
authorTom Lane2004-06-09 19:08:20 +0000
committerTom Lane2004-06-09 19:08:20 +0000
commit7e64dbc6b5e516a2510ae41c8c7999d1d8d25872 (patch)
treec819b78903b490e720b4c20969ed6cf8816889d1 /src/include
parent3a0df651da253879bf133a8556853acfb1f664fd (diff)
Support assignment to subfields of composite columns in UPDATE and INSERT.
As a side effect, cause subscripts in INSERT targetlists to do something more or less sensible; previously we evaluated such subscripts and then effectively ignored them. Another side effect is that UPDATE-ing an element or slice of an array value that is NULL now produces a non-null result, namely an array containing just the assigned-to positions.
Diffstat (limited to 'src/include')
-rw-r--r--src/include/nodes/execnodes.h14
-rw-r--r--src/include/nodes/nodes.h6
-rw-r--r--src/include/nodes/parsenodes.h62
-rw-r--r--src/include/nodes/primnodes.h35
-rw-r--r--src/include/parser/parse_node.h7
5 files changed, 89 insertions, 35 deletions
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index 325bf876800..a32378c7f84 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.116 2004/05/10 22:44:49 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.117 2004/06/09 19:08:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -575,6 +575,18 @@ typedef struct FieldSelectState
} FieldSelectState;
/* ----------------
+ * FieldStoreState node
+ * ----------------
+ */
+typedef struct FieldStoreState
+{
+ ExprState xprstate;
+ ExprState *arg; /* input tuple value */
+ List *newvals; /* new value(s) for field(s) */
+ TupleDesc argdesc; /* tupdesc for most recent input */
+} FieldStoreState;
+
+/* ----------------
* CaseExprState node
* ----------------
*/
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 6feedf6762c..b719747e762 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.156 2004/05/26 13:57:02 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/nodes.h,v 1.157 2004/06/09 19:08:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -110,6 +110,7 @@ typedef enum NodeTag
T_SubLink,
T_SubPlan,
T_FieldSelect,
+ T_FieldStore,
T_RelabelType,
T_CaseExpr,
T_CaseWhen,
@@ -143,6 +144,7 @@ typedef enum NodeTag
T_BoolExprState,
T_SubPlanState,
T_FieldSelectState,
+ T_FieldStoreState,
T_CaseExprState,
T_CaseWhenState,
T_ArrayExprState,
@@ -274,7 +276,7 @@ typedef enum NodeTag
T_A_Const,
T_FuncCall,
T_A_Indices,
- T_ExprFieldSelect,
+ T_A_Indirection,
T_ResTarget,
T_TypeCast,
T_SortBy,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 8f6cc25e0aa..0da9b379077 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.257 2004/06/02 21:01:09 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.258 2004/06/09 19:08:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -166,26 +166,26 @@ typedef struct TypeName
* ColumnRef - specifies a reference to a column, or possibly a whole tuple
*
* The "fields" list must be nonempty; its last component may be "*"
- * instead of a field name. Subscripts are optional.
+ * instead of a regular field name.
+ *
+ * Note: any array subscripting or selection of fields from composite columns
+ * is represented by an A_Indirection node above the ColumnRef. However,
+ * for simplicity in the normal case, initial field selection from a table
+ * name is represented within ColumnRef and not by adding A_Indirection.
*/
typedef struct ColumnRef
{
NodeTag type;
List *fields; /* field names (list of Value strings) */
- List *indirection; /* subscripts (list of A_Indices) */
} ColumnRef;
/*
- * ParamRef - specifies a parameter reference
- *
- * The parameter could be qualified with field names and/or subscripts
+ * ParamRef - specifies a $n parameter reference
*/
typedef struct ParamRef
{
NodeTag type;
int number; /* the number of the parameter */
- List *fields; /* field names (list of Value strings) */
- List *indirection; /* subscripts (list of A_Indices) */
} ParamRef;
/*
@@ -267,40 +267,50 @@ typedef struct A_Indices
} A_Indices;
/*
- * ExprFieldSelect - select a field and/or array element from an expression
+ * A_Indirection - select a field and/or array element from an expression
*
- * This is used in the raw parsetree to represent selection from an
- * arbitrary expression (not a column or param reference). Either
- * fields or indirection may be NIL if not used.
+ * The indirection list can contain both A_Indices nodes (representing
+ * subscripting) and string Value nodes (representing field selection
+ * --- the string value is the name of the field to select). For example,
+ * a complex selection operation like
+ * (foo).field1[42][7].field2
+ * would be represented with a single A_Indirection node having a 4-element
+ * indirection list.
+ *
+ * Note: as of Postgres 7.5, we don't support arrays of composite values,
+ * so cases in which a field select follows a subscript aren't actually
+ * semantically legal. However the parser is prepared to handle such.
*/
-typedef struct ExprFieldSelect
+typedef struct A_Indirection
{
NodeTag type;
Node *arg; /* the thing being selected from */
- List *fields; /* field names (list of Value strings) */
- List *indirection; /* subscripts (list of A_Indices) */
-} ExprFieldSelect;
+ List *indirection; /* subscripts and/or field names */
+} A_Indirection;
/*
* ResTarget -
- * result target (used in target list of pre-transformed Parse trees)
+ * result target (used in target list of pre-transformed parse trees)
*
- * In a SELECT or INSERT target list, 'name' is either NULL or
- * the column name assigned to the value. (If there is an 'AS ColumnLabel'
- * clause, the grammar sets 'name' from it; otherwise 'name' is initially NULL
- * and is filled in during the parse analysis phase.)
- * The 'indirection' field is not used at all.
+ * In a SELECT or INSERT target list, 'name' is the column label from an
+ * 'AS ColumnLabel' clause, or NULL if there was none, and 'val' is the
+ * value expression itself. The 'indirection' field is not used.
*
- * In an UPDATE target list, 'name' is the name of the destination column,
+ * INSERT has a second ResTarget list which is the target-column-names list.
+ * Here, 'val' is not used, 'name' is the name of the destination column,
* and 'indirection' stores any subscripts attached to the destination.
- * That is, our representation is UPDATE table SET name [indirection] = val.
+ *
+ * In an UPDATE target list, 'name' is the name of the destination column,
+ * 'indirection' stores any subscripts attached to the destination, and
+ * 'val' is the expression to assign.
+ *
+ * See A_Indirection for more info about what can appear in 'indirection'.
*/
typedef struct ResTarget
{
NodeTag type;
char *name; /* column name or NULL */
- List *indirection; /* subscripts for destination column, or
- * NIL */
+ List *indirection; /* subscripts and field names, or NIL */
Node *val; /* the value expression to compute or
* assign */
} ResTarget;
diff --git a/src/include/nodes/primnodes.h b/src/include/nodes/primnodes.h
index 5db00199cef..3ed4d74ee35 100644
--- a/src/include/nodes/primnodes.h
+++ b/src/include/nodes/primnodes.h
@@ -10,7 +10,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.99 2004/05/30 23:40:39 neilc Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/primnodes.h,v 1.100 2004/06/09 19:08:18 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -36,14 +36,15 @@
* ordinal position (counting from 1). However, in an INSERT or UPDATE
* targetlist, resno represents the attribute number of the destination
* column for the item; so there may be missing or out-of-order resnos.
- * In an UPDATE, it is even legal to have duplicated resnos; consider
+ * It is even legal to have duplicated resnos; consider
* UPDATE table SET arraycol[1] = ..., arraycol[2] = ..., ...
* The two meanings come together in the executor, because the planner
* transforms INSERT/UPDATE tlists into a normalized form with exactly
* one entry for each column of the destination table. Before that's
* happened, however, it is risky to assume that resno == position.
* Generally get_tle_by_resno() should be used rather than list_nth()
- * to fetch tlist entries by resno.
+ * to fetch tlist entries by resno, and only in SELECT should you assume
+ * that resno is a unique identifier.
*
* resname is required to represent the correct column name in non-resjunk
* entries of top-level SELECT targetlists, since it will be used as the
@@ -541,6 +542,31 @@ typedef struct FieldSelect
} FieldSelect;
/* ----------------
+ * FieldStore
+ *
+ * FieldStore represents the operation of modifying one field in a tuple
+ * value, yielding a new tuple value (the input is not touched!). Like
+ * the assign case of ArrayRef, this is used to implement UPDATE of a
+ * portion of a column.
+ *
+ * A single FieldStore can actually represent updates of several different
+ * fields. The parser only generates FieldStores with single-element lists,
+ * but the planner will collapse multiple updates of the same base column
+ * into one FieldStore.
+ * ----------------
+ */
+
+typedef struct FieldStore
+{
+ Expr xpr;
+ Expr *arg; /* input tuple value */
+ List *newvals; /* new value(s) for field(s) */
+ List *fieldnums; /* integer list of field attnums */
+ Oid resulttype; /* type of result (same as type of arg) */
+ /* Like RowExpr, we deliberately omit a typmod here */
+} FieldStore;
+
+/* ----------------
* RelabelType
*
* RelabelType represents a "dummy" type coercion between two binary-
@@ -607,6 +633,9 @@ typedef struct CaseWhen
* Placeholder node for the test value to be processed by a CASE expression.
* This is effectively like a Param, but can be implemented more simply
* since we need only one replacement value at a time.
+ *
+ * We also use this in nested UPDATE expressions.
+ * See transformAssignmentIndirection().
*/
typedef struct CaseTestExpr
{
diff --git a/src/include/parser/parse_node.h b/src/include/parser/parse_node.h
index 8bb595c7098..de7b4766559 100644
--- a/src/include/parser/parse_node.h
+++ b/src/include/parser/parse_node.h
@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.38 2003/11/29 22:41:09 pgsql Exp $
+ * $PostgreSQL: pgsql/src/include/parser/parse_node.h,v 1.39 2004/06/09 19:08:19 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -67,12 +67,13 @@ typedef struct ParseState
extern ParseState *make_parsestate(ParseState *parentParseState);
extern Var *make_var(ParseState *pstate, RangeTblEntry *rte, int attrno);
+extern Oid transformArrayType(Oid arrayType);
extern ArrayRef *transformArraySubscripts(ParseState *pstate,
Node *arrayBase,
Oid arrayType,
- int32 arrayTypMod,
+ Oid elementType,
+ int32 elementTypMod,
List *indirection,
- bool forceSlice,
Node *assignFrom);
extern Const *make_const(Value *value);