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 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

static xmltypeDatumGetXmlP (Datum X)
 
static Datum XmlPGetDatum (const xmltype *X)
 
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_arg, 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_options (xmltype *data, XmlOptionType xmloption_arg, bool indent)
 
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

◆ PG_GETARG_XML_P

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

Definition at line 62 of file xml.h.

◆ PG_RETURN_XML_P

#define PG_RETURN_XML_P (   x)    PG_RETURN_POINTER(x)

Definition at line 63 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

◆ DatumGetXmlP()

static xmltype* DatumGetXmlP ( Datum  X)
inlinestatic

Definition at line 51 of file xml.h.

52 {
53  return (xmltype *) PG_DETOAST_DATUM(X);
54 }
#define PG_DETOAST_DATUM(datum)
Definition: fmgr.h:240
Definition: c.h:671

References PG_DETOAST_DATUM.

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

◆ escape_xml()

char* escape_xml ( const char *  str)

Definition at line 2603 of file xml.c.

2604 {
2606  const char *p;
2607 
2608  initStringInfo(&buf);
2609  for (p = str; *p; p++)
2610  {
2611  switch (*p)
2612  {
2613  case '&':
2614  appendStringInfoString(&buf, "&");
2615  break;
2616  case '<':
2617  appendStringInfoString(&buf, "&lt;");
2618  break;
2619  case '>':
2620  appendStringInfoString(&buf, "&gt;");
2621  break;
2622  case '\r':
2623  appendStringInfoString(&buf, "&#x0d;");
2624  break;
2625  default:
2627  break;
2628  }
2629  }
2630  return buf.data;
2631 }
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 2286 of file xml.c.

2288 {
2289 #ifdef USE_LIBXML
2291  const char *p;
2292 
2293  /*
2294  * SQL/XML doesn't make use of this case anywhere, so it's probably a
2295  * mistake.
2296  */
2297  Assert(fully_escaped || !escape_period);
2298 
2299  initStringInfo(&buf);
2300 
2301  for (p = ident; *p; p += pg_mblen(p))
2302  {
2303  if (*p == ':' && (p == ident || fully_escaped))
2304  appendStringInfoString(&buf, "_x003A_");
2305  else if (*p == '_' && *(p + 1) == 'x')
2306  appendStringInfoString(&buf, "_x005F_");
2307  else if (fully_escaped && p == ident &&
2308  pg_strncasecmp(p, "xml", 3) == 0)
2309  {
2310  if (*p == 'x')
2311  appendStringInfoString(&buf, "_x0078_");
2312  else
2313  appendStringInfoString(&buf, "_x0058_");
2314  }
2315  else if (escape_period && *p == '.')
2316  appendStringInfoString(&buf, "_x002E_");
2317  else
2318  {
2319  pg_wchar u = sqlchar_to_unicode(p);
2320 
2321  if ((p == ident)
2322  ? !is_valid_xml_namefirst(u)
2323  : !is_valid_xml_namechar(u))
2324  appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
2325  else
2327  }
2328  }
2329 
2330  return buf.data;
2331 #else /* not USE_LIBXML */
2332  NO_XML_SUPPORT();
2333  return NULL;
2334 #endif /* not USE_LIBXML */
2335 }
#define ident
Definition: indent_codes.h:47
Assert(fmt[strlen(fmt) - 1] !='\n')
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1024
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 void *data, int datalen)
Definition: stringinfo.c:227
#define NO_XML_SUPPORT()
Definition: xml.c:225

References appendBinaryStringInfo(), appendStringInfo(), appendStringInfoString(), Assert(), buf, ident, 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 2384 of file xml.c.

