From 767dcd0f3669d2701d9f94a0112108be34071c38 Mon Sep 17 00:00:00 2001 From: Marcos Magueta Date: Wed, 21 Jan 2026 17:11:24 -0300 Subject: [PATCH 2/5] Add pg_dump support for XMLSCHEMA objects --- src/bin/pg_dump/common.c | 3 + src/bin/pg_dump/pg_backup_archiver.c | 1 + src/bin/pg_dump/pg_dump.c | 128 +++++++++++++++++++++++++++ src/bin/pg_dump/pg_dump.h | 8 ++ 4 files changed, 140 insertions(+) diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c index 349b47c8e29..651cf674365 100644 --- a/src/bin/pg_dump/common.c +++ b/src/bin/pg_dump/common.c @@ -182,6 +182,9 @@ getSchemaData(Archive *fout, int *numTablesPtr) pg_log_info("reading user-defined conversions"); getConversions(fout); + pg_log_info("reading XML schemas"); + getXmlSchemas(fout); + pg_log_info("reading type casts"); getCasts(fout); diff --git a/src/bin/pg_dump/pg_backup_archiver.c b/src/bin/pg_dump/pg_backup_archiver.c index 4a63f7392ae..3175083edb0 100644 --- a/src/bin/pg_dump/pg_backup_archiver.c +++ b/src/bin/pg_dump/pg_backup_archiver.c @@ -3816,6 +3816,7 @@ _getObjectDescription(PQExpBuffer buf, const TocEntry *te) strcmp(type, "TEXT SEARCH CONFIGURATION") == 0 || strcmp(type, "TYPE") == 0 || strcmp(type, "VIEW") == 0 || + strcmp(type, "XMLSCHEMA") == 0 || /* non-schema-specified objects */ strcmp(type, "DATABASE") == 0 || strcmp(type, "PROCEDURAL LANGUAGE") == 0 || diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c index 687dc98e46d..9a531ff3e8c 100644 --- a/src/bin/pg_dump/pg_dump.c +++ b/src/bin/pg_dump/pg_dump.c @@ -310,6 +310,7 @@ static void dumpAccessMethod(Archive *fout, const AccessMethodInfo *aminfo); static void dumpOpclass(Archive *fout, const OpclassInfo *opcinfo); static void dumpOpfamily(Archive *fout, const OpfamilyInfo *opfinfo); static void dumpCollation(Archive *fout, const CollInfo *collinfo); +static void dumpXmlSchema(Archive *fout, const XmlSchemaInfo * xmlschemainfo); static void dumpConversion(Archive *fout, const ConvInfo *convinfo); static void dumpRule(Archive *fout, const RuleInfo *rinfo); static void dumpAgg(Archive *fout, const AggInfo *agginfo); @@ -6563,6 +6564,62 @@ getConversions(Archive *fout) destroyPQExpBuffer(query); } +/* + * getXmlSchemas: + * get information about all XML schemas in the system catalogs + */ +void +getXmlSchemas(Archive *fout) +{ + PGresult *res; + int ntups; + int i; + PQExpBuffer query; + XmlSchemaInfo *xmlschemainfo; + int i_tableoid; + int i_oid; + int i_schemaname; + int i_schemanamespace; + int i_schemaowner; + + query = createPQExpBuffer(); + + appendPQExpBufferStr(query, "SELECT tableoid, oid, schemaname, " + "schemanamespace, " + "schemaowner " + "FROM pg_xmlschema"); + + res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK); + + ntups = PQntuples(res); + + xmlschemainfo = (XmlSchemaInfo *) pg_malloc(ntups * sizeof(XmlSchemaInfo)); + + i_tableoid = PQfnumber(res, "tableoid"); + i_oid = PQfnumber(res, "oid"); + i_schemaname = PQfnumber(res, "schemaname"); + i_schemanamespace = PQfnumber(res, "schemanamespace"); + i_schemaowner = PQfnumber(res, "schemaowner"); + + for (i = 0; i < ntups; i++) + { + xmlschemainfo[i].dobj.objType = DO_XMLSCHEMA; + xmlschemainfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid)); + xmlschemainfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid)); + AssignDumpId(&xmlschemainfo[i].dobj); + xmlschemainfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_schemaname)); + xmlschemainfo[i].dobj.namespace = + findNamespace(atooid(PQgetvalue(res, i, i_schemanamespace))); + xmlschemainfo[i].rolname = getRoleName(PQgetvalue(res, i, i_schemaowner)); + + selectDumpableObject(&(xmlschemainfo[i].dobj), fout); + } + + PQclear(res); + + destroyPQExpBuffer(query); +} + /* * getAccessMethods: * get information about all user-defined access methods @@ -11710,6 +11767,9 @@ dumpDumpableObject(Archive *fout, DumpableObject *dobj) case DO_CONVERSION: dumpConversion(fout, (const ConvInfo *) dobj); break; + case DO_XMLSCHEMA: + dumpXmlSchema(fout, (const XmlSchemaInfo *) dobj); + break; case DO_TABLE: dumpTable(fout, (const TableInfo *) dobj); break; @@ -15235,6 +15295,73 @@ dumpCollation(Archive *fout, const CollInfo *collinfo) free(qcollname); } +/* + * dumpXmlSchema + * write out a single XML schema definition + */ +static void +dumpXmlSchema(Archive *fout, const XmlSchemaInfo * xmlschemainfo) +{ + DumpOptions *dopt = fout->dopt; + PQExpBuffer query; + PQExpBuffer q; + PQExpBuffer delq; + char *qxmlschemaname; + PGresult *res; + int i_schemadata; + char *schemadata; + + if (!dopt->dumpSchema) + return; + + query = createPQExpBuffer(); + q = createPQExpBuffer(); + delq = createPQExpBuffer(); + + qxmlschemaname = pg_strdup(fmtId(xmlschemainfo->dobj.name)); + + appendPQExpBuffer(query, + "SELECT schemadata " + "FROM pg_catalog.pg_xmlschema " + "WHERE oid = '%u'::pg_catalog.oid", + xmlschemainfo->dobj.catId.oid); + + res = ExecuteSqlQueryForSingleRow(fout, query->data); + + i_schemadata = PQfnumber(res, "schemadata"); + schemadata = PQgetvalue(res, 0, i_schemadata); + + appendPQExpBuffer(delq, "DROP XMLSCHEMA %s;\n", + fmtQualifiedDumpable(xmlschemainfo)); + + appendPQExpBuffer(q, "CREATE XMLSCHEMA %s AS ", + fmtQualifiedDumpable(xmlschemainfo)); + appendStringLiteralAH(q, schemadata, fout); + appendPQExpBufferStr(q, ";\n"); + + if (xmlschemainfo->dobj.dump & DUMP_COMPONENT_DEFINITION) + ArchiveEntry(fout, xmlschemainfo->dobj.catId, xmlschemainfo->dobj.dumpId, + ARCHIVE_OPTS(.tag = xmlschemainfo->dobj.name, + .namespace = xmlschemainfo->dobj.namespace->dobj.name, + .owner = xmlschemainfo->rolname, + .description = "XMLSCHEMA", + .section = SECTION_PRE_DATA, + .createStmt = q->data, + .dropStmt = delq->data)); + + if (xmlschemainfo->dobj.dump & DUMP_COMPONENT_COMMENT) + dumpComment(fout, "XMLSCHEMA", qxmlschemaname, + xmlschemainfo->dobj.namespace->dobj.name, xmlschemainfo->rolname, + xmlschemainfo->dobj.catId, 0, xmlschemainfo->dobj.dumpId); + + PQclear(res); + + destroyPQExpBuffer(query); + destroyPQExpBuffer(q); + destroyPQExpBuffer(delq); + free(qxmlschemaname); +} + /* * dumpConversion * write out a single conversion definition @@ -20177,6 +20304,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs, case DO_OPFAMILY: case DO_COLLATION: case DO_CONVERSION: + case DO_XMLSCHEMA: case DO_TABLE: case DO_TABLE_ATTACH: case DO_ATTRDEF: diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h index 4c4b14e5fc7..bc1cf5a00d2 100644 --- a/src/bin/pg_dump/pg_dump.h +++ b/src/bin/pg_dump/pg_dump.h @@ -50,6 +50,7 @@ typedef enum DO_OPFAMILY, DO_COLLATION, DO_CONVERSION, + DO_XMLSCHEMA, DO_TABLE, DO_TABLE_ATTACH, DO_ATTRDEF, @@ -299,6 +300,12 @@ typedef struct _convInfo const char *rolname; } ConvInfo; +typedef struct _xmlSchemaInfo +{ + DumpableObject dobj; + const char *rolname; +} XmlSchemaInfo; + typedef struct _tableInfo { /* @@ -797,6 +804,7 @@ extern void getOpclasses(Archive *fout); extern void getOpfamilies(Archive *fout); extern void getCollations(Archive *fout); extern void getConversions(Archive *fout); +extern void getXmlSchemas(Archive *fout); extern TableInfo *getTables(Archive *fout, int *numTables); extern void getOwnedSeqs(Archive *fout, TableInfo tblinfo[], int numTables); extern InhInfo *getInherits(Archive *fout, int *numInherits); -- 2.51.2