PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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:692

References PG_DETOAST_DATUM.

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

◆ escape_xml()

char* escape_xml ( const char *  str)

Definition at line 2695 of file xml.c.

2696 {
2698  const char *p;
2699 
2700  initStringInfo(&buf);
2701  for (p = str; *p; p++)
2702  {
2703  switch (*p)
2704  {
2705  case '&':
2706  appendStringInfoString(&buf, "&");
2707  break;
2708  case '<':
2709  appendStringInfoString(&buf, "&lt;");
2710  break;
2711  case '>':
2712  appendStringInfoString(&buf, "&gt;");
2713  break;
2714  case '\r':
2715  appendStringInfoString(&buf, "&#x0d;");
2716  break;
2717  default:
2719  break;
2720  }
2721  }
2722  return buf.data;
2723 }
const char * str
static char * buf
Definition: pg_test_fsync.c:72
void appendStringInfoString(StringInfo str, const char *s)
Definition: stringinfo.c:179
void initStringInfo(StringInfo str)
Definition: stringinfo.c:56
#define appendStringInfoCharMacro(str, ch)
Definition: stringinfo.h:204

References appendStringInfoCharMacro, appendStringInfoString(), buf, initStringInfo(), and 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 2378 of file xml.c.

2380 {
2381 #ifdef USE_LIBXML
2383  const char *p;
2384 
2385  /*
2386  * SQL/XML doesn't make use of this case anywhere, so it's probably a
2387  * mistake.
2388  */
2389  Assert(fully_escaped || !escape_period);
2390 
2391  initStringInfo(&buf);
2392 
2393  for (p = ident; *p; p += pg_mblen(p))
2394  {
2395  if (*p == ':' && (p == ident || fully_escaped))
2396  appendStringInfoString(&buf, "_x003A_");
2397  else if (*p == '_' && *(p + 1) == 'x')
2398  appendStringInfoString(&buf, "_x005F_");
2399  else if (fully_escaped && p == ident &&
2400  pg_strncasecmp(p, "xml", 3) == 0)
2401  {
2402  if (*p == 'x')
2403  appendStringInfoString(&buf, "_x0078_");
2404  else
2405  appendStringInfoString(&buf, "_x0058_");
2406  }
2407  else if (escape_period && *p == '.')
2408  appendStringInfoString(&buf, "_x002E_");
2409  else
2410  {
2411  pg_wchar u = sqlchar_to_unicode(p);
2412 
2413  if ((p == ident)
2414  ? !is_valid_xml_namefirst(u)
2415  : !is_valid_xml_namechar(u))
2416  appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
2417  else
2419  }
2420  }
2421 
2422  return buf.data;
2423 #else /* not USE_LIBXML */
2424  NO_XML_SUPPORT();
2425  return NULL;
2426 #endif /* not USE_LIBXML */
2427 }
#define Assert(condition)
Definition: c.h:863
#define ident
Definition: indent_codes.h:47
unsigned int pg_wchar
Definition: mbprint.c:31
int pg_mblen(const char *mbstr)
Definition: mbutils.c:1023
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:94
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition: stringinfo.c:230
#define NO_XML_SUPPORT()
Definition: xml.c:235

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

