Add db and server sqlcmd variables for database references (#12089)

* add support for adding db and server sqlcmd variables

* fix incrementing

* split up test
This commit is contained in:
Kim Santiago
2020-09-03 10:27:02 -07:00
committed by GitHub
parent d97993e518
commit f29127d515
4 changed files with 91 additions and 12 deletions

View File

@@ -197,6 +197,8 @@ export const Value = 'Value';
export const ArtifactReference = 'ArtifactReference';
export const SuppressMissingDependenciesErrors = 'SuppressMissingDependenciesErrors';
export const DatabaseVariableLiteralValue = 'DatabaseVariableLiteralValue';
export const DatabaseSqlCmdVariable = 'DatabaseSqlCmdVariable';
export const ServerSqlCmdVariable = 'ServerSqlCmdVariable';
export const DSP = 'DSP';
export const Properties = 'Properties';
export const RelativeOuterPath = '..';

View File

@@ -126,7 +126,9 @@ export class AddDatabaseReferenceDialog {
databaseName: <string>this.databaseNameTextbox?.value,
databaseLocation: <DatabaseReferenceLocation>this.referenceLocationMap.get(<string>this.locationDropdown?.value),
dacpacFileLocation: vscode.Uri.file(<string>this.dacpacTextbox?.value),
databaseVariable: <string>this.databaseVariableTextbox?.value
databaseVariable: <string>this.databaseVariableTextbox?.value,
serverName: <string>this.serverNameTextbox?.value,
serverVariable: <string>this.serverVariableTextbox?.value
};
// TODO: add project reference support
}

View File

