diff options
author | Tom Lane | 2017-05-26 16:51:05 +0000 |
---|---|---|
committer | Tom Lane | 2017-05-26 16:51:05 +0000 |
commit | 0461b66e361f56560aaa50e1bd006e36e8bedc6e (patch) | |
tree | 97410e35870d04d8fa5c38a1397a5df91feb650c | |
parent | 9c34a05b7d2304eac3fdc5e9db9fcd0d7c72883f (diff) |
Fix pg_dump to not emit invalid SQL for an empty operator class.
If an operator class has no operators or functions, and doesn't need
a STORAGE clause, we emitted "CREATE OPERATOR CLASS ... AS ;" which
is syntactically invalid. Fix by forcing a STORAGE clause to be
emitted anyway in this case.
(At some point we might consider changing the grammar to allow CREATE
OPERATOR CLASS without an opclass_item_list. But probably we'd want to
omit the AS in that case, so that wouldn't fix this pg_dump issue anyway.)
It's been like this all along, so back-patch to all supported branches.
Daniel Gustafsson, tweaked by me to avoid a dangling-pointer bug
Discussion: https://postgr.es/m/[email protected]
-rw-r--r-- | src/bin/pg_dump/pg_dump.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 053ae0e417..9da9b9e962 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -12440,7 +12440,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) i_opcfamilynsp = PQfnumber(res, "opcfamilynsp"); i_amname = PQfnumber(res, "amname"); - opcintype = PQgetvalue(res, 0, i_opcintype); + /* opcintype may still be needed after we PQclear res */ + opcintype = pg_strdup(PQgetvalue(res, 0, i_opcintype)); opckeytype = PQgetvalue(res, 0, i_opckeytype); opcdefault = PQgetvalue(res, 0, i_opcdefault); /* opcfamily will still be needed after we PQclear res */ @@ -12674,6 +12675,15 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) PQclear(res); + /* + * If needComma is still false it means we haven't added anything after + * the AS keyword. To avoid printing broken SQL, append a dummy STORAGE + * clause with the same datatype. This isn't sanctioned by the + * documentation, but actually DefineOpClass will treat it as a no-op. + */ + if (!needComma) + appendPQExpBuffer(q, "STORAGE %s", opcintype); + appendPQExpBufferStr(q, ";\n"); appendPQExpBuffer(labelq, "OPERATOR CLASS %s", @@ -12701,6 +12711,8 @@ dumpOpclass(Archive *fout, OpclassInfo *opcinfo) opcinfo->dobj.namespace->dobj.name, opcinfo->rolname, opcinfo->dobj.catId, 0, opcinfo->dobj.dumpId); + free(opcintype); + free(opcfamily); free(amname); destroyPQExpBuffer(query); destroyPQExpBuffer(q); |