2477 {
2479  {
2480  ArrayType *array;
2481  Oid elmtype;
2482  int16 elmlen;
2483  bool elmbyval;
2484  char elmalign;
2485  int num_elems;
2486  Datum *elem_values;
2487  bool *elem_nulls;
2489  int i;
2490 
2491  array = DatumGetArrayTypeP(value);
2492  elmtype = ARR_ELEMTYPE(array);
2493  get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
2494 
2495  deconstruct_array(array, elmtype,
2496  elmlen, elmbyval, elmalign,
2497  &elem_values, &elem_nulls,
2498  &num_elems);
2499 
2500  initStringInfo(&buf);
2501 
2502  for (i = 0; i < num_elems; i++)
2503  {
2504  if (elem_nulls[i])
2505  continue;
2506  appendStringInfoString(&buf, "<element>");
2508  map_sql_value_to_xml_value(elem_values[i],
2509  elmtype, true));
2510  appendStringInfoString(&buf, "</element>");
2511  }
2512 
2513  pfree(elem_values);
2514  pfree(elem_nulls);
2515 
2516  return buf.data;
2517  }
2518  else
2519  {
2520  Oid typeOut;
2521  bool isvarlena;
2522  char *str;
2523 
2524  /*
2525  * Flatten domains; the special-case treatments below should apply to,
2526  * eg, domains over boolean not just boolean.
2527  */
2528  type = getBaseType(type);
2529 
2530  /*
2531  * Special XSD formatting for some data types
2532  */
2533  switch (type)
2534  {
2535  case BOOLOID:
2536  if (DatumGetBool(value))
2537  return "true";
2538  else
2539  return "false";
2540 
2541  case DATEOID:
2542  {
2543  DateADT date;
2544  struct pg_tm tm;
2545  char buf[MAXDATELEN + 1];
2546 
2548  /* XSD doesn't support infinite values */
2549  if (DATE_NOT_FINITE(date))
2550  ereport(ERROR,
2551  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2552  errmsg("date out of range"),
2553  errdetail("XML does not support infinite date values.")));
2555  &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2557 
2558  return pstrdup(buf);
2559  }
2560 
2561  case TIMESTAMPOID:
2562  {
2564  struct pg_tm tm;
2565  fsec_t fsec;
2566  char buf[MAXDATELEN + 1];
2567 
2569 
2570  /* XSD doesn't support infinite values */
2572  ereport(ERROR,
2573  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2574  errmsg("timestamp out of range"),
2575  errdetail("XML does not support infinite timestamp values.")));
2576  else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
2577  EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
2578  else
2579  ereport(ERROR,
2580  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2581  errmsg("timestamp out of range")));
2582 
2583  return pstrdup(buf);
2584  }
2585 
2586  case TIMESTAMPTZOID:
2587  {
2589  struct pg_tm tm;
2590  int tz;
2591  fsec_t fsec;
2592  const char *tzn = NULL;
2593  char buf[MAXDATELEN + 1];
2594 
2596 
2597  /* XSD doesn't support infinite values */
2599  ereport(ERROR,
2600  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2601  errmsg("timestamp out of range"),
2602  errdetail("XML does not support infinite timestamp values.")));
2603  else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
2604  EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
2605  else
2606  ereport(ERROR,
2607  (errcode(ERRCODE_DATETIME_VALUE_OUT_OF_RANGE),
2608  errmsg("timestamp out of range")));
2609 
2610  return pstrdup(buf);
2611  }
2612 
2613 #ifdef USE_LIBXML
2614  case BYTEAOID:
2615  {
2616  bytea *bstr = DatumGetByteaPP(value);
2617  PgXmlErrorContext *xmlerrcxt;
2618  volatile xmlBufferPtr buf = NULL;
2619  volatile xmlTextWriterPtr writer = NULL;
2620  char *result;
2621 
2622  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
2623 
2624  PG_TRY();
2625  {
2626  buf = xmlBufferCreate();
2627  if (buf == NULL || xmlerrcxt->err_occurred)
2628  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2629  "could not allocate xmlBuffer");
2630  writer = xmlNewTextWriterMemory(buf, 0);
2631  if (writer == NULL || xmlerrcxt->err_occurred)
2632  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
2633  "could not allocate xmlTextWriter");
2634 
2635  if (xmlbinary == XMLBINARY_BASE64)
2636  xmlTextWriterWriteBase64(writer, VARDATA_ANY(bstr),
2637  0, VARSIZE_ANY_EXHDR(bstr));
2638  else
2639  xmlTextWriterWriteBinHex(writer, VARDATA_ANY(bstr),
2640  0, VARSIZE_ANY_EXHDR(bstr));
2641 
2642  /* we MUST do this now to flush data out to the buffer */
2643  xmlFreeTextWriter(writer);
2644  writer = NULL;
2645 
2646  result = pstrdup((const char *) xmlBufferContent(buf));
2647  }
2648  PG_CATCH();
2649  {
2650  if (writer)
2651  xmlFreeTextWriter(writer);
2652  if (buf)
2653  xmlBufferFree(buf);
2654 
2655  pg_xml_done(xmlerrcxt, true);
2656 
2657  PG_RE_THROW();
2658  }
2659  PG_END_TRY();
2660 
2661  xmlBufferFree(buf);
2662 
2663  pg_xml_done(xmlerrcxt, false);
2664 
2665  return result;
2666  }
2667 #endif /* USE_LIBXML */
2668 
2669  }
2670 
2671  /*
2672  * otherwise, just use the type's native text representation
2673  */
2674  getTypeOutputInfo(type, &typeOut, &isvarlena);
2675  str = OidOutputFunctionCall(typeOut, value);
2676 
2677  /* ... exactly as-is for XML, and when escaping is not wanted */
2678  if (type == XMLOID || !xml_escape_strings)
2679  return str;
2680 
2681  /* otherwise, translate special characters as needed */
2682  return escape_xml(str);
2683  }
2684 }
#define DatumGetArrayTypeP(X)
Definition: array.h:261
#define ARR_ELEMTYPE(a)
Definition: array.h:292
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Definition: arrayfuncs.c:3631
void j2date(int jd, int *year, int *month, int *day)
Definition: datetime.c:311
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition: datetime.c:4342
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition: datetime.c:4227
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition: timestamp.c:1891
signed short int16
Definition: c.h:507
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:169
#define POSTGRES_EPOCH_JDATE
Definition: timestamp.h:235
#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:1203
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define PG_RE_THROW()
Definition: elog.h:412
#define PG_TRY(...)
Definition: elog.h:371
#define PG_END_TRY(...)
Definition: elog.h:396
#define ERROR
Definition: elog.h:39
#define PG_CATCH(...)
Definition: elog.h:381
#define ereport(elevel,...)
Definition: elog.h:149
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition: fmgr.c:1763
#define DatumGetByteaPP(X)
Definition: fmgr.h:291
#define MAXDATELEN
Definition: datetime.h:200
static struct @160 value
int i
Definition: isn.c:72
static struct pg_tm tm
Definition: localtime.c:104
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition: lsyscache.c:2907
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition: lsyscache.c:2271
Oid getBaseType(Oid typid)
Definition: lsyscache.c:2521
#define type_is_array_domain(typid)
Definition: lsyscache.h:211
char * pstrdup(const char *in)
Definition: mcxt.c:1696
void pfree(void *pointer)
Definition: mcxt.c:1521
#define USE_XSD_DATES
Definition: miscadmin.h:239
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
const char * type
int xmlbinary
Definition: xml.c:109
char * escape_xml(const char *str)
Definition: xml.c:2695
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition: xml.c:2476
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(), str, timestamp2tm(), TIMESTAMP_NOT_FINITE, tm, pg_tm::tm_mday, pg_tm::tm_mon, pg_tm::tm_year, 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 2434 of file xml.c.

