Adding sr.strings file and removing hard-coded strings (#52)

* Strings sweep for connection service

* String sweep for credentials service

* String sweep for hosting

* String sweep for query execution service

* String sweep for Workspace service

* Renaming utility namespace to match standards

Renaming Microsoft.SqlTools.EditorServices.Utility to
Microsoft.SqlTools.ServiceLayer.Utility to match the naming changes done a
while back. Also renaming them on the files that use them

* Namespace change on reliable connection

* Adding the new resx and designer files

* Final bug fixes for srgen

Fixing flakey moq package name

* Removing todo as per @kevcunnane

* Adding using statements as per @llali's comment

* Fixing issues from broken unit tests

Note: This feature contains changes that will break the contract for
saving as CSV and JSON. On success, null is returned as a message instead
of "Success". Changes will be made to the vscode component to handle this
change.
This commit is contained in:
Benjamin Russell
2016-09-16 16:18:25 -07:00
committed by GitHub
parent 55047a0196
commit 41198e9357
63 changed files with 1713 additions and 264 deletions

View File

@@ -10,10 +10,10 @@ using System.Data.SqlClient;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.SqlTools.EditorServices.Utility;
using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
@@ -22,8 +22,6 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
/// </summary>
public class Batch : IDisposable
{
private const string RowsAffectedFormat = "({0} row(s) affected)";
#region Member Variables
/// <summary>
@@ -160,8 +158,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
// Create a message with the number of affected rows -- IF the query affects rows
resultMessages.Add(reader.RecordsAffected >= 0
? string.Format(RowsAffectedFormat, reader.RecordsAffected)
: "Command(s) completed successfully.");
? SR.QueryServiceAffectedRows(reader.RecordsAffected)
: SR.QueryServiceCompletedSuccessfully);
continue;
}
@@ -173,7 +171,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
resultSets.Add(resultSet);
// Add a message for the number of rows the query returned
resultMessages.Add(string.Format(RowsAffectedFormat, resultSet.RowCount));
resultMessages.Add(SR.QueryServiceAffectedRows(reader.RecordsAffected));
} while (await reader.NextResultAsync(cancellationToken));
}
}
@@ -214,8 +212,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Sanity check to make sure we have valid numbers
if (resultSetIndex < 0 || resultSetIndex >= resultSets.Count)
{
throw new ArgumentOutOfRangeException(nameof(resultSetIndex), "Result set index cannot be less than 0" +
"or greater than the number of result sets");
throw new ArgumentOutOfRangeException(nameof(resultSetIndex), SR.QueryServiceSubsetResultSetOutOfRange);
}
// Retrieve the result set
@@ -256,9 +253,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
if (sqlError != null)
{
int lineNumber = sqlError.LineNumber + StartLine;
string message = String.Format("Msg {0}, Level {1}, State {2}, Line {3}{4}{5}",
sqlError.Number, sqlError.Class, sqlError.State, lineNumber,
Environment.NewLine, sqlError.Message);
string message = SR.QueryServiceErrorFormat(sqlError.Number, sqlError.Class, sqlError.State,
lineNumber, Environment.NewLine, sqlError.Message);
resultMessages.Add(message);
}
}

View File

@@ -195,8 +195,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
{
get
{
// TODO: Localize
return string.IsNullOrEmpty(internalColumn.ColumnName) ? "(No column name)" : internalColumn.ColumnName;
return string.IsNullOrEmpty(internalColumn.ColumnName)
? SR.QueryServiceColumnNull
: internalColumn.ColumnName;
}
}

View File

