PostgreSQL Source Code git master
Loading...
Searching...
No Matches
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 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, const Datum *named_argvalue, const bool *named_argnull, const Datum *argvalue, const bool *argnull)
 
xmltypexmlparse (text *data, XmlOptionType xmloption_arg, bool preserve_whitespace, Node *escontext)
 
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)
 
charescape_xml (const char *str)
 
charmap_sql_identifier_to_xml_name (const char *ident, bool fully_escaped, bool escape_period)
 
charmap_xml_name_to_sql_identifier (const char *name)
 
charmap_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 48 of file xml.h.

◆ 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: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
static int fb(int x)
Definition c.h:776

References fb(), and PG_DETOAST_DATUM.

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

◆ escape_xml()

char * escape_xml ( const char str)
extern

Definition at line 2739 of file xml.c.

2740{
2742 const char *p;
2743
2745 for (p = str; *p; p++)
2746 {
2747 switch (*p)
2748 {
2749 case '&':
2750 appendStringInfoString(&buf, "&");
2751 break;
2752 case '<':
2753 appendStringInfoString(&buf, "&lt;");
2754 break;
2755 case '>':
2756 appendStringInfoString(&buf, "&gt;");
2757 break;
2758 case '\r':
2759 appendStringInfoString(&buf, "&#x0d;");
2760 break;
2761 default:
2763 break;
2764 }
2765 }
2766 return buf.data;
2767}
const char * str
static char buf[DEFAULT_XLOG_SEG_SIZE]
void appendStringInfoString(StringInfo str, const char *s)
Definition stringinfo.c:230
void initStringInfo(StringInfo str)
Definition stringinfo.c:97
#define appendStringInfoCharMacro(str, ch)
Definition stringinfo.h:231

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

Definition at line 2422 of file xml.c.

2424{
2425#ifdef USE_LIBXML
2427 const char *p;
2428
2429 /*
2430 * SQL/XML doesn't make use of this case anywhere, so it's probably a
2431 * mistake.
2432 */
2434
2436
2437 for (p = ident; *p; p += pg_mblen_cstr(p))
2438 {
2439 if (*p == ':' && (p == ident || fully_escaped))
2440 appendStringInfoString(&buf, "_x003A_");
2441 else if (*p == '_' && *(p + 1) == 'x')
2442 appendStringInfoString(&buf, "_x005F_");
2443 else if (fully_escaped && p == ident &&
2444 pg_strncasecmp(p, "xml", 3) == 0)
2445 {
2446 if (*p == 'x')
2447 appendStringInfoString(&buf, "_x0078_");
2448 else
2449 appendStringInfoString(&buf, "_x0058_");
2450 }
2451 else if (escape_period && *p == '.')
2452 appendStringInfoString(&buf, "_x002E_");
2453 else
2454 {
2456
2457 if ((p == ident)
2460 appendStringInfo(&buf, "_x%04X_", (unsigned int) u);
2461 else
2463 }
2464 }
2465
2466 return buf.data;
2467#else /* not USE_LIBXML */
2469 return NULL;
2470#endif /* not USE_LIBXML */
2471}
#define Assert(condition)
Definition c.h:943
#define ident
unsigned int pg_wchar
Definition mbprint.c:31
int pg_mblen_cstr(const char *mbstr)
Definition mbutils.c:1045
int pg_strncasecmp(const char *s1, const char *s2, size_t n)
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition stringinfo.c:145
void appendBinaryStringInfo(StringInfo str, const void *data, int datalen)
Definition stringinfo.c:281
#define NO_XML_SUPPORT()
Definition xml.c:234

References appendBinaryStringInfo(), appendStringInfo(), appendStringInfoString(), Assert, buf, fb(), ident, initStringInfo(), NO_XML_SUPPORT, pg_mblen_cstr(), 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 
)
extern

Definition at line 2520 of file xml.c.