2435 {
2437  const char *p;
2438 
2439  initStringInfo(&buf);
2440 
2441  for (p = name; *p; p += pg_mblen(p))
2442  {
2443  if (*p == '_' && *(p + 1) == 'x'
2444  && isxdigit((unsigned char) *(p + 2))
2445  && isxdigit((unsigned char) *(p + 3))
2446  && isxdigit((unsigned char) *(p + 4))
2447  && isxdigit((unsigned char) *(p + 5))
2448  && *(p + 6) == '_')
2449  {
2450  char cbuf[MAX_UNICODE_EQUIVALENT_STRING + 1];
2451  unsigned int u;
2452 
2453  sscanf(p + 2, "%X", &u);
2454  pg_unicode_to_server(u, (unsigned char *) cbuf);
2455  appendStringInfoString(&buf, cbuf);
2456  p += 6;
2457  }
2458  else
2460  }
2461 
2462  return buf.data;
2463 }
void pg_unicode_to_server(pg_wchar c, unsigned char *s)
Definition: mbutils.c:864
#define MAX_UNICODE_EQUIVALENT_STRING
Definition: pg_wchar.h:329
const char * name

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

1118 {
1119 #ifdef USE_LIBXML
1120  xmlDocPtr doc;
1121  ErrorSaveContext escontext = {T_ErrorSaveContext};
1122 
1123  /*
1124  * We'll report "true" if no soft error is reported by xml_parse().
1125  */
1126  doc = xml_parse((text *) arg, XMLOPTION_DOCUMENT, true,
1127  GetDatabaseEncoding(), NULL, NULL, (Node *) &escontext);
1128  if (doc)
1129  xmlFreeDoc(doc);
1130 
1131  return !escontext.error_occurred;
1132 #else /* not USE_LIBXML */
1133  NO_XML_SUPPORT();
1134  return false;
1135 #endif /* not USE_LIBXML */
1136 }
int GetDatabaseEncoding(void)
Definition: mbutils.c:1261
void * arg
@ XMLOPTION_DOCUMENT
Definition: primnodes.h:1592
bool error_occurred
Definition: miscnodes.h:47
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 553 of file xml.c.

