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

int xmlbinary
 
int xmloption
 
const TableFuncRoutine XmlTableRoutine
 

Macro Definition Documentation

◆ DatumGetXmlP

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

Definition at line 50 of file xml.h.

Referenced by ExecEvalXmlExpr(), xmlconcat(), and XmlTableSetDocument().

◆ PG_GETARG_XML_P

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

Definition at line 53 of file xml.h.

Referenced by xml_out(), xml_send(), xmlconcat2(), xmlexists(), xmltotext(), xpath(), and xpath_exists().

◆ PG_RETURN_XML_P

◆ XmlPGetDatum

#define XmlPGetDatum (   X)    PointerGetDatum(X)

Definition at line 51 of file xml.h.

Typedef Documentation

◆ PgXmlErrorContext

Definition at line 48 of file xml.h.

◆ xmltype

typedef struct varlena xmltype

Definition at line 23 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:39

◆ XmlBinaryType

Enumerator
XMLBINARY_BASE64 
XMLBINARY_HEX 

Definition at line 33 of file xml.h.

34 {
XmlBinaryType
Definition: xml.h:33

◆ XmlStandaloneType

Enumerator
XML_STANDALONE_YES 
XML_STANDALONE_NO 
XML_STANDALONE_NO_VALUE 
XML_STANDALONE_OMITTED 

Definition at line 25 of file xml.h.

Function Documentation

◆ escape_xml()

char* escape_xml ( const char *  str)

Definition at line 2371 of file xml.c.

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

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

2372 {
2374  const char *p;
2375 
2376  initStringInfo(&buf);
2377  for (p = str; *p; p++)
2378  {
2379  switch (*p)
2380  {
2381  case '&':
2382  appendStringInfoString(&buf, "&");
2383  break;
2384  case '<':
2385  appendStringInfoString(&buf, "&lt;");
2386  break;
2387  case '>':
2388  appendStringInfoString(&buf, "&gt;");
2389  break;
2390  case '\r':
2391  appendStringInfoString(&buf, "&#x0d;");
2392  break;
2393  default:
2394  appendStringInfoCharMacro(&buf, *p);
2395  break;
2396  }
2397  }
2398  return buf.data;
2399 }
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:128
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59

◆ 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 2036 of file xml.c.

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

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

◆ map_sql_value_to_xml_value()

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

Definition at line 2152 of file xml.c.

References appendStringInfoString(), ARR_ELEMTYPE, buf, StringInfoData::data, 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(), map_sql_value_to_xml_value(), 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, 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, and XMLBINARY_BASE64.

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

2153 {
2155  {
2156  ArrayType *array;
2157  Oid elmtype;
2158  int16 elmlen;
2159  bool elmbyval;
2160  char elmalign;
2161  int num_elems;
2162  Datum *elem_values;
2163  bool *elem_nulls;
2165  int i;
2166 
2167  array = DatumGetArrayTypeP(value);
2168  elmtype = ARR_ELEMTYPE(array);
2169  get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
2170 
2171  deconstruct_array(array, elmtype,
2172  elmlen, elmbyval, elmalign,
2173  &elem_values, &elem_nulls,
2174  &num_elems);
2175 
2176  initStringInfo(&buf);
2177 
2178  for (i = 0; i < num_elems; i++)
2179  {
2180  if (elem_nulls[i])
2181  continue;
2182  appendStringInfoString(&buf, "<element>");
2184  map_sql_value_to_xml_value(elem_values[i],
2185  elmtype, true));
2186  appendStringInfoString(&buf, "</element>");
2187  }
2188 
2189  pfree(elem_values);
2190  pfree(elem_nulls);
2191 
2192  return buf.data;
2193  }
2194  else
2195  {
2196  Oid typeOut;
2197  bool isvarlena;
2198  char *str;
2199 
2200  /*
2201  * Flatten domains; the special-case treatments below should apply to,
2202  * eg, domains over boolean not just boolean.
2203  */
2204  type = getBaseType(type);
2205 
2206  /*
2207  * Special XSD formatting for some data types
2208  */
2209  switch (type)
2210  {
2211  case BOOLOID:
2212  if (DatumGetBool(value))
2213  return "true";
2214  else
2215  return "false";
2216 
2217  case DATEOID:
2218  {
2219  DateADT date;
2220  struct pg_tm tm;
2221  char buf[MAXDATELEN + 1];
2222 
2223  date = DatumGetDateADT(value);
2224  /* XSD doesn't support infinite values */
2225  if (DATE_NOT_FINITE(date))
2226  ereport(ERROR,
2227  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2228  errmsg("date out of range"),
2229  errdetail("XML does not support infinite date values.")));
2231  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2233 
2234  return pstrdup(buf);
2235  }
2236 
2237  case TIMESTAMPOID:
2238  {
2240  struct pg_tm tm;
2241  fsec_t fsec;
2242  char buf[MAXDATELEN + 1];
2243 
2244  timestamp = DatumGetTimestamp(value);
2245 
2246  /* XSD doesn't support infinite values */
2247  if (TIMESTAMP_NOT_FINITE(timestamp))
2248  ereport(ERROR,
2249  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2250  errmsg("timestamp out of range"),
2251  errdetail("XML does not support infinite timestamp values.")));
2252  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
2253  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
2254  else
2255  ereport(ERROR,
2256  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2257  errmsg("timestamp out of range")));
2258 
2259  return pstrdup(buf);
2260  }
2261 
2262  case TIMESTAMPTZOID:
2263  {
2265  struct pg_tm tm;
2266  int tz;
2267  fsec_t fsec;
2268  const char *tzn = NULL;
2269  char buf[MAXDATELEN + 1];
2270 
2271  timestamp = DatumGetTimestamp(value);
2272 
2273  /* XSD doesn't support infinite values */
2274  if (TIMESTAMP_NOT_FINITE(timestamp))
2275  ereport(ERROR,
2276  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2277  errmsg("timestamp out of range"),
2278  errdetail("XML does not support infinite timestamp values.")));
2279  else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
2280  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
2281  else
2282  ereport(ERROR,
2283  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2284  errmsg("timestamp out of range")));
2285 
2286  return pstrdup(buf);
2287  }
2288 
2289 #ifdef USE_LIBXML
2290  case BYTEAOID:
2291  {
2292  bytea *bstr = DatumGetByteaPP(value);
2293  PgXmlErrorContext *xmlerrcxt;
2294  volatile xmlBufferPtr buf = NULL;
2295  volatile xmlTextWriterPtr writer = NULL;
2296  char *result;
2297 
2298  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
2299 
2300  PG_TRY();
2301  {
2302  buf = xmlBufferCreate();
2303  if (buf == NULL || xmlerrcxt->err_occurred)
2304  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2305  "could not allocate xmlBuffer");
2306  writer = xmlNewTextWriterMemory(buf, 0);
2307  if (writer == NULL || xmlerrcxt->err_occurred)
2308  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2309  "could not allocate xmlTextWriter");
2310 
2311  if (xmlbinary == XMLBINARY_BASE64)
2312  xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
2313  0, VARSIZE_ANY_EXHDR(bstr));
2314  else
2315  xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
2316  0, VARSIZE_ANY_EXHDR(bstr));
2317 
2318  /* we MUST do this now to flush data out to the buffer */
2319  xmlFreeTextWriter(writer);
2320  writer = NULL;
2321 
2322  result = pstrdup((const char *) xmlBufferContent(buf));
2323  }
2324  PG_CATCH();
2325  {
2326  if (writer)
2327  xmlFreeTextWriter(writer);
2328  if (buf)
2329  xmlBufferFree(buf);
2330 
2331  pg_xml_done(xmlerrcxt, true);
2332 
2333  PG_RE_THROW();
2334  }
2335  PG_END_TRY();
2336 
2337  xmlBufferFree(buf);
2338 
2339  pg_xml_done(xmlerrcxt, false);
2340 
2341  return result;
2342  }
2343 #endif /* USE_LIBXML */
2344 
2345  }
2346 
2347  /*
2348  * otherwise, just use the type's native text representation
2349  */
2350  getTypeOutputInfo(type, &typeOut, &isvarlena);
2351  str = OidOutputFunctionCall(typeOut, value);
2352 
2353  /* ... exactly as-is for XML, and when escaping is not wanted */
2354  if (type == XMLOID || !xml_escape_strings)
2355  return str;
2356 
2357  /* otherwise, translate special characters as needed */
2358  return escape_xml(str);
2359  }
2360 }
#define MAXDATELEN
Definition: datetime.h:201
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:3855
signed short int16
Definition: c.h:346
#define DatumGetDateADT(X)
Definition: date.h:53
#define type_is_array_domain(typid)
Definition: lsyscache.h:186
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2674
#define VARDATA_ANY(PTR)
Definition: postgres.h:348
int32 DateADT
Definition: date.h:23
int64 timestamp
int64 TimestampTz
Definition: timestamp.h:39
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2049
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1791
struct PgXmlErrorContext PgXmlErrorContext
Definition: xml.h:48
static struct @145 value
int errcode(int sqlerrcode)
Definition: elog.c:608
#define DatumGetByteaPP(X)
Definition: fmgr.h:285
long date
Definition: pgtypes_date.h:9
Definition: pgtime.h:25
unsigned int Oid
Definition: postgres_ext.h:31
static struct pg_tm tm
Definition: localtime.c:108
#define TIMESTAMP_NOT_FINITE(j)
Definition: timestamp.h:122
void pfree(void *pointer)
Definition: mcxt.c:1056
#define ERROR
Definition: elog.h:43
#define DATE_NOT_FINITE(j)
Definition: date.h:43
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
int tm_mday
Definition: pgtime.h:30
static char * buf
Definition: pg_test_fsync.c:67
int tm_mon
Definition: pgtime.h:31
int errdetail(const char *fmt,...)
Definition: elog.c:955
#define DatumGetBool(X)
Definition: postgres.h:393
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:3970
int32 fsec_t
Definition: timestamp.h:41
void pg_xml_done(PgXmlErrorContext *errcxt, bool isError)
#define ereport(elevel, rest)
Definition: elog.h:141
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:294
int64 Timestamp
Definition: timestamp.h:38
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
uintptr_t Datum
Definition: postgres.h:367
#define PG_CATCH()
Definition: elog.h:332
#define PG_RE_THROW()
Definition: elog.h:363
int xmlbinary
Definition: xml.c:97
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3461
#define USE_XSD_DATES
Definition: miscadmin.h:217
int tm_year
Definition: pgtime.h:32
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1655
#define VARSIZE_ANY_EXHDR(PTR)
Definition: postgres.h:341
int errmsg(const char *fmt,...)
Definition: elog.c:822
int i
Definition: c.h:556
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:163
char * escape_xml(const char *str)
Definition: xml.c:2371
#define PG_TRY()
Definition: elog.h:322
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2152
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2299
#define ARR_ELEMTYPE(a)
Definition: array.h:280
PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness)
#define PG_END_TRY()
Definition: elog.h:347
void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
#define DatumGetTimestamp(X)
Definition: timestamp.h:27
#define DatumGetArrayTypeP(X)
Definition: array.h:249

