Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitfc568b9

Browse files
committed
Allow for arbitrary data types as content in XMLELEMENT. The original
coercion to type xml was a mistake. Escape values so they are validXML character data.
1 parent1b1c6ed commitfc568b9

File tree

5 files changed

+149
-19
lines changed

5 files changed

+149
-19
lines changed

‎src/backend/parser/parse_expr.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.205 2007/01/08 23:41:56 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/parser/parse_expr.c,v 1.206 2007/01/12 16:29:24 petere Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -1455,10 +1455,6 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
14551455
newe=coerce_to_specific_type(pstate,newe,XMLOID,
14561456
"XMLCONCAT");
14571457
break;
1458-
caseIS_XMLELEMENT:
1459-
newe=coerce_to_specific_type(pstate,newe,XMLOID,
1460-
"XMLELEMENT");
1461-
break;
14621458
caseIS_XMLFOREST:
14631459
newe=coerce_to_specific_type(pstate,newe,XMLOID,
14641460
"XMLFOREST");
@@ -1488,7 +1484,7 @@ transformXmlExpr(ParseState *pstate, XmlExpr *x)
14881484
newx->args=lappend(newx->args,newe);
14891485
i++;
14901486
}
1491-
1487+
14921488
return (Node*)newx;
14931489
}
14941490

‎src/backend/utils/adt/xml.c

Lines changed: 92 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.14 2007/01/10 20:33:54 petere Exp $
10+
* $PostgreSQL: pgsql/src/backend/utils/adt/xml.c,v 1.15 2007/01/12 16:29:24 petere Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -35,12 +35,16 @@
3535
#include<libxml/xmlwriter.h>
3636
#endif/* USE_LIBXML */
3737

38+
#include"catalog/pg_type.h"
3839
#include"executor/executor.h"
3940
#include"fmgr.h"
4041
#include"libpq/pqformat.h"
4142
#include"mb/pg_wchar.h"
4243
#include"nodes/execnodes.h"
44+
#include"parser/parse_expr.h"
45+
#include"utils/array.h"
4346
#include"utils/builtins.h"
47+
#include"utils/lsyscache.h"
4448
#include"utils/memutils.h"
4549
#include"utils/xml.h"
4650

@@ -66,6 +70,8 @@ static void xml_ereport_by_code(int level, int sqlcode,
6670
staticxmlChar*xml_text2xmlChar(text*in);
6771
staticxmlDocPtrxml_parse(text*data,boolis_document,boolpreserve_whitespace);
6872

73+
staticchar*map_sql_value_to_xml_value(Datumvalue,Oidtype);
74+
6975
#endif/* USE_LIBXML */
7076

7177
#defineNO_XML_SUPPORT() \
@@ -284,13 +290,7 @@ xmlelement(XmlExprState *xmlExpr, ExprContext *econtext)
284290

285291
value=ExecEvalExpr(e,econtext,&isnull,NULL);
286292
if (!isnull)
287-
{
288-
/* we know the value is XML type */
289-
str=DatumGetCString(DirectFunctionCall1(xml_out,
290-
value));
291-
xmlTextWriterWriteRaw(writer, (xmlChar*)str);
292-
pfree(str);
293-
}
293+
xmlTextWriterWriteRaw(writer, (xmlChar*)map_sql_value_to_xml_value(value,exprType((Node*)e->expr)));
294294
}
295295

296296
xmlTextWriterEndElement(writer);
@@ -1258,3 +1258,87 @@ map_xml_name_to_sql_identifier(char *name)
12581258

12591259
returnbuf.data;
12601260
}
1261+
1262+
1263+
#ifdefUSE_LIBXML
1264+
/*
1265+
* Map SQL value to XML value; see SQL/XML:2003 section 9.16.
1266+
*/
1267+
staticchar*
1268+
map_sql_value_to_xml_value(Datumvalue,Oidtype)
1269+
{
1270+
StringInfoDatabuf;
1271+
1272+
initStringInfo(&buf);
1273+
1274+
if (is_array_type(type))
1275+
{
1276+
inti;
1277+
ArrayType*array;
1278+
Oidelmtype;
1279+
int16elmlen;
1280+
boolelmbyval;
1281+
charelmalign;
1282+
1283+
array=DatumGetArrayTypeP(value);
1284+
1285+
/* TODO: need some code-fu here to remove this limitation */
1286+
if (ARR_NDIM(array)!=1)
1287+
ereport(ERROR,
1288+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1289+
errmsg("only supported for one-dimensional array")));
1290+
1291+
elmtype=ARR_ELEMTYPE(array);
1292+
get_typlenbyvalalign(elmtype,&elmlen,&elmbyval,&elmalign);
1293+
1294+
for (i=ARR_LBOUND(array)[0];
1295+
i<ARR_LBOUND(array)[0]+ARR_DIMS(array)[0];
1296+
i++)
1297+
{
1298+
Datumsubval;
1299+
boolisnull;
1300+
1301+
subval=array_ref(array,1,&i,-1,elmlen,elmbyval,elmalign,&isnull);
1302+
appendStringInfoString(&buf,"<element>");
1303+
appendStringInfoString(&buf,map_sql_value_to_xml_value(subval,elmtype));
1304+
appendStringInfoString(&buf,"</element>");
1305+
}
1306+
}
1307+
else
1308+
{
1309+
OidtypeOut;
1310+
boolisvarlena;
1311+
char*p,*str;
1312+
1313+
getTypeOutputInfo(type,&typeOut,&isvarlena);
1314+
str=OidOutputFunctionCall(typeOut,value);
1315+
1316+
if (type==XMLOID)
1317+
returnstr;
1318+
1319+
for (p=str;*p;p+=pg_mblen(p))
1320+
{
1321+
switch (*p)
1322+
{
1323+
case'&':
1324+
appendStringInfo(&buf,"&amp;");
1325+
break;
1326+
case'<':
1327+
appendStringInfo(&buf,"&lt;");
1328+
break;
1329+
case'>':
1330+
appendStringInfo(&buf,"&gt;");
1331+
break;
1332+
case'\r':
1333+
appendStringInfo(&buf,"&#x0d;");
1334+
break;
1335+
default:
1336+
appendBinaryStringInfo(&buf,p,pg_mblen(p));
1337+
break;
1338+
}
1339+
}
1340+
}
1341+
1342+
returnbuf.data;
1343+
}
1344+
#endif/* USE_LIBXML */

