PostgreSQL Source Code  git master
xml.h File Reference
#include "executor/tablefunc.h"
#include "fmgr.h"
#include "nodes/execnodes.h"
#include "nodes/primnodes.h"
Include dependency graph for xml.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define DatumGetXmlP(X)   ((xmltype *) PG_DETOAST_DATUM(X))
 
#define XmlPGetDatum(X)   PointerGetDatum(X)
 
#define PG_GETARG_XML_P(n)   DatumGetXmlP(PG_GETARG_DATUM(n))
 
#define PG_RETURN_XML_P(x)   PG_RETURN_POINTER(x)
 

Typedefs

typedef struct varlena xmltype
 
typedef struct PgXmlErrorContext PgXmlErrorContext
 

Enumerations

enum  XmlStandaloneType { XML_STANDALONE_YES , XML_STANDALONE_NO , XML_STANDALONE_NO_VALUE , XML_STANDALONE_OMITTED }
 
enum  XmlBinaryType { XMLBINARY_BASE64 , XMLBINARY_HEX }
 
enum  PgXmlStrictness { PG_XML_STRICTNESS_LEGACY , PG_XML_STRICTNESS_WELLFORMED , PG_XML_STRICTNESS_ALL }
 

Functions

void pg_xml_init_library (void)
 
PgXmlErrorContextpg_xml_init (PgXmlStrictness strictness)
 
void pg_xml_done (PgXmlErrorContext *errcxt, bool isError)
 
bool pg_xml_error_occurred (PgXmlErrorContext *errcxt)
 