2385 {
2387  {
2388  ArrayType *array;
2389  Oid elmtype;
2390  int16 elmlen;
2391  bool elmbyval;
2392  char elmalign;
2393  int num_elems;
2394  Datum *elem_values;
2395  bool *elem_nulls;
2397  int i;
2398 
2399  array = DatumGetArrayTypeP(value);
2400  elmtype = ARR_ELEMTYPE(array);
2401  get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
2402 
2403  deconstruct_array(array, elmtype,
2404  elmlen, elmbyval, elmalign,
2405  &elem_values, &elem_nulls,
2406  &num_elems);
2407 
2408  initStringInfo(&buf);
2409 
2410  for (i = 0; i < num_elems; i++)
2411  {
2412  if (elem_nulls[i])
2413  continue;
2414  appendStringInfoString(&buf, "<element>");
2416  map_sql_value_to_xml_value(elem_values[i],
2417  elmtype, true));
2418  appendStringInfoString(&buf, "</element>");
2419  }
2420 
2421  pfree(elem_values);
2422  pfree(elem_nulls);
2423 
2424  return buf.data;
2425  }
2426  else
2427  {
2428  Oid typeOut;
2429  bool isvarlena;
2430  char *str;
2431 
2432  /*
2433  * Flatten domains; the special-case treatments below should apply to,
2434  * eg, domains over boolean not just boolean.
2435  */
2436  type = getBaseType(type);
2437 
2438  /*
2439  * Special XSD formatting for some data types
2440  */
2441  switch (type)
2442  {
2443  case BOOLOID:
2444  if (DatumGetBool(value))
2445  return "true";
2446  else
2447  return "false";
2448 
2449  case DATEOID:
2450  {
2451  DateADT date;
2452  struct pg_tm tm;
2453  char buf[MAXDATELEN + 1];
2454 
2456  /* XSD doesn't support infinite values */
2457  if (DATE_NOT_FINITE(date))
2458  ereport(ERROR,
2459  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2460  errmsg("date out of range"),
2461  errdetail("XML does not support infinite date values.")));
2463  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2465 
2466  return pstrdup(buf);
2467  }
2468 
2469  case TIMESTAMPOID:
2470  {
2472  struct pg_tm tm;
2473  fsec_t fsec;
2474  char buf[MAXDATELEN + 1];
2475 
2477 
2478  /* XSD doesn't support infinite values */
2480  ereport(ERROR,
2481  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2482  errmsg("timestamp out of range"),
2483  errdetail("XML does not support infinite timestamp values.")));
2484  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
2485  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
2486  else
2487  ereport(ERROR,
2488  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2489  errmsg("timestamp out of range")));
2490 
2491  return pstrdup(buf);
2492  }
2493 
2494  case TIMESTAMPTZOID:
2495  {
2497  struct pg_tm tm;
2498  int tz;
2499  fsec_t fsec;
2500  const char *tzn = NULL;
2501  char buf[MAXDATELEN + 1];
2502 
2504 
2505  /* XSD doesn't support infinite values */
2507  ereport(ERROR,
2508  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2509  errmsg("timestamp out of range"),
2510  errdetail("XML does not support infinite timestamp values.")));
2511  else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
2512  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
2513  else
2514  ereport(ERROR,
2515  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2516  errmsg("timestamp out of range")));
2517 
2518  return pstrdup(buf);
2519  }
2520 
2521 #ifdef USE_LIBXML
2522  case BYTEAOID:
2523  {
2524  bytea *bstr = DatumGetByteaPP(value);
2525  PgXmlErrorContext *xmlerrcxt;
2526  volatile xmlBufferPtr buf = NULL;
2527  volatile xmlTextWriterPtr writer = NULL;
2528  char *result;
2529 
2530  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
2531 
2532  PG_TRY();
2533  {
2534  buf = xmlBufferCreate();
2535  if (buf == NULL || xmlerrcxt->err_occurred)
2536  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2537  "could not allocate xmlBuffer");
2538  writer = xmlNewTextWriterMemory(buf, 0);
2539  if (writer == NULL || xmlerrcxt->err_occurred)
2540  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2541  "could not allocate xmlTextWriter");
2542 
2543  if (xmlbinary == XMLBINARY_BASE64)
2544  xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
2545  0, VARSIZE_ANY_EXHDR(bstr));
2546  else
2547  xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
2548  0, VARSIZE_ANY_EXHDR(bstr));
2549 
2550  /* we MUST do this now to flush data out to the buffer */
2551  xmlFreeTextWriter(writer);
2552  writer = NULL;
2553 
2554  result = pstrdup((const char *) xmlBufferContent(buf));
2555  }
2556  PG_CATCH();
2557  {
2558  if (writer)
2559  xmlFreeTextWriter(writer);
2560  if (buf)
2561  xmlBufferFree(buf);
2562 
2563  pg_xml_done(xmlerrcxt, true);
2564 
2565  PG_RE_THROW();
2566  }
2567  PG_END_TRY();
2568 
2569  xmlBufferFree(buf);
2570 
2571  pg_xml_done(xmlerrcxt, false);
2572 
2573  return result;
2574  }
2575 #endif /* USE_LIBXML */
2576 
2577  }
2578 
2579  /*
2580  * otherwise, just use the type's native text representation
2581  */
2582  getTypeOutputInfo(type, &typeOut, &isvarlena);
2583  str = OidOutputFunctionCall(typeOut, value);
2584 
2585  /* ... exactly as-is for XML, and when escaping is not wanted */
2586  if (type == XMLOID || !xml_escape_strings)
2587  return str;
2588 
2589  /* otherwise, translate special characters as needed */
2590  return escape_xml(str);
2591  }
2592 }
#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:3599
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:313
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4217
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4102
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1830
signed short int16
Definition: c.h:477
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:168
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:209
#define DATE_NOT_FINITE(j)
Definition: date.h:43
int32 DateADT
Definition: date.h:23
static DateADT DatumGetDateADT(Datum X)
Definition: date.h:54
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errcode(int sqlerrcode)
Definition: elog.c:858
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define PG_RE_THROW()
Definition: elog.h:411
#define PG_TRY(...)
Definition: elog.h:370
#define PG_END_TRY(...)
Definition: elog.h:395
#define ERROR
Definition: elog.h:39
#define PG_CATCH(...)
Definition: elog.h:380
#define ereport(elevel,...)
Definition: elog.h:149
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1734
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define MAXDATELEN
Definition: datetime.h:200
static struct @147 value
int i
Definition: isn.c:73
static struct pg_tm tm
Definition: localtime.c:104
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2865
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2229
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2479
#define type_is_array_domain(typid)
Definition: lsyscache.h:208
char * pstrdup(const char *in)
Definition: mcxt.c:1644
void pfree(void *pointer)
Definition: mcxt.c:1456
#define USE_XSD_DATES
Definition: miscadmin.h:233
long date
Definition: pgtypes_date.h:9
int64 timestamp
static bool DatumGetBool(Datum X)
Definition: postgres.h:90
uintptr_t Datum
Definition: postgres.h:64
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
static Timestamp DatumGetTimestamp(Datum X)
Definition: timestamp.h:28
#define VARDATA_ANY(PTR)
Definition: varatt.h:324
#define VARSIZE_ANY_EXHDR(PTR)
Definition: varatt.h:317
int xmlbinary
Definition: xml.c:99
char * escape_xml(const char *str)
Definition: xml.c:2603
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2384
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 2342 of file xml.c.

