add foreign keys and constraints (#17697)

* foreign keys and constraints

* refactoring

* fix issues
This commit is contained in:
Alan Ren
2021-11-17 19:15:24 -08:00
committed by GitHub
parent 6f03cbac97
commit 7c26e14605
8 changed files with 310 additions and 75 deletions

View File

@@ -1079,18 +1079,20 @@ declare module 'azdata' {
/** /**
* Name of the common table properties. * Name of the common table properties.
* Extensions can use the names to access the designer data. * Extensions can use the names to access the designer view model.
*/ */
export enum TableProperty { export enum TableProperty {
Columns = 'columns', Columns = 'columns',
Description = 'description', Description = 'description',
Name = 'name', Name = 'name',
Schema = 'schema', Schema = 'schema',
Script = 'script' Script = 'script',
ForeignKeys = 'foreignKeys',
CheckConstraints = 'checkConstraints',
} }
/** /**
* Name of the common table column properties. * Name of the common table column properties.
* Extensions can use the names to access the designer data. * Extensions can use the names to access the designer view model.
*/ */
export enum TableColumnProperty { export enum TableColumnProperty {
AllowNulls = 'allowNulls', AllowNulls = 'allowNulls',
@@ -1103,6 +1105,35 @@ declare module 'azdata' {
Scale = 'scale' Scale = 'scale'
} }
/**
* Name of the common foreign key constraint properties.
* Extensions can use the names to access the designer view model.
*/
export enum TableForeignKeyProperty {
Name = 'name',
PrimaryKeyTable = 'primaryKeyTable',
OnDeleteAction = 'onDeleteAction',
OnUpdateAction = 'onUpdateAction',
Columns = 'columns'
}
/**
* Name of the columns mapping properties for foreign key.
*/
export enum ForeignKeyColumnMappingProperty {
PrimaryKeyColumn = 'primaryKeyColumn',
ForeignKeyColumn = 'foreignKeyColumn'
}
/**
* Name of the common check constraint properties.
* Extensions can use the name to access the designer view model.
*/
export enum TableCheckConstraintProperty {
Name = 'name',
Expression = 'expression'
}
/** /**
* The table designer view definition. * The table designer view definition.
*/ */
@@ -1112,25 +1143,65 @@ declare module 'azdata' {
*/ */
additionalTableProperties?: DesignerDataPropertyInfo[]; additionalTableProperties?: DesignerDataPropertyInfo[];
/** /**
* Additional table column properties.Common table properties are handled by Azure Data Studio. see {@link TableColumnProperty} * Whether to show columns tab. The default value is false.
*/
showColumnsTab?: boolean;
/**
* Additional table column properties. Common table columns properties are handled by Azure Data Studio. see {@link TableColumnProperty}
*/ */
additionalTableColumnProperties?: DesignerDataPropertyInfo[]; additionalTableColumnProperties?: DesignerDataPropertyInfo[];
/**
* Additional tabs.
*/
additionalTabs?: DesignerTab[];
/** /**
* The properties to be displayed in the columns table. Default values are: Name, Type, Length, Precision, Scale, IsPrimaryKey, AllowNulls, DefaultValue. * The properties to be displayed in the columns table. Default values are: Name, Type, Length, Precision, Scale, IsPrimaryKey, AllowNulls, DefaultValue.
*/ */
columnsTableProperties?: string[]; columnsTableProperties?: string[];
/** /**
* Whether user can add columns. The default value is true. * Whether user can add columns. The default value is false.
*/ */
canAddColumns?: boolean; canAddColumns?: boolean;
/** /**
* Whether user can remove columns. The default value is true. * Whether user can remove columns. The default value is false.
*/ */
canRemoveColumns?: boolean; canRemoveColumns?: boolean;
/**
* Whether to show foreign keys tab. The default value is false.
*/
showForeignKeysTab?: boolean;
/**
* Additional foreign key properties. Common foreign key properties are handled by Azure Data Studio. see {@link TableForeignKeyProperty}
*/
additionalForeignKeyProperties?: DesignerDataPropertyInfo[];
/**
* The properties to be displayed in the foreign keys table. Default values are: Name, PrimaryKeyTable.
*/
foreignKeysTableProperties?: string[];
/**
* Whether user can add foreign keys. The default value is false.
*/
canAddForeignKeys?: boolean;
/**
* Whether user can remove foreign keys. The default value is false.
*/
canRemoveForeignKeys?: boolean;
/**
* Whether to show check constraints tab. The default value is false.
*/
showCheckConstraintsTab?: boolean;
/**
* Additional check constraint properties. Common check constraint properties are handled by Azure Data Studio. see {@link TableCheckConstraintProperty}
*/
additionalCheckConstraintProperties?: DesignerDataPropertyInfo[];
/**
* Whether user can add check constraints keys. The default value is false.
*/
canAddCheckConstraints?: boolean;
/**
* Whether user can remove check constraints. The default value is false.
*/
canRemoveCheckConstraints?: boolean;
/**
* Additional tabs.
*/
additionalTabs?: DesignerTab[];
} }
/** /**

View File

@@ -572,6 +572,9 @@ export function createAdsApiFactory(accessor: ServicesAccessor): IAdsExtensionAp
const designers: typeof azdata.designers = { const designers: typeof azdata.designers = {
TableProperty: sqlExtHostTypes.designers.TableProperty, TableProperty: sqlExtHostTypes.designers.TableProperty,
TableColumnProperty: sqlExtHostTypes.designers.TableColumnProperty, TableColumnProperty: sqlExtHostTypes.designers.TableColumnProperty,
TableForeignKeyProperty: sqlExtHostTypes.designers.TableForeignKeyProperty,
ForeignKeyColumnMappingProperty: sqlExtHostTypes.designers.ForeignKeyColumnMappingProperty,
TableCheckConstraintProperty: sqlExtHostTypes.designers.TableCheckConstraintProperty,
DesignerEditType: sqlExtHostTypes.designers.DesignerEditType, DesignerEditType: sqlExtHostTypes.designers.DesignerEditType,
openTableDesigner(providerId, tableInfo: azdata.designers.TableInfo): Promise<void> { openTableDesigner(providerId, tableInfo: azdata.designers.TableInfo): Promise<void> {
return extHostDataProvider.$openTableDesigner(providerId, tableInfo); return extHostDataProvider.$openTableDesigner(providerId, tableInfo);

View File

@@ -913,7 +913,9 @@ export namespace designers {
Name = 'name', Name = 'name',
Description = 'description', Description = 'description',
Columns = 'columns', Columns = 'columns',
Script = 'script' Script = 'script',
ForeignKeys = 'foreignKeys',
CheckConstraints = 'checkConstraints',
} }
export enum TableColumnProperty { export enum TableColumnProperty {
@@ -927,6 +929,24 @@ export namespace designers {
Scale = 'scale' Scale = 'scale'
} }
export enum TableForeignKeyProperty {
Name = 'name',
PrimaryKeyTable = 'primaryKeyTable',
OnDeleteAction = 'onDeleteAction',
OnUpdateAction = 'onUpdateAction',
Columns = 'columns'
}
export enum ForeignKeyColumnMappingProperty {
PrimaryKeyColumn = 'primaryKeyColumn',
ForeignKeyColumn = 'foreignKeyColumn'
}
export enum TableCheckConstraintProperty {
Name = 'name',
Expression = 'expression'
}
export enum DesignerEditType { export enum DesignerEditType {
Add = 0, Add = 0,
Remove = 1, Remove = 1,

View File

@@ -98,7 +98,7 @@ export class Designer extends Disposable implements IThemable {
}); });
}, },
optionsGetter: (item, column): string[] => { optionsGetter: (item, column): string[] => {
return item[column.field].options; return item[column.field].values;
}, },
editorStyler: (component) => { editorStyler: (component) => {
this.styleComponent(component); this.styleComponent(component);
@@ -503,6 +503,8 @@ export class Designer extends Disposable implements IThemable {
const groupNames = []; const groupNames = [];
const componentsToCreate = !isMainView ? components.filter(component => component.showInPropertiesView !== false) : components; const componentsToCreate = !isMainView ? components.filter(component => component.showInPropertiesView !== false) : components;
componentsToCreate.forEach(component => { componentsToCreate.forEach(component => {
// Set the default group name if not set (undefined or null).
component.group = component.group || localize('designer.generalGroupName', "General");
if (groupNames.indexOf(component.group) === -1) { if (groupNames.indexOf(component.group) === -1) {
groupNames.push(component.group); groupNames.push(component.group);
} }
@@ -518,7 +520,7 @@ export class Designer extends Disposable implements IThemable {
const groupHeader = container.appendChild(DOM.$('div.full-row.group-header')); const groupHeader = container.appendChild(DOM.$('div.full-row.group-header'));
groupHeaders.push(groupHeader); groupHeaders.push(groupHeader);
this.styleGroupHeader(groupHeader); this.styleGroupHeader(groupHeader);
groupHeader.innerText = group ?? localize('designer.generalGroupName', "General"); groupHeader.innerText = group;
componentsToCreate.forEach(component => { componentsToCreate.forEach(component => {
if (component.group === group) { if (component.group === group) {
uiComponents.push(this.createComponent(container, component, parentPath, componentMap, setWidth, isMainView)); uiComponents.push(this.createComponent(container, component, parentPath, componentMap, setWidth, isMainView));
@@ -565,7 +567,7 @@ export class Designer extends Disposable implements IThemable {
container.appendChild(DOM.$('')).appendChild(DOM.$('span.component-label')).innerText = componentDefinition.componentProperties?.title ?? ''; container.appendChild(DOM.$('')).appendChild(DOM.$('span.component-label')).innerText = componentDefinition.componentProperties?.title ?? '';
const dropdownContainer = container.appendChild(DOM.$('')); const dropdownContainer = container.appendChild(DOM.$(''));
const dropdownProperties = componentDefinition.componentProperties as DropDownProperties; const dropdownProperties = componentDefinition.componentProperties as DropDownProperties;
const dropdown = new SelectBox(dropdownProperties.values as string[], undefined, this._contextViewProvider, undefined); const dropdown = new SelectBox(dropdownProperties.values as string[] || [], undefined, this._contextViewProvider, undefined);
dropdown.render(dropdownContainer); dropdown.render(dropdownContainer);
dropdown.selectElem.style.height = '25px'; dropdown.selectElem.style.height = '25px';
dropdown.onDidSelect((e) => { dropdown.onDidSelect((e) => {
@@ -579,12 +581,10 @@ export class Designer extends Disposable implements IThemable {
component = dropdown; component = dropdown;
break; break;
case 'checkbox': case 'checkbox':
container.appendChild(DOM.$('')); // label container place holder container.appendChild(DOM.$('')).appendChild(DOM.$('span.component-label')).innerText = componentDefinition.componentProperties?.title ?? '';
const checkboxContainer = container.appendChild(DOM.$('')); const checkboxContainer = container.appendChild(DOM.$(''));
const checkboxProperties = componentDefinition.componentProperties as CheckBoxProperties; const checkboxProperties = componentDefinition.componentProperties as CheckBoxProperties;
const checkbox = new Checkbox(checkboxContainer, { const checkbox = new Checkbox(checkboxContainer, { label: '', ariaLabel: checkboxProperties.title });
label: checkboxProperties.title
});
checkbox.onChange((newValue) => { checkbox.onChange((newValue) => {
this.handleEdit({ type: DesignerEditType.Update, path: propertyPath, value: newValue }); this.handleEdit({ type: DesignerEditType.Update, path: propertyPath, value: newValue });
}); });
@@ -600,7 +600,7 @@ export class Designer extends Disposable implements IThemable {
container.appendChild(DOM.$('.full-row')).appendChild(DOM.$('span.component-label')).innerText = componentDefinition.componentProperties?.title ?? ''; container.appendChild(DOM.$('.full-row')).appendChild(DOM.$('span.component-label')).innerText = componentDefinition.componentProperties?.title ?? '';
} }
const tableProperties = componentDefinition.componentProperties as DesignerTableProperties; const tableProperties = componentDefinition.componentProperties as DesignerTableProperties;
if (tableProperties.canAddRows !== false) { if (tableProperties.canAddRows) {
const buttonContainer = container.appendChild(DOM.$('.full-row')).appendChild(DOM.$('.add-row-button-container')); const buttonContainer = container.appendChild(DOM.$('.full-row')).appendChild(DOM.$('.add-row-button-container'));
const addNewText = localize('designer.newRowText', "Add New"); const addNewText = localize('designer.newRowText', "Add New");
const addRowButton = new Button(buttonContainer, { const addRowButton = new Button(buttonContainer, {
@@ -673,7 +673,7 @@ export class Designer extends Disposable implements IThemable {
}; };
} }
}); });
if (tableProperties.canRemoveRows !== false) { if (tableProperties.canRemoveRows) {
const deleteRowColumn = new ButtonColumn({ const deleteRowColumn = new ButtonColumn({
id: 'deleteRow', id: 'deleteRow',
iconCssClass: Codicon.trash.classNames, iconCssClass: Codicon.trash.classNames,

View File

@@ -49,13 +49,12 @@ export class DesignerPropertiesPane {
} }
public updateDescription(definition: DesignerDataPropertyInfo) { public updateDescription(definition: DesignerDataPropertyInfo) {
const title: string = definition.componentProperties.title; this._descriptionContainer.style.display = 'block';
const description: string = definition.description; const title: string = definition.componentProperties.title ?? '';
if (title && description) { const description: string = definition.description ?? '';
this._descriptionTitleContainer.innerText = title; this._descriptionTitleContainer.innerText = title;
this._descriptionTextContainer.innerText = description; this._descriptionTextContainer.innerText = description;
} }
}
public clear(): void { public clear(): void {
this._componentMap.forEach((value) => { this._componentMap.forEach((value) => {
@@ -89,5 +88,6 @@ export class DesignerPropertiesPane {
this._componentMap.forEach((value) => { this._componentMap.forEach((value) => {
this._setComponentValue(value.defintion, value.component, item.viewModel); this._setComponentValue(value.defintion, value.component, item.viewModel);
}); });
this._descriptionContainer.style.display = 'none';
} }
} }

View File

@@ -79,7 +79,6 @@
.designer-component .add-row-button-container { .designer-component .add-row-button-container {
display: flex; display: flex;
flex-flow: row-reverse;
} }
.designer-component .add-row-button-container .codicon.add-row-button { .designer-component .add-row-button-container .codicon.add-row-button {

View File

@@ -10,7 +10,6 @@ import { localize } from 'vs/nls';
import { designers } from 'sql/workbench/api/common/sqlExtHostTypes'; import { designers } from 'sql/workbench/api/common/sqlExtHostTypes';
import { Emitter, Event } from 'vs/base/common/event'; import { Emitter, Event } from 'vs/base/common/event';
import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; import { INotificationService, Severity } from 'vs/platform/notification/common/notification';
import { ColumnPropertyDescriptions, TablePropertyDescriptions } from 'sql/workbench/services/tableDesigner/browser/tableDesignerStrings';
import { deepClone, equals } from 'vs/base/common/objects'; import { deepClone, equals } from 'vs/base/common/objects';
export class TableDesignerComponentInput implements DesignerComponentInput { export class TableDesignerComponentInput implements DesignerComponentInput {
@@ -146,11 +145,46 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
this._originalViewModel = deepClone(this._viewModel); this._originalViewModel = deepClone(this._viewModel);
this.setDefaultData(); this.setDefaultData();
const tabs = [];
if (designerInfo.view.showColumnsTab) {
tabs.push(this.getColumnsTab(designerInfo));
}
if (designerInfo.view.showForeignKeysTab) {
tabs.push(this.getForeignKeysTab(designerInfo));
}
if (designerInfo.view.showCheckConstraintsTab) {
tabs.push(this.getCheckConstraintsTab(designerInfo));
}
if (designerInfo.view.additionalTabs) {
tabs.push(...designerInfo.view.additionalTabs);
}
tabs.push(this.getGeneralTab(designerInfo));
this._view = {
components: [{
componentType: 'input',
propertyName: designers.TableColumnProperty.Name,
description: localize('designer.table.description.name', "The name of the table object."),
componentProperties: {
title: localize('tableDesigner.nameTitle', "Table name"),
width: 200
}
}],
tabs: tabs
};
}
private getGeneralTab(designerInfo: azdata.designers.TableDesignerInfo): DesignerTab {
const generalTabComponents: DesignerDataPropertyInfo[] = [ const generalTabComponents: DesignerDataPropertyInfo[] = [
{ {
componentType: 'dropdown', componentType: 'dropdown',
propertyName: designers.TableProperty.Schema, propertyName: designers.TableProperty.Schema,
description: TablePropertyDescriptions.SCHEMA, description: localize('designer.table.description.schema', "The schema that contains the table."),
componentProperties: <DropDownProperties>{ componentProperties: <DropDownProperties>{
title: localize('tableDesigner.schemaTitle', "Schema"), title: localize('tableDesigner.schemaTitle', "Schema"),
values: designerInfo.schemas values: designerInfo.schemas
@@ -158,7 +192,7 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
}, { }, {
componentType: 'input', componentType: 'input',
propertyName: designers.TableProperty.Description, propertyName: designers.TableProperty.Description,
description: TablePropertyDescriptions.DESCRIPTION, description: localize('designer.table.description.description', "Description for the table."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.descriptionTitle', "Description") title: localize('tableDesigner.descriptionTitle', "Description")
} }
@@ -169,16 +203,19 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
generalTabComponents.push(...designerInfo.view.additionalTableProperties); generalTabComponents.push(...designerInfo.view.additionalTableProperties);
} }
const generalTab = <DesignerTab>{ return <DesignerTab>{
title: localize('tableDesigner.generalTab', "General"), title: localize('tableDesigner.generalTab', "General"),
components: generalTabComponents components: generalTabComponents
}; };
}
private getColumnsTab(designerInfo: azdata.designers.TableDesignerInfo): DesignerTab {
const columnProperties: DesignerDataPropertyInfo[] = [ const columnProperties: DesignerDataPropertyInfo[] = [
{ {
componentType: 'input', componentType: 'input',
propertyName: designers.TableColumnProperty.Name, propertyName: designers.TableColumnProperty.Name,
description: ColumnPropertyDescriptions.NAME, description: localize('designer.column.description.name', "The name of the column object."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnNameTitle', "Name"), title: localize('tableDesigner.columnNameTitle', "Name"),
width: 150 width: 150
@@ -186,7 +223,7 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
}, { }, {
componentType: 'dropdown', componentType: 'dropdown',
propertyName: designers.TableColumnProperty.Type, propertyName: designers.TableColumnProperty.Type,
description: ColumnPropertyDescriptions.DATA_TYPE, description: localize('designer.column.description.dataType', "Displays the data type name for the column"),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnTypeTitle', "Type"), title: localize('tableDesigner.columnTypeTitle', "Type"),
width: 100, width: 100,
@@ -195,7 +232,7 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
}, { }, {
componentType: 'input', componentType: 'input',
propertyName: designers.TableColumnProperty.Length, propertyName: designers.TableColumnProperty.Length,
description: ColumnPropertyDescriptions.LENGTH, description: localize('designer.column.description.length', "The maximum length (in characters) that can be stored in this database object."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnLengthTitle', "Length"), title: localize('tableDesigner.columnLengthTitle', "Length"),
width: 60 width: 60
@@ -203,7 +240,7 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
}, { }, {
componentType: 'input', componentType: 'input',
propertyName: designers.TableColumnProperty.DefaultValue, propertyName: designers.TableColumnProperty.DefaultValue,
description: ColumnPropertyDescriptions.DEFAULT_VALUE_OR_BINDING, description: localize('designer.column.description.defaultValueBinding', "A predefined global default value for the column or binding."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnDefaultValueTitle', "Default Value"), title: localize('tableDesigner.columnDefaultValueTitle', "Default Value"),
width: 150 width: 150
@@ -211,21 +248,21 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
}, { }, {
componentType: 'checkbox', componentType: 'checkbox',
propertyName: designers.TableColumnProperty.AllowNulls, propertyName: designers.TableColumnProperty.AllowNulls,
description: ColumnPropertyDescriptions.ALLOW_NULLS, description: localize('designer.column.description.allowNulls', "Specifies whether the column may have a NULL value."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnAllowNullTitle', "Allow Nulls"), title: localize('tableDesigner.columnAllowNullTitle', "Allow Nulls"),
} }
}, { }, {
componentType: 'checkbox', componentType: 'checkbox',
propertyName: designers.TableColumnProperty.IsPrimaryKey, propertyName: designers.TableColumnProperty.IsPrimaryKey,
description: ColumnPropertyDescriptions.PRIMARY_KEY, description: localize('designer.column.description.primaryKey', "Specifies whether the column is included in the primary key for the table."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnIsPrimaryKeyTitle', "Primary Key"), title: localize('tableDesigner.columnIsPrimaryKeyTitle', "Primary Key"),
} }
}, { }, {
componentType: 'input', componentType: 'input',
propertyName: designers.TableColumnProperty.Precision, propertyName: designers.TableColumnProperty.Precision,
description: ColumnPropertyDescriptions.PRECISION, description: localize('designer.column.description.precision', "For numeric data, the maximum number of decimal digits that can be stored in this database object."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnPrecisionTitle', "Precision"), title: localize('tableDesigner.columnPrecisionTitle', "Precision"),
width: 60 width: 60
@@ -233,7 +270,7 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
}, { }, {
componentType: 'input', componentType: 'input',
propertyName: designers.TableColumnProperty.Scale, propertyName: designers.TableColumnProperty.Scale,
description: ColumnPropertyDescriptions.NAME, description: localize('designer.column.description.scale', "For numeric data, the maximum number of decimal digits that can be stored in this database object to the right of decimal point."),
componentProperties: { componentProperties: {
title: localize('tableDesigner.columnScaleTitle', "Scale"), title: localize('tableDesigner.columnScaleTitle', "Scale"),
width: 60 width: 60
@@ -256,7 +293,7 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
designers.TableColumnProperty.DefaultValue, designers.TableColumnProperty.DefaultValue,
]; ];
const columnsTab = <DesignerTab>{ return <DesignerTab>{
title: localize('tableDesigner.columnsTabTitle', "Columns"), title: localize('tableDesigner.columnsTabTitle', "Columns"),
components: [ components: [
{ {
@@ -274,26 +311,154 @@ export class TableDesignerComponentInput implements DesignerComponentInput {
} }
] ]
}; };
const tabs = [columnsTab, generalTab];
if (designerInfo.view.additionalTabs) {
tabs.push(...tabs);
} }
this._view = { private getForeignKeysTab(designerInfo: azdata.designers.TableDesignerInfo): DesignerTab {
components: [{
componentType: 'input', const foreignKeyColumnMappingProperties: DesignerDataPropertyInfo[] = [
propertyName: designers.TableColumnProperty.Name, {
description: TablePropertyDescriptions.NAME, componentType: 'dropdown',
propertyName: designers.ForeignKeyColumnMappingProperty.ForeignKeyColumn,
componentProperties: { componentProperties: {
title: localize('tableDesigner.nameTitle', "Table name"), title: localize('tableDesigner.foreignKeyColumn', "Foreign Key Column"),
width: 150
}
},
{
componentType: 'dropdown',
propertyName: designers.ForeignKeyColumnMappingProperty.PrimaryKeyColumn,
componentProperties: {
title: localize('tableDesigner.primaryKeyColumn', "Primary Key Column"),
width: 150
}
},
];
const foreignKeyProperties: DesignerDataPropertyInfo[] = [
{
componentType: 'input',
propertyName: designers.TableForeignKeyProperty.Name,
description: localize('designer.foreignkey.description.name', "The name of the foreign key."),
componentProperties: {
title: localize('tableDesigner.foreignKeyNameTitle', "Name"),
width: 300
}
},
{
componentType: 'dropdown',
propertyName: designers.TableForeignKeyProperty.PrimaryKeyTable,
description: localize('designer.foreignkey.description.primaryKeyTable', "The table which contains the primary or unique key column."),
componentProperties: {
title: localize('tableDesigner.PrimaryKeyTableName', "Primary Key Table"),
width: 200 width: 200
} }
}], },
tabs: tabs {
componentType: 'dropdown',
propertyName: designers.TableForeignKeyProperty.OnUpdateAction,
description: localize('designer.foreignkey.description.onUpdateAction', "The behavior when a user tries to update a row with data that is involved in a foreign key relationship."),
componentProperties: {
title: localize('tableDesigner.foreignKeyOnUpdateAction', "On Update Action"),
width: 100
}
},
{
componentType: 'dropdown',
propertyName: designers.TableForeignKeyProperty.OnDeleteAction,
description: localize('designer.foreignkey.description.onDeleteAction', "The behavior when a user tries to delete a row with data that is involved in a foreign key relationship."),
componentProperties: {
title: localize('tableDesigner.foreignKeyOnDeleteAction', "On Delete Action"),
width: 100
}
},
{
componentType: 'table',
propertyName: designers.TableForeignKeyProperty.Columns,
group: localize('tableDesigner.foreignKeyColumns', "Column Mapping"),
componentProperties: <DesignerTableProperties>{
ariaLabel: localize('tableDesigner.foreignKeyColumns', "Column Mapping"),
columns: [designers.ForeignKeyColumnMappingProperty.ForeignKeyColumn, designers.ForeignKeyColumnMappingProperty.PrimaryKeyColumn],
itemProperties: foreignKeyColumnMappingProperties,
objectTypeDisplayName: '',
canAddRows: designerInfo.view.canAddForeignKeys,
canRemoveRows: designerInfo.view.canRemoveColumns,
}
},
];
if (designerInfo.view.additionalForeignKeyProperties) {
foreignKeyProperties.push(...designerInfo.view.additionalForeignKeyProperties);
}
const foreignKeysTableProperties = designerInfo.view.foreignKeysTableProperties?.length > 0 ? designerInfo.view.foreignKeysTableProperties : [
designers.TableForeignKeyProperty.Name,
designers.TableForeignKeyProperty.PrimaryKeyTable,
];
return <DesignerTab>{
title: localize('tableDesigner.foreignKeysTabTitle', "Foreign Keys"),
components: [
{
componentType: 'table',
propertyName: designers.TableProperty.ForeignKeys,
showInPropertiesView: false,
componentProperties: <DesignerTableProperties>{
ariaLabel: localize('tableDesigner.foreignKeysTabTitle', "Foreign Keys"),
columns: foreignKeysTableProperties,
itemProperties: foreignKeyProperties,
objectTypeDisplayName: localize('tableDesigner.ForeignKeyTypeName', "Foreign Key"),
canAddRows: designerInfo.view.canAddForeignKeys,
canRemoveRows: designerInfo.view.canRemoveForeignKeys
}
}
]
}; };
} }
private getCheckConstraintsTab(designerInfo: azdata.designers.TableDesignerInfo): DesignerTab {
const checkConstraintProperties: DesignerDataPropertyInfo[] = [
{
componentType: 'input',
propertyName: designers.TableCheckConstraintProperty.Name,
description: localize('designer.checkConstraint.description.name', "The name of the check constraint."),
componentProperties: {
title: localize('tableDesigner.checkConstraintNameTitle', "Name"),
width: 200
}
}, {
componentType: 'input',
propertyName: designers.TableCheckConstraintProperty.Expression,
description: localize('designer.checkConstraint.description.expression', "The expression defining the check constraint."),
componentProperties: {
title: localize('tableDesigner.checkConstraintExpressionTitle', "Expression"),
width: 300
}
}
];
if (designerInfo.view.additionalCheckConstraintProperties) {
checkConstraintProperties.push(...designerInfo.view.additionalCheckConstraintProperties);
}
return <DesignerTab>{
title: localize('tableDesigner.checkConstraintsTabTitle', "Check Constraints"),
components: [
{
componentType: 'table',
propertyName: designers.TableProperty.CheckConstraints,
showInPropertiesView: false,
componentProperties: <DesignerTableProperties>{
ariaLabel: localize('tableDesigner.checkConstraintsTabTitle', "Check Constraints"),
columns: [designers.TableCheckConstraintProperty.Name, designers.TableCheckConstraintProperty.Expression],
itemProperties: checkConstraintProperties,
objectTypeDisplayName: localize('tableDesigner.checkConstraintTypeName', "Check Constraint"),
canAddRows: designerInfo.view.canAddCheckConstraints,
canRemoveRows: designerInfo.view.canRemoveCheckConstraints
}
}
]
};
}
private setDefaultData(): void { private setDefaultData(): void {
const properties = Object.keys(this._viewModel); const properties = Object.keys(this._viewModel);
this.setDefaultInputData(properties, designers.TableProperty.Name); this.setDefaultInputData(properties, designers.TableProperty.Name);

View File

@@ -1,23 +0,0 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { localize } from 'vs/nls';
export const TablePropertyDescriptions = {
NAME: localize('designer.table.description.name', "The name of the table object."),
DESCRIPTION: localize('designer.table.description.description', "Description for the table."),
SCHEMA: localize('designer.table.description.schema', "The schema that contains the table.")
};
export const ColumnPropertyDescriptions = {
NAME: localize('designer.column.description.name', "The name of the column object."),
ALLOW_NULLS: localize('designer.column.description.allowNulls', "Specifies whether the column may have a NULL value."),
DATA_TYPE: localize('designer.column.description.dataType', "Displays the data type name for the column"),
DEFAULT_VALUE_OR_BINDING: localize('designer.column.description.defaultValueBinding', "A predefined global default value for the column or binding."),
DESCRIPTION: localize('designer.column.description.description', "Description for the column."),
LENGTH: localize('designer.column.description.length', "The maximum length (in characters) that can be stored in this database object."),
PRECISION: localize('designer.column.description.precision', "For numeric data, the maximum number of decimal digits that can be stored in this database object."),
PRIMARY_KEY: localize('designer.column.description.primaryKey', "Specifies whether the column is included in the primary key for the table.")
};