mirror of
https://github.com/Fabio286/antares.git
synced 2025-06-05 21:59:22 +02:00
feat: DDL query in table settings for MySQL and PostgreSQL, closes #581
This commit is contained in:
@ -31,11 +31,12 @@ export const defaults: Customizations = {
|
|||||||
routines: false,
|
routines: false,
|
||||||
functions: false,
|
functions: false,
|
||||||
schedulers: false,
|
schedulers: false,
|
||||||
// Settings
|
// Misc
|
||||||
elementsWrapper: '',
|
elementsWrapper: '',
|
||||||
stringsWrapper: '"',
|
stringsWrapper: '"',
|
||||||
tableAdd: false,
|
tableAdd: false,
|
||||||
tableTruncateDisableFKCheck: false,
|
tableTruncateDisableFKCheck: false,
|
||||||
|
tableDdl: false,
|
||||||
viewAdd: false,
|
viewAdd: false,
|
||||||
triggerAdd: false,
|
triggerAdd: false,
|
||||||
triggerFunctionAdd: false,
|
triggerFunctionAdd: false,
|
||||||
|
@ -44,6 +44,7 @@ export const customizations: Customizations = {
|
|||||||
tableAdd: true,
|
tableAdd: true,
|
||||||
tableTruncateDisableFKCheck: true,
|
tableTruncateDisableFKCheck: true,
|
||||||
tableDuplicate: true,
|
tableDuplicate: true,
|
||||||
|
tableDdl: true,
|
||||||
viewAdd: true,
|
viewAdd: true,
|
||||||
triggerAdd: true,
|
triggerAdd: true,
|
||||||
routineAdd: true,
|
routineAdd: true,
|
||||||
|
@ -35,11 +35,12 @@ export const customizations: Customizations = {
|
|||||||
triggerFunctions: true,
|
triggerFunctions: true,
|
||||||
routines: true,
|
routines: true,
|
||||||
functions: true,
|
functions: true,
|
||||||
// Settings
|
// Misc
|
||||||
elementsWrapper: '"',
|
elementsWrapper: '"',
|
||||||
stringsWrapper: '\'',
|
stringsWrapper: '\'',
|
||||||
tableAdd: true,
|
tableAdd: true,
|
||||||
tableDuplicate: true,
|
tableDuplicate: true,
|
||||||
|
tableDdl: true,
|
||||||
viewAdd: true,
|
viewAdd: true,
|
||||||
triggerAdd: true,
|
triggerAdd: true,
|
||||||
triggerFunctionAdd: true,
|
triggerFunctionAdd: true,
|
||||||
|
@ -30,7 +30,7 @@ export interface Customizations {
|
|||||||
routines?: boolean;
|
routines?: boolean;
|
||||||
functions?: boolean;
|
functions?: boolean;
|
||||||
schedulers?: boolean;
|
schedulers?: boolean;
|
||||||
// Settings
|
// Misc
|
||||||
elementsWrapper: string;
|
elementsWrapper: string;
|
||||||
stringsWrapper: string;
|
stringsWrapper: string;
|
||||||
tableAdd?: boolean;
|
tableAdd?: boolean;
|
||||||
@ -39,6 +39,7 @@ export interface Customizations {
|
|||||||
tableArray?: boolean;
|
tableArray?: boolean;
|
||||||
tableRealCount?: boolean;
|
tableRealCount?: boolean;
|
||||||
tableTruncateDisableFKCheck?: boolean;
|
tableTruncateDisableFKCheck?: boolean;
|
||||||
|
tableDdl?: boolean;
|
||||||
viewAdd?: boolean;
|
viewAdd?: boolean;
|
||||||
viewSettings?: boolean;
|
viewSettings?: boolean;
|
||||||
triggerAdd?: boolean;
|
triggerAdd?: boolean;
|
||||||
|
@ -75,6 +75,17 @@ export default (connections: {[key: string]: antares.Client}) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.handle('get-table-ddl', async (event, params) => {
|
||||||
|
try {
|
||||||
|
const result = await connections[params.uid].getTableDll(params);
|
||||||
|
|
||||||
|
return { status: 'success', response: result };
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
return { status: 'error', response: err.toString() };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
ipcMain.handle('get-key-usage', async (event, params) => {
|
ipcMain.handle('get-key-usage', async (event, params) => {
|
||||||
try {
|
try {
|
||||||
const result = await connections[params.uid].getKeyUsage(params);
|
const result = await connections[params.uid].getKeyUsage(params);
|
||||||
|
@ -174,6 +174,10 @@ export abstract class AntaresCore {
|
|||||||
throw new Error('Method "dropSchema" not implemented');
|
throw new Error('Method "dropSchema" not implemented');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTableDll (...args: any) {
|
||||||
|
throw new Error('Method "getTableDll" not implemented');
|
||||||
|
}
|
||||||
|
|
||||||
getDatabaseCollation (...args: any) {
|
getDatabaseCollation (...args: any) {
|
||||||
throw new Error('Method "getDatabaseCollation" not implemented');
|
throw new Error('Method "getDatabaseCollation" not implemented');
|
||||||
}
|
}
|
||||||
|
@ -701,6 +701,17 @@ export class MySQLClient extends AntaresCore {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getTableDll ({ schema, table }: { schema: string; table: string }) {
|
||||||
|
const { rows } = await this.raw<antares.QueryResult<{
|
||||||
|
'Create Table'?: string;
|
||||||
|
Table: string;
|
||||||
|
}>>(`SHOW CREATE TABLE \`${schema}\`.\`${table}\``);
|
||||||
|
|
||||||
|
if (rows.length)
|
||||||
|
return rows[0]['Create Table'];
|
||||||
|
else return '';
|
||||||
|
}
|
||||||
|
|
||||||
async getKeyUsage ({ schema, table }: { schema: string; table: string }) {
|
async getKeyUsage ({ schema, table }: { schema: string; table: string }) {
|
||||||
interface KeyResult {
|
interface KeyResult {
|
||||||
TABLE_SCHEMA: string;
|
TABLE_SCHEMA: string;
|
||||||
|
@ -582,6 +582,146 @@ export class PostgreSQLClient extends AntaresCore {
|
|||||||
}, {} as {table: string; schema: string}[]);
|
}, {} as {table: string; schema: string}[]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
|
async getTableDll ({ schema, table }: { schema: string; table: string }) {
|
||||||
|
// const { rows } = await this.raw<antares.QueryResult<{'ddl'?: string}>>(`
|
||||||
|
// SELECT
|
||||||
|
// 'CREATE TABLE ' || relname || E'\n(\n' ||
|
||||||
|
// array_to_string(
|
||||||
|
// array_agg(' ' || column_name || ' ' || type || ' '|| not_null)
|
||||||
|
// , E',\n'
|
||||||
|
// ) || E'\n);\n' AS ddl
|
||||||
|
// FROM (
|
||||||
|
// SELECT
|
||||||
|
// a.attname AS column_name
|
||||||
|
// , pg_catalog.format_type(a.atttypid, a.atttypmod) AS type
|
||||||
|
// , CASE WHEN a.attnotnull THEN 'NOT NULL' ELSE 'NULL' END AS not_null
|
||||||
|
// , c.relname
|
||||||
|
// FROM pg_attribute a, pg_class c, pg_type t
|
||||||
|
// WHERE a.attnum > 0
|
||||||
|
// AND a.attrelid = c.oid
|
||||||
|
// AND a.atttypid = t.oid
|
||||||
|
// AND c.relname = '${table}'
|
||||||
|
// ORDER BY a.attnum
|
||||||
|
// ) AS tabledefinition
|
||||||
|
// GROUP BY relname
|
||||||
|
// `);
|
||||||
|
|
||||||
|
// if (rows.length)
|
||||||
|
// return rows[0].ddl;
|
||||||
|
// else return '';
|
||||||
|
|
||||||
|
/* eslint-disable camelcase */
|
||||||
|
interface SequenceRecord {
|
||||||
|
sequence_catalog: string;
|
||||||
|
sequence_schema: string;
|
||||||
|
sequence_name: string;
|
||||||
|
data_type: string;
|
||||||
|
numeric_precision: number;
|
||||||
|
numeric_precision_radix: number;
|
||||||
|
numeric_scale: number;
|
||||||
|
start_value: string;
|
||||||
|
minimum_value: string;
|
||||||
|
maximum_value: string;
|
||||||
|
increment: string;
|
||||||
|
cycle_option: string;
|
||||||
|
}
|
||||||
|
/* eslint-enable camelcase */
|
||||||
|
|
||||||
|
let createSql = '';
|
||||||
|
const sequences = [];
|
||||||
|
const columnsSql = [];
|
||||||
|
const arrayTypes: {[key: string]: string} = {
|
||||||
|
_int2: 'smallint',
|
||||||
|
_int4: 'integer',
|
||||||
|
_int8: 'bigint',
|
||||||
|
_float4: 'real',
|
||||||
|
_float8: 'double precision',
|
||||||
|
_char: '"char"',
|
||||||
|
_varchar: 'character varying'
|
||||||
|
};
|
||||||
|
|
||||||
|
// Table columns
|
||||||
|
const { rows } = await this.raw(`
|
||||||
|
SELECT *
|
||||||
|
FROM "information_schema"."columns"
|
||||||
|
WHERE "table_schema" = '${schema}'
|
||||||
|
AND "table_name" = '${table}'
|
||||||
|
ORDER BY "ordinal_position" ASC
|
||||||
|
`, { schema: 'information_schema' });
|
||||||
|
|
||||||
|
if (!rows.length) return '';
|
||||||
|
|
||||||
|
for (const column of rows) {
|
||||||
|
let fieldType = column.data_type;
|
||||||
|
if (fieldType === 'USER-DEFINED') fieldType = `"${schema}".${column.udt_name}`;
|
||||||
|
else if (fieldType === 'ARRAY') {
|
||||||
|
if (Object.keys(arrayTypes).includes(fieldType))
|
||||||
|
fieldType = arrayTypes[column.udt_name] + '[]';
|
||||||
|
else
|
||||||
|
fieldType = column.udt_name.replaceAll('_', '') + '[]';
|
||||||
|
}
|
||||||
|
|
||||||
|
const columnArr = [
|
||||||
|
`"${column.column_name}"`,
|
||||||
|
`${fieldType}${column.character_maximum_length ? `(${column.character_maximum_length})` : ''}`
|
||||||
|
];
|
||||||
|
|
||||||
|
if (column.column_default) {
|
||||||
|
columnArr.push(`DEFAULT ${column.column_default}`);
|
||||||
|
if (column.column_default.includes('nextval')) {
|
||||||
|
const sequenceName = column.column_default.split('\'')[1];
|
||||||
|
sequences.push(sequenceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (column.is_nullable === 'NO') columnArr.push('NOT NULL');
|
||||||
|
|
||||||
|
columnsSql.push(columnArr.join(' '));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table sequences
|
||||||
|
for (let sequence of sequences) {
|
||||||
|
if (sequence.includes('.')) sequence = sequence.split('.')[1];
|
||||||
|
|
||||||
|
const { rows } = await this.select('*')
|
||||||
|
.schema('information_schema')
|
||||||
|
.from('sequences')
|
||||||
|
.where({ sequence_schema: `= '${schema}'`, sequence_name: `= '${sequence}'` })
|
||||||
|
.run<SequenceRecord>();
|
||||||
|
|
||||||
|
if (rows.length) {
|
||||||
|
createSql += `CREATE SEQUENCE "${schema}"."${sequence}"
|
||||||
|
START WITH ${rows[0].start_value}
|
||||||
|
INCREMENT BY ${rows[0].increment}
|
||||||
|
MINVALUE ${rows[0].minimum_value}
|
||||||
|
MAXVALUE ${rows[0].maximum_value}
|
||||||
|
CACHE 1;\n`;
|
||||||
|
|
||||||
|
// createSql += `\nALTER TABLE "${sequence}" OWNER TO ${this._client._params.user};\n\n`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Table create
|
||||||
|
createSql += `\nCREATE TABLE "${schema}"."${table}"(
|
||||||
|
${columnsSql.join(',\n ')}
|
||||||
|
);\n`;
|
||||||
|
|
||||||
|
// createSql += `\nALTER TABLE "${tableName}" OWNER TO ${this._client._params.user};\n\n`;
|
||||||
|
|
||||||
|
// Table indexes
|
||||||
|
createSql += '\n';
|
||||||
|
const { rows: indexes } = await this.select('*')
|
||||||
|
.schema('pg_catalog')
|
||||||
|
.from('pg_indexes')
|
||||||
|
.where({ schemaname: `= '${schema}'`, tablename: `= '${table}'` })
|
||||||
|
.run<{indexdef: string}>();
|
||||||
|
|
||||||
|
for (const index of indexes)
|
||||||
|
createSql += `${index.indexdef};\n`;
|
||||||
|
|
||||||
|
return createSql;
|
||||||
|
}
|
||||||
|
|
||||||
async getKeyUsage ({ schema, table }: { schema: string; table: string }) {
|
async getKeyUsage ({ schema, table }: { schema: string; table: string }) {
|
||||||
/* eslint-disable camelcase */
|
/* eslint-disable camelcase */
|
||||||
interface KeyResult {
|
interface KeyResult {
|
||||||
|
@ -7,7 +7,7 @@ import MysqlExporter from '../libs/exporters/sql/MysqlExporter';
|
|||||||
import PostgreSQLExporter from '../libs/exporters/sql/PostgreSQLExporter';
|
import PostgreSQLExporter from '../libs/exporters/sql/PostgreSQLExporter';
|
||||||
let exporter: antares.Exporter;
|
let exporter: antares.Exporter;
|
||||||
|
|
||||||
process.on('message', async ({ type, client, tables, options }) => {
|
process.on('message', async ({ type, client, tables, options }: any) => {
|
||||||
if (type === 'init') {
|
if (type === 'init') {
|
||||||
const connection = await ClientsFactory.getClient({
|
const connection = await ClientsFactory.getClient({
|
||||||
client: client.name,
|
client: client.name,
|
||||||
|
@ -44,6 +44,11 @@ watch(() => props.mode, () => {
|
|||||||
editor.session.setMode(`ace/mode/${props.mode}`);
|
editor.session.setMode(`ace/mode/${props.mode}`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
watch(() => props.modelValue, () => {
|
||||||
|
if (editor)
|
||||||
|
editor.session.setValue(props.modelValue);
|
||||||
|
});
|
||||||
|
|
||||||
watch(editorTheme, () => {
|
watch(editorTheme, () => {
|
||||||
if (editor)
|
if (editor)
|
||||||
editor.setTheme(`ace/theme/${editorTheme.value}`);
|
editor.setTheme(`ace/theme/${editorTheme.value}`);
|
||||||
|
@ -43,13 +43,25 @@
|
|||||||
<span>{{ t('word.indexes') }}</span>
|
<span>{{ t('word.indexes') }}</span>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
class="btn btn-dark btn-sm"
|
class="btn btn-dark btn-sm mr-0"
|
||||||
:disabled="isSaving"
|
:disabled="isSaving"
|
||||||
@click="showForeignModal"
|
@click="showForeignModal"
|
||||||
>
|
>
|
||||||
<i class="mdi mdi-24px mdi-key-link mr-1" />
|
<i class="mdi mdi-24px mdi-key-link mr-1" />
|
||||||
<span>{{ t('word.foreignKeys') }}</span>
|
<span>{{ t('word.foreignKeys') }}</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
|
<div class="divider-vert py-3" />
|
||||||
|
|
||||||
|
<button
|
||||||
|
v-if="workspace.customizations.tableDdl"
|
||||||
|
class="btn btn-dark btn-sm"
|
||||||
|
:disabled="isSaving"
|
||||||
|
@click="showDdlModal"
|
||||||
|
>
|
||||||
|
<i class="mdi mdi-24px mdi-code-tags mr-1" />
|
||||||
|
<span>{{ t('word.ddl') }}</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="workspace-query-info">
|
<div class="workspace-query-info">
|
||||||
<div class="d-flex" :title="t('word.schema')">
|
<div class="d-flex" :title="t('word.schema')">
|
||||||
@ -169,6 +181,13 @@
|
|||||||
@hide="hideForeignModal"
|
@hide="hideForeignModal"
|
||||||
@foreigns-update="foreignsUpdate"
|
@foreigns-update="foreignsUpdate"
|
||||||
/>
|
/>
|
||||||
|
<WorkspaceTabPropsTableDdlModal
|
||||||
|
v-if="isDdlModal"
|
||||||
|
:table="table"
|
||||||
|
:schema="schema"
|
||||||
|
:workspace="workspace"
|
||||||
|
@hide="hideDdlModal"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -186,6 +205,7 @@ import BaseSelect from '@/components/BaseSelect.vue';
|
|||||||
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields.vue';
|
import WorkspaceTabPropsTableFields from '@/components/WorkspaceTabPropsTableFields.vue';
|
||||||
import WorkspaceTabPropsTableIndexesModal from '@/components/WorkspaceTabPropsTableIndexesModal.vue';
|
import WorkspaceTabPropsTableIndexesModal from '@/components/WorkspaceTabPropsTableIndexesModal.vue';
|
||||||
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal.vue';
|
import WorkspaceTabPropsTableForeignModal from '@/components/WorkspaceTabPropsTableForeignModal.vue';
|
||||||
|
import WorkspaceTabPropsTableDdlModal from '@/components/WorkspaceTabPropsTableDdlModal.vue';
|
||||||
import { ipcRenderer } from 'electron';
|
import { ipcRenderer } from 'electron';
|
||||||
import { useSettingsStore } from '@/stores/settings';
|
import { useSettingsStore } from '@/stores/settings';
|
||||||
|
|
||||||
@ -221,6 +241,7 @@ const isLoading = ref(false);
|
|||||||
const isSaving = ref(false);
|
const isSaving = ref(false);
|
||||||
const isIndexesModal = ref(false);
|
const isIndexesModal = ref(false);
|
||||||
const isForeignModal = ref(false);
|
const isForeignModal = ref(false);
|
||||||
|
const isDdlModal = ref(false);
|
||||||
const originalFields: Ref<TableField[]> = ref([]);
|
const originalFields: Ref<TableField[]> = ref([]);
|
||||||
const localFields: Ref<TableField[]> = ref([]);
|
const localFields: Ref<TableField[]> = ref([]);
|
||||||
const originalKeyUsage: Ref<TableForeign[]> = ref([]);
|
const originalKeyUsage: Ref<TableForeign[]> = ref([]);
|
||||||
@ -649,6 +670,14 @@ const hideForeignModal = () => {
|
|||||||
isForeignModal.value = false;
|
isForeignModal.value = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const showDdlModal = () => {
|
||||||
|
isDdlModal.value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
const hideDdlModal = () => {
|
||||||
|
isDdlModal.value = false;
|
||||||
|
};
|
||||||
|
|
||||||
const foreignsUpdate = (foreigns: TableForeign[]) => {
|
const foreignsUpdate = (foreigns: TableForeign[]) => {
|
||||||
localKeyUsage.value = foreigns;
|
localKeyUsage.value = foreigns;
|
||||||
};
|
};
|
||||||
|
70
src/renderer/components/WorkspaceTabPropsTableDdlModal.vue
Normal file
70
src/renderer/components/WorkspaceTabPropsTableDdlModal.vue
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
<template>
|
||||||
|
<ConfirmModal
|
||||||
|
:confirm-text="t('word.confirm')"
|
||||||
|
size="large"
|
||||||
|
class="options-modal"
|
||||||
|
:cancel-text="t('word.close')"
|
||||||
|
:hide-footer="true"
|
||||||
|
@hide="$emit('hide')"
|
||||||
|
>
|
||||||
|
<template #header>
|
||||||
|
<div class="d-flex">
|
||||||
|
<i class="mdi mdi-24px mdi-code-tags mr-1" />
|
||||||
|
<span class="cut-text">{{ t('word.ddl') }} "{{ table }}"</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #body>
|
||||||
|
<div class="pb-4">
|
||||||
|
<BaseTextEditor
|
||||||
|
ref="queryEditor"
|
||||||
|
v-model="createDdl"
|
||||||
|
editor-class="textarea-editor"
|
||||||
|
:read-only="true"
|
||||||
|
mode="sql"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</ConfirmModal>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup lang="ts">
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
import { useNotificationsStore } from '@/stores/notifications';
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import Tables from '@/ipc-api/Tables';
|
||||||
|
import ConfirmModal from '@/components/BaseConfirmModal.vue';
|
||||||
|
import BaseTextEditor from '@/components/BaseTextEditor.vue';
|
||||||
|
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
table: String,
|
||||||
|
schema: String,
|
||||||
|
workspace: Object
|
||||||
|
});
|
||||||
|
|
||||||
|
const createDdl = ref('');
|
||||||
|
|
||||||
|
defineEmits(['hide']);
|
||||||
|
|
||||||
|
const { addNotification } = useNotificationsStore();
|
||||||
|
|
||||||
|
onMounted(async () => {
|
||||||
|
try {
|
||||||
|
const { status, response } = await Tables.getTableDll({
|
||||||
|
uid: props.workspace.uid,
|
||||||
|
table: props.table,
|
||||||
|
schema: props.schema
|
||||||
|
});
|
||||||
|
|
||||||
|
if (status === 'success')
|
||||||
|
createDdl.value = response;
|
||||||
|
else
|
||||||
|
addNotification({ status: 'error', message: response });
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
addNotification({ status: 'error', message: err.stack });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
@ -149,7 +149,8 @@ export const enUS = {
|
|||||||
color: 'Color',
|
color: 'Color',
|
||||||
label: 'Label',
|
label: 'Label',
|
||||||
icon: 'Icon',
|
icon: 'Icon',
|
||||||
resultsTable: 'Results table'
|
resultsTable: 'Results table',
|
||||||
|
ddl: 'DDL'
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
appWelcome: 'Welcome to Antares SQL Client!',
|
appWelcome: 'Welcome to Antares SQL Client!',
|
||||||
|
@ -35,6 +35,10 @@ export default class {
|
|||||||
return ipcRenderer.invoke('get-table-indexes', unproxify(params));
|
return ipcRenderer.invoke('get-table-indexes', unproxify(params));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static getTableDll (params: { uid: string; schema: string; table: string }): Promise<IpcResponse<string>> {
|
||||||
|
return ipcRenderer.invoke('get-table-ddl', unproxify(params));
|
||||||
|
}
|
||||||
|
|
||||||
static getKeyUsage (params: { uid: string; schema: string; table: string }): Promise<IpcResponse> {
|
static getKeyUsage (params: { uid: string; schema: string; table: string }): Promise<IpcResponse> {
|
||||||
return ipcRenderer.invoke('get-key-usage', unproxify(params));
|
return ipcRenderer.invoke('get-key-usage', unproxify(params));
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user