554 {
555 #ifdef USE_LIBXML
556  int global_standalone = 1;
557  xmlChar *global_version = NULL;
558  bool global_version_no_value = false;
560  ListCell *v;
561 
563  foreach(v, args)
564  {
566  size_t len;
567  xmlChar *version;
568  int standalone;
569  char *str;
570 
571  len = VARSIZE(x) - VARHDRSZ;
572  str = text_to_cstring((text *) x);
573 
574  parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
575 
576  if (standalone == 0 && global_standalone == 1)
577  global_standalone = 0;
578  if (standalone < 0)
579  global_standalone = -1;
580 
581  if (!version)
582  global_version_no_value = true;
583  else if (!global_version)
584  global_version = version;
585  else if (xmlStrcmp(version, global_version) != 0)
586  global_version_no_value = true;
587 
589  pfree(str);
590  }
591 
592  if (!global_version_no_value || global_standalone >= 0)
593  {
594  StringInfoData buf2;
595 
596  initStringInfo(&buf2);
597 
598  print_xml_decl(&buf2,
599  (!global_version_no_value) ? global_version : NULL,
600  0,
601  global_standalone);
602 
603  appendBinaryStringInfo(&buf2, buf.data, buf.len);
604  buf = buf2;
605  }
606 
607  return stringinfo_to_xmltype(&buf);
608 #else
609  NO_XML_SUPPORT();
610  return NULL;
611 #endif
612 }
#define VARHDRSZ
Definition: c.h:697
int x
Definition: isn.c:70
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:217
static xmltype * stringinfo_to_xmltype(StringInfo buf)
Definition: xml.c:467
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(), 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 857 of file xml.c.

860 {
861 #ifdef USE_LIBXML
862  xmltype *result;
863  List *named_arg_strings;
864  List *arg_strings;
865  int i;
866  ListCell *arg;
867  ListCell *narg;
868  PgXmlErrorContext *xmlerrcxt;
869  volatile xmlBufferPtr buf = NULL;
870  volatile xmlTextWriterPtr writer = NULL;
871 
872  /*
873  * All arguments are already evaluated, and their values are passed in the
874  * named_argvalue/named_argnull or argvalue/argnull arrays. This avoids
875  * issues if one of the arguments involves a call to some other function
876  * or subsystem that wants to use libxml on its own terms. We examine the
877  * original XmlExpr to identify the numbers and types of the arguments.
878  */
879  named_arg_strings = NIL;
880  i = 0;
881  foreach(arg, xexpr->named_args)
882  {
883  Expr *e = (Expr *) lfirst(arg);
884  char *str;
885 
886  if (named_argnull[i])
887  str = NULL;
888  else
889  str = map_sql_value_to_xml_value(named_argvalue[i],
890  exprType((Node *) e),
891  false);
892  named_arg_strings = lappend(named_arg_strings, str);
893  i++;
894  }
895 
896  arg_strings = NIL;
897  i = 0;
898  foreach(arg, xexpr->args)
899  {
900  Expr *e = (Expr *) lfirst(arg);
901  char *str;
902 
903  /* here we can just forget NULL elements immediately */
904  if (!argnull[i])
905  {
906  str = map_sql_value_to_xml_value(argvalue[i],
907  exprType((Node *) e),
908  true);
909  arg_strings = lappend(arg_strings, str);
910  }
911  i++;
912  }
913 
914  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
915 
916  PG_TRY();
917  {
918  buf = xmlBufferCreate();
919  if (buf == NULL || xmlerrcxt->err_occurred)
920  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
921  "could not allocate xmlBuffer");
922  writer = xmlNewTextWriterMemory(buf, 0);
923  if (writer == NULL || xmlerrcxt->err_occurred)
924  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
925  "could not allocate xmlTextWriter");
926 
927  xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name);
928 
929  forboth(arg, named_arg_strings, narg, xexpr->arg_names)
930  {
931  char *str = (char *) lfirst(arg);
932  char *argname = strVal(lfirst(narg));
933 
934  if (str)
935  xmlTextWriterWriteAttribute(writer,
936  (xmlChar *) argname,
937  (xmlChar *) str);
938  }
939 
940  foreach(arg, arg_strings)
941  {
942  char *str = (char *) lfirst(arg);
943 
944  xmlTextWriterWriteRaw(writer, (xmlChar *) str);
945  }
946 
947  xmlTextWriterEndElement(writer);
948 
949  /* we MUST do this now to flush data out to the buffer ... */
950  xmlFreeTextWriter(writer);
951  writer = NULL;
952 
953  result = xmlBuffer_to_xmltype(buf);
954  }
955  PG_CATCH();
956  {
957  if (writer)
958  xmlFreeTextWriter(writer);
959  if (buf)
960  xmlBufferFree(buf);
961 
962  pg_xml_done(xmlerrcxt, true);
963 
964  PG_RE_THROW();
965  }
966  PG_END_TRY();
967 
968  xmlBufferFree(buf);
969 
970  pg_xml_done(xmlerrcxt, false);
971 
972  return result;
973 #else
974  NO_XML_SUPPORT();
975  return NULL;
976 #endif
977 }
List * lappend(List *list, void *datum)
Definition: list.c:339
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
e
Definition: preproc-init.c:82
Definition: pg_list.h:54
List * args
Definition: primnodes.h:1608
List * named_args
Definition: primnodes.h:1604
#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, str, strVal, and xml_ereport().

