Skip to content

Commit

Permalink
Convert queries to M format for use in Power BI
Browse files Browse the repository at this point in the history
  • Loading branch information
MarkMpn committed Oct 30, 2021
1 parent ef054bb commit 1be32ec
Show file tree
Hide file tree
Showing 20 changed files with 625 additions and 56 deletions.
2 changes: 2 additions & 0 deletions MarkMpn.Sql4Cds.SSMS/MarkMpn.Sql4Cds.SSMS.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="QueryExecutionOptions.cs" />
<Compile Include="Reflection\ReflectionObjectBase.cs" />
<Compile Include="Reflection\ScriptFactoryWrapper.cs" />
<Compile Include="Sql2MCommand.cs" />
<Compile Include="Sql2FetchXmlCommand.cs" />
<Compile Include="Sql4CdsPackage.cs" />
<Compile Include="Reflection\DisplaySQLResultsControlWrapper.cs" />
Expand All @@ -85,6 +86,7 @@
</None>
</ItemGroup>
<ItemGroup>
<Content Include="Resources\Sql2MCommand.png" />
<VSCTCompile Include="Sql4CdsPackage.vsct">
<ResourceName>Menus.ctmenu</ResourceName>
</VSCTCompile>
Expand Down
Binary file added MarkMpn.Sql4Cds.SSMS/Resources/Sql2MCommand.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
134 changes: 134 additions & 0 deletions MarkMpn.Sql4Cds.SSMS/Sql2MCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
using System;
using System.Collections.Generic;
using System.ComponentModel.Design;
using System.Linq;
using EnvDTE80;
using MarkMpn.Sql4Cds.Engine;
using MarkMpn.Sql4Cds.Engine.ExecutionPlan;
using Microsoft.SqlServer.Management.UI.VSIntegration;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Task = System.Threading.Tasks.Task;

