Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions | Variables

xml.c File Reference

#include "postgres.h"
#include "access/htup_details.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "commands/dbcommands.h"
#include "executor/executor.h"
#include "executor/spi.h"
#include "fmgr.h"
#include "lib/stringinfo.h"
#include "libpq/pqformat.h"
#include "mb/pg_wchar.h"
#include "miscadmin.h"
#include "nodes/execnodes.h"
#include "nodes/nodeFuncs.h"
#include "utils/array.h"
#include "utils/builtins.h"
#include "utils/date.h"
#include "utils/datetime.h"
#include "utils/lsyscache.h"
#include "utils/memutils.h"
#include "utils/rel.h"
#include "utils/syscache.h"
#include "utils/xml.h"
Include dependency graph for xml.c:

Go to the source code of this file.

Defines

#define NO_XML_SUPPORT()
#define NAMESPACE_XSD   "http://www.w3.org/2001/XMLSchema"
#define NAMESPACE_XSI   "http://www.w3.org/2001/XMLSchema-instance"
#define NAMESPACE_SQLXML   "http://standards.iso.org/iso/9075/2003/sqlxml"
#define PG_XML_DEFAULT_VERSION   "1.0"
#define XML_VISIBLE_SCHEMAS_EXCLUDE   "(nspname ~ '^pg_' OR nspname = 'information_schema')"
#define XML_VISIBLE_SCHEMAS   "SELECT oid FROM pg_catalog.pg_namespace WHERE pg_catalog.has_schema_privilege (oid, 'USAGE') AND NOT " XML_VISIBLE_SCHEMAS_EXCLUDE

Functions

static StringInfo query_to_xml_internal (const char *query, char *tablename, const char *xmlschema, bool nulls, bool tableforest, const char *targetns, bool top_level)
static const char * map_sql_table_to_xmlschema (TupleDesc tupdesc, Oid relid, bool nulls, bool tableforest, const char *targetns)
static const char * map_sql_schema_to_xmlschema_types (Oid nspid, List *relid_list, bool nulls, bool tableforest, const char *targetns)
static const char * map_sql_catalog_to_xmlschema_types (List *nspid_list, bool nulls, bool tableforest, const char *targetns)
static const char * map_sql_type_to_xml_name (Oid typeoid, int typmod)
static const char * map_sql_typecoll_to_xmlschema_types (List *tupdesc_list)
static const char * map_sql_type_to_xmlschema_type (Oid typeoid, int typmod)
static void SPI_sql_row_to_xmlelement (int rownum, StringInfo result, char *tablename, bool nulls, bool tableforest, const char *targetns, bool top_level)
Datum xml_in (PG_FUNCTION_ARGS)
static char * xml_out_internal (xmltype *x, pg_enc target_encoding)
Datum xml_out (PG_FUNCTION_ARGS)
Datum xml_recv (PG_FUNCTION_ARGS)
Datum xml_send (PG_FUNCTION_ARGS)
static xmltypestringinfo_to_xmltype (StringInfo buf)
static xmltypecstring_to_xmltype (const char *string)
Datum xmlcomment (PG_FUNCTION_ARGS)
xmltypexmlconcat (List *args)
Datum xmlconcat2 (PG_FUNCTION_ARGS)
Datum texttoxml (PG_FUNCTION_ARGS)
Datum xmltotext (PG_FUNCTION_ARGS)
textxmltotext_with_xmloption (xmltype *data, XmlOptionType xmloption_arg)
xmltypexmlelement (XmlExprState *xmlExpr, ExprContext *econtext)
xmltypexmlparse (text *data, XmlOptionType xmloption_arg, bool preserve_whitespace)
xmltypexmlpi (char *target, text *arg, bool arg_is_null, bool *result_is_null)
xmltypexmlroot (xmltype *data, text *version, int standalone)
Datum xmlvalidate (PG_FUNCTION_ARGS)
bool xml_is_document (xmltype *arg)
char * map_sql_identifier_to_xml_name (char *ident, bool fully_escaped, bool escape_period)
static char * unicode_to_sqlchar (pg_wchar c)
char * map_xml_name_to_sql_identifier (char *name)
char * map_sql_value_to_xml_value (Datum value, Oid type, bool xml_escape_strings)
char * escape_xml (const char *str)
static char * _SPI_strdup (const char *s)
static Listquery_to_oid_list (const char *query)
static Listschema_get_xml_visible_tables (Oid nspid)
static Listdatabase_get_xml_visible_schemas (void)
static Listdatabase_get_xml_visible_tables (void)
static StringInfo table_to_xml_internal (Oid relid, const char *xmlschema, bool nulls, bool tableforest, const char *targetns, bool top_level)
Datum table_to_xml (PG_FUNCTION_ARGS)
Datum query_to_xml (PG_FUNCTION_ARGS)
Datum cursor_to_xml (PG_FUNCTION_ARGS)
static void xmldata_root_element_start (StringInfo result, const char *eltname, const char *xmlschema, const char *targetns, bool top_level)
static void xmldata_root_element_end (StringInfo result, const char *eltname)
Datum table_to_xmlschema (PG_FUNCTION_ARGS)
Datum query_to_xmlschema (PG_FUNCTION_ARGS)
Datum cursor_to_xmlschema (PG_FUNCTION_ARGS)
Datum table_to_xml_and_xmlschema (PG_FUNCTION_ARGS)
Datum query_to_xml_and_xmlschema (PG_FUNCTION_ARGS)
static StringInfo schema_to_xml_internal (Oid nspid, const char *xmlschema, bool nulls, bool tableforest, const char *targetns, bool top_level)
Datum schema_to_xml (PG_FUNCTION_ARGS)
static void xsd_schema_element_start (StringInfo result, const char *targetns)
static void xsd_schema_element_end (StringInfo result)
static StringInfo schema_to_xmlschema_internal (const char *schemaname, bool nulls, bool tableforest, const char *targetns)
Datum schema_to_xmlschema (PG_FUNCTION_ARGS)
Datum schema_to_xml_and_xmlschema (PG_FUNCTION_ARGS)
static StringInfo database_to_xml_internal (const char *xmlschema, bool nulls, bool tableforest, const char *targetns)
Datum database_to_xml (PG_FUNCTION_ARGS)
static StringInfo database_to_xmlschema_internal (bool nulls, bool tableforest, const char *targetns)
Datum database_to_xmlschema (PG_FUNCTION_ARGS)
Datum database_to_xml_and_xmlschema (PG_FUNCTION_ARGS)
static char * map_multipart_sql_identifier_to_xml_name (char *a, char *b, char *c, char *d)
Datum xpath (PG_FUNCTION_ARGS)
Datum xmlexists (PG_FUNCTION_ARGS)
Datum xpath_exists (PG_FUNCTION_ARGS)
Datum xml_is_well_formed (PG_FUNCTION_ARGS)
Datum xml_is_well_formed_document (PG_FUNCTION_ARGS)
Datum xml_is_well_formed_content (PG_FUNCTION_ARGS)

Variables

int xmlbinary
int xmloption

Define Documentation

#define NAMESPACE_SQLXML   "http://standards.iso.org/iso/9075/2003/sqlxml"

Definition at line 178 of file xml.c.

#define NAMESPACE_XSD   "http://www.w3.org/2001/XMLSchema"

Definition at line 176 of file xml.c.

Referenced by xsd_schema_element_start().

#define NAMESPACE_XSI   "http://www.w3.org/2001/XMLSchema-instance"

Definition at line 177 of file xml.c.

Referenced by xmldata_root_element_start().

#define NO_XML_SUPPORT (  ) 
Value:
ereport(ERROR, \
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), \
             errmsg("unsupported XML feature"), \
             errdetail("This functionality requires the server to be built with libxml support."), \
             errhint("You need to rebuild PostgreSQL using --with-libxml.")))

Definition at line 167 of file xml.c.

Referenced by map_sql_identifier_to_xml_name(), xml_in(), xml_is_document(), xml_is_well_formed(), xml_is_well_formed_content(), xml_is_well_formed_document(), xml_recv(), xmlcomment(), xmlconcat(), xmlelement(), xmlexists(), xmlparse(), xmlpi(), xmlroot(), xpath(), and xpath_exists().

#define PG_XML_DEFAULT_VERSION   "1.0"

Definition at line 230 of file xml.c.

#define XML_VISIBLE_SCHEMAS   "SELECT oid FROM pg_catalog.pg_namespace WHERE pg_catalog.has_schema_privilege (oid, 'USAGE') AND NOT " XML_VISIBLE_SCHEMAS_EXCLUDE

Definition at line 2306 of file xml.c.

Referenced by database_get_xml_visible_schemas(), and database_get_xml_visible_tables().

#define XML_VISIBLE_SCHEMAS_EXCLUDE   "(nspname ~ '^pg_' OR nspname = 'information_schema')"

Definition at line 2304 of file xml.c.


Function Documentation

static char* _SPI_strdup ( const char *  s  )  [static]

Definition at line 2207 of file xml.c.

References SPI_palloc().

Referenced by cursor_to_xmlschema(), query_to_xml_and_xmlschema(), and query_to_xmlschema().

{
    size_t      len = strlen(s) + 1;
    char       *ret = SPI_palloc(len);

    memcpy(ret, s, len);
    return ret;
}

static xmltype* cstring_to_xmltype ( const char *  string  )  [static]

Definition at line 405 of file xml.c.

References cstring_to_text().

Referenced by cursor_to_xmlschema(), query_to_xmlschema(), and table_to_xmlschema().

{
    return (xmltype *) cstring_to_text(string);
}

Datum cursor_to_xml ( PG_FUNCTION_ARGS   ) 

Definition at line 2375 of file xml.c.

References ereport, errcode(), errmsg(), ERROR, i, initStringInfo(), NULL, PG_GETARG_BOOL, PG_GETARG_INT32, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, SPI_connect(), SPI_cursor_fetch(), SPI_cursor_find(), SPI_finish(), SPI_processed, SPI_sql_row_to_xmlelement(), stringinfo_to_xmltype(), and text_to_cstring().

{
    char       *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
    int32       count = PG_GETARG_INT32(1);
    bool        nulls = PG_GETARG_BOOL(2);
    bool        tableforest = PG_GETARG_BOOL(3);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(4));

    StringInfoData result;
    Portal      portal;
    int         i;

    initStringInfo(&result);

    SPI_connect();
    portal = SPI_cursor_find(name);
    if (portal == NULL)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_CURSOR),
                 errmsg("cursor \"%s\" does not exist", name)));

    SPI_cursor_fetch(portal, true, count);
    for (i = 0; i < SPI_processed; i++)
        SPI_sql_row_to_xmlelement(i, &result, NULL, nulls,
                                  tableforest, targetns, true);

    SPI_finish();

    PG_RETURN_XML_P(stringinfo_to_xmltype(&result));
}

Datum cursor_to_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2547 of file xml.c.

References _SPI_strdup(), cstring_to_xmltype(), ereport, errcode(), errmsg(), ERROR, InvalidOid, map_sql_table_to_xmlschema(), NULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, SPI_connect(), SPI_cursor_find(), SPI_finish(), text_to_cstring(), and PortalData::tupDesc.