@@ -498,7 +498,6 @@ export class Project {
if (isSystemDatabaseProjectEntry) {
this.addSystemDatabaseReferenceToProjFile(<SystemDatabaseReferenceProjectEntry>entry);
} else {
const referenceNode = this.projFileXmlDoc.createElement(constants.ArtifactReference);
referenceNode.setAttribute(constants.Include, entry.pathForSqlProj());
this.addDatabaseReferenceChildren(referenceNode, entry);
@@ -519,13 +518,30 @@ export class Project {
suppressMissingDependenciesErrorNode.appendChild(falseTextNode);
referenceNode.appendChild(suppressMissingDependenciesErrorNode);
// TODO: add support for sqlcmd vars and server https://github.com/microsoft/azuredatastudio/issues/12036
if (entry.databaseVariableLiteralValue) {
if ((<DacpacReferenceProjectEntry>entry).databaseSqlCmdVariable) {
const databaseSqlCmdVariableElement = this.projFileXmlDoc.createElement(constants.DatabaseSqlCmdVariable);
const databaseSqlCmdVariableTextNode = this.projFileXmlDoc.createTextNode((<DacpacReferenceProjectEntry>entry).databaseSqlCmdVariable);
databaseSqlCmdVariableElement.appendChild(databaseSqlCmdVariableTextNode);
referenceNode.appendChild(databaseSqlCmdVariableElement);
// add SQLCMD variable
this.addSqlCmdVariable((<DacpacReferenceProjectEntry>entry).databaseSqlCmdVariable!, (<DacpacReferenceProjectEntry>entry).databaseName);
} else if (entry.databaseVariableLiteralValue) {
const databaseVariableLiteralValueElement = this.projFileXmlDoc.createElement(constants.DatabaseVariableLiteralValue);
const databaseTextNode = this.projFileXmlDoc.createTextNode(entry.databaseVariableLiteralValue);
databaseVariableLiteralValueElement.appendChild(databaseTextNode);
referenceNode.appendChild(databaseVariableLiteralValueElement);
}
if ((<DacpacReferenceProjectEntry>entry).serverSqlCmdVariable) {
const serverSqlCmdVariableElement = this.projFileXmlDoc.createElement(constants.ServerSqlCmdVariable);
const serverSqlCmdVariableTextNode = this.projFileXmlDoc.createTextNode((<DacpacReferenceProjectEntry>entry).serverSqlCmdVariable);
serverSqlCmdVariableElement.appendChild(serverSqlCmdVariableTextNode);
referenceNode.appendChild(serverSqlCmdVariableElement);
// add SQLCMD variable
this.addSqlCmdVariable((<DacpacReferenceProjectEntry>entry).serverSqlCmdVariable!, (<DacpacReferenceProjectEntry>entry).serverName!);
}
}
public addSqlCmdVariableToProjFile(entry: SqlCmdVariableProjectEntry): void {
@@ -561,7 +577,7 @@ export class Project {
*/
private getNextSqlCmdVariableCounter(): number {
const sqlCmdVariableNodes = this.projFileXmlDoc.documentElement.getElementsByTagName(constants.SqlCmdVariable);
let highestNumber = 1;
let highestNumber = 0;
for (let i = 0; i < sqlCmdVariableNodes.length; i++) {
const value: string = sqlCmdVariableNodes[i].getElementsByTagName(constants.Value)[0].childNodes[0].nodeValue;
@@ -767,11 +783,17 @@ export interface IDatabaseReferenceProjectEntry extends FileProjectEntry {
export class DacpacReferenceProjectEntry extends FileProjectEntry implements IDatabaseReferenceProjectEntry {
databaseLocation: DatabaseReferenceLocation;
databaseVariableLiteralValue?: string;
databaseSqlCmdVariable?: string;
serverName?: string;
serverSqlCmdVariable?: string;
constructor(settings: IDacpacReferenceSettings) {
super(settings.dacpacFileLocation, '', EntryType.DatabaseReference);
this.databaseLocation = settings.databaseLocation;
this.databaseSqlCmdVariable = settings.databaseVariable;
this.databaseVariableLiteralValue = settings.databaseName;
this.serverName = settings.serverName;
this.serverSqlCmdVariable = settings.serverVariable;
}
/**

View File

@@ -187,11 +187,11 @@ describe('Project: sqlproj content operations', function (): void {
await testUtils.shouldThrowSpecificError(async () => await project.getSystemDacpacUri(constants.masterDacpac), constants.invalidDataSchemaProvider);
});
it('Should add database references correctly', async function (): Promise<void> {
it('Should add system database references correctly', async function (): Promise<void> {
projFilePath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline);
const project = await Project.openProject(projFilePath);
should(project.databaseReferences.length).equal(0, 'There should be no datbase references to start with');
should(project.databaseReferences.length).equal(0, 'There should be no database references to start with');
await project.addSystemDatabaseReference({ databaseName: 'master', systemDb: SystemDatabase.master });
should(project.databaseReferences.length).equal(1, 'There should be one database reference after adding a reference to master');
should(project.databaseReferences[0].databaseName).equal(constants.master, 'The database reference should be master');
@@ -207,13 +207,66 @@ describe('Project: sqlproj content operations', function (): void {
projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql(convertSlashesForSqlProj(project.getSystemDacpacUri(constants.msdb).fsPath.substring(1)));
should(projFileText).containEql(convertSlashesForSqlProj(project.getSystemDacpacSsdtUri(constants.msdb).fsPath.substring(1)));
});
await project.addDatabaseReference({ dacpacFileLocation: Uri.file('test.dacpac'), databaseLocation: DatabaseReferenceLocation.sameDatabase });
should(project.databaseReferences.length).equal(3, 'There should be three database references after adding a reference to test');
should(project.databaseReferences[2].databaseName).equal('test', 'The database reference should be test');
it('Should add a dacpac reference to the same database correctly', async function (): Promise<void> {
projFilePath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline);
const project = await Project.openProject(projFilePath);
// add database reference in the same database
should(project.databaseReferences.length).equal(0, 'There should be no database references to start with');
await project.addDatabaseReference({ dacpacFileLocation: Uri.file('test1.dacpac'), databaseLocation: DatabaseReferenceLocation.sameDatabase });
should(project.databaseReferences.length).equal(1, 'There should be a database reference after adding a reference to test1');
should(project.databaseReferences[0].databaseName).equal('test1', 'The database reference should be test1');
// make sure reference to test.dacpac was added
projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('test.dacpac');
let projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('test1.dacpac');
});
it('Should add a dacpac reference to a different database in the same server correctly', async function (): Promise<void> {
projFilePath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline);
const project = await Project.openProject(projFilePath);
// add database reference to a different database on the same server
should(project.databaseReferences.length).equal(0, 'There should be no database references to start with');
await project.addDatabaseReference({
dacpacFileLocation: Uri.file('test2.dacpac'),
databaseLocation: DatabaseReferenceLocation.differentDatabaseSameServer,
databaseName: 'test2DbName',
databaseVariable: 'test2Db'
});
should(project.databaseReferences.length).equal(1, 'There should be a database reference after adding a reference to test2');
should(project.databaseReferences[0].databaseName).equal('test2', 'The database reference should be test2');
// make sure reference to test2.dacpac and SQLCMD variable was added
let projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('test2.dacpac');
should(projFileText).containEql('<DatabaseSqlCmdVariable>test2Db</DatabaseSqlCmdVariable>');
should(projFileText).containEql('<SqlCmdVariable Include="test2Db">');
});
it('Should add a dacpac reference to a different database in a different server correctly', async function (): Promise<void> {
projFilePath = await testUtils.createTestSqlProjFile(baselines.newProjectFileBaseline);
const project = await Project.openProject(projFilePath);
// add database reference to a different database on a different server
should(project.databaseReferences.length).equal(0, 'There should be no database references to start with');
await project.addDatabaseReference({
dacpacFileLocation: Uri.file('test3.dacpac'),
databaseLocation: DatabaseReferenceLocation.differentDatabaseDifferentServer,
databaseName: 'test3DbName',
databaseVariable: 'test3Db',
serverName: 'otherServerName',
serverVariable: 'otherServer'
});
should(project.databaseReferences.length).equal(1, 'There should be a database reference after adding a reference to test3');
should(project.databaseReferences[0].databaseName).equal('test3', 'The database reference should be test3');
// make sure reference to test2.dacpac and SQLCMD variables were added
let projFileText = (await fs.readFile(projFilePath)).toString();
should(projFileText).containEql('test3.dacpac');
should(projFileText).containEql('<DatabaseSqlCmdVariable>test3Db</DatabaseSqlCmdVariable>');
should(projFileText).containEql('<SqlCmdVariable Include="test3Db">');
should(projFileText).containEql('<ServerSqlCmdVariable>otherServer</ServerSqlCmdVariable>');
should(projFileText).containEql('<SqlCmdVariable Include="otherServer">');
});
it('Should not allow adding duplicate database references', async function (): Promise<void> {