summaryrefslogtreecommitdiff
path: root/src/backend/parser
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser')
-rw-r--r--src/backend/parser/gram.y15
-rw-r--r--src/backend/parser/parse_relation.c6
-rw-r--r--src/backend/parser/parse_utilcmd.c16
3 files changed, 32 insertions, 5 deletions
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index d7f9c00c409..d3887628d46 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -636,7 +636,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
%type <str> opt_existing_window_name
%type <boolean> opt_if_not_exists
%type <boolean> opt_unique_null_treatment
-%type <ival> generated_when override_kind
+%type <ival> generated_when override_kind opt_virtual_or_stored
%type <partspec> PartitionSpec OptPartitionSpec
%type <partelem> part_elem
%type <list> part_params
@@ -784,7 +784,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
UNLISTEN UNLOGGED UNTIL UPDATE USER USING
VACUUM VALID VALIDATE VALIDATOR VALUE_P VALUES VARCHAR VARIADIC VARYING
- VERBOSE VERSION_P VIEW VIEWS VOLATILE
+ VERBOSE VERSION_P VIEW VIEWS VIRTUAL VOLATILE
WHEN WHERE WHITESPACE_P WINDOW WITH WITHIN WITHOUT WORK WRAPPER WRITE
@@ -3995,7 +3995,7 @@ ColConstraintElem:
n->location = @1;
$$ = (Node *) n;
}
- | GENERATED generated_when AS '(' a_expr ')' STORED
+ | GENERATED generated_when AS '(' a_expr ')' opt_virtual_or_stored
{
Constraint *n = makeNode(Constraint);
@@ -4003,6 +4003,7 @@ ColConstraintElem:
n->generated_when = $2;
n->raw_expr = $5;
n->cooked_expr = NULL;
+ n->generated_kind = $7;
n->location = @1;
/*
@@ -4050,6 +4051,12 @@ generated_when:
| BY DEFAULT { $$ = ATTRIBUTE_IDENTITY_BY_DEFAULT; }
;
+opt_virtual_or_stored:
+ STORED { $$ = ATTRIBUTE_GENERATED_STORED; }
+ | VIRTUAL { $$ = ATTRIBUTE_GENERATED_VIRTUAL; }
+ | /*EMPTY*/ { $$ = ATTRIBUTE_GENERATED_VIRTUAL; }
+ ;
+
/*
* ConstraintAttr represents constraint attributes, which we parse as if
* they were independent constraint clauses, in order to avoid shift/reduce
@@ -17990,6 +17997,7 @@ unreserved_keyword:
| VERSION_P
| VIEW
| VIEWS
+ | VIRTUAL
| VOLATILE
| WHITESPACE_P
| WITHIN
@@ -18645,6 +18653,7 @@ bare_label_keyword:
| VERSION_P
| VIEW
| VIEWS
+ | VIRTUAL
| VOLATILE
| WHEN
| WHITESPACE_P
diff --git a/src/backend/parser/parse_relation.c b/src/backend/parser/parse_relation.c
index 101fba34b18..04ecf64b1fc 100644
--- a/src/backend/parser/parse_relation.c
+++ b/src/backend/parser/parse_relation.c
@@ -712,7 +712,11 @@ scanNSItemForColumn(ParseState *pstate, ParseNamespaceItem *nsitem,
colname),
parser_errposition(pstate, location)));
- /* In generated column, no system column is allowed except tableOid */
+ /*
+ * In generated column, no system column is allowed except tableOid.
+ * (Required for stored generated, but we also do it for virtual generated
+ * for now for consistency.)
+ */
if (pstate->p_expr_kind == EXPR_KIND_GENERATED_COLUMN &&
attnum < InvalidAttrNumber && attnum != TableOidAttributeNumber)
ereport(ERROR,
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index ca028d2a66d..eb7716cd84c 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -889,7 +889,7 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
column->colname, cxt->relation->relname),
parser_errposition(cxt->pstate,
constraint->location)));
- column->generated = ATTRIBUTE_GENERATED_STORED;
+ column->generated = constraint->generated_kind;
column->raw_default = constraint->raw_expr;
Assert(constraint->cooked_expr == NULL);
saw_generated = true;
@@ -988,6 +988,20 @@ transformColumnDefinition(CreateStmtContext *cxt, ColumnDef *column)
column->colname, cxt->relation->relname),
parser_errposition(cxt->pstate,
constraint->location)));
+
+ /*
+ * TODO: Straightforward not-null constraints won't work on virtual
+ * generated columns, because there is no support for expanding the
+ * column when the constraint is checked. Maybe we could convert the
+ * not-null constraint into a full check constraint, so that the
+ * generation expression can be expanded at check time.
+ */
+ if (column->is_not_null && column->generated == ATTRIBUTE_GENERATED_VIRTUAL)
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("not-null constraints are not supported on virtual generated columns"),
+ parser_errposition(cxt->pstate,
+ constraint->location)));
}
/*