◆ map_xml_name_to_sql_identifier()

char* map_xml_name_to_sql_identifier ( const char *  name)

Definition at line 2112 of file xml.c.

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

Referenced by get_rule_expr().

2113 {
2115  const char *p;
2116 
2117  initStringInfo(&buf);
2118 
2119  for (p = name; *p; p += pg_mblen(p))
2120  {
2121  if (*p == '_' && *(p + 1) == 'x'
2122  && isxdigit((unsigned char) *(p + 2))
2123  && isxdigit((unsigned char) *(p + 3))
2124  && isxdigit((unsigned char) *(p + 4))
2125  && isxdigit((unsigned char) *(p + 5))
2126  && *(p + 6) == '_')
2127  {
2128  unsigned int u;
2129 
2130  sscanf(p + 2, "%X", &u);
2132  p += 6;
2133  }
2134  else
2135  appendBinaryStringInfo(&buf, p, pg_mblen(p));
2136  }
2137 
2138  return buf.data;
2139 }
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
int pg_mblen(const char *mbstr)
Definition: mbutils.c:802
const char * name
Definition: encode.c:521
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227
static char * unicode_to_sqlchar(pg_wchar c)
Definition: xml.c:2092

◆ pg_xml_done()

◆ pg_xml_error_occurred()

