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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Xml;
using Microsoft.Data.SqlClient;
using Microsoft.Data.SqlClient.Internal;
Expand All @@ -32,6 +33,13 @@ internal static class SqlTypeWorkarounds
private static readonly XmlReaderSettings s_defaultXmlReaderSettingsCloseInput = new() { ConformanceLevel = ConformanceLevel.Fragment, CloseInput = true };
private static readonly XmlReaderSettings s_defaultXmlReaderSettingsAsyncCloseInput = new() { Async = true, ConformanceLevel = ConformanceLevel.Fragment, CloseInput = true };

private static readonly XmlParserContext s_defaultXmlParserContext = new(
nt: null, nsMgr: null, xmlLang: string.Empty, xmlSpace: XmlSpace.None,
// Do not use SqlUnicodeEncoding here. It assumes no BOM, but some streams backing
// XmlReader (specifically, SqlStream) can have artificial BOMs. Consider removing
// artificial BOM behavior from SqlStream as a future optimization.
Encoding.Unicode);

internal const SqlCompareOptions SqlStringValidSqlCompareOptionMask =
SqlCompareOptions.BinarySort |
SqlCompareOptions.BinarySort2 |
Expand All @@ -50,7 +58,7 @@ internal static XmlReader SqlXmlCreateSqlXmlReader(Stream stream, bool closeInpu
: s_defaultXmlReaderSettingsCloseInput
: s_defaultXmlReaderSettings;

return XmlReader.Create(stream, settingsToUse);
return XmlReader.Create(stream, settingsToUse, s_defaultXmlParserContext);
}

#endregion
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ public static async Task GetFieldValueAsync_OfXmlReader(CommandBehavior behavior
using (XmlReader xmlReader = await reader.GetFieldValueAsync<XmlReader>(1))
{
isAsync = xmlReader.Settings.Async;
outputXml = GetXmlDocumentContents(xmlReader);
outputXml = GetXmlReaderContents(xmlReader);
}
}
}
Expand Down Expand Up @@ -207,7 +207,7 @@ public static async Task GetFieldValue_OfXmlReader(CommandBehavior behavior, boo
using (XmlReader xmlReader = reader.GetFieldValue<XmlReader>(1))
{
isAsync = xmlReader.Settings.Async;
outputXml = GetXmlDocumentContents(xmlReader);
outputXml = GetXmlReaderContents(xmlReader);
}
}
}
Expand Down Expand Up @@ -364,7 +364,7 @@ public static async Task GetXmlReader(CommandBehavior behavior, bool isExecuteAs
using (XmlReader xmlReader = reader.GetXmlReader(1))
{
isAsync = xmlReader.Settings.Async;
outputXml = GetXmlDocumentContents(xmlReader);
outputXml = GetXmlReaderContents(xmlReader);
}
}
}
Expand Down Expand Up @@ -481,7 +481,7 @@ public static void NullStreamProperties(CommandBehavior behavior, AccessorType a
// get a clean reader over the same field and check that the value is empty
using (XmlReader xmlReader = GetValue<XmlReader>(reader, 0, accessorType))
{
Assert.Equal(GetXmlDocumentContents(xmlReader), string.Empty);
Assert.Equal(GetXmlReaderContents(xmlReader), string.Empty);
}

using (TextReader textReader = GetValue<TextReader>(reader, 1, accessorType))
Expand Down Expand Up @@ -1169,6 +1169,11 @@ private static string CreateXmlData(int packetSize, int forcedPacketCount)
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings))
{
int index = 1;
// Purposefully start with root-level text to confuse the encoding-detection logic
// in XmlTextReaderImpl so it would assume UTF-8. This ensures tests will fail if a
// SqlDataReader creates an XmlReader over a UTF-16LE stream without explicitly
// specifying the encoding.
xmlWriter.WriteString("foo");
xmlWriter.WriteStartElement("root");
while (buffer.Length / 2 < (packetSize * forcedPacketCount))
{
Expand Down Expand Up @@ -1232,15 +1237,19 @@ private static string CreateCharDataQuery(string originalText)
return queryBuilder.ToString();
}

private static string GetXmlDocumentContents(XmlReader xmlReader)
/// <summary>
/// Serializes the contents of the specified <see cref="XmlReader"/> to a
/// <see langword="string"/>.
/// </summary>
/// <param name="xmlReader">The reader whose contents are to be serialized.</param>
/// <returns>
/// A string representation of the contents of <paramref name="xmlReader"/>.
/// </returns>
private static string GetXmlReaderContents(XmlReader xmlReader)
{
string outputXml;
XmlDocument document = new XmlDocument();
document.Load(xmlReader);

XmlWriterSettings settings = new XmlWriterSettings
{
ConformanceLevel = ConformanceLevel.Document,
ConformanceLevel = ConformanceLevel.Fragment,
Encoding = Encoding.Unicode,
Indent = true,
OmitXmlDeclaration = true
Expand All @@ -1250,10 +1259,9 @@ private static string GetXmlDocumentContents(XmlReader xmlReader)
using (StringWriter stringWriter = new StringWriter(buffer))
using (XmlWriter xmlWriter = XmlWriter.Create(stringWriter, settings))
{
document.WriteContentTo(xmlWriter);
xmlWriter.WriteNode(xmlReader, defattr: false);
}
outputXml = buffer.ToString();
return outputXml;
return buffer.ToString();
}

private static byte[] GetStreamContents(Stream stream)
Expand Down
Loading