From 8b770aa48aa40bcfad5b01e835785f50e6c6c74b Mon Sep 17 00:00:00 2001 From: Royi Shauli Date: Tue, 17 Feb 2026 13:12:38 +0200 Subject: [PATCH] Add support for Kusto control commands (.show, .alter, .create, .drop) Previously, Quest only supported KQL queries (sent to /v1/rest/query endpoint). Control commands like .show tables, .show version, .alter table, etc. would fail because they require the management endpoint (/v1/rest/mgmt). Changes: - KustoService.cs: Detect control commands (starting with '.') and use ICslAdminProvider + ExecuteControlCommandAsync instead of ICslQueryProvider - KustoDataSource.cs: Add command examples and quick-start guide entries - create-query.md: Add walkthrough section for control commands - README.md: Update ADX description to mention command support --- README.md | 2 +- .../resources/walkthrough/create-query.md | 7 +++++ libs/MyTools.Core/KustoService.cs | 21 ++++++++++++--- server/Models/KustoDataSource.cs | 27 +++++++++++++++++++ 4 files changed, 53 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 3b2a28c..73e696a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ A powerful VS Code extension for querying multiple data sources with AI assistan | Source | Language | Description | |--------|----------|-------------| -| **Azure Data Explorer** | KQL | Query Kusto clusters with full IntelliSense and schema explorer | +| **Azure Data Explorer** | KQL | Query Kusto clusters with full IntelliSense and schema explorer. Supports both KQL queries and control commands (`.show`, `.alter`, `.create`, `.drop`) | | **Azure DevOps** | WIQL | Query work items with preview panel showing description/repro steps | | **Outlook** | OQL | Query local Outlook mail, calendar, contacts using KQL-like syntax | diff --git a/extension/resources/walkthrough/create-query.md b/extension/resources/walkthrough/create-query.md index 23e8565..0633f81 100644 --- a/extension/resources/walkthrough/create-query.md +++ b/extension/resources/walkthrough/create-query.md @@ -21,6 +21,13 @@ StormEvents | take 100 ``` +### KQL Control Command +```kql +.show tables +``` + +Control commands (starting with `.`) are also supported — `.show version`, `.show database schema as json`, `.show operations`, etc. + ### OQL Query ```oql Inbox diff --git a/libs/MyTools.Core/KustoService.cs b/libs/MyTools.Core/KustoService.cs index 7d124ec..711c500 100644 --- a/libs/MyTools.Core/KustoService.cs +++ b/libs/MyTools.Core/KustoService.cs @@ -74,18 +74,20 @@ public async Task RunQueryAsync( logAction?.Invoke($"Running query on {clusterName}:{database}"); } + // Detect if this is a control command (starts with '.') + var isControlCommand = query.TrimStart().StartsWith("."); + // Run the entire query execution on a background thread to avoid UI freezing return await Task.Run(async () => { var result = new KustoResult(); var rows = new List(); ICslQueryProvider queryProvider = null; + ICslAdminProvider adminProvider = null; IDataReader reader = null; try { - queryProvider = KustoClientFactory.CreateCslQueryProvider(kcsb); - var clientRequestProperties = new ClientRequestProperties { ClientRequestId = "MyKusto " + Guid.NewGuid(), @@ -102,6 +104,7 @@ public async Task RunQueryAsync( { reader?.Dispose(); queryProvider?.Dispose(); + adminProvider?.Dispose(); logAction?.Invoke("Query cancellation requested - cleaning up resources"); } catch @@ -110,7 +113,18 @@ public async Task RunQueryAsync( } })) { - reader = await queryProvider.ExecuteQueryAsync(database, query, clientRequestProperties); + if (isControlCommand) + { + // Control commands (.show, .alter, .create, .drop, etc.) use the admin/mgmt endpoint + adminProvider = KustoClientFactory.CreateCslAdminProvider(kcsb); + reader = await adminProvider.ExecuteControlCommandAsync(database, query, clientRequestProperties); + } + else + { + // Regular KQL queries use the query endpoint + queryProvider = KustoClientFactory.CreateCslQueryProvider(kcsb); + reader = await queryProvider.ExecuteQueryAsync(database, query, clientRequestProperties); + } cancellationToken.ThrowIfCancellationRequested(); @@ -150,6 +164,7 @@ public async Task RunQueryAsync( // Ensure resources are disposed even if an exception occurs try { reader?.Dispose(); } catch { } try { queryProvider?.Dispose(); } catch { } + try { adminProvider?.Dispose(); } catch { } } return result; diff --git a/server/Models/KustoDataSource.cs b/server/Models/KustoDataSource.cs index 88a1052..f27ca16 100644 --- a/server/Models/KustoDataSource.cs +++ b/server/Models/KustoDataSource.cs @@ -331,6 +331,27 @@ public QueryExample[] GetExamples() Description = "Create time series chart", Query = "TableName\n| where Timestamp > ago(7d)\n| summarize count() by bin(Timestamp, 1h)\n| render timechart", Category = "Visualization" + }, + new QueryExample + { + Title = "Show Tables", + Description = "List all tables in the database", + Query = ".show tables", + Category = "Commands" + }, + new QueryExample + { + Title = "Show Version", + Description = "Show the cluster version", + Query = ".show version", + Category = "Commands" + }, + new QueryExample + { + Title = "Show Schema", + Description = "Show the database schema as JSON", + Query = ".show database schema as json", + Category = "Commands" } }; } @@ -346,6 +367,12 @@ public QueryExample[] GetExamples() 5. Sort: | order by Column desc 6. Project columns: | project Col1, Col2, Col3 +Control Commands (start with '.'): +7. .show tables — List all tables +8. .show version — Show cluster version +9. .show database schema as json — Show schema +10. .show operations — List recent operations + Press Ctrl+Space for autocomplete."; // ============ IExternalViewer ============