bool pg_xml_error_occurred ( PgXmlErrorContext errcxt)

Referenced by xml_is_document().

◆ pg_xml_init()

◆ pg_xml_init_library()

void pg_xml_init_library ( void  )

Referenced by xml_is_document().

◆ xml_ereport()

◆ xml_is_document()

bool xml_is_document ( xmltype arg)

Definition at line 888 of file xml.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, appendBinaryStringInfo(), appendStringInfo(), appendStringInfoChar(), appendStringInfoString(), Assert, CopyErrorData(), CurrentMemoryContext, StringInfoData::data, elog, encoding, ereport, errcode(), errdetail(), errdetail_internal(), errhint(), errmsg(), errmsg_internal(), ERROR, error(), FATAL, FlushErrorState(), GetDatabaseEncoding(), gettext_noop, initStringInfo(), StringInfoData::len, makeStringInfo(), MAX_MULTIBYTE_CHAR_LEN, MemoryContextAlloc(), MemoryContextStrdup(), MemoryContextSwitchTo(), name, NO_XML_SUPPORT, NOTICE, palloc(), pfree(), PG_CATCH, pg_do_encoding_conversion(), pg_encoding_mb2wchar_with_len(), pg_encoding_mblen(), pg_encoding_to_char(), PG_END_TRY, PG_FINALLY, pg_mblen(), PG_RE_THROW, pg_server_to_any(), PG_TRY, PG_UTF8, PG_XML_DEFAULT_VERSION, pg_xml_done(), pg_xml_error_occurred(), pg_xml_init(), pg_xml_init_library(), PG_XML_STRICTNESS_LEGACY, PG_XML_STRICTNESS_WELLFORMED, pstrdup(), repalloc(), ErrorData::sqlerrcode, generate_unaccent_rules::str, strnlen(), text_to_cstring(), TopMemoryContext, VARSIZE_ANY_EXHDR, WARNING, xml_ereport(), and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXmlExpr(), and xmltotext_with_xmloption().