2343 {
2345  const char *p;
2346 
2347  initStringInfo(&buf);
2348 
2349  for (p = name; *p; p += pg_mblen(p))
2350  {
2351  if (*p == '_' && *(p + 1) == 'x'
2352  && isxdigit((unsigned char) *(p + 2))
2353  && isxdigit((unsigned char) *(p + 3))
2354  && isxdigit((unsigned char) *(p + 4))
2355  && isxdigit((unsigned char) *(p + 5))
2356  && *(p + 6) == '_')
2357  {
2358  char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
2359  unsigned int u;
2360 
2361  sscanf(p + 2, "%X", &u);
2362  pg_unicode_to_server(u, (unsigned char *) cbuf);
2363  appendStringInfoString(&buf, cbuf);
2364  p += 6;
2365  }
2366  else
2368  }
2369 
2370  return buf.data;
2371 }
const char * name
Definition: encode.c:571
void pg_unicode_to_server(pg_wchar c, unsigned char *s)
Definition: mbutils.c:865
#define MAX_UNICODE_EQUIVALENT_STRING
Definition: pg_wchar.h:329

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

1066 {
1067 #ifdef USE_LIBXML
1068  xmlDocPtr doc;
1069  ErrorSaveContext escontext = {T_ErrorSaveContext};
1070 
1071  /*
1072  * We'll report "true" if no soft error is reported by xml_parse().
1073  */
1074  doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
1075  GetDatabaseEncoding(), NULL, NULL, (Node *) &escontext);
1076  if (doc)
1077  xmlFreeDoc(doc);
1078 
1079  return !escontext.error_occurred;
1080 #else /* not USE_LIBXML */
1081  NO_XML_SUPPORT();
1082  return false;
1083 #endif /* not USE_LIBXML */
1084 }
int GetDatabaseEncoding(void)
Definition: mbutils.c:1268
void * arg
@ XMLOPTION_DOCUMENT
Definition: primnodes.h:1517
bool error_occurred
Definition: miscnodes.h:46
Definition: nodes.h:129