2521{
2523 {
2524 ArrayType *array;
2525 Oid elmtype;
2526 int16 elmlen;
2527 bool elmbyval;
2528 char elmalign;
2529 int num_elems;
2530 Datum *elem_values;
2531 bool *elem_nulls;
2533 int i;
2534
2535 array = DatumGetArrayTypeP(value);
2536 elmtype = ARR_ELEMTYPE(array);
2537 get_typlenbyvalalign(elmtype, &elmlen, &elmbyval, &elmalign);
2538
2540 elmlen, elmbyval, elmalign,
2541 &elem_values, &elem_nulls,
2542 &num_elems);
2543
2545
2546 for (i = 0; i < num_elems; i++)
2547 {
2548 if (elem_nulls[i])
2549 continue;
2550 appendStringInfoString(&buf, "<element>");
2552 map_sql_value_to_xml_value(elem_values[i],
2553 elmtype, true));
2554 appendStringInfoString(&buf, "</element>");
2555 }
2556
2557 pfree(elem_values);
2558 pfree(elem_nulls);
2559
2560 return buf.data;
2561 }
2562 else
2563 {
2564 Oid typeOut;
2565 bool isvarlena;
2566 char *str;
2567
2568 /*
2569 * Flatten domains; the special-case treatments below should apply to,
2570 * eg, domains over boolean not just boolean.
2571 */
2573
2574 /*
2575 * Special XSD formatting for some data types
2576 */
2577 switch (type)
2578 {
2579 case BOOLOID:
2580 if (DatumGetBool(value))
2581 return "true";
2582 else
2583 return "false";
2584
2585 case DATEOID:
2586 {
2587 DateADT date;
2588 struct pg_tm tm;
2589 char buf[MAXDATELEN + 1];
2590
2592 /* XSD doesn't support infinite values */
2593 if (DATE_NOT_FINITE(date))
2594 ereport(ERROR,
2596 errmsg("date out of range"),
2597 errdetail("XML does not support infinite date values.")));
2599 &(tm.tm_year), &(tm.tm_mon), &(tm.tm_mday));
2601
2602 return pstrdup(buf);
2603 }
2604
2605 case TIMESTAMPOID:
2606 {
2608 struct pg_tm tm;
2609 fsec_t fsec;
2610 char buf[MAXDATELEN + 1];
2611
2613
2614 /* XSD doesn't support infinite values */
2616 ereport(ERROR,
2618 errmsg("timestamp out of range"),
2619 errdetail("XML does not support infinite timestamp values.")));
2620 else if (timestamp2tm(timestamp, NULL, &tm, &fsec, NULL, NULL) == 0)
2621 EncodeDateTime(&tm, fsec, false, 0, NULL, USE_XSD_DATES, buf);
2622 else
2623 ereport(ERROR,
2625 errmsg("timestamp out of range")));
2626
2627 return pstrdup(buf);
2628 }
2629
2630 case TIMESTAMPTZOID:
2631 {
2633 struct pg_tm tm;
2634 int tz;
2635 fsec_t fsec;
2636 const char *tzn = NULL;
2637 char buf[MAXDATELEN + 1];
2638
2640
2641 /* XSD doesn't support infinite values */
2643 ereport(ERROR,
2645 errmsg("timestamp out of range"),
2646 errdetail("XML does not support infinite timestamp values.")));
2647 else if (timestamp2tm(timestamp, &tz, &tm, &fsec, &tzn, NULL) == 0)
2648 EncodeDateTime(&tm, fsec, true, tz, tzn, USE_XSD_DATES, buf);
2649 else
2650 ereport(ERROR,
2652 errmsg("timestamp out of range")));
2653
2654 return pstrdup(buf);
2655 }
2656
2657#ifdef USE_LIBXML
2658 case BYTEAOID:
2659 {
2662 volatile xmlBufferPtr buf = NULL;
2663 volatile xmlTextWriterPtr writer = NULL;
2664 char *result;
2665
2667
2668 PG_TRY();
2669 {
2670 buf = xmlBufferCreate();
2671 if (buf == NULL || xmlerrcxt->err_occurred)
2673 "could not allocate xmlBuffer");
2675 if (writer == NULL || xmlerrcxt->err_occurred)
2677 "could not allocate xmlTextWriter");
2678
2682 else
2685
2686 /* we MUST do this now to flush data out to the buffer */
2688 writer = NULL;
2689
2690 result = pstrdup((const char *) xmlBufferContent(buf));
2691 }
2692 PG_CATCH();
2693 {
2694 if (writer)
2696 if (buf)
2698
2699 pg_xml_done(xmlerrcxt, true);
2700
2701 PG_RE_THROW();
2702 }
2703 PG_END_TRY();
2704
2706
2707 pg_xml_done(xmlerrcxt, false);
2708
2709 return result;
2710 }
2711#endif /* USE_LIBXML */
2712
2713 }
2714
2715 /*
2716 * otherwise, just use the type's native text representation
2717 */
2720
2721 /* ... exactly as-is for XML, and when escaping is not wanted */
2722 if (type == XMLOID || !xml_escape_strings)
2723 return str;
2724
2725 /* otherwise, translate special characters as needed */
2726 return escape_xml(str);
2727 }
2728}
#define DatumGetArrayTypeP(X)
Definition array.h:261
#define ARR_ELEMTYPE(a)
Definition array.h:292
void deconstruct_array(const ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
void j2date(int jd, int *year, int *month, int *day)
Definition datetime.c:322
void EncodeDateTime(struct pg_tm *tm, fsec_t fsec, bool print_tz, int tz, const char *tzn, int style, char *str)
Definition datetime.c:4465
void EncodeDateOnly(struct pg_tm *tm, int style, char *str)
Definition datetime.c:4350
int timestamp2tm(Timestamp dt, int *tzp, struct pg_tm *tm, fsec_t *fsec, const char **tzn, pg_tz *attimezone)
Definition timestamp.c:1904
int16_t int16
Definition c.h:619
uint32 result
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:49
int32 DateADT
Definition date.h:21
static DateADT DatumGetDateADT(Datum X)
Definition date.h:60
int errcode(int sqlerrcode)
Definition elog.c:874
#define PG_RE_THROW()
Definition elog.h:407
int errdetail(const char *fmt,...) pg_attribute_printf(1
#define PG_TRY(...)
Definition elog.h:374
#define PG_END_TRY(...)
Definition elog.h:399
#define ERROR
Definition elog.h:40
#define PG_CATCH(...)
Definition elog.h:384
#define ereport(elevel,...)
Definition elog.h:152
char * OidOutputFunctionCall(Oid functionId, Datum val)
Definition fmgr.c:1764
#define DatumGetByteaPP(X)
Definition fmgr.h:292
#define MAXDATELEN
Definition datetime.h:200
static struct @177 value
int i
Definition isn.c:77
static struct pg_tm tm
Definition localtime.c:104
void getTypeOutputInfo(Oid type, Oid *typOutput, bool *typIsVarlena)
Definition lsyscache.c:3129
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Definition lsyscache.c:2491
Oid getBaseType(Oid typid)
Definition lsyscache.c:2743
#define type_is_array_domain(typid)
Definition lsyscache.h:222
char * pstrdup(const char *in)
Definition mcxt.c:1781
void pfree(void *pointer)
Definition mcxt.c:1616
#define USE_XSD_DATES
Definition miscadmin.h:243
static char * errmsg
long date
Definition pgtypes_date.h:9
int64 timestamp
static bool DatumGetBool(Datum X)
Definition postgres.h:100
uint64_t Datum
Definition postgres.h:70
unsigned int Oid
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
static Size VARSIZE_ANY_EXHDR(const void *PTR)
Definition varatt.h:472
static char * VARDATA_ANY(const void *PTR)
Definition varatt.h:486
const char * type
int xmlbinary
Definition xml.c:108
char * map_sql_value_to_xml_value(Datum value, Oid type, bool xml_escape_strings)
Definition xml.c:2520
char * escape_xml(const char *str)
Definition xml.c:2739
struct PgXmlErrorContext PgXmlErrorContext
Definition xml.h:48
PgXmlErrorContext * pg_xml_init(PgXmlStrictness strictness)
void xml_ereport(PgXmlErrorContext *errcxt, int level, int sqlcode, const char *msg)
void pg_xml_done(PgXmlErrorContext *errcxt, bool isError)

References appendStringInfoString(), ARR_ELEMTYPE, buf, DATE_NOT_FINITE, DatumGetArrayTypeP, DatumGetBool(), DatumGetByteaPP, DatumGetDateADT(), DatumGetTimestamp(), deconstruct_array(), EncodeDateOnly(), EncodeDateTime(), ereport, errcode(), errdetail(), errmsg, ERROR, escape_xml(), fb(), 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(), result, 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(), map_sql_value_to_xml_value(), SPI_sql_row_to_xmlelement(), and xmlelement().

◆ map_xml_name_to_sql_identifier()

char * map_xml_name_to_sql_identifier ( const char name)
extern

Definition at line 2478 of file xml.c.

2479{
2481 const char *p;
2482
2484
2485 for (p = name; *p; p += pg_mblen_cstr(p))
2486 {
2487 if (*p == '_' && *(p + 1) == 'x'
2488 && isxdigit((unsigned char) *(p + 2))
2489 && isxdigit((unsigned char) *(p + 3))
2490 && isxdigit((unsigned char) *(p + 4))
2491 && isxdigit((unsigned char) *(p + 5))
2492 && *(p + 6) == '_')
2493 {
2495 unsigned int u;
2496
2497 sscanf(p + 2, "%X", &u);
2498 pg_unicode_to_server(u, (unsigned char *) cbuf);
2500 p += 6;
2501 }
2502 else
2504 }
2505
2506 return buf.data;
2507}
void pg_unicode_to_server(char32_t c, unsigned char *s)
Definition mbutils.c:875
#define MAX_UNICODE_EQUIVALENT_STRING
Definition pg_wchar.h:182
const char * name

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

Referenced by get_rule_expr().

◆ pg_xml_done()

◆ pg_xml_error_occurred()

◆ pg_xml_init()

◆ pg_xml_init_library()

void pg_xml_init_library ( void  )
extern

◆ xml_ereport()

◆ xml_is_document()

bool xml_is_document ( xmltype arg)
extern

Definition at line 1172 of file xml.c.

1173{
1174#ifdef USE_LIBXML
1175 xmlDocPtr doc;
1177
1178 /*
1179 * We'll report "true" if no soft error is reported by xml_parse().
1180 */
1182 GetDatabaseEncoding(), NULL, NULL, (Node *) &escontext);
1183 if (doc)
1184 xmlFreeDoc(doc);
1185
1186 return !escontext.error_occurred;
1187#else /* not USE_LIBXML */
1189 return false;
1190#endif /* not USE_LIBXML */
1191}
Datum arg
Definition elog.c:1322
int GetDatabaseEncoding(void)
Definition mbutils.c:1388
@ XMLOPTION_DOCUMENT
Definition primnodes.h:1619
Definition nodes.h:135

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

Referenced by ExecEvalXmlExpr().

◆ xmlconcat()

xmltype * xmlconcat ( List args)
extern

Definition at line 575 of file xml.c.

576{
577#ifdef USE_LIBXML
578 int global_standalone = 1;
580 bool global_version_no_value = false;
582 ListCell *v;
583
585 foreach(v, args)
586 {
588 size_t len;
589 xmlChar *version;
590 int standalone;
591 char *str;
592
593 len = VARSIZE(x) - VARHDRSZ;
594 str = text_to_cstring((text *) x);
595
596 parse_xml_decl((xmlChar *) str, &len, &version, NULL, &standalone);
597
598 if (standalone == 0 && global_standalone == 1)
600 if (standalone < 0)
602
603 if (!version)
605 else if (!global_version)
606 global_version = version;
607 else if (xmlStrcmp(version, global_version) != 0)
609
611 pfree(str);
612 }
613
615 {
616 StringInfoData buf2;
617
618 initStringInfo(&buf2);
619
620 print_xml_decl(&buf2,
622 0,
624
625 appendBinaryStringInfo(&buf2, buf.data, buf.len);
626 buf = buf2;
627 }
628
629 return stringinfo_to_xmltype(&buf);
630#else
632 return NULL;
633#endif
634}
#define VARHDRSZ
Definition c.h:781
int x
Definition isn.c:75
const void size_t len
#define lfirst(lc)
Definition pg_list.h:172
static Datum PointerGetDatum(const void *X)
Definition postgres.h:342
static Size VARSIZE(const void *PTR)
Definition varatt.h:298
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(), buf, StringInfoData::data, DatumGetXmlP(), fb(), 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,
const Datum named_argvalue,
const bool named_argnull,
const Datum argvalue,
const bool argnull 
)
extern

Definition at line 894 of file xml.c.

897{
898#ifdef USE_LIBXML
902 int i;
903 ListCell *arg;
904 ListCell *narg;
906 volatile xmlBufferPtr buf = NULL;
907 volatile xmlTextWriterPtr writer = NULL;
908
909 /*
910 * All arguments are already evaluated, and their values are passed in the
911 * named_argvalue/named_argnull or argvalue/argnull arrays. This avoids
912 * issues if one of the arguments involves a call to some other function
913 * or subsystem that wants to use libxml on its own terms. We examine the
914 * original XmlExpr to identify the numbers and types of the arguments.
915 */
917 i = 0;
918 foreach(arg, xexpr->named_args)
919 {
920 Expr *e = (Expr *) lfirst(arg);
921 char *str;
922
923 if (named_argnull[i])
924 str = NULL;
925 else
926 str = map_sql_value_to_xml_value(named_argvalue[i],
927 exprType((Node *) e),
928 false);
930 i++;
931 }
932
934 i = 0;
935 foreach(arg, xexpr->args)
936 {
937 Expr *e = (Expr *) lfirst(arg);
938 char *str;
939
940 /* here we can just forget NULL elements immediately */
941 if (!argnull[i])
942 {
943 str = map_sql_value_to_xml_value(argvalue[i],
944 exprType((Node *) e),
945 true);
947 }
948 i++;
949 }
950
952
953 PG_TRY();
954 {
956 if (buf == NULL || xmlerrcxt->err_occurred)
958 "could not allocate xmlBuffer");
960 if (writer == NULL || xmlerrcxt->err_occurred)
962 "could not allocate xmlTextWriter");
963
964 if (xmlTextWriterStartElement(writer, (xmlChar *) xexpr->name) < 0 ||
965 xmlerrcxt->err_occurred)
967 "could not start xml element");
968
969 forboth(arg, named_arg_strings, narg, xexpr->arg_names)
970 {
971 char *str = (char *) lfirst(arg);
972 char *argname = strVal(lfirst(narg));
973
974 if (str)
975 {
977 (xmlChar *) argname,
978 (xmlChar *) str) < 0 ||
979 xmlerrcxt->err_occurred)
981 "could not write xml attribute");
982 }
983 }
984
985 foreach(arg, arg_strings)
986 {
987 char *str = (char *) lfirst(arg);
988
989 if (xmlTextWriterWriteRaw(writer, (xmlChar *) str) < 0 ||
990 xmlerrcxt->err_occurred)
992 "could not write raw xml text");
993 }
994
996 xmlerrcxt->err_occurred)
998 "could not end xml element");
999
1000 /* we MUST do this now to flush data out to the buffer ... */
1002 writer = NULL;
1003
1005 }
1006 PG_CATCH();
1007 {
1008 if (writer)
1010 if (buf)
1012
1013 pg_xml_done(xmlerrcxt, true);
1014
1015 PG_RE_THROW();
1016 }
1017 PG_END_TRY();
1018
1020
1021 pg_xml_done(xmlerrcxt, false);
1022
1023 return result;
1024#else
1026 return NULL;
1027#endif
1028}
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:550
e
Definition pg_list.h:54
List * args
Definition primnodes.h:1635
List * named_args
Definition primnodes.h:1631
#define strVal(v)
Definition value.h:82