889 {
890 #ifdef USE_LIBXML
891  bool result;
892  volatile xmlDocPtr doc = NULL;
894 
895  /* We want to catch ereport(INVALID_XML_DOCUMENT) and return false */
896  PG_TRY();
897  {
898  doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
900  result = true;
901  }
902  PG_CATCH();
903  {
904  ErrorData *errdata;
905  MemoryContext ecxt;
906 
907  ecxt = MemoryContextSwitchTo(ccxt);
908  errdata = CopyErrorData();
909  if (errdata->sqlerrcode == ERRCODE_INVALID_XML_DOCUMENT)
910  {
911  FlushErrorState();
912  result = false;
913  }
914  else
915  {
916  MemoryContextSwitchTo(ecxt);
917  PG_RE_THROW();
918  }
919  }
920  PG_END_TRY();
921 
922  if (doc)
923  xmlFreeDoc(doc);
924 
925  return result;
926 #else /* not USE_LIBXML */
927  NO_XML_SUPPORT();
928  return false;
929 #endif /* not USE_LIBXML */
930 }
#define NO_XML_SUPPORT()
Definition: xml.c:219
int sqlerrcode
Definition: elog.h:391
ErrorData * CopyErrorData(void)
Definition: elog.c:1584
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
void FlushErrorState(void)
Definition: elog.c:1678
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
int GetDatabaseEncoding(void)
Definition: mbutils.c:1046
#define PG_CATCH()
Definition: elog.h:332
#define PG_RE_THROW()
Definition: elog.h:363
Definition: c.h:556
#define PG_TRY()
Definition: elog.h:322
#define PG_END_TRY()
Definition: elog.h:347

◆ xmlconcat()

xmltype* xmlconcat ( List args)

Definition at line 512 of file xml.c.

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

Referenced by ExecEvalXmlExpr(), and xmlconcat2().

513 {
514 #ifdef USE_LIBXML
515  int global_standalone = 1;
516  xmlChar *global_version = NULL;
517  bool global_version_no_value = false;
519  ListCell *v;
520 
521  initStringInfo(&buf);
522  foreach(v, args)
523  {
525  size_t len;
526  xmlChar *version;
527  int standalone;
528  char *str;
529 
530  len = VARSIZE(x) - VARHDRSZ;
531  str = text_to_cstring((text *) x);
532 
533  parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
534 
535  if (standalone == 0 && global_standalone == 1)
536  global_standalone = 0;
537  if (standalone < 0)
538  global_standalone = -1;
539 
540  if (!version)
541  global_version_no_value = true;
542  else if (!global_version)
543  global_version = version;
544  else if (xmlStrcmp(version, global_version) != 0)
545  global_version_no_value = true;
546 
547  appendStringInfoString(&buf, str + len);
548  pfree(str);
549  }
550 
551  if (!global_version_no_value || global_standalone >= 0)
552  {
553  StringInfoData buf2;
554 
555  initStringInfo(&buf2);
556 
557  print_xml_decl(&buf2,
558  (!global_version_no_value) ? global_version : NULL,
559  0,
560  global_standalone);
561 
562  appendBinaryStringInfo(&buf2, buf.data, buf.len);
563  buf = buf2;
564  }
565 
566  return stringinfo_to_xmltype(&buf);
567 #else
568  NO_XML_SUPPORT();
569  return NULL;
570 #endif
571 }
#define NO_XML_SUPPORT()
Definition: xml.c:219
#define VARSIZE(PTR)
Definition: postgres.h:303
#define PointerGetDatum(X)
Definition: postgres.h:556
#define VARHDRSZ
Definition: c.h:562
#define DatumGetXmlP(X)
Definition: xml.h:50
void pfree(void *pointer)
Definition: mcxt.c:1056
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
#define lfirst(lc)
Definition: pg_list.h:190
char * text_to_cstring(const text *t)
Definition: varlena.c:204
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Definition: xml.c:447
Definition: c.h:556
void appendBinaryStringInfo(StringInfo str, const char *data, int datalen)
Definition: stringinfo.c:227

