Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5189398

Browse files
committed
Handle unqualified SEQUENCE NAME options properly in parse_utilcmd.c.
generateSerialExtraStmts() was sloppy about handling the case where SEQUENCE NAME is given with a not-schema-qualified name. It was generating a CreateSeqStmt with an unqualified sequence name, and an AlterSeqStmt whose "owned_by" DefElem contained a T_String Value with a null string pointer in the schema-name position. The generated nextval() argument was also underqualified. This accidentally failed to fail at runtime, but only so long as the current default creation namespace at runtime is the right namespace. That's bogus; the parse-time transformation is supposed to be inserting the right schema name in all cases, so as to avoid any possible skew in that selection. I'm not sure this could fail in pg_dump's usage, but it's still wrong; we have had real bugs in this area before adopting the policy that parse_utilcmd.c should generate only fully-qualified auxiliary commands. A slightly lesser problem, which is what led me to notice this in the first place, is that pprint() dumped core on the AlterSeqStmt because of the bogus T_String. Noted while poking into the open problem with ALTER SEQUENCE breaking pg_upgrade.
1 parent 4f7a95b commit 5189398

File tree

1 file changed

+22
-2
lines changed

1 file changed

+22
-2
lines changed

src/backend/parser/parse_utilcmd.c

+22-2
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,15 @@ transformCreateStmt(CreateStmt *stmt, const char *queryString)
345345
return result;
346346
}
347347

348+
/*
349+
* generateSerialExtraStmts
350+
* Generate CREATE SEQUENCE and ALTER SEQUENCE ... OWNED BY statements
351+
* to create the sequence for a serial or identity column.
352+
*
353+
* This includes determining the name the sequence will have. The caller
354+
* can ask to get back the name components by passing non-null pointers
355+
* for snamespace_p and sname_p.
356+
*/
348357
static void
349358
generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
350359
Oid seqtypid, List *seqoptions, bool for_identity,
@@ -373,7 +382,6 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
373382
* problem, especially since few people would need two serial columns in
374383
* one table.
375384
*/
376-
377385
foreach(option, seqoptions)
378386
{
379387
DefElem *defel = lfirst_node(DefElem, option);
@@ -393,7 +401,17 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
393401
RangeVar *rv = makeRangeVarFromNameList(castNode(List, nameEl->arg));
394402

395403
snamespace = rv->schemaname;
404+
if (!snamespace)
405+
{
406+
/* Given unqualified SEQUENCE NAME, select namespace */
407+
if (cxt->rel)
408+
snamespaceid = RelationGetNamespace(cxt->rel);
409+
else
410+
snamespaceid = RangeVarGetCreationNamespace(cxt->relation);
411+
snamespace = get_namespace_name(snamespaceid);
412+
}
396413
sname = rv->relname;
414+
/* Remove the SEQUENCE NAME item from seqoptions */
397415
seqoptions = list_delete_ptr(seqoptions, nameEl);
398416
}
399417
else
@@ -433,7 +451,9 @@ generateSerialExtraStmts(CreateStmtContext *cxt, ColumnDef *column,
433451
* not our synthetic one.
434452
*/
435453
if (seqtypid)
436-
seqstmt->options = lcons(makeDefElem("as", (Node *) makeTypeNameFromOid(seqtypid, -1), -1),
454+
seqstmt->options = lcons(makeDefElem("as",
455+
(Node *) makeTypeNameFromOid(seqtypid, -1),
456+
-1),
437457
seqstmt->options);
438458

439459
/*

0 commit comments

Comments
 (0)