void xml_ereport (PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
 
xmltypexmlconcat (List *args)
 
xmltypexmlelement (XmlExpr *xexpr, Datum *named_argvalue, bool *named_argnull, Datum *argvalue, bool *argnull)
 
xmltypexmlparse (text *data, XmlOptionType xmloption, bool preserve_whitespace)
 
xmltypexmlpi (const char *target, text *arg, bool arg_is_null, bool *result_is_null)
 
xmltypexmlroot (xmltype *data, text *version, int standalone)
 
bool xml_is_document (xmltype *arg)
 
textxmltotext_with_xmloption (xmltype *data, XmlOptionType xmloption_arg)
 
char * escape_xml (const char *str)
 
char * map_sql_identifier_to_xml_name (const char *ident, bool fully_escaped, bool escape_period)
 
char * map_xml_name_to_sql_identifier (const char *name)
 
char * map_sql_value_to_xml_value (Datum value, Oid type, bool xml_escape_strings)
 

Variables

PGDLLIMPORT int xmlbinary
 
PGDLLIMPORT int xmloption
 
PGDLLIMPORT const TableFuncRoutine XmlTableRoutine
 

Macro Definition Documentation

◆ DatumGetXmlP

#define DatumGetXmlP (   X)    ((xmltype *) PG_DETOAST_DATUM(X))

Definition at line 50 of file xml.h.

◆ PG_GETARG_XML_P

#define PG_GETARG_XML_P (   n)    DatumGetXmlP(PG_GETARG_DATUM(n))

Definition at line 53 of file xml.h.

◆ PG_RETURN_XML_P

#define PG_RETURN_XML_P (   x)    PG_RETURN_POINTER(x)

Definition at line 54 of file xml.h.

◆ XmlPGetDatum

#define XmlPGetDatum (   X)    PointerGetDatum(X)

Definition at line 51 of file xml.h.

Typedef Documentation

◆ PgXmlErrorContext

Definition at line 1 of file xml.h.

◆ xmltype

typedef struct varlena xmltype

Definition at line 1 of file xml.h.

Enumeration Type Documentation

◆ PgXmlStrictness

Enumerator
PG_XML_STRICTNESS_LEGACY 
PG_XML_STRICTNESS_WELLFORMED 
PG_XML_STRICTNESS_ALL 

Definition at line 39 of file xml.h.

40 {
41  PG_XML_STRICTNESS_LEGACY, /* ignore errors unless function result
42  * indicates error condition */
43  PG_XML_STRICTNESS_WELLFORMED, /* ignore non-parser messages */
44  PG_XML_STRICTNESS_ALL /* report all notices/warnings/errors */
PgXmlStrictness
Definition: xml.h:40
@ PG_XML_STRICTNESS_LEGACY
Definition: xml.h:41
@ PG_XML_STRICTNESS_ALL
Definition: xml.h:44
@ PG_XML_STRICTNESS_WELLFORMED
Definition: xml.h:43

◆ XmlBinaryType

Enumerator
XMLBINARY_BASE64 
XMLBINARY_HEX 

Definition at line 33 of file xml.h.

34 {
XmlBinaryType
Definition: xml.h:34
@ XMLBINARY_BASE64
Definition: xml.h:35
@ XMLBINARY_HEX
Definition: xml.h:36

◆ XmlStandaloneType

Enumerator
XML_STANDALONE_YES 
XML_STANDALONE_NO 
XML_STANDALONE_NO_VALUE 
XML_STANDALONE_OMITTED 

Definition at line 25 of file xml.h.

26 {
XmlStandaloneType
Definition: xml.h:26
@ XML_STANDALONE_OMITTED
Definition: xml.h:30
@ XML_STANDALONE_NO_VALUE
Definition: xml.h:29
@ XML_STANDALONE_YES
Definition: xml.h:27
@ XML_STANDALONE_NO
Definition: xml.h:28

Function Documentation

◆ escape_xml()

char* escape_xml ( const char *  str)

Definition at line 2352 of file xml.c.

2353 {
2355  const char *p;
2356 
2357  initStringInfo(&buf);
2358  for (p = str; *p; p++)
2359  {
2360  switch (*p)
2361  {
2362  case '&':
2363  appendStringInfoString(&buf, "&");
2364  break;
2365  case '<':
2366  appendStringInfoString(&buf, "&lt;");
2367  break;
2368  case '>':
2369  appendStringInfoString(&buf, "&gt;");
2370  break;
2371  case '\r':
2372  appendStringInfoString(&buf, "&#x0d;");
2373  break;
2374  default:
2376  break;
2377  }
2378  }
2379  return buf.data;
2380 }
static char * buf
Definition: pg_test_fsync.c:67
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128

References appendStringInfoCharMacro, appendStringInfoString(), buf, initStringInfo(), and generate_unaccent_rules::str.

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

◆ map_sql_identifier_to_xml_name()

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

Definition at line 2035 of file xml.c.

2037 {
2038 #ifdef USE_LIBXML
2040  const char *p;
2041 
2042  /*
2043  * SQL/XML doesn't make use of this case anywhere, so it's probably a
2044  * mistake.
2045  */
2046  Assert(fully_escaped || !escape_period);
2047 
2048  initStringInfo(&buf);
2049 
2050  for (p = ident; *p; p += pg_mblen(p))
2051  {
2052  if (*p == ':' && (p == ident || fully_escaped))
2053  appendStringInfoString(&buf, "_x003A_");
2054  else if (*p == '_' && *(p + 1) == 'x')
2055  appendStringInfoString(&buf, "_x005F_");
2056  else if (fully_escaped && p == ident &&
2057  pg_strncasecmp(p, "xml", 3) == 0)
2058  {
2059  if (*p == 'x')
2060  appendStringInfoString(&buf, "_x0078_");
2061  else
2062  appendStringInfoString(&buf, "_x0058_");
2063  }
2064  else if (escape_period && *p == '.')
2065  appendStringInfoString(&buf, "_x002E_");
2066  else
2067  {
2068  pg_wchar u = sqlchar_to_unicode(p);
2069 
2070  if ((p == ident)
2071  ? !is_valid_xml_namefirst(u)
2072  : !is_valid_xml_namechar(u))
2073  appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
2074  else
2076  }
2077  }
2078 
2079  return buf.data;
2080 #else /* not USE_LIBXML */
2081  NO_XML_SUPPORT();
2082  return NULL;
2083 #endif /* not USE_LIBXML */
2084 }
Assert(fmt[strlen(fmt) - 1] !='\n')
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mblen(const char *mbstr)
Definition: mbutils.c:966
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
Definition: pgstrcasecmp.c:69
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
#define NO_XML_SUPPORT()
Definition: xml.c:219

References appendBinaryStringInfo(), appendStringInfo(), appendStringInfoString(), Assert(), buf, 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().

◆ map_sql_value_to_xml_value()

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

Definition at line 2133 of file xml.c.

2134 {
2136  {
2137  ArrayType *array;
2138  Oid elmtype;
2139  int16 elmlen;
2140  bool elmbyval;
2141  char elmalign;
2142  int num_elems;
2143  Datum *elem_values;
2144  bool *elem_nulls;
2146  int i;
2147 
2148  array = DatumGetArrayTypeP(value);
2149  elmtype = ARR_ELEMTYPE(array);
2150  get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
2151 
2152  deconstruct_array(array, elmtype,
2153  elmlen, elmbyval, elmalign,
2154  &elem_values, &elem_nulls,
2155  &num_elems);
2156 
2157  initStringInfo(&buf);
2158 
2159  for (i = 0; i < num_elems; i++)
2160  {
2161  if (elem_nulls[i])
2162  continue;
2163  appendStringInfoString(&buf, "<element>");
2165  map_sql_value_to_xml_value(elem_values[i],
2166  elmtype, true));
2167  appendStringInfoString(&buf, "</element>");
2168  }
2169 
2170  pfree(elem_values);
2171  pfree(elem_nulls);
2172 
2173  return buf.data;
2174  }
2175  else
2176  {
2177  Oid typeOut;
2178  bool isvarlena;
2179  char *str;
2180 
2181  /*
2182  * Flatten domains; the special-case treatments below should apply to,
2183  * eg, domains over boolean not just boolean.
2184  */
2185  type = getBaseType(type);
2186 
2187  /*
2188  * Special XSD formatting for some data types
2189  */
2190  switch (type)
2191  {
2192  case BOOLOID:
2193  if (DatumGetBool(value))
2194  return "true";
2195  else
2196  return "false";
2197 
2198  case DATEOID:
2199  {
2200  DateADT date;
2201  struct pg_tm tm;
2202  char buf[MAXDATELEN + 1];
2203 
2205  /* XSD doesn't support infinite values */
2206  if (DATE_NOT_FINITE(date))
2207  ereport(ERROR,
2208  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2209  errmsg("date out of range"),
2210  errdetail("XML does not support infinite date values.")));
2212  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2214 
2215  return pstrdup(buf);
2216  }
2217 
2218  case TIMESTAMPOID:
2219  {
2221  struct pg_tm tm;
2222  fsec_t fsec;
2223  char buf[MAXDATELEN + 1];
2224 
2226 
2227  /* XSD doesn't support infinite values */
2229  ereport(ERROR,
2230  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2231  errmsg("timestamp out of range"),
2232  errdetail("XML does not support infinite timestamp values.")));
2233  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
2234  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
2235  else
2236  ereport(ERROR,
2237  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2238  errmsg("timestamp out of range")));
2239 
2240  return pstrdup(buf);
2241  }
2242 
2243  case TIMESTAMPTZOID:
2244  {
2246  struct pg_tm tm;
2247  int tz;
2248  fsec_t fsec;
2249  const char *tzn = NULL;
2250  char buf[MAXDATELEN + 1];
2251 
2253 
2254  /* XSD doesn't support infinite values */
2256  ereport(ERROR,
2257  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2258  errmsg("timestamp out of range"),
2259  errdetail("XML does not support infinite timestamp values.")));
2260  else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
2261  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
2262  else
2263  ereport(ERROR,
2264  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2265  errmsg("timestamp out of range")));
2266 
2267  return pstrdup(buf);
2268  }
2269 
2270 #ifdef USE_LIBXML
2271  case BYTEAOID:
2272  {
2273  bytea *bstr = DatumGetByteaPP(value);
2274  PgXmlErrorContext *xmlerrcxt;
2275  volatile xmlBufferPtr buf = NULL;
2276  volatile xmlTextWriterPtr writer = NULL;
2277  char *result;
2278 
2279  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
2280 
2281  PG_TRY();
2282  {
2283  buf = xmlBufferCreate();
2284  if (buf == NULL || xmlerrcxt->err_occurred)
2285  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2286  "could not allocate xmlBuffer");
2287  writer = xmlNewTextWriterMemory(buf, 0);
2288  if (writer == NULL || xmlerrcxt->err_occurred)
2289  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2290  "could not allocate xmlTextWriter");
2291 
2292  if (xmlbinary == XMLBINARY_BASE64)
2293  xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
2294  0, VARSIZE_ANY_EXHDR(bstr));
2295  else
2296  xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
2297  0, VARSIZE_ANY_EXHDR(bstr));
2298 
2299  /* we MUST do this now to flush data out to the buffer */
2300  xmlFreeTextWriter(writer);
2301  writer = NULL;
2302 
2303  result = pstrdup((const char *) xmlBufferContent(buf));
2304  }
2305  PG_CATCH();
2306  {
2307  if (writer)
2308  xmlFreeTextWriter(writer);
2309  if (buf)
2310  xmlBufferFree(buf);
2311 
2312  pg_xml_done(xmlerrcxt, true);
2313 
2314  PG_RE_THROW();
2315  }
2316  PG_END_TRY();
2317 
2318  xmlBufferFree(buf);
2319 
2320  pg_xml_done(xmlerrcxt, false);
2321 
2322  return result;
2323  }
2324 #endif /* USE_LIBXML */
2325 
2326  }
2327 
2328  /*
2329  * otherwise, just use the type's native text representation
2330  */
2331  getTypeOutputInfo(type, &typeOut, &isvarlena);
2332  str = OidOutputFunctionCall(typeOut, value);
2333 
2334  /* ... exactly as-is for XML, and when escaping is not wanted */
2335  if (type == XMLOID || !xml_escape_strings)
2336  return str;
2337 
2338  /* otherwise, translate special characters as needed */
2339  return escape_xml(str);
2340  }
2341 }
#define DatumGetArrayTypeP(X)
Definition: array.h:254
#define ARR_ELEMTYPE(a)
Definition: array.h:285
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3577
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:309
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4258
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4143
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1816
signed short int16
Definition: c.h:439
int64 Timestamp
Definition: timestamp.h:38
int64 TimestampTz
Definition: timestamp.h:39
int32 fsec_t
Definition: timestamp.h:41
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:161
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:202
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
#define DatumGetDateADT(X)
Definition: date.h:53
int errdetail(const char *fmt,...)
Definition: elog.c:1037
int errcode(int sqlerrcode)
Definition: elog.c:693
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define PG_RE_THROW()
Definition: elog.h:340
#define PG_END_TRY()
Definition: elog.h:324
#define PG_TRY()
Definition: elog.h:299
#define ERROR
Definition: elog.h:33
#define PG_CATCH()
Definition: elog.h:309
#define ereport(elevel,...)
Definition: elog.h:143
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1639
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define MAXDATELEN
Definition: datetime.h:201
static struct @151 value
int i
Definition: isn.c:73
static struct pg_tm tm
Definition: localtime.c:102
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2864
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2228
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2478
#define type_is_array_domain(typid)
Definition: lsyscache.h:204
char * pstrdup(const char *in)
Definition: mcxt.c:1305
void pfree(void *pointer)
Definition: mcxt.c:1175
#define USE_XSD_DATES
Definition: miscadmin.h:233
long date
Definition: pgtypes_date.h:9
int64 timestamp
uintptr_t Datum
Definition: postgres.h:411
#define DatumGetBool(X)
Definition: postgres.h:437
#define VARDATA_ANY(PTR)
Definition: postgres.h:361
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:354
unsigned int Oid
Definition: postgres_ext.h:31
Definition: pgtime.h:35
int tm_mday
Definition: pgtime.h:39
int tm_mon
Definition: pgtime.h:40
int tm_year
Definition: pgtime.h:41
Definition: c.h:633
#define DatumGetTimestamp(X)
Definition: timestamp.h:27
int xmlbinary
Definition: xml.c:97
char * escape_xml(const char *str)
Definition: xml.c:2352
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2133
struct PgXmlErrorContext PgXmlErrorContext
Definition: xml.h:48
void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
void pg_xml_done(PgXmlErrorContext *errcxt, bool isError)
PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness)