{
    char       *name = text_to_cstring(PG_GETARG_TEXT_PP(0));
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
    const char *xmlschema;
    Portal      portal;

    SPI_connect();
    portal = SPI_cursor_find(name);
    if (portal == NULL)
        ereport(ERROR,
                (errcode(ERRCODE_UNDEFINED_CURSOR),
                 errmsg("cursor \"%s\" does not exist", name)));

    xmlschema = _SPI_strdup(map_sql_table_to_xmlschema(portal->tupDesc,
                                                       InvalidOid, nulls,
                                                     tableforest, targetns));
    SPI_finish();

    PG_RETURN_XML_P(cstring_to_xmltype(xmlschema));
}

static List* database_get_xml_visible_schemas ( void   )  [static]

Definition at line 2310 of file xml.c.

References query_to_oid_list(), and XML_VISIBLE_SCHEMAS.

Referenced by database_to_xml_internal(), and database_to_xmlschema_internal().

{
    return query_to_oid_list(XML_VISIBLE_SCHEMAS " ORDER BY nspname;");
}

static List* database_get_xml_visible_tables ( void   )  [static]

Definition at line 2317 of file xml.c.

References query_to_oid_list(), and XML_VISIBLE_SCHEMAS.

Referenced by database_to_xmlschema_internal().

{
    /* At the moment there is no order required here. */
    return query_to_oid_list("SELECT oid FROM pg_catalog.pg_class WHERE relkind IN ('r', 'm', 'v') AND pg_catalog.has_table_privilege (pg_class.oid, 'SELECT') AND relnamespace IN (" XML_VISIBLE_SCHEMAS ");");
}

Datum database_to_xml ( PG_FUNCTION_ARGS   ) 

Definition at line 2854 of file xml.c.

References database_to_xml_internal(), NULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, stringinfo_to_xmltype(), and text_to_cstring().

{
    bool        nulls = PG_GETARG_BOOL(0);
    bool        tableforest = PG_GETARG_BOOL(1);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(2));

    PG_RETURN_XML_P(stringinfo_to_xmltype(database_to_xml_internal(NULL, nulls,
                                                    tableforest, targetns)));
}

Datum database_to_xml_and_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2921 of file xml.c.

References StringInfoData::data, database_to_xml_internal(), database_to_xmlschema_internal(), PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, stringinfo_to_xmltype(), and text_to_cstring().

{
    bool        nulls = PG_GETARG_BOOL(0);
    bool        tableforest = PG_GETARG_BOOL(1);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(2));
    StringInfo  xmlschema;

    xmlschema = database_to_xmlschema_internal(nulls, tableforest, targetns);

    PG_RETURN_XML_P(stringinfo_to_xmltype(database_to_xml_internal(xmlschema->data,
                                             nulls, tableforest, targetns)));
}

static StringInfo database_to_xml_internal ( const char *  xmlschema,
bool  nulls,
bool  tableforest,
const char *  targetns 
) [static]

Definition at line 2808 of file xml.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), StringInfoData::data, database_get_xml_visible_schemas(), get_database_name(), lfirst_oid, makeStringInfo(), map_sql_identifier_to_xml_name(), MyDatabaseId, NULL, schema_to_xml_internal(), SPI_connect(), SPI_finish(), SPI_pop(), SPI_push(), xmldata_root_element_end(), and xmldata_root_element_start().

Referenced by database_to_xml(), and database_to_xml_and_xmlschema().

{
    StringInfo  result;
    List       *nspid_list;
    ListCell   *cell;
    char       *xmlcn;

    xmlcn = map_sql_identifier_to_xml_name(get_database_name(MyDatabaseId),
                                           true, false);
    result = makeStringInfo();

    xmldata_root_element_start(result, xmlcn, xmlschema, targetns, true);
    appendStringInfoString(result, "\n");

    if (xmlschema)
        appendStringInfo(result, "%s\n\n", xmlschema);

    SPI_connect();

    nspid_list = database_get_xml_visible_schemas();

    SPI_push();

    foreach(cell, nspid_list)
    {
        Oid         nspid = lfirst_oid(cell);
        StringInfo  subres;

        subres = schema_to_xml_internal(nspid, NULL, nulls,
                                        tableforest, targetns, false);

        appendStringInfoString(result, subres->data);
        appendStringInfoChar(result, '\n');
    }

    SPI_pop();
    SPI_finish();

    xmldata_root_element_end(result, xmlcn);

    return result;
}

Datum database_to_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2909 of file xml.c.

References database_to_xmlschema_internal(), PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, stringinfo_to_xmltype(), and text_to_cstring().

{
    bool        nulls = PG_GETARG_BOOL(0);
    bool        tableforest = PG_GETARG_BOOL(1);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(2));

    PG_RETURN_XML_P(stringinfo_to_xmltype(database_to_xmlschema_internal(nulls,
                                                    tableforest, targetns)));
}

static StringInfo database_to_xmlschema_internal ( bool  nulls,
bool  tableforest,
const char *  targetns 
) [static]
char* escape_xml ( const char *  str  ) 

Definition at line 2175 of file xml.c.

References appendStringInfoCharMacro, appendStringInfoString(), StringInfoData::data, and initStringInfo().

Referenced by ExplainProperty(), ExplainPropertyList(), and map_sql_value_to_xml_value().

{
    StringInfoData buf;
    const char *p;

    initStringInfo(&buf);
    for (p = str; *p; p++)
    {
        switch (*p)
        {
            case '&':
                appendStringInfoString(&buf, "&amp;");
                break;
            case '<':
                appendStringInfoString(&buf, "&lt;");
                break;
            case '>':
                appendStringInfoString(&buf, "&gt;");
                break;
            case '\r':
                appendStringInfoString(&buf, "&#x0d;");
                break;
            default:
                appendStringInfoCharMacro(&buf, *p);
                break;
        }
    }
    return buf.data;
}

static char* map_multipart_sql_identifier_to_xml_name ( char *  a,
char *  b,
char *  c,
char *  d 
) [static]
static const char * map_sql_catalog_to_xmlschema_types ( List nspid_list,
bool  nulls,
bool  tableforest,
const char *  targetns 
) [static]

Definition at line 3147 of file xml.c.

References appendStringInfo(), appendStringInfoString(), StringInfoData::data, get_database_name(), get_namespace_name(), initStringInfo(), lfirst_oid, map_multipart_sql_identifier_to_xml_name(), map_sql_identifier_to_xml_name(), MyDatabaseId, and NULL.

Referenced by database_to_xmlschema_internal().

{
    char       *dbname;
    char       *xmlcn;
    char       *catalogtypename;
    StringInfoData result;
    ListCell   *cell;

    dbname = get_database_name(MyDatabaseId);

    initStringInfo(&result);

    xmlcn = map_sql_identifier_to_xml_name(dbname, true, false);

    catalogtypename = map_multipart_sql_identifier_to_xml_name("CatalogType",
                                                               dbname,
                                                               NULL,
                                                               NULL);

    appendStringInfo(&result,
                     "<xsd:complexType name=\"%s\">\n", catalogtypename);
    appendStringInfoString(&result,
                           "  <xsd:all>\n");

    foreach(cell, nspid_list)
    {
        Oid         nspid = lfirst_oid(cell);
        char       *nspname = get_namespace_name(nspid);
        char       *xmlsn = map_sql_identifier_to_xml_name(nspname, true, false);
        char       *schematypename = map_multipart_sql_identifier_to_xml_name("SchemaType",
                                                                      dbname,
                                                                     nspname,
                                                                       NULL);

        appendStringInfo(&result,
                         "    <xsd:element name=\"%s\" type=\"%s\"/>\n",
                         xmlsn, schematypename);
    }

    appendStringInfoString(&result,
                           "  </xsd:all>\n");
    appendStringInfoString(&result,
                           "</xsd:complexType>\n\n");

    appendStringInfo(&result,
                     "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
                     xmlcn, catalogtypename);

    return result.data;
}

char* map_sql_identifier_to_xml_name ( char *  ident,
bool  fully_escaped,
bool  escape_period 
)

Definition at line 1836 of file xml.c.

References appendBinaryStringInfo(), appendStringInfo(), Assert, StringInfoData::data, initStringInfo(), NO_XML_SUPPORT, pg_mblen(), and pg_strncasecmp().

Referenced by database_to_xml_internal(), map_multipart_sql_identifier_to_xml_name(), map_sql_catalog_to_xmlschema_types(), map_sql_schema_to_xmlschema_types(), map_sql_table_to_xmlschema(), query_to_xml_internal(), schema_to_xml_internal(), SPI_sql_row_to_xmlelement(), and transformXmlExpr().

{
#ifdef USE_LIBXML
    StringInfoData buf;
    char       *p;

    /*
     * SQL/XML doesn't make use of this case anywhere, so it's probably a
     * mistake.
     */
    Assert(fully_escaped || !escape_period);

    initStringInfo(&buf);

    for (p = ident; *p; p += pg_mblen(p))
    {
        if (*p == ':' && (p == ident || fully_escaped))
            appendStringInfo(&buf, "_x003A_");
        else if (*p == '_' && *(p + 1) == 'x')
            appendStringInfo(&buf, "_x005F_");
        else if (fully_escaped && p == ident &&
                 pg_strncasecmp(p, "xml", 3) == 0)
        {
            if (*p == 'x')
                appendStringInfo(&buf, "_x0078_");
            else
                appendStringInfo(&buf, "_x0058_");
        }
        else if (escape_period && *p == '.')
            appendStringInfo(&buf, "_x002E_");
        else
        {
            pg_wchar    u = sqlchar_to_unicode(p);

            if ((p == ident)
                ? !is_valid_xml_namefirst(u)
                : !is_valid_xml_namechar(u))
                appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
            else
                appendBinaryStringInfo(&buf, p, pg_mblen(p));
        }
    }

    return buf.data;
#else                           /* not USE_LIBXML */
    NO_XML_SUPPORT();
    return NULL;
#endif   /* not USE_LIBXML */
}

static const char * map_sql_schema_to_xmlschema_types ( Oid  nspid,
List relid_list,
bool  nulls,
bool  tableforest,
const char *  targetns 
) [static]

Definition at line 3074 of file xml.c.

References appendStringInfo(), appendStringInfoString(), StringInfoData::data, get_database_name(), get_namespace_name(), get_rel_name(), initStringInfo(), lfirst_oid, map_multipart_sql_identifier_to_xml_name(), map_sql_identifier_to_xml_name(), MyDatabaseId, and NULL.

Referenced by schema_to_xmlschema_internal().

