mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
@@ -15,7 +15,7 @@ import * as uiLoc from '../ui/localizedConstants';
|
|||||||
import { UserDialog } from './ui/userDialog';
|
import { UserDialog } from './ui/userDialog';
|
||||||
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
import { IObjectManagementService, ObjectManagement } from 'mssql';
|
||||||
import * as constants from '../constants';
|
import * as constants from '../constants';
|
||||||
import { refreshParentNode } from './utils';
|
import { refreshParentNode, escapeSingleQuotes } from './utils';
|
||||||
import { TelemetryReporter } from '../telemetry';
|
import { TelemetryReporter } from '../telemetry';
|
||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './ui/objectManagementDialogBase';
|
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './ui/objectManagementDialogBase';
|
||||||
import { ServerRoleDialog } from './ui/serverRoleDialog';
|
import { ServerRoleDialog } from './ui/serverRoleDialog';
|
||||||
@@ -113,8 +113,8 @@ async function handleObjectPropertiesDialogCommand(context: azdata.ObjectExplore
|
|||||||
try {
|
try {
|
||||||
const parentUrn = context.nodeInfo ? await getParentUrn(context) : undefined;
|
const parentUrn = context.nodeInfo ? await getParentUrn(context) : undefined;
|
||||||
const objectType = context.nodeInfo ? context.nodeInfo.nodeType as ObjectManagement.NodeType : (context.connectionProfile.databaseName === '' ? ObjectManagement.NodeType.Server : ObjectManagement.NodeType.Database);
|
const objectType = context.nodeInfo ? context.nodeInfo.nodeType as ObjectManagement.NodeType : (context.connectionProfile.databaseName === '' ? ObjectManagement.NodeType.Server : ObjectManagement.NodeType.Database);
|
||||||
const objectName = context.nodeInfo ? context.nodeInfo.label : objectManagementLoc.PropertiesHeader;
|
const objectName = context.nodeInfo ? context.nodeInfo.label : (!context.connectionProfile.databaseName ? context.connectionProfile.serverName : context.connectionProfile.databaseName);
|
||||||
const objectUrn = context.nodeInfo ? context.nodeInfo!.metadata!.urn : undefined;
|
const objectUrn = context.nodeInfo ? context.nodeInfo!.metadata!.urn : (context.connectionProfile.databaseName === '' ? 'Server' : `Server/Database[@Name='${escapeSingleQuotes(context.connectionProfile.databaseName)}']`);
|
||||||
|
|
||||||
const options: ObjectManagementDialogOptions = {
|
const options: ObjectManagementDialogOptions = {
|
||||||
connectionUri: connectionUri,
|
connectionUri: connectionUri,
|
||||||
|
|||||||
@@ -43,5 +43,3 @@ export const enum TelemetryActions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const ObjectManagementViewName = 'ObjectManagement';
|
export const ObjectManagementViewName = 'ObjectManagement';
|
||||||
|
|
||||||
export const AzureSQLMI = 'Azure SQL Database Managed Instance';
|
|
||||||
|
|||||||
@@ -482,7 +482,7 @@ export interface Server extends ObjectManagement.SqlObject {
|
|||||||
rootDirectory: string;
|
rootDirectory: string;
|
||||||
serverCollation: string;
|
serverCollation: string;
|
||||||
serviceTier: string;
|
serviceTier: string;
|
||||||
storageSpaceUsageInGB: number;
|
storageSpaceUsageInMB: number;
|
||||||
minServerMemory: number;
|
minServerMemory: number;
|
||||||
maxServerMemory: number;
|
maxServerMemory: number;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -252,11 +252,11 @@ export const IsHadrEnabledText = localize('objectManagement.isHadrEnabled', "Is
|
|||||||
export const IsPolyBaseInstalledText = localize('objectManagement.isPolyBaseInstalled', "Is PolyBase Installed");
|
export const IsPolyBaseInstalledText = localize('objectManagement.isPolyBaseInstalled', "Is PolyBase Installed");
|
||||||
export const IsXTPSupportedText = localize('objectManagement.isXTPSupported', "Is XTP Supported");
|
export const IsXTPSupportedText = localize('objectManagement.isXTPSupported', "Is XTP Supported");
|
||||||
export const ProductText = localize('objectManagement.product', "Product");
|
export const ProductText = localize('objectManagement.product', "Product");
|
||||||
export const ReservedStorageSizeInMBText = localize('objectManagement.reservedStorageSizeInMB', "Reserved Storage Size");
|
export const ReservedStorageSizeInMBText = localize('objectManagement.reservedStorageSizeInMB', "Reserved Storage Size (MB)");
|
||||||
export const RootDirectoryText = localize('objectManagement.rootDirectory', "Root Directory");
|
export const RootDirectoryText = localize('objectManagement.rootDirectory', "Root Directory");
|
||||||
export const ServerCollationText = localize('objectManagement.serverCollation', "Server Collation");
|
export const ServerCollationText = localize('objectManagement.serverCollation', "Server Collation");
|
||||||
export const ServiceTierText = localize('objectManagement.serviceTier', "Service Tier");
|
export const ServiceTierText = localize('objectManagement.serviceTier', "Service Tier");
|
||||||
export const StorageSpaceUsageInGBText = localize('objectManagement.storageSpaceUsageInGB', "Storage Space Usage");
|
export const StorageSpaceUsageInMBText = localize('objectManagement.storageSpaceUsageInMB', "Storage Space Usage (MB)");
|
||||||
export const VersionText = localize('objectManagement.versionText', "Version");
|
export const VersionText = localize('objectManagement.versionText', "Version");
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import * as azdata from 'azdata';
|
|||||||
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
import { ObjectManagementDialogBase, ObjectManagementDialogOptions } from './objectManagementDialogBase';
|
||||||
import { IObjectManagementService } from 'mssql';
|
import { IObjectManagementService } from 'mssql';
|
||||||
import * as localizedConstants from '../localizedConstants';
|
import * as localizedConstants from '../localizedConstants';
|
||||||
import { AzureSQLMI, ViewServerPropertiesDocUrl } from '../constants';
|
import { ViewServerPropertiesDocUrl } from '../constants';
|
||||||
import { Server, ServerViewInfo } from '../interfaces';
|
import { Server, ServerViewInfo } from '../interfaces';
|
||||||
|
|
||||||
export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, ServerViewInfo> {
|
export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, ServerViewInfo> {
|
||||||
@@ -29,23 +29,32 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
private rootDirectoryInput: azdata.InputBoxComponent;
|
private rootDirectoryInput: azdata.InputBoxComponent;
|
||||||
private serverCollationInput: azdata.InputBoxComponent;
|
private serverCollationInput: azdata.InputBoxComponent;
|
||||||
private serviceTierInput: azdata.InputBoxComponent;
|
private serviceTierInput: azdata.InputBoxComponent;
|
||||||
private storageSpaceUsageInGBInput: azdata.InputBoxComponent;
|
private storageSpaceUsageInMBInput: azdata.InputBoxComponent;
|
||||||
private versionInput: azdata.InputBoxComponent;
|
private versionInput: azdata.InputBoxComponent;
|
||||||
|
|
||||||
private memoryTab: azdata.Tab;
|
private memoryTab: azdata.Tab;
|
||||||
private memorySection: azdata.GroupContainer;
|
private memorySection: azdata.GroupContainer;
|
||||||
private minServerMemoryInput: azdata.InputBoxComponent;
|
private minServerMemoryInput: azdata.InputBoxComponent;
|
||||||
private maxServerMemoryInput: azdata.InputBoxComponent;
|
private maxServerMemoryInput: azdata.InputBoxComponent;
|
||||||
|
private engineEdition: azdata.DatabaseEngineEdition;
|
||||||
|
|
||||||
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
constructor(objectManagementService: IObjectManagementService, options: ObjectManagementDialogOptions) {
|
||||||
super(objectManagementService, options);
|
super(objectManagementService, options);
|
||||||
|
this.dialogObject.customButtons[1].enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override get helpUrl(): string {
|
protected override get helpUrl(): string {
|
||||||
return ViewServerPropertiesDocUrl;
|
return ViewServerPropertiesDocUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override onFormFieldChange(): void {
|
||||||
|
this.dialogObject.customButtons[1].enabled = false;
|
||||||
|
this.dialogObject.okButton.enabled = this.isDirty;
|
||||||
|
}
|
||||||
|
|
||||||
protected async initializeUI(): Promise<void> {
|
protected async initializeUI(): Promise<void> {
|
||||||
|
const serverInfo = await azdata.connection.getServerInfo(this.options.objectExplorerContext.connectionProfile.id);
|
||||||
|
this.engineEdition = serverInfo.engineEditionId;
|
||||||
this.initializeGeneralSection();
|
this.initializeGeneralSection();
|
||||||
this.initializeMemorySection();
|
this.initializeMemorySection();
|
||||||
const serverPropertiesTabGroup = { title: '', tabs: [this.generalTab, this.memoryTab] };
|
const serverPropertiesTabGroup = { title: '', tabs: [this.generalTab, this.memoryTab] };
|
||||||
@@ -98,7 +107,7 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
this.productInput = this.createInputBox(localizedConstants.ProductText, async () => { }, this.objectInfo.product, this.options.isNewObject);
|
this.productInput = this.createInputBox(localizedConstants.ProductText, async () => { }, this.objectInfo.product, this.options.isNewObject);
|
||||||
const productContainer = this.createLabelInputContainer(localizedConstants.ProductText, this.productInput);
|
const productContainer = this.createLabelInputContainer(localizedConstants.ProductText, this.productInput);
|
||||||
|
|
||||||
this.reservedStorageSizeInMBInput = this.createInputBox(localizedConstants.ReservedStorageSizeInMBText, async () => { }, this.objectInfo.reservedStorageSizeMB.toString().concat(' MB'), this.options.isNewObject);
|
this.reservedStorageSizeInMBInput = this.createInputBox(localizedConstants.ReservedStorageSizeInMBText, async () => { }, localizedConstants.StringValueInMB(this.objectInfo.reservedStorageSizeMB.toString()), this.options.isNewObject);
|
||||||
const reservedStorageSizeInMBContainer = this.createLabelInputContainer(localizedConstants.ReservedStorageSizeInMBText, this.reservedStorageSizeInMBInput);
|
const reservedStorageSizeInMBContainer = this.createLabelInputContainer(localizedConstants.ReservedStorageSizeInMBText, this.reservedStorageSizeInMBInput);
|
||||||
|
|
||||||
this.rootDirectoryInput = this.createInputBox(localizedConstants.RootDirectoryText, async () => { }, this.objectInfo.rootDirectory, this.options.isNewObject);
|
this.rootDirectoryInput = this.createInputBox(localizedConstants.RootDirectoryText, async () => { }, this.objectInfo.rootDirectory, this.options.isNewObject);
|
||||||
@@ -110,8 +119,8 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
this.serviceTierInput = this.createInputBox(localizedConstants.ServiceTierText, async () => { }, this.objectInfo.serviceTier, this.options.isNewObject);
|
this.serviceTierInput = this.createInputBox(localizedConstants.ServiceTierText, async () => { }, this.objectInfo.serviceTier, this.options.isNewObject);
|
||||||
const serviceTierContainer = this.createLabelInputContainer(localizedConstants.ServiceTierText, this.serviceTierInput);
|
const serviceTierContainer = this.createLabelInputContainer(localizedConstants.ServiceTierText, this.serviceTierInput);
|
||||||
|
|
||||||
this.storageSpaceUsageInGBInput = this.createInputBox(localizedConstants.StorageSpaceUsageInGBText, async () => { }, this.objectInfo.storageSpaceUsageInGB.toString().concat(' GB'), this.options.isNewObject);
|
this.storageSpaceUsageInMBInput = this.createInputBox(localizedConstants.StorageSpaceUsageInMBText, async () => { }, localizedConstants.StringValueInMB(this.objectInfo.storageSpaceUsageInMB.toString()), this.options.isNewObject);
|
||||||
const storageSpaceUsageInGbContainer = this.createLabelInputContainer(localizedConstants.StorageSpaceUsageInGBText, this.storageSpaceUsageInGBInput);
|
const storageSpaceUsageInMbContainer = this.createLabelInputContainer(localizedConstants.StorageSpaceUsageInMBText, this.storageSpaceUsageInMBInput);
|
||||||
|
|
||||||
this.versionInput = this.createInputBox(localizedConstants.VersionText, async () => { }, this.objectInfo.version, this.options.isNewObject);
|
this.versionInput = this.createInputBox(localizedConstants.VersionText, async () => { }, this.objectInfo.version, this.options.isNewObject);
|
||||||
const versionContainer = this.createLabelInputContainer(localizedConstants.VersionText, this.versionInput);
|
const versionContainer = this.createLabelInputContainer(localizedConstants.VersionText, this.versionInput);
|
||||||
@@ -136,9 +145,9 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
versionContainer
|
versionContainer
|
||||||
];
|
];
|
||||||
|
|
||||||
if (this.objectInfo.platform === AzureSQLMI) {
|
if (this.engineEdition === azdata.DatabaseEngineEdition.SqlManagedInstance) {
|
||||||
platformItems.unshift(hardwareGenerationContainer);
|
platformItems.unshift(hardwareGenerationContainer);
|
||||||
sqlServerItems.push(reservedStorageSizeInMBContainer, serviceTierContainer, storageSpaceUsageInGbContainer);
|
sqlServerItems.push(reservedStorageSizeInMBContainer, serviceTierContainer, storageSpaceUsageInMbContainer);
|
||||||
// remove isXTPSupported
|
// remove isXTPSupported
|
||||||
sqlServerItems.splice(3, 1);
|
sqlServerItems.splice(3, 1);
|
||||||
}
|
}
|
||||||
@@ -152,14 +161,15 @@ export class ServerPropertiesDialog extends ObjectManagementDialogBase<Server, S
|
|||||||
}
|
}
|
||||||
|
|
||||||
private initializeMemorySection(): void {
|
private initializeMemorySection(): void {
|
||||||
|
const isEnabled = this.engineEdition !== azdata.DatabaseEngineEdition.SqlManagedInstance;
|
||||||
this.minServerMemoryInput = this.createInputBox(localizedConstants.minServerMemoryText, async (newValue) => {
|
this.minServerMemoryInput = this.createInputBox(localizedConstants.minServerMemoryText, async (newValue) => {
|
||||||
this.objectInfo.minServerMemory = +newValue;
|
this.objectInfo.minServerMemory = +newValue;
|
||||||
}, this.objectInfo.minServerMemory.toString(), true, 'number');
|
}, this.objectInfo.minServerMemory.toString(), isEnabled, 'number');
|
||||||
const minMemoryContainer = this.createLabelInputContainer(localizedConstants.minServerMemoryText, this.minServerMemoryInput);
|
const minMemoryContainer = this.createLabelInputContainer(localizedConstants.minServerMemoryText, this.minServerMemoryInput);
|
||||||
|
|
||||||
this.maxServerMemoryInput = this.createInputBox(localizedConstants.maxServerMemoryText, async (newValue) => {
|
this.maxServerMemoryInput = this.createInputBox(localizedConstants.maxServerMemoryText, async (newValue) => {
|
||||||
this.objectInfo.maxServerMemory = +newValue;
|
this.objectInfo.maxServerMemory = +newValue;
|
||||||
}, this.objectInfo.maxServerMemory.toString(), true, 'number');
|
}, this.objectInfo.maxServerMemory.toString(), isEnabled, 'number');
|
||||||
const maxMemoryContainer = this.createLabelInputContainer(localizedConstants.maxServerMemoryText, this.maxServerMemoryInput);
|
const maxMemoryContainer = this.createLabelInputContainer(localizedConstants.maxServerMemoryText, this.maxServerMemoryInput);
|
||||||
|
|
||||||
this.memorySection = this.createGroup('', [
|
this.memorySection = this.createGroup('', [
|
||||||
|
|||||||
@@ -47,3 +47,8 @@ export function isValidSQLPassword(password: string, userName: string = 'sa'): b
|
|||||||
export function convertNumToTwoDecimalStringinMB(value: number): string {
|
export function convertNumToTwoDecimalStringinMB(value: number): string {
|
||||||
return localizedConstants.StringValueInMB(value?.toFixed(2));
|
return localizedConstants.StringValueInMB(value?.toFixed(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Escape single quotes
|
||||||
|
export function escapeSingleQuotes(value: string): string {
|
||||||
|
return value.replace(/'/g, "\'");
|
||||||
|
}
|
||||||
|
|||||||
32
extensions/mssql/src/test/util/utils.test.ts
Normal file
32
extensions/mssql/src/test/util/utils.test.ts
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*---------------------------------------------------------------------------------------------
|
||||||
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||||
|
* Licensed under the Source EULA. See License.txt in the project root for license information.
|
||||||
|
*--------------------------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
import { escapeSingleQuotes } from '../../objectManagement/utils';
|
||||||
|
import 'mocha';
|
||||||
|
import * as should from 'should';
|
||||||
|
|
||||||
|
describe('escapeSingleQuotes Method Tests', () => {
|
||||||
|
|
||||||
|
it('Should return original string if no single quotes', function (): void {
|
||||||
|
const dbName = "My Database";
|
||||||
|
const testString: string = "Server/Database[@Name='My Database']";
|
||||||
|
const ret = `Server/Database[@Name='${escapeSingleQuotes(dbName)}']`;
|
||||||
|
should(ret).equal(testString);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return original string if it contains single quotes', function (): void {
|
||||||
|
const dbName = "My'Database";
|
||||||
|
const testString: string = "Server/Database[@Name='My'Database']";
|
||||||
|
const ret = `Server/Database[@Name='${escapeSingleQuotes(dbName)}']`;
|
||||||
|
should(ret).equal(testString);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('Should return escaped original string if it contains an escaped single quote', function (): void {
|
||||||
|
const dbName = "My Database\'WithEscapedSingleQuote";
|
||||||
|
const testString: string = "Server/Database[@Name='My Database\'WithEscapedSingleQuote']";
|
||||||
|
const ret = `Server/Database[@Name='${escapeSingleQuotes(dbName)}']`;
|
||||||
|
should(ret).equal(testString);
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user