References appendStringInfoString(), ARR_ELEMTYPE, buf, DATE_NOT_FINITE, DatumGetArrayTypeP, DatumGetBool, DatumGetByteaPP, DatumGetDateADT, DatumGetTimestamp, deconstruct_array(), EncodeDateOnly(), EncodeDateTime(), ereport, errcode(), errdetail(), errmsg(), ERROR, escape_xml(), get_typlenbyvalalign(), getBaseType(), getTypeOutputInfo(), i, initStringInfo(), j2date(), MAXDATELEN, 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(), generate_unaccent_rules::str, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, generate_unaccent_rules::type, type_is_array_domain, USE_XSD_DATES, value, VARDATA_ANY, VARSIZE_ANY_EXHDR, xml_ereport(), xmlbinary, and XMLBINARY_BASE64.

Referenced by ExecEvalXmlExpr(), SPI_sql_row_to_xmlelement(), and xmlelement().

◆ map_xml_name_to_sql_identifier()

char* map_xml_name_to_sql_identifier ( const char *  name)

Definition at line 2091 of file xml.c.

2092 {
2094  const char *p;
2095 
2096  initStringInfo(&buf);
2097 
2098  for (p = name; *p; p += pg_mblen(p))
2099  {
2100  if (*p == '_' && *(p + 1) == 'x'
2101  && isxdigit((unsigned char) *(p + 2))
2102  && isxdigit((unsigned char) *(p + 3))
2103  && isxdigit((unsigned char) *(p + 4))
2104  && isxdigit((unsigned char) *(p + 5))
2105  && *(p + 6) == '_')
2106  {
2107  char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
2108  unsigned int u;
2109 
2110  sscanf(p + 2, "%X", &u);
2111  pg_unicode_to_server(u, (unsigned char *) cbuf);
2112  appendStringInfoString(&buf, cbuf);
2113  p += 6;
2114  }
2115  else
2117  }
2118 
2119  return buf.data;
2120 }
const char * name
Definition: encode.c:561
void pg_unicode_to_server(pg_wchar c, unsigned char *s)
Definition: mbutils.c:864
#define MAX_UNICODE_EQUIVALENT_STRING
Definition: pg_wchar.h:327

