mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-10-16 14:50:15 +08:00
Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5cd56acf4f | ||
|
|
dace3afa2d |
+7
@@ -35,6 +35,7 @@ import org.jkiss.dbeaver.model.struct.DBSEntity;
|
||||
import org.jkiss.dbeaver.model.struct.DBSObject;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
public class WebDBDResultSetDataProvider implements DBDResultSetDataProvider, DBSObject {
|
||||
@@ -59,6 +60,12 @@ public class WebDBDResultSetDataProvider implements DBDResultSetDataProvider, DB
|
||||
return contextInfo.getResults(resultsId).getAttributes();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<DBDAttributeBinding> getVisibleAttributes() throws DBException {
|
||||
return Arrays.asList(getAttributes());
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public List<? extends DBDValueRow> getAllRows() {
|
||||
|
||||
@@ -41,6 +41,7 @@ export default [
|
||||
['ui_ignore', 'Ignore'],
|
||||
['ui_unexpected_error', 'Unexpected error'],
|
||||
['ui_error', 'Error'],
|
||||
['ui_unknown_error', 'Unknown Error'],
|
||||
['ui_error_message', 'Error:'],
|
||||
['ui_error_close', 'Close'],
|
||||
['ui_clear', 'Clear'],
|
||||
|
||||
@@ -39,6 +39,7 @@ export default [
|
||||
['ui_ignore', 'Ignorer'],
|
||||
['ui_unexpected_error', 'Erreur inattendue'],
|
||||
['ui_error', 'Erreur'],
|
||||
['ui_unknown_error', 'Erreur inconnue'],
|
||||
['ui_error_message', 'Erreur :'],
|
||||
['ui_error_close', 'Fermer'],
|
||||
['ui_clear', 'Effacer'],
|
||||
|
||||
@@ -38,6 +38,7 @@ export default [
|
||||
['ui_reject', 'Reject'],
|
||||
['ui_ignore', 'Ignore'],
|
||||
['ui_error', 'Errore'],
|
||||
['ui_unknown_error', 'Errore sconosciuto'],
|
||||
['ui_error_message', 'Errore:'],
|
||||
['ui_error_close', 'Chiudi'],
|
||||
['ui_clear', 'Clear'],
|
||||
|
||||
@@ -37,6 +37,7 @@ export default [
|
||||
['ui_reject', 'Отклонить'],
|
||||
['ui_ignore', 'Пропустить'],
|
||||
['ui_error', 'Ошибка'],
|
||||
['ui_unknown_error', 'Неизвестная ошибка'],
|
||||
['ui_error_message', 'Ошибка:'],
|
||||
['ui_error_close', 'Закрыть'],
|
||||
['ui_clear', 'Очистить'],
|
||||
|
||||
@@ -41,6 +41,7 @@ export default [
|
||||
['ui_ignore', 'Bỏ qua'],
|
||||
['ui_unexpected_error', 'Lỗi không mong muốn'],
|
||||
['ui_error', 'Lỗi'],
|
||||
['ui_unknown_error', 'Lỗi không xác định'],
|
||||
['ui_error_message', 'Lỗi:'],
|
||||
['ui_error_close', 'Đóng'],
|
||||
['ui_clear', 'Xóa'],
|
||||
|
||||
@@ -38,6 +38,7 @@ export default [
|
||||
['ui_reject', '拒绝'],
|
||||
['ui_ignore', '忽略'],
|
||||
['ui_error', '错误'],
|
||||
['ui_unknown_error', '未知错误'],
|
||||
['ui_error_message', '错误:'],
|
||||
['ui_error_close', '关闭'],
|
||||
['ui_clear', '清除'],
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
query sqlGenerateResultSetQuery(
|
||||
$projectId: ID
|
||||
$connectionId: ID!
|
||||
$contextId: ID!
|
||||
$generatorId: SQLResultSetGeneratorId!
|
||||
$resultsId: ID!
|
||||
$selectedRows: [SQLResultRow!]!
|
||||
) {
|
||||
sqlGenerateResultSetQuery(
|
||||
projectId: $projectId
|
||||
connectionId: $connectionId
|
||||
contextId: $contextId
|
||||
generatorId: $generatorId
|
||||
resultsId: $resultsId
|
||||
selectedRows: $selectedRows
|
||||
)
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
||||
+2
-1
@@ -1,10 +1,11 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { AdministrationScreenService } from '@cloudbeaver/core-administration';
|
||||
import { ADMIN_USERNAME_MIN_LENGTH, AUTH_PROVIDER_LOCAL_ID, AuthProvidersResource, PasswordPolicyService } from '@cloudbeaver/core-authentication';
|
||||
import { ExecutorInterrupter, type IExecutionContextProvider } from '@cloudbeaver/core-executor';
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -100,7 +100,9 @@ export class DataImportBootstrap extends Bootstrap {
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
const presentation = context.get(DATA_CONTEXT_DV_PRESENTATION);
|
||||
const isContainer = model.source instanceof ContainerDataSource;
|
||||
|
||||
return (
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
!model.isReadonly(resultIndex) &&
|
||||
isContainer &&
|
||||
!this.dataImportService.disabled &&
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
"@cloudbeaver/plugin-data-grid": "workspace:*",
|
||||
"@cloudbeaver/plugin-data-viewer": "workspace:*",
|
||||
"@cloudbeaver/plugin-data-viewer-conditional-formatting": "workspace:*",
|
||||
"@cloudbeaver/plugin-sql-generator": "workspace:*",
|
||||
"@dbeaver/js-helpers": "workspace:*",
|
||||
"@dbeaver/result-set-api": "workspace:*",
|
||||
"@dbeaver/ui-kit": "workspace:*",
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { createAction } from '@cloudbeaver/core-view';
|
||||
|
||||
export const ACTION_DATA_GRID_GENERATE_SQL_DELETE = createAction('data-grid-generate-sql-delete', {
|
||||
label: 'data_grid_table_generate_sql_delete',
|
||||
tooltip: 'data_grid_table_generate_sql_delete_tooltip',
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { createAction } from '@cloudbeaver/core-view';
|
||||
|
||||
export const ACTION_DATA_GRID_GENERATE_SQL_INSERT = createAction('data-grid-generate-sql-insert', {
|
||||
label: 'data_grid_table_generate_sql_insert',
|
||||
tooltip: 'data_grid_table_generate_sql_insert_tooltip',
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { createAction } from '@cloudbeaver/core-view';
|
||||
|
||||
export const ACTION_DATA_GRID_GENERATE_SQL_SELECT = createAction('data-grid-generate-sql-select', {
|
||||
label: 'data_grid_table_generate_sql_select',
|
||||
tooltip: 'data_grid_table_generate_sql_select_tooltip',
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { createAction } from '@cloudbeaver/core-view';
|
||||
|
||||
export const ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY = createAction('data-grid-generate-sql-select-many', {
|
||||
label: 'data_grid_table_generate_sql_select_many',
|
||||
tooltip: 'data_grid_table_generate_sql_select_many_tooltip',
|
||||
});
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { createAction } from '@cloudbeaver/core-view';
|
||||
|
||||
export const ACTION_DATA_GRID_GENERATE_SQL_UPDATE = createAction('data-grid-generate-sql-update', {
|
||||
label: 'data_grid_table_generate_sql_update',
|
||||
tooltip: 'data_grid_table_generate_sql_update_tooltip',
|
||||
});
|
||||
+2
@@ -64,6 +64,7 @@ export class DataGridContextMenuCellEditingService {
|
||||
isApplicable: context => {
|
||||
const model = context.get(DATA_CONTEXT_DV_DDM)!;
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
return isResultSetDataSource(model.source) && !model.isDisabled(resultIndex) && !model.isReadonly(resultIndex);
|
||||
},
|
||||
getItems: (context, items) => [...items, MENU_DATA_GRID_EDITING],
|
||||
@@ -108,6 +109,7 @@ export class DataGridContextMenuCellEditingService {
|
||||
// If we somehow added a new row, we can always edit it
|
||||
const canEdit = editor.getElementState(key) === DatabaseEditChangeType.add;
|
||||
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
if (model.isReadonly(resultIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
+289
@@ -0,0 +1,289 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import { SqlResultSetGeneratorId, type SqlResultRow } from '@cloudbeaver/core-sdk';
|
||||
import { ActionService, MenuService, type IAction, type IActionInfo } from '@cloudbeaver/core-view';
|
||||
import {
|
||||
DATA_CONTEXT_DV_DDM,
|
||||
DATA_CONTEXT_DV_DDM_RESULT_INDEX,
|
||||
DATA_CONTEXT_DV_RESULT_KEY,
|
||||
GridDataKeysUtils,
|
||||
GridSelectAction,
|
||||
GridViewAction,
|
||||
IDatabaseDataFormatAction,
|
||||
IDatabaseDataResult,
|
||||
IDatabaseDataSelectAction,
|
||||
IDatabaseDataSource,
|
||||
isResultSetDataModel,
|
||||
ResultSetDataAction,
|
||||
ResultSetDataContentAction,
|
||||
type IDatabaseDataModel,
|
||||
type IDatabaseValueHolder,
|
||||
type IGridColumnKey,
|
||||
type IGridDataKey,
|
||||
type IGridRowKey,
|
||||
type IResultSetValue,
|
||||
} from '@cloudbeaver/plugin-data-viewer';
|
||||
|
||||
import { ACTION_DATA_GRID_GENERATE_SQL_DELETE } from '../Actions/GenerateSQL/ACTION_DATA_GRID_GENERATE_SQL_DELETE.js';
|
||||
import { ACTION_DATA_GRID_GENERATE_SQL_INSERT } from '../Actions/GenerateSQL/ACTION_DATA_GRID_GENERATE_SQL_INSERT.js';
|
||||
import { ACTION_DATA_GRID_GENERATE_SQL_SELECT } from '../Actions/GenerateSQL/ACTION_DATA_GRID_GENERATE_SQL_SELECT.js';
|
||||
import { ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY } from '../Actions/GenerateSQL/ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY.js';
|
||||
import { ACTION_DATA_GRID_GENERATE_SQL_UPDATE } from '../Actions/GenerateSQL/ACTION_DATA_GRID_GENERATE_SQL_UPDATE.js';
|
||||
import { MENU_DATA_GRID_GENERATE_SQL } from './GenerateSQL/MENU_DATA_GRID_GENERATE_SQL.js';
|
||||
import type { IDataContextProvider } from '@cloudbeaver/core-data-context';
|
||||
import { GeneratedSqlDialog, SqlGeneratorsResource } from '@cloudbeaver/plugin-sql-generator';
|
||||
import { isNotNullDefined } from '@dbeaver/js-helpers';
|
||||
|
||||
@injectable(() => [ActionService, MenuService, CommonDialogService, NotificationService, SqlGeneratorsResource])
|
||||
export class DataGridContextMenuGenerateSqlService {
|
||||
constructor(
|
||||
private readonly actionService: ActionService,
|
||||
private readonly menuService: MenuService,
|
||||
private readonly commonDialogService: CommonDialogService,
|
||||
private readonly notificationService: NotificationService,
|
||||
private readonly sqlGenerationResource: SqlGeneratorsResource,
|
||||
) {}
|
||||
|
||||
register(): void {
|
||||
this.menuService.addCreator({
|
||||
root: true,
|
||||
menus: [],
|
||||
contexts: [DATA_CONTEXT_DV_DDM, DATA_CONTEXT_DV_DDM_RESULT_INDEX, DATA_CONTEXT_DV_RESULT_KEY],
|
||||
isApplicable: context => {
|
||||
const model = context.get(DATA_CONTEXT_DV_DDM);
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
return isResultSetDataModel(model) && !model.isReadonly(resultIndex) && !model.isDisabled(resultIndex);
|
||||
},
|
||||
getItems: (context, items) => [...items, MENU_DATA_GRID_GENERATE_SQL],
|
||||
});
|
||||
|
||||
this.menuService.addCreator({
|
||||
menus: [MENU_DATA_GRID_GENERATE_SQL],
|
||||
getItems: () => [
|
||||
ACTION_DATA_GRID_GENERATE_SQL_INSERT,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_UPDATE,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_DELETE,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_SELECT,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY,
|
||||
],
|
||||
});
|
||||
|
||||
this.actionService.addHandler({
|
||||
id: 'data-grid-generate-sql-handler',
|
||||
menus: [MENU_DATA_GRID_GENERATE_SQL],
|
||||
contexts: [DATA_CONTEXT_DV_DDM, DATA_CONTEXT_DV_DDM_RESULT_INDEX, DATA_CONTEXT_DV_RESULT_KEY],
|
||||
actions: [
|
||||
ACTION_DATA_GRID_GENERATE_SQL_INSERT,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_UPDATE,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_DELETE,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_SELECT,
|
||||
ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY,
|
||||
],
|
||||
isDisabled: context => {
|
||||
const model = context.get(DATA_CONTEXT_DV_DDM)!;
|
||||
|
||||
if (model.isLoading()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return hasLargeObjectValuesInSelectedRows(context);
|
||||
},
|
||||
getActionInfo: (context, action): IActionInfo => {
|
||||
const actionInfo = action.info;
|
||||
|
||||
if (hasLargeObjectValuesInSelectedRows(context)) {
|
||||
return {
|
||||
...actionInfo,
|
||||
tooltip: 'data_grid_table_generate_sql_disabled_lob_tooltip',
|
||||
};
|
||||
}
|
||||
|
||||
return actionInfo;
|
||||
},
|
||||
handler: async (context, action) => {
|
||||
await this.openSqlDialog(context, mapGeneratorIdFromAction(action));
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
private async openSqlDialog(context: IDataContextProvider, generatorId: SqlResultSetGeneratorId): Promise<void> {
|
||||
const model = context.get(DATA_CONTEXT_DV_DDM)!;
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
const key = context.get(DATA_CONTEXT_DV_RESULT_KEY);
|
||||
|
||||
if (!isResultSetDataModel(model)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const select = model.source.tryGetAction(resultIndex, IDatabaseDataSelectAction, GridSelectAction);
|
||||
const projectId = model.source.executionContext?.context?.projectId;
|
||||
const connectionId = model.source.executionContext?.context?.connectionId;
|
||||
const contextId = model.source.executionContext?.context?.id;
|
||||
const resultId = model.source.getResult(resultIndex)?.id;
|
||||
const selectedElements = select?.getSelectedElements() || [];
|
||||
const rows = getSqlResultRows(model, resultIndex, selectedElements, key);
|
||||
|
||||
if (rows.length === 0) {
|
||||
this.notificationService.logError({
|
||||
title: 'data_grid_table_generate_sql_error_title',
|
||||
message: 'data_grid_table_generate_sql_error_no_rows',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isNotNullDefined(projectId) || !isNotNullDefined(connectionId) || !isNotNullDefined(contextId) || !isNotNullDefined(resultId)) {
|
||||
this.notificationService.logError({
|
||||
title: 'data_grid_table_generate_sql_error_title',
|
||||
message: 'data_grid_table_generate_sql_error_no_connection',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const query = await this.sqlGenerationResource.generateResultSetSql({
|
||||
projectId,
|
||||
connectionId,
|
||||
contextId,
|
||||
resultsId: resultId,
|
||||
generatorId,
|
||||
selectedRows: rows,
|
||||
});
|
||||
|
||||
if (!query) {
|
||||
this.notificationService.logError({
|
||||
title: 'data_grid_table_generate_sql_error_title',
|
||||
message: 'data_grid_table_generate_sql_error_no_query',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
await this.commonDialogService.open(GeneratedSqlDialog, {
|
||||
query,
|
||||
nodeId: connectionId,
|
||||
});
|
||||
} catch (e: any) {
|
||||
this.notificationService.logException(e, 'data_grid_table_generate_sql_error_title');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function mapGeneratorIdFromAction(action: IAction): SqlResultSetGeneratorId {
|
||||
switch (action) {
|
||||
case ACTION_DATA_GRID_GENERATE_SQL_INSERT:
|
||||
return SqlResultSetGeneratorId.DataInsert;
|
||||
case ACTION_DATA_GRID_GENERATE_SQL_UPDATE:
|
||||
return SqlResultSetGeneratorId.DataUpdate;
|
||||
case ACTION_DATA_GRID_GENERATE_SQL_DELETE:
|
||||
return SqlResultSetGeneratorId.DataDeleteByUniqueKey;
|
||||
case ACTION_DATA_GRID_GENERATE_SQL_SELECT:
|
||||
return SqlResultSetGeneratorId.DataSelect;
|
||||
case ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY:
|
||||
return SqlResultSetGeneratorId.DataSelectMany;
|
||||
default: {
|
||||
throw new Error(`Unsupported action for SQL generation: ${action.id}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function getRowKeys(
|
||||
selectedElements: IGridDataKey<IGridRowKey, IGridColumnKey>[],
|
||||
key: IGridDataKey<IGridRowKey, IGridColumnKey> | undefined,
|
||||
): IGridRowKey[] {
|
||||
const rowKeysMap = new Map<string, IGridRowKey>(selectedElements.map(element => [GridDataKeysUtils.serialize(element.row), element.row]));
|
||||
let rowKeys: IGridRowKey[] = Array.from(rowKeysMap.values());
|
||||
|
||||
if (rowKeys.length === 0 && key) {
|
||||
rowKeys = [key.row];
|
||||
}
|
||||
|
||||
return rowKeys;
|
||||
}
|
||||
|
||||
function getSqlResultRows(
|
||||
model: IDatabaseDataModel<IDatabaseDataSource<unknown, IDatabaseDataResult>>,
|
||||
resultIndex: number,
|
||||
selectedElements: IGridDataKey<IGridRowKey, IGridColumnKey>[],
|
||||
key: IGridDataKey<IGridRowKey, IGridColumnKey> | undefined,
|
||||
): SqlResultRow[] {
|
||||
const data = model.source.getAction(resultIndex, ResultSetDataAction);
|
||||
const format = model.source.getAction(resultIndex, IDatabaseDataFormatAction);
|
||||
const view = model.source.getAction(resultIndex, GridViewAction);
|
||||
const rowKeys = getRowKeys(selectedElements, key);
|
||||
const result: SqlResultRow[] = [];
|
||||
const columnKeys = view.columnKeys;
|
||||
|
||||
for (const rowKey of rowKeys) {
|
||||
const rowValue = data.getRowValue(rowKey);
|
||||
const rowMetadata = data.getRowMetadata(rowKey);
|
||||
|
||||
if (rowValue) {
|
||||
result.push({
|
||||
data: rowValue.map((value, index) => {
|
||||
const columnKey = columnKeys[index];
|
||||
|
||||
if (!columnKey) {
|
||||
return value;
|
||||
}
|
||||
|
||||
const cellKey: IGridDataKey = { row: rowKey, column: columnKey };
|
||||
const holder = format.get(cellKey);
|
||||
const text = format.getText(holder);
|
||||
|
||||
return text || null;
|
||||
}),
|
||||
metaData: rowMetadata,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function hasLargeObjectValuesInSelectedRows(context: IDataContextProvider): boolean {
|
||||
const model = context.get(DATA_CONTEXT_DV_DDM)!;
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
const key = context.get(DATA_CONTEXT_DV_RESULT_KEY);
|
||||
|
||||
const format = model.source.getAction(resultIndex, IDatabaseDataFormatAction);
|
||||
const view = model.source.getAction(resultIndex, GridViewAction);
|
||||
const data = model.source.getAction(resultIndex, ResultSetDataAction);
|
||||
const content = model.source.getAction(resultIndex, ResultSetDataContentAction);
|
||||
const select = model.source.tryGetAction(resultIndex, IDatabaseDataSelectAction, GridSelectAction);
|
||||
|
||||
const selectedElements = select?.getSelectedElements() || [];
|
||||
const rowKeys = getRowKeys(selectedElements, key);
|
||||
const columnKeys = view.columnKeys;
|
||||
|
||||
for (const rowKey of rowKeys) {
|
||||
const rowValue = data.getRowValue(rowKey);
|
||||
|
||||
if (!rowValue) {
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const columnKey of columnKeys) {
|
||||
const cellKey: IGridDataKey = { row: rowKey, column: columnKey };
|
||||
const cellHolder = view.getCellHolder(cellKey) as IDatabaseValueHolder<IGridDataKey, IResultSetValue>;
|
||||
|
||||
if (format.isBinary(cellHolder)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (content.isTextTruncated(cellHolder) || content.isBlobTruncated(cellHolder)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -62,6 +62,7 @@ export class DataGridContextMenuSaveContentService {
|
||||
|
||||
if (action === ACTION_UPLOAD) {
|
||||
return (
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
!format.isBinary(cellHolder) ||
|
||||
model.isReadonly(resultIndex) ||
|
||||
(format.isReadOnly(key) && editor.getElementState(key) !== DatabaseEditChangeType.add)
|
||||
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { createMenu } from '@cloudbeaver/core-view';
|
||||
|
||||
export const MENU_DATA_GRID_GENERATE_SQL = createMenu('data-grid-generate-sql', {
|
||||
label: 'data_grid_table_generate_sql',
|
||||
icon: 'sql-script',
|
||||
});
|
||||
@@ -27,6 +27,7 @@ import { DataGridContextMenuCellEditingService } from './DataGrid/DataGridContex
|
||||
import { DataGridContextMenuFilterService } from './DataGrid/DataGridContextMenu/DataGridContextMenuFilter/DataGridContextMenuFilterService.js';
|
||||
import { DataGridContextMenuOrderService } from './DataGrid/DataGridContextMenu/DataGridContextMenuOrderService.js';
|
||||
import { DataGridContextMenuSaveContentService } from './DataGrid/DataGridContextMenu/DataGridContextMenuSaveContentService.js';
|
||||
import { DataGridContextMenuGenerateSqlService } from './DataGrid/DataGridContextMenu/DataGridContextMenuGenerateSqlService.js';
|
||||
import { DataGridSettingsService } from './DataGridSettingsService.js';
|
||||
import { ACTION_DATA_GRID_PIN_COLUMN } from './DataGrid/Actions/Pin/ACTION_DATA_GRID_PIN_COLUMN.js';
|
||||
import { ACTION_DATA_GRID_UNPIN_COLUMN } from './DataGrid/Actions/Pin/ACTION_DATA_GRID_UNPIN_COLUMN.js';
|
||||
@@ -44,6 +45,7 @@ const SpreadsheetGrid = importLazyComponent(() => import('./SpreadsheetGrid.js')
|
||||
DataGridContextMenuFilterService,
|
||||
DataGridContextMenuCellEditingService,
|
||||
DataGridContextMenuSaveContentService,
|
||||
DataGridContextMenuGenerateSqlService,
|
||||
ActionService,
|
||||
MenuService,
|
||||
ExceptionsCatcherService,
|
||||
@@ -56,6 +58,7 @@ export class SpreadsheetBootstrap extends Bootstrap {
|
||||
private readonly dataGridContextMenuFilterService: DataGridContextMenuFilterService,
|
||||
private readonly dataGridContextMenuCellEditingService: DataGridContextMenuCellEditingService,
|
||||
private readonly dataGridContextMenuSaveContentService: DataGridContextMenuSaveContentService,
|
||||
private readonly dataGridContextMenuGenerateSqlService: DataGridContextMenuGenerateSqlService,
|
||||
private readonly actionService: ActionService,
|
||||
private readonly menuService: MenuService,
|
||||
exceptionsCatcherService: ExceptionsCatcherService,
|
||||
@@ -79,6 +82,7 @@ export class SpreadsheetBootstrap extends Bootstrap {
|
||||
this.dataGridContextMenuFilterService.register();
|
||||
this.dataGridContextMenuCellEditingService.register();
|
||||
this.dataGridContextMenuSaveContentService.register();
|
||||
this.dataGridContextMenuGenerateSqlService.register();
|
||||
|
||||
this.menuService.addCreator({
|
||||
root: true,
|
||||
|
||||
@@ -32,4 +32,22 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
'Verwenden Sie die Formatierung für Zahlen und Daten entsprechend dem ausgewählten Gebietsschema. (!) Dies betrifft nur die Datendarstellung; für die Bearbeitung sollten Rohwerte verwendet werden.',
|
||||
],
|
||||
['data_grid_table_generate_sql', 'SQL generieren'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', 'INSERT-Anweisung generieren'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', 'UPDATE-Anweisung generieren'],
|
||||
['data_grid_table_generate_sql_delete', 'DELETE nach eindeutigem Schlüssel'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', 'DELETE-Anweisung generieren'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', 'SELECT-Anweisung mit WHERE-Klausel generieren'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', 'SELECT-Anweisung mit WHERE IN-Klausel generieren'],
|
||||
['data_grid_table_generate_sql_error_title', 'SQL-Generierungsfehler'],
|
||||
['data_grid_table_generate_sql_error_no_query', 'Keine Abfrage für das aktuelle Ergebnis verfügbar'],
|
||||
['data_grid_table_generate_sql_error_no_connection', 'Unbekannter Ausführungskontext'],
|
||||
['data_grid_table_generate_sql_error_no_rows', 'Keine Zeilen ausgewählt'],
|
||||
['data_grid_table_generate_sql_error_no_result', 'Kein Ergebnis verfügbar'],
|
||||
['data_grid_table_generate_sql_error_no_context', 'Kein Ausführungskontext verfügbar'],
|
||||
['data_grid_table_generate_sql_disabled_lob_tooltip', 'SQL-Generierung ist für Zeilen mit LOB oder abgeschnittenen Werten nicht verfügbar'],
|
||||
];
|
||||
|
||||
@@ -38,4 +38,22 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
'Use formatting for numbers and dates according to the selected locale. (!)This only affects data representation; raw values should be used for editing.',
|
||||
],
|
||||
['data_grid_table_generate_sql', 'Generate SQL'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', 'Generate INSERT statement'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', 'Generate UPDATE statement'],
|
||||
['data_grid_table_generate_sql_delete', 'DELETE by Unique Key'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', 'Generate DELETE statement'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', 'Generate SELECT statement with WHERE clause'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', 'Generate SELECT statement with WHERE IN clause'],
|
||||
['data_grid_table_generate_sql_error_title', 'SQL Generation Error'],
|
||||
['data_grid_table_generate_sql_error_no_query', 'No query available for the current result'],
|
||||
['data_grid_table_generate_sql_error_no_connection', 'Unknown execution context'],
|
||||
['data_grid_table_generate_sql_error_no_rows', 'No rows selected'],
|
||||
['data_grid_table_generate_sql_error_no_result', 'No result set available'],
|
||||
['data_grid_table_generate_sql_error_no_context', 'No execution context available'],
|
||||
['data_grid_table_generate_sql_disabled_lob_tooltip', 'SQL generation is not available for rows containing LOB or truncated values'],
|
||||
];
|
||||
|
||||
@@ -37,4 +37,25 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
"Utilisez le formatage pour les nombres et les dates selon les paramètres régionaux sélectionnés. (!) Cela n'affecte que la représentation des données ; les valeurs brutes doivent être utilisées pour l'édition.",
|
||||
],
|
||||
['data_grid_table_generate_sql', 'Générer SQL'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', 'Générer une instruction INSERT'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', 'Générer une instruction UPDATE'],
|
||||
['data_grid_table_generate_sql_delete', 'DELETE par clé unique'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', 'Générer une instruction DELETE'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', 'Générer une instruction SELECT avec clause WHERE'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', 'Générer une instruction SELECT avec clause WHERE IN'],
|
||||
['data_grid_table_generate_sql_error_title', 'Erreur de génération SQL'],
|
||||
['data_grid_table_generate_sql_error_no_query', 'Aucune requête disponible pour le résultat actuel'],
|
||||
['data_grid_table_generate_sql_error_no_connection', "Contexte d'exécution inconnu"],
|
||||
['data_grid_table_generate_sql_error_no_rows', 'Aucune ligne sélectionnée'],
|
||||
['data_grid_table_generate_sql_error_no_result', 'Aucun ensemble de résultats disponible'],
|
||||
['data_grid_table_generate_sql_error_no_context', "Aucun contexte d'exécution disponible"],
|
||||
[
|
||||
'data_grid_table_generate_sql_disabled_lob_tooltip',
|
||||
"La génération SQL n'est pas disponible pour les lignes contenant des valeurs LOB ou tronquées",
|
||||
],
|
||||
];
|
||||
|
||||
@@ -35,4 +35,22 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
'Usa la formattazione per numeri e date in base alla locale selezionata. (!) Questo influisce solo sulla rappresentazione dei dati; i valori grezzi devono essere usati per la modifica.',
|
||||
],
|
||||
['data_grid_table_generate_sql', 'Genera SQL'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', 'Genera istruzione INSERT'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', 'Genera istruzione UPDATE'],
|
||||
['data_grid_table_generate_sql_delete', 'DELETE per chiave univoca'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', 'Genera istruzione DELETE'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', 'Genera istruzione SELECT con clausola WHERE'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', 'Genera istruzione SELECT con clausola WHERE IN'],
|
||||
['data_grid_table_generate_sql_error_title', 'Errore di generazione SQL'],
|
||||
['data_grid_table_generate_sql_error_no_query', 'Nessuna query disponibile per il risultato attuale'],
|
||||
['data_grid_table_generate_sql_error_no_connection', 'Contesto di esecuzione sconosciuto'],
|
||||
['data_grid_table_generate_sql_error_no_rows', 'Nessuna riga selezionata'],
|
||||
['data_grid_table_generate_sql_error_no_result', 'Nessun set di risultati disponibile'],
|
||||
['data_grid_table_generate_sql_error_no_context', 'Nessun contesto di esecuzione disponibile'],
|
||||
['data_grid_table_generate_sql_disabled_lob_tooltip', 'La generazione SQL non è disponibile per le righe contenenti valori LOB o troncati'],
|
||||
];
|
||||
|
||||
@@ -38,4 +38,22 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
'Использовать форматирование для чисел и дат в соответствии с выбранной локалью. (!) Это влияет только на представление данных; для редактирования должны использоваться исходные значения.',
|
||||
],
|
||||
['data_grid_table_generate_sql', 'Сгенерировать SQL'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', 'Сгенерировать INSERT-запрос'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', 'Сгенерировать UPDATE-запрос'],
|
||||
['data_grid_table_generate_sql_delete', 'DELETE по уникальному ключу'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', 'Сгенерировать DELETE-запрос'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', 'Сгенерировать SELECT-запрос с WHERE'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', 'Сгенерировать SELECT-запрос с WHERE IN'],
|
||||
['data_grid_table_generate_sql_error_title', 'Ошибка генерации SQL'],
|
||||
['data_grid_table_generate_sql_error_no_query', 'Нет запроса для текущего результата'],
|
||||
['data_grid_table_generate_sql_error_no_connection', 'Неизвестный контекст выполнения'],
|
||||
['data_grid_table_generate_sql_error_no_rows', 'Не выбрано ни одной строки'],
|
||||
['data_grid_table_generate_sql_error_no_result', 'Результаты недоступны'],
|
||||
['data_grid_table_generate_sql_error_no_context', 'Контекст выполнения недоступен'],
|
||||
['data_grid_table_generate_sql_disabled_lob_tooltip', 'Генерация SQL недоступна для строк, содержащих LOB или усеченные значения'],
|
||||
];
|
||||
|
||||
@@ -38,4 +38,22 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
'Sử dụng định dạng cho số và ngày theo ngôn ngữ đã chọn. (!) Điều này chỉ ảnh hưởng đến việc hiển thị dữ liệu; các giá trị thô nên được sử dụng để chỉnh sửa.',
|
||||
],
|
||||
['data_grid_table_generate_sql', 'Tạo SQL'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', 'Tạo câu lệnh INSERT'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', 'Tạo câu lệnh UPDATE'],
|
||||
['data_grid_table_generate_sql_delete', 'DELETE theo khóa duy nhất'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', 'Tạo câu lệnh DELETE'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', 'Tạo câu lệnh SELECT với điều kiện WHERE'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', 'Tạo câu lệnh SELECT với điều kiện WHERE IN'],
|
||||
['data_grid_table_generate_sql_error_title', 'Lỗi Tạo SQL'],
|
||||
['data_grid_table_generate_sql_error_no_query', 'Không có truy vấn nào cho kết quả hiện tại'],
|
||||
['data_grid_table_generate_sql_error_no_connection', 'Ngữ cảnh thực thi không xác định'],
|
||||
['data_grid_table_generate_sql_error_no_rows', 'Không có hàng nào được chọn'],
|
||||
['data_grid_table_generate_sql_error_no_result', 'Không có tập kết quả'],
|
||||
['data_grid_table_generate_sql_error_no_context', 'Không có ngữ cảnh thực thi'],
|
||||
['data_grid_table_generate_sql_disabled_lob_tooltip', 'Tạo SQL không khả dụng cho các hàng chứa giá trị LOB hoặc bị cắt ngắn'],
|
||||
];
|
||||
|
||||
@@ -37,4 +37,22 @@ export default [
|
||||
'plugin_data_spreadsheet_new_settings_use_locale_formatting_description',
|
||||
'根据选定的区域设置对数字和日期进行格式化。(!)这仅影响数据表示;编辑时应使用原始值。',
|
||||
],
|
||||
['data_grid_table_generate_sql', '生成 SQL'],
|
||||
['data_grid_table_generate_sql_insert', 'INSERT'],
|
||||
['data_grid_table_generate_sql_insert_tooltip', '生成 INSERT 语句'],
|
||||
['data_grid_table_generate_sql_update', 'UPDATE'],
|
||||
['data_grid_table_generate_sql_update_tooltip', '生成 UPDATE 语句'],
|
||||
['data_grid_table_generate_sql_delete', '按唯一键 DELETE'],
|
||||
['data_grid_table_generate_sql_delete_tooltip', '生成 DELETE 语句'],
|
||||
['data_grid_table_generate_sql_select', 'SELECT .. WHERE .. ='],
|
||||
['data_grid_table_generate_sql_select_tooltip', '生成带 WHERE 子句的 SELECT 语句'],
|
||||
['data_grid_table_generate_sql_select_many', 'SELECT .. WHERE .. IN'],
|
||||
['data_grid_table_generate_sql_select_many_tooltip', '生成带 WHERE IN 子句的 SELECT 语句'],
|
||||
['data_grid_table_generate_sql_error_title', 'SQL 生成错误'],
|
||||
['data_grid_table_generate_sql_error_no_query', '当前结果没有可用的查询'],
|
||||
['data_grid_table_generate_sql_error_no_connection', '未知的执行上下文'],
|
||||
['data_grid_table_generate_sql_error_no_rows', '未选择任何行'],
|
||||
['data_grid_table_generate_sql_error_no_result', '没有可用的结果集'],
|
||||
['data_grid_table_generate_sql_error_no_context', '没有可用的执行上下文'],
|
||||
['data_grid_table_generate_sql_disabled_lob_tooltip', '包含 LOB 或截断值的行无法生成 SQL'],
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -14,6 +14,7 @@ import { DataGridContextMenuSaveContentService } from './DataGrid/DataGridContex
|
||||
import { DataGridContextMenuOrderService } from './DataGrid/DataGridContextMenu/DataGridContextMenuOrderService.js';
|
||||
import { DataGridContextMenuFilterService } from './DataGrid/DataGridContextMenu/DataGridContextMenuFilter/DataGridContextMenuFilterService.js';
|
||||
import { DataGridContextMenuCellEditingService } from './DataGrid/DataGridContextMenu/DataGridContextMenuCellEditingService.js';
|
||||
import { DataGridContextMenuGenerateSqlService } from './DataGrid/DataGridContextMenu/DataGridContextMenuGenerateSqlService.js';
|
||||
|
||||
export default ModuleRegistry.add({
|
||||
name: '@cloudbeaver/plugin-data-spreadsheet-new',
|
||||
@@ -26,6 +27,7 @@ export default ModuleRegistry.add({
|
||||
.addSingleton(DataGridContextMenuCellEditingService)
|
||||
.addSingleton(DataGridSettingsService)
|
||||
.addSingleton(DataGridContextMenuSaveContentService)
|
||||
.addSingleton(DataGridContextMenuGenerateSqlService)
|
||||
.addSingleton(DataGridContextMenuOrderService)
|
||||
.addSingleton(DataGridContextMenuFilterService);
|
||||
},
|
||||
|
||||
@@ -69,6 +69,9 @@
|
||||
},
|
||||
{
|
||||
"path": "../plugin-data-viewer-conditional-formatting"
|
||||
},
|
||||
{
|
||||
"path": "../plugin-sql-generator"
|
||||
}
|
||||
],
|
||||
"include": [
|
||||
|
||||
+3
-7
@@ -113,13 +113,7 @@ export class TableFooterMenuService {
|
||||
handler: this.tableFooterMenuActionHandler.bind(this),
|
||||
});
|
||||
|
||||
this.dataViewerViewService.registerAction(
|
||||
ACTION_DELETE,
|
||||
ACTION_REVERT,
|
||||
ACTION_ADD,
|
||||
ACTION_DUPLICATE,
|
||||
ACTION_CANCEL,
|
||||
);
|
||||
this.dataViewerViewService.registerAction(ACTION_DELETE, ACTION_REVERT, ACTION_ADD, ACTION_DUPLICATE, ACTION_CANCEL);
|
||||
}
|
||||
|
||||
private registerEditingActions() {
|
||||
@@ -131,6 +125,7 @@ export class TableFooterMenuService {
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
const presentation = context.get(DATA_CONTEXT_DV_PRESENTATION);
|
||||
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
return !model.isReadonly(resultIndex) && !presentation?.readonly && (!presentation || presentation.type === DataViewerPresentationType.Data);
|
||||
},
|
||||
getItems(context, items) {
|
||||
@@ -149,6 +144,7 @@ export class TableFooterMenuService {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
if (model.isReadonly(resultIndex)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,7 @@ export class TableHeaderService extends Bootstrap {
|
||||
contexts: [DATA_CONTEXT_DV_DDM, DATA_CONTEXT_DV_DDM_RESULT_INDEX],
|
||||
isHidden(context, action) {
|
||||
const model = context.get(DATA_CONTEXT_DV_DDM)!;
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
const isReadonly = model.isReadonly(context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!);
|
||||
|
||||
if ([ACTION_UNDO, ACTION_REDO].includes(action)) {
|
||||
|
||||
+2
-1
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ export function isTextValueReadonly({ contentAction, formatAction, model, result
|
||||
}
|
||||
|
||||
return (
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
model.isReadonly(resultIndex) ||
|
||||
model.isDisabled(resultIndex) ||
|
||||
(formatAction.isReadOnly(cellHolder.key) && editAction.getElementState(cellHolder.key) !== DatabaseEditChangeType.add) ||
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
"@cloudbeaver/core-navigation-tree": "workspace:*",
|
||||
"@cloudbeaver/core-resource": "workspace:*",
|
||||
"@cloudbeaver/core-sdk": "workspace:*",
|
||||
"@cloudbeaver/core-utils": "workspace:*",
|
||||
"@cloudbeaver/core-view": "workspace:*",
|
||||
"@cloudbeaver/plugin-codemirror6": "workspace:*",
|
||||
"@cloudbeaver/plugin-data-viewer": "workspace:*",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -42,6 +42,7 @@ export class GeneratorMenuBootstrap extends Bootstrap {
|
||||
const resultIndex = context.get(DATA_CONTEXT_DV_DDM_RESULT_INDEX)!;
|
||||
const presentation = context.get(DATA_CONTEXT_DV_PRESENTATION);
|
||||
return (
|
||||
// TODO add more proper way to define to what features it should be added https://github.com/dbeaver/pro/issues/8299
|
||||
!model.isReadonly(resultIndex) &&
|
||||
model.source.getResult(resultIndex)?.dataFormat === ResultDataFormat.Resultset &&
|
||||
!presentation?.readonly &&
|
||||
|
||||
@@ -5,9 +5,7 @@
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
import { observable } from 'mobx';
|
||||
import { observer } from 'mobx-react-lite';
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import {
|
||||
Button,
|
||||
@@ -15,12 +13,8 @@ import {
|
||||
CommonDialogFooter,
|
||||
CommonDialogHeader,
|
||||
CommonDialogWrapper,
|
||||
ErrorMessage,
|
||||
Loader,
|
||||
s,
|
||||
useClipboard,
|
||||
useErrorDetails,
|
||||
useObservableRef,
|
||||
useResource,
|
||||
useS,
|
||||
useTranslate,
|
||||
@@ -28,16 +22,14 @@ import {
|
||||
import { ConnectionDialectResource, ConnectionInfoResource, createConnectionParam } from '@cloudbeaver/core-connections';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import type { DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { GQLErrorCatcher } from '@cloudbeaver/core-sdk';
|
||||
import { useCodemirrorExtensions } from '@cloudbeaver/plugin-codemirror6';
|
||||
import { SQLCodeEditor, useSqlDialectExtension } from '@cloudbeaver/plugin-sql-editor-codemirror';
|
||||
|
||||
import style from './GeneratedSqlDialog.module.css';
|
||||
import { SqlGeneratorsResource } from './SqlGeneratorsResource.js';
|
||||
|
||||
interface Payload {
|
||||
generatorId: string;
|
||||
pathId: string;
|
||||
nodeId: string;
|
||||
query: string;
|
||||
}
|
||||
|
||||
export const GeneratedSqlDialog = observer<DialogComponentProps<Payload>>(function GeneratedSqlDialog({ rejectDialog, payload }) {
|
||||
@@ -45,34 +37,9 @@ export const GeneratedSqlDialog = observer<DialogComponentProps<Payload>>(functi
|
||||
const copy = useClipboard();
|
||||
const styles = useS(style);
|
||||
|
||||
const sqlGeneratorsResource = useService(SqlGeneratorsResource);
|
||||
const connectionInfoResource = useService(ConnectionInfoResource);
|
||||
const connection = connectionInfoResource.getConnectionForNode(payload.pathId);
|
||||
const connection = connectionInfoResource.getConnectionForNode(payload.nodeId);
|
||||
|
||||
const state = useObservableRef(
|
||||
() => ({
|
||||
query: '',
|
||||
loading: true,
|
||||
error: new GQLErrorCatcher(),
|
||||
async load() {
|
||||
this.error.clear();
|
||||
|
||||
try {
|
||||
this.query = await sqlGeneratorsResource.generateEntityQuery(payload.generatorId, payload.pathId);
|
||||
} catch (exception: any) {
|
||||
this.error.catch(exception);
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
}),
|
||||
{
|
||||
query: observable.ref,
|
||||
loading: observable.ref,
|
||||
connection: observable.ref,
|
||||
},
|
||||
{ connection },
|
||||
);
|
||||
const connectionDialectResource = useResource(GeneratedSqlDialog, ConnectionDialectResource, connection ? createConnectionParam(connection) : null);
|
||||
const sqlDialect = useSqlDialectExtension(connectionDialectResource.data);
|
||||
|
||||
@@ -80,34 +47,19 @@ export const GeneratedSqlDialog = observer<DialogComponentProps<Payload>>(functi
|
||||
if (sqlDialect) {
|
||||
extensions.set(...sqlDialect);
|
||||
}
|
||||
const error = useErrorDetails(state.error.exception);
|
||||
|
||||
useEffect(() => {
|
||||
state.load();
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<CommonDialogWrapper size="large">
|
||||
<CommonDialogHeader title="app_shared_sql_generators_dialog_title" icon="sql-script" onReject={rejectDialog} />
|
||||
<CommonDialogBody noOverflow noBodyPadding>
|
||||
<div className={s(styles, { wrapper: true })}>
|
||||
<Loader loading={state.loading}>
|
||||
{() => <SQLCodeEditor className={s(styles, { sqlCodeEditorLoader: true })} value={state.query} extensions={extensions} readonly />}
|
||||
</Loader>
|
||||
<SQLCodeEditor className={s(styles, { sqlCodeEditorLoader: true })} value={payload.query} extensions={extensions} readonly />
|
||||
</div>
|
||||
</CommonDialogBody>
|
||||
<CommonDialogFooter>
|
||||
<div className={s(styles, { footerContainer: true })}>
|
||||
{state.error.responseMessage && (
|
||||
<ErrorMessage
|
||||
className={s(styles, { errorMessage: true })}
|
||||
text={state.error.responseMessage}
|
||||
hasDetails={error.hasDetails}
|
||||
onShowDetails={error.open}
|
||||
/>
|
||||
)}
|
||||
<div className={s(styles, { buttons: true })}>
|
||||
<Button variant="secondary" onClick={() => copy(state.query, true)}>
|
||||
<Button variant="secondary" disabled={!payload.query} onClick={() => copy(payload.query, true)}>
|
||||
{translate('ui_copy_to_clipboard')}
|
||||
</Button>
|
||||
<Button onClick={() => rejectDialog()}>{translate('ui_close')}</Button>
|
||||
|
||||
@@ -14,15 +14,17 @@ import { MenuBaseItem, MenuService } from '@cloudbeaver/core-view';
|
||||
|
||||
import { MENU_SQL_GENERATORS } from './MENU_SQL_GENERATORS.js';
|
||||
import { SqlGeneratorsResource } from './SqlGeneratorsResource.js';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
|
||||
const GeneratedSqlDialog = importLazyComponent(() => import('./GeneratedSqlDialog.js').then(m => m.GeneratedSqlDialog));
|
||||
|
||||
@injectable(() => [SqlGeneratorsResource, CommonDialogService, MenuService])
|
||||
@injectable(() => [SqlGeneratorsResource, CommonDialogService, MenuService, NotificationService])
|
||||
export class SqlGeneratorsBootstrap extends Bootstrap {
|
||||
constructor(
|
||||
private readonly sqlGeneratorsResource: SqlGeneratorsResource,
|
||||
private readonly commonDialogService: CommonDialogService,
|
||||
private readonly menuService: MenuService,
|
||||
private readonly notificationService: NotificationService,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
@@ -77,11 +79,16 @@ export class SqlGeneratorsBootstrap extends Bootstrap {
|
||||
tooltip: action.description,
|
||||
},
|
||||
{
|
||||
onSelect: () => {
|
||||
this.commonDialogService.open(GeneratedSqlDialog, {
|
||||
generatorId: action.id,
|
||||
pathId: node.id,
|
||||
});
|
||||
onSelect: async () => {
|
||||
try {
|
||||
const query = await this.sqlGeneratorsResource.generateEntityQuery(action.id, node.id);
|
||||
await this.commonDialogService.open(GeneratedSqlDialog, {
|
||||
query,
|
||||
nodeId: node.id,
|
||||
});
|
||||
} catch (e: any) {
|
||||
this.notificationService.logException(e, 'sql_generator_error_title');
|
||||
}
|
||||
},
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2024 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -8,7 +8,7 @@
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree';
|
||||
import { CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource';
|
||||
import { GraphQLService, type SqlQueryGenerator } from '@cloudbeaver/core-sdk';
|
||||
import { GraphQLService, type SqlGenerateResultSetQueryQueryVariables, type SqlQueryGenerator } from '@cloudbeaver/core-sdk';
|
||||
|
||||
export const MAX_GENERATORS_LENGTH = 15;
|
||||
|
||||
@@ -34,6 +34,12 @@ export class SqlGeneratorsResource extends CachedMapResource<string, SqlQueryGen
|
||||
return result.sqlGenerateEntityQuery;
|
||||
}
|
||||
|
||||
async generateResultSetSql(params: SqlGenerateResultSetQueryQueryVariables): Promise<string | null> {
|
||||
const response = await this.graphQLService.sdk.sqlGenerateResultSetQuery(params);
|
||||
|
||||
return response.sqlGenerateResultSetQuery;
|
||||
}
|
||||
|
||||
protected async loader(key: ResourceKey<string>): Promise<Map<string, SqlQueryGenerator[]>> {
|
||||
if (isResourceAlias(key)) {
|
||||
throw new Error('Aliases not supported by this resource.');
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2025 DBeaver Corp and others
|
||||
* Copyright (C) 2020-2026 DBeaver Corp and others
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0.
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -11,3 +11,4 @@ import './module.js';
|
||||
export * from './SqlGenerators/SqlGeneratorsResource.js';
|
||||
export * from './SqlGenerators/SqlGeneratorsBootstrap.js';
|
||||
export * from './actions/ACTION_SQL_GENERATE.js';
|
||||
export * from './SqlGenerators/GeneratedSqlDialog.js';
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default [['sql_generator_error_title', 'SQL Generation Error']];
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default [['sql_generator_error_title', 'Erreur de génération SQL']];
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default [['sql_generator_error_title', 'Errore di generazione SQL']];
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default [['sql_generator_error_title', 'Ошибка генерации SQL']];
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default [['sql_generator_error_title', 'Lỗi tạo SQL']];
|
||||
|
||||
@@ -1 +1 @@
|
||||
export default [];
|
||||
export default [['sql_generator_error_title', 'SQL生成错误']];
|
||||
|
||||
@@ -40,6 +40,9 @@
|
||||
{
|
||||
"path": "../core-sdk"
|
||||
},
|
||||
{
|
||||
"path": "../core-utils"
|
||||
},
|
||||
{
|
||||
"path": "../core-view"
|
||||
},
|
||||
|
||||
@@ -2973,6 +2973,7 @@ __metadata:
|
||||
"@cloudbeaver/plugin-data-grid": "workspace:*"
|
||||
"@cloudbeaver/plugin-data-viewer": "workspace:*"
|
||||
"@cloudbeaver/plugin-data-viewer-conditional-formatting": "workspace:*"
|
||||
"@cloudbeaver/plugin-sql-generator": "workspace:*"
|
||||
"@cloudbeaver/tsconfig": "workspace:*"
|
||||
"@dbeaver/cli": "workspace:*"
|
||||
"@dbeaver/js-helpers": "workspace:*"
|
||||
@@ -4325,6 +4326,7 @@ __metadata:
|
||||
"@cloudbeaver/core-navigation-tree": "workspace:*"
|
||||
"@cloudbeaver/core-resource": "workspace:*"
|
||||
"@cloudbeaver/core-sdk": "workspace:*"
|
||||
"@cloudbeaver/core-utils": "workspace:*"
|
||||
"@cloudbeaver/core-view": "workspace:*"
|
||||
"@cloudbeaver/plugin-codemirror6": "workspace:*"
|
||||
"@cloudbeaver/plugin-data-viewer": "workspace:*"
|
||||
|
||||
Reference in New Issue
Block a user