Skip to content
Open
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -20,4 +20,5 @@ export enum EObjectFeature {
'dataSourceConnected' = 'dataSourceConnected',
'entityContainer' = 'entityContainer',
'supportsDataFilter' = 'supportsDataFilter',
'supportsFullDdl' = 'supportsFullDdl', // some connections may not have the full DDL feature
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mutation asyncSqlGenerateEntityQuery($generatorId: String!, $nodePathList: [String!]!, $generatorOptions: SQLQueryGeneratorOptions) {
taskInfo: asyncSqlGenerateEntityQuery(generatorId: $generatorId, nodePathList: $nodePathList, generatorOptions: $generatorOptions) {
...AsyncTaskInfo
}
}
3 changes: 0 additions & 3 deletions webapp/packages/core-sdk/src/queries/metadataGetNodeDDL.gql

This file was deleted.

This file was deleted.

38 changes: 38 additions & 0 deletions webapp/packages/core-sql-generator/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"name": "@cloudbeaver/core-sql-generator",
"type": "module",
"sideEffects": [
"./lib/module.js",
"./lib/index.js",
"src/**/*.css",
"public/**/*"
],
"version": "0.1.0",
"description": "",
"license": "Apache-2.0",
"exports": {
".": "./lib/index.js",
"./module": "./lib/module.js"
},
"scripts": {
"build": "tsc -b",
"clean": "rimraf --glob lib",
"lint": "eslint ./src/ --ext .ts,.tsx",
"test": "dbeaver-test",
"validate-dependencies": "core-cli-validate-dependencies"
},
"dependencies": {
"@cloudbeaver/core-di": "workspace:*",
"@cloudbeaver/core-navigation-tree": "workspace:*",
"@cloudbeaver/core-resource": "workspace:*",
"@cloudbeaver/core-root": "workspace:*",
"@cloudbeaver/core-sdk": "workspace:*",
"tslib": "^2"
},
"devDependencies": {
"@cloudbeaver/core-cli": "workspace:*",
"@cloudbeaver/tsconfig": "workspace:*",
"rimraf": "^6",
"typescript": "^5"
}
}
92 changes: 92 additions & 0 deletions webapp/packages/core-sql-generator/src/SqlEntityQueryResource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
/*
* 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 { NavNodeInfoResource } from '@cloudbeaver/core-navigation-tree';
import { CachedMapResource, isResourceAlias, type ResourceKey, resourceKeyList, ResourceKeyUtils } from '@cloudbeaver/core-resource';
import { AsyncTaskInfoService } from '@cloudbeaver/core-root';
import { GraphQLService, type SqlQueryGeneratorOptions } from '@cloudbeaver/core-sdk';

export interface ISqlEntityQueryKey {
readonly nodeId: string;
readonly generatorId: string;
readonly options: SqlQueryGeneratorOptions;
}

@injectable(() => [GraphQLService, AsyncTaskInfoService, NavNodeInfoResource])
export class SqlEntityQueryResource extends CachedMapResource<ISqlEntityQueryKey, string> {
constructor(
private readonly graphQLService: GraphQLService,
private readonly asyncTaskInfoService: AsyncTaskInfoService,
private readonly navNodeInfoResource: NavNodeInfoResource,
) {
super();

this.navNodeInfoResource.outdateResource(this, nodeId =>
resourceKeyList(this.keys.filter(key => ResourceKeyUtils.isIntersect(nodeId, key.nodeId))),
);
this.navNodeInfoResource.deleteInResource(this, nodeId =>
resourceKeyList(this.keys.filter(key => ResourceKeyUtils.isIntersect(nodeId, key.nodeId))),
);
}

protected async loader(key: ResourceKey<ISqlEntityQueryKey>): Promise<Map<ISqlEntityQueryKey, string>> {
if (isResourceAlias(key)) {
throw new Error('Aliases not supported by this resource.');
}

const keys: ISqlEntityQueryKey[] = [];
const values: string[] = [];

await ResourceKeyUtils.forEachAsync(key, async entityQueryKey => {
const query = await this.generateEntityQuery(entityQueryKey.generatorId, entityQueryKey.nodeId, entityQueryKey.options);
keys.push(entityQueryKey);
values.push(query);
});

this.set(resourceKeyList(keys), values);

return this.data;
}

private async generateEntityQuery(generatorId: string, nodeId: string, options?: SqlQueryGeneratorOptions): Promise<string> {
const task = this.asyncTaskInfoService.create(async () => {
const { taskInfo } = await this.graphQLService.sdk.asyncSqlGenerateEntityQuery({
generatorId,
nodePathList: nodeId,
generatorOptions: options,
});

return taskInfo;
});

const info = await this.asyncTaskInfoService.run(task);
await this.asyncTaskInfoService.remove(task.id);

return info.taskResult;
}

override isKeyEqual(param: ISqlEntityQueryKey, second: ISqlEntityQueryKey): boolean {
return (
param.nodeId === second.nodeId &&
param.generatorId === second.generatorId &&
param.options.useFullyQualifiedNames === second.options.useFullyQualifiedNames &&
param.options.compactSql === second.options.compactSql &&
param.options.showFullDdl === second.options.showFullDdl
);
}

protected validateKey(key: ISqlEntityQueryKey): boolean {
return (
typeof key === 'object' &&
key !== null &&
typeof key.nodeId === 'string' &&
typeof key.generatorId === 'string' &&
typeof key.options === 'object'
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const MAX_GENERATORS_LENGTH = 15;
export const getDefaultQueryGeneratorOptions = (): SqlQueryGeneratorOptions => ({
useFullyQualifiedNames: true,
compactSql: false,
showFullDdl: false,
});
export const DDL_GENERATOR_ID = 'tableDDL';

Expand All @@ -34,16 +35,6 @@ export class SqlGeneratorsResource extends CachedMapResource<string, SqlQueryGen
this.navNodeInfoResource.deleteInResource(this);
}

async generateEntityQuery(generatorId: string, nodePathList: string | string[], options?: SqlQueryGeneratorOptions): Promise<string> {
const result = await this.graphQLService.sdk.sqlGenerateEntityQuery({
generatorId,
nodePathList,
generatorOptions: options,
});

return result.sqlGenerateEntityQuery;
}

async generateResultSetSql(params: SqlGenerateResultSetQueryQueryVariables): Promise<string | null> {
const response = await this.graphQLService.sdk.sqlGenerateResultSetQuery(params);

Expand Down
12 changes: 12 additions & 0 deletions webapp/packages/core-sql-generator/src/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* 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 './module.js';

export * from './SqlGeneratorsResource.js';
export * from './SqlEntityQueryResource.js';
22 changes: 22 additions & 0 deletions webapp/packages/core-sql-generator/src/module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 { Dependency, ModuleRegistry, proxy } from '@cloudbeaver/core-di';
import { SqlEntityQueryResource } from './SqlEntityQueryResource.js';
import { SqlGeneratorsResource } from './SqlGeneratorsResource.js';

export default ModuleRegistry.add({
Comment thread
devnaumov marked this conversation as resolved.
Outdated
name: '@cloudbeaver/core-sql-generator',

configure: serviceCollection => {
serviceCollection
.addSingleton(Dependency, proxy(SqlGeneratorsResource))
.addSingleton(SqlGeneratorsResource)
.addSingleton(Dependency, proxy(SqlEntityQueryResource))
.addSingleton(SqlEntityQueryResource);
},
});
39 changes: 39 additions & 0 deletions webapp/packages/core-sql-generator/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
{
"extends": "@cloudbeaver/tsconfig/tsconfig.json",
"compilerOptions": {
"rootDir": "src",
"outDir": "lib",
"tsBuildInfoFile": "lib/tsconfig.tsbuildinfo",
"composite": true
},
"references": [
{
"path": "../core-cli"
},
{
"path": "../core-di"
},
{
"path": "../core-navigation-tree"
},
{
"path": "../core-resource"
},
{
"path": "../core-root"
},
{
"path": "../core-sdk"
}
],
"include": [
"__custom_mocks__/**/*",
"src/**/*",
"src/**/*.json",
"src/**/*.css"
],
"exclude": [
"**/node_modules",
"lib/**/*"
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,13 @@ import { ACTION_DATA_GRID_GENERATE_SQL_SELECT_MANY } from '../Actions/GenerateSQ
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 { getDefaultQueryGeneratorOptions, GeneratedSqlDialog, SqlGeneratorsResource, DDL_GENERATOR_ID } from '@cloudbeaver/plugin-sql-generator';
import {
getDefaultQueryGeneratorOptions,
GeneratedSqlDialog,
SqlEntityQueryResource,
SqlGeneratorsResource,
DDL_GENERATOR_ID,
} from '@cloudbeaver/plugin-sql-generator';
import { isNotNullDefined } from '@dbeaver/js-helpers';

@injectable(() => [
Expand All @@ -50,6 +56,7 @@ import { isNotNullDefined } from '@dbeaver/js-helpers';
CommonDialogService,
NotificationService,
SqlGeneratorsResource,
SqlEntityQueryResource,
LocalizationService,
NavNodeInfoResource,
])
Expand All @@ -60,6 +67,7 @@ export class DataGridContextMenuGenerateSqlService {
private readonly commonDialogService: CommonDialogService,
private readonly notificationService: NotificationService,
private readonly sqlGenerationResource: SqlGeneratorsResource,
private readonly sqlEntityQueryResource: SqlEntityQueryResource,
private readonly localizationService: LocalizationService,
private readonly navNodeInfoResource: NavNodeInfoResource,
) {}
Expand Down Expand Up @@ -179,6 +187,7 @@ export class DataGridContextMenuGenerateSqlService {
query,
nodeId: nodePath ?? connectionId,
nodeName: this.getEntityNameFromNodePath(containerNodePath, model.name),
generatorId,
generatorName: this.localizationService.translate(generatorLabel),
options: getDefaultQueryGeneratorOptions(),
regenerateQuery: options =>
Expand Down Expand Up @@ -228,15 +237,21 @@ export class DataGridContextMenuGenerateSqlService {
return;
}

const query = await this.sqlGenerationResource.generateEntityQuery(createGenerator.id, nodePathList, getDefaultQueryGeneratorOptions());
const query = await this.sqlEntityQueryResource.load({
nodeId: nodePathList,
generatorId: createGenerator.id,
options: getDefaultQueryGeneratorOptions(),
});

await this.commonDialogService.open(GeneratedSqlDialog, {
query,
nodeId: nodePathList,
nodeName: this.getEntityNameFromNodePath(nodePathList, model.name),
generatorId: createGenerator.id,
generatorName: createGenerator.label,
options: getDefaultQueryGeneratorOptions(),
regenerateQuery: genOptions => this.sqlGenerationResource.generateEntityQuery(createGenerator.id, nodePathList, genOptions),
regenerateQuery: genOptions =>
this.sqlEntityQueryResource.load({ nodeId: nodePathList, generatorId: createGenerator.id, options: genOptions }),
});
} catch (e: any) {
this.notificationService.logException(e, 'data_grid_table_generate_sql_error_title');
Expand Down
3 changes: 3 additions & 0 deletions webapp/packages/plugin-ddl-viewer/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,12 @@
"@cloudbeaver/core-connections": "workspace:*",
"@cloudbeaver/core-data-context": "workspace:*",
"@cloudbeaver/core-di": "workspace:*",
"@cloudbeaver/core-events": "workspace:*",
"@cloudbeaver/core-localization": "workspace:*",
"@cloudbeaver/core-navigation-tree": "workspace:*",
"@cloudbeaver/core-resource": "workspace:*",
"@cloudbeaver/core-sdk": "workspace:*",
"@cloudbeaver/core-sql-generator": "workspace:*",
"@cloudbeaver/core-ui": "workspace:*",
"@cloudbeaver/core-utils": "workspace:*",
"@cloudbeaver/core-view": "workspace:*",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* 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_DDL_VIEWER_FULL_DDL = createAction('ddl-viewer-full-ddl', {
label: 'plugin_ddl_viewer_full_ddl',
tooltip: 'plugin_ddl_viewer_full_ddl',
type: 'checkbox',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
* 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 { createDataContext } from '@cloudbeaver/core-data-context';

export interface IDdlViewerFullDdlState {
value: boolean;
loading: boolean;
onChange: (value: boolean) => void;
}

export const DATA_CONTEXT_DDL_VIEWER_FULL_DDL = createDataContext<IDdlViewerFullDdlState>('ddl-full-ddl');
Loading
Loading