Export headers in an empty result set (#1434)

* Minimal changes to make headers appear on empty result sets

* Columns for everyone!

* Updating tests - some don't pass yet

* Adding some more tests to verify the changes for column/row selection

* null default columns

* Updates to comments as per PR comments
This commit is contained in:
Benjamin Russell
2022-03-31 11:10:32 -05:00
committed by GitHub
parent 5d805bd678
commit 2ace786d95
24 changed files with 814 additions and 499 deletions

View File

@@ -306,12 +306,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
/// <summary>
/// Generates the execution plan from the table returned
/// Generates the execution plan from the table returned
/// </summary>
/// <returns>An execution plan object</returns>
public Task<Contracts.ExecutionPlan> GetExecutionPlan()
{
// Process the action just in case it hasn't been yet
// Process the action just in case it hasn't been yet
ProcessSpecialAction();
// Sanity check to make sure that results read has started
@@ -319,7 +319,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
throw new InvalidOperationException(SR.QueryServiceResultSetNotRead);
}
// Check that we this result set contains a showplan
// Check that we this result set contains a showplan
if (!specialAction.ExpectYukonXMLShowPlan)
{
throw new Exception(SR.QueryServiceExecutionPlanNotFound);
@@ -327,7 +327,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
return Task.Factory.StartNew(() =>
{
{
string content;
string format = null;
@@ -336,12 +336,12 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Determine the format and get the first col/row of XML
content = fileStreamReader.ReadRow(0, 0, Columns)[0].DisplayValue;
if (specialAction.ExpectYukonXMLShowPlan)
if (specialAction.ExpectYukonXMLShowPlan)
{
format = "xml";
}
}
return new Contracts.ExecutionPlan
{
Format = format,
@@ -371,7 +371,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Open a writer for the file
//
var fileWriter = fileStreamFactory.GetWriter(outputFileName);
var fileWriter = fileStreamFactory.GetWriter(outputFileName, null);
using (fileWriter)
{
// If we can initialize the columns using the column schema, use that
@@ -456,7 +456,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
/// <summary>
/// Updates the values in a row with the
/// Updates the values in a row with the
/// </summary>
/// <param name="rowId"></param>
/// <param name="dbDataReader"></param>
@@ -528,7 +528,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
using (var fileReader = fileFactory.GetReader(outputFileName))
using (var fileWriter = fileFactory.GetWriter(saveParams.FilePath))
using (var fileWriter = fileFactory.GetWriter(saveParams.FilePath, Columns))
{
// Iterate over the rows that are in the selected row set
for (long i = rowStartIndex; i < rowEndIndex; ++i)
@@ -551,13 +551,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
}
});
// Add exception handling to the save task
Task taskWithHandling = saveAsTask.ContinueWithOnFaulted(async t =>
{
if (failureHandler != null)
{
await failureHandler(saveParams, t.Exception.Message);
await failureHandler(saveParams, t.Exception?.Message);
}
});
@@ -691,7 +691,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
}
finally
{
{
// Release the sendResultsSemphore so the next invocation gets unblocked
//
sendResultsSemphore.Release();
@@ -706,7 +706,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
/// <summary>
/// If the result set represented by this class corresponds to a single XML
/// column that contains results of "for xml" query, set isXml = true
/// column that contains results of "for xml" query, set isXml = true
/// If the result set represented by this class corresponds to a single JSON
/// column that contains results of "for json" query, set isJson = true
/// </summary>
@@ -755,10 +755,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
/// <summary>
/// Determine the special action, if any, for this result set
/// </summary>
private SpecialAction ProcessSpecialAction()
{
private SpecialAction ProcessSpecialAction()
{
// Check if this result set is a showplan
// Check if this result set is a showplan
if (Columns.Length == 1 && string.Compare(Columns[0].ColumnName, YukonXmlShowPlanColumn, StringComparison.OrdinalIgnoreCase) == 0)
{
specialAction.ExpectYukonXMLShowPlan = true;
@@ -780,7 +780,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
throw new InvalidOperationException(SR.QueryServiceResultSetNotRead);
}
// NOTE: We are no longer checking to see if the data reader has rows before reading
// NOTE: We are no longer checking to see if the data reader has rows before reading
// b/c of a quirk in SqlClient. In some scenarios, a SqlException isn't thrown until we
// read. In order to get appropriate errors back to the user, we'll read first.
// Returning false from .ReadAsync means there aren't any rows.
@@ -791,7 +791,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
throw new InvalidOperationException(SR.QueryServiceResultSetAddNoRows);
}
using (IFileStreamWriter writer = fileStreamFactory.GetWriter(outputFileName))
{
// Write the row to the end of the file