diff --git a/console/src/components/Common/utils/pgUtils.js b/console/src/components/Common/utils/pgUtils.js index c039c5d248c..ee6847b59c6 100644 --- a/console/src/components/Common/utils/pgUtils.js +++ b/console/src/components/Common/utils/pgUtils.js @@ -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 => { diff --git a/console/src/components/Services/Data/TableModify/CheckConstraints.js b/console/src/components/Services/Data/TableModify/CheckConstraints.js new file mode 100644 index 00000000000..3eeb5e76572 --- /dev/null +++ b/console/src/components/Services/Data/TableModify/CheckConstraints.js @@ -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 ( +
+ {constraint_name} +
+ ); + }; + + // expand button text "View" + const expandButtonText = 'View'; + + // Check constraint definition in AceEditor for syntax highlighting + const expandedContent = () => { + return ( + + ); + }; + + // function to remove the check constraint + const removeFunc = () => { + dispatch(removeCheckConstraint(constraint_name)); + }; + + return ( + + ); + }); +}; + +export default CheckConstraints; diff --git a/console/src/components/Services/Data/TableModify/ModifyActions.js b/console/src/components/Services/Data/TableModify/ModifyActions.js index fd9242bcb93..8507d0b82d1 100644 --- a/console/src/components/Services/Data/TableModify/ModifyActions.js +++ b/console/src/components/Services/Data/TableModify/ModifyActions.js @@ -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 */ diff --git a/console/src/components/Services/Data/TableModify/ModifyTable.js b/console/src/components/Services/Data/TableModify/ModifyTable.js index b51477aa745..0cf622eaf93 100644 --- a/console/src/components/Services/Data/TableModify/ModifyTable.js +++ b/console/src/components/Services/Data/TableModify/ModifyTable.js @@ -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 = (