@@ -6,6 +6,7 @@
using System;
using System.Diagnostics;
using System.IO;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
{
@@ -51,17 +52,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
public void Init(string fileName, int bufferLength, FileAccess accessMethod)
{
// Sanity check for valid buffer length, fileName, and accessMethod
if (bufferLength <= 0)
{
throw new ArgumentOutOfRangeException(nameof(bufferLength), "Buffer length must be a positive value");
}
if (string.IsNullOrWhiteSpace(fileName))
{
throw new ArgumentNullException(nameof(fileName), "File name cannot be null or whitespace");
}
Validate.IsGreaterThan(nameof(bufferLength), bufferLength, 0);
Validate.IsNotNullOrEmptyString(nameof(fileName), fileName);
if (accessMethod == FileAccess.Write)
{
throw new ArgumentException("Access method cannot be write-only", nameof(fileName));
throw new ArgumentException(SR.QueryServiceFileWrapperWriteOnly, nameof(fileName));
}
// Setup the buffer
@@ -95,7 +90,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
// Make sure that we're initialized before performing operations
if (buffer == null)
{
throw new InvalidOperationException("FileStreamWrapper must be initialized before performing operations");
throw new InvalidOperationException(SR.QueryServiceFileWrapperNotInitialized);
}
MoveTo(offset);
@@ -135,11 +130,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
// Make sure that we're initialized before performing operations
if (buffer == null)
{
throw new InvalidOperationException("FileStreamWrapper must be initialized before performing operations");
throw new InvalidOperationException(SR.QueryServiceFileWrapperNotInitialized);
}
if (!fileStream.CanWrite)
{
throw new InvalidOperationException("This FileStreamWrapper canot be used for writing");
throw new InvalidOperationException(SR.QueryServiceFileWrapperReadOnly);
}
int bytesCopied = 0;
@@ -172,11 +167,11 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
// Make sure that we're initialized before performing operations
if (buffer == null)
{
throw new InvalidOperationException("FileStreamWrapper must be initialized before performing operations");
throw new InvalidOperationException(SR.QueryServiceFileWrapperNotInitialized);
}
if (!fileStream.CanWrite)
{
throw new InvalidOperationException("This FileStreamWrapper cannot be used for writing");
throw new InvalidOperationException(SR.QueryServiceFileWrapperReadOnly);
}
// Make sure we are at the right place in the file

View File

@@ -80,7 +80,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
// Workaround .NET bug, see sqlbu# 440643 and vswhidbey# 599834
// TODO: Is this workaround necessary for .NET Core?
if (colType == null && sqlVariantTypeResult.Value == "System.Data.SqlTypes.SqlSingle")
if (colType == null && sqlVariantTypeResult.Value == @"System.Data.SqlTypes.SqlSingle")
{
colType = typeof(SqlSingle);
}

View File

@@ -10,6 +10,7 @@ using System.IO;
using System.Linq;
using System.Text;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
{
@@ -603,10 +604,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
/// <returns>Number of bytes used to store the string</returns>
public int WriteString(string sVal)
{
if (sVal == null)
{
throw new ArgumentNullException(nameof(sVal), "String to store must be non-null.");
}
Validate.IsNotNull(nameof(sVal), sVal);
int iTotalLen;
if (0 == sVal.Length) // special case of 0 length string
@@ -640,10 +638,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
/// <returns>Number of bytes used to store the byte[]</returns>
public int WriteBytes(byte[] bytesVal, int iLen)
{
if (bytesVal == null)
{
throw new ArgumentNullException(nameof(bytesVal), "Byte array to store must be non-null.");
}
Validate.IsNotNull(nameof(bytesVal), bytesVal);
int iTotalLen;
if (0 == iLen) // special case of 0 length byte array "0x"

View File

@@ -13,8 +13,8 @@ using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Xml;
using Microsoft.SqlTools.EditorServices.Utility;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
{
@@ -135,7 +135,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
{
if (maxNumBytesToReturn <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxNumBytesToReturn), "Maximum number of bytes to return must be greater than zero.");
throw new ArgumentOutOfRangeException(nameof(maxNumBytesToReturn), SR.QueryServiceDataReaderByteCountInvalid);
}
//first, ask provider how much data it has and calculate the final # of bytes
@@ -177,7 +177,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
{
if (maxCharsToReturn <= 0)
{
throw new ArgumentOutOfRangeException(nameof(maxCharsToReturn), "Maximum number of chars to return must be greater than zero");
throw new ArgumentOutOfRangeException(nameof(maxCharsToReturn), SR.QueryServiceDataReaderCharCountInvalid);
}
//first, ask provider how much data it has and calculate the final # of chars
@@ -221,37 +221,47 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage
/// <returns>String</returns>
public string GetXmlWithMaxCapacity(int iCol, int maxCharsToReturn)
{
if (supportSqlXml)
if (maxCharsToReturn <= 0)
{
SqlXml sm = GetSqlXml(iCol);
if (sm == null)
{
return null;
}
throw new ArgumentOutOfRangeException(nameof(maxCharsToReturn), SR.QueryServiceDataReaderXmlCountInvalid);
}
//this code is mostly copied from SqlClient implementation of returning value for XML data type
StringWriterWithMaxCapacity sw = new StringWriterWithMaxCapacity(null, maxCharsToReturn);
XmlWriterSettings writerSettings = new XmlWriterSettings
{
CloseOutput = false,
ConformanceLevel = ConformanceLevel.Fragment
};
// don't close the memory stream
XmlWriter ww = XmlWriter.Create(sw, writerSettings);
// If we're not in SQL XML mode, just return the entire thing as a string
if (!supportSqlXml)
{
object o = GetValue(iCol);
return o?.ToString();
}
XmlReader reader = sm.CreateReader();
// We have SQL XML support, so write it properly
SqlXml sm = GetSqlXml(iCol);
if (sm == null)
{
return null;
}
// Setup the writer so that we don't close the memory stream and can process fragments
// of XML
XmlWriterSettings writerSettings = new XmlWriterSettings
{
CloseOutput = false, // don't close the memory stream
ConformanceLevel = ConformanceLevel.Fragment
};
using (StringWriterWithMaxCapacity sw = new StringWriterWithMaxCapacity(null, maxCharsToReturn))
using (XmlWriter ww = XmlWriter.Create(sw, writerSettings))
using (XmlReader reader = sm.CreateReader())
{
reader.Read();
while (!reader.EOF)
{
ww.WriteNode(reader, true);
}
ww.Flush();
return sw.ToString();
}
object o = GetValue(iCol);
return o?.ToString();
}
#endregion

View File

@@ -14,6 +14,7 @@ using Microsoft.SqlTools.ServiceLayer.Connection.ReliableConnection;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts;
using Microsoft.SqlTools.ServiceLayer.QueryExecution.DataStorage;
using Microsoft.SqlTools.ServiceLayer.SqlContext;
using Microsoft.SqlTools.ServiceLayer.Utility;
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
@@ -67,22 +68,10 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
public Query(string queryText, ConnectionInfo connection, QueryExecutionSettings settings, IFileStreamFactory outputFactory)
{
// Sanity check for input
if (string.IsNullOrEmpty(queryText))
{
throw new ArgumentNullException(nameof(queryText), "Query text cannot be null");
}
if (connection == null)
{
throw new ArgumentNullException(nameof(connection), "Connection cannot be null");
}
if (settings == null)
{
throw new ArgumentNullException(nameof(settings), "Settings cannot be null");
}
if (outputFactory == null)
{
throw new ArgumentNullException(nameof(outputFactory), "Output file factory cannot be null");
}
Validate.IsNotNullOrEmptyString(nameof(queryText), queryText);
Validate.IsNotNull(nameof(connection), connection);
Validate.IsNotNull(nameof(settings), settings);
Validate.IsNotNull(nameof(outputFactory), outputFactory);
// Initialize the internal state
QueryText = queryText;
@@ -165,7 +154,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Make sure that the query hasn't completed execution
if (HasExecuted)
{
throw new InvalidOperationException("The query has already completed, it cannot be cancelled.");
throw new InvalidOperationException(SR.QueryServiceCancelAlreadyCompleted);
}
// Issue the cancellation token for the query
@@ -218,7 +207,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
SqlConnection conn = sender as SqlConnection;
if (conn == null)
{
throw new InvalidOperationException("Sender for OnInfoMessage event must be a SqlConnection");
throw new InvalidOperationException(SR.QueryServiceMessageSenderNotSql);
}
foreach(SqlError error in args.Errors)
@@ -244,14 +233,13 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Sanity check that the results are available
if (!HasExecuted)
{
throw new InvalidOperationException("The query has not completed, yet.");
throw new InvalidOperationException(SR.QueryServiceSubsetNotCompleted);
}
// Sanity check to make sure that the batch is within bounds
if (batchIndex < 0 || batchIndex >= Batches.Length)
{
throw new ArgumentOutOfRangeException(nameof(batchIndex), "Result set index cannot be less than 0" +
"or greater than the number of result sets");
throw new ArgumentOutOfRangeException(nameof(batchIndex), SR.QueryServiceSubsetBatchOutOfRange);
}
return Batches[batchIndex].GetSubset(resultSetIndex, startRow, rowCount);

View File

@@ -149,7 +149,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
await requestContext.SendResult(new QueryExecuteSubsetResult
{
Message = "The requested query does not exist."
Message = SR.QueryServiceRequestsNoQuery
});
return;
}
@@ -197,7 +197,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
await requestContext.SendResult(new QueryDisposeResult
{
Messages = "Failed to dispose query, ID not found."
Messages = SR.QueryServiceRequestsNoQuery
});
return;
}
@@ -225,7 +225,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
await requestContext.SendResult(new QueryCancelResult
{
Messages = "Failed to cancel query, ID not found."
Messages = SR.QueryServiceRequestsNoQuery
});
return;
}
@@ -239,7 +239,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// It really shouldn't be possible to get to this scenario, but we'll cover it anyhow
await requestContext.SendResult(new QueryCancelResult
{
Messages = "Query successfully cancelled, failed to dispose query. ID not found."
Messages = SR.QueryServiceCancelDisposeFailed
});
return;
}
@@ -272,7 +272,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
await requestContext.SendResult(new SaveResultRequestResult
{
Messages = "Failed to save results, ID not found."
Messages = SR.QueryServiceRequestsNoQuery
});
return;
}
@@ -295,6 +295,9 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
await csvFile.WriteLineAsync( string.Join( ",", row.Select( field => SaveResults.EncodeCsvField((field != null) ? field.ToString(): string.Empty))));
}
}
// Successfully wrote file, send success result
await requestContext.SendResult(new SaveResultRequestResult { Messages = null });
}
catch(Exception ex)
{
@@ -304,13 +307,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
File.Delete(saveParams.FilePath);
}
await requestContext.SendError(ex.Message);
return;
}
await requestContext.SendResult(new SaveResultRequestResult
{
Messages = "Success"
});
return;
}
/// <summary>
@@ -361,6 +358,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
}
jsonWriter.WriteEndArray();
}
await requestContext.SendResult(new SaveResultRequestResult { Messages = null });
}
catch(Exception ex)
{
@@ -370,13 +369,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
File.Delete(saveParams.FilePath);
}
await requestContext.SendError(ex.Message);
return;
}
await requestContext.SendResult(new SaveResultRequestResult
{
Messages = "Success"
});
return;
}
#endregion
@@ -392,7 +385,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
await requestContext.SendResult(new QueryExecuteResult
{
Messages = "This editor is not connected to a database."
Messages = SR.QueryServiceQueryInvalidOwnerUri
});
return null;
}
@@ -413,15 +406,14 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
{
await requestContext.SendResult(new QueryExecuteResult
{
Messages = "A query is already in progress for this editor session." +
"Please cancel this query or wait for its completion."
Messages = SR.QueryServiceQueryInProgress
});
return null;
}
return newQuery;
}
catch (ArgumentNullException ane)
catch (ArgumentException ane)
{
await requestContext.SendResult(new QueryExecuteResult { Messages = ane.Message });
return null;

View File

@@ -64,10 +64,8 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
public ResultSet(DbDataReader reader, IFileStreamFactory factory)
{
// Sanity check to make sure we got a reader
if (reader == null)
{
throw new ArgumentNullException(nameof(reader), "Reader cannot be null");
}
Validate.IsNotNull(nameof(reader), SR.QueryServiceResultSetReaderNull);
DataReader = new StorageDataReader(reader);
// Initialize the storage
@@ -134,18 +132,17 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// Sanity check to make sure that the results have been read beforehand
if (!hasBeenRead || fileStreamReader == null)
{
throw new InvalidOperationException("Cannot read subset unless the results have been read from the server");
throw new InvalidOperationException(SR.QueryServiceResultSetNotRead);
}
// Sanity check to make sure that the row and the row count are within bounds
if (startRow < 0 || startRow >= RowCount)
{
throw new ArgumentOutOfRangeException(nameof(startRow), "Start row cannot be less than 0 " +
"or greater than the number of rows in the resultset");
throw new ArgumentOutOfRangeException(nameof(startRow), SR.QueryServiceResultSetStartRowOutOfRange);
}
if (rowCount <= 0)
{
throw new ArgumentOutOfRangeException(nameof(rowCount), "Row count must be a positive integer");
throw new ArgumentOutOfRangeException(nameof(rowCount), SR.QueryServiceResultSetRowCountOutOfRange);
}
return Task.Factory.StartNew(() =>
@@ -177,7 +174,7 @@ namespace Microsoft.SqlTools.ServiceLayer.QueryExecution
// If we can initialize the columns using the column schema, use that
if (!DataReader.DbDataReader.CanGetColumnSchema())
{
throw new InvalidOperationException("Could not retrieve column schema for result set.");
throw new InvalidOperationException(SR.QueryServiceResultSetNoColumnSchema);
}
Columns = DataReader.Columns;
long currentFileOffset = 0;