References arg, ErrorSaveContext::error_occurred, GetDatabaseEncoding(), NO_XML_SUPPORT, and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXmlExpr().

◆ xmlconcat()

xmltype* xmlconcat ( List args)

Definition at line 522 of file xml.c.

523 {
524 #ifdef USE_LIBXML
525  int global_standalone = 1;
526  xmlChar *global_version = NULL;
527  bool global_version_no_value = false;
529  ListCell *v;
530 
532  foreach(v, args)
533  {
535  size_t len;
536  xmlChar *version;
537  int standalone;
538  char *str;
539 
540  len = VARSIZE(x) - VARHDRSZ;
541  str = text_to_cstring((text *) x);
542 
543  parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
544 
545  if (standalone == 0 && global_standalone == 1)
546  global_standalone = 0;
547  if (standalone < 0)
548  global_standalone = -1;
549 
550  if (!version)
551  global_version_no_value = true;
552  else if (!global_version)
553  global_version = version;
554  else if (xmlStrcmp(version, global_version) != 0)
555  global_version_no_value = true;
556 
558  pfree(str);
559  }
560 
561  if (!global_version_no_value || global_standalone >= 0)
562  {
563  StringInfoData buf2;
564 
565  initStringInfo(&buf2);
566 
567  print_xml_decl(&buf2,
568  (!global_version_no_value) ? global_version : NULL,
569  0,
570  global_standalone);
571 
572  appendBinaryStringInfo(&buf2, buf.data, buf.len);
573  buf = buf2;
574  }
575 
576  return stringinfo_to_xmltype(&buf);
577 #else
578  NO_XML_SUPPORT();
579  return NULL;
580 #endif
581 }
#define VARHDRSZ
Definition: c.h:676
int x
Definition: isn.c:71
const void size_t len
#define lfirst(lc)
Definition: pg_list.h:172
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
#define VARSIZE(PTR)
Definition: varatt.h:279
char * text_to_cstring(const text *t)
Definition: varlena.c:215
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Definition: xml.c:457
static xmltype * DatumGetXmlP(Datum X)
Definition: xml.h:51

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