◆ xmlelement()

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

Definition at line 628 of file xml.c.

References arg, XmlExpr::arg_names, XmlExpr::args, 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().

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

◆ xmlparse()

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

Definition at line 752 of file xml.c.

References GetDatabaseEncoding(), and NO_XML_SUPPORT.

Referenced by ExecEvalXmlExpr(), and texttoxml().

753 {
754 #ifdef USE_LIBXML
755  xmlDocPtr doc;
756 
757  doc = xml_parse(data, xmloption_arg, preserve_whitespace,
759  xmlFreeDoc(doc);
760 
761  return (xmltype *) data;
762 #else
763  NO_XML_SUPPORT();
764  return NULL;
765 #endif
766 }
#define NO_XML_SUPPORT()
Definition: xml.c:219
int GetDatabaseEncoding(void)
Definition: mbutils.c:1046
Definition: c.h:556

◆ xmlpi()

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

Definition at line 770 of file xml.c.

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

Referenced by ExecEvalXmlExpr().

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

◆ xmlroot()

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

Definition at line 822 of file xml.c.

References appendStringInfoString(), buf, initStringInfo(), 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().

823 {
824 #ifdef USE_LIBXML
825  char *str;
826  size_t len;
827  xmlChar *orig_version;
828  int orig_standalone;
830 
831  len = VARSIZE(data) - VARHDRSZ;
832  str = text_to_cstring((text *) data);
833 
834  parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);
835 
836  if (version)
837  orig_version = xml_text2xmlChar(version);
838  else
839  orig_version = NULL;
840 
841  switch (standalone)
842  {
843  case XML_STANDALONE_YES:
844  orig_standalone = 1;
845  break;
846  case XML_STANDALONE_NO:
847  orig_standalone = 0;
848  break;
850  orig_standalone = -1;
851  break;
853  /* leave original value */
854  break;
855  }
856 
857  initStringInfo(&buf);
858  print_xml_decl(&buf, orig_version, 0, orig_standalone);
859  appendStringInfoString(&buf, str + len);
860 
861  return stringinfo_to_xmltype(&buf);
862 #else
863  NO_XML_SUPPORT();
864  return NULL;
865 #endif
866 }
#define NO_XML_SUPPORT()
Definition: xml.c:219
#define VARSIZE(PTR)
Definition: postgres.h:303
#define VARHDRSZ
Definition: c.h:562
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:176
static char * buf
Definition: pg_test_fsync.c:67
void initStringInfo(StringInfo str)
Definition: stringinfo.c:59
char * text_to_cstring(const text *t)
Definition: varlena.c:204
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Definition: xml.c:447
Definition: c.h:556

◆ xmltotext_with_xmloption()

text* xmltotext_with_xmloption ( xmltype data,
XmlOptionType  xmloption_arg 
)

Definition at line 615 of file xml.c.

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

Referenced by ExecEvalXmlExpr().

616 {
617  if (xmloption_arg == XMLOPTION_DOCUMENT && !xml_is_document(data))
618  ereport(ERROR,
619  (errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
620  errmsg("not an XML document")));
621 
622  /* It's actually binary compatible, save for the above check. */
623  return (text *) data;
624 }
int errcode(int sqlerrcode)
Definition: elog.c:608
#define ERROR
Definition: elog.h:43
#define ereport(elevel, rest)
Definition: elog.h:141
bool xml_is_document(xmltype *arg)
Definition: xml.c:888
int errmsg(const char *fmt,...)
Definition: elog.c:822
Definition: c.h:556

Variable Documentation

◆ xmlbinary

int xmlbinary

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

const TableFuncRoutine XmlTableRoutine

Definition at line 207 of file xml.c.

Referenced by ExecInitTableFuncScan().