Skip to content

Commit

Permalink
Added initial export to CSV/Excel for XTB tool
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkMpn committed Jun 29, 2024
1 parent a57cf81 commit b029f12
Show file tree
Hide file tree
Showing 39 changed files with 5,049 additions and 145 deletions.
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
namespace MarkMpn.Sql4Cds.LanguageServer.QueryExecution.Contracts
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

using Microsoft.SqlTools.Utility;

namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
{
/// <summary>
/// Class used for internally passing results from a cell around.
Expand All @@ -23,7 +30,7 @@ public class DbCellValue
/// <summary>
/// The raw object for the cell, for use internally
/// </summary>
internal object RawObject { get; set; }
public object RawObject { get; set; }

/// <summary>
/// The internal ID for the row. Should be used when directly referencing the row for edit
Expand All @@ -37,6 +44,8 @@ public class DbCellValue
/// <param name="other">The DbCellValue (or child) that will receive the values</param>
public virtual void CopyTo(DbCellValue other)
{
Validate.IsNotNull(nameof(other), other);

other.DisplayValue = DisplayValue;
other.InvariantCultureDisplayValue = InvariantCultureDisplayValue;
other.IsNull = IsNull;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
using System;
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//


using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Data.SqlTypes;
using System.Diagnostics;
using Microsoft.SqlTools.Utility;

namespace MarkMpn.Sql4Cds.LanguageServer.QueryExecution.Contracts
namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
{
/// <summary>
/// Wrapper around a DbColumn, which provides extra functionality, but can be used as a
Expand Down Expand Up @@ -114,20 +121,19 @@ public DbColumnWrapper(DbColumn column)
}
}

public DbColumnWrapper(ColumnInfo columnInfo)
public DbColumnWrapper(string name, string dataTypeName, int? numericScale)
{
DataTypeName = columnInfo.DataTypeName.ToLowerInvariant();
DataTypeName = dataTypeName.ToLowerInvariant();
DetermineSqlDbType();
DataType = TypeConvertor.ToNetType(SqlDbType);
if (DataType == typeof(string))
DataType = TypeConvertor.ToNetType(this.SqlDbType);
if (DataType == typeof(String))
{
ColumnSize = int.MaxValue;
this.ColumnSize = int.MaxValue;
}
AddNameAndDataFields(columnInfo.Name);
NumericScale = columnInfo.NumericScale;
AddNameAndDataFields(name);
NumericScale = numericScale;
}


/// <summary>
/// Default constructor, used for deserializing JSON RPC only
/// </summary>
Expand Down Expand Up @@ -206,9 +212,9 @@ public DbColumnWrapper()
/// Logic taken from SSDT determination of updatable columns
/// Special treatment for HierarchyId since we are using an Expression for HierarchyId column and expression column is readonly.
/// </remarks>
public bool IsUpdatable => IsAutoIncrement != true &&
IsReadOnly != true &&
!IsSqlXmlType || IsHierarchyId;
public bool IsUpdatable => (!IsAutoIncrement.HasTrue() &&
!IsReadOnly.HasTrue() &&
!IsSqlXmlType) || IsHierarchyId;

#endregion

Expand Down Expand Up @@ -248,7 +254,7 @@ private void AddNameAndDataFields(string columnName)
{
// We want the display name for the column to always exist
ColumnName = string.IsNullOrEmpty(columnName)
? null//SR.QueryServiceColumnNull
? SR.QueryServiceColumnNull
: columnName;

switch (DataTypeName)
Expand Down Expand Up @@ -317,4 +323,71 @@ private void AddNameAndDataFields(string columnName)
}
}
}



/// <summary>
/// Convert a base data type to another base data type
/// </summary>
public sealed class TypeConvertor
{
private static Dictionary<SqlDbType,Type> _typeMap = new Dictionary<SqlDbType,Type>();

static TypeConvertor()
{
_typeMap[SqlDbType.BigInt] = typeof(Int64);
_typeMap[SqlDbType.Binary] = typeof(Byte);
_typeMap[SqlDbType.Bit] = typeof(Boolean);
_typeMap[SqlDbType.Char] = typeof(String);
_typeMap[SqlDbType.DateTime] = typeof(DateTime);
_typeMap[SqlDbType.Decimal] = typeof(Decimal);
_typeMap[SqlDbType.Float] = typeof(Double);
_typeMap[SqlDbType.Image] = typeof(Byte[]);
_typeMap[SqlDbType.Int] = typeof(Int32);
_typeMap[SqlDbType.Money] = typeof(Decimal);
_typeMap[SqlDbType.NChar] = typeof(String);
_typeMap[SqlDbType.NChar] = typeof(String);
_typeMap[SqlDbType.NChar] = typeof(String);
_typeMap[SqlDbType.NText] = typeof(String);
_typeMap[SqlDbType.NVarChar] = typeof(String);
_typeMap[SqlDbType.Real] = typeof(Single);
_typeMap[SqlDbType.UniqueIdentifier] = typeof(Guid);
_typeMap[SqlDbType.SmallDateTime] = typeof(DateTime);
_typeMap[SqlDbType.SmallInt] = typeof(Int16);
_typeMap[SqlDbType.SmallMoney] = typeof(Decimal);
_typeMap[SqlDbType.Text] = typeof(String);
_typeMap[SqlDbType.Timestamp] = typeof(Byte[]);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.VarBinary] = typeof(Byte[]);
_typeMap[SqlDbType.VarChar] = typeof(String);
_typeMap[SqlDbType.Variant] = typeof(Object);
// Note: treating as string
_typeMap[SqlDbType.Xml] = typeof(String);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
_typeMap[SqlDbType.TinyInt] = typeof(Byte);
}

