aboutsummaryrefslogtreecommitdiff
path: root/src/backend/parser/parse_utilcmd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/parser/parse_utilcmd.c')
-rw-r--r--src/backend/parser/parse_utilcmd.c80
1 files changed, 54 insertions, 26 deletions
diff --git a/src/backend/parser/parse_utilcmd.c b/src/backend/parser/parse_utilcmd.c
index 15274607542..1e15ce10b48 100644
--- a/src/backend/parser/parse_utilcmd.c
+++ b/src/backend/parser/parse_utilcmd.c
@@ -365,30 +365,22 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
{
ListCell *option;
DefElem *nameEl = NULL;
+ DefElem *loggedEl = NULL;
Oid snamespaceid;
char *snamespace;
char *sname;
+ char seqpersistence;
CreateSeqStmt *seqstmt;
AlterSeqStmt *altseqstmt;
List *attnamelist;
- int nameEl_idx = -1;
/* Make a copy of this as we may end up modifying it in the code below */
seqoptions = list_copy(seqoptions);
/*
- * Determine namespace and name to use for the sequence.
- *
- * First, check if a sequence name was passed in as an option. This is
- * used by pg_dump. Else, generate a name.
- *
- * Although we use ChooseRelationName, it's not guaranteed that the
- * selected sequence name won't conflict; given sufficiently long field
- * names, two different serial columns in the same table could be assigned
- * the same sequence name, and we'd not notice since we aren't creating
- * the sequence quite yet. In practice this seems quite unlikely to be a
- * problem, especially since few people would need two serial columns in
- * one table.
+ * Check for non-SQL-standard options (not supported within CREATE
+ * SEQUENCE, because they'd be redundant), and remove them from the
+ * seqoptions list if found.
*/
foreach(option, seqoptions)
{
@@ -399,12 +391,24 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
if (nameEl)
errorConflictingDefElem(defel, cxt->pstate);
nameEl = defel;
- nameEl_idx = foreach_current_index(option);
+ seqoptions = foreach_delete_current(seqoptions, option);
+ }
+ else if (strcmp(defel->defname, "logged") == 0 ||
+ strcmp(defel->defname, "unlogged") == 0)
+ {
+ if (loggedEl)
+ errorConflictingDefElem(defel, cxt->pstate);
+ loggedEl = defel;
+ seqoptions = foreach_delete_current(seqoptions, option);
}
}
+ /*
+ * Determine namespace and name to use for the sequence.
+ */
if (nameEl)
{
+ /* Use specified name */
RangeVar *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg));
snamespace = rv->schemaname;
@@ -418,11 +422,20 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
snamespace = get_namespace_name(snamespaceid);
}
sname = rv->relname;
- /* Remove the SEQUENCE NAME item from seqoptions */
- seqoptions = list_delete_nth_cell(seqoptions, nameEl_idx);
}
else
{
+ /*
+ * Generate a name.
+ *
+ * Although we use ChooseRelationName, it's not guaranteed that the
+ * selected sequence name won't conflict; given sufficiently long
+ * field names, two different serial columns in the same table could
+ * be assigned the same sequence name, and we'd not notice since we
+ * aren't creating the sequence quite yet. In practice this seems
+ * quite unlikely to be a problem, especially since few people would
+ * need two serial columns in one table.
+ */
if (cxt->rel)
snamespaceid = RelationGetNamespace(cxt->rel);
else
@@ -444,22 +457,37 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
cxt->relation->relname, column->colname)));
/*
+ * Determine the persistence of the sequence. By default we copy the
+ * persistence of the table, but if LOGGED or UNLOGGED was specified, use
+ * that (as long as the table isn't TEMP).
+ *
+ * For CREATE TABLE, we get the persistence from cxt->relation, which
+ * comes from the CreateStmt in progress. For ALTER TABLE, the parser
+ * won't set cxt->relation->relpersistence, but we have cxt->rel as the
+ * existing table, so we copy the persistence from there.
+ */
+ seqpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
+ if (loggedEl)
+ {
+ if (seqpersistence == RELPERSISTENCE_TEMP)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+ errmsg("cannot set logged status of a temporary sequence"),
+ parser_errposition(cxt->pstate, loggedEl->location)));
+ else if (strcmp(loggedEl->defname, "logged") == 0)
+ seqpersistence = RELPERSISTENCE_PERMANENT;
+ else
+ seqpersistence = RELPERSISTENCE_UNLOGGED;
+ }
+
+ /*
* Build a CREATE SEQUENCE command to create the sequence object, and add
* it to the list of things to be done before this CREATE/ALTER TABLE.
*/
seqstmt = makeNode(CreateSeqStmt);
seqstmt->for_identity = for_identity;
seqstmt->sequence = makeRangeVar(snamespace, sname, -1);
-
- /*
- * Copy the persistence of the table. For CREATE TABLE, we get the
- * persistence from cxt->relation, which comes from the CreateStmt in
- * progress. For ALTER TABLE, the parser won't set
- * cxt->relation->relpersistence, but we have cxt->rel as the existing
- * table, so we copy the persistence from there.
- */
- seqstmt->sequence->relpersistence = cxt->rel ? cxt->rel->rd_rel->relpersistence : cxt->relation->relpersistence;
-
+ seqstmt->sequence->relpersistence = seqpersistence;
seqstmt->options = seqoptions;
/*