References appendBinaryStringInfo(), appendStringInfoString(), buf, initStringInfo(), MAX_UNICODE_EQUIVALENT_STRING, name, pg_mblen(), and pg_unicode_to_server().

Referenced by get_rule_expr().

◆ pg_xml_done()

◆ pg_xml_error_occurred()

bool pg_xml_error_occurred ( PgXmlErrorContext errcxt)

◆ pg_xml_init()

◆ pg_xml_init_library()

void pg_xml_init_library ( void  )

◆ xml_ereport()

◆ xml_is_document()

bool xml_is_document ( xmltype arg)

Definition at line 887 of file xml.c.

888 {
889 #ifdef USE_LIBXML
890  bool result;
891  volatile xmlDocPtr doc = NULL;
893 
894  /* We want to catch ereport(INVALID_XML_DOCUMENT) and return false */
895  PG_TRY();
896  {
897  doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
899  result = true;
900  }
901  PG_CATCH();
902  {
903  ErrorData *errdata;
904  MemoryContext ecxt;
905 
906  ecxt = MemoryContextSwitchTo(ccxt);
907  errdata = CopyErrorData();
908  if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
909  {
910  FlushErrorState();
911  result = false;
912  }
913  else
914  {
915  MemoryContextSwitchTo(ecxt);
916  PG_RE_THROW();
917  }
918  }
919  PG_END_TRY();
920 
921  if (doc)
922  xmlFreeDoc(doc);
923 
924  return result;
925 #else /* not USE_LIBXML */
926  NO_XML_SUPPORT();
927  return false;
928 #endif /* not USE_LIBXML */
929 }
void FlushErrorState(void)
Definition: elog.c:1649
ErrorData * CopyErrorData(void)
Definition: elog.c:1555
int GetDatabaseEncoding(void)
Definition: mbutils.c:1210
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void * arg
@ XMLOPTION_DOCUMENT
Definition: primnodes.h:1339
int sqlerrcode
Definition: elog.h:367