{
    char       *dbname;
    char       *nspname;
    char       *xmlsn;
    char       *schematypename;
    StringInfoData result;
    ListCell   *cell;

    dbname = get_database_name(MyDatabaseId);
    nspname = get_namespace_name(nspid);

    initStringInfo(&result);

    xmlsn = map_sql_identifier_to_xml_name(nspname, true, false);

    schematypename = map_multipart_sql_identifier_to_xml_name("SchemaType",
                                                              dbname,
                                                              nspname,
                                                              NULL);

    appendStringInfo(&result,
                     "<xsd:complexType name=\"%s\">\n", schematypename);
    if (!tableforest)
        appendStringInfoString(&result,
                               "  <xsd:all>\n");
    else
        appendStringInfoString(&result,
                               "  <xsd:sequence>\n");

    foreach(cell, relid_list)
    {
        Oid         relid = lfirst_oid(cell);
        char       *relname = get_rel_name(relid);
        char       *xmltn = map_sql_identifier_to_xml_name(relname, true, false);
        char       *tabletypename = map_multipart_sql_identifier_to_xml_name(tableforest ? "RowType" : "TableType",
                                                                      dbname,
                                                                     nspname,
                                                                    relname);

        if (!tableforest)
            appendStringInfo(&result,
                             "    <xsd:element name=\"%s\" type=\"%s\"/>\n",
                             xmltn, tabletypename);
        else
            appendStringInfo(&result,
                             "    <xsd:element name=\"%s\" type=\"%s\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n",
                             xmltn, tabletypename);
    }

    if (!tableforest)
        appendStringInfoString(&result,
                               "  </xsd:all>\n");
    else
        appendStringInfoString(&result,
                               "  </xsd:sequence>\n");
    appendStringInfoString(&result,
                           "</xsd:complexType>\n\n");

    appendStringInfo(&result,
                     "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
                     xmlsn, schematypename);

    return result.data;
}

static const char * map_sql_table_to_xmlschema ( TupleDesc  tupdesc,
Oid  relid,
bool  nulls,
bool  tableforest,
const char *  targetns 
) [static]

Definition at line 2971 of file xml.c.

References appendStringInfo(), appendStringInfoString(), tupleDesc::attrs, StringInfoData::data, elog, ERROR, get_database_name(), get_namespace_name(), GETSTRUCT, HeapTupleIsValid, i, initStringInfo(), list_make1, map_multipart_sql_identifier_to_xml_name(), map_sql_identifier_to_xml_name(), map_sql_type_to_xml_name(), map_sql_typecoll_to_xmlschema_types(), MyDatabaseId, NameStr, tupleDesc::natts, ObjectIdGetDatum, OidIsValid, ReleaseSysCache(), RELOID, SearchSysCache1, xsd_schema_element_end(), and xsd_schema_element_start().

Referenced by cursor_to_xmlschema(), query_to_xml_and_xmlschema(), query_to_xmlschema(), table_to_xml_and_xmlschema(), and table_to_xmlschema().

{
    int         i;
    char       *xmltn;
    char       *tabletypename;
    char       *rowtypename;
    StringInfoData result;

    initStringInfo(&result);

    if (OidIsValid(relid))
    {
        HeapTuple   tuple;
        Form_pg_class reltuple;

        tuple = SearchSysCache1(RELOID, ObjectIdGetDatum(relid));
        if (!HeapTupleIsValid(tuple))
            elog(ERROR, "cache lookup failed for relation %u", relid);
        reltuple = (Form_pg_class) GETSTRUCT(tuple);

        xmltn = map_sql_identifier_to_xml_name(NameStr(reltuple->relname),
                                               true, false);

        tabletypename = map_multipart_sql_identifier_to_xml_name("TableType",
                                             get_database_name(MyDatabaseId),
                                  get_namespace_name(reltuple->relnamespace),
                                                 NameStr(reltuple->relname));

        rowtypename = map_multipart_sql_identifier_to_xml_name("RowType",
                                             get_database_name(MyDatabaseId),
                                  get_namespace_name(reltuple->relnamespace),
                                                 NameStr(reltuple->relname));

        ReleaseSysCache(tuple);
    }
    else
    {
        if (tableforest)
            xmltn = "row";
        else
            xmltn = "table";

        tabletypename = "TableType";
        rowtypename = "RowType";
    }

    xsd_schema_element_start(&result, targetns);

    appendStringInfoString(&result,
                   map_sql_typecoll_to_xmlschema_types(list_make1(tupdesc)));

    appendStringInfo(&result,
                     "<xsd:complexType name=\"%s\">\n"
                     "  <xsd:sequence>\n",
                     rowtypename);

    for (i = 0; i < tupdesc->natts; i++)
    {
        if (tupdesc->attrs[i]->attisdropped)
            continue;
        appendStringInfo(&result,
               "    <xsd:element name=\"%s\" type=\"%s\"%s></xsd:element>\n",
          map_sql_identifier_to_xml_name(NameStr(tupdesc->attrs[i]->attname),
                                         true, false),
                   map_sql_type_to_xml_name(tupdesc->attrs[i]->atttypid, -1),
                         nulls ? " nillable=\"true\"" : " minOccurs=\"0\"");
    }

    appendStringInfoString(&result,
                           "  </xsd:sequence>\n"
                           "</xsd:complexType>\n\n");

    if (!tableforest)
    {
        appendStringInfo(&result,
                         "<xsd:complexType name=\"%s\">\n"
                         "  <xsd:sequence>\n"
                         "    <xsd:element name=\"row\" type=\"%s\" minOccurs=\"0\" maxOccurs=\"unbounded\"/>\n"
                         "  </xsd:sequence>\n"
                         "</xsd:complexType>\n\n",
                         tabletypename, rowtypename);

        appendStringInfo(&result,
                         "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
                         xmltn, tabletypename);
    }
    else
        appendStringInfo(&result,
                         "<xsd:element name=\"%s\" type=\"%s\"/>\n\n",
                         xmltn, rowtypename);

    xsd_schema_element_end(&result);

    return result.data;
}

static const char * map_sql_type_to_xml_name ( Oid  typeoid,
int  typmod 
) [static]

Definition at line 3204 of file xml.c.

References appendStringInfo(), appendStringInfoString(), BOOLOID, BPCHAROID, StringInfoData::data, DATEOID, elog, ERROR, FLOAT4OID, FLOAT8OID, get_database_name(), get_namespace_name(), GETSTRUCT, HeapTupleIsValid, initStringInfo(), INT2OID, INT4OID, INT8OID, map_multipart_sql_identifier_to_xml_name(), MyDatabaseId, NameStr, NUMERICOID, ObjectIdGetDatum, ReleaseSysCache(), SearchSysCache1, TIMEOID, TIMESTAMPOID, TIMESTAMPTZOID, TIMETZOID, TYPEOID, TYPTYPE_DOMAIN, VARCHAROID, VARHDRSZ, and XMLOID.

Referenced by map_sql_table_to_xmlschema(), and map_sql_type_to_xmlschema_type().

{
    StringInfoData result;

    initStringInfo(&result);

    switch (typeoid)
    {
        case BPCHAROID:
            if (typmod == -1)
                appendStringInfo(&result, "CHAR");
            else
                appendStringInfo(&result, "CHAR_%d", typmod - VARHDRSZ);
            break;
        case VARCHAROID:
            if (typmod == -1)
                appendStringInfo(&result, "VARCHAR");
            else
                appendStringInfo(&result, "VARCHAR_%d", typmod - VARHDRSZ);
            break;
        case NUMERICOID:
            if (typmod == -1)
                appendStringInfo(&result, "NUMERIC");
            else
                appendStringInfo(&result, "NUMERIC_%d_%d",
                                 ((typmod - VARHDRSZ) >> 16) & 0xffff,
                                 (typmod - VARHDRSZ) & 0xffff);
            break;
        case INT4OID:
            appendStringInfo(&result, "INTEGER");
            break;
        case INT2OID:
            appendStringInfo(&result, "SMALLINT");
            break;
        case INT8OID:
            appendStringInfo(&result, "BIGINT");
            break;
        case FLOAT4OID:
            appendStringInfo(&result, "REAL");
            break;
        case FLOAT8OID:
            appendStringInfo(&result, "DOUBLE");
            break;
        case BOOLOID:
            appendStringInfo(&result, "BOOLEAN");
            break;
        case TIMEOID:
            if (typmod == -1)
                appendStringInfo(&result, "TIME");
            else
                appendStringInfo(&result, "TIME_%d", typmod);
            break;
        case TIMETZOID:
            if (typmod == -1)
                appendStringInfo(&result, "TIME_WTZ");
            else
                appendStringInfo(&result, "TIME_WTZ_%d", typmod);
            break;
        case TIMESTAMPOID:
            if (typmod == -1)
                appendStringInfo(&result, "TIMESTAMP");
            else
                appendStringInfo(&result, "TIMESTAMP_%d", typmod);
            break;
        case TIMESTAMPTZOID:
            if (typmod == -1)
                appendStringInfo(&result, "TIMESTAMP_WTZ");
            else
                appendStringInfo(&result, "TIMESTAMP_WTZ_%d", typmod);
            break;
        case DATEOID:
            appendStringInfo(&result, "DATE");
            break;
        case XMLOID:
            appendStringInfo(&result, "XML");
            break;
        default:
            {
                HeapTuple   tuple;
                Form_pg_type typtuple;

                tuple = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeoid));
                if (!HeapTupleIsValid(tuple))
                    elog(ERROR, "cache lookup failed for type %u", typeoid);
                typtuple = (Form_pg_type) GETSTRUCT(tuple);

                appendStringInfoString(&result,
                                       map_multipart_sql_identifier_to_xml_name((typtuple->typtype == TYPTYPE_DOMAIN) ? "Domain" : "UDT",
                                             get_database_name(MyDatabaseId),
                                  get_namespace_name(typtuple->typnamespace),
                                                NameStr(typtuple->typname)));

                ReleaseSysCache(tuple);
            }
    }

    return result.data;
}

static const char * map_sql_type_to_xmlschema_type ( Oid  typeoid,
int  typmod 
) [static]

Definition at line 3363 of file xml.c.

References appendStringInfo(), BOOLOID, BPCHAROID, BYTEAOID, StringInfoData::data, DATEOID, FLOAT4OID, FLOAT8OID, get_typtype(), getBaseTypeAndTypmod(), initStringInfo(), INT2OID, INT4OID, INT8OID, map_sql_type_to_xml_name(), NUMERICOID, TEXTOID, TIMEOID, TIMESTAMPOID, TIMESTAMPTZOID, TIMETZOID, TYPTYPE_DOMAIN, VARCHAROID, VARHDRSZ, xmlbinary, XMLBINARY_BASE64, and XMLOID.

Referenced by map_sql_typecoll_to_xmlschema_types().

