Skip to content

Commit 38498a2

Browse files
committed
Clean up pg_dump's handling of ownership for indexes (including
pkey/unique constraint indexes) and schemas. Per report from Michael Fuhr.
1 parent fc29917 commit 38498a2

File tree

2 files changed

+110
-82
lines changed

2 files changed

+110
-82
lines changed

src/bin/pg_dump/pg_backup_archiver.c

Lines changed: 107 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
*
1616
*
1717
* IDENTIFICATION
18-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.100 2004/11/06 19:36:01 tgl Exp $
18+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_backup_archiver.c,v 1.101 2005/01/11 05:14:10 tgl Exp $
1919
*
2020
*-------------------------------------------------------------------------
2121
*/
@@ -47,7 +47,7 @@ static char *modulename = gettext_noop("archiver");
4747

4848
static ArchiveHandle *_allocAH(const char *FileSpec, const ArchiveFormat fmt,
4949
const int compression, ArchiveMode mode);
50-
static char *_getObjectFromDropStmt(const char *dropStmt, const char *type);
50+
static void _getObjectDescription(PQExpBuffer buf, TocEntry *te);
5151
static void _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isData, bool acl_pass);
5252

5353

@@ -2363,64 +2363,78 @@ _selectTablespace(ArchiveHandle *AH, const char *tablespace)
23632363
destroyPQExpBuffer(qry);
23642364
}
23652365

2366-
/**
2367-
* Parses the dropStmt part of a TOC entry and returns
2368-
* a newly allocated string that is the object identifier
2369-
* The caller must free the result.
2366+
/*
2367+
* Extract an object description for a TOC entry, and append it to buf.
2368+
*
2369+
* This is not quite as general as it may seem, since it really only
2370+
* handles constructing the right thing to put into ALTER ... OWNER TO.
2371+
*
2372+
* The whole thing is pretty grotty, but we are kind of stuck since the
2373+
* information used is all that's available in older dump files.
23702374
*/
2371-
static char *
2372-
_getObjectFromDropStmt(const char *dropStmt, const char *type)
2375+
static void
2376+
_getObjectDescription(PQExpBuffer buf, TocEntry *te)
23732377
{
2374-
/* Chop "DROP" off the front and make a copy */
2375-
char *first = strdup(dropStmt + 5);
2376-
char *last = first + strlen(first) - 1; /* Points to the last
2377-
* real char in extract */
2378-
char *buf = NULL;
2378+
const char *type = te->desc;
23792379

2380-
/*
2381-
* Loop from the end of the string until last char is no longer '\n'
2382-
* or ';'
2383-
*/
2384-
while (last >= first && (*last == '\n' || *last == ';'))
2385-
last--;
2380+
/* Use ALTER TABLE for views and sequences */
2381+
if (strcmp(type, "VIEW") == 0 ||
2382+
strcmp(type, "SEQUENCE") == 0)
2383+
type = "TABLE";
23862384

2387-
/* Insert end of string one place after last */
2388-
*(last + 1) = '\0';
2385+
/* We assume CONSTRAINTs are always pkey/unique indexes */
2386+
if (strcmp(type, "CONSTRAINT") == 0)
2387+
type = "INDEX";
23892388

2390-
/*
2391-
* Take off CASCADE if necessary. Only TYPEs seem to have this, but
2392-
* may as well check for all
2393-
*/
2394-
if ((last - first) >= 8)
2389+
/* objects named by a schema and name */
2390+
if (strcmp(type, "CONVERSION") == 0 ||
2391+
strcmp(type, "DOMAIN") == 0 ||
2392+
strcmp(type, "INDEX") == 0 ||
2393+
strcmp(type, "TABLE") == 0 ||
2394+
strcmp(type, "TYPE") == 0)
23952395
{
2396-
if (strcmp(last - 7, " CASCADE") == 0)
2397-
last -= 8;
2396+
appendPQExpBuffer(buf, "%s %s", type, fmtId(te->namespace));
2397+
appendPQExpBuffer(buf, ".%s", fmtId(te->tag));
2398+
return;
23982399
}
23992400

2400-
/* Insert end of string one place after last */
2401-
*(last + 1) = '\0';
2402-
2403-
/* Special case VIEWs and SEQUENCEs. They must use ALTER TABLE. */
2404-
if (strcmp(type, "VIEW") == 0 && (last - first) >= 5)
2401+
/* objects named by just a name */
2402+
if (strcmp(type, "DATABASE") == 0 ||
2403+
strcmp(type, "SCHEMA") == 0)
24052404
{
2406-
int len = 6 + strlen(first + 5) + 1;
2407-
2408-
buf = malloc(len);
2409-
snprintf(buf, len, "TABLE %s", first + 5);
2410-
free(first);
2405+
appendPQExpBuffer(buf, "%s %s", type, fmtId(te->tag));
2406+
return;
24112407
}
2412-
else if (strcmp(type, "SEQUENCE") == 0 && (last - first) >= 9)
2408+
2409+
/*
2410+
* These object types require additional decoration. Fortunately,
2411+
* the information needed is exactly what's in the DROP command.
2412+
*/
2413+
if (strcmp(type, "AGGREGATE") == 0 ||
2414+
strcmp(type, "FUNCTION") == 0 ||
2415+
strcmp(type, "OPERATOR") == 0 ||
2416+
strcmp(type, "OPERATOR CLASS") == 0)
24132417
{
2414-
int len = 6 + strlen(first + 9) + 1;
2418+
/* Chop "DROP " off the front and make a modifiable copy */
2419+
char *first = strdup(te->dropStmt + 5);
2420+
char *last;
2421+
2422+
/* point to last character in string */
2423+
last = first + strlen(first) - 1;
2424+
2425+
/* Strip off any ';' or '\n' at the end */
2426+
while (last >= first && (*last == '\n' || *last == ';'))
2427+
last--;
2428+
*(last + 1) = '\0';
2429+
2430+
appendPQExpBufferStr(buf, first);
24152431

2416-
buf = malloc(len);
2417-
snprintf(buf, len, "TABLE %s", first + 9);
24182432
free(first);
2433+
return;
24192434
}
2420-
else
2421-
buf = first;
24222435

2423-
return buf;
2436+
write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2437+
type);
24242438
}
24252439