References arg, 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 ExecEvalXmlExpr(), and xmltotext_with_xmloption().

◆ xmlconcat()

xmltype* xmlconcat ( List args)

Definition at line 511 of file xml.c.

512 {
513 #ifdef USE_LIBXML
514  int global_standalone = 1;
515  xmlChar *global_version = NULL;
516  bool global_version_no_value = false;
518  ListCell *v;
519 
521  foreach(v, args)
522  {
524  size_t len;
525  xmlChar *version;
526  int standalone;
527  char *str;
528 
529  len = VARSIZE(x) - VARHDRSZ;
530  str = text_to_cstring((text *) x);
531 
532  parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
533 
534  if (standalone == 0 && global_standalone == 1)
535  global_standalone = 0;
536  if (standalone < 0)
537  global_standalone = -1;
538 
539  if (!version)
540  global_version_no_value = true;
541  else if (!global_version)
542  global_version = version;
543  else if (xmlStrcmp(version, global_version) != 0)
544  global_version_no_value = true;
545 
547  pfree(str);
548  }
549 
550  if (!global_version_no_value || global_standalone >= 0)
551  {
552  StringInfoData buf2;
553 
554  initStringInfo(&buf2);
555 
556  print_xml_decl(&buf2,
557  (!global_version_no_value) ? global_version : NULL,
558  0,
559  global_standalone);
560 
561  appendBinaryStringInfo(&buf2, buf.data, buf.len);
562  buf = buf2;
563  }
564 
565  return stringinfo_to_xmltype(&buf);
566 #else
567  NO_XML_SUPPORT();
568  return NULL;
569 #endif
570 }
#define VARHDRSZ
Definition: c.h:638
int x
Definition: isn.c:71
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:170
#define VARSIZE(PTR)
Definition: postgres.h:316
#define PointerGetDatum(X)
Definition: postgres.h:600
char * text_to_cstring(const text *t)
Definition: varlena.c:221
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Definition: xml.c:446
#define DatumGetXmlP(X)
Definition: xml.h:50

