mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
console: filter out partitions from track table list and display partition info
### Description Resolves #1128 ### Changelist - [x] Removed partitions from list of untracked tables (clean up awaits) - [x] Display table definition at modify table like that of `psql \d+ tableName` - [x] Fix broken console error when reloading console on `Modify` and `Relationships` tab for any other schema than default redirect schema. - [x] Fetch table partition info only at /table/modify ### Screenshots <img width="700" alt="Screenshot 2021-05-04 at 12 57 30" src="https://user-images.githubusercontent.com/9019397/116993856-4c6c2000-acd8-11eb-8a61-cd2b45d6e7ac.png"> ### Changelog - [x] Console Co-authored-by: Vijay Prasanna <11921040+vijayprasanna13@users.noreply.github.com> Co-authored-by: Aleksandra Sikora <9019397+beerose@users.noreply.github.com> GitOrigin-RevId: 3a6e527839daf52af101c2ce1803eefba600d29e
This commit is contained in:
parent
f015234ef6
commit
512c3008b6
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
(Add entries below in the order of: server, console, cli, docs, others)
|
(Add entries below in the order of: server, console, cli, docs, others)
|
||||||
|
|
||||||
|
- console: filter out partitions from track table list and display partition info
|
||||||
|
|
||||||
## v2.0.0-alpha.10
|
## v2.0.0-alpha.10
|
||||||
|
|
||||||
|
@ -1334,6 +1334,10 @@ code {
|
|||||||
font-style: normal;
|
font-style: normal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.fontSizeSm {
|
||||||
|
font-size: 13px !important;
|
||||||
|
}
|
||||||
|
|
||||||
.cursorPointer {
|
.cursorPointer {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
@ -200,6 +200,7 @@ const loadSchema = configOptions => {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
if (dataSource?.checkConstraintsSql) {
|
if (dataSource?.checkConstraintsSql) {
|
||||||
body.args.push(
|
body.args.push(
|
||||||
getRunSqlQuery(
|
getRunSqlQuery(
|
||||||
@ -356,6 +357,7 @@ const fetchDataInit = (source, driver) => (dispatch, getState) => {
|
|||||||
schemaList,
|
schemaList,
|
||||||
});
|
});
|
||||||
let newSchema = '';
|
let newSchema = '';
|
||||||
|
const { locationBeforeTransitions } = getState().routing;
|
||||||
if (schemaList.length) {
|
if (schemaList.length) {
|
||||||
newSchema =
|
newSchema =
|
||||||
dataSource.defaultRedirectSchema &&
|
dataSource.defaultRedirectSchema &&
|
||||||
@ -363,6 +365,10 @@ const fetchDataInit = (source, driver) => (dispatch, getState) => {
|
|||||||
? dataSource.defaultRedirectSchema
|
? dataSource.defaultRedirectSchema
|
||||||
: schemaList.sort(Intl.Collator().compare)[0];
|
: schemaList.sort(Intl.Collator().compare)[0];
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
locationBeforeTransitions &&
|
||||||
|
!locationBeforeTransitions.pathname.includes('tables')
|
||||||
|
)
|
||||||
dispatch({ type: UPDATE_CURRENT_SCHEMA, currentSchema: newSchema });
|
dispatch({ type: UPDATE_CURRENT_SCHEMA, currentSchema: newSchema });
|
||||||
return dispatch(updateSchemaInfo()); // TODO
|
return dispatch(updateSchemaInfo()); // TODO
|
||||||
},
|
},
|
||||||
@ -916,6 +922,52 @@ const fetchColumnTypeInfo = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const fetchPartitionDetails = table => {
|
||||||
|
return (dispatch, getState) => {
|
||||||
|
const url = Endpoints.query;
|
||||||
|
const currState = getState();
|
||||||
|
const { currentDataSource } = currState.tables;
|
||||||
|
const query = getRunSqlQuery(
|
||||||
|
dataSource.getPartitionDetailsSql(table.table_name, table.table_schema),
|
||||||
|
currentDataSource,
|
||||||
|
false,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
const options = {
|
||||||
|
credentials: globalCookiePolicy,
|
||||||
|
method: 'POST',
|
||||||
|
headers: dataHeaders(getState),
|
||||||
|
body: JSON.stringify(query),
|
||||||
|
};
|
||||||
|
return dispatch(requestAction(url, options)).then(
|
||||||
|
data => {
|
||||||
|
try {
|
||||||
|
const partitions = data.result.slice(1).map(row => ({
|
||||||
|
parent_schema: row[0],
|
||||||
|
parent_table: row[1],
|
||||||
|
partition_name: row[2],
|
||||||
|
partition_schema: row[3],
|
||||||
|
partition_def: row[4],
|
||||||
|
partition_key: row[5],
|
||||||
|
}));
|
||||||
|
return partitions;
|
||||||
|
} catch (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
error => {
|
||||||
|
dispatch(
|
||||||
|
showErrorNotification(
|
||||||
|
'Error fetching partition information',
|
||||||
|
null,
|
||||||
|
error
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
/* ******************************************************* */
|
/* ******************************************************* */
|
||||||
const dataReducer = (state = defaultState, action) => {
|
const dataReducer = (state = defaultState, action) => {
|
||||||
// eslint-disable-line no-unused-vars
|
// eslint-disable-line no-unused-vars
|
||||||
@ -1114,4 +1166,5 @@ export {
|
|||||||
fetchAdditionalColumnsInfo,
|
fetchAdditionalColumnsInfo,
|
||||||
SET_FILTER_SCHEMA,
|
SET_FILTER_SCHEMA,
|
||||||
SET_FILTER_TABLES,
|
SET_FILTER_TABLES,
|
||||||
|
fetchPartitionDetails,
|
||||||
};
|
};
|
||||||
|
@ -55,7 +55,8 @@ const trackAllItems = (sql, isMigration, migrationName, source, driver) => (
|
|||||||
|
|
||||||
const objects = parseCreateSQL(sql, driver);
|
const objects = parseCreateSQL(sql, driver);
|
||||||
const changes = [];
|
const changes = [];
|
||||||
objects.forEach(({ type, name, schema }) => {
|
objects.forEach(({ type, name, schema, isPartition }) => {
|
||||||
|
if (isPartition) return;
|
||||||
let req = {};
|
let req = {};
|
||||||
if (type === 'function') {
|
if (type === 'function') {
|
||||||
req = getTrackFunctionQuery(name, schema, source, {}, driver);
|
req = getTrackFunctionQuery(name, schema, source, {}, driver);
|
||||||
|
@ -17,41 +17,25 @@ const getDefaultSchema = driver => {
|
|||||||
if (driver === 'mssql') return 'dbo';
|
if (driver === 'mssql') return 'dbo';
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parses create table|function|view sql
|
||||||
|
* @param {string} sql
|
||||||
|
* @param {typeof currentDriver} [driver=currentDriver]
|
||||||
|
* @return {Array<{type: "table"|"function"|"view", schema: string, table: string, isPartition: boolean}>}
|
||||||
|
*/
|
||||||
export const parseCreateSQL = (sql, driver = currentDriver) => {
|
export const parseCreateSQL = (sql, driver = currentDriver) => {
|
||||||
const _objects = [];
|
const _objects = [];
|
||||||
|
|
||||||
const regExp = services[driver].createSQLRegex;
|
const regExp = services[driver].createSQLRegex;
|
||||||
|
for (const result of sql.matchAll(regExp)) {
|
||||||
const matches = sql.match(new RegExp(regExp, 'gmi'));
|
const { type, schema, table, tableWithSchema, partition } =
|
||||||
if (matches) {
|
result.groups ?? {};
|
||||||
matches.forEach(element => {
|
if (!type || !(table || tableWithSchema)) continue;
|
||||||
const itemMatch = element.match(new RegExp(regExp, 'i'));
|
_objects.push({
|
||||||
|
type: type.toLowerCase(),
|
||||||
if (itemMatch && itemMatch.length === 6) {
|
schema: getSQLValue(schema || getDefaultSchema(driver)),
|
||||||
const _object = {};
|
name: getSQLValue(table || tableWithSchema),
|
||||||
|
isPartition: !!partition,
|
||||||
const type = itemMatch[1];
|
|
||||||
|
|
||||||
// If group 5 is undefined, use group 3 and 4 for schema and table respectively
|
|
||||||
// If group 5 is present, use group 5 for table name using public schema.
|
|
||||||
let name;
|
|
||||||
let schema;
|
|
||||||
if (itemMatch[5]) {
|
|
||||||
name = itemMatch[5];
|
|
||||||
schema = getDefaultSchema(driver);
|
|
||||||
} else {
|
|
||||||
name = itemMatch[4];
|
|
||||||
schema = itemMatch[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
_object.type = type.toLowerCase();
|
|
||||||
_object.name = getSQLValue(name);
|
|
||||||
_object.schema = getSQLValue(schema);
|
|
||||||
|
|
||||||
_objects.push(_object);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return _objects;
|
return _objects;
|
||||||
};
|
};
|
||||||
|
@ -49,6 +49,7 @@ import { RightContainer } from '../../../Common/Layout/RightContainer';
|
|||||||
import { NotSupportedNote } from '../../../Common/NotSupportedNote';
|
import { NotSupportedNote } from '../../../Common/NotSupportedNote';
|
||||||
import ConnectedComputedFields from './ComputedFields';
|
import ConnectedComputedFields from './ComputedFields';
|
||||||
import FeatureDisabled from '../FeatureDisabled';
|
import FeatureDisabled from '../FeatureDisabled';
|
||||||
|
import PartitionInfo from './PartitionInfo';
|
||||||
|
|
||||||
class ModifyTable extends React.Component {
|
class ModifyTable extends React.Component {
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
@ -191,6 +192,7 @@ class ModifyTable extends React.Component {
|
|||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
/>
|
/>
|
||||||
<EnumTableModifyWarning isEnum={table.is_enum} />
|
<EnumTableModifyWarning isEnum={table.is_enum} />
|
||||||
|
|
||||||
<h4 className={styles.subheading_text}>Columns</h4>
|
<h4 className={styles.subheading_text}>Columns</h4>
|
||||||
<ColumnEditorList
|
<ColumnEditorList
|
||||||
validTypeCasts={validTypeCasts}
|
validTypeCasts={validTypeCasts}
|
||||||
@ -269,6 +271,11 @@ class ModifyTable extends React.Component {
|
|||||||
dispatch={dispatch}
|
dispatch={dispatch}
|
||||||
/>
|
/>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
{table.table_type === 'PARTITIONED TABLE' && (
|
||||||
|
<PartitionInfo table={table} dispatch={dispatch} />
|
||||||
|
)}
|
||||||
|
|
||||||
<RootFields tableSchema={table} />
|
<RootFields tableSchema={table} />
|
||||||
<hr />
|
<hr />
|
||||||
{getEnumsSection()}
|
{getEnumsSection()}
|
||||||
|
@ -69,3 +69,27 @@ hr {
|
|||||||
margin-bottom: 15px;
|
margin-bottom: 15px;
|
||||||
// overflow: auto;
|
// overflow: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paddingSm {
|
||||||
|
padding: 10px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partitionLabel {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.partitionDef {
|
||||||
|
padding-left: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.quoteText {
|
||||||
|
color: #960000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.defText {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
|
||||||
|
.paddingTopSm {
|
||||||
|
padding-top: 10px !important;
|
||||||
|
}
|
||||||
|
@ -0,0 +1,92 @@
|
|||||||
|
import React, { useEffect, useState } from 'react';
|
||||||
|
import { Table, Partition } from '../../../../dataSources/types';
|
||||||
|
import { Dispatch } from '../../../../types';
|
||||||
|
import { fetchPartitionDetails } from '../DataActions';
|
||||||
|
import styles from './ModifyTable.scss';
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
table: Table;
|
||||||
|
dispatch: Dispatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
const HighlightedText = ({ value }: { value: string }) => {
|
||||||
|
let insideQuotes = false;
|
||||||
|
return (
|
||||||
|
<span className={styles.defText}>
|
||||||
|
{value.split('').map(k => {
|
||||||
|
let res = <span>{k}</span>;
|
||||||
|
if (k === `'` || k === `"`) {
|
||||||
|
res = <span className={styles.quoteText}>{k}</span>;
|
||||||
|
insideQuotes = !insideQuotes;
|
||||||
|
}
|
||||||
|
if (insideQuotes) {
|
||||||
|
res = <span className={styles.quoteText}>{k}</span>;
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
})}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const PartitionInfo: React.FC<Props> = ({ table, dispatch }) => {
|
||||||
|
const [partitions, setPartitions] = useState<Record<string, Partition[]>>({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
dispatch(fetchPartitionDetails(table)).then((data: Partition[]) => {
|
||||||
|
const partitionsMap = {} as Record<string, Partition[]>;
|
||||||
|
const unqiuePKs = data
|
||||||
|
.map(p => p.partition_key)
|
||||||
|
.filter((elem, index, self) => {
|
||||||
|
return index === self.indexOf(elem);
|
||||||
|
});
|
||||||
|
|
||||||
|
unqiuePKs.forEach(t => {
|
||||||
|
const related = data.filter(x => x.partition_key === t);
|
||||||
|
partitionsMap[t] = related;
|
||||||
|
});
|
||||||
|
|
||||||
|
setPartitions(partitionsMap);
|
||||||
|
});
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{partitions && Object.keys(partitions).length > 0 && (
|
||||||
|
<>
|
||||||
|
<h4 className={styles.subheading_text}>Partitions</h4>
|
||||||
|
{Object.keys(partitions).map(key => (
|
||||||
|
<div>
|
||||||
|
<b>
|
||||||
|
<i
|
||||||
|
className={`fa fa-columns ${styles.partitionLabel}`}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
created_at -{' '}
|
||||||
|
</b>
|
||||||
|
<i>{key}</i>
|
||||||
|
{partitions[key].map(p => {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`${styles.paddingTopSm} ${styles.partitionDef}`}
|
||||||
|
>
|
||||||
|
<b>
|
||||||
|
<i
|
||||||
|
className={`fa fa-table ${styles.partitionLabel}`}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>{' '}
|
||||||
|
{p.partition_name} -{' '}
|
||||||
|
</b>
|
||||||
|
<HighlightedText value={p.partition_def} />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
<hr />
|
||||||
|
</>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PartitionInfo;
|
@ -214,6 +214,7 @@ export const mergeLoadSchemaDataPostgres = (
|
|||||||
>[];
|
>[];
|
||||||
const primaryKeys = JSON.parse(data[2].result[1]) as Table['primary_key'][];
|
const primaryKeys = JSON.parse(data[2].result[1]) as Table['primary_key'][];
|
||||||
const uniqueKeys = JSON.parse(data[3].result[1]) as any;
|
const uniqueKeys = JSON.parse(data[3].result[1]) as any;
|
||||||
|
|
||||||
const checkConstraints = dataSource?.checkConstraintsSql
|
const checkConstraints = dataSource?.checkConstraintsSql
|
||||||
? (JSON.parse(data[4].result[1]) as Table['check_constraints'])
|
? (JSON.parse(data[4].result[1]) as Table['check_constraints'])
|
||||||
: ([] as Table['check_constraints']);
|
: ([] as Table['check_constraints']);
|
||||||
|
@ -315,6 +315,7 @@ export interface DataSourcesAPI {
|
|||||||
aggregationPermissionsAllowed: boolean;
|
aggregationPermissionsAllowed: boolean;
|
||||||
supportedFeatures?: SupportedFeaturesType;
|
supportedFeatures?: SupportedFeaturesType;
|
||||||
defaultRedirectSchema?: string;
|
defaultRedirectSchema?: string;
|
||||||
|
getPartitionDetailsSql?: (tableName: string, tableSchema: string) => string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export let currentDriver: Driver = 'postgres';
|
export let currentDriver: Driver = 'postgres';
|
||||||
|
@ -62,7 +62,7 @@ const operators = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
// eslint-disable-next-line no-useless-escape
|
||||||
const createSQLRegex = /create\s*(?:|or\s*replace)\s*(view|table|function)\s*(?:\s*if*\s*not\s*exists\s*)?((\"?\w+\"?)\.(\"?\w+\"?)|(\"?\w+\"?))/g;
|
const createSQLRegex = /create\s*(?:|or\s*replace)\s*(?<type>view|table|function)\s*(?:\s*if*\s*not\s*exists\s*)?((?<schema>\"?\w+\"?)\.(?<tableWithSchema>\"?\w+\"?)|(?<table>\"?\w+\"?))\s*(?<partition>partition\s*of)?/gim;
|
||||||
|
|
||||||
export const displayTableName = (table: Table) => {
|
export const displayTableName = (table: Table) => {
|
||||||
const tableName = table.table_name;
|
const tableName = table.table_name;
|
||||||
|
@ -72,7 +72,7 @@ const columnDataTypes = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line no-useless-escape
|
// eslint-disable-next-line no-useless-escape
|
||||||
const createSQLRegex = /create\s*(?:|or\s*replace)\s*(view|table|function)\s*(?:\s*if*\s*not\s*exists\s*)?((\"?\w+\"?)\.(\"?\w+\"?)|(\"?\w+\"?))/g;
|
const createSQLRegex = /create\s*(?:|or\s*replace)\s*(?<type>view|table|function)\s*(?:\s*if*\s*not\s*exists\s*)?((?<schema>\"?\w+\"?)\.(?<tableWithSchema>\"?\w+\"?)|(?<table>\"?\w+\"?))\s*(?<partition>partition\s*of)?/gim;
|
||||||
|
|
||||||
export const displayTableName = (table: Table) => {
|
export const displayTableName = (table: Table) => {
|
||||||
const tableName = table.table_name;
|
const tableName = table.table_name;
|
||||||
|
@ -426,7 +426,7 @@ export const isColTypeString = (colType: string) =>
|
|||||||
|
|
||||||
const dependencyErrorCode = '2BP01'; // pg dependent error > https://www.postgresql.org/docs/current/errcodes-appendix.html
|
const dependencyErrorCode = '2BP01'; // pg dependent error > https://www.postgresql.org/docs/current/errcodes-appendix.html
|
||||||
|
|
||||||
const createSQLRegex = /create\s*(?:|or\s*replace)\s*(view|table|function)\s*(?:\s*if*\s*not\s*exists\s*)?((\"?\w+\"?)\.(\"?\w+\"?)|(\"?\w+\"?))/g; // eslint-disable-line
|
const createSQLRegex = /create\s*(?:|or\s*replace)\s*(?<type>view|table|function)\s*(?:\s*if*\s*not\s*exists\s*)?((?<schema>\"?\w+\"?)\.(?<tableWithSchema>\"?\w+\"?)|(?<table>\"?\w+\"?))\s*(?<partition>partition\s*of)?/gim; // eslint-disable-line
|
||||||
|
|
||||||
const isTimeoutError = (error: {
|
const isTimeoutError = (error: {
|
||||||
code: string;
|
code: string;
|
||||||
@ -574,6 +574,23 @@ export const supportedFeatures: SupportedFeaturesType = {
|
|||||||
|
|
||||||
const defaultRedirectSchema = 'public';
|
const defaultRedirectSchema = 'public';
|
||||||
|
|
||||||
|
const getPartitionDetailsSql = (tableName: string, tableSchema: string) => {
|
||||||
|
return `SELECT
|
||||||
|
nmsp_parent.nspname AS parent_schema,
|
||||||
|
parent.relname AS parent_table,
|
||||||
|
child.relname AS partition_name,
|
||||||
|
nmsp_child.nspname AS partition_schema,
|
||||||
|
pg_catalog.pg_get_expr(child.relpartbound, child.oid) AS partition_def,
|
||||||
|
pg_catalog.pg_get_partkeydef(parent.oid) AS partition_key
|
||||||
|
FROM pg_inherits
|
||||||
|
JOIN pg_class parent ON pg_inherits.inhparent = parent.oid
|
||||||
|
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
||||||
|
JOIN pg_namespace nmsp_parent ON nmsp_parent.oid = parent.relnamespace
|
||||||
|
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
|
||||||
|
WHERE nmsp_child.nspname = '${tableSchema}'
|
||||||
|
AND parent.relname = '${tableName}';`;
|
||||||
|
};
|
||||||
|
|
||||||
export const postgres: DataSourcesAPI = {
|
export const postgres: DataSourcesAPI = {
|
||||||
isTable,
|
isTable,
|
||||||
isJsonColumn,
|
isJsonColumn,
|
||||||
@ -649,4 +666,5 @@ export const postgres: DataSourcesAPI = {
|
|||||||
aggregationPermissionsAllowed: true,
|
aggregationPermissionsAllowed: true,
|
||||||
supportedFeatures,
|
supportedFeatures,
|
||||||
defaultRedirectSchema,
|
defaultRedirectSchema,
|
||||||
|
getPartitionDetailsSql,
|
||||||
};
|
};
|
||||||
|
@ -65,6 +65,21 @@ export const getFetchTablesListQuery = (options: {
|
|||||||
SELECT
|
SELECT
|
||||||
COALESCE(Json_agg(Row_to_json(info)), '[]' :: json) AS tables
|
COALESCE(Json_agg(Row_to_json(info)), '[]' :: json) AS tables
|
||||||
FROM (
|
FROM (
|
||||||
|
with partitions as (
|
||||||
|
select array(
|
||||||
|
SELECT
|
||||||
|
child.relname AS partition
|
||||||
|
FROM pg_inherits
|
||||||
|
JOIN pg_class child ON pg_inherits.inhrelid = child.oid
|
||||||
|
JOIN pg_namespace nmsp_child ON nmsp_child.oid = child.relnamespace
|
||||||
|
${generateWhereClause(
|
||||||
|
options,
|
||||||
|
'child.relname',
|
||||||
|
'nmsp_child.nspname',
|
||||||
|
'where'
|
||||||
|
)}
|
||||||
|
) as names
|
||||||
|
)
|
||||||
SELECT
|
SELECT
|
||||||
pgn.nspname as table_schema,
|
pgn.nspname as table_schema,
|
||||||
pgc.relname as table_name,
|
pgc.relname as table_name,
|
||||||
@ -80,7 +95,7 @@ export const getFetchTablesListQuery = (options: {
|
|||||||
COALESCE(json_agg(DISTINCT row_to_json(ist) :: jsonb || jsonb_build_object('comment', obj_description(pgt.oid))) filter (WHERE ist.trigger_name IS NOT NULL), '[]' :: json) AS triggers,
|
COALESCE(json_agg(DISTINCT row_to_json(ist) :: jsonb || jsonb_build_object('comment', obj_description(pgt.oid))) filter (WHERE ist.trigger_name IS NOT NULL), '[]' :: json) AS triggers,
|
||||||
row_to_json(isv) AS view_info
|
row_to_json(isv) AS view_info
|
||||||
|
|
||||||
FROM pg_class as pgc
|
FROM partitions, pg_class as pgc
|
||||||
INNER JOIN pg_namespace as pgn
|
INNER JOIN pg_namespace as pgn
|
||||||
ON pgc.relnamespace = pgn.oid
|
ON pgc.relnamespace = pgn.oid
|
||||||
|
|
||||||
@ -162,6 +177,7 @@ export const getFetchTablesListQuery = (options: {
|
|||||||
|
|
||||||
WHERE
|
WHERE
|
||||||
pgc.relkind IN ('r', 'v', 'f', 'm', 'p')
|
pgc.relkind IN ('r', 'v', 'f', 'm', 'p')
|
||||||
|
and NOT (pgc.relname = ANY (partitions.names))
|
||||||
${whereQuery}
|
${whereQuery}
|
||||||
GROUP BY pgc.oid, pgn.nspname, pgc.relname, table_type, isv.*
|
GROUP BY pgc.oid, pgn.nspname, pgc.relname, table_type, isv.*
|
||||||
) AS info;
|
) AS info;
|
||||||
|
@ -161,6 +161,15 @@ export interface Table extends BaseTable {
|
|||||||
}[];
|
}[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type Partition = {
|
||||||
|
parent_schema: string;
|
||||||
|
partition_schema: string;
|
||||||
|
partition_name: string;
|
||||||
|
parent_table: string;
|
||||||
|
partition_def: string;
|
||||||
|
partition_key: string;
|
||||||
|
};
|
||||||
|
|
||||||
export type ColumnAction = 'add' | 'modify';
|
export type ColumnAction = 'add' | 'modify';
|
||||||
|
|
||||||
export interface FrequentlyUsedColumn {
|
export interface FrequentlyUsedColumn {
|
||||||
|
Loading…
Reference in New Issue
Block a user