{
    StringInfoData result;
    const char *typename = map_sql_type_to_xml_name(typeoid, typmod);

    initStringInfo(&result);

    if (typeoid == XMLOID)
    {
        appendStringInfo(&result,
                         "<xsd:complexType mixed=\"true\">\n"
                         "  <xsd:sequence>\n"
                         "    <xsd:any name=\"element\" minOccurs=\"0\" maxOccurs=\"unbounded\" processContents=\"skip\"/>\n"
                         "  </xsd:sequence>\n"
                         "</xsd:complexType>\n");
    }
    else
    {
        appendStringInfo(&result,
                         "<xsd:simpleType name=\"%s\">\n", typename);

        switch (typeoid)
        {
            case BPCHAROID:
            case VARCHAROID:
            case TEXTOID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:string\">\n");
                if (typmod != -1)
                    appendStringInfo(&result,
                                     "    <xsd:maxLength value=\"%d\"/>\n",
                                     typmod - VARHDRSZ);
                appendStringInfo(&result,
                                 "  </xsd:restriction>\n");
                break;

            case BYTEAOID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:%s\">\n"
                                 "  </xsd:restriction>\n",
                xmlbinary == XMLBINARY_BASE64 ? "base64Binary" : "hexBinary");
                break;

            case NUMERICOID:
                if (typmod != -1)
                    appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:decimal\">\n"
                                     "    <xsd:totalDigits value=\"%d\"/>\n"
                                   "    <xsd:fractionDigits value=\"%d\"/>\n"
                                     "  </xsd:restriction>\n",
                                     ((typmod - VARHDRSZ) >> 16) & 0xffff,
                                     (typmod - VARHDRSZ) & 0xffff);
                break;

            case INT2OID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:short\">\n"
                                 "    <xsd:maxInclusive value=\"%d\"/>\n"
                                 "    <xsd:minInclusive value=\"%d\"/>\n"
                                 "  </xsd:restriction>\n",
                                 SHRT_MAX, SHRT_MIN);
                break;

            case INT4OID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:int\">\n"
                                 "    <xsd:maxInclusive value=\"%d\"/>\n"
                                 "    <xsd:minInclusive value=\"%d\"/>\n"
                                 "  </xsd:restriction>\n",
                                 INT_MAX, INT_MIN);
                break;

            case INT8OID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:long\">\n"
                       "    <xsd:maxInclusive value=\"" INT64_FORMAT "\"/>\n"
                       "    <xsd:minInclusive value=\"" INT64_FORMAT "\"/>\n"
                                 "  </xsd:restriction>\n",
                               (((uint64) 1) << (sizeof(int64) * 8 - 1)) - 1,
                                 (((uint64) 1) << (sizeof(int64) * 8 - 1)));
                break;

            case FLOAT4OID:
                appendStringInfo(&result,
                "  <xsd:restriction base=\"xsd:float\"></xsd:restriction>\n");
                break;

            case FLOAT8OID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:double\"></xsd:restriction>\n");
                break;

            case BOOLOID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:boolean\"></xsd:restriction>\n");
                break;

            case TIMEOID:
            case TIMETZOID:
                {
                    const char *tz = (typeoid == TIMETZOID ? "(+|-)\\p{Nd}{2}:\\p{Nd}{2}" : "");

                    if (typmod == -1)
                        appendStringInfo(&result,
                                    "  <xsd:restriction base=\"xsd:time\">\n"
                                         "    <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}(.\\p{Nd}+)?%s\"/>\n"
                                         "  </xsd:restriction>\n", tz);
                    else if (typmod == 0)
                        appendStringInfo(&result,
                                    "  <xsd:restriction base=\"xsd:time\">\n"
                                         "    <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
                                         "  </xsd:restriction>\n", tz);
                    else
                        appendStringInfo(&result,
                                    "  <xsd:restriction base=\"xsd:time\">\n"
                                         "    <xsd:pattern value=\"\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}.\\p{Nd}{%d}%s\"/>\n"
                            "  </xsd:restriction>\n", typmod - VARHDRSZ, tz);
                    break;
                }

            case TIMESTAMPOID:
            case TIMESTAMPTZOID:
                {
                    const char *tz = (typeoid == TIMESTAMPTZOID ? "(+|-)\\p{Nd}{2}:\\p{Nd}{2}" : "");

                    if (typmod == -1)
                        appendStringInfo(&result,
                                "  <xsd:restriction base=\"xsd:dateTime\">\n"
                                         "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}(.\\p{Nd}+)?%s\"/>\n"
                                         "  </xsd:restriction>\n", tz);
                    else if (typmod == 0)
                        appendStringInfo(&result,
                                "  <xsd:restriction base=\"xsd:dateTime\">\n"
                                         "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}%s\"/>\n"
                                         "  </xsd:restriction>\n", tz);
                    else
                        appendStringInfo(&result,
                                "  <xsd:restriction base=\"xsd:dateTime\">\n"
                                         "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}T\\p{Nd}{2}:\\p{Nd}{2}:\\p{Nd}{2}.\\p{Nd}{%d}%s\"/>\n"
                            "  </xsd:restriction>\n", typmod - VARHDRSZ, tz);
                    break;
                }

            case DATEOID:
                appendStringInfo(&result,
                                 "  <xsd:restriction base=\"xsd:date\">\n"
                                 "    <xsd:pattern value=\"\\p{Nd}{4}-\\p{Nd}{2}-\\p{Nd}{2}\"/>\n"
                                 "  </xsd:restriction>\n");
                break;

            default:
                if (get_typtype(typeoid) == TYPTYPE_DOMAIN)
                {
                    Oid         base_typeoid;
                    int32       base_typmod = -1;

                    base_typeoid = getBaseTypeAndTypmod(typeoid, &base_typmod);

                    appendStringInfo(&result,
                                     "  <xsd:restriction base=\"%s\"/>\n",
                        map_sql_type_to_xml_name(base_typeoid, base_typmod));
                }
                break;
        }
        appendStringInfo(&result,
                         "</xsd:simpleType>\n");
    }

    return result.data;
}

static const char * map_sql_typecoll_to_xmlschema_types ( List tupdesc_list  )  [static]

Definition at line 3309 of file xml.c.

References appendStringInfo(), tupleDesc::attrs, StringInfoData::data, getBaseType(), i, initStringInfo(), lfirst, lfirst_oid, list_append_unique_oid(), map_sql_type_to_xmlschema_type(), and tupleDesc::natts.

Referenced by database_to_xmlschema_internal(), map_sql_table_to_xmlschema(), and schema_to_xmlschema_internal().

{
    List       *uniquetypes = NIL;
    int         i;
    StringInfoData result;
    ListCell   *cell0;

    /* extract all column types used in the set of TupleDescs */
    foreach(cell0, tupdesc_list)
    {
        TupleDesc   tupdesc = (TupleDesc) lfirst(cell0);

        for (i = 0; i < tupdesc->natts; i++)
        {
            if (tupdesc->attrs[i]->attisdropped)
                continue;
            uniquetypes = list_append_unique_oid(uniquetypes,
                                                 tupdesc->attrs[i]->atttypid);
        }
    }

    /* add base types of domains */
    foreach(cell0, uniquetypes)
    {
        Oid         typid = lfirst_oid(cell0);
        Oid         basetypid = getBaseType(typid);

        if (basetypid != typid)
            uniquetypes = list_append_unique_oid(uniquetypes, basetypid);
    }

    /* Convert to textual form */
    initStringInfo(&result);

    foreach(cell0, uniquetypes)
    {
        appendStringInfo(&result, "%s\n",
                         map_sql_type_to_xmlschema_type(lfirst_oid(cell0),
                                                        -1));
    }

    return result.data;
}

char* map_sql_value_to_xml_value ( Datum  value,
Oid  type,
bool  xml_escape_strings 
)

Definition at line 1956 of file xml.c.

References appendStringInfoString(), ARR_ELEMTYPE, BOOLOID, BYTEAOID, StringInfoData::data, DATE_NOT_FINITE, DATEOID, DatumGetArrayTypeP, DatumGetBool, DatumGetByteaPP, DatumGetDateADT, DatumGetTimestamp, deconstruct_array(), EncodeDateOnly(), EncodeDateTime(), ereport, errcode(), errdetail(), errmsg(), ERROR, escape_xml(), get_typlenbyvalalign(), getBaseType(), getTypeOutputInfo(), i, initStringInfo(), j2date(), map_sql_value_to_xml_value(), MAXDATELEN, NULL, OidOutputFunctionCall(), pfree(), PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, POSTGRES_EPOCH_JDATE, pstrdup(), timestamp2tm(), TIMESTAMP_NOT_FINITE, TIMESTAMPOID, TIMESTAMPTZOID, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, type_is_array_domain, USE_XSD_DATES, VARDATA_ANY, VARSIZE_ANY_EXHDR, xml_ereport(), xmlbinary, XMLBINARY_BASE64, and XMLOID.

Referenced by ExecEvalXml(), map_sql_value_to_xml_value(), SPI_sql_row_to_xmlelement(), and xmlelement().

{
    if (type_is_array_domain(type))
    {
        ArrayType  *array;
        Oid         elmtype;
        int16       elmlen;
        bool        elmbyval;
        char        elmalign;
        int         num_elems;
        Datum      *elem_values;
        bool       *elem_nulls;
        StringInfoData buf;
        int         i;

        array = DatumGetArrayTypeP(value);
        elmtype = ARR_ELEMTYPE(array);
        get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);

        deconstruct_array(array, elmtype,
                          elmlen, elmbyval, elmalign,
                          &elem_values, &elem_nulls,
                          &num_elems);

        initStringInfo(&buf);

        for (i = 0; i < num_elems; i++)
        {
            if (elem_nulls[i])
                continue;
            appendStringInfoString(&buf, "<element>");
            appendStringInfoString(&buf,
                                   map_sql_value_to_xml_value(elem_values[i],
                                                              elmtype, true));
            appendStringInfoString(&buf, "</element>");
        }

        pfree(elem_values);
        pfree(elem_nulls);

        return buf.data;
    }
    else
    {
        Oid         typeOut;
        bool        isvarlena;
        char       *str;

        /*
         * Flatten domains; the special-case treatments below should apply
         * to, eg, domains over boolean not just boolean.
         */
        type = getBaseType(type);

        /*
         * Special XSD formatting for some data types
         */
        switch (type)
        {
            case BOOLOID:
                if (DatumGetBool(value))
                    return "true";
                else
                    return "false";

            case DATEOID:
                {
                    DateADT     date;
                    struct pg_tm tm;
                    char        buf[MAXDATELEN + 1];

                    date = DatumGetDateADT(value);
                    /* XSD doesn't support infinite values */
                    if (DATE_NOT_FINITE(date))
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("date out of range"),
                                 errdetail("XML does not support infinite date values.")));
                    j2date(date + POSTGRES_EPOCH_JDATE,
                           &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
                    EncodeDateOnly(&tm, USE_XSD_DATES, buf);

                    return pstrdup(buf);
                }

            case TIMESTAMPOID:
                {
                    Timestamp   timestamp;
                    struct pg_tm tm;
                    fsec_t      fsec;
                    char        buf[MAXDATELEN + 1];

                    timestamp = DatumGetTimestamp(value);

                    /* XSD doesn't support infinite values */
                    if (TIMESTAMP_NOT_FINITE(timestamp))
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range"),
                                 errdetail("XML does not support infinite timestamp values.")));
                    else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
                        EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
                    else
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range")));

                    return pstrdup(buf);
                }

            case TIMESTAMPTZOID:
                {
                    TimestampTz timestamp;
                    struct pg_tm tm;
                    int         tz;
                    fsec_t      fsec;
                    const char *tzn = NULL;
                    char        buf[MAXDATELEN + 1];

                    timestamp = DatumGetTimestamp(value);

                    /* XSD doesn't support infinite values */
                    if (TIMESTAMP_NOT_FINITE(timestamp))
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range"),
                                 errdetail("XML does not support infinite timestamp values.")));
                    else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
                        EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
                    else
                        ereport(ERROR,
                                (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
                                 errmsg("timestamp out of range")));

                    return pstrdup(buf);
                }