namespace MarkMpn.Sql4Cds.SSMS
{
/// <summary>
/// Command handler
/// </summary>
internal sealed class Sql2MCommand : CommandBase
{
/// <summary>
/// Command ID.
/// </summary>
public const int CommandId = 0x0300;

/// <summary>
/// Command menu group (command set GUID).
/// </summary>
public static readonly Guid CommandSet = new Guid("fd809e45-c5a9-40cc-9f78-501dd3f71817");

/// <summary>
/// Initializes a new instance of the <see cref="Sql2MCommand"/> class.
/// Adds our command handlers for menu (commands must exist in the command table file)
/// </summary>
/// <param name="package">Owner package, not null.</param>
/// <param name="commandService">Command service to add command to, not null.</param>
private Sql2MCommand(Sql4CdsPackage package, OleMenuCommandService commandService, DTE2 dte) : base(package, dte)
{
commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

var menuCommandID = new CommandID(CommandSet, CommandId);
var menuItem = new OleMenuCommand(this.Execute, menuCommandID);
menuItem.BeforeQueryStatus += QueryStatus;
commandService.AddCommand(menuItem);
}

private void QueryStatus(object sender, EventArgs e)
{
var menuItem = (OleMenuCommand)sender;

if (ActiveDocument == null || ActiveDocument.Language != "SQL" || !IsDataverse())
{
menuItem.Enabled = false;
return;
}

menuItem.Enabled = true;
}

/// <summary>
/// Gets the instance of the command.
/// </summary>
public static Sql2MCommand Instance
{
get;
private set;
}

/// <summary>
/// Initializes the singleton instance of the command.
/// </summary>
/// <param name="package">Owner package, not null.</param>
public static async Task InitializeAsync(Sql4CdsPackage package, DTE2 dte)
{
// Verify the current thread is the UI thread - the call to AddCommand in Sql2FetchXmlCommand's constructor requires
// the UI thread.
ThreadHelper.ThrowIfNotOnUIThread();

OleMenuCommandService commandService = await package.GetServiceAsync((typeof(IMenuCommandService))) as OleMenuCommandService;
Instance = new Sql2MCommand(package, commandService, dte);
}

/// <summary>
/// This function is the callback used to execute the command when the menu item is clicked.
/// See the constructor to see how the menu item is associated with this function using
/// OleMenuCommandService service and MenuCommand class.
/// </summary>
/// <param name="sender">Event sender.</param>
/// <param name="e">Event args.</param>
private void Execute(object sender, EventArgs e)
{
ThreadHelper.ThrowIfNotOnUIThread();

var scriptFactory = new ScriptFactoryWrapper(ServiceCache.ScriptFactory);
var sqlScriptEditorControl = scriptFactory.GetCurrentlyActiveFrameDocView(ServiceCache.VSMonitorSelection, false, out _);

var constr = GetConnectionInfo();
var server = constr.DataSource.Split(',')[0];

_ai.TrackEvent("Convert", new Dictionary<string, string> { ["QueryType"] = "M", ["Source"] = "SSMS" });

var sql = GetQuery();
var m = $@"/*
Query converted to M format by SQL 4 CDS
To use in Power BI:
1. Click New Source
2. Click Blank Query
3. Click Advanced Editor
4. Copy & paste in this query
*/
let
Source = CommonDataService.Database(""{server}"")
DataverseSQL = Value.NativeQuery(Source, ""{sql.Replace("\"", "\"\"").Replace("\r\n", " ").Trim()}"", null, [EnableFolding=true])
in
DataverseSQL";

var window = Dte.ItemOperations.NewFile("General\\Text File");

var editPoint = ActiveDocument.EndPoint.CreateEditPoint();
editPoint.Insert(m);
}

private IEnumerable<IExecutionPlanNode> GetAllNodes(IExecutionPlanNode node)
{
foreach (var source in node.GetSources())
{
yield return source;

foreach (var subSource in GetAllNodes(source))
yield return subSource;
}
}
}
}
1 change: 1 addition & 0 deletions MarkMpn.Sql4Cds.SSMS/Sql4CdsPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ protected override async Task InitializeAsync(CancellationToken cancellationToke
var dte = (DTE2)await GetServiceAsync(typeof(EnvDTE.DTE));
await Sql2FetchXmlCommand.InitializeAsync(this, dte);
await FetchXml2SqlCommand.InitializeAsync(this, dte);
await Sql2MCommand.InitializeAsync(this, dte);

// Intercept query execution
DmlExecute.Initialize(this, dte);
Expand Down
19 changes: 18 additions & 1 deletion MarkMpn.Sql4Cds.SSMS/Sql4CdsPackage.vsct
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@
<ToolTipText>Convert FetchXML to SQL</ToolTipText>
</Strings>
</Button>
<Button guid="guidSql4CdsPackageCmdSet" id="Sql2MCommandId" priority="0x0100" type="Button">
<Parent guid="guidSql4CdsPackageCmdSet" id="ToolbarGroup" />
<Icon guid="guidImages2" id="bmpPic1" />
<CommandFlag>IconAndText</CommandFlag>
<CommandFlag>DontCache</CommandFlag>
<CommandFlag>DefaultDisabled</CommandFlag>
<Strings>
<ButtonText>M</ButtonText>
<ToolTipText>Convert SQL to M for Power BI</ToolTipText>
</Strings>
</Button>
</Buttons>

<!--The bitmaps section is used to define the bitmaps that are used for the commands.-->
Expand All @@ -94,6 +105,7 @@
must be the actual index (1-based) of the bitmap inside the bitmap strip. -->
<Bitmap guid="guidImages" href="Resources\Sql2FetchXmlCommand.png" usedList="bmpPic1" />
<Bitmap guid="guidImages1" href="Resources\FetchXml2SqlCommand.png" usedList="bmpPic1" />
<Bitmap guid="guidImages2" href="Resources\Sql2MCommand.png" usedList="bmpPic1" />
</Bitmaps>
</Commands>

Expand All @@ -107,14 +119,19 @@
<IDSymbol name="Toolbar" value="0x1010" />
<IDSymbol name="Sql2FetchXmlCommandId" value="0x0100" />
<IDSymbol name="FetchXml2SqlCommandId" value="0x0200" />
<IDSymbol name="Sql2MCommandId" value="0x0300" />
</GuidSymbol>

<GuidSymbol name="guidImages" value="{4134aa85-5a36-4ce6-98e8-2186a7482e8a}">
<IDSymbol name="bmpPic1" value="1" />
</GuidSymbol>

<GuidSymbol value="{eec144ec-cdab-4b5e-b7ac-1fcba8ecf93f}" name="guidImages1">
<IDSymbol name="bmpPic1" value="1" />
</GuidSymbol>

<GuidSymbol value="{DD8ED865-8747-4FB4-8823-139EBF9A57A3}" name="guidImages2">
<IDSymbol name="bmpPic1" value="1" />
</GuidSymbol>
</Symbols>
</CommandTable>
2 changes: 2 additions & 0 deletions MarkMpn.Sql4Cds/FetchXmlControl.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion MarkMpn.Sql4Cds/FetchXmlControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public FetchXmlControl()
{
InitializeComponent();

Text = $"* FetchXML {++_queryCounter}";
Text = $"FetchXML {++_queryCounter} *";

// Ref: https://gist.github.com/anonymous/63036aa8c1cefcfcb013

Expand Down
25 changes: 25 additions & 0 deletions MarkMpn.Sql4Cds/FetchXmlControl.resx
Original file line number Diff line number Diff line change
Expand Up @@ -117,4 +117,29 @@
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
<data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAMMOAADDDgAAAAAAAAAA
AAD29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAA9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAPb29v9CQkL/8e/w//Hv8P/x7/D/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAD29vb/QkJC//Hv8P/x7/D/8e/w/0JCQv/29vb/AAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JCQv9CQkL/8e/w/0JCQv9CQkL/9vb2/wAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vYf9vb2//b29v9CQkL/9vb2//b29v/29vYQAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2Afb29h/29vb/QkJC//b29v/29vYfAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2//b29v/29vb/9vb2//b2
9v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JC
Qv9CQkL/9vb2/wAAAAD29vYQ9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JCQv/x7/D/8e/w//Hv
8P/x7/D/QkJC//b29v/29vYQ9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v9CQkL/8e/w//Hv
8P/x7/D/8e/w/0JCQv/29vb/9vb2//b29v9CQkL/QkJC//Hv8P/x7/D/QkJC//b29v/29vb/QkJC//Hv
8P/x7/D/8e/w//Hv8P9CQkL/9vb2/0JCQv9CQkL/QkJC//Hv8P/x7/D/8e/w/0JCQv/29vb/9vb2/0JC
Qv/x7/D/8e/w//Hv8P/x7/D/QkJC//b29v/29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/9vb2//b2
9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2H/b29v/29vb/QkJC/0JCQv9CQkL/QkJC//b2
9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29gH29vYf9vb2//b29v/29vb/9vb2//b2
9v/29vb/Af8AAAH/AAAB/wAAAf8AAAH/AAAB/wAAAf8AAAP/AAAA/wAAAIAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAA==
</value>
</data>
</root>
64 changes: 64 additions & 0 deletions MarkMpn.Sql4Cds/MQueryControl.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 1be32ec

Please sign in to comment.