diff --git a/extensions/sql-database-projects/package.json b/extensions/sql-database-projects/package.json index 21df917419..a96a6008db 100644 --- a/extensions/sql-database-projects/package.json +++ b/extensions/sql-database-projects/package.json @@ -16,6 +16,7 @@ "onCommand:sqlDatabaseProjects.new", "onCommand:sqlDatabaseProjects.open", "onCommand:sqlDatabaseProjects.createProjectFromDatabase", + "onCommand:sqlDatabaseProjects.addSqlBinding", "workspaceContains:**/*.sqlproj", "onView:dataworkspace.views.main" ], diff --git a/extensions/sql-database-projects/src/common/utils.ts b/extensions/sql-database-projects/src/common/utils.ts index bf9be842be..fab38074bd 100644 --- a/extensions/sql-database-projects/src/common/utils.ts +++ b/extensions/sql-database-projects/src/common/utils.ts @@ -298,6 +298,16 @@ export async function getSchemaCompareService(): Promise } } +export async function getAzureFunctionService(): Promise { + if (getAzdataApi()) { + // this isn't supported in ADS + throw new Error('Azure Functions service is not supported in Azure Data Studio'); + } else { + const api = await getVscodeMssqlApi(); + return api.azureFunctions; + } +} + export async function getVscodeMssqlApi(): Promise { const ext = vscode.extensions.getExtension(vscodeMssql.extension.name) as vscode.Extension; return ext.activate(); diff --git a/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts b/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts index 696a891a24..54914c4ea6 100644 --- a/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts +++ b/extensions/sql-database-projects/src/dialogs/addSqlBindingQuickpick.ts @@ -1,5 +1,7 @@ import * as vscode from 'vscode'; +import { BindingType } from 'vscode-mssql'; import * as constants from '../common/constants'; +import * as utils from '../common/utils'; export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined): Promise { if (!uri) { @@ -8,8 +10,45 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined): uri = vscode.window.activeTextEditor!.document.uri; } - // 1. select input or output binding - const inputOutputItems: string[] = [constants.input, constants.output]; + // get all the Azure functions in the file + const azureFunctionsService = await utils.getAzureFunctionService(); + let getAzureFunctionsResult; + try { + getAzureFunctionsResult = await azureFunctionsService.getAzureFunctions(uri.fsPath); + } catch (e) { + vscode.window.showErrorMessage(e); + return; + } + + const azureFunctions = getAzureFunctionsResult.azureFunctions; + + if (azureFunctions.length === 0) { + vscode.window.showErrorMessage(constants.noAzureFunctionsInFile); + return; + } + + // 1. select Azure function from the current file + const azureFunctionName = (await vscode.window.showQuickPick(azureFunctions, { + canPickMany: false, + title: constants.selectAzureFunction, + ignoreFocusOut: true + })); + + if (!azureFunctionName) { + return; + } + + // 2. select input or output binding + const inputOutputItems: (vscode.QuickPickItem & { type: BindingType })[] = [ + { + label: constants.input, + type: BindingType.input + }, + { + label: constants.output, + type: BindingType.output + } + ]; const selectedBinding = (await vscode.window.showQuickPick(inputOutputItems, { canPickMany: false, @@ -21,29 +60,9 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined): return; } - // get all the azure functions in the file - // TODO: get actual functions. Need to add in sqltoolsservice first - const azureFunctions = ['af1', 'af2']; //await getAzureFunctions(uri); - - if (azureFunctions.length === 0) { - vscode.window.showErrorMessage(constants.noAzureFunctionsInFile); - return; - } - - // 2. select Azure function from the current file - const azureFunctionName = (await vscode.window.showQuickPick(azureFunctions, { - canPickMany: false, - title: constants.selectAzureFunction, - ignoreFocusOut: true - })); - - if (!azureFunctionName) { - return; - } - // 3. ask for object name for the binding const objectName = await vscode.window.showInputBox({ - prompt: selectedBinding === constants.input ? constants.sqlObjectToQuery : constants.sqlTableToUpsert, + prompt: selectedBinding.type === BindingType.input ? constants.sqlObjectToQuery : constants.sqlTableToUpsert, value: constants.placeHolderObject, ignoreFocusOut: true }); @@ -64,7 +83,17 @@ export async function launchAddSqlBindingQuickpick(uri: vscode.Uri | undefined): return; } - // TODO: hook up actually adding binding // 5. insert binding + try { + const result = await azureFunctionsService.addSqlBinding(selectedBinding.type, uri.fsPath, azureFunctionName, objectName, connectionStringSetting); + + if (!result.success) { + vscode.window.showErrorMessage(result.errorMessage); + return; + } + } catch (e) { + vscode.window.showErrorMessage(e); + return; + } } diff --git a/extensions/sql-database-projects/src/typings/vscode-mssql.d.ts b/extensions/sql-database-projects/src/typings/vscode-mssql.d.ts index a632e46e5a..fe5d89f9d3 100644 --- a/extensions/sql-database-projects/src/typings/vscode-mssql.d.ts +++ b/extensions/sql-database-projects/src/typings/vscode-mssql.d.ts @@ -39,6 +39,11 @@ declare module 'vscode-mssql' { */ readonly schemaCompare: ISchemaCompareService; + /** + * Service for accessing AzureFunctions functionality + */ + readonly azureFunctions: IAzureFunctionsService; + /** * Prompts the user to select an existing connection or create a new one, and then returns the result * @param ignoreFocusOut Whether the quickpick prompt ignores focus out (default false) @@ -51,7 +56,7 @@ declare module 'vscode-mssql' { * @param connectionInfo The connection info * @returns The URI associated with this connection */ - connect(connectionInfo: IConnectionInfo): Promise; + connect(connectionInfo: IConnectionInfo): Promise; /** * Lists the databases for a given connection. Must be given an already-opened connection to succeed. @@ -73,7 +78,7 @@ declare module 'vscode-mssql' { /** * Information about a database connection */ - export interface IConnectionInfo { + export interface IConnectionInfo { /** * server name */ @@ -258,6 +263,24 @@ declare module 'vscode-mssql' { validateStreamingJob(packageFilePath: string, createStreamingJobTsql: string): Thenable; } + export interface IAzureFunctionsService { + /** + * Adds a SQL Binding to a specified Azure function in a file + * @param bindingType Type of SQL Binding + * @param filePath Path of the file where the Azure Functions are + * @param functionName Name of the function where the SQL Binding is to be added + * @param objectName Name of Object for the SQL Query + * @param connectionStringSetting Setting for the connection string + */ + addSqlBinding(bindingType: BindingType, filePath: string, functionName: string, objectName: string, connectionStringSetting: string): Thenable; + /** + * Gets the names of the Azure functions in the file + * @param filePath Path of the file to get the Azure functions + * @returns array of names of Azure functions in the file + */ + getAzureFunctions(filePath: string): Thenable; + } + export const enum TaskExecutionMode { execute = 0, script = 1, @@ -532,4 +555,62 @@ declare module 'vscode-mssql' { schema: string; } + + /** + * Azure functions binding type + */ + export const enum BindingType { + input, + output + } + + /** + * Parameters for adding a SQL binding to an Azure function + */ + export interface AddSqlBindingParams { + /** + * Aboslute file path of file to add SQL binding + */ + filePath: string; + + /** + * Name of function to add SQL binding + */ + functionName: string; + + /** + * Name of object to use in SQL binding + */ + objectName: string; + + /** + * Type of Azure function binding + */ + bindingType: BindingType; + + /** + * Name of SQL connection string setting specified in local.settings.json + */ + connectionStringSetting: string; + } + + /** + * Parameters for getting the names of the Azure functions in a file + */ + export interface GetAzureFunctionsParams { + /** + * Absolute file path of file to get Azure functions + */ + filePath: string; + } + + /** + * Result from a get Azure functions request + */ + export interface GetAzureFunctionsResult extends ResultStatus { + /** + * Array of names of Azure functions in the file + */ + azureFunctions: string[]; + } }