References arg, XmlExpr::args, buf, ERROR, exprType(), fb(), 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, result, str, strVal, and xml_ereport().

Referenced by ExecEvalXmlExpr().

◆ xmlparse()

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

Definition at line 1032 of file xml.c.

1033{
1034#ifdef USE_LIBXML
1035 xmlDocPtr doc;
1036
1038 GetDatabaseEncoding(), NULL, NULL, escontext);
1039 if (doc)
1040 xmlFreeDoc(doc);
1041
1042 if (SOFT_ERROR_OCCURRED(escontext))
1043 return NULL;
1044
1045 return (xmltype *) data;
1046#else
1048 return NULL;
1049#endif
1050}
#define SOFT_ERROR_OCCURRED(escontext)
Definition miscnodes.h:53
const void * data

References data, fb(), GetDatabaseEncoding(), NO_XML_SUPPORT, and SOFT_ERROR_OCCURRED.

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 fb(), and PointerGetDatum().

◆ xmlpi()

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

Definition at line 1054 of file xml.c.

1055{
1056#ifdef USE_LIBXML
1057 xmltype *result;
1059
1060 if (pg_strcasecmp(target, "xml") == 0)
1061 ereport(ERROR,
1063 errmsg("invalid XML processing instruction"),
1064 errdetail("XML processing instruction target name cannot be \"%s\".", target)));
1065
1066 /*
1067 * Following the SQL standard, the null check comes after the syntax check
1068 * above.
1069 */
1071 if (*result_is_null)
1072 return NULL;
1073
1075
1076 appendStringInfo(&buf, "<?%s", target);
1077
1078 if (arg != NULL)
1079 {
1080 char *string;
1081
1082 string = text_to_cstring(arg);
1083 if (strstr(string, "?>") != NULL)
1084 ereport(ERROR,
1086 errmsg("invalid XML processing instruction"),
1087 errdetail("XML processing instruction cannot contain \"?>\".")));
1088
1090 appendStringInfoString(&buf, string + strspn(string, " "));
1091 pfree(string);
1092 }
1094
1096 pfree(buf.data);
1097 return result;
1098#else
1100 return NULL;
1101#endif
1102}
int pg_strcasecmp(const char *s1, const char *s2)
char string[11]
void appendStringInfoChar(StringInfo str, char ch)
Definition stringinfo.c:242

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

