Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 52 additions & 12 deletions contrib/babelfishpg_tsql/src/tsql_for/forxml.c
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,8 @@ tsql_row_to_xml_raw(StringInfo state, Datum record, const char *element_name, bo
TupleDesc tupdesc;
HeapTupleData tmptup;
HeapTuple tuple;

bool allnull = true;

td = DatumGetHeapTupleHeader(record);

/* Extract rowtype info and find a tupdesc */
Expand All @@ -228,19 +229,34 @@ tsql_row_to_xml_raw(StringInfo state, Datum record, const char *element_name, bo
tmptup.t_data = td;
tuple = &tmptup;

/* Output opening tag */
if (elements)
/*
* Empty element name without ELEMENTS mode is not allowed — attribute-centric
* serialization requires a row tag name.
*/
if (element_name[0] == '\0' && !elements)
{
/* ELEMENTS mode: <row><col>value</col></row> */
if (xsinil)
appendStringInfo(state, "<%s " XML_XMLNS_XSI ">", element_name);
else
appendStringInfo(state, "<%s>", element_name);
ereport(ERROR,
(errcode(ERRCODE_INVALID_XML_PROCESSING_INSTRUCTION),
errmsg("Row tag omission (empty row tag name) cannot be used "
"with attribute-centric FOR XML serialization.")));
}
else

/* Output opening tag (only when element_name is non-empty) */
if (element_name[0] != '\0')
{
/* ATTRIBUTES mode: <row col="value"/> */
appendStringInfo(state, "<%s", element_name);
if (elements)
{
/* ELEMENTS mode: <row><col>value</col></row> */
if (xsinil)
appendStringInfo(state, "<%s " XML_XMLNS_XSI ">", element_name);
else
appendStringInfo(state, "<%s>", element_name);
}
else
{
/* ATTRIBUTES mode: <row col="value"/> */
appendStringInfo(state, "<%s", element_name);
}
}

for (int i = 0; i < tupdesc->natts; i++)
Expand All @@ -265,6 +281,7 @@ tsql_row_to_xml_raw(StringInfo state, Datum record, const char *element_name, bo
/* ELEMENTS mode output */
if (!isnull)
{
allnull = false;
/* Normal element: <col>value</col> */
appendStringInfo(state, "<%s>%s</%s>",
colname,
Expand All @@ -273,6 +290,7 @@ tsql_row_to_xml_raw(StringInfo state, Datum record, const char *element_name, bo
}
else if (xsinil)
{
allnull = false;
/* XSINIL: <col xsi:nil="true"/> */
appendStringInfo(state, "<%s " XML_XSI_NIL "/>", colname);
}
Expand All @@ -292,7 +310,29 @@ tsql_row_to_xml_raw(StringInfo state, Datum record, const char *element_name, bo

/* Output closing tag */
if (elements)
appendStringInfo(state, "</%s>", element_name);
{
if (element_name[0] == '\0')
{
/*
* Empty element name with ELEMENTS: no wrapper tag needed.
* Just output the child elements directly, same as PATH('').
*/
}
else if (allnull)
{
/*
* If all column values are NULL, produce a self-closing element
* like TSQL does: <row/>. Replace the '>' in the already
* appended opening tag with '/' and append '>'.
*/
state->data[state->len - 1] = '/';
appendStringInfoChar(state, '>');
}
else
{
appendStringInfo(state, "</%s>", element_name);
}
}
else
appendStringInfoString(state, "/>");

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ SELECT NULL AS a, NULL AS b FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand All @@ -170,7 +170,7 @@ SELECT NULL AS a, NULL AS b, NULL AS c, NULL AS d FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand Down Expand Up @@ -198,7 +198,7 @@ SELECT NULL AS a, NULL AS b FOR XML RAW, ELEMENTS ABSENT;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand Down Expand Up @@ -510,7 +510,7 @@ SELECT name, salary FROM forxml_raw_elements_t1 FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row><name>John</name><salary>50000</salary></row><row><name>Jane</name><salary>60000</salary></row><row><name>Bob</name></row><row><name>Alice</name><salary>70000</salary></row><row></row>
<row><name>John</name><salary>50000</salary></row><row><name>Jane</name><salary>60000</salary></row><row><name>Bob</name></row><row><name>Alice</name><salary>70000</salary></row><row/>
~~END~~


Expand Down Expand Up @@ -950,7 +950,7 @@ SELECT CAST(NULL AS VARCHAR(10)) AS null_val FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand All @@ -971,7 +971,34 @@ SELECT 1 AS a, 2 AS b FOR XML RAW(''), ELEMENTS;
GO
~~START~~
ntext
<><a>1</a><b>2</b></>
<a>1</a><b>2</b>
~~END~~


-- Empty element name without ELEMENTS (attribute-centric) - should error
SELECT 1 AS a, 2 AS b FOR XML RAW('');
GO
~~START~~
ntext
~~ERROR (Code: 33557097)~~

~~ERROR (Message: Row tag omission (empty row tag name) cannot be used with attribute-centric FOR XML serialization.)~~


-- All NULLs under attribute mode (no ELEMENTS)
SELECT NULL AS a, NULL AS b FOR XML RAW;
GO
~~START~~
ntext
<row/>
~~END~~


-- All NULLs with empty element name and ELEMENTS
SELECT NULL AS a, NULL AS b FOR XML RAW(''), ELEMENTS;
GO
~~START~~
ntext
~~END~~


Expand Down
39 changes: 33 additions & 6 deletions test/JDBC/expected/forxml-raw-elements-vu-verify.out
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ SELECT NULL AS a, NULL AS b FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand All @@ -170,7 +170,7 @@ SELECT NULL AS a, NULL AS b, NULL AS c, NULL AS d FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand Down Expand Up @@ -198,7 +198,7 @@ SELECT NULL AS a, NULL AS b FOR XML RAW, ELEMENTS ABSENT;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand Down Expand Up @@ -510,7 +510,7 @@ SELECT name, salary FROM forxml_raw_elements_t1 FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row><name>John</name><salary>50000</salary></row><row><name>Jane</name><salary>60000</salary></row><row><name>Bob</name></row><row><name>Alice</name><salary>70000</salary></row><row></row>
<row><name>John</name><salary>50000</salary></row><row><name>Jane</name><salary>60000</salary></row><row><name>Bob</name></row><row><name>Alice</name><salary>70000</salary></row><row/>
~~END~~


Expand Down Expand Up @@ -950,7 +950,7 @@ SELECT CAST(NULL AS VARCHAR(10)) AS null_val FOR XML RAW, ELEMENTS;
GO
~~START~~
ntext
<row></row>
<row/>
~~END~~


Expand All @@ -971,7 +971,34 @@ SELECT 1 AS a, 2 AS b FOR XML RAW(''), ELEMENTS;
GO
~~START~~
ntext
<><a>1</a><b>2</b></>
<a>1</a><b>2</b>
~~END~~


-- Empty element name without ELEMENTS (attribute-centric) - should error
SELECT 1 AS a, 2 AS b FOR XML RAW('');
GO
~~START~~
ntext
~~ERROR (Code: 33557097)~~

~~ERROR (Message: Row tag omission (empty row tag name) cannot be used with attribute-centric FOR XML serialization.)~~


-- All NULLs under attribute mode (no ELEMENTS)
SELECT NULL AS a, NULL AS b FOR XML RAW;
GO
~~START~~
ntext
<row/>
~~END~~


-- All NULLs with empty element name and ELEMENTS
SELECT NULL AS a, NULL AS b FOR XML RAW(''), ELEMENTS;
GO
~~START~~
ntext
~~END~~


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,18 @@ GO
SELECT 1 AS a, 2 AS b FOR XML RAW(''), ELEMENTS;
GO

-- Empty element name without ELEMENTS (attribute-centric) - should error
SELECT 1 AS a, 2 AS b FOR XML RAW('');
GO

-- All NULLs under attribute mode (no ELEMENTS)
SELECT NULL AS a, NULL AS b FOR XML RAW;
GO

-- All NULLs with empty element name and ELEMENTS
SELECT NULL AS a, NULL AS b FOR XML RAW(''), ELEMENTS;
GO

-- Element name with spaces
SELECT 1 AS a FOR XML RAW('element name'), ELEMENTS;
GO
Expand Down
12 changes: 12 additions & 0 deletions test/JDBC/input/forxml/forxml-raw-elements-vu-verify.sql
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,18 @@ GO
SELECT 1 AS a, 2 AS b FOR XML RAW(''), ELEMENTS;
GO

-- Empty element name without ELEMENTS (attribute-centric) - should error
SELECT 1 AS a, 2 AS b FOR XML RAW('');
GO

-- All NULLs under attribute mode (no ELEMENTS)
SELECT NULL AS a, NULL AS b FOR XML RAW;
GO

-- All NULLs with empty element name and ELEMENTS
SELECT NULL AS a, NULL AS b FOR XML RAW(''), ELEMENTS;
GO

-- Element name with spaces
SELECT 1 AS a FOR XML RAW('element name'), ELEMENTS;
GO
Expand Down
Loading