#ifdef USE_LIBXML
            case BYTEAOID:
                {
                    bytea      *bstr = DatumGetByteaPP(value);
                    PgXmlErrorContext *xmlerrcxt;
                    volatile xmlBufferPtr buf = NULL;
                    volatile xmlTextWriterPtr writer = NULL;
                    char       *result;

                    xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);

                    PG_TRY();
                    {
                        buf = xmlBufferCreate();
                        if (buf == NULL || xmlerrcxt->err_occurred)
                            xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
                                        "could not allocate xmlBuffer");
                        writer = xmlNewTextWriterMemory(buf, 0);
                        if (writer == NULL || xmlerrcxt->err_occurred)
                            xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
                                        "could not allocate xmlTextWriter");

                        if (xmlbinary == XMLBINARY_BASE64)
                            xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
                                                 0, VARSIZE_ANY_EXHDR(bstr));
                        else
                            xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
                                                 0, VARSIZE_ANY_EXHDR(bstr));

                        /* we MUST do this now to flush data out to the buffer */
                        xmlFreeTextWriter(writer);
                        writer = NULL;

                        result = pstrdup((const char *) xmlBufferContent(buf));
                    }
                    PG_CATCH();
                    {
                        if (writer)
                            xmlFreeTextWriter(writer);
                        if (buf)
                            xmlBufferFree(buf);

                        pg_xml_done(xmlerrcxt, true);

                        PG_RE_THROW();
                    }
                    PG_END_TRY();

                    xmlBufferFree(buf);

                    pg_xml_done(xmlerrcxt, false);

                    return result;
                }
#endif   /* USE_LIBXML */

        }

        /*
         * otherwise, just use the type's native text representation
         */
        getTypeOutputInfo(type, &typeOut, &isvarlena);
        str = OidOutputFunctionCall(typeOut, value);

        /* ... exactly as-is for XML, and when escaping is not wanted */
        if (type == XMLOID || !xml_escape_strings)
            return str;

        /* otherwise, translate special characters as needed */
        return escape_xml(str);
    }
}

char* map_xml_name_to_sql_identifier ( char *  name  ) 

Definition at line 1916 of file xml.c.

References appendBinaryStringInfo(), appendStringInfoString(), StringInfoData::data, initStringInfo(), pg_mblen(), and unicode_to_sqlchar().

Referenced by get_rule_expr().

{
    StringInfoData buf;
    char       *p;

    initStringInfo(&buf);

    for (p = name; *p; p += pg_mblen(p))
    {
        if (*p == '_' && *(p + 1) == 'x'
            && isxdigit((unsigned char) *(p + 2))
            && isxdigit((unsigned char) *(p + 3))
            && isxdigit((unsigned char) *(p + 4))
            && isxdigit((unsigned char) *(p + 5))
            && *(p + 6) == '_')
        {
            unsigned int u;

            sscanf(p + 2, "%X", &u);
            appendStringInfoString(&buf, unicode_to_sqlchar(u));
            p += 6;
        }
        else
            appendBinaryStringInfo(&buf, p, pg_mblen(p));
    }

    return buf.data;
}

static List* query_to_oid_list ( const char *  query  )  [static]

Definition at line 2264 of file xml.c.

References DatumGetObjectId, i, lappend_oid(), sort-test::list, SPI_execute(), SPI_getbinval(), SPI_processed, SPI_tuptable, SPITupleTable::tupdesc, and SPITupleTable::vals.

Referenced by database_get_xml_visible_schemas(), database_get_xml_visible_tables(), and schema_get_xml_visible_tables().

{
    int         i;
    List       *list = NIL;

    SPI_execute(query, true, 0);

    for (i = 0; i < SPI_processed; i++)
    {
        Datum       oid;
        bool        isnull;

        oid = SPI_getbinval(SPI_tuptable->vals[i],
                            SPI_tuptable->tupdesc,
                            1,
                            &isnull);
        if (!isnull)
            list = lappend_oid(list, DatumGetObjectId(oid));
    }

    return list;
}

Datum query_to_xml ( PG_FUNCTION_ARGS   ) 

Definition at line 2361 of file xml.c.

References NULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, query_to_xml_internal(), stringinfo_to_xmltype(), and text_to_cstring().

{
    char       *query = text_to_cstring(PG_GETARG_TEXT_PP(0));
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));

    PG_RETURN_XML_P(stringinfo_to_xmltype(query_to_xml_internal(query, NULL,
                                                    NULL, nulls, tableforest,
                                                           targetns, true)));
}

Datum query_to_xml_and_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2594 of file xml.c.

References _SPI_strdup(), elog, ERROR, InvalidOid, map_sql_table_to_xmlschema(), NULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, query_to_xml_internal(), SPI_connect(), SPI_cursor_close(), SPI_cursor_open(), SPI_finish(), SPI_prepare(), stringinfo_to_xmltype(), text_to_cstring(), and PortalData::tupDesc.

{
    char       *query = text_to_cstring(PG_GETARG_TEXT_PP(0));
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));

    const char *xmlschema;
    SPIPlanPtr  plan;
    Portal      portal;

    SPI_connect();

    if ((plan = SPI_prepare(query, 0, NULL)) == NULL)
        elog(ERROR, "SPI_prepare(\"%s\") failed", query);

    if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)
        elog(ERROR, "SPI_cursor_open(\"%s\") failed", query);

    xmlschema = _SPI_strdup(map_sql_table_to_xmlschema(portal->tupDesc,
                                  InvalidOid, nulls, tableforest, targetns));
    SPI_cursor_close(portal);
    SPI_finish();

    PG_RETURN_XML_P(stringinfo_to_xmltype(query_to_xml_internal(query, NULL,
                                               xmlschema, nulls, tableforest,
                                                           targetns, true)));
}

static StringInfo query_to_xml_internal ( const char *  query,
char *  tablename,
const char *  xmlschema,
bool  nulls,
bool  tableforest,
const char *  targetns,
bool  top_level 
) [static]

Definition at line 2454 of file xml.c.

References appendStringInfo(), appendStringInfoString(), ereport, errcode(), errmsg(), ERROR, i, makeStringInfo(), map_sql_identifier_to_xml_name(), SPI_connect(), SPI_execute(), SPI_finish(), SPI_OK_SELECT, SPI_processed, SPI_sql_row_to_xmlelement(), xmldata_root_element_end(), and xmldata_root_element_start().

Referenced by query_to_xml(), query_to_xml_and_xmlschema(), and table_to_xml_internal().

{
    StringInfo  result;
    char       *xmltn;
    int         i;

    if (tablename)
        xmltn = map_sql_identifier_to_xml_name(tablename, true, false);
    else
        xmltn = "table";

    result = makeStringInfo();

    SPI_connect();
    if (SPI_execute(query, true, 0) != SPI_OK_SELECT)
        ereport(ERROR,
                (errcode(ERRCODE_DATA_EXCEPTION),
                 errmsg("invalid query")));

    if (!tableforest)
    {
        xmldata_root_element_start(result, xmltn, xmlschema,
                                   targetns, top_level);
        appendStringInfoString(result, "\n");
    }

    if (xmlschema)
        appendStringInfo(result, "%s\n\n", xmlschema);

    for (i = 0; i < SPI_processed; i++)
        SPI_sql_row_to_xmlelement(i, result, tablename, nulls,
                                  tableforest, targetns, top_level);

    if (!tableforest)
        xmldata_root_element_end(result, xmltn);

    SPI_finish();

    return result;
}

Datum query_to_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2518 of file xml.c.

References _SPI_strdup(), cstring_to_xmltype(), elog, ERROR, InvalidOid, map_sql_table_to_xmlschema(), NULL, PG_GETARG_BOOL, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, SPI_connect(), SPI_cursor_close(), SPI_cursor_open(), SPI_finish(), SPI_prepare(), text_to_cstring(), and PortalData::tupDesc.

{
    char       *query = text_to_cstring(PG_GETARG_TEXT_PP(0));
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
    const char *result;
    SPIPlanPtr  plan;
    Portal      portal;

    SPI_connect();

    if ((plan = SPI_prepare(query, 0, NULL)) == NULL)
        elog(ERROR, "SPI_prepare(\"%s\") failed", query);

    if ((portal = SPI_cursor_open(NULL, plan, NULL, NULL, true)) == NULL)
        elog(ERROR, "SPI_cursor_open(\"%s\") failed", query);

    result = _SPI_strdup(map_sql_table_to_xmlschema(portal->tupDesc,
                                                    InvalidOid, nulls,
                                                    tableforest, targetns));
    SPI_cursor_close(portal);
    SPI_finish();

    PG_RETURN_XML_P(cstring_to_xmltype(result));
}

static List* schema_get_xml_visible_tables ( Oid  nspid  )  [static]

Definition at line 2289 of file xml.c.

References appendStringInfo(), StringInfoData::data, initStringInfo(), and query_to_oid_list().

Referenced by schema_to_xml_internal(), and schema_to_xmlschema_internal().

{
    StringInfoData query;

    initStringInfo(&query);
    appendStringInfo(&query, "SELECT oid FROM pg_catalog.pg_class WHERE relnamespace = %u AND relkind IN ('r', 'm', 'v') AND pg_catalog.has_table_privilege (oid, 'SELECT') ORDER BY relname;", nspid);

    return query_to_oid_list(query.data);
}

Datum schema_to_xml ( PG_FUNCTION_ARGS   ) 

Definition at line 2676 of file xml.c.

References LookupExplicitNamespace(), NameStr, NULL, PG_GETARG_BOOL, PG_GETARG_NAME, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, schema_to_xml_internal(), stringinfo_to_xmltype(), and text_to_cstring().

{
    Name        name = PG_GETARG_NAME(0);
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));

    char       *schemaname;
    Oid         nspid;

    schemaname = NameStr(*name);
    nspid = LookupExplicitNamespace(schemaname, false);

    PG_RETURN_XML_P(stringinfo_to_xmltype(schema_to_xml_internal(nspid, NULL,
                                       nulls, tableforest, targetns, true)));
}

Datum schema_to_xml_and_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2780 of file xml.c.

References StringInfoData::data, LookupExplicitNamespace(), NameStr, PG_GETARG_BOOL, PG_GETARG_NAME, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, schema_to_xml_internal(), schema_to_xmlschema_internal(), stringinfo_to_xmltype(), and text_to_cstring().

{
    Name        name = PG_GETARG_NAME(0);
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
    char       *schemaname;
    Oid         nspid;
    StringInfo  xmlschema;

    schemaname = NameStr(*name);
    nspid = LookupExplicitNamespace(schemaname, false);

    xmlschema = schema_to_xmlschema_internal(schemaname, nulls,
                                             tableforest, targetns);

    PG_RETURN_XML_P(stringinfo_to_xmltype(schema_to_xml_internal(nspid,
                                                      xmlschema->data, nulls,
                                              tableforest, targetns, true)));
}

static StringInfo schema_to_xml_internal ( Oid  nspid,
const char *  xmlschema,
bool  nulls,
bool  tableforest,
const char *  targetns,
bool  top_level 
) [static]

Definition at line 2630 of file xml.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), StringInfoData::data, get_namespace_name(), lfirst_oid, makeStringInfo(), map_sql_identifier_to_xml_name(), NULL, schema_get_xml_visible_tables(), SPI_connect(), SPI_finish(), SPI_pop(), SPI_push(), table_to_xml_internal(), xmldata_root_element_end(), and xmldata_root_element_start().

Referenced by database_to_xml_internal(), schema_to_xml(), and schema_to_xml_and_xmlschema().

