Initial support for SQLCMD variables in sql project tree (#21574)

* initial changes

* sqlcmd node showing in tree

* Add edit sqlcmdvar command

* remove commands on sqlcmd vars  for now

* cleanup

* fix tests

* add icons

* remove TestProject

* add checks for undefined

* add variable
This commit is contained in:
Kim Santiago
2023-01-25 10:19:39 -08:00
committed by GitHub
parent a63f43088e
commit 17949b9d03
9 changed files with 105 additions and 4 deletions

View File

@@ -79,6 +79,7 @@ export const refreshDataWorkspaceCommand = 'dataworkspace.refresh';
// UI Strings
export const dataSourcesNodeName = localize('dataSourcesNodeName', "Data Sources");
export const databaseReferencesNodeName = localize('databaseReferencesNodeName', "Database References");
export const sqlcmdVariablesNodeName = localize('sqlcmdVariablesNodeName', "SQLCMD Variables");
export const sqlConnectionStringFriendly = localize('sqlConnectionStringFriendly', "SQL connection string");
export const yesString = localize('yesString', "Yes");
export const openEulaString = localize('openEulaString', "Open License Agreement");
@@ -553,6 +554,8 @@ export enum DatabaseProjectItemType {
referencesRoot = 'databaseProject.itemType.referencesRoot',
reference = 'databaseProject.itemType.reference',
dataSourceRoot = 'databaseProject.itemType.dataSourceRoot',
sqlcmdVariablesRoot = 'databaseProject.itemType.sqlcmdVariablesRoot',
sqlcmdVariable = 'databaseProject.itemType.sqlcmdVariable'
}
// AutoRest

View File

@@ -24,6 +24,9 @@ export class IconPathHelper {
public static referenceGroup: IconPath;
public static referenceDatabase: IconPath;
public static sqlCmdVariablesGroup: IconPath;
public static sqlCmdVariable: IconPath;
public static refresh: IconPath;
public static folder_blue: IconPath;
public static selectConnection: IconPath;
@@ -57,6 +60,9 @@ export class IconPathHelper {
IconPathHelper.referenceGroup = IconPathHelper.makeIcon('referenceGroup');
IconPathHelper.referenceDatabase = IconPathHelper.makeIcon('reference-database');
IconPathHelper.sqlCmdVariablesGroup = IconPathHelper.makeIcon('symbol-string');
IconPathHelper.sqlCmdVariable = IconPathHelper.makeIcon('symbol-variable');
IconPathHelper.refresh = IconPathHelper.makeIcon('refresh', true);
IconPathHelper.folder_blue = IconPathHelper.makeIcon('folder_blue', true);
IconPathHelper.selectConnection = IconPathHelper.makeIcon('selectConnection', true);

View File

@@ -16,6 +16,7 @@ import { IconPathHelper } from '../../common/iconHelper';
import { FileProjectEntry } from '../projectEntry';
import { EntryType } from 'sqldbproj';
import { DBProjectConfigurationKey } from '../../tools/netcoreTool';
import { SqlCmdVariablesTreeItem } from './sqlcmdVariableTreeItem';
/**
* TreeNode root that represents an entire project
@@ -23,6 +24,7 @@ import { DBProjectConfigurationKey } from '../../tools/netcoreTool';
export class ProjectRootTreeItem extends BaseProjectTreeItem {
dataSourceNode: DataSourcesTreeItem;
databaseReferencesNode: DatabaseReferencesTreeItem;
sqlCmdVariablesNode: SqlCmdVariablesTreeItem;
fileChildren: { [childName: string]: (fileTree.FolderNode | fileTree.FileNode) } = {};
project: Project;
fileSystemUri: vscode.Uri;
@@ -34,7 +36,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
this.fileSystemUri = vscode.Uri.file(project.projectFilePath);
this.dataSourceNode = new DataSourcesTreeItem(this);
this.databaseReferencesNode = new DatabaseReferencesTreeItem(this);
this.sqlCmdVariablesNode = new SqlCmdVariablesTreeItem(this);
this.construct();
}
@@ -43,6 +45,7 @@ export class ProjectRootTreeItem extends BaseProjectTreeItem {
// [8/31/2020] Hiding Data source for Preview since we do not have a way to add or update those.
// output.push(this.dataSourceNode);
output.push(this.databaseReferencesNode);
output.push(this.sqlCmdVariablesNode);
return output.concat(Object.values(this.fileChildren).sort(fileTree.sortFileFolderNodes));
}

View File

@@ -0,0 +1,73 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import * as vscode from 'vscode';
import * as path from 'path';
import * as constants from '../../common/constants';
import { BaseProjectTreeItem } from './baseTreeItem';
import { ProjectRootTreeItem } from './projectTreeItem';
import { IconPathHelper } from '../../common/iconHelper';
/**
* Folder for containing SQLCMD variable nodes in the tree
*/
export class SqlCmdVariablesTreeItem extends BaseProjectTreeItem {
private sqlcmdVariables: SqlCmdVariableTreeItem[] = [];
constructor(project: ProjectRootTreeItem) {
super(vscode.Uri.file(path.join(project.projectUri.fsPath, constants.sqlcmdVariablesNodeName)), project);
this.construct();
}
private construct() {
const sqlCmdVariables = (this.parent as ProjectRootTreeItem).project.sqlCmdVariables;
if (!sqlCmdVariables) {
return;
}
for (const sqlCmdVariable of Object.keys(sqlCmdVariables)) {
if (sqlCmdVariable) {
this.sqlcmdVariables.push(new SqlCmdVariableTreeItem(sqlCmdVariable, this));
}
}
}
public get children(): SqlCmdVariableTreeItem[] {
return this.sqlcmdVariables;
}
public get treeItem(): vscode.TreeItem {
const sqlCmdVariableFolderItem = new vscode.TreeItem(this.projectUri, vscode.TreeItemCollapsibleState.Collapsed);
sqlCmdVariableFolderItem.contextValue = constants.DatabaseProjectItemType.sqlcmdVariablesRoot;
sqlCmdVariableFolderItem.iconPath = IconPathHelper.sqlCmdVariablesGroup;
return sqlCmdVariableFolderItem;
}
}
/**
* Represents a SQLCMD variable in a .sqlproj
*/
export class SqlCmdVariableTreeItem extends BaseProjectTreeItem {
constructor(private sqlcmdVar: string, sqlcmdVarsTreeItem: SqlCmdVariablesTreeItem) {
super(vscode.Uri.file(path.join(sqlcmdVarsTreeItem.projectUri.fsPath, sqlcmdVar)), sqlcmdVarsTreeItem);
}
public get children(): BaseProjectTreeItem[] {
return [];
}
public get treeItem(): vscode.TreeItem {
const sqlcmdVariableItem = new vscode.TreeItem(this.projectUri, vscode.TreeItemCollapsibleState.None);
sqlcmdVariableItem.label = this.sqlcmdVar;
sqlcmdVariableItem.contextValue = constants.DatabaseProjectItemType.sqlcmdVariable;
sqlcmdVariableItem.iconPath = IconPathHelper.sqlCmdVariable;
return sqlcmdVariableItem;
}
}

View File

@@ -70,6 +70,7 @@ describe('Project Tree tests', function (): void {
const tree = new ProjectRootTreeItem(proj);
should(tree.children.map(x => x.projectUri.path)).deepEqual([
'/TestProj/Database References',
'/TestProj/SQLCMD Variables',
'/TestProj/duplicateFolder',
'/TestProj/someFolder',
'/TestProj/duplicate.sql']);
@@ -82,6 +83,7 @@ describe('Project Tree tests', function (): void {
should(tree.children.map(x => x.treeItem.contextValue)).deepEqual([
DatabaseProjectItemType.referencesRoot,
DatabaseProjectItemType.sqlcmdVariablesRoot,
DatabaseProjectItemType.folder,
DatabaseProjectItemType.folder,
DatabaseProjectItemType.file]);
@@ -106,12 +108,13 @@ describe('Project Tree tests', function (): void {
const tree = new ProjectRootTreeItem(proj);
should(tree.children.map(x => x.projectUri.path)).deepEqual([
'/TestProj/Database References',
'/TestProj/SQLCMD Variables',
'/TestProj/someFolder1']);
should(tree.children.find(x => x.projectUri.path === '/TestProj/someFolder1')?.children.map(y => y.projectUri.path)).deepEqual([
'/TestProj/someFolder1/MyNestedFolder1',
'/TestProj/someFolder1/MyNestedFolder2',
'/TestProj/someFolder1/MyFile2.sql']);
'/TestProj/someFolder1/MyNestedFolder1',
'/TestProj/someFolder1/MyNestedFolder2',
'/TestProj/someFolder1/MyFile2.sql']);
});
it('Should be able to parse and include relative paths outside project folder', function (): void {
@@ -127,6 +130,7 @@ describe('Project Tree tests', function (): void {
const tree = new ProjectRootTreeItem(proj);
should(tree.children.map(x => x.projectUri.path)).deepEqual([
'/TestProj/Database References',
'/TestProj/SQLCMD Variables',
'/TestProj/MyFile1.sql',
'/TestProj/MyFile2.sql']);
});