References appendBinaryStringInfo(), appendStringInfoString(), generate_unaccent_rules::args, buf, DatumGetXmlP, initStringInfo(), len, lfirst, NO_XML_SUPPORT, pfree(), PointerGetDatum, generate_unaccent_rules::str, stringinfo_to_xmltype(), text_to_cstring(), VARHDRSZ, VARSIZE, and x.

Referenced by ExecEvalXmlExpr(), and xmlconcat2().

◆ xmlelement()

xmltype* xmlelement ( XmlExpr xexpr,
Datum named_argvalue,
bool named_argnull,
Datum argvalue,
bool argnull 
)

Definition at line 627 of file xml.c.

630 {
631 #ifdef USE_LIBXML
632  xmltype *result;
633  List *named_arg_strings;
634  List *arg_strings;
635  int i;
636  ListCell *arg;
637  ListCell *narg;
638  PgXmlErrorContext *xmlerrcxt;
639  volatile xmlBufferPtr buf = NULL;
640  volatile xmlTextWriterPtr writer = NULL;
641 
642  /*
643  * All arguments are already evaluated, and their values are passed in the
644  * named_argvalue/named_argnull or argvalue/argnull arrays. This avoids
645  * issues if one of the arguments involves a call to some other function
646  * or subsystem that wants to use libxml on its own terms. We examine the
647  * original XmlExpr to identify the numbers and types of the arguments.
648  */
649  named_arg_strings = NIL;
650  i = 0;
651  foreach(arg, xexpr->named_args)
652  {
653  Expr *e = (Expr *) lfirst(arg);
654  char *str;
655 
656  if (named_argnull[i])
657  str = NULL;
658  else
659  str = map_sql_value_to_xml_value(named_argvalue[i],
660  exprType((Node *) e),
661  false);
662  named_arg_strings = lappend(named_arg_strings, str);
663  i++;
664  }
665 
666  arg_strings = NIL;
667  i = 0;
668  foreach(arg, xexpr->args)
669  {
670  Expr *e = (Expr *) lfirst(arg);
671  char *str;
672 
673  /* here we can just forget NULL elements immediately */
674  if (!argnull[i])
675  {
676  str = map_sql_value_to_xml_value(argvalue[i],
677  exprType((Node *) e),
678  true);
679  arg_strings = lappend(arg_strings, str);
680  }
681  i++;
682  }
683 
684  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
685 
686  PG_TRY();
687  {
688  buf = xmlBufferCreate();
689  if (buf == NULL || xmlerrcxt->err_occurred)
690  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
691  "could not allocate xmlBuffer");
692  writer = xmlNewTextWriterMemory(buf, 0);
693  if (writer == NULL || xmlerrcxt->err_occurred)
694  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
695  "could not allocate xmlTextWriter");
696 
697  xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);
698 
699  forboth(arg, named_arg_strings, narg, xexpr->arg_names)
700  {
701  char *str = (char *) lfirst(arg);
702  char *argname = strVal(lfirst(narg));
703 
704  if (str)
705  xmlTextWriterWriteAttribute(writer,
706  (xmlChar *) argname,
707  (xmlChar *) str);
708  }
709 
710  foreach(arg, arg_strings)
711  {
712  char *str = (char *) lfirst(arg);
713 
714  xmlTextWriterWriteRaw(writer, (xmlChar *) str);
715  }
716 
717  xmlTextWriterEndElement(writer);
718 
719  /* we MUST do this now to flush data out to the buffer ... */
720  xmlFreeTextWriter(writer);
721  writer = NULL;
722 
723  result = xmlBuffer_to_xmltype(buf);
724  }
725  PG_CATCH();
726  {
727  if (writer)
728  xmlFreeTextWriter(writer);
729  if (buf)
730  xmlBufferFree(buf);
731 
732  pg_xml_done(xmlerrcxt, true);
733 
734  PG_RE_THROW();
735  }
736  PG_END_TRY();
737 
738  xmlBufferFree(buf);
739 
740  pg_xml_done(xmlerrcxt, false);
741 
742  return result;
743 #else
744  NO_XML_SUPPORT();
745  return NULL;
746 #endif
747 }
List * lappend(List *list, void *datum)
Definition: list.c:338
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
#define NIL
Definition: pg_list.h:66
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:465
e
Definition: preproc-init.c:82
Definition: pg_list.h:52
Definition: nodes.h:575
List * args
Definition: primnodes.h:1350
char * name
Definition: primnodes.h:1347
List * arg_names
Definition: primnodes.h:1349
List * named_args
Definition: primnodes.h:1348
#define strVal(v)
Definition: value.h:72