{
    StringInfo  result;
    char       *xmlsn;
    List       *relid_list;
    ListCell   *cell;

    xmlsn = map_sql_identifier_to_xml_name(get_namespace_name(nspid),
                                           true, false);
    result = makeStringInfo();

    xmldata_root_element_start(result, xmlsn, xmlschema, targetns, top_level);
    appendStringInfoString(result, "\n");

    if (xmlschema)
        appendStringInfo(result, "%s\n\n", xmlschema);

    SPI_connect();

    relid_list = schema_get_xml_visible_tables(nspid);

    SPI_push();

    foreach(cell, relid_list)
    {
        Oid         relid = lfirst_oid(cell);
        StringInfo  subres;

        subres = table_to_xml_internal(relid, NULL, nulls, tableforest,
                                       targetns, false);

        appendStringInfoString(result, subres->data);
        appendStringInfoChar(result, '\n');
    }

    SPI_pop();
    SPI_finish();

    xmldata_root_element_end(result, xmlsn);

    return result;
}

Datum schema_to_xmlschema ( PG_FUNCTION_ARGS   ) 
static StringInfo schema_to_xmlschema_internal ( const char *  schemaname,
bool  nulls,
bool  tableforest,
const char *  targetns 
) [static]
static void SPI_sql_row_to_xmlelement ( int  rownum,
StringInfo  result,
char *  tablename,
bool  nulls,
bool  tableforest,
const char *  targetns,
bool  top_level 
) [static]

Definition at line 3540 of file xml.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), i, map_sql_identifier_to_xml_name(), map_sql_value_to_xml_value(), tupleDesc::natts, NULL, SPI_fname(), SPI_getbinval(), SPI_gettypeid(), SPI_tuptable, SPITupleTable::tupdesc, SPITupleTable::vals, xmldata_root_element_end(), and xmldata_root_element_start().

Referenced by cursor_to_xml(), and query_to_xml_internal().

{
    int         i;
    char       *xmltn;

    if (tablename)
        xmltn = map_sql_identifier_to_xml_name(tablename, true, false);
    else
    {
        if (tableforest)
            xmltn = "row";
        else
            xmltn = "table";
    }

    if (tableforest)
        xmldata_root_element_start(result, xmltn, NULL, targetns, top_level);
    else
        appendStringInfoString(result, "<row>\n");

    for (i = 1; i <= SPI_tuptable->tupdesc->natts; i++)
    {
        char       *colname;
        Datum       colval;
        bool        isnull;

        colname = map_sql_identifier_to_xml_name(SPI_fname(SPI_tuptable->tupdesc, i),
                                                 true, false);
        colval = SPI_getbinval(SPI_tuptable->vals[rownum],
                               SPI_tuptable->tupdesc,
                               i,
                               &isnull);
        if (isnull)
        {
            if (nulls)
                appendStringInfo(result, "  <%s xsi:nil=\"true\"/>\n", colname);
        }
        else
            appendStringInfo(result, "  <%s>%s</%s>\n",
                             colname,
                             map_sql_value_to_xml_value(colval,
                              SPI_gettypeid(SPI_tuptable->tupdesc, i), true),
                             colname);
    }

    if (tableforest)
    {
        xmldata_root_element_end(result, xmltn);
        appendStringInfoChar(result, '\n');
    }
    else
        appendStringInfoString(result, "</row>\n\n");
}

static xmltype* stringinfo_to_xmltype ( StringInfo  buf  )  [static]
Datum table_to_xml ( PG_FUNCTION_ARGS   ) 

Definition at line 2347 of file xml.c.

References NULL, PG_GETARG_BOOL, PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, stringinfo_to_xmltype(), table_to_xml_internal(), and text_to_cstring().

{
    Oid         relid = PG_GETARG_OID(0);
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));

    PG_RETURN_XML_P(stringinfo_to_xmltype(table_to_xml_internal(relid, NULL,
                                                          nulls, tableforest,
                                                           targetns, true)));
}

Datum table_to_xml_and_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2573 of file xml.c.

References AccessShareLock, heap_close, heap_open(), map_sql_table_to_xmlschema(), NoLock, PG_GETARG_BOOL, PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, RelationData::rd_att, stringinfo_to_xmltype(), table_to_xml_internal(), and text_to_cstring().

{
    Oid         relid = PG_GETARG_OID(0);
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
    Relation    rel;
    const char *xmlschema;

    rel = heap_open(relid, AccessShareLock);
    xmlschema = map_sql_table_to_xmlschema(rel->rd_att, relid, nulls,
                                           tableforest, targetns);
    heap_close(rel, NoLock);

    PG_RETURN_XML_P(stringinfo_to_xmltype(table_to_xml_internal(relid,
                                               xmlschema, nulls, tableforest,
                                                           targetns, true)));
}

static StringInfo table_to_xml_internal ( Oid  relid,
const char *  xmlschema,
bool  nulls,
bool  tableforest,
const char *  targetns,
bool  top_level 
) [static]
Datum table_to_xmlschema ( PG_FUNCTION_ARGS   ) 

Definition at line 2499 of file xml.c.

References AccessShareLock, cstring_to_xmltype(), heap_close, heap_open(), map_sql_table_to_xmlschema(), NoLock, PG_GETARG_BOOL, PG_GETARG_OID, PG_GETARG_TEXT_PP, PG_RETURN_XML_P, RelationData::rd_att, and text_to_cstring().

{
    Oid         relid = PG_GETARG_OID(0);
    bool        nulls = PG_GETARG_BOOL(1);
    bool        tableforest = PG_GETARG_BOOL(2);
    const char *targetns = text_to_cstring(PG_GETARG_TEXT_PP(3));
    const char *result;
    Relation    rel;

    rel = heap_open(relid, AccessShareLock);
    result = map_sql_table_to_xmlschema(rel->rd_att, relid, nulls,
                                        tableforest, targetns);
    heap_close(rel, NoLock);

    PG_RETURN_XML_P(cstring_to_xmltype(result));
}

Datum texttoxml ( PG_FUNCTION_ARGS   ) 

Definition at line 547 of file xml.c.

References PG_GETARG_TEXT_P, PG_RETURN_XML_P, xmloption, and xmlparse().

{
    text       *data = PG_GETARG_TEXT_P(0);

    PG_RETURN_XML_P(xmlparse(data, xmloption, true));
}

static char* unicode_to_sqlchar ( pg_wchar  c  )  [static]

Definition at line 1892 of file xml.c.

References GetDatabaseEncoding(), pg_do_encoding_conversion(), pg_encoding_mblen(), PG_UTF8, pstrdup(), and unicode_to_utf8().

Referenced by map_xml_name_to_sql_identifier().

{
    unsigned char utf8string[5];    /* need room for trailing zero */
    char       *result;

    memset(utf8string, 0, sizeof(utf8string));
    unicode_to_utf8(c, utf8string);

    result = (char *) pg_do_encoding_conversion(utf8string,
                                                pg_encoding_mblen(PG_UTF8,
                                                        (char *) utf8string),
                                                PG_UTF8,
                                                GetDatabaseEncoding());
    /* if pg_do_encoding_conversion didn't strdup, we must */
    if (result == (char *) utf8string)
        result = pstrdup(result);
    return result;
}

Datum xml_in ( PG_FUNCTION_ARGS   ) 

Definition at line 206 of file xml.c.

References cstring_to_text(), GetDatabaseEncoding(), NO_XML_SUPPORT, PG_GETARG_CSTRING, PG_RETURN_XML_P, and xmloption.

{
#ifdef USE_LIBXML
    char       *s = PG_GETARG_CSTRING(0);
    xmltype    *vardata;
    xmlDocPtr   doc;

    vardata = (xmltype *) cstring_to_text(s);

    /*
     * Parse the data to check if it is well-formed XML data.  Assume that
     * ERROR occurred if parsing failed.
     */
    doc = xml_parse(vardata, xmloption, true, GetDatabaseEncoding());
    xmlFreeDoc(doc);

    PG_RETURN_XML_P(vardata);
#else
    NO_XML_SUPPORT();
    return 0;
#endif
}

bool xml_is_document ( xmltype arg  ) 

Definition at line 839 of file xml.c.

References CopyErrorData(), CurrentMemoryContext, FlushErrorState(), GetDatabaseEncoding(), MemoryContextSwitchTo(), NO_XML_SUPPORT, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, ErrorData::sqlerrcode, and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXml(), and xmltotext_with_xmloption().

{
#ifdef USE_LIBXML
    bool        result;
    volatile xmlDocPtr doc = NULL;
    MemoryContext ccxt = CurrentMemoryContext;

    /* We want to catch ereport(INVALID_XML_DOCUMENT) and return false */
    PG_TRY();
    {
        doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
                        GetDatabaseEncoding());
        result = true;
    }
    PG_CATCH();
    {
        ErrorData  *errdata;
        MemoryContext ecxt;

        ecxt = MemoryContextSwitchTo(ccxt);
        errdata = CopyErrorData();
        if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
        {
            FlushErrorState();
            result = false;
        }
        else
        {
            MemoryContextSwitchTo(ecxt);
            PG_RE_THROW();
        }
    }
    PG_END_TRY();

    if (doc)
        xmlFreeDoc(doc);

    return result;
#else                           /* not USE_LIBXML */
    NO_XML_SUPPORT();
    return false;
#endif   /* not USE_LIBXML */
}

Datum xml_is_well_formed ( PG_FUNCTION_ARGS   ) 

Definition at line 4036 of file xml.c.

References NO_XML_SUPPORT, NULL, PG_CATCH, PG_END_TRY, PG_GETARG_TEXT_P, PG_RE_THROW, PG_RETURN_BOOL, PG_TRY, pg_xml_done(), PG_XML_STRICTNESS_LEGACY, pgxml_parser_init(), VARDATA, VARSIZE, and xmloption.

{
#ifdef USE_LIBXML
    text       *data = PG_GETARG_TEXT_P(0);

    PG_RETURN_BOOL(wellformed_xml(data, xmloption));
#else
    NO_XML_SUPPORT();
    return 0;
#endif   /* not USE_LIBXML */
}

Datum xml_is_well_formed_content ( PG_FUNCTION_ARGS   ) 

Definition at line 4062 of file xml.c.

References NO_XML_SUPPORT, PG_GETARG_TEXT_P, PG_RETURN_BOOL, and XMLOPTION_CONTENT.

{
#ifdef USE_LIBXML
    text       *data = PG_GETARG_TEXT_P(0);

    PG_RETURN_BOOL(wellformed_xml(data, XMLOPTION_CONTENT));
#else
    NO_XML_SUPPORT();
    return 0;
#endif   /* not USE_LIBXML */
}

Datum xml_is_well_formed_document ( PG_FUNCTION_ARGS   ) 

Definition at line 4049 of file xml.c.

References NO_XML_SUPPORT, PG_GETARG_TEXT_P, PG_RETURN_BOOL, and XMLOPTION_DOCUMENT.

{
#ifdef USE_LIBXML
    text       *data = PG_GETARG_TEXT_P(0);

    PG_RETURN_BOOL(wellformed_xml(data, XMLOPTION_DOCUMENT));
#else
    NO_XML_SUPPORT();
    return 0;
#endif   /* not USE_LIBXML */
}

Datum xml_out ( PG_FUNCTION_ARGS   ) 

Definition at line 284 of file xml.c.