Referenced by ExecEvalXmlExpr().

◆ xmlparse()

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

Definition at line 981 of file xml.c.

982 {
983 #ifdef USE_LIBXML
984  xmlDocPtr doc;
985 
986  doc = xml_parse(data, xmloption_arg, preserve_whitespace,
987  GetDatabaseEncoding(), NULL, NULL, NULL);
988  xmlFreeDoc(doc);
989 
990  return (xmltype *) data;
991 #else
992  NO_XML_SUPPORT();
993  return NULL;
994 #endif
995 }
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 999 of file xml.c.

1000 {
1001 #ifdef USE_LIBXML
1002  xmltype *result;
1004 
1005  if (pg_strcasecmp(target, "xml") == 0)
1006  ereport(ERROR,
1007  (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
1008  errmsg("invalid XML processing instruction"),
1009  errdetail("XML processing instruction target name cannot be \"%s\".", target)));
1010 
1011  /*
1012  * Following the SQL standard, the null check comes after the syntax check
1013  * above.
1014  */
1015  *result_is_null = arg_is_null;
1016  if (*result_is_null)
1017  return NULL;
1018 
1019  initStringInfo(&buf);
1020 
1021  appendStringInfo(&buf, "<?%s", target);
1022 
1023  if (arg != NULL)
1024  {
1025  char *string;
1026 
1027  string = text_to_cstring(arg);
1028  if (strstr(string, "?>") != NULL)
1029  ereport(ERROR,
1030  (errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
1031  errmsg("invalid XML processing instruction"),
1032  errdetail("XML processing instruction cannot contain \"?>\".")));
1033 
1034  appendStringInfoChar(&buf, ' ');
1035  appendStringInfoString(&buf, string + strspn(string, " "));
1036  pfree(string);
1037  }
1038  appendStringInfoString(&buf, "?>");
1039 
1040  result = stringinfo_to_xmltype(&buf);
1041  pfree(buf.data);
1042  return result;
1043 #else
1044  NO_XML_SUPPORT();
1045  return NULL;
1046 #endif
1047 }
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:191

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