Referenced by ExecEvalXmlExpr().

◆ xmlroot()

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

Definition at line 1106 of file xml.c.

1107{
1108#ifdef USE_LIBXML
1109 char *str;
1110 size_t len;
1112 int orig_standalone;
1114
1115 len = VARSIZE(data) - VARHDRSZ;
1117
1119
1120 if (version)
1121 orig_version = xml_text2xmlChar(version);
1122 else
1124
1125 switch (standalone)
1126 {
1127 case XML_STANDALONE_YES:
1128 orig_standalone = 1;
1129 break;
1130 case XML_STANDALONE_NO:
1131 orig_standalone = 0;
1132 break;
1134 orig_standalone = -1;
1135 break;
1137 /* leave original value */
1138 break;
1139 }
1140
1144
1145 return stringinfo_to_xmltype(&buf);
1146#else
1148 return NULL;
1149#endif
1150}

References appendStringInfoString(), buf, data, fb(), 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 
)
extern

Definition at line 678 of file xml.c.

679{
680#ifdef USE_LIBXML
681 text *volatile result;
685 volatile xmlBufferPtr buf = NULL;
686 volatile xmlSaveCtxtPtr ctxt = NULL;
688 PgXmlErrorContext *volatile xmlerrcxt = NULL;
689#endif
690
691 if (xmloption_arg != XMLOPTION_DOCUMENT && !indent)
692 {
693 /*
694 * We don't actually need to do anything, so just return the
695 * binary-compatible input. For backwards-compatibility reasons,
696 * allow such cases to succeed even without USE_LIBXML.
697 */
698 return (text *) data;
699 }
700
701#ifdef USE_LIBXML
702
703 /*
704 * Parse the input according to the xmloption.
705 *
706 * preserve_whitespace is set to false in case we are indenting, otherwise
707 * libxml2 will fail to indent elements that have whitespace between them.
708 */
711 (Node *) &escontext);
712 if (doc == NULL || escontext.error_occurred)
713 {
714 if (doc)
716 /* A soft error must be failure to conform to XMLOPTION_DOCUMENT */
719 errmsg("not an XML document")));
720 }
721
722 /* If we weren't asked to indent, we're done. */
723 if (!indent)
724 {
726 return (text *) data;
727 }
728
729 /*
730 * Otherwise, we gotta spin up some error handling. Unlike most other
731 * routines in this module, we already have a libxml "doc" structure to
732 * free, so we need to call pg_xml_init() inside the PG_TRY and be
733 * prepared for it to fail (typically due to palloc OOM).
734 */
735 PG_TRY();
736 {
737 size_t decl_len = 0;
738
740
741 /* The serialized data will go into this buffer. */
743
744 if (buf == NULL || xmlerrcxt->err_occurred)
746 "could not allocate xmlBuffer");
747
748 /* Detect whether there's an XML declaration */
750
751 /*
752 * Emit declaration only if the input had one. Note: some versions of
753 * xmlSaveToBuffer leak memory if a non-null encoding argument is
754 * passed, so don't do that. We don't want any encoding conversion
755 * anyway.
756 */
757 if (decl_len == 0)
758 ctxt = xmlSaveToBuffer(buf, NULL,
760 else
761 ctxt = xmlSaveToBuffer(buf, NULL,
763
764 if (ctxt == NULL || xmlerrcxt->err_occurred)
766 "could not allocate xmlSaveCtxt");
767
769 {
770 /* If it's a document, saving is easy. */
771 if (xmlSaveDoc(ctxt, doc) == -1 || xmlerrcxt->err_occurred)
773 "could not save document to xmlBuffer");
774 }
775 else if (content_nodes != NULL)
776 {
777 /*
778 * Deal with the case where we have non-singly-rooted XML.
779 * libxml's dump functions don't work well for that without help.
780 * We build a fake root node that serves as a container for the
781 * content nodes, and then iterate over the nodes.
782 */
786
787 root = xmlNewNode(NULL, (const xmlChar *) "content-root");
788 if (root == NULL || xmlerrcxt->err_occurred)
790 "could not allocate xml node");
791
792 /*
793 * This attaches root to doc, so we need not free it separately...
794 * but instead, we have to free the old root if there was one.
795 */
797 if (oldroot != NULL)
799
801 xmlerrcxt->err_occurred)
803 "could not append xml node list");
804
805 /*
806 * We use this node to insert newlines in the dump. Note: in at
807 * least some libxml versions, xmlNewDocText would not attach the
808 * node to the document even if we passed it. Therefore, manage
809 * freeing of this node manually, and pass NULL here to make sure
810 * there's not a dangling link.
811 */
812 newline = xmlNewDocText(NULL, (const xmlChar *) "\n");
813 if (newline == NULL || xmlerrcxt->err_occurred)
815 "could not allocate xml node");
816
817 for (xmlNodePtr node = root->children; node; node = node->next)
818 {
819 /* insert newlines between nodes */
820 if (node->type != XML_TEXT_NODE && node->prev != NULL)
821 {
822 if (xmlSaveTree(ctxt, newline) == -1 || xmlerrcxt->err_occurred)
823 {
826 "could not save newline to xmlBuffer");
827 }
828 }
829
830 if (xmlSaveTree(ctxt, node) == -1 || xmlerrcxt->err_occurred)
831 {
834 "could not save content to xmlBuffer");
835 }
836 }
837
839 }
840
841 if (xmlSaveClose(ctxt) == -1 || xmlerrcxt->err_occurred)
842 {
843 ctxt = NULL; /* don't try to close it again */
845 "could not close xmlSaveCtxtPtr");
846 }
847
848 /*
849 * xmlDocContentDumpOutput may add a trailing newline, so remove that.
850 */
852 {
853 const char *str = (const char *) xmlBufferContent(buf);
854 int len = xmlBufferLength(buf);
855
856 while (len > 0 && (str[len - 1] == '\n' ||
857 str[len - 1] == '\r'))
858 len--;
859
861 }
862 else
864 }
865 PG_CATCH();
866 {
867 if (ctxt)
868 xmlSaveClose(ctxt);
869 if (buf)
872
873 if (xmlerrcxt)
874 pg_xml_done(xmlerrcxt, true);
875
876 PG_RE_THROW();
877 }
878 PG_END_TRY();
879
882
883 pg_xml_done(xmlerrcxt, false);
884
885 return result;
886#else
888 return NULL;
889#endif
890}
#define newline
XmlOptionType
Definition primnodes.h:1618
tree ctl root
Definition radixtree.h:1857
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, fb(), 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, result, root, str, xml_ereport(), and XMLOPTION_DOCUMENT.

