mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
parent
e01008413e
commit
2e93abd6a9
@ -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 => {
|
||||
|
@ -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;
|
@ -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 */
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user