References arg, XmlExpr::arg_names, XmlExpr::args, buf, ERROR, exprType(), forboth, i, lappend(), lfirst, map_sql_value_to_xml_value(), XmlExpr::name, XmlExpr::named_args, NIL, NO_XML_SUPPORT, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, generate_unaccent_rules::str, strVal, and xml_ereport().

Referenced by ExecEvalXmlExpr().

◆ xmlparse()

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

Definition at line 751 of file xml.c.

752 {
753 #ifdef USE_LIBXML
754  xmlDocPtr doc;
755 
756  doc = xml_parse(data, xmloption_arg, preserve_whitespace,
758  xmlFreeDoc(doc);
759 
760  return (xmltype *) data;
761 #else
762  NO_XML_SUPPORT();
763  return NULL;
764 #endif
765 }
const void * data

References data, GetDatabaseEncoding(), and NO_XML_SUPPORT.

Referenced by ExecEvalXmlExpr(), and texttoxml().

◆ xmlpi()

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

Definition at line 769 of file xml.c.

770 {
771 #ifdef USE_LIBXML
772  xmltype *result;
774 
775  if (pg_strcasecmp(target, "xml") == 0)
776  ereport(ERROR,
777  (errcode(ERRCODE_SYNTAX_ERROR), /* really */
778  errmsg("invalid XML processing instruction"),
779  errdetail("XML processing instruction target name cannot be \"%s\".", target)));
780 
781  /*
782  * Following the SQL standard, the null check comes after the syntax check
783  * above.
784  */
785  *result_is_null = arg_is_null;
786  if (*result_is_null)
787  return NULL;
788 
790 
791  appendStringInfo(&buf, "<?%s", target);
792 
793  if (arg != NULL)
794  {
795  char *string;
796 
797  string = text_to_cstring(arg);
798  if (strstr(string, "?>") != NULL)
799  ereport(ERROR,
800  (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
801  errmsg("invalid XML processing instruction"),
802  errdetail("XML processing instruction cannot contain \"?>\".")));
803 
804  appendStringInfoChar(&buf, ' ');
805  appendStringInfoString(&buf, string + strspn(string, " "));
806  pfree(string);
807  }
808  appendStringInfoString(&buf, "?>");
809 
810  result = stringinfo_to_xmltype(&buf);
811  pfree(buf.data);
812  return result;
813 #else
814  NO_XML_SUPPORT();
815  return NULL;
816 #endif
817 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
char string[11]
Definition: preproc-type.c:46
void appendStringInfoChar(StringInfo str, char ch)
Definition: stringinfo.c:188

References appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), arg, buf, ereport, errcode(), errdetail(), errmsg(), ERROR, initStringInfo(), NO_XML_SUPPORT, pfree(), pg_strcasecmp(), stringinfo_to_xmltype(), and text_to_cstring().

Referenced by ExecEvalXmlExpr().

◆ xmlroot()

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

Definition at line 821 of file xml.c.

822 {
823 #ifdef USE_LIBXML
824  char *str;
825  size_t len;
826  xmlChar *orig_version;
827  int orig_standalone;
829 
830  len = VARSIZE(data) - VARHDRSZ;
831  str = text_to_cstring((text *) data);
832 
833  parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);
834 
835  if (version)
836  orig_version = xml_text2xmlChar(version);
837  else
838  orig_version = NULL;
839 
840  switch (standalone)
841  {
842  case XML_STANDALONE_YES:
843  orig_standalone = 1;
844  break;
845  case XML_STANDALONE_NO:
846  orig_standalone = 0;
847  break;
849  orig_standalone = -1;
850  break;
852  /* leave original value */
853  break;
854  }
855 
857  print_xml_decl(&buf, orig_version, 0, orig_standalone);
859 
860  return stringinfo_to_xmltype(&buf);
861 #else
862  NO_XML_SUPPORT();
863  return NULL;
864 #endif
865 }