Referenced by ExecEvalXmlExpr().

Variable Documentation

◆ xmlbinary

PGDLLIMPORT int xmlbinary
extern

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

223{
224 .InitOpaque = XmlTableInitOpaque,
225 .SetDocument = XmlTableSetDocument,
226 .SetNamespace = XmlTableSetNamespace,
227 .SetRowFilter = XmlTableSetRowFilter,
228 .SetColumnFilter = XmlTableSetColumnFilter,
229 .FetchRow = XmlTableFetchRow,
230 .GetValue = XmlTableGetValue,
231 .DestroyOpaque = XmlTableDestroyOpaque
232};
static void XmlTableInitOpaque(struct TableFuncScanState *state, int natts)
Definition xml.c:4733
static void XmlTableSetNamespace(struct TableFuncScanState *state, const char *name, const char *uri)
Definition xml.c:4838
static void XmlTableSetRowFilter(struct TableFuncScanState *state, const char *path)
Definition xml.c:4864
static Datum XmlTableGetValue(struct TableFuncScanState *state, int colnum, Oid typid, int32 typmod, bool *isnull)
Definition xml.c:4976
static void XmlTableSetDocument(struct TableFuncScanState *state, Datum value)
Definition xml.c:4781
static void XmlTableDestroyOpaque(struct TableFuncScanState *state)
Definition xml.c:5128
static bool XmlTableFetchRow(struct TableFuncScanState *state)
Definition xml.c:4931
static void XmlTableSetColumnFilter(struct TableFuncScanState *state, const char *path, int colnum)
Definition xml.c:4896

Referenced by ExecInitTableFuncScan().