mirror of
https://github.com/dbeaver/cloudbeaver.git
synced 2026-09-24 16:04:36 +08:00
fix: CB-1609 unexpected requests
This commit is contained in:
+10
-9
@@ -87,8 +87,8 @@ export const ConnectionSelector = observer(function ConnectionSelector() {
|
||||
const drivers = useMapResource(ConnectionSelector, DBDriverResource, CachedMapAllKey, {
|
||||
isActive: () => isEnabled,
|
||||
});
|
||||
|
||||
useMapResource(ConnectionSelector, ConnectionInfoResource, CachedMapAllKey, {
|
||||
|
||||
const connectionInfo = useMapResource(ConnectionSelector, ConnectionInfoResource, CachedMapAllKey, {
|
||||
isActive: () => isEnabled,
|
||||
});
|
||||
|
||||
@@ -96,12 +96,13 @@ export const ConnectionSelector = observer(function ConnectionSelector() {
|
||||
const driver = drivers.resource.get(connection?.driverId || '');
|
||||
|
||||
const contextsActive = getComputed(() => (
|
||||
isEnabled
|
||||
isEnabled
|
||||
&& !connectionInfo.isOutdated()
|
||||
&& connection?.connected === true
|
||||
&& !!connectionSelectorService.activeConnectionId
|
||||
));
|
||||
|
||||
useDataResource(ConnectionSelector, ContainerResource, {
|
||||
useDataResource(ConnectionSelector, ContainerResource, {
|
||||
connectionId: connectionSelectorService.activeConnectionId!,
|
||||
catalogId: connectionSelectorService.activeObjectCatalogId,
|
||||
}, {
|
||||
@@ -152,14 +153,14 @@ export const ConnectionSelector = observer(function ConnectionSelector() {
|
||||
|
||||
return styled(style)(
|
||||
<connection-selector {...use({ isVisible })}>
|
||||
<ContextMenu
|
||||
<ContextMenu
|
||||
menu={connectionsMenu}
|
||||
placement="bottom-end"
|
||||
style={[menuStyles, connectionMenu, topMenuStyles, removeDisableEffect]}
|
||||
disclosure
|
||||
modal
|
||||
>
|
||||
<TopNavButton
|
||||
<TopNavButton
|
||||
title={connection?.name || 'app_topnavbar_connection_schema_manager_not_selected'}
|
||||
icon={driver?.icon}
|
||||
style={[menuStyles, connectionMenu, removeDisableEffect]}
|
||||
@@ -167,19 +168,19 @@ export const ConnectionSelector = observer(function ConnectionSelector() {
|
||||
secondary
|
||||
/>
|
||||
</ContextMenu>
|
||||
<ContextMenu
|
||||
<ContextMenu
|
||||
menu={dataContainerMenu}
|
||||
placement="bottom-end"
|
||||
style={[menuStyles, topMenuStyles]}
|
||||
disclosure
|
||||
modal
|
||||
>
|
||||
<TopNavButton
|
||||
<TopNavButton
|
||||
title={objectContainerName}
|
||||
icon={objectContainerIcon}
|
||||
style={[menuStyles, removeDisableEffect]}
|
||||
menu={
|
||||
connectionSelectorService.isObjectCatalogChangeable
|
||||
connectionSelectorService.isObjectCatalogChangeable
|
||||
|| connectionSelectorService.isObjectSchemaChangeable
|
||||
}
|
||||
secondary
|
||||
|
||||
@@ -30,15 +30,6 @@ export const NodeManagerUtils = {
|
||||
return `database://${connectionId}`;
|
||||
},
|
||||
|
||||
nodeIdToConnectionId(nodeId: string): string {
|
||||
const matches = nodeId.match(/database:\/\/(.*?)(|\/.*)$/);
|
||||
if (!matches) {
|
||||
throw new Error('Not database object');
|
||||
}
|
||||
|
||||
return matches[1];
|
||||
},
|
||||
|
||||
isDatabaseObject(objectId: string): boolean {
|
||||
return /^database:\/\//.test(objectId);
|
||||
},
|
||||
|
||||
@@ -12,6 +12,7 @@ import { useEffect } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button, ErrorMessage, Loader, useClipboard, useErrorDetails, useObservableRef } from '@cloudbeaver/core-blocks';
|
||||
import { ConnectionInfoResource } from '@cloudbeaver/core-connections';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogWrapper, DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
@@ -19,7 +20,6 @@ import { GQLErrorCatcher, SqlDialectInfo } from '@cloudbeaver/core-sdk';
|
||||
import { composes, useStyles } from '@cloudbeaver/core-theming';
|
||||
import { SQLCodeEditorLoader, SqlDialectInfoService } from '@cloudbeaver/plugin-sql-editor';
|
||||
|
||||
import { NodeManagerUtils } from '../NodesManager/NodeManagerUtils';
|
||||
import { SqlGeneratorsResource } from './SqlGeneratorsResource';
|
||||
|
||||
const styles = composes(
|
||||
@@ -73,14 +73,19 @@ export const GeneratedSqlDialog = observer<DialogComponentProps<Payload>>(functi
|
||||
|
||||
const sqlDialectInfoService = useService(SqlDialectInfoService);
|
||||
const sqlGeneratorsResource = useService(SqlGeneratorsResource);
|
||||
const connectionId = NodeManagerUtils.nodeIdToConnectionId(payload.pathId);
|
||||
const connectionInfoResource = useService(ConnectionInfoResource);
|
||||
const connection = connectionInfoResource.getConnectionForNode(payload.pathId);
|
||||
|
||||
const state = useObservableRef(() => ({
|
||||
query: '',
|
||||
loading: true,
|
||||
error: new GQLErrorCatcher(),
|
||||
get dialect(): SqlDialectInfo | undefined {
|
||||
return this.sqlDialectInfoService.getDialectInfo(this.connectionId);
|
||||
if (!this.connection?.connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
return this.sqlDialectInfoService.getDialectInfo(this.connection.id);
|
||||
},
|
||||
async load() {
|
||||
this.error.clear();
|
||||
@@ -96,21 +101,27 @@ export const GeneratedSqlDialog = observer<DialogComponentProps<Payload>>(functi
|
||||
}), {
|
||||
query: observable.ref,
|
||||
loading: observable.ref,
|
||||
connectionId: observable.ref,
|
||||
connection: observable.ref,
|
||||
dialect: computed,
|
||||
}, { connectionId, sqlDialectInfoService });
|
||||
}, { connection, sqlDialectInfoService });
|
||||
|
||||
const error = useErrorDetails(state.error.exception);
|
||||
|
||||
useEffect(() => {
|
||||
state.load();
|
||||
}, []);
|
||||
|
||||
sqlDialectInfoService.loadSqlDialectInfo(connectionId)
|
||||
useEffect(() => {
|
||||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
|
||||
sqlDialectInfoService.loadSqlDialectInfo(connection.id)
|
||||
.catch(exception => {
|
||||
console.error(exception);
|
||||
console.warn(`Can't get dialect for connection: '${connectionId}'. Default dialect will be used`);
|
||||
console.warn(`Can't get dialect for connection: '${connection.id}'. Default dialect will be used`);
|
||||
});
|
||||
}, []);
|
||||
});
|
||||
|
||||
return styled(style)(
|
||||
<CommonDialogWrapper
|
||||
|
||||
@@ -99,14 +99,14 @@ export function useDataResource<
|
||||
async [loadFunctionName](refresh?: boolean) {
|
||||
const { key, includes, loading, resource, actions, prevData } = this;
|
||||
|
||||
if (loading) {
|
||||
if (loading || actions?.active === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const active = await actions?.isActive?.(resource);
|
||||
|
||||
if (active === false || actions?.active === false) {
|
||||
if (active === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -45,17 +45,7 @@ import {
|
||||
} from '@cloudbeaver/core-app';
|
||||
import { coreAuthenticationManifest } from '@cloudbeaver/core-authentication';
|
||||
import { BlocksLocaleService } from '@cloudbeaver/core-blocks';
|
||||
import {
|
||||
ConnectionExecutionContextResource,
|
||||
ConnectionExecutionContextService,
|
||||
ConnectionsManagerService,
|
||||
ConnectionInfoResource,
|
||||
ContainerResource,
|
||||
DBDriverResource,
|
||||
NetworkHandlerResource,
|
||||
DatabaseAuthModelsResource,
|
||||
ConnectionsLocaleService,
|
||||
} from '@cloudbeaver/core-connections';
|
||||
import { coreConnectionsManifest } from '@cloudbeaver/core-connections';
|
||||
import type { PluginManifest } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogService, ContextMenuService } from '@cloudbeaver/core-dialogs';
|
||||
import { NotificationService, ExceptionsCatcherService, EventsSettingsService } from '@cloudbeaver/core-events';
|
||||
@@ -97,19 +87,11 @@ export const coreManifests: PluginManifest[] = [
|
||||
CommonDialogService,
|
||||
SessionExpireWarningDialogService,
|
||||
SessionExpiredDialogService,
|
||||
ConnectionsLocaleService,
|
||||
ConnectionDialogsService,
|
||||
ConnectionSchemaManagerBootstrap,
|
||||
ConnectionSchemaManagerService,
|
||||
ConnectionInfoResource,
|
||||
BlocksLocaleService,
|
||||
AppLocaleService,
|
||||
ContainerResource,
|
||||
DBDriverResource,
|
||||
NetworkHandlerResource,
|
||||
ConnectionExecutionContextResource,
|
||||
ConnectionExecutionContextService,
|
||||
ConnectionsManagerService,
|
||||
ScreenService,
|
||||
AppScreenService,
|
||||
ContextMenuService,
|
||||
@@ -122,7 +104,6 @@ export const coreManifests: PluginManifest[] = [
|
||||
MainMenuService,
|
||||
TopNavService,
|
||||
NavigationTabsService,
|
||||
DatabaseAuthModelsResource,
|
||||
NavNodeContextMenuService,
|
||||
NavigationTreeService,
|
||||
NavNodeManagerService,
|
||||
@@ -147,4 +128,5 @@ export const coreManifests: PluginManifest[] = [
|
||||
coreVersionManifest,
|
||||
coreVersionUpdateManifest,
|
||||
coreRootManifest,
|
||||
coreConnectionsManifest,
|
||||
];
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2022 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 { runInAction } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { ExecutorInterrupter } from '@cloudbeaver/core-executor';
|
||||
import {
|
||||
GraphQLService,
|
||||
CachedMapResource,
|
||||
ResourceKey,
|
||||
ResourceKeyUtils,
|
||||
CachedMapAllKey,
|
||||
resourceKeyList,
|
||||
SqlDialectInfo
|
||||
} from '@cloudbeaver/core-sdk';
|
||||
|
||||
import type { IConnectionExecutionContextInfo } from './ConnectionExecutionContext/IConnectionExecutionContextInfo';
|
||||
import { ConnectionInfoResource } from './ConnectionInfoResource';
|
||||
|
||||
export type ConnectionDialect = SqlDialectInfo;
|
||||
|
||||
@injectable()
|
||||
export class ConnectionDialectResource extends CachedMapResource<string, ConnectionDialect> {
|
||||
constructor(
|
||||
private readonly graphQLService: GraphQLService,
|
||||
connectionInfoResource: ConnectionInfoResource,
|
||||
) {
|
||||
super();
|
||||
this.sync(connectionInfoResource);
|
||||
this.addAlias(CachedMapAllKey, () => resourceKeyList(connectionInfoResource.keys));
|
||||
this.before(ExecutorInterrupter.interrupter(key => !connectionInfoResource.isConnected(key)));
|
||||
}
|
||||
|
||||
async formatScript(context: IConnectionExecutionContextInfo, query: string): Promise<string> {
|
||||
const result = await this.graphQLService.sdk.formatSqlQuery({
|
||||
connectionId: context.connectionId,
|
||||
contextId: context.id,
|
||||
query,
|
||||
});
|
||||
|
||||
return result.query;
|
||||
}
|
||||
|
||||
async loadAll(): Promise<Map<string, ConnectionDialect>> {
|
||||
await this.load(CachedMapAllKey);
|
||||
return this.data;
|
||||
}
|
||||
|
||||
protected async loader(key: ResourceKey<string>, includes: string[]): Promise<Map<string, ConnectionDialect>> {
|
||||
const all = ResourceKeyUtils.includes(key, CachedMapAllKey);
|
||||
key = this.transformParam(key);
|
||||
|
||||
const dialects: Map<string, ConnectionDialect> = new Map();
|
||||
|
||||
await ResourceKeyUtils.forEachAsync(key, async key => {
|
||||
const connectionId = key;
|
||||
|
||||
const { dialect } = await this.graphQLService.sdk.querySqlDialectInfo({
|
||||
connectionId,
|
||||
...this.getIncludesMap(connectionId, includes),
|
||||
});
|
||||
|
||||
if (!dialect) {
|
||||
throw new Error('Dialect not found');
|
||||
}
|
||||
|
||||
dialects.set(connectionId, dialect);
|
||||
});
|
||||
|
||||
runInAction(() => {
|
||||
if (all) {
|
||||
this.resetIncludes();
|
||||
this.data.clear();
|
||||
}
|
||||
|
||||
for (const [connectionId, dialect] of dialects) {
|
||||
this.dataSet(connectionId, dialect);
|
||||
}
|
||||
});
|
||||
|
||||
return this.data;
|
||||
}
|
||||
}
|
||||
@@ -52,9 +52,9 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
|
||||
readonly onConnectionClose: ISyncExecutor<Connection>;
|
||||
|
||||
private sessionUpdate: boolean;
|
||||
private nodeIdMap: Map<string, string>;
|
||||
private readonly nodeIdMap: Map<string, string>;
|
||||
constructor(
|
||||
private graphQLService: GraphQLService,
|
||||
private readonly graphQLService: GraphQLService,
|
||||
sessionDataResource: SessionDataResource,
|
||||
permissionsResource: PermissionsResource
|
||||
) {
|
||||
@@ -89,6 +89,13 @@ export class ConnectionInfoResource extends CachedMapResource<string, Connection
|
||||
});
|
||||
}
|
||||
|
||||
isConnected(key: string): boolean;
|
||||
isConnected(key: ResourceKeyList<string>): boolean;
|
||||
isConnected(key: ResourceKey<string>): boolean;
|
||||
isConnected(key: ResourceKey<string>): boolean {
|
||||
return ResourceKeyUtils.every(key, connectionId => this.get(connectionId)?.connected ?? false);
|
||||
}
|
||||
|
||||
getConnectionForNode(nodeId: string): Connection | undefined {
|
||||
const indexOfConnectionPart = nodeId.indexOf('/', 11);
|
||||
const connectionPart = nodeId.slice(
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
import { observable } from 'mobx';
|
||||
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { ExecutorInterrupter } from '@cloudbeaver/core-executor';
|
||||
import {
|
||||
GraphQLService,
|
||||
CachedDataResource,
|
||||
@@ -70,6 +71,7 @@ string
|
||||
}));
|
||||
|
||||
this.preloadResource(connectionInfoResource, () => CachedMapAllKey);
|
||||
this.before(ExecutorInterrupter.interrupter(key => !connectionInfoResource.isConnected(key.connectionId)));
|
||||
|
||||
this.connectionInfoResource.onItemDelete.addHandler(
|
||||
key => ResourceKeyUtils.forEach(key, key => this.data.delete(key))
|
||||
|
||||
@@ -7,6 +7,7 @@ export * from './ConnectionExecutionContext/IConnectionExecutionContextInfo';
|
||||
export * from './extensions/IConnectionProvider';
|
||||
export * from './extensions/IConnectionSetter';
|
||||
export * from './ConnectionsManagerService';
|
||||
export * from './ConnectionDialectResource';
|
||||
export * from './ConnectionInfoResource';
|
||||
export * from './EConnectionFeature';
|
||||
export * from './ContainerResource';
|
||||
@@ -20,3 +21,4 @@ export * from './NetworkHandlerResource';
|
||||
export * from './useConnectionInfo';
|
||||
export * from './useDBDriver';
|
||||
export * from './USER_NAME_PROPERTY_ID';
|
||||
export { manifest as coreConnectionsManifest } from './manifest';
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* CloudBeaver - Cloud Database Manager
|
||||
* Copyright (C) 2020-2022 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 type { PluginManifest } from '@cloudbeaver/core-di';
|
||||
|
||||
import { ConnectionDialectResource } from './ConnectionDialectResource';
|
||||
import { ConnectionExecutionContextResource } from './ConnectionExecutionContext/ConnectionExecutionContextResource';
|
||||
import { ConnectionExecutionContextService } from './ConnectionExecutionContext/ConnectionExecutionContextService';
|
||||
import { ConnectionInfoResource } from './ConnectionInfoResource';
|
||||
import { ConnectionsLocaleService } from './ConnectionsLocaleService';
|
||||
import { ConnectionsManagerService } from './ConnectionsManagerService';
|
||||
import { ContainerResource } from './ContainerResource';
|
||||
import { DatabaseAuthModelsResource } from './DatabaseAuthModelsResource';
|
||||
import { DBDriverResource } from './DBDriverResource';
|
||||
import { NetworkHandlerResource } from './NetworkHandlerResource';
|
||||
|
||||
|
||||
export const manifest: PluginManifest = {
|
||||
info: {
|
||||
name: 'Core Connections',
|
||||
},
|
||||
|
||||
providers: [
|
||||
ConnectionExecutionContextResource,
|
||||
ConnectionExecutionContextService,
|
||||
ConnectionsManagerService,
|
||||
ConnectionInfoResource,
|
||||
ContainerResource,
|
||||
ConnectionsLocaleService,
|
||||
DatabaseAuthModelsResource,
|
||||
DBDriverResource,
|
||||
NetworkHandlerResource,
|
||||
ConnectionDialectResource,
|
||||
],
|
||||
};
|
||||
@@ -35,11 +35,11 @@ export const ExecutorInterrupter = {
|
||||
};
|
||||
},
|
||||
|
||||
interrupter(flag: () => Promise<boolean> | boolean) {
|
||||
return async (data: any, contexts: IExecutionContextProvider<any>): Promise<void> => {
|
||||
interrupter<T>(flag: (data: T) => Promise<boolean> | boolean) {
|
||||
return async (data: T, contexts: IExecutionContextProvider<T>): Promise<void> => {
|
||||
const interrupt = contexts.getContext(ExecutorInterrupter.interruptContext);
|
||||
|
||||
if ((await flag())) {
|
||||
if ((await flag(data))) {
|
||||
interrupt.interrupt();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -134,8 +134,8 @@ export abstract class CachedMapResource<
|
||||
|
||||
getException(key: TKey): Error | null;
|
||||
getException(key: ResourceKeyList<TKey>): Array<Error | null>;
|
||||
getException(key: ResourceKey<TKey>): Array<Error | null>| Error | null;
|
||||
getException(key: ResourceKey<TKey>): Array<Error | null>| Error | null {
|
||||
getException(key: ResourceKey<TKey>): Array<Error | null> | Error | null;
|
||||
getException(key: ResourceKey<TKey>): Array<Error | null> | Error | null {
|
||||
key = this.transformParam(key);
|
||||
return ResourceKeyUtils.map(key, key => this.metadata.get(key).exception);
|
||||
}
|
||||
@@ -201,11 +201,11 @@ export abstract class CachedMapResource<
|
||||
(
|
||||
(key === undefined ? this.scheduler.executing : this.scheduler.isExecuting(key))
|
||||
) && !this.outdateWaitList.some(param => this.includes(key!, param))) {
|
||||
this.outdateWaitList.push(key as ResourceKey<TKey>);
|
||||
this.outdateWaitList.push(key!);
|
||||
return;
|
||||
}
|
||||
|
||||
this.markOutdatedSync(key as ResourceKey<TKey>);
|
||||
this.markOutdatedSync(key!);
|
||||
}
|
||||
|
||||
cleanError(): void
|
||||
@@ -267,8 +267,8 @@ export abstract class CachedMapResource<
|
||||
|
||||
get(key: TKey): TValue | undefined;
|
||||
get(key: ResourceKeyList<TKey>): Array<TValue | undefined>;
|
||||
get(key: ResourceKey<TKey>): Array<TValue | undefined>| TValue | undefined;
|
||||
get(key: ResourceKey<TKey>): Array<TValue | undefined>| TValue | undefined {
|
||||
get(key: ResourceKey<TKey>): Array<TValue | undefined> | TValue | undefined;
|
||||
get(key: ResourceKey<TKey>): Array<TValue | undefined> | TValue | undefined {
|
||||
key = this.transformParam(key);
|
||||
return ResourceKeyUtils.map(key, key => this.data.get(key));
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@ import { useEffect } from 'react';
|
||||
import styled, { css } from 'reshadow';
|
||||
|
||||
import { Button, useClipboard, useObservableRef } from '@cloudbeaver/core-blocks';
|
||||
import { ConnectionExecutionContextService } from '@cloudbeaver/core-connections';
|
||||
import { useService } from '@cloudbeaver/core-di';
|
||||
import { CommonDialogWrapper, DialogComponentProps } from '@cloudbeaver/core-dialogs';
|
||||
import { useTranslate } from '@cloudbeaver/core-localization';
|
||||
@@ -19,7 +20,6 @@ import type { SqlDialectInfo } from '@cloudbeaver/core-sdk';
|
||||
import { SQLCodeEditorLoader, SqlDialectInfoService } from '@cloudbeaver/plugin-sql-editor';
|
||||
|
||||
import type { IDatabaseDataModel } from '../DatabaseDataModel/IDatabaseDataModel';
|
||||
import type { IDatabaseDataResult } from '../DatabaseDataModel/IDatabaseDataResult';
|
||||
|
||||
export const dialogStyle = css`
|
||||
footer {
|
||||
@@ -46,7 +46,7 @@ const styles = css`
|
||||
|
||||
interface Payload {
|
||||
script: string;
|
||||
model: IDatabaseDataModel<any, IDatabaseDataResult>;
|
||||
model: IDatabaseDataModel;
|
||||
}
|
||||
|
||||
export const ScriptPreviewDialog = observer<DialogComponentProps<Payload>>(function ScriptPreviewDialog({
|
||||
@@ -56,8 +56,10 @@ export const ScriptPreviewDialog = observer<DialogComponentProps<Payload>>(funct
|
||||
const translate = useTranslate();
|
||||
const copy = useClipboard();
|
||||
|
||||
const connectionExecutionContextService = useService(ConnectionExecutionContextService);
|
||||
const sqlDialectInfoService = useService(SqlDialectInfoService);
|
||||
const connectionId = payload.model.source.executionContext?.context?.connectionId;
|
||||
const context = connectionExecutionContextService.get(payload.model.source.executionContext?.context?.id ?? '');
|
||||
const connectionId = context?.context?.connectionId;
|
||||
|
||||
const dialect = useObservableRef(() => ({
|
||||
get dialect(): SqlDialectInfo | undefined {
|
||||
|
||||
@@ -6,35 +6,21 @@
|
||||
* you may not use this file except in compliance with the License.
|
||||
*/
|
||||
|
||||
import { observable, makeObservable } from 'mobx';
|
||||
|
||||
import type { IConnectionExecutionContextInfo } from '@cloudbeaver/core-connections';
|
||||
import { ConnectionDialectResource, IConnectionExecutionContextInfo } from '@cloudbeaver/core-connections';
|
||||
import { injectable } from '@cloudbeaver/core-di';
|
||||
import { NotificationService } from '@cloudbeaver/core-events';
|
||||
import { GraphQLService, SqlDialectInfo } from '@cloudbeaver/core-sdk';
|
||||
import type { SqlDialectInfo } from '@cloudbeaver/core-sdk';
|
||||
|
||||
@injectable()
|
||||
export class SqlDialectInfoService {
|
||||
private dialectInfo = new Map<string, SqlDialectInfo>();
|
||||
|
||||
constructor(
|
||||
private graphQLService: GraphQLService,
|
||||
private notificationService: NotificationService
|
||||
) {
|
||||
makeObservable<SqlDialectInfoService, 'dialectInfo'>(this, {
|
||||
dialectInfo: observable,
|
||||
});
|
||||
}
|
||||
private readonly connectionDialectResource: ConnectionDialectResource,
|
||||
private readonly notificationService: NotificationService
|
||||
) { }
|
||||
|
||||
async formatScript(context: IConnectionExecutionContextInfo, query: string): Promise<string> {
|
||||
try {
|
||||
const result = await this.graphQLService.sdk.formatSqlQuery({
|
||||
connectionId: context.connectionId,
|
||||
contextId: context.id,
|
||||
query,
|
||||
});
|
||||
|
||||
return result.query;
|
||||
return await this.connectionDialectResource.formatScript(context, query);
|
||||
} catch (error) {
|
||||
this.notificationService.logException(error, 'Failed to format script');
|
||||
}
|
||||
@@ -42,14 +28,13 @@ export class SqlDialectInfoService {
|
||||
}
|
||||
|
||||
getDialectInfo(connectionId: string): SqlDialectInfo | undefined {
|
||||
return this.dialectInfo.get(connectionId);
|
||||
return this.connectionDialectResource.get(connectionId);
|
||||
}
|
||||
|
||||
async loadSqlDialectInfo(connectionId: string): Promise<SqlDialectInfo | undefined> {
|
||||
if (!this.dialectInfo.has(connectionId)) {
|
||||
if (!this.connectionDialectResource.has(connectionId)) {
|
||||
try {
|
||||
const result = await this.graphQLService.sdk.querySqlDialectInfo({ connectionId });
|
||||
this.dialectInfo.set(connectionId, result.dialect!);
|
||||
return this.connectionDialectResource.load(connectionId);
|
||||
} catch (error) {
|
||||
this.notificationService.logException(error, 'Failed to load SqlDialectInfo');
|
||||
}
|
||||
|
||||
@@ -151,12 +151,16 @@ export class SqlEditorController implements IInitializableController, IDestructi
|
||||
|
||||
this.reactionDisposer = autorun(() => {
|
||||
if (this.state.executionContext) {
|
||||
this.sqlDialectInfoService
|
||||
.loadSqlDialectInfo(this.state.executionContext.connectionId)
|
||||
.then(async dialect => {
|
||||
this.parser.setDialect(dialect || null);
|
||||
await this.updateParserScriptsThrottle();
|
||||
});
|
||||
const context = this.connectionExecutionContextService.get(this.state.executionContext.id);
|
||||
|
||||
if (context) {
|
||||
this.sqlDialectInfoService
|
||||
.loadSqlDialectInfo(this.state.executionContext.connectionId)
|
||||
.then(async dialect => {
|
||||
this.parser.setDialect(dialect || null);
|
||||
await this.updateParserScriptsThrottle();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -297,8 +301,8 @@ export class SqlEditorController implements IInitializableController, IDestructi
|
||||
private async updateParserScripts() {
|
||||
const connectionId = this.state.executionContext?.connectionId;
|
||||
const script = this.parser.actualScript;
|
||||
|
||||
if (!connectionId) {
|
||||
|
||||
if (!connectionId) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -307,7 +311,7 @@ export class SqlEditorController implements IInitializableController, IDestructi
|
||||
connectionId,
|
||||
script
|
||||
);
|
||||
|
||||
|
||||
if (this.parser.actualScript === script) {
|
||||
this.parser.setQueries(queries);
|
||||
this.highlightActiveQuery();
|
||||
|
||||
Reference in New Issue
Block a user