private TypeConvertor()
{

}


/// <summary>
/// Convert TSQL type to .Net data type
/// </summary>
/// <param name="sqlDbType"></param>
/// <returns></returns>
public static Type ToNetType(SqlDbType sqlDbType)
{
Type netType;
if (!_typeMap.TryGetValue(sqlDbType, out netType))
{
netType = typeof(String);
}
return netType;
}
}
}
194 changes: 194 additions & 0 deletions MarkMpn.Sql4Cds.Export/Contracts/SaveResultsRequest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//


namespace Microsoft.SqlTools.ServiceLayer.QueryExecution.Contracts
{
/// <summary>
/// Parameters for the save results request
/// </summary>
public class SaveResultsRequestParams
{
/// <summary>
/// The path of the file to save results in
/// </summary>
public string FilePath { get; set; }

/// <summary>
/// Index of the batch to get the results from
/// </summary>
public int BatchIndex { get; set; }

/// <summary>
/// Index of the result set to get the results from
/// </summary>
public int ResultSetIndex { get; set; }

/// <summary>
/// URI for the editor that called save results
/// </summary>
public string OwnerUri { get; set; }

/// <summary>
/// Start index of the selected rows (inclusive)
/// </summary>
public int? RowStartIndex { get; set; }

/// <summary>
/// End index of the selected rows (inclusive)
/// </summary>
public int? RowEndIndex { get; set; }

/// <summary>
/// Start index of the selected columns (inclusive)
/// </summary>
/// <returns></returns>
public int? ColumnStartIndex { get; set; }

/// <summary>
/// End index of the selected columns (inclusive)
/// </summary>
/// <returns></returns>
public int? ColumnEndIndex { get; set; }

/// <summary>
/// Check if request is a subset of result set or whole result set
/// </summary>
/// <returns></returns>
internal bool IsSaveSelection
{
get
{
return ColumnStartIndex.HasValue && ColumnEndIndex.HasValue
&& RowStartIndex.HasValue && RowEndIndex.HasValue;
}
}
}

/// <summary>
/// Parameters to save results as CSV
/// </summary>
public class SaveResultsAsCsvRequestParams: SaveResultsRequestParams
{
/// <summary>
/// Include headers of columns in CSV
/// </summary>
public bool IncludeHeaders { get; set; }

/// <summary>
/// Delimiter for separating data items in CSV
/// </summary>
public string Delimiter { get; set; }

/// <summary>
/// either CR, CRLF or LF to separate rows in CSV
/// </summary>
public string LineSeperator { get; set; }

/// <summary>
/// Text identifier for alphanumeric columns in CSV
/// </summary>
public string TextIdentifier { get; set; }

/// <summary>
/// Encoding of the CSV file
/// </summary>
public string Encoding { get; set; }

/// <summary>
/// Maximum number of characters to store
/// </summary>
public int MaxCharsToStore { get; set; }
}

/// <summary>
/// Parameters to save results as Excel
/// </summary>
public class SaveResultsAsExcelRequestParams : SaveResultsRequestParams
{
/// <summary>
/// Include headers of columns in Excel
/// </summary>
public bool IncludeHeaders { get; set; }

/// <summary>
/// Freeze header row in Excel
/// </summary>
public bool FreezeHeaderRow { get; set; }

/// <summary>
/// Bold header row in Excel
/// </summary>
public bool BoldHeaderRow { get; set; }

/// <summary>
/// Enable auto filter on header row in Excel
/// </summary>
public bool AutoFilterHeaderRow { get; set; }

/// <summary>
/// Auto size columns in Excel
/// </summary>
public bool AutoSizeColumns { get; set; }
}

/// <summary>
/// Parameters to save results as JSON
/// </summary>
public class SaveResultsAsJsonRequestParams: SaveResultsRequestParams
{
//TODO: define config for save as JSON
}

/// <summary>
/// Parameters for saving results as a Markdown table
/// </summary>
public class SaveResultsAsMarkdownRequestParams : SaveResultsRequestParams
{
/// <summary>
/// Encoding of the CSV file
/// </summary>
public string Encoding { get; set; }

/// <summary>
/// Whether to include column names as header for the table.
/// </summary>
public bool IncludeHeaders { get; set; }

/// <summary>
/// Character sequence to separate a each row in the table. Should be either CR, CRLF, or
/// LF. If not provided, defaults to the system default line ending sequence.
/// </summary>
public string LineSeparator { get; set; }
}

/// <summary>
/// Parameters to save results as XML
/// </summary>
public class SaveResultsAsXmlRequestParams: SaveResultsRequestParams
{
/// <summary>
/// Formatting of the XML file
/// </summary>
public bool Formatted { get; set; }

/// <summary>
/// Encoding of the XML file
/// </summary>
public string Encoding { get; set; }
}

/// <summary>
/// Parameters for the save results result
/// </summary>
public class SaveResultRequestResult
{
/// <summary>
/// Error messages for saving to file.
/// </summary>
public string Messages { get; set; }
}

}
Loading

0 comments on commit b029f12

Please sign in to comment.