mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-09 01:32:34 -05:00
SQL Bindings - Adds Views support for Create Azure Function with SQL Binding (#19894)
* add views logic * add views tests * address PR and Figma comments * add ObjectType Enum to be used as a parameter * add comment
This commit is contained in:
@@ -8,7 +8,7 @@ import * as path from 'path';
|
||||
import * as utils from './utils';
|
||||
import * as constants from './constants';
|
||||
import * as azureFunctionsContracts from '../contracts/azureFunctions/azureFunctionsContracts';
|
||||
import { BindingType, IConnectionStringInfo } from 'sql-bindings';
|
||||
import { BindingType, IConnectionStringInfo, ObjectType } from 'sql-bindings';
|
||||
import { ConnectionDetails, IConnectionInfo } from 'vscode-mssql';
|
||||
// https://github.com/microsoft/vscode-azurefunctions/blob/main/src/vscode-azurefunctions.api.d.ts
|
||||
import { AzureFunctionsExtensionApi } from '../../../types/vscode-azurefunctions.api';
|
||||
@@ -286,9 +286,13 @@ export async function isFunctionProject(folderPath: string): Promise<boolean> {
|
||||
|
||||
/**
|
||||
* Prompts the user to select type of binding and returns result
|
||||
* @param objectType (Optional) The type of object user choose to insert/upsert into
|
||||
* @param funcName (Optional) Name of the function to which we are adding the SQL Binding
|
||||
* @returns binding type or undefined if the user cancelled out of the prompt
|
||||
*/
|
||||
export async function promptForBindingType(funcName?: string): Promise<BindingType | undefined> {
|
||||
export async function promptForBindingType(objectType?: ObjectType, funcName?: string): Promise<BindingType | undefined> {
|
||||
// check to see if objectType is view
|
||||
let isView = (objectType === ObjectType.View);
|
||||
const inputOutputItems: (vscode.QuickPickItem & { type: BindingType })[] = [
|
||||
{
|
||||
label: constants.input,
|
||||
@@ -302,7 +306,8 @@ export async function promptForBindingType(funcName?: string): Promise<BindingTy
|
||||
}
|
||||
];
|
||||
|
||||
const selectedBinding = (await vscode.window.showQuickPick(inputOutputItems, {
|
||||
// view can only be used with input binding
|
||||
const selectedBinding = isView ? { type: BindingType.input } : (await vscode.window.showQuickPick(inputOutputItems, {
|
||||
canPickMany: false,
|
||||
title: constants.selectBindingType(funcName),
|
||||
ignoreFocusOut: true
|
||||
@@ -311,14 +316,30 @@ export async function promptForBindingType(funcName?: string): Promise<BindingTy
|
||||
return selectedBinding?.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to select to use a table or view as the object to query/upsert into
|
||||
*/
|
||||
export async function promptForObjectType(): Promise<ObjectType | undefined> {
|
||||
const objectTypes: (vscode.QuickPickItem & { type: ObjectType })[] =
|
||||
[{ label: constants.table, type: ObjectType.Table }, { label: constants.view, type: ObjectType.View }];
|
||||
const selectedObjectType = (await vscode.window.showQuickPick(objectTypes, {
|
||||
canPickMany: false,
|
||||
title: constants.selectSqlTableOrViewPrompt,
|
||||
ignoreFocusOut: true
|
||||
}));
|
||||
|
||||
return selectedObjectType?.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prompts the user to enter object name for the SQL query
|
||||
* @param bindingType Type of SQL Binding
|
||||
* @param connectionInfo (optional) connection info from the selected connection profile
|
||||
* if left undefined we prompt to manually enter the object name
|
||||
* @param objectType (optional) type of object to query/upsert into
|
||||
* @returns the object name from user's input or menu choice
|
||||
*/
|
||||
export async function promptForObjectName(bindingType: BindingType, connectionInfo?: IConnectionInfo): Promise<string | undefined> {
|
||||
export async function promptForObjectName(bindingType: BindingType, connectionInfo?: IConnectionInfo, objectType?: ObjectType): Promise<string | undefined> {
|
||||
// show the connection string methods (user input and connection profile options)
|
||||
let connectionURI: string | undefined;
|
||||
let selectedDatabase: string | undefined;
|
||||
@@ -329,9 +350,8 @@ export async function promptForObjectName(bindingType: BindingType, connectionIn
|
||||
return promptToManuallyEnterObjectName(bindingType);
|
||||
}
|
||||
|
||||
// TODO create path to solve for selectView (first need to support views as well)
|
||||
// Prompt user to select a table based on connection profile and selected database}
|
||||
// get connectionURI and selectedDatabase to be used for listing tables query request
|
||||
// Prompt user to select a table/view based on connection profile and selected database
|
||||
// get connectionURI and selectedDatabase to be used for listing tables/view query request
|
||||
connectionURI = await getConnectionURI(connectionInfo);
|
||||
if (!connectionURI) {
|
||||
// mssql connection error
|
||||
@@ -345,7 +365,7 @@ export async function promptForObjectName(bindingType: BindingType, connectionIn
|
||||
|
||||
connectionInfo.database = selectedDatabase;
|
||||
|
||||
let selectedObjectName = await promptSelectTable(connectionURI, bindingType, selectedDatabase);
|
||||
let selectedObjectName = await promptSelectObject(connectionURI, bindingType, selectedDatabase, objectType);
|
||||
|
||||
return selectedObjectName;
|
||||
}
|
||||
@@ -618,35 +638,38 @@ export async function getConnectionURI(connectionInfo: IConnectionInfo): Promise
|
||||
return connectionURI;
|
||||
}
|
||||
|
||||
export async function promptSelectTable(connectionURI: string, bindingType: BindingType, selectedDatabase: string): Promise<string | undefined> {
|
||||
export async function promptSelectObject(connectionURI: string, bindingType: BindingType, selectedDatabase: string, objectType?: string): Promise<string | undefined> {
|
||||
const vscodeMssqlApi = await utils.getVscodeMssqlApi();
|
||||
const userObjectName = bindingType === BindingType.input ? constants.enterObjectName : constants.enterObjectNameToUpsert;
|
||||
let isView = (objectType === ObjectType.View);
|
||||
|
||||
// Create query to get list of tables from database selected
|
||||
let tableQuery = tablesQuery(selectedDatabase);
|
||||
const params = { ownerUri: connectionURI, queryString: tableQuery };
|
||||
const userObjectName = isView ? constants.enterViewName : bindingType === BindingType.input ? constants.enterTableName : constants.enterTableNameToUpsert;
|
||||
|
||||
// Create query to get list of tables or views from selected database
|
||||
let listQuery = isView ? viewsQuery(selectedDatabase) : tablesQuery(selectedDatabase);
|
||||
const params = { ownerUri: connectionURI, queryString: listQuery };
|
||||
let queryResult: azureFunctionsContracts.SimpleExecuteResult | undefined;
|
||||
|
||||
// send SimpleExecuteRequest query to STS to get list of schema and tables based on the connection profile and database of the user
|
||||
await vscode.window.withProgress(
|
||||
{
|
||||
location: vscode.ProgressLocation.Notification,
|
||||
title: constants.tableListProgressTitle,
|
||||
title: isView ? constants.viewListProgressTitle : constants.tableListProgressTitle,
|
||||
cancellable: false
|
||||
}, async (_progress, _token) => {
|
||||
queryResult = await vscodeMssqlApi.sendRequest(azureFunctionsContracts.SimpleExecuteRequest.type, params);
|
||||
}
|
||||
);
|
||||
|
||||
// Get schema and table names from query result rows
|
||||
const tableNames = queryResult!.rows.map(r => r[0].displayValue);
|
||||
// add manual entry option to table names list for user to choose from as well (with pencil icon)
|
||||
// Get schema and table/view names from query result rows
|
||||
const objectNames = queryResult!.rows.map(r => r[0].displayValue);
|
||||
// add manual entry option to object names list for user to choose from as well (with pencil icon)
|
||||
let manuallyEnterObjectName = constants.manuallyEnterObjectName(userObjectName);
|
||||
tableNames.unshift(manuallyEnterObjectName);
|
||||
// prompt user to select table from list of tables options
|
||||
objectNames.unshift(manuallyEnterObjectName);
|
||||
// prompt user to select object from list of objects
|
||||
while (true) {
|
||||
let selectedObject = await vscode.window.showQuickPick(tableNames, {
|
||||
let selectedObject = await vscode.window.showQuickPick(objectNames, {
|
||||
canPickMany: false,
|
||||
title: constants.selectTable,
|
||||
title: isView ? constants.selectView : constants.selectTable,
|
||||
ignoreFocusOut: true
|
||||
});
|
||||
|
||||
@@ -667,10 +690,15 @@ export function tablesQuery(selectedDatabase: string): string {
|
||||
return `SELECT CONCAT(QUOTENAME(table_schema),'.',QUOTENAME(table_name)) from ${quotedDatabase}.INFORMATION_SCHEMA.TABLES where TABLE_TYPE = 'BASE TABLE'`;
|
||||
}
|
||||
|
||||
export function viewsQuery(selectedDatabase: string): string {
|
||||
let quotedDatabase = '[' + utils.escapeClosingBrackets(selectedDatabase) + ']';
|
||||
return `SELECT CONCAT(QUOTENAME(table_schema),'.',QUOTENAME(table_name)) from ${quotedDatabase}.INFORMATION_SCHEMA.VIEWS;`;
|
||||
}
|
||||
|
||||
export async function promptToManuallyEnterObjectName(bindingType: BindingType): Promise<string | undefined> {
|
||||
// user manually enters table or view to query or upsert into
|
||||
let selectedObject = await vscode.window.showInputBox({
|
||||
prompt: bindingType === BindingType.input ? constants.sqlTableOrViewToQuery : constants.sqlTableToUpsert,
|
||||
prompt: bindingType === BindingType.input ? constants.sqlObjectToQuery : constants.sqlTableToUpsert,
|
||||
placeHolder: constants.placeHolderObject,
|
||||
validateInput: input => input ? undefined : constants.nameMustNotBeEmpty,
|
||||
ignoreFocusOut: true
|
||||
|
||||
Reference in New Issue
Block a user