References PG_GETARG_XML_P, PG_RETURN_CSTRING, and xml_out_internal().

{
    xmltype    *x = PG_GETARG_XML_P(0);

    /*
     * xml_out removes the encoding property in all cases.  This is because we
     * cannot control from here whether the datum will be converted to a
     * different client encoding, so we'd do more harm than good by including
     * it.
     */
    PG_RETURN_CSTRING(xml_out_internal(x, 0));
}

static char* xml_out_internal ( xmltype x,
pg_enc  target_encoding 
) [static]

Definition at line 241 of file xml.c.

References appendStringInfoString(), buf, StringInfoData::data, initStringInfo(), NULL, pfree(), text_to_cstring(), and WARNING.

Referenced by xml_out(), and xml_send().

{
    char       *str = text_to_cstring((text *) x);

#ifdef USE_LIBXML
    size_t      len = strlen(str);
    xmlChar    *version;
    int         standalone;
    int         res_code;

    if ((res_code = parse_xml_decl((xmlChar *) str,
                                   &len, &version, NULL, &standalone)) == 0)
    {
        StringInfoData buf;

        initStringInfo(&buf);

        if (!print_xml_decl(&buf, version, target_encoding, standalone))
        {
            /*
             * If we are not going to produce an XML declaration, eat a single
             * newline in the original string to prevent empty first lines in
             * the output.
             */
            if (*(str + len) == '\n')
                len += 1;
        }
        appendStringInfoString(&buf, str + len);

        pfree(str);

        return buf.data;
    }

    xml_ereport_by_code(WARNING, ERRCODE_INTERNAL_ERROR,
                        "could not parse XML declaration in stored value",
                        res_code);
#endif
    return str;
}

Datum xml_recv ( PG_FUNCTION_ARGS   ) 

Definition at line 299 of file xml.c.

References buf, cstring_to_text(), StringInfoData::cursor, encoding, GetDatabaseEncoding(), StringInfoData::len, NO_XML_SUPPORT, NULL, palloc(), pfree(), pg_do_encoding_conversion(), PG_GETARG_POINTER, PG_RETURN_XML_P, pq_getmsgbytes(), SET_VARSIZE, VARDATA, VARHDRSZ, and xmloption.

{
#ifdef USE_LIBXML
    StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
    xmltype    *result;
    char       *str;
    char       *newstr;
    int         nbytes;
    xmlDocPtr   doc;
    xmlChar    *encodingStr = NULL;
    int         encoding;

    /*
     * Read the data in raw format. We don't know yet what the encoding is, as
     * that information is embedded in the xml declaration; so we have to
     * parse that before converting to server encoding.
     */
    nbytes = buf->len - buf->cursor;
    str = (char *) pq_getmsgbytes(buf, nbytes);

    /*
     * We need a null-terminated string to pass to parse_xml_decl().  Rather
     * than make a separate copy, make the temporary result one byte bigger
     * than it needs to be.
     */
    result = palloc(nbytes + 1 + VARHDRSZ);
    SET_VARSIZE(result, nbytes + VARHDRSZ);
    memcpy(VARDATA(result), str, nbytes);
    str = VARDATA(result);
    str[nbytes] = '\0';

    parse_xml_decl((const xmlChar *) str, NULL, NULL, &encodingStr, NULL);

    /*
     * If encoding wasn't explicitly specified in the XML header, treat it as
     * UTF-8, as that's the default in XML. This is different from xml_in(),
     * where the input has to go through the normal client to server encoding
     * conversion.
     */
    encoding = encodingStr ? xmlChar_to_encoding(encodingStr) : PG_UTF8;

    /*
     * Parse the data to check if it is well-formed XML data.  Assume that
     * xml_parse will throw ERROR if not.
     */
    doc = xml_parse(result, xmloption, true, encoding);
    xmlFreeDoc(doc);

    /* Now that we know what we're dealing with, convert to server encoding */
    newstr = (char *) pg_do_encoding_conversion((unsigned char *) str,
                                                nbytes,
                                                encoding,
                                                GetDatabaseEncoding());

    if (newstr != str)
    {
        pfree(result);
        result = (xmltype *) cstring_to_text(newstr);
        pfree(newstr);
    }

    PG_RETURN_XML_P(result);
#else
    NO_XML_SUPPORT();
    return 0;
#endif
}

Datum xml_send ( PG_FUNCTION_ARGS   ) 

Definition at line 369 of file xml.c.

References buf, pfree(), pg_get_client_encoding(), PG_GETARG_XML_P, PG_RETURN_BYTEA_P, pq_begintypsend(), pq_endtypsend(), pq_sendtext(), and xml_out_internal().

{
    xmltype    *x = PG_GETARG_XML_P(0);
    char       *outval;
    StringInfoData buf;

    /*
     * xml_out_internal doesn't convert the encoding, it just prints the right
     * declaration. pq_sendtext will do the conversion.
     */
    outval = xml_out_internal(x, pg_get_client_encoding());

    pq_begintypsend(&buf);
    pq_sendtext(&buf, outval, strlen(outval));
    pfree(outval);
    PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}

Datum xmlcomment ( PG_FUNCTION_ARGS   ) 

Definition at line 422 of file xml.c.

References appendStringInfo(), appendStringInfoText(), arg, ereport, errcode(), errmsg(), ERROR, i, initStringInfo(), NO_XML_SUPPORT, PG_GETARG_TEXT_P, PG_RETURN_XML_P, stringinfo_to_xmltype(), VARDATA, and VARSIZE.

{
#ifdef USE_LIBXML
    text       *arg = PG_GETARG_TEXT_P(0);
    char       *argdata = VARDATA(arg);
    int         len = VARSIZE(arg) - VARHDRSZ;
    StringInfoData buf;
    int         i;

    /* check for "--" in string or "-" at the end */
    for (i = 1; i < len; i++)
    {
        if (argdata[i] == '-' && argdata[i - 1] == '-')
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_XML_COMMENT),
                     errmsg("invalid XML comment")));
    }
    if (len > 0 && argdata[len - 1] == '-')
        ereport(ERROR,
                (errcode(ERRCODE_INVALID_XML_COMMENT),
                 errmsg("invalid XML comment")));

    initStringInfo(&buf);
    appendStringInfo(&buf, "<!--");
    appendStringInfoText(&buf, arg);
    appendStringInfo(&buf, "-->");

    PG_RETURN_XML_P(stringinfo_to_xmltype(&buf));
#else
    NO_XML_SUPPORT();
    return 0;
#endif
}

xmltype* xmlconcat ( List args  ) 

Definition at line 463 of file xml.c.

References appendStringInfoString(), StringInfoData::data, DatumGetXmlP, initStringInfo(), lfirst, NO_XML_SUPPORT, NULL, pfree(), PointerGetDatum, stringinfo_to_xmltype(), text_to_cstring(), and VARSIZE.

Referenced by ExecEvalXml(), and xmlconcat2().

{
#ifdef USE_LIBXML
    int         global_standalone = 1;
    xmlChar    *global_version = NULL;
    bool        global_version_no_value = false;
    StringInfoData buf;
    ListCell   *v;

    initStringInfo(&buf);
    foreach(v, args)
    {
        xmltype    *x = DatumGetXmlP(PointerGetDatum(lfirst(v)));
        size_t      len;
        xmlChar    *version;
        int         standalone;
        char       *str;

        len = VARSIZE(x) - VARHDRSZ;
        str = text_to_cstring((text *) x);

        parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);

        if (standalone == 0 && global_standalone == 1)
            global_standalone = 0;
        if (standalone < 0)
            global_standalone = -1;

        if (!version)
            global_version_no_value = true;
        else if (!global_version)
            global_version = version;
        else if (xmlStrcmp(version, global_version) != 0)
            global_version_no_value = true;

        appendStringInfoString(&buf, str + len);
        pfree(str);
    }

    if (!global_version_no_value || global_standalone >= 0)
    {
        StringInfoData buf2;

        initStringInfo(&buf2);

        print_xml_decl(&buf2,
                       (!global_version_no_value) ? global_version : NULL,
                       0,
                       global_standalone);

        appendStringInfoString(&buf2, buf.data);
        buf = buf2;
    }

    return stringinfo_to_xmltype(&buf);
#else
    NO_XML_SUPPORT();
    return NULL;
#endif
}

Datum xmlconcat2 ( PG_FUNCTION_ARGS   ) 
static void xmldata_root_element_end ( StringInfo  result,
const char *  eltname 
) [static]

Definition at line 2447 of file xml.c.

References appendStringInfo().

Referenced by database_to_xml_internal(), query_to_xml_internal(), schema_to_xml_internal(), and SPI_sql_row_to_xmlelement().

{
    appendStringInfo(result, "</%s>\n", eltname);
}

static void xmldata_root_element_start ( StringInfo  result,
const char *  eltname,
const char *  xmlschema,
const char *  targetns,
bool  top_level 
) [static]

Definition at line 2420 of file xml.c.

References appendStringInfo(), appendStringInfoString(), Assert, and NAMESPACE_XSI.

Referenced by database_to_xml_internal(), query_to_xml_internal(), schema_to_xml_internal(), and SPI_sql_row_to_xmlelement().

{
    /* This isn't really wrong but currently makes no sense. */
    Assert(top_level || !xmlschema);

    appendStringInfo(result, "<%s", eltname);
    if (top_level)
    {
        appendStringInfoString(result, " xmlns:xsi=\"" NAMESPACE_XSI "\"");
        if (strlen(targetns) > 0)
            appendStringInfo(result, " xmlns=\"%s\"", targetns);
    }
    if (xmlschema)
    {
        /* FIXME: better targets */
        if (strlen(targetns) > 0)
            appendStringInfo(result, " xsi:schemaLocation=\"%s #\"", targetns);
        else
            appendStringInfo(result, " xsi:noNamespaceSchemaLocation=\"#\"");
    }
    appendStringInfo(result, ">\n");
}

xmltype* xmlelement ( XmlExprState xmlExpr,
ExprContext econtext 
)

Definition at line 579 of file xml.c.

References arg, XmlExpr::arg_names, XmlExprState::args, ERROR, ExecEvalExpr, ExprState::expr, exprType(), forboth, i, lappend(), lfirst, map_sql_value_to_xml_value(), XmlExpr::name, XmlExprState::named_args, NIL, NO_XML_SUPPORT, NULL, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, strVal, value, xml_ereport(), and XmlExprState::xprstate.

Referenced by ExecEvalXml().

