mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-18 17:22:45 -05:00
Hook up add database references dialog (#12002)
* initial dialog * got enabling working * add tests * cleanup * add test coverage for systemDbRadioButtonClick() * change DAC to .dacpac * remove isEmptyOrUndefined * hook up add database reference dialog * cleanup * Addressing comments
This commit is contained in:
@@ -7,7 +7,7 @@ import { DatabaseReferenceLocation, SystemDatabase } from './project';
|
||||
import { Uri } from 'vscode';
|
||||
|
||||
export interface IDatabaseReferenceSettings {
|
||||
databaseName: string;
|
||||
databaseName?: string;
|
||||
}
|
||||
|
||||
export interface ISystemDatabaseReferenceSettings extends IDatabaseReferenceSettings {
|
||||
|
||||
@@ -14,6 +14,7 @@ import * as templates from '../templates/templates';
|
||||
import { Uri, window } from 'vscode';
|
||||
import { promises as fs } from 'fs';
|
||||
import { DataSource } from './dataSources/dataSources';
|
||||
import { ISystemDatabaseReferenceSettings, IDacpacReferenceSettings } from './IDatabaseReferenceSettings';
|
||||
|
||||
/**
|
||||
* Class representing a Project, and providing functions for operating on it
|
||||
@@ -123,7 +124,12 @@ export class Project {
|
||||
|
||||
const nameNodes = references[r].getElementsByTagName(constants.DatabaseVariableLiteralValue);
|
||||
const name = nameNodes.length === 1 ? nameNodes[0].childNodes[0].nodeValue : undefined;
|
||||
this.databaseReferences.push(new DacpacReferenceProjectEntry(Uri.file(filepath), name ? DatabaseReferenceLocation.differentDatabaseSameServer : DatabaseReferenceLocation.sameDatabase, name));
|
||||
|
||||
this.databaseReferences.push(new DacpacReferenceProjectEntry({
|
||||
dacpacFileLocation: Uri.file(utils.getPlatformSafeFileEntryPath(filepath)),
|
||||
databaseLocation: name ? DatabaseReferenceLocation.differentDatabaseSameServer : DatabaseReferenceLocation.sameDatabase,
|
||||
databaseName: name
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,21 +291,19 @@ export class Project {
|
||||
/**
|
||||
* Adds reference to the appropriate system database dacpac to the project
|
||||
*/
|
||||
public async addSystemDatabaseReference(name: SystemDatabase): Promise<void> {
|
||||
public async addSystemDatabaseReference(settings: ISystemDatabaseReferenceSettings): Promise<void> {
|
||||
let uri: Uri;
|
||||
let ssdtUri: Uri;
|
||||
let dbName: string;
|
||||
if (name === SystemDatabase.master) {
|
||||
|
||||
if (settings.systemDb === SystemDatabase.master) {
|
||||
uri = this.getSystemDacpacUri(constants.masterDacpac);
|
||||
ssdtUri = this.getSystemDacpacSsdtUri(constants.masterDacpac);
|
||||
dbName = constants.master;
|
||||
} else {
|
||||
uri = this.getSystemDacpacUri(constants.msdbDacpac);
|
||||
ssdtUri = this.getSystemDacpacSsdtUri(constants.msdbDacpac);
|
||||
dbName = constants.msdb;
|
||||
}
|
||||
|
||||
let systemDatabaseReferenceProjectEntry = new SystemDatabaseReferenceProjectEntry(uri, ssdtUri, dbName);
|
||||
const systemDatabaseReferenceProjectEntry = new SystemDatabaseReferenceProjectEntry(uri, ssdtUri, <string>settings.databaseName);
|
||||
await this.addToProjFile(systemDatabaseReferenceProjectEntry);
|
||||
}
|
||||
|
||||
@@ -340,8 +344,8 @@ export class Project {
|
||||
* @param uri Uri of the dacpac
|
||||
* @param databaseName name of the database
|
||||
*/
|
||||
public async addDatabaseReference(uri: Uri, databaseLocation: DatabaseReferenceLocation, databaseName?: string): Promise<void> {
|
||||
let databaseReferenceEntry = new DacpacReferenceProjectEntry(uri, databaseLocation, databaseName);
|
||||
public async addDatabaseReference(settings: IDacpacReferenceSettings): Promise<void> {
|
||||
const databaseReferenceEntry = new DacpacReferenceProjectEntry(settings);
|
||||
await this.addToProjFile(databaseReferenceEntry);
|
||||
}
|
||||
|
||||
@@ -432,32 +436,41 @@ export class Project {
|
||||
throw new Error(constants.unableToFindObject(path, constants.folderObject));
|
||||
}
|
||||
|
||||
private addSystemDatabaseReferenceToProjFile(entry: SystemDatabaseReferenceProjectEntry): void {
|
||||
const systemDbReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
||||
|
||||
// if it's a system database reference, we'll add an additional node with the SSDT location of the dacpac later
|
||||
systemDbReferenceNode.setAttribute(constants.Condition, constants.NetCoreCondition);
|
||||
systemDbReferenceNode.setAttribute(constants.Include, entry.pathForSqlProj());
|
||||
this.addDatabaseReferenceChildren(systemDbReferenceNode, entry);
|
||||
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(systemDbReferenceNode);
|
||||
this.databaseReferences.push(entry);
|
||||
|
||||
// add a reference to the system dacpac in SSDT if it's a system db
|
||||
const ssdtReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
||||
ssdtReferenceNode.setAttribute(constants.Condition, constants.NotNetCoreCondition);
|
||||
ssdtReferenceNode.setAttribute(constants.Include, entry.ssdtPathForSqlProj());
|
||||
this.addDatabaseReferenceChildren(ssdtReferenceNode, entry);
|
||||
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(ssdtReferenceNode);
|
||||
}
|
||||
|
||||
private addDatabaseReferenceToProjFile(entry: IDatabaseReferenceProjectEntry): void {
|
||||
// check if reference to this database already exists
|
||||
if (this.databaseReferenceExists(entry)) {
|
||||
throw new Error(constants.databaseReferenceAlreadyExists);
|
||||
}
|
||||
|
||||
let referenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
||||
const isSystemDatabaseProjectEntry = (<SystemDatabaseReferenceProjectEntry>entry).ssdtUri;
|
||||
|
||||
// if it's a system database reference, we'll add an additional node with the SSDT location of the dacpac later
|
||||
if (isSystemDatabaseProjectEntry) {
|
||||
referenceNode.setAttribute(constants.Condition, constants.NetCoreCondition);
|
||||
}
|
||||
this.addSystemDatabaseReferenceToProjFile(<SystemDatabaseReferenceProjectEntry>entry);
|
||||
} else {
|
||||
|
||||
referenceNode.setAttribute(constants.Include, entry.pathForSqlProj());
|
||||
this.addDatabaseReferenceChildren(referenceNode, entry.sqlCmdName);
|
||||
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(referenceNode);
|
||||
this.databaseReferences.push(entry);
|
||||
|
||||
// add a reference to the system dacpac in SSDT if it's a system db
|
||||
if (isSystemDatabaseProjectEntry) {
|
||||
let ssdtReferenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
||||
ssdtReferenceNode.setAttribute(constants.Condition, constants.NotNetCoreCondition);
|
||||
ssdtReferenceNode.setAttribute(constants.Include, (<SystemDatabaseReferenceProjectEntry>entry).ssdtPathForSqlProj());
|
||||
this.addDatabaseReferenceChildren(ssdtReferenceNode, entry.sqlCmdName);
|
||||
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(ssdtReferenceNode);
|
||||
const referenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
|
||||
referenceNode.setAttribute(constants.Include, entry.pathForSqlProj());
|
||||
this.addDatabaseReferenceChildren(referenceNode, entry);
|
||||
this.findOrCreateItemGroup(constants.ArtifactReference).appendChild(referenceNode);
|
||||
this.databaseReferences.push(entry);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -466,17 +479,19 @@ export class Project {
|
||||
return found;
|
||||
}
|
||||
|
||||
private addDatabaseReferenceChildren(referenceNode: any, name?: string): void {
|
||||
let suppressMissingDependenciesErrorNode = this.projFileXmlDoc.createElement(constants.SuppressMissingDependenciesErrors);
|
||||
let falseTextNode = this.projFileXmlDoc.createTextNode('False');
|
||||
private addDatabaseReferenceChildren(referenceNode: any, entry: IDatabaseReferenceProjectEntry): void {
|
||||
// TODO: create checkbox for this setting
|
||||
const suppressMissingDependenciesErrorNode = this.projFileXmlDoc.createElement(constants.SuppressMissingDependenciesErrors);
|
||||
const falseTextNode = this.projFileXmlDoc.createTextNode('False');
|
||||
suppressMissingDependenciesErrorNode.appendChild(falseTextNode);
|
||||
referenceNode.appendChild(suppressMissingDependenciesErrorNode);
|
||||
|
||||
if (name) {
|
||||
let databaseVariableLiteralValue = this.projFileXmlDoc.createElement(constants.DatabaseVariableLiteralValue);
|
||||
let databaseTextNode = this.projFileXmlDoc.createTextNode(name);
|
||||
databaseVariableLiteralValue.appendChild(databaseTextNode);
|
||||
referenceNode.appendChild(databaseVariableLiteralValue);
|
||||
// TODO: add support for sqlcmd vars and server https://github.com/microsoft/azuredatastudio/issues/12036
|
||||
if (entry.databaseVariableLiteralValue) {
|
||||
const databaseVariableLiteralValueElement = this.projFileXmlDoc.createElement(constants.DatabaseVariableLiteralValue);
|
||||
const databaseTextNode = this.projFileXmlDoc.createTextNode(entry.databaseVariableLiteralValue);
|
||||
databaseVariableLiteralValueElement.appendChild(databaseTextNode);
|
||||
referenceNode.appendChild(databaseVariableLiteralValueElement);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -521,13 +536,22 @@ export class Project {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update system db references to have the ADS and SSDT paths to the system dacpacs
|
||||
*/
|
||||
public async updateSystemDatabaseReferencesInProjFile(): Promise<void> {
|
||||
// find all system database references
|
||||
for (let r = 0; r < this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ArtifactReference).length; r++) {
|
||||
const currentNode = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.ArtifactReference)[r];
|
||||
if (!currentNode.getAttribute(constants.Condition) && currentNode.getAttribute(constants.Include).includes(constants.DacpacRootPath)) {
|
||||
// get name of system database
|
||||
const name = currentNode.getAttribute(constants.Include).includes(constants.master) ? SystemDatabase.master : SystemDatabase.msdb;
|
||||
const systemDb = currentNode.getAttribute(constants.Include).includes(constants.master) ? SystemDatabase.master : SystemDatabase.msdb;
|
||||
|
||||
// get name
|
||||
const nameNodes = currentNode.getElementsByTagName(constants.DatabaseVariableLiteralValue);
|
||||
const databaseVariableName = nameNodes[0].childNodes[0]?.nodeValue;
|
||||
|
||||
// remove this node
|
||||
this.projFileXmlDoc.documentElement.removeChild(currentNode);
|
||||
|
||||
// delete ItemGroup if there aren't any other children
|
||||
@@ -536,9 +560,9 @@ export class Project {
|
||||
}
|
||||
|
||||
// remove from database references because it'll get added again later
|
||||
this.databaseReferences.splice(this.databaseReferences.findIndex(n => n.databaseName === (name === SystemDatabase.master ? constants.master : constants.msdb)), 1);
|
||||
this.databaseReferences.splice(this.databaseReferences.findIndex(n => n.databaseName === (systemDb === SystemDatabase.master ? constants.master : constants.msdb)), 1);
|
||||
|
||||
await this.addSystemDatabaseReference(name);
|
||||
await this.addSystemDatabaseReference({ databaseName: databaseVariableName, systemDb: systemDb });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -643,26 +667,37 @@ export class ProjectEntry {
|
||||
|
||||
export interface IDatabaseReferenceProjectEntry extends ProjectEntry {
|
||||
databaseName: string;
|
||||
sqlCmdName?: string | undefined;
|
||||
databaseVariableLiteralValue?: string;
|
||||
}
|
||||
|
||||
export class DacpacReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
|
||||
sqlCmdName: string | undefined;
|
||||
databaseLocation: DatabaseReferenceLocation;
|
||||
databaseVariableLiteralValue?: string;
|
||||
|
||||
constructor(uri: Uri, public databaseLocation: DatabaseReferenceLocation, name?: string) {
|
||||
super(uri, '', EntryType.DatabaseReference);
|
||||
this.sqlCmdName = name;
|
||||
constructor(settings: IDacpacReferenceSettings) {
|
||||
super(settings.dacpacFileLocation, '', EntryType.DatabaseReference);
|
||||
this.databaseLocation = settings.databaseLocation;
|
||||
this.databaseVariableLiteralValue = settings.databaseName;
|
||||
}
|
||||
|
||||
/**
|
||||
* File name that gets displayed in the project tree
|
||||
*/
|
||||
public get databaseName(): string {
|
||||
return path.parse(utils.getPlatformSafeFileEntryPath(this.fsUri.fsPath)).name;
|
||||
}
|
||||
}
|
||||
|
||||
class SystemDatabaseReferenceProjectEntry extends DacpacReferenceProjectEntry {
|
||||
constructor(uri: Uri, public ssdtUri: Uri, name: string) {
|
||||
super(uri, DatabaseReferenceLocation.differentDatabaseSameServer, name);
|
||||
this.sqlCmdName = name;
|
||||
class SystemDatabaseReferenceProjectEntry extends ProjectEntry implements IDatabaseReferenceProjectEntry {
|
||||
constructor(uri: Uri, public ssdtUri: Uri, public databaseVariableLiteralValue: string) {
|
||||
super(uri, '', EntryType.DatabaseReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* File name that gets displayed in the project tree
|
||||
*/
|
||||
public get databaseName(): string {
|
||||
return path.parse(utils.getPlatformSafeFileEntryPath(this.fsUri.fsPath)).name;
|
||||
}
|
||||
|
||||
public pathForSqlProj(): string {
|
||||
|
||||
Reference in New Issue
Block a user