mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-15 01:25:36 -05:00
Add sqlproj property to trace the origin of the project. (#18670)
* Add sqlproj property to trace the origin of the project. As part of the database migration process (schema conversion, in particular) we want to be able to tell when converted schemas are being built/deployed to the actual database server. Given that we rely on the SQL Database Projects ADS extension for the compilation/deployment, we don't have too many options other than updating the said extension. The suggested approach is to make the following changes: 1) Add new property to the sqlproj file (called `DatabaseSource`), which will maintain the origin(s) of the project. The property can contain multiple values (separated by semicolon), in case same project contains objects produced by multiple sources (extract schema, convert from another database, etc.). 2) During build and deploy actions, send the well-known values from the newly added property to the telemetry. We don't want to send any random value of the property, as it may raise some privacy concerns. Instead we define a list of the well-known values that we know do not carry any personal information and send those, if they are specified. This change adds all necessary APIs to the SQl Database projects extension which will be consumed by our migration extensions to populate new `DatabaseSource` property. * Use `undefined` instead of `null` Co-authored-by: Kim Santiago <kisantia@microsoft.com>
This commit is contained in:
@@ -14,7 +14,7 @@ import * as constants from '../common/constants';
|
||||
|
||||
import { promises as fs } from 'fs';
|
||||
import { Project } from '../models/project';
|
||||
import { exists, convertSlashesForSqlProj } from '../common/utils';
|
||||
import { exists, convertSlashesForSqlProj, getWellKnownDatabaseSources } from '../common/utils';
|
||||
import { Uri, window } from 'vscode';
|
||||
import { IDacpacReferenceSettings, IProjectReferenceSettings, ISystemDatabaseReferenceSettings } from '../models/IDatabaseReferenceSettings';
|
||||
import { SqlTargetPlatform } from 'sqldbproj';
|
||||
@@ -1558,6 +1558,118 @@ describe('Project: properties', function (): void {
|
||||
should(() => project.getDatabaseDefaultCollation())
|
||||
.throw('Invalid value specified for the property \'DefaultCollation\' in .sqlproj file');
|
||||
});
|
||||
|
||||
it('Should add database source to project property', async function (): Promise<void> {
|
||||
projFilePath = await testUtils.createTestSqlProjFile(baselines.sqlProjectInvalidCollationBaseline);
|
||||
const project = await Project.openProject(projFilePath);
|
||||
|
||||
// Should add a single database source
|
||||
await project.addDatabaseSource('test1');
|
||||
let databaseSourceItems: string[] = project.getDatabaseSourceValues();
|
||||
should(databaseSourceItems.length).equal(1);
|
||||
should(databaseSourceItems[0]).equal('test1');
|
||||
|
||||
// Should add multiple database sources
|
||||
await project.addDatabaseSource('test2');
|
||||
await project.addDatabaseSource('test3');
|
||||
databaseSourceItems = project.getDatabaseSourceValues();
|
||||
should(databaseSourceItems.length).equal(3);
|
||||
should(databaseSourceItems[0]).equal('test1');
|
||||
should(databaseSourceItems[1]).equal('test2');
|
||||
should(databaseSourceItems[2]).equal('test3');
|
||||
|
||||
// Should not add duplicate database sources
|
||||
await project.addDatabaseSource('test1');
|
||||
await project.addDatabaseSource('test2');
|
||||
await project.addDatabaseSource('test3');
|
||||
should(databaseSourceItems.length).equal(3);
|
||||
should(databaseSourceItems[0]).equal('test1');
|
||||
should(databaseSourceItems[1]).equal('test2');
|
||||
should(databaseSourceItems[2]).equal('test3');
|
||||
});
|
||||
|
||||
it('Should remove database source from project property', async function (): Promise<void> {
|
||||
projFilePath = await testUtils.createTestSqlProjFile(baselines.sqlProjectInvalidCollationBaseline);
|
||||
const project = await Project.openProject(projFilePath);
|
||||
|
||||
await project.addDatabaseSource('test1');
|
||||
await project.addDatabaseSource('test2');
|
||||
await project.addDatabaseSource('test3');
|
||||
await project.addDatabaseSource('test4');
|
||||
|
||||
let databaseSourceItems: string[] = project.getDatabaseSourceValues();
|
||||
should(databaseSourceItems.length).equal(4);
|
||||
|
||||
// Should remove database sources
|
||||
await project.removeDatabaseSource('test2');
|
||||
await project.removeDatabaseSource('test1');
|
||||
await project.removeDatabaseSource('test4');
|
||||
|
||||
databaseSourceItems = project.getDatabaseSourceValues();
|
||||
should(databaseSourceItems.length).equal(1);
|
||||
should(databaseSourceItems[0]).equal('test3');
|
||||
|
||||
// Should remove database source tag when last database source is removed
|
||||
await project.removeDatabaseSource('test3');
|
||||
databaseSourceItems = project.getDatabaseSourceValues();
|
||||
|
||||
should(databaseSourceItems.length).equal(0);
|
||||
});
|
||||
|
||||
it('Should add and remove values from project properties according to specified case sensitivity', async function (): Promise<void> {
|
||||
projFilePath = await testUtils.createTestSqlProjFile(baselines.sqlProjectInvalidCollationBaseline);
|
||||
const project = await Project.openProject(projFilePath);
|
||||
const propertyName = 'TestProperty';
|
||||
|
||||
// Should add value to collection
|
||||
await project['addValueToCollectionProjectProperty'](propertyName, 'test');
|
||||
should(project['evaluateProjectPropertyValue'](propertyName)).equal('test');
|
||||
|
||||
// Should not allow duplicates of different cases when comparing case insitively
|
||||
await project['addValueToCollectionProjectProperty'](propertyName, 'TEST');
|
||||
should(project['evaluateProjectPropertyValue'](propertyName)).equal('test');
|
||||
|
||||
// Should allow duplicates of differnt cases when comparing case sensitively
|
||||
await project['addValueToCollectionProjectProperty'](propertyName, 'TEST', true);
|
||||
should(project['evaluateProjectPropertyValue'](propertyName)).equal('test;TEST');
|
||||
|
||||
// Should remove values case insesitively
|
||||
await project['removeValueFromCollectionProjectProperty'](propertyName, 'Test');
|
||||
should(project['evaluateProjectPropertyValue'](propertyName)).equal('TEST');
|
||||
|
||||
// Should remove values case sensitively
|
||||
await project['removeValueFromCollectionProjectProperty'](propertyName, 'Test', true);
|
||||
should(project['evaluateProjectPropertyValue'](propertyName)).equal('TEST');
|
||||
await project['removeValueFromCollectionProjectProperty'](propertyName, 'TEST', true);
|
||||
should(project['evaluateProjectPropertyValue'](propertyName)).equal(undefined);
|
||||
});
|
||||
|
||||
it('Should only return well known database strings when getWellKnownDatabaseSourceString function is called', async function (): Promise<void> {
|
||||
projFilePath = await testUtils.createTestSqlProjFile(baselines.sqlProjectInvalidCollationBaseline);
|
||||
const project = await Project.openProject(projFilePath);
|
||||
|
||||
await project.addDatabaseSource('test1');
|
||||
await project.addDatabaseSource('test2');
|
||||
await project.addDatabaseSource('test3');
|
||||
await project.addDatabaseSource(constants.WellKnownDatabaseSources[0]);
|
||||
|
||||
should(getWellKnownDatabaseSources(project.getDatabaseSourceValues()).length).equal(1);
|
||||
should(getWellKnownDatabaseSources(project.getDatabaseSourceValues())[0]).equal(constants.WellKnownDatabaseSources[0]);
|
||||
});
|
||||
|
||||
it('Should throw error when adding or removing database source that contains semicolon', async function (): Promise<void> {
|
||||
projFilePath = await testUtils.createTestSqlProjFile(baselines.sqlProjectInvalidCollationBaseline);
|
||||
const project = await Project.openProject(projFilePath);
|
||||
const semicolon = ';';
|
||||
|
||||
await testUtils.shouldThrowSpecificError(
|
||||
async () => await project.addDatabaseSource(semicolon),
|
||||
constants.invalidProjectPropertyValueProvided(semicolon));
|
||||
|
||||
await testUtils.shouldThrowSpecificError(
|
||||
async () => await project.removeDatabaseSource(semicolon),
|
||||
constants.invalidProjectPropertyValueProvided(semicolon));
|
||||
});
|
||||
});
|
||||
|
||||
describe('Project: round trip updates', function (): void {
|
||||
|
||||
Reference in New Issue
Block a user