‎src/test/regress/expected/xml.out

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,10 +83,44 @@ SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
8383
<employee><name>linda</name><age>19</age><pay>100</pay></employee>
8484
(6 rows)
8585

86-
SELECT xmlelement(name wrong, 37);
87-
ERROR: argument of XMLELEMENT must be type xml, not type integer
8886
SELECT xmlelement(name duplicate, xmlattributes(1 as a, 2 as b, 3 as a));
8987
ERROR: XML attribute name "a" appears more than once
88+
SELECT xmlelement(name num, 37);
89+
xmlelement
90+
---------------
91+
<num>37</num>
92+
(1 row)
93+
94+
SELECT xmlelement(name foo, text 'bar');
95+
xmlelement
96+
----------------
97+
<foo>bar</foo>
98+
(1 row)
99+
100+
SELECT xmlelement(name foo, xml 'bar');
101+
xmlelement
102+
----------------
103+
<foo>bar</foo>
104+
(1 row)
105+
106+
SELECT xmlelement(name foo, text 'b<a/>r');
107+
xmlelement
108+
-------------------------
109+
<foo>b&lt;a/&gt;r</foo>
110+
(1 row)
111+
112+
SELECT xmlelement(name foo, xml 'b<a/>r');
113+
xmlelement
114+
-------------------
115+
<foo>b<a/>r</foo>
116+
(1 row)
117+
118+
SELECT xmlelement(name foo, array[1, 2, 3]);
119+
xmlelement
120+
-------------------------------------------------------------------------
121+
<foo><element>1</element><element>2</element><element>3</element></foo>
122+
(1 row)
123+
90124
SELECT xmlparse(content 'abc');
91125
xmlparse
92126
----------

‎src/test/regress/expected/xml_1.out

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,20 @@ SELECT xmlelement(name element, xmlelement(name nested, 'stuff'));
4444
ERROR: no XML support in this installation
4545
SELECT xmlelement(name employee, xmlforest(name, age, salary as pay)) FROM emp;
4646
ERROR: no XML support in this installation
47-
SELECT xmlelement(name wrong, 37);
48-
ERROR: no XML support in this installation
4947
SELECT xmlelement(name duplicate, xmlattributes(1 as a, 2 as b, 3 as a));
5048
ERROR: no XML support in this installation
49+
SELECT xmlelement(name num, 37);
50+
ERROR: no XML support in this installation
51+
SELECT xmlelement(name foo, text 'bar');
52+
ERROR: no XML support in this installation
53+
SELECT xmlelement(name foo, xml 'bar');
54+
ERROR: no XML support in this installation
55+
SELECT xmlelement(name foo, text 'b<a/>r');
56+
ERROR: no XML support in this installation
57+
SELECT xmlelement(name foo, xml 'b<a/>r');
58+
ERROR: no XML support in this installation
59+
SELECT xmlelement(name foo, array[1, 2, 3]);
60+
ERROR: no XML support in this installation
5161
SELECT xmlparse(content 'abc');
5262
ERROR: no XML support in this installation
5363
SELECT xmlparse(content '<abc>x</abc>');

‎src/test/regress/sql/xml.sql

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,15 @@ SELECT xmlelement(name element, xmlelement(name nested, 'stuff'));
3737

3838
SELECT xmlelement(name employee, xmlforest(name, age, salaryas pay))FROM emp;
3939

40-
SELECT xmlelement(name wrong,37);
4140
SELECT xmlelement(name duplicate, xmlattributes(1as a,2as b,3as a));
4241

42+
SELECT xmlelement(name num,37);
43+
SELECT xmlelement(name foo,text'bar');
44+
SELECT xmlelement(name foo, xml'bar');
45+
SELECT xmlelement(name foo,text'b<a/>r');
46+
SELECT xmlelement(name foo, xml'b<a/>r');
47+
SELECT xmlelement(name foo, array[1,2,3]);
48+
4349

4450
SELECT xmlparse(content'abc');
4551
SELECT xmlparse(content'<abc>x</abc>');

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp