[CB] SQL Query generation: front-end part (#4132)

* dbeaver/pro#8048 pass commit message validation

* fixes json + translations

* fixes gis generation

* uses format action to get text value for sql generators
This commit is contained in:
sergeyteleshev
2026-02-11 18:17:43 +01:00
committed by Serge Rider
parent 06da0705d2
commit dace3afa2d
47 changed files with 588 additions and 82 deletions
@@ -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 -1
View File
@@ -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.
@@ -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:*",
@@ -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',
});
@@ -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',
});
@@ -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',
});
@@ -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',
});
@@ -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',
});
@@ -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;
}
@@ -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;
}
@@ -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)
@@ -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": [
@@ -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)) {
@@ -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"
},
+2
View File
@@ -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:*"