808 {
809 #ifdef USE_LIBXML
810  xmltype *result;
811  List *named_arg_strings;
812  List *arg_strings;
813  int i;
814  ListCell *arg;
815  ListCell *narg;
816  PgXmlErrorContext *xmlerrcxt;
817  volatile xmlBufferPtr buf = NULL;
818  volatile xmlTextWriterPtr writer = NULL;
819 
820  /*
821  * All arguments are already evaluated, and their values are passed in the
822  * named_argvalue/named_argnull or argvalue/argnull arrays. This avoids
823  * issues if one of the arguments involves a call to some other function
824  * or subsystem that wants to use libxml on its own terms. We examine the
825  * original XmlExpr to identify the numbers and types of the arguments.
826  */
827  named_arg_strings = NIL;
828  i = 0;
829  foreach(arg, xexpr->named_args)
830  {
831  Expr *e = (Expr *) lfirst(arg);
832  char *str;
833 
834  if (named_argnull[i])
835  str = NULL;
836  else
837  str = map_sql_value_to_xml_value(named_argvalue[i],
838  exprType((Node *) e),
839  false);
840  named_arg_strings = lappend(named_arg_strings, str);
841  i++;
842  }
843 
844  arg_strings = NIL;
845  i = 0;
846  foreach(arg, xexpr->args)
847  {
848  Expr *e = (Expr *) lfirst(arg);
849  char *str;
850 
851  /* here we can just forget NULL elements immediately */
852  if (!argnull[i])
853  {
854  str = map_sql_value_to_xml_value(argvalue[i],
855  exprType((Node *) e),
856  true);
857  arg_strings = lappend(arg_strings, str);
858  }
859  i++;
860  }
861 
862  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
863 
864  PG_TRY();
865  {
866  buf = xmlBufferCreate();
867  if (buf == NULL || xmlerrcxt->err_occurred)
868  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
869  "could not allocate xmlBuffer");
870  writer = xmlNewTextWriterMemory(buf, 0);
871  if (writer == NULL || xmlerrcxt->err_occurred)
872  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
873  "could not allocate xmlTextWriter");
874 
875  xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);
876 
877  forboth(arg, named_arg_strings, narg, xexpr->arg_names)
878  {
879  char *str = (char *) lfirst(arg);
880  char *argname = strVal(lfirst(narg));
881 
882  if (str)
883  xmlTextWriterWriteAttribute(writer,
884  (xmlChar *) argname,
885  (xmlChar *) str);
886  }
887 
888  foreach(arg, arg_strings)
889  {
890  char *str = (char *) lfirst(arg);
891 
892  xmlTextWriterWriteRaw(writer, (xmlChar *) str);
893  }
894 
895  xmlTextWriterEndElement(writer);
896 
897  /* we MUST do this now to flush data out to the buffer ... */
898  xmlFreeTextWriter(writer);
899  writer = NULL;
900 
901  result = xmlBuffer_to_xmltype(buf);
902  }
903  PG_CATCH();
904  {
905  if (writer)
906  xmlFreeTextWriter(writer);
907  if (buf)
908  xmlBufferFree(buf);
909 
910  pg_xml_done(xmlerrcxt, true);
911 
912  PG_RE_THROW();
913  }
914  PG_END_TRY();
915 
916  xmlBufferFree(buf);
917 
918  pg_xml_done(xmlerrcxt, false);
919 
920  return result;
921 #else
922  NO_XML_SUPPORT();
923  return NULL;
924 #endif
925 }
List * lappend(List *list, void *datum)
Definition: list.c:338
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:43
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:467
e
Definition: preproc-init.c:82
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1533
List * named_args
Definition: primnodes.h:1529
#define strVal(v)
Definition: value.h:82

References arg, XmlExpr::args, buf, ERROR, exprType(), forboth, i, lappend(), lfirst, map_sql_value_to_xml_value(), 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_arg,
bool  preserve_whitespace 
)

Definition at line 929 of file xml.c.

930 {
931 #ifdef USE_LIBXML
932  xmlDocPtr doc;
933 
934  doc = xml_parse(data, xmloption_arg, preserve_whitespace,
935  GetDatabaseEncoding(), NULL, NULL, NULL);
936  xmlFreeDoc(doc);
937 
938  return (xmltype *) data;
939 #else
940  NO_XML_SUPPORT();
941  return NULL;
942 #endif
943 }
const void * data

References data, GetDatabaseEncoding(), and NO_XML_SUPPORT.

Referenced by ExecEvalXmlExpr(), and texttoxml().

◆ XmlPGetDatum()

static Datum XmlPGetDatum ( const xmltype X)
inlinestatic

Definition at line 57 of file xml.h.

58 {
59  return PointerGetDatum(X);
60 }

References PointerGetDatum().

◆ xmlpi()

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

Definition at line 947 of file xml.c.

948 {
949 #ifdef USE_LIBXML
950  xmltype *result;
952 
953  if (pg_strcasecmp(target, "xml") == 0)
954  ereport(ERROR,
955  (errcode(ERRCODE_SYNTAX_ERROR), /* really */
956  errmsg("invalid XML processing instruction"),
957  errdetail("XML processing instruction target name cannot be \"%s\".", target)));
958 
959  /*
960  * Following the SQL standard, the null check comes after the syntax check
961  * above.
962  */
963  *result_is_null = arg_is_null;
964  if (*result_is_null)
965  return NULL;
966 
968 
969  appendStringInfo(&buf, "<?%s", target);
970 
971  if (arg != NULL)
972  {
973  char *string;
974 
975  string = text_to_cstring(arg);
976  if (strstr(string, "?>") != NULL)
977  ereport(ERROR,
978  (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
979  errmsg("invalid XML processing instruction"),
980  errdetail("XML processing instruction cannot contain \"?>\".")));
981 
982  appendStringInfoChar(&buf, ' ');
983  appendStringInfoString(&buf, string + strspn(string, " "));
984  pfree(string);
985  }
986  appendStringInfoString(&buf, "?>");
987 
988  result = stringinfo_to_xmltype(&buf);
989  pfree(buf.data);
990  return result;
991 #else
992  NO_XML_SUPPORT();
993  return NULL;
994 #endif
995 }
int pg_strcasecmp(const char *s1, const char *s2)
Definition: pgstrcasecmp.c:36
char string[11]
Definition: preproc-type.c:52
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 999 of file xml.c.