References appendStringInfoString(), buf, data, initStringInfo(), len, NO_XML_SUPPORT, generate_unaccent_rules::str, stringinfo_to_xmltype(), text_to_cstring(), VARHDRSZ, VARSIZE, XML_STANDALONE_NO, XML_STANDALONE_NO_VALUE, XML_STANDALONE_OMITTED, and XML_STANDALONE_YES.

Referenced by ExecEvalXmlExpr().

◆ xmltotext_with_xmloption()

text* xmltotext_with_xmloption ( xmltype data,
XmlOptionType  xmloption_arg 
)

Definition at line 614 of file xml.c.

615 {
616  if (xmloption_arg == XMLOPTION_DOCUMENT && !xml_is_document(data))
617  ereport(ERROR,
618  (errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
619  errmsg("not an XML document")));
620 
621  /* It's actually binary compatible, save for the above check. */
622  return (text *) data;
623 }
bool xml_is_document(xmltype *arg)
Definition: xml.c:887

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

Referenced by ExecEvalXmlExpr().

Variable Documentation

◆ xmlbinary

PGDLLIMPORT int xmlbinary
extern

Definition at line 97 of file xml.c.

Referenced by map_sql_type_to_xmlschema_type(), and map_sql_value_to_xml_value().

◆ xmloption

◆ XmlTableRoutine

PGDLLIMPORT const TableFuncRoutine XmlTableRoutine
extern

Definition at line 207 of file xml.c.

Referenced by ExecInitTableFuncScan().