1052 {
1053 #ifdef USE_LIBXML
1054  char *str;
1055  size_t len;
1056  xmlChar *orig_version;
1057  int orig_standalone;
1059 
1060  len = VARSIZE(data) - VARHDRSZ;
1061  str = text_to_cstring((text *) data);
1062 
1063  parse_xml_decl((xmlChar *) str, &len, &orig_version, NULL, &orig_standalone);
1064 
1065  if (version)
1066  orig_version = xml_text2xmlChar(version);
1067  else
1068  orig_version = NULL;
1069 
1070  switch (standalone)
1071  {
1072  case XML_STANDALONE_YES:
1073  orig_standalone = 1;
1074  break;
1075  case XML_STANDALONE_NO:
1076  orig_standalone = 0;
1077  break;
1079  orig_standalone = -1;
1080  break;
1082  /* leave original value */
1083  break;
1084  }
1085 
1086  initStringInfo(&buf);
1087  print_xml_decl(&buf, orig_version, 0, orig_standalone);
1089 
1090  return stringinfo_to_xmltype(&buf);
1091 #else
1092  NO_XML_SUPPORT();
1093  return NULL;
1094 #endif
1095 }

References appendStringInfoString(), buf, data, initStringInfo(), len, NO_XML_SUPPORT, 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 656 of file xml.c.