{
#ifdef USE_LIBXML
    XmlExpr    *xexpr = (XmlExpr *) xmlExpr->xprstate.expr;
    xmltype    *result;
    List       *named_arg_strings;
    List       *arg_strings;
    int         i;
    ListCell   *arg;
    ListCell   *narg;
    PgXmlErrorContext *xmlerrcxt;
    volatile xmlBufferPtr buf = NULL;
    volatile xmlTextWriterPtr writer = NULL;

    /*
     * We first evaluate all the arguments, then start up libxml and create
     * the result.  This avoids issues if one of the arguments involves a call
     * to some other function or subsystem that wants to use libxml on its own
     * terms.
     */
    named_arg_strings = NIL;
    i = 0;
    foreach(arg, xmlExpr->named_args)
    {
        ExprState  *e = (ExprState *) lfirst(arg);
        Datum       value;
        bool        isnull;
        char       *str;

        value = ExecEvalExpr(e, econtext, &isnull, NULL);
        if (isnull)
            str = NULL;
        else
            str = map_sql_value_to_xml_value(value, exprType((Node *) e->expr), false);
        named_arg_strings = lappend(named_arg_strings, str);
        i++;
    }

    arg_strings = NIL;
    foreach(arg, xmlExpr->args)
    {
        ExprState  *e = (ExprState *) lfirst(arg);
        Datum       value;
        bool        isnull;
        char       *str;

        value = ExecEvalExpr(e, econtext, &isnull, NULL);
        /* here we can just forget NULL elements immediately */
        if (!isnull)
        {
            str = map_sql_value_to_xml_value(value,
                                           exprType((Node *) e->expr), true);
            arg_strings = lappend(arg_strings, str);
        }
    }

    /* now safe to run libxml */
    xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);

    PG_TRY();
    {
        buf = xmlBufferCreate();
        if (buf == NULL || xmlerrcxt->err_occurred)
            xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
                        "could not allocate xmlBuffer");
        writer = xmlNewTextWriterMemory(buf, 0);
        if (writer == NULL || xmlerrcxt->err_occurred)
            xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
                        "could not allocate xmlTextWriter");

        xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);

        forboth(arg, named_arg_strings, narg, xexpr->arg_names)
        {
            char       *str = (char *) lfirst(arg);
            char       *argname = strVal(lfirst(narg));

            if (str)
                xmlTextWriterWriteAttribute(writer,
                                            (xmlChar *) argname,
                                            (xmlChar *) str);
        }

        foreach(arg, arg_strings)
        {
            char       *str = (char *) lfirst(arg);

            xmlTextWriterWriteRaw(writer, (xmlChar *) str);
        }

        xmlTextWriterEndElement(writer);

        /* we MUST do this now to flush data out to the buffer ... */
        xmlFreeTextWriter(writer);
        writer = NULL;

        result = xmlBuffer_to_xmltype(buf);
    }
    PG_CATCH();
    {
        if (writer)
            xmlFreeTextWriter(writer);
        if (buf)
            xmlBufferFree(buf);

        pg_xml_done(xmlerrcxt, true);

        PG_RE_THROW();
    }
    PG_END_TRY();

    xmlBufferFree(buf);

    pg_xml_done(xmlerrcxt, false);

    return result;
#else
    NO_XML_SUPPORT();
    return NULL;
#endif
}

Datum xmlexists ( PG_FUNCTION_ARGS   ) 

Definition at line 3963 of file xml.c.

References NO_XML_SUPPORT, NULL, PG_GETARG_TEXT_P, PG_GETARG_XML_P, and PG_RETURN_BOOL.

{
#ifdef USE_LIBXML
    text       *xpath_expr_text = PG_GETARG_TEXT_P(0);
    xmltype    *data = PG_GETARG_XML_P(1);
    int         res_nitems;

    xpath_internal(xpath_expr_text, data, NULL,
                   &res_nitems, NULL);

    PG_RETURN_BOOL(res_nitems > 0);
#else
    NO_XML_SUPPORT();
    return 0;
#endif
}

xmltype* xmlparse ( text data,
XmlOptionType  xmloption_arg,
bool  preserve_whitespace 
)

Definition at line 703 of file xml.c.

References GetDatabaseEncoding(), and NO_XML_SUPPORT.

Referenced by ExecEvalXml(), and texttoxml().

{
#ifdef USE_LIBXML
    xmlDocPtr   doc;

    doc = xml_parse(data, xmloption_arg, preserve_whitespace,
                    GetDatabaseEncoding());
    xmlFreeDoc(doc);

    return (xmltype *) data;
#else
    NO_XML_SUPPORT();
    return NULL;
#endif
}

xmltype* xmlpi ( char *  target,
text arg,
bool  arg_is_null,
bool result_is_null 
)

Definition at line 721 of file xml.c.

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), StringInfoData::data, ereport, errcode(), errdetail(), errmsg(), ERROR, initStringInfo(), NO_XML_SUPPORT, NULL, pfree(), pg_strcasecmp(), stringinfo_to_xmltype(), and text_to_cstring().

Referenced by ExecEvalXml().

{
#ifdef USE_LIBXML
    xmltype    *result;
    StringInfoData buf;

    if (pg_strcasecmp(target, "xml") == 0)
        ereport(ERROR,
                (errcode(ERRCODE_SYNTAX_ERROR), /* really */
                 errmsg("invalid XML processing instruction"),
                 errdetail("XML processing instruction target name cannot be \"%s\".", target)));

    /*
     * Following the SQL standard, the null check comes after the syntax check
     * above.
     */
    *result_is_null = arg_is_null;
    if (*result_is_null)
        return NULL;

    initStringInfo(&buf);

    appendStringInfo(&buf, "<?%s", target);

    if (arg != NULL)
    {
        char       *string;

        string = text_to_cstring(arg);
        if (strstr(string, "?>") != NULL)
            ereport(ERROR,
                    (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
                     errmsg("invalid XML processing instruction"),
            errdetail("XML processing instruction cannot contain \"?>\".")));

        appendStringInfoChar(&buf, ' ');
        appendStringInfoString(&buf, string + strspn(string, " "));
        pfree(string);
    }
    appendStringInfoString(&buf, "?>");

    result = stringinfo_to_xmltype(&buf);
    pfree(buf.data);
    return result;
#else
    NO_XML_SUPPORT();
    return NULL;
#endif
}

xmltype* xmlroot ( xmltype data,
text version,
int  standalone 
)

Definition at line 773 of file xml.c.

References appendStringInfoString(), initStringInfo(), NO_XML_SUPPORT, NULL, stringinfo_to_xmltype(), text_to_cstring(), VARSIZE, XML_STANDALONE_NO, XML_STANDALONE_NO_VALUE, XML_STANDALONE_OMITTED, and XML_STANDALONE_YES.

Referenced by ExecEvalXml().

{
#ifdef USE_LIBXML
    char       *str;
    size_t      len;
    xmlChar    *orig_version;
    int         orig_standalone;
    StringInfoData buf;

    len = VARSIZE(data) - VARHDRSZ;
    str = text_to_cstring((text *) data);

    parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);

    if (version)
        orig_version = xml_text2xmlChar(version);
    else
        orig_version = NULL;

    switch (standalone)
    {
        case XML_STANDALONE_YES:
            orig_standalone = 1;
            break;
        case XML_STANDALONE_NO:
            orig_standalone = 0;
            break;
        case XML_STANDALONE_NO_VALUE:
            orig_standalone = -1;
            break;
        case XML_STANDALONE_OMITTED:
            /* leave original value */
            break;
    }

    initStringInfo(&buf);
    print_xml_decl(&buf, orig_version, 0, orig_standalone);
    appendStringInfoString(&buf, str + len);

    return stringinfo_to_xmltype(&buf);
#else
    NO_XML_SUPPORT();
    return NULL;
#endif
}

Datum xmltotext ( PG_FUNCTION_ARGS   ) 

Definition at line 556 of file xml.c.

References PG_GETARG_XML_P, and PG_RETURN_TEXT_P.

{
    xmltype    *data = PG_GETARG_XML_P(0);

    /* It's actually binary compatible. */
    PG_RETURN_TEXT_P((text *) data);
}

text* xmltotext_with_xmloption ( xmltype data,
XmlOptionType  xmloption_arg 
)

Definition at line 566 of file xml.c.

References ereport, errcode(), errmsg(), ERROR, xml_is_document(), and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXml().

{
    if (xmloption_arg == XMLOPTION_DOCUMENT && !xml_is_document(data))
        ereport(ERROR,
                (errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
                 errmsg("not an XML document")));

    /* It's actually binary compatible, save for the above check. */
    return (text *) data;
}

Datum xmlvalidate ( PG_FUNCTION_ARGS   ) 

Definition at line 829 of file xml.c.

References ereport, errcode(), errmsg(), and ERROR.

{
    ereport(ERROR,
            (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
             errmsg("xmlvalidate is not implemented")));
    return 0;
}

Datum xpath ( PG_FUNCTION_ARGS   ) 

Definition at line 3936 of file xml.c.

References construct_empty_array(), CurrentMemoryContext, makeArrayResult(), NO_XML_SUPPORT, PG_GETARG_ARRAYTYPE_P, PG_GETARG_TEXT_P, PG_GETARG_XML_P, PG_RETURN_ARRAYTYPE_P, and XMLOID.

{
#ifdef USE_LIBXML
    text       *xpath_expr_text = PG_GETARG_TEXT_P(0);
    xmltype    *data = PG_GETARG_XML_P(1);
    ArrayType  *namespaces = PG_GETARG_ARRAYTYPE_P(2);
    int         res_nitems;
    ArrayBuildState *astate;

    xpath_internal(xpath_expr_text, data, namespaces,
                   &res_nitems, &astate);

    if (res_nitems == 0)
        PG_RETURN_ARRAYTYPE_P(construct_empty_array(XMLOID));
    else
        PG_RETURN_ARRAYTYPE_P(makeArrayResult(astate, CurrentMemoryContext));
#else
    NO_XML_SUPPORT();
    return 0;
#endif
}

Datum xpath_exists ( PG_FUNCTION_ARGS   ) 

Definition at line 3986 of file xml.c.

References NO_XML_SUPPORT, NULL, PG_GETARG_ARRAYTYPE_P, PG_GETARG_TEXT_P, PG_GETARG_XML_P, and PG_RETURN_BOOL.

{
#ifdef USE_LIBXML
    text       *xpath_expr_text = PG_GETARG_TEXT_P(0);
    xmltype    *data = PG_GETARG_XML_P(1);
    ArrayType  *namespaces = PG_GETARG_ARRAYTYPE_P(2);
    int         res_nitems;

    xpath_internal(xpath_expr_text, data, namespaces,
                   &res_nitems, NULL);

    PG_RETURN_BOOL(res_nitems > 0);
#else
    NO_XML_SUPPORT();
    return 0;
#endif
}

static void xsd_schema_element_end ( StringInfo  result  )  [static]

Definition at line 2715 of file xml.c.

References appendStringInfoString().

Referenced by database_to_xmlschema_internal(), map_sql_table_to_xmlschema(), and schema_to_xmlschema_internal().

{
    appendStringInfoString(result, "</xsd:schema>");
}

static void xsd_schema_element_start ( StringInfo  result,
const char *  targetns 
) [static]

Definition at line 2698 of file xml.c.

References appendStringInfo(), appendStringInfoString(), and NAMESPACE_XSD.

Referenced by database_to_xmlschema_internal(), map_sql_table_to_xmlschema(), and schema_to_xmlschema_internal().

{
    appendStringInfoString(result,
                           "<xsd:schema\n"
                           "    xmlns:xsd=\"" NAMESPACE_XSD "\"");
    if (strlen(targetns) > 0)
        appendStringInfo(result,
                         "\n"
                         "    targetNamespace=\"%s\"\n"
                         "    elementFormDefault=\"qualified\"",
                         targetns);
    appendStringInfoString(result,
                           ">\n\n");
}


Variable Documentation

int xmlbinary

Definition at line 95 of file xml.c.

Referenced by map_sql_type_to_xmlschema_type(), and map_sql_value_to_xml_value().

int xmloption