display table check constraints in console (close #2898) (#3086)

This commit is contained in:
Rishichandra Wawhal 2019-10-16 21:24:27 +05:30 committed by Rikin Kachhia
parent e01008413e
commit 2e93abd6a9
5 changed files with 204 additions and 40 deletions

View File

@ -197,6 +197,16 @@ export const getTablePermissions = (table, role = null, action = null) => {
return tablePermissions;
};
/*** Table/View Check Constraints utils ***/
export const getTableCheckConstraints = table => {
return table.check_constraints;
};
export const findTableCheckConstraint = (checkConstraints, constraintName) => {
return checkConstraints.find(c => c.constraint_name === constraintName);
};
/*** Function utils ***/
export const getFunctionSchema = pgFunction => {

View File

@ -0,0 +1,67 @@
import React from 'react';
import AceEditor from 'react-ace';
import ExpandableEditor from '../../../Common/Layout/ExpandableEditor/Editor';
import styles from './ModifyTable.scss';
import { removeCheckConstraint } from './ModifyActions';
const CheckConstraints = ({ constraints, dispatch }) => {
// if no constraints are present
if (!constraints.length) {
return 'No check constraints';
}
// map over constraints
return constraints.map((constraint, i) => {
const { constraint_name, check } = constraint;
// constraint name as expanded and collapsed label
const label = () => {
return (
<div>
<b>{constraint_name}</b>
</div>
);
};
// expand button text "View"
const expandButtonText = 'View';
// Check constraint definition in AceEditor for syntax highlighting
const expandedContent = () => {
return (
<AceEditor
mode="sql"
theme="github"
name={constraint_name}
value={check}
minLines={1}
maxLines={100}
width="100%"
showPrintMargin={false}
className={styles.add_mar_top_small}
/>
);
};
// function to remove the check constraint
const removeFunc = () => {
dispatch(removeCheckConstraint(constraint_name));
};
return (
<ExpandableEditor
key={constraint_name}
editorExpanded={expandedContent}
expandedLabel={label}
collapsedLabel={label}
property={`check-constraint-${i}`}
service="modify-table"
expandButtonText={expandButtonText}
removeFunc={removeFunc}
isCollapsable
/>
);
});
};
export default CheckConstraints;

View File

@ -29,6 +29,12 @@ import {
import { isPostgresFunction } from '../utils';
import { sqlEscapeText } from '../../../Common/utils/sqlUtils';
import { getConfirmation } from '../../../Common/utils/jsUtils';
import {
findTable,
generateTableDef,
getTableCheckConstraints,
findTableCheckConstraint,
} from '../../../Common/utils/pgUtils';
import {
fetchColumnCastsQuery,
@ -128,6 +134,61 @@ const resetPrimaryKeys = () => ({
type: RESET_PRIMARY_KEY,
});
export const removeCheckConstraint = constraintName => (dispatch, getState) => {
const confirmMessage = `This will permanently delete the check constraint "${constraintName}" from this table`;
const isOk = getConfirmation(confirmMessage, true, constraintName);
if (!isOk) return;
const { currentTable: tableName, currentSchema } = getState().tables;
const table = findTable(
getState().tables.allSchemas,
generateTableDef(tableName, currentSchema)
);
const constraint = findTableCheckConstraint(
getTableCheckConstraints(table),
constraintName
);
const upQuery = {
type: 'run_sql',
args: {
sql: `alter table "${currentSchema}"."${tableName}" drop constraint "${constraintName}"`,
},
};
const downQuery = {
type: 'run_sql',
args: {
sql: `alter table "${currentSchema}"."${tableName}" add constraint "${constraintName}" ${
constraint.check
};`,
},
};
const migrationName = `drop_check_constraint_${currentSchema}_${tableName}_${constraintName}`;
const requestMsg = 'Deleting check constraint...';
const successMsg = 'Check constraint deleted';
const errorMsg = 'Deleting check constraint failed';
const customOnSuccess = () => {};
const customOnError = err => {
dispatch({ type: UPDATE_MIGRATION_STATUS_ERROR, data: err });
};
makeMigrationCall(
dispatch,
getState,
[upQuery],
[downQuery],
migrationName,
customOnSuccess,
customOnError,
requestMsg,
successMsg,
errorMsg
);
};
const savePrimaryKeys = (tableName, schemaName, constraintName) => {
return (dispatch, getState) => {
dispatch({ type: SAVE_FOREIGN_KEY });
@ -332,14 +393,14 @@ const saveForeignKeys = (index, tableSchema, columns) => {
alter table "${schemaName}"."${tableName}" drop constraint "${generatedConstraintName}",
add constraint "${constraintName}"
foreign key (${Object.keys(oldConstraint.column_mapping)
.map(lc => `"${lc}"`)
.join(', ')})
.map(lc => `"${lc}"`)
.join(', ')})
references "${oldConstraint.ref_table_table_schema}"."${
oldConstraint.ref_table
}"
oldConstraint.ref_table
}"
(${Object.values(oldConstraint.column_mapping)
.map(rc => `"${rc}"`)
.join(', ')})
.map(rc => `"${rc}"`)
.join(', ')})
on update ${pgConfTypes[oldConstraint.on_update]}
on delete ${pgConfTypes[oldConstraint.on_delete]};
`;
@ -597,8 +658,8 @@ const deleteTrigger = (trigger, table) => {
downMigrationSql += `CREATE TRIGGER "${triggerName}"
${trigger.action_timing} ${
trigger.event_manipulation
} ON "${tableSchema}"."${tableName}"
trigger.event_manipulation
} ON "${tableSchema}"."${tableName}"
FOR EACH ${trigger.action_orientation} ${trigger.action_statement};`;
if (trigger.comment) {
@ -1459,24 +1520,24 @@ const saveColumnChangesSql = (colName, column, onSuccess) => {
const schemaChangesUp =
originalColType !== colType
? [
{
type: 'run_sql',
args: {
sql: columnChangesUpQuery,
{
type: 'run_sql',
args: {
sql: columnChangesUpQuery,
},
},
},
]
]
: [];
const schemaChangesDown =
originalColType !== colType
? [
{
type: 'run_sql',
args: {
sql: columnChangesDownQuery,
{
type: 'run_sql',
args: {
sql: columnChangesDownQuery,
},
},
},
]
]
: [];
/* column default up/down migration */

View File

@ -30,10 +30,16 @@ import EnumsSection, {
import ForeignKeyEditor from './ForeignKeyEditor';
import UniqueKeyEditor from './UniqueKeyEditor';
import TriggerEditorList from './TriggerEditorList';
import CheckConstraints from './CheckConstraints';
import styles from './ModifyTable.scss';
import { NotFoundError } from '../../../Error/PageNotFound';
import { getConfirmation } from '../../../Common/utils/jsUtils';
import {
getTableCheckConstraints,
findTable,
generateTableDef,
} from '../../../Common/utils/pgUtils';
class ModifyTable extends React.Component {
componentDidMount() {
@ -50,7 +56,7 @@ class ModifyTable extends React.Component {
render() {
const {
tableName,
allSchemas,
allTables,
dispatch,
migrationMode,
currentSchema,
@ -68,14 +74,17 @@ class ModifyTable extends React.Component {
const dataTypeIndexMap = getAllDataTypeMap(dataTypes);
const tableSchema = allSchemas.find(
t => t.table_name === tableName && t.table_schema === currentSchema
const table = findTable(
allTables,
generateTableDef(tableName, currentSchema)
);
if (!tableSchema) {
if (!table) {
// throw a 404 exception
throw new NotFoundError();
}
const tableComment = tableSchema.comment;
const tableComment = table.comment;
const untrackBtn = (
<Button
@ -105,7 +114,7 @@ class ModifyTable extends React.Component {
const confirmMessage = `This will permanently delete the table "${tableName}" from the database`;
const isOk = getConfirmation(confirmMessage, true, tableName);
if (isOk) {
dispatch(deleteTableSql(tableName, tableSchema));
dispatch(deleteTableSql(tableName, table));
}
}}
data-test="delete-table"
@ -120,12 +129,12 @@ class ModifyTable extends React.Component {
globals.featuresCompatibility[TABLE_ENUMS_SUPPORT];
if (!supportEnums) return null;
const toggleEnum = () => dispatch(toggleTableAsEnum(tableSchema.is_enum));
const toggleEnum = () => dispatch(toggleTableAsEnum(table.is_enum));
return (
<React.Fragment>
<EnumsSection
isEnum={tableSchema.is_enum}
isEnum={table.is_enum}
toggleEnum={toggleEnum}
loading={tableEnum.loading}
/>
@ -134,12 +143,12 @@ class ModifyTable extends React.Component {
);
};
// if (tableSchema.primary_key.columns > 0) {}
// if (table.primary_key.columns > 0) {}
return (
<div className={`${styles.container} container-fluid`}>
<TableHeader
dispatch={dispatch}
table={tableSchema}
table={table}
tabName="modify"
migrationMode={migrationMode}
/>
@ -158,12 +167,12 @@ class ModifyTable extends React.Component {
isTable
dispatch={dispatch}
/>
<EnumTableModifyWarning isEnum={tableSchema.is_enum} />
<EnumTableModifyWarning isEnum={table.is_enum} />
<h4 className={styles.subheading_text}>Columns</h4>
<ColumnEditorList
validTypeCasts={validTypeCasts}
dataTypeIndexMap={dataTypeIndexMap}
tableSchema={tableSchema}
tableSchema={table}
columnEdit={columnEdit}
dispatch={dispatch}
currentSchema={currentSchema}
@ -181,7 +190,7 @@ class ModifyTable extends React.Component {
<hr />
<h4 className={styles.subheading_text}>Primary Key</h4>
<PrimaryKeyEditor
tableSchema={tableSchema}
tableSchema={table}
pkModify={pkModify}
dispatch={dispatch}
currentSchema={currentSchema}
@ -189,9 +198,9 @@ class ModifyTable extends React.Component {
<hr />
<h4 className={styles.subheading_text}>Foreign Keys</h4>
<ForeignKeyEditor
tableSchema={tableSchema}
tableSchema={table}
currentSchema={currentSchema}
allSchemas={allSchemas}
allSchemas={allTables}
schemaList={schemaList}
dispatch={dispatch}
fkModify={fkModify}
@ -199,16 +208,22 @@ class ModifyTable extends React.Component {
<hr />
<h4 className={styles.subheading_text}>Unique Keys</h4>
<UniqueKeyEditor
tableSchema={tableSchema}
tableSchema={table}
currentSchema={currentSchema}
allSchemas={allSchemas}
allSchemas={allTables}
dispatch={dispatch}
uniqueKeys={uniqueKeyModify}
setUniqueKeys={setUniqueKeys}
/>
<hr />
<h4 className={styles.subheading_text}>Triggers</h4>
<TriggerEditorList tableSchema={tableSchema} dispatch={dispatch} />
<TriggerEditorList tableSchema={table} dispatch={dispatch} />
<hr />
<h4 className={styles.subheading_text}>Check Constraints</h4>
<CheckConstraints
constraints={getTableCheckConstraints(table)}
dispatch={dispatch}
/>
<hr />
{getEnumsSection()}
{untrackBtn}
@ -225,7 +240,7 @@ class ModifyTable extends React.Component {
ModifyTable.propTypes = {
tableName: PropTypes.string.isRequired,
currentSchema: PropTypes.string.isRequired,
allSchemas: PropTypes.array.isRequired,
allTables: PropTypes.array.isRequired,
migrationMode: PropTypes.bool.isRequired,
activeEdit: PropTypes.object.isRequired,
fkAdd: PropTypes.object.isRequired,
@ -243,7 +258,7 @@ ModifyTable.propTypes = {
const mapStateToProps = (state, ownProps) => ({
tableName: ownProps.params.table,
allSchemas: state.tables.allSchemas,
allTables: state.tables.allSchemas,
migrationMode: state.main.migrationMode,
serverVersion: state.main.serverVersion,
currentSchema: state.tables.currentSchema,

View File

@ -228,6 +228,14 @@ export const fetchTrackedTableListQuery = options => {
name: 'unique_constraints',
columns: ['*'],
},
{
name: 'check_constraints',
columns: ['*'],
order_by: {
column: 'constraint_name',
type: 'asc'
}
}
],
order_by: [{ column: 'table_name', type: 'asc' }],
},
@ -481,6 +489,7 @@ export const mergeLoadSchemaData = (
let _fkConstraints = [];
let _refFkConstraints = [];
let _isEnum = false;
let _checkConstraints = [];
if (_isTableTracked) {
_primaryKey = trackedTableInfo.primary_key;
@ -488,6 +497,7 @@ export const mergeLoadSchemaData = (
_permissions = trackedTableInfo.permissions;
_uniqueConstraints = trackedTableInfo.unique_constraints;
_isEnum = trackedTableInfo.is_enum;
_checkConstraints = trackedTableInfo.check_constraints;
_fkConstraints = fkData.filter(
fk => fk.table_schema === _tableSchema && fk.table_name === _tableName
@ -512,6 +522,7 @@ export const mergeLoadSchemaData = (
relationships: _relationships,
permissions: _permissions,
unique_constraints: _uniqueConstraints,
check_constraints: _checkConstraints,
foreign_key_constraints: _fkConstraints,
opp_foreign_key_constraints: _refFkConstraints,
view_info: _viewInfo,