657 {
658 #ifdef USE_LIBXML
659  text *volatile result;
660  xmlDocPtr doc;
661  XmlOptionType parsed_xmloptiontype;
662  xmlNodePtr content_nodes;
663  volatile xmlBufferPtr buf = NULL;
664  volatile xmlSaveCtxtPtr ctxt = NULL;
665  ErrorSaveContext escontext = {T_ErrorSaveContext};
666  PgXmlErrorContext *xmlerrcxt;
667 #endif
668 
669  if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
670  {
671  /*
672  * We don't actually need to do anything, so just return the
673  * binary-compatible input. For backwards-compatibility reasons,
674  * allow such cases to succeed even without USE_LIBXML.
675  */
676  return (text *) data;
677  }
678 
679 #ifdef USE_LIBXML
680 
681  /*
682  * Parse the input according to the xmloption.
683  *
684  * preserve_whitespace is set to false in case we are indenting, otherwise
685  * libxml2 will fail to indent elements that have whitespace between them.
686  */
687  doc = xml_parse(data, xmloption_arg, !indent, GetDatabaseEncoding(),
688  &parsed_xmloptiontype, &content_nodes,
689  (Node *) &escontext);
690  if (doc == NULL || escontext.error_occurred)
691  {
692  if (doc)
693  xmlFreeDoc(doc);
694  /* A soft error must be failure to conform to XMLOPTION_DOCUMENT */
695  ereport(ERROR,
696  (errcode(ERRCODE_NOT_AN_XML_DOCUMENT),
697  errmsg("not an XML document")));
698  }
699 
700  /* If we weren't asked to indent, we're done. */
701  if (!indent)
702  {
703  xmlFreeDoc(doc);
704  return (text *) data;
705  }
706 
707  /* Otherwise, we gotta spin up some error handling. */
708  xmlerrcxt = pg_xml_init(PG_XML_STRICTNESS_ALL);
709 
710  PG_TRY();
711  {
712  size_t decl_len = 0;
713 
714  /* The serialized data will go into this buffer. */
715  buf = xmlBufferCreate();
716 
717  if (buf == NULL || xmlerrcxt->err_occurred)
718  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
719  "could not allocate xmlBuffer");
720 
721  /* Detect whether there's an XML declaration */
722  parse_xml_decl(xml_text2xmlChar(data), &decl_len, NULL, NULL, NULL);
723 
724  /*
725  * Emit declaration only if the input had one. Note: some versions of
726  * xmlSaveToBuffer leak memory if a non-null encoding argument is
727  * passed, so don't do that. We don't want any encoding conversion
728  * anyway.
729  */
730  if (decl_len == 0)
731  ctxt = xmlSaveToBuffer(buf, NULL,
732  XML_SAVE_NO_DECL | XML_SAVE_FORMAT);
733  else
734  ctxt = xmlSaveToBuffer(buf, NULL,
735  XML_SAVE_FORMAT);
736 
737  if (ctxt == NULL || xmlerrcxt->err_occurred)
738  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
739  "could not allocate xmlSaveCtxt");
740 
741  if (parsed_xmloptiontype == XMLOPTION_DOCUMENT)
742  {
743  /* If it's a document, saving is easy. */
744  if (xmlSaveDoc(ctxt, doc) == -1 || xmlerrcxt->err_occurred)
745  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
746  "could not save document to xmlBuffer");
747  }
748  else if (content_nodes != NULL)
749  {
750  /*
751  * Deal with the case where we have non-singly-rooted XML.
752  * libxml's dump functions don't work well for that without help.
753  * We build a fake root node that serves as a container for the
754  * content nodes, and then iterate over the nodes.
755  */
756  xmlNodePtr root;
757  xmlNodePtr newline;
758 
759  root = xmlNewNode(NULL, (const xmlChar *) "content-root");
760  if (root == NULL || xmlerrcxt->err_occurred)
761  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
762  "could not allocate xml node");
763 
764  /* This attaches root to doc, so we need not free it separately. */
765  xmlDocSetRootElement(doc, root);
766  xmlAddChildList(root, content_nodes);
767 
768  /*
769  * We use this node to insert newlines in the dump. Note: in at
770  * least some libxml versions, xmlNewDocText would not attach the
771  * node to the document even if we passed it. Therefore, manage
772  * freeing of this node manually, and pass NULL here to make sure
773  * there's not a dangling link.
774  */
775  newline = xmlNewDocText(NULL, (const xmlChar *) "\n");
776  if (newline == NULL || xmlerrcxt->err_occurred)
777  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
778  "could not allocate xml node");
779 
780  for (xmlNodePtr node = root->children; node; node = node->next)
781  {
782  /* insert newlines between nodes */
783  if (node->type != XML_TEXT_NODE && node->prev != NULL)
784  {
785  if (xmlSaveTree(ctxt, newline) == -1 || xmlerrcxt->err_occurred)
786  {
787  xmlFreeNode(newline);
788  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
789  "could not save newline to xmlBuffer");
790  }
791  }
792 
793  if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred)
794  {
795  xmlFreeNode(newline);
796  xml_ereport(xmlerrcxt, ERROR, ERRCODE_OUT_OF_MEMORY,
797  "could not save content to xmlBuffer");
798  }
799  }
800 
801  xmlFreeNode(newline);
802  }
803 
804  if (xmlSaveClose(ctxt) == -1 || xmlerrcxt->err_occurred)
805  {
806  ctxt = NULL; /* don't try to close it again */
807  xml_ereport(xmlerrcxt, ERROR, ERRCODE_INTERNAL_ERROR,
808  "could not close xmlSaveCtxtPtr");
809  }
810 
811  /*
812  * xmlDocContentDumpOutput may add a trailing newline, so remove that.
813  */
814  if (xmloption_arg == XMLOPTION_DOCUMENT)
815  {
816  const char *str = (const char *) xmlBufferContent(buf);
817  int len = xmlBufferLength(buf);
818 
819  while (len > 0 && (str[len - 1] == '\n' ||
820  str[len - 1] == '\r'))
821  len--;
822 
823  result = cstring_to_text_with_len(str, len);
824  }
825  else
826  result = (text *) xmlBuffer_to_xmltype(buf);
827  }
828  PG_CATCH();
829  {
830  if (ctxt)
831  xmlSaveClose(ctxt);
832  if (buf)
833  xmlBufferFree(buf);
834  if (doc)
835  xmlFreeDoc(doc);
836 
837  pg_xml_done(xmlerrcxt, true);
838 
839  PG_RE_THROW();
840  }
841  PG_END_TRY();
842 
843  xmlBufferFree(buf);
844  xmlFreeDoc(doc);
845 
846  pg_xml_done(xmlerrcxt, false);
847 
848  return result;
849 #else
850  NO_XML_SUPPORT();
851  return NULL;
852 #endif
853 }
#define newline
Definition: indent_codes.h:35
XmlOptionType
Definition: primnodes.h:1591
tree ctl root
Definition: radixtree.h:1886
text * cstring_to_text_with_len(const char *s, int len)
Definition: varlena.c:196

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

Referenced by ExecEvalXmlExpr().

Variable Documentation

◆ xmlbinary

PGDLLIMPORT int xmlbinary
extern

Definition at line 109 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 110 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 223 of file xml.c.

Referenced by ExecInitTableFuncScan().