24262440
static void
@@ -2497,13 +2511,14 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
24972511
/*
24982512
* Actually print the definition.
24992513
*
2500-
* Really crude hack for suppressing AUTHORIZATION clause of CREATE
2501-
* SCHEMA when --no-owner mode is selected. This is ugly, but I see
2514+
* Really crude hack for suppressing AUTHORIZATION clause that old
2515+
* pg_dump versions put into CREATE SCHEMA. We have to do this when
2516+
* --no-owner mode is selected. This is ugly, but I see
25022517
* no other good way ...
25032518
*/
2504-
if (AH->ropt && AH->ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
2519+
if (ropt->noOwner && strcmp(te->desc, "SCHEMA") == 0)
25052520
{
2506-
ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", te->tag);
2521+
ahprintf(AH, "CREATE SCHEMA %s;\n\n\n", fmtId(te->tag));
25072522
}
25082523
else
25092524
{
@@ -2513,29 +2528,51 @@ _printTocEntry(ArchiveHandle *AH, TocEntry *te, RestoreOptions *ropt, bool isDat
25132528

25142529
/*
25152530
* If we aren't using SET SESSION AUTH to determine ownership, we must
2516-
* instead issue an ALTER OWNER command. Ugly, since we have to cons
2517-
* one up based on the dropStmt. We don't need this for schemas
2518-
* (since we use CREATE SCHEMA AUTHORIZATION instead), nor for some
2519-
* other object types.
2531+
* instead issue an ALTER OWNER command. We assume that anything without
2532+
* a DROP command is not a separately ownable object. All the categories
2533+
* with DROP commands must appear in one list or the other.
25202534
*/
25212535
if (!ropt->noOwner && !ropt->use_setsessauth &&
2522-
strlen(te->owner) > 0 && strlen(te->dropStmt) > 0 &&
2523-
(strcmp(te->desc, "AGGREGATE") == 0 ||
2524-
strcmp(te->desc, "CONVERSION") == 0 ||
2525-
strcmp(te->desc, "DATABASE") == 0 ||
2526-
strcmp(te->desc, "DOMAIN") == 0 ||
2527-
strcmp(te->desc, "FUNCTION") == 0 ||
2528-
strcmp(te->desc, "OPERATOR") == 0 ||
2529-
strcmp(te->desc, "OPERATOR CLASS") == 0 ||
2530-
strcmp(te->desc, "TABLE") == 0 ||
2531-
strcmp(te->desc, "TYPE") == 0 ||
2532-
strcmp(te->desc, "VIEW") == 0 ||
2533-
strcmp(te->desc, "SEQUENCE") == 0))
2534-
{
2535-
char *temp = _getObjectFromDropStmt(te->dropStmt, te->desc);
2536-
2537-
ahprintf(AH, "ALTER %s OWNER TO %s;\n\n", temp, fmtId(te->owner));
2538-
free(temp);
2536+
strlen(te->owner) > 0 && strlen(te->dropStmt) > 0)
2537+
{
2538+
if (strcmp(te->desc, "AGGREGATE") == 0 ||
2539+
strcmp(te->desc, "CONSTRAINT") == 0 ||
2540+
strcmp(te->desc, "CONVERSION") == 0 ||
2541+
strcmp(te->desc, "DATABASE") == 0 ||
2542+
strcmp(te->desc, "DOMAIN") == 0 ||
2543+
strcmp(te->desc, "FUNCTION") == 0 ||
2544+
strcmp(te->desc, "INDEX") == 0 ||
2545+
strcmp(te->desc, "OPERATOR") == 0 ||
2546+
strcmp(te->desc, "OPERATOR CLASS") == 0 ||
2547+
strcmp(te->desc, "SCHEMA") == 0 ||
2548+
strcmp(te->desc, "TABLE") == 0 ||
2549+
strcmp(te->desc, "TYPE") == 0 ||
2550+
strcmp(te->desc, "VIEW") == 0 ||
2551+
strcmp(te->desc, "SEQUENCE") == 0)
2552+
{
2553+
PQExpBuffer temp = createPQExpBuffer();
2554+
2555+
appendPQExpBuffer(temp, "ALTER ");
2556+
_getObjectDescription(temp, te);
2557+
appendPQExpBuffer(temp, " OWNER TO %s;", fmtId(te->owner));
2558+
ahprintf(AH, "%s\n\n", temp->data);
2559+
destroyPQExpBuffer(temp);
2560+
}
2561+
else if (strcmp(te->desc, "CAST") == 0 ||
2562+
strcmp(te->desc, "CHECK CONSTRAINT") == 0 ||
2563+
strcmp(te->desc, "DEFAULT") == 0 ||
2564+
strcmp(te->desc, "FK CONSTRAINT") == 0 ||
2565+
strcmp(te->desc, "PROCEDURAL LANGUAGE") == 0 ||
2566+
strcmp(te->desc, "RULE") == 0 ||
2567+
strcmp(te->desc, "TRIGGER") == 0)
2568+
{
2569+
/* these object types don't have separate owners */
2570+
}
2571+
else
2572+
{
2573+
write_msg(modulename, "WARNING: don't know how to set owner for object type %s\n",
2574+
te->desc);
2575+
}
25392576
}
25402577

25412578
/*

src/bin/pg_dump/pg_dump.c

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* by PostgreSQL
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.398 2005/01/04 22:27:46 tgl Exp $
15+
* $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.399 2005/01/11 05:14:13 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -4428,23 +4428,14 @@ dumpNamespace(Archive *fout, NamespaceInfo *nspinfo)
44284428

44294429
qnspname = strdup(fmtId(nspinfo->dobj.name));
44304430

4431-
/*
4432-
* Note that ownership is shown in the AUTHORIZATION clause, while the
4433-
* archive entry is listed with empty owner (causing it to be emitted
4434-
* with SET SESSION AUTHORIZATION DEFAULT). This seems the best way of
4435-
* dealing with schemas owned by users without CREATE SCHEMA
4436-
* privilege. Further hacking has to be applied for --no-owner mode,
4437-
* though!
4438-
*/
44394431
appendPQExpBuffer(delq, "DROP SCHEMA %s;\n", qnspname);
44404432

4441-
appendPQExpBuffer(q, "CREATE SCHEMA %s AUTHORIZATION %s;\n",
4442-
qnspname, fmtId(nspinfo->usename));
4433+
appendPQExpBuffer(q, "CREATE SCHEMA %s;\n", qnspname);
44434434

44444435
ArchiveEntry(fout, nspinfo->dobj.catId, nspinfo->dobj.dumpId,
44454436
nspinfo->dobj.name,
44464437
NULL, NULL,
4447-
strcmp(nspinfo->dobj.name, "public") == 0 ? nspinfo->usename : "",
4438+
nspinfo->usename,
44484439
false, "SCHEMA", q->data, delq->data, NULL,
44494440
nspinfo->dobj.dependencies, nspinfo->dobj.nDeps,
44504441
NULL, NULL);

0 commit comments

Comments
 (0)