1000 {
1001 #ifdef USE_LIBXML
1002  char *str;
1003  size_t len;
1004  xmlChar *orig_version;
1005  int orig_standalone;
1007 
1008  len = VARSIZE(data) - VARHDRSZ;
1009  str = text_to_cstring((text *) data);
1010 
1011  parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);
1012 
1013  if (version)
1014  orig_version = xml_text2xmlChar(version);
1015  else
1016  orig_version = NULL;
1017 
1018  switch (standalone)
1019  {
1020  case XML_STANDALONE_YES:
1021  orig_standalone = 1;
1022  break;
1023  case XML_STANDALONE_NO:
1024  orig_standalone = 0;
1025  break;
1027  orig_standalone = -1;
1028  break;
1030  /* leave original value */
1031  break;
1032  }
1033 
1034  initStringInfo(&buf);
1035  print_xml_decl(&buf, orig_version, 0, orig_standalone);
1037 
1038  return stringinfo_to_xmltype(&buf);
1039 #else
1040  NO_XML_SUPPORT();
1041  return NULL;
1042 #endif
1043 }

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_options()

text* xmltotext_with_options ( xmltype data,
XmlOptionType  xmloption_arg,
bool  indent 
)

Definition at line 625 of file xml.c.

626 {
627 #ifdef USE_LIBXML
628  text *volatile result;
629  xmlDocPtr doc;
630  XmlOptionType parsed_xmloptiontype;
631  xmlNodePtr content_nodes;
632  volatile xmlBufferPtr buf = NULL;
633  volatile xmlSaveCtxtPtr ctxt = NULL;
634  ErrorSaveContext escontext = {T_ErrorSaveContext};
635  PgXmlErrorContext *xmlerrcxt;
636 #endif
637 
638  if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
639  {
640  /*
641  * We don't actually need to do anything, so just return the
642  * binary-compatible input. For backwards-compatibility reasons,
643  * allow such cases to succeed even without USE_LIBXML.
644  */
645  return (text *) data;
646  }
647 
648 #ifdef USE_LIBXML
649  /* Parse the input according to the xmloption */
650  doc = xml_parse(data, xmloption_arg, true, GetDatabaseEncoding(),
651  &parsed_xmloptiontype, &content_nodes,
652  (Node *) &escontext);
653  if (doc == NULL || escontext.error_occurred)
654  {
655  if (doc)
656  xmlFreeDoc(doc);
657  /* A soft error must be failure to conform to XMLOPTION_DOCUMENT */
658  ereport(ERROR,
659  (errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
660  errmsg("not an XML document")));
661  }
662 
663  /* If we weren't asked to indent, we're done. */
664  if (!indent)
665  {
666  xmlFreeDoc(doc);
667  return (text *) data;
668  }
669 
670  /* Otherwise, we gotta spin up some error handling. */
671  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
672 
673  PG_TRY();
674  {
675  size_t decl_len = 0;
676 
677  /* The serialized data will go into this buffer. */
678  buf = xmlBufferCreate();
679 
680  if (buf == NULL || xmlerrcxt->err_occurred)
681  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
682  "could not allocate xmlBuffer");
683 
684  /* Detect whether there's an XML declaration */
685  parse_xml_decl(xml_text2xmlChar(data), &decl_len, NULL, NULL, NULL);
686 
687  /*
688  * Emit declaration only if the input had one. Note: some versions of
689  * xmlSaveToBuffer leak memory if a non-null encoding argument is
690  * passed, so don't do that. We don't want any encoding conversion
691  * anyway.
692  */
693  if (decl_len == 0)
694  ctxt = xmlSaveToBuffer(buf, NULL,
695  XML_SAVE_NO_DECL | XML_SAVE_FORMAT);
696  else
697  ctxt = xmlSaveToBuffer(buf, NULL,
698  XML_SAVE_FORMAT);
699 
700  if (ctxt == NULL || xmlerrcxt->err_occurred)
701  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
702  "could not allocate xmlSaveCtxt");
703 
704  if (parsed_xmloptiontype == XMLOPTION_DOCUMENT)
705  {
706  /* If it's a document, saving is easy. */
707  if (xmlSaveDoc(ctxt, doc) == -1 || xmlerrcxt->err_occurred)
708  xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
709  "could not save document to xmlBuffer");
710  }
711  else if (content_nodes != NULL)
712  {
713  /*
714  * Deal with the case where we have non-singly-rooted XML.
715  * libxml's dump functions don't work well for that without help.
716  * We build a fake root node that serves as a container for the
717  * content nodes, and then iterate over the nodes.
718  */
719  xmlNodePtr root;
720  xmlNodePtr newline;
721 
722  root = xmlNewNode(NULL, (const xmlChar *) "content-root");
723  if (root == NULL || xmlerrcxt->err_occurred)
724  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
725  "could not allocate xml node");
726 
727  /* This attaches root to doc, so we need not free it separately. */
728  xmlDocSetRootElement(doc, root);
729  xmlAddChild(root, content_nodes);
730 
731  /*
732  * We use this node to insert newlines in the dump. Note: in at
733  * least some libxml versions, xmlNewDocText would not attach the
734  * node to the document even if we passed it. Therefore, manage
735  * freeing of this node manually, and pass NULL here to make sure
736  * there's not a dangling link.
737  */
738  newline = xmlNewDocText(NULL, (const xmlChar *) "\n");
739  if (newline == NULL || xmlerrcxt->err_occurred)
740  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
741  "could not allocate xml node");
742 
743  for (xmlNodePtr node = root->children; node; node = node->next)
744  {
745  /* insert newlines between nodes */
746  if (node->type != XML_TEXT_NODE && node->prev != NULL)
747  {
748  if (xmlSaveTree(ctxt, newline) == -1 || xmlerrcxt->err_occurred)
749  {
750  xmlFreeNode(newline);
751  xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
752  "could not save newline to xmlBuffer");
753  }
754  }
755 
756  if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred)
757  {
758  xmlFreeNode(newline);
759  xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
760  "could not save content to xmlBuffer");
761  }
762  }
763 
764  xmlFreeNode(newline);
765  }
766 
767  if (xmlSaveClose(ctxt) == -1 || xmlerrcxt->err_occurred)
768  {
769  ctxt = NULL; /* don't try to close it again */
770  xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
771  "could not close xmlSaveCtxtPtr");
772  }
773 
774  result = (text *) xmlBuffer_to_xmltype(buf);
775  }
776  PG_CATCH();
777  {
778  if (ctxt)
779  xmlSaveClose(ctxt);
780  if (buf)
781  xmlBufferFree(buf);
782  if (doc)
783  xmlFreeDoc(doc);
784 
785  pg_xml_done(xmlerrcxt, true);
786 
787  PG_RE_THROW();
788  }
789  PG_END_TRY();
790 
791  xmlBufferFree(buf);
792  xmlFreeDoc(doc);
793 
794  pg_xml_done(xmlerrcxt, false);
795 
796  return result;
797 #else
798  NO_XML_SUPPORT();
799  return NULL;
800 #endif
801 }
#define newline
Definition: indent_codes.h:35
XmlOptionType
Definition: primnodes.h:1516

References buf, data, ereport, errcode(), errmsg(), ERROR, ErrorSaveContext::error_occurred, GetDatabaseEncoding(), newline, NO_XML_SUPPORT, PG_CATCH, PG_END_TRY, PG_RE_THROW, PG_TRY, pg_xml_done(), pg_xml_init(), PG_XML_STRICTNESS_ALL, xml_ereport(), and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXmlExpr().

Variable Documentation

◆ xmlbinary

PGDLLIMPORT int xmlbinary
extern

Definition at line 99 of file xml.c.

Referenced by map_sql_type_to_xmlschema_type(), and map_sql_value_to_xml_value().

◆ xmloption

PGDLLIMPORT int xmloption
extern

Definition at line 100 of file xml.c.

Referenced by texttoxml(), xml_in(), xml_is_well_formed(), and xml_recv().

◆ XmlTableRoutine

PGDLLIMPORT const TableFuncRoutine XmlTableRoutine
extern

Definition at line 213 of file xml.c.

Referenced by ExecInitTableFuncScan().