@deephaven-enterprise/query-utils 2026.1.37 → 2026.1.39
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/EditableQueryInfoUtils.d.ts +19 -0
- package/dist/EditableQueryInfoUtils.js +53 -0
- package/dist/QueryFinders.d.ts +5 -0
- package/dist/QueryFinders.js +15 -0
- package/dist/QueryPermissions.d.ts +41 -0
- package/dist/QueryPermissions.js +148 -0
- package/dist/QueryScheduler.d.ts +1 -1
- package/dist/QueryStateUtils.d.ts +57 -0
- package/dist/QueryStateUtils.js +187 -0
- package/dist/QueryUtils.d.ts +16 -2
- package/dist/QueryUtils.js +24 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +4 -0
- package/package.json +2 -2
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { EditableQueryInfo, PlainEditableQueryInfo } from '@deephaven-enterprise/jsapi-types';
|
|
2
|
+
import type DraftQuery from './DraftQuery';
|
|
3
|
+
import type { ScriptDraftQuery } from './DraftQuery';
|
|
4
|
+
declare const FIELDS: {
|
|
5
|
+
readonly SCRIPT_LANGUAGE: "scriptLanguage";
|
|
6
|
+
readonly SCRIPT_PATH: "scriptPath";
|
|
7
|
+
readonly SCRIPT_CODE: "scriptCode";
|
|
8
|
+
};
|
|
9
|
+
type QueryContentFields = Pick<EditableQueryInfo, typeof FIELDS.SCRIPT_LANGUAGE | typeof FIELDS.SCRIPT_PATH | typeof FIELDS.SCRIPT_CODE>;
|
|
10
|
+
/**
|
|
11
|
+
* Check if the content fields in the given queries have different values
|
|
12
|
+
* @param queryA Query A
|
|
13
|
+
* @param queryB Query B
|
|
14
|
+
* @returns True, if the content fields don't match
|
|
15
|
+
*/
|
|
16
|
+
export declare function isContentChanged(queryA: QueryContentFields, queryB: QueryContentFields): boolean;
|
|
17
|
+
export declare function getPlainEditableQueryInfo(query: EditableQueryInfo | PlainEditableQueryInfo): PlainEditableQueryInfo;
|
|
18
|
+
export declare function isScriptDraftQuery(query: DraftQuery | ScriptDraftQuery): query is ScriptDraftQuery;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const FIELDS = {
|
|
2
|
+
SCRIPT_LANGUAGE: 'scriptLanguage',
|
|
3
|
+
SCRIPT_PATH: 'scriptPath',
|
|
4
|
+
SCRIPT_CODE: 'scriptCode',
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Check if the content fields in the given queries have different values
|
|
8
|
+
* @param queryA Query A
|
|
9
|
+
* @param queryB Query B
|
|
10
|
+
* @returns True, if the content fields don't match
|
|
11
|
+
*/
|
|
12
|
+
export function isContentChanged(queryA, queryB) {
|
|
13
|
+
return Object.values(FIELDS).some(field => queryA[field] !== queryB[field]);
|
|
14
|
+
}
|
|
15
|
+
export function getPlainEditableQueryInfo(query) {
|
|
16
|
+
// Can't use a spread operator because the EditableQueryInfo JS API object uses property accessors
|
|
17
|
+
return {
|
|
18
|
+
adminGroups: [...query.adminGroups],
|
|
19
|
+
dataMemoryRatio: query.dataMemoryRatio,
|
|
20
|
+
dbServerName: query.dbServerName,
|
|
21
|
+
enabled: query.enabled,
|
|
22
|
+
enableGcLogs: query.enableGcLogs,
|
|
23
|
+
envVars: query.envVars,
|
|
24
|
+
extraClasspaths: query.extraClasspaths,
|
|
25
|
+
heapSize: query.heapSize,
|
|
26
|
+
additionalMemory: query.additionalMemory,
|
|
27
|
+
jvmArgs: query.jvmArgs,
|
|
28
|
+
jvmProfile: query.jvmProfile,
|
|
29
|
+
name: query.name,
|
|
30
|
+
owner: query.owner,
|
|
31
|
+
restartUsers: query.restartUsers,
|
|
32
|
+
scheduling: [...query.scheduling],
|
|
33
|
+
scriptLanguage: query.scriptLanguage,
|
|
34
|
+
scriptPath: query.scriptPath,
|
|
35
|
+
timeout: query.timeout,
|
|
36
|
+
type: query.type,
|
|
37
|
+
typeSpecificFields: query.typeSpecificFields == null ? null : Object.assign({}, query.typeSpecificFields),
|
|
38
|
+
viewerGroups: [...query.viewerGroups],
|
|
39
|
+
replicaCount: query.replicaCount,
|
|
40
|
+
spareCount: query.spareCount,
|
|
41
|
+
assignmentPolicy: query.assignmentPolicy,
|
|
42
|
+
assignmentPolicyParams: query.assignmentPolicyParams,
|
|
43
|
+
scriptCode: query.scriptCode,
|
|
44
|
+
serial: query.serial,
|
|
45
|
+
genericWorkerControl: query.genericWorkerControl,
|
|
46
|
+
kubernetesControl: query.kubernetesControl,
|
|
47
|
+
pythonControl: query.pythonControl,
|
|
48
|
+
workerKind: query.workerKind,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export function isScriptDraftQuery(query) {
|
|
52
|
+
return query.scriptLanguage != null;
|
|
53
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { EnterpriseClient, QueryInfo } from '@deephaven-enterprise/jsapi-types';
|
|
2
|
+
export declare function findQueryByGrpcUrl(client: EnterpriseClient, grpcUrl: string): QueryInfo | undefined;
|
|
3
|
+
export declare function findQueryByName(client: EnterpriseClient, queryName: string): QueryInfo | undefined;
|
|
4
|
+
export declare function findQueryBySerial(client: EnterpriseClient, querySerial: string): QueryInfo | undefined;
|
|
5
|
+
export declare function getQueryNameForSerial(client: EnterpriseClient, querySerial: string): string | null;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export function findQueryByGrpcUrl(client, grpcUrl) {
|
|
2
|
+
return client
|
|
3
|
+
.getKnownConfigs()
|
|
4
|
+
.find(({ designated }) => (designated === null || designated === void 0 ? void 0 : designated.grpcUrl) === grpcUrl);
|
|
5
|
+
}
|
|
6
|
+
export function findQueryByName(client, queryName) {
|
|
7
|
+
return client.getKnownConfigs().find(({ name }) => name === queryName);
|
|
8
|
+
}
|
|
9
|
+
export function findQueryBySerial(client, querySerial) {
|
|
10
|
+
return client.getKnownConfigs().find(({ serial }) => serial === querySerial);
|
|
11
|
+
}
|
|
12
|
+
export function getQueryNameForSerial(client, querySerial) {
|
|
13
|
+
const query = findQueryBySerial(client, querySerial);
|
|
14
|
+
return query ? query.name : null;
|
|
15
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { EnterpriseUser, QueryConfigurationType, QueryInfo, QuerySelectionPermissions } from '@deephaven-enterprise/jsapi-types';
|
|
2
|
+
import DraftQuery from './DraftQuery';
|
|
3
|
+
export declare const RESTART_USERS: Readonly<{
|
|
4
|
+
readonly RESTARTUSERS_ADMIN: 1;
|
|
5
|
+
readonly RESTARTUSERS_ADMINANDVIEWERS: 2;
|
|
6
|
+
readonly RESTARTUSERS_VIEWERSWHENDOWN: 4;
|
|
7
|
+
}>;
|
|
8
|
+
export declare const TYPE_SPECIFIC_FIELD_PARTITION_FORMULA = "PartitionFormula";
|
|
9
|
+
/**
|
|
10
|
+
* Check if the user can view permissions for the query
|
|
11
|
+
* @param user User object to check if can view permissions for the query
|
|
12
|
+
* @param draftQuery The draft query object to check against
|
|
13
|
+
* @returns True if the user can view permissions for the query, false otherwise
|
|
14
|
+
*/
|
|
15
|
+
export declare function canViewPermissions(user: EnterpriseUser, draftQuery: DraftQuery | null): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Get the query configuration types that are displayable and the user is allowed to create
|
|
18
|
+
* @param queryConfigurationTypes Query configuration types to filter
|
|
19
|
+
* @param userGroups Groups the user is in
|
|
20
|
+
* @param isSuperUser Whether the user is a super user
|
|
21
|
+
* @returns Query configuration types that are displayable and the user is allowed to create
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDisplayableQueryTypes(queryConfigurationTypes: QueryConfigurationType[], userGroups: string[], isSuperUser?: boolean): QueryConfigurationType[];
|
|
24
|
+
/**
|
|
25
|
+
* Get the user permissions for selected queries.
|
|
26
|
+
*
|
|
27
|
+
* Based on com.illumon.iris.controller.utils.PersistentQueryConfigTableUtils.SelectedQueryStates#SelectedQueryStates
|
|
28
|
+
*
|
|
29
|
+
* @param user The user to check permissions for
|
|
30
|
+
* @param selectedQueries The queries to check permissions for
|
|
31
|
+
* @returns The query permissions for the user for the selected queries
|
|
32
|
+
*/
|
|
33
|
+
export declare function getQuerySelectionPermissions(user: EnterpriseUser, selectedQueries: QueryInfo[]): QuerySelectionPermissions;
|
|
34
|
+
/**
|
|
35
|
+
* Check if the user is allowed to create a query of this type
|
|
36
|
+
* @param queryConfigurationType Type of query configuration
|
|
37
|
+
* @param userGroups Groups the user is in
|
|
38
|
+
* @param isSuperUser Whether the user is a super user
|
|
39
|
+
* @returns True if the user is allowed to create a query of this type, false otherwise
|
|
40
|
+
*/
|
|
41
|
+
export declare function isAllowedQueryConfigurationType(queryConfigurationType: QueryConfigurationType | undefined, userGroups: string[], isSuperUser?: boolean): boolean;
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import DraftQuery from './DraftQuery';
|
|
2
|
+
import { QueryScheduler } from './QueryScheduler';
|
|
3
|
+
import { checkAllReplicas, isRunningForRestart, isStoppedForPermissions, } from './QueryStateUtils';
|
|
4
|
+
import { getQuerySchedulerType } from './QueryUtils';
|
|
5
|
+
export const RESTART_USERS = Object.freeze({
|
|
6
|
+
RESTARTUSERS_ADMIN: 1,
|
|
7
|
+
RESTARTUSERS_ADMINANDVIEWERS: 2,
|
|
8
|
+
RESTARTUSERS_VIEWERSWHENDOWN: 4,
|
|
9
|
+
});
|
|
10
|
+
export const TYPE_SPECIFIC_FIELD_PARTITION_FORMULA = 'PartitionFormula';
|
|
11
|
+
/**
|
|
12
|
+
* Check if the user can view permissions for the query
|
|
13
|
+
* @param user User object to check if can view permissions for the query
|
|
14
|
+
* @param draftQuery The draft query object to check against
|
|
15
|
+
* @returns True if the user can view permissions for the query, false otherwise
|
|
16
|
+
*/
|
|
17
|
+
export function canViewPermissions(user, draftQuery) {
|
|
18
|
+
if (draftQuery == null) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
// If they own the query or are creating a new one, permissions tab is available only if they have the share permission
|
|
22
|
+
if (draftQuery.serial === DraftQuery.NO_SERIAL ||
|
|
23
|
+
draftQuery.owner === user.operateAs) {
|
|
24
|
+
return user.permissions.canShareQueries;
|
|
25
|
+
}
|
|
26
|
+
// If it's shared with them and they're an admin, show the permissions tab
|
|
27
|
+
if (draftQuery.adminGroups.some(group => user.groups.includes(group))) {
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
// Otherwise, only show it if they can view the shared users
|
|
31
|
+
return user.permissions.canViewQuerySharedUsers;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Get the query configuration types that are displayable and the user is allowed to create
|
|
35
|
+
* @param queryConfigurationTypes Query configuration types to filter
|
|
36
|
+
* @param userGroups Groups the user is in
|
|
37
|
+
* @param isSuperUser Whether the user is a super user
|
|
38
|
+
* @returns Query configuration types that are displayable and the user is allowed to create
|
|
39
|
+
*/
|
|
40
|
+
export function getDisplayableQueryTypes(queryConfigurationTypes, userGroups, isSuperUser = false) {
|
|
41
|
+
return queryConfigurationTypes.filter(queryConfigurationType => queryConfigurationType.isDisplayable &&
|
|
42
|
+
isAllowedQueryConfigurationType(queryConfigurationType, userGroups, isSuperUser));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Get the user permissions for selected queries.
|
|
46
|
+
*
|
|
47
|
+
* Based on com.illumon.iris.controller.utils.PersistentQueryConfigTableUtils.SelectedQueryStates#SelectedQueryStates
|
|
48
|
+
*
|
|
49
|
+
* @param user The user to check permissions for
|
|
50
|
+
* @param selectedQueries The queries to check permissions for
|
|
51
|
+
* @returns The query permissions for the user for the selected queries
|
|
52
|
+
*/
|
|
53
|
+
export function getQuerySelectionPermissions(user, selectedQueries) {
|
|
54
|
+
const permissions = {
|
|
55
|
+
allAdmin: true,
|
|
56
|
+
allOwner: true,
|
|
57
|
+
allRestartable: true,
|
|
58
|
+
allStoppable: true,
|
|
59
|
+
allStopped: true,
|
|
60
|
+
allDisabled: true,
|
|
61
|
+
allEnabled: true,
|
|
62
|
+
allTemporary: true,
|
|
63
|
+
allImportMerge: true,
|
|
64
|
+
readOnlyUser: user.permissions.isQueryViewOnly,
|
|
65
|
+
};
|
|
66
|
+
// If there are no queries selected, then don't assume allTemporary
|
|
67
|
+
if (selectedQueries.length === 0) {
|
|
68
|
+
permissions.allTemporary = false;
|
|
69
|
+
}
|
|
70
|
+
const { isQueryManager } = user.permissions;
|
|
71
|
+
selectedQueries.forEach(query => {
|
|
72
|
+
const isOwner = query.owner === user.operateAs;
|
|
73
|
+
const isAdmin = user.permissions.isSuperUser ||
|
|
74
|
+
user.groups.includes(query.owner) ||
|
|
75
|
+
query.adminGroups.some(group => user.groups.includes(group));
|
|
76
|
+
const isViewer = query.viewerGroups.some(group => user.groups.includes(group));
|
|
77
|
+
const isVisibleToUser = isOwner || isAdmin || isViewer;
|
|
78
|
+
if (!isOwner) {
|
|
79
|
+
permissions.allOwner = false;
|
|
80
|
+
}
|
|
81
|
+
if (!isAdmin) {
|
|
82
|
+
permissions.allAdmin = false;
|
|
83
|
+
}
|
|
84
|
+
if (permissions.allTemporary &&
|
|
85
|
+
getQuerySchedulerType(query.scheduling) !== QueryScheduler.TYPES.TEMPORARY) {
|
|
86
|
+
permissions.allTemporary = false;
|
|
87
|
+
}
|
|
88
|
+
// Check if the query can be restarted based on the restartUsers setting
|
|
89
|
+
switch (query.restartUsers) {
|
|
90
|
+
case RESTART_USERS.RESTARTUSERS_ADMINANDVIEWERS:
|
|
91
|
+
permissions.allRestartable =
|
|
92
|
+
permissions.allRestartable && (isAdmin || isViewer || isQueryManager);
|
|
93
|
+
break;
|
|
94
|
+
case RESTART_USERS.RESTARTUSERS_VIEWERSWHENDOWN:
|
|
95
|
+
if (!isAdmin && !isQueryManager) {
|
|
96
|
+
const isRunning = checkAllReplicas(query, isRunningForRestart);
|
|
97
|
+
permissions.allRestartable =
|
|
98
|
+
permissions.allRestartable && !isRunning && isVisibleToUser;
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
case RESTART_USERS.RESTARTUSERS_ADMIN:
|
|
102
|
+
default:
|
|
103
|
+
permissions.allRestartable =
|
|
104
|
+
permissions.allRestartable && (isAdmin || isQueryManager);
|
|
105
|
+
}
|
|
106
|
+
permissions.allStoppable =
|
|
107
|
+
permissions.allStoppable && (isAdmin || isQueryManager);
|
|
108
|
+
const isStopped = checkAllReplicas(query, isStoppedForPermissions);
|
|
109
|
+
if (!isStopped) {
|
|
110
|
+
permissions.allStopped = false;
|
|
111
|
+
}
|
|
112
|
+
if (query.enabled) {
|
|
113
|
+
permissions.allDisabled = false;
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
permissions.allEnabled = false;
|
|
117
|
+
}
|
|
118
|
+
const { typeSpecificFields } = query;
|
|
119
|
+
if (typeSpecificFields != null) {
|
|
120
|
+
const hasPartitionFormula = Object.hasOwn(typeSpecificFields, TYPE_SPECIFIC_FIELD_PARTITION_FORMULA);
|
|
121
|
+
if (!hasPartitionFormula) {
|
|
122
|
+
permissions.allImportMerge = false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else {
|
|
126
|
+
permissions.allImportMerge = false;
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return permissions;
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Check if the user is allowed to create a query of this type
|
|
133
|
+
* @param queryConfigurationType Type of query configuration
|
|
134
|
+
* @param userGroups Groups the user is in
|
|
135
|
+
* @param isSuperUser Whether the user is a super user
|
|
136
|
+
* @returns True if the user is allowed to create a query of this type, false otherwise
|
|
137
|
+
*/
|
|
138
|
+
export function isAllowedQueryConfigurationType(queryConfigurationType, userGroups, isSuperUser = false) {
|
|
139
|
+
if (queryConfigurationType == null) {
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
if (isSuperUser) {
|
|
143
|
+
return true;
|
|
144
|
+
}
|
|
145
|
+
const { allowedGroups } = queryConfigurationType;
|
|
146
|
+
return (allowedGroups.length === 0 ||
|
|
147
|
+
allowedGroups.some(group => userGroups.includes(group)));
|
|
148
|
+
}
|
package/dist/QueryScheduler.d.ts
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { dh } from '@deephaven/jsapi-types';
|
|
2
|
+
import type { QueryInfo } from '@deephaven-enterprise/jsapi-types';
|
|
3
|
+
import type DraftQuery from './DraftQuery';
|
|
4
|
+
export type QueryInfoMap = Map<string, QueryInfo>;
|
|
5
|
+
export declare const NON_RUNNING_STATUSES: Set<string>;
|
|
6
|
+
/**
|
|
7
|
+
* Determines if the given draft query is a batch query
|
|
8
|
+
* @param type the type of the draft query to check
|
|
9
|
+
* @returns true if the draft query is a batch query, false otherwise
|
|
10
|
+
*/
|
|
11
|
+
export declare function isBatchQueryType(type: string | null | undefined): boolean;
|
|
12
|
+
export declare function isEnableable(queryInfoMap: QueryInfoMap, serial: string): boolean;
|
|
13
|
+
export declare function isDisableable(queryInfoMap: QueryInfoMap, serial: string): boolean;
|
|
14
|
+
export declare function isRestartable(queryInfoMap: QueryInfoMap | undefined, serial: string): boolean;
|
|
15
|
+
export declare function isStartable(queryInfoMap: QueryInfoMap | undefined, serial: string): boolean;
|
|
16
|
+
export declare function isStoppable(queryInfoMap: QueryInfoMap | undefined, serial: string): boolean;
|
|
17
|
+
export declare function isRunning(query: QueryInfo): boolean;
|
|
18
|
+
export declare function isWebClient(query: QueryInfo): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Check if the specified query can be restarted in it's current state.
|
|
21
|
+
* @param status the status of the query replica
|
|
22
|
+
*/
|
|
23
|
+
export declare function isRestartableForEdit(status: unknown): boolean;
|
|
24
|
+
export declare function isRestartableForEditByRow(table?: dh.Table, row?: dh.Row): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if the query has a pending update to be applied. That is, that the currently
|
|
27
|
+
* running version of the query is not the latest saved configuration of the query.
|
|
28
|
+
*
|
|
29
|
+
* @param status the status field of the query replica
|
|
30
|
+
* @param configVersion the version of the query configuration
|
|
31
|
+
* @param runningVersion the currently running version of the query replica
|
|
32
|
+
* @returns true if an update is pending, false otherwise
|
|
33
|
+
*/
|
|
34
|
+
export declare function isQueryUpdatePending(status: unknown, configVersion: unknown, runningVersion?: unknown): boolean;
|
|
35
|
+
export declare function isUpdatePendingForRow(table?: dh.Table, row?: dh.Row): boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Check if this query is allowed to be saved without a restart.
|
|
38
|
+
* Queries are allowed to be saved without restart as long as:
|
|
39
|
+
* - The Owner has not changed
|
|
40
|
+
* - The Admin Groups have not been removed from
|
|
41
|
+
* - The query type has not changed
|
|
42
|
+
* - The scheduler and scheduler properties have not changed
|
|
43
|
+
* - The query is not a Temporary query
|
|
44
|
+
*
|
|
45
|
+
* @param draft the draft query to compare
|
|
46
|
+
* @param queryInfo the original query to compare to
|
|
47
|
+
*/
|
|
48
|
+
export declare function isNoRestartAllowed(draft?: DraftQuery | null, queryInfo?: Partial<QueryInfo> | null): boolean;
|
|
49
|
+
/**
|
|
50
|
+
* Checks if the query is running or executing, which means it can be restarted.
|
|
51
|
+
*
|
|
52
|
+
* @param queryStatus The status of the query to check
|
|
53
|
+
* @returns true if the query is running or executing, false otherwise
|
|
54
|
+
*/
|
|
55
|
+
export declare function isRunningForRestart(queryStatus: string): boolean;
|
|
56
|
+
export declare function isStoppedForPermissions(queryStatus: string): boolean;
|
|
57
|
+
export declare function checkAllReplicas(query: QueryInfo, statusFunction: (status: string) => boolean): boolean;
|
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { QueryColumns } from './QueryColumns';
|
|
2
|
+
import { QueryScheduler } from './QueryScheduler';
|
|
3
|
+
import { QueryStatus } from './QueryStatus';
|
|
4
|
+
import { QueryType } from './QueryType';
|
|
5
|
+
import { WEB_CLIENT_DATA_CORE_CONFIG_TYPE } from './QueryUtils';
|
|
6
|
+
export const NON_RUNNING_STATUSES = new Set([
|
|
7
|
+
QueryStatus.uninitialized,
|
|
8
|
+
QueryStatus.stopped,
|
|
9
|
+
QueryStatus.error,
|
|
10
|
+
QueryStatus.failed,
|
|
11
|
+
QueryStatus.disconnected,
|
|
12
|
+
QueryStatus.completed,
|
|
13
|
+
QueryStatus.none,
|
|
14
|
+
]);
|
|
15
|
+
/**
|
|
16
|
+
* Determines if the given draft query is a batch query
|
|
17
|
+
* @param type the type of the draft query to check
|
|
18
|
+
* @returns true if the draft query is a batch query, false otherwise
|
|
19
|
+
*/
|
|
20
|
+
export function isBatchQueryType(type) {
|
|
21
|
+
return (type === QueryType.RUN_AND_DONE || type === QueryType.RUN_AND_DONE_IMPORT);
|
|
22
|
+
}
|
|
23
|
+
export function isEnableable(queryInfoMap, serial) {
|
|
24
|
+
var _a, _b;
|
|
25
|
+
return (queryInfoMap.has(serial) && !((_b = (_a = queryInfoMap.get(serial)) === null || _a === void 0 ? void 0 : _a.enabled) !== null && _b !== void 0 ? _b : false));
|
|
26
|
+
}
|
|
27
|
+
export function isDisableable(queryInfoMap, serial) {
|
|
28
|
+
var _a;
|
|
29
|
+
if (!queryInfoMap.has(serial)) {
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const queryInfo = queryInfoMap.get(serial);
|
|
33
|
+
if (!queryInfo) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
return (queryInfo.enabled &&
|
|
37
|
+
// Can't disable temporary queries
|
|
38
|
+
!((_a = queryInfo.scheduling) === null || _a === void 0 ? void 0 : _a.includes(QueryScheduler.TOKENS.SCHEDULER_TYPE +
|
|
39
|
+
QueryScheduler.TOKENS.DELIMITER +
|
|
40
|
+
QueryScheduler.TYPES.TEMPORARY)));
|
|
41
|
+
}
|
|
42
|
+
export function isRestartable(queryInfoMap, serial) {
|
|
43
|
+
const query = queryInfoMap === null || queryInfoMap === void 0 ? void 0 : queryInfoMap.get(serial);
|
|
44
|
+
if (query == null)
|
|
45
|
+
return false;
|
|
46
|
+
return (query.enabled === true &&
|
|
47
|
+
query.type !== QueryType.INTERACTIVE_CONSOLE &&
|
|
48
|
+
query.type !== QueryType.SCHEMA_API);
|
|
49
|
+
}
|
|
50
|
+
export function isStartable(queryInfoMap, serial) {
|
|
51
|
+
var _a, _b;
|
|
52
|
+
const query = queryInfoMap === null || queryInfoMap === void 0 ? void 0 : queryInfoMap.get(serial);
|
|
53
|
+
return (isRestartable(queryInfoMap, serial) &&
|
|
54
|
+
query != null &&
|
|
55
|
+
NON_RUNNING_STATUSES.has((_b = (_a = query === null || query === void 0 ? void 0 : query.designated) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : QueryStatus.none));
|
|
56
|
+
}
|
|
57
|
+
export function isStoppable(queryInfoMap, serial) {
|
|
58
|
+
var _a, _b;
|
|
59
|
+
const query = queryInfoMap === null || queryInfoMap === void 0 ? void 0 : queryInfoMap.get(serial);
|
|
60
|
+
if (query == null)
|
|
61
|
+
return false;
|
|
62
|
+
return (query.enabled === true &&
|
|
63
|
+
((_a = query.designated) === null || _a === void 0 ? void 0 : _a.status) !== QueryStatus.stopped &&
|
|
64
|
+
((_b = query.designated) === null || _b === void 0 ? void 0 : _b.status) !== QueryStatus.stopping);
|
|
65
|
+
}
|
|
66
|
+
export function isRunning(query) {
|
|
67
|
+
var _a;
|
|
68
|
+
return ((_a = query.designated) === null || _a === void 0 ? void 0 : _a.status) === QueryStatus.running;
|
|
69
|
+
}
|
|
70
|
+
export function isWebClient(query) {
|
|
71
|
+
return query.type === WEB_CLIENT_DATA_CORE_CONFIG_TYPE;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Check if the specified query can be restarted in it's current state.
|
|
75
|
+
* @param status the status of the query replica
|
|
76
|
+
*/
|
|
77
|
+
export function isRestartableForEdit(status) {
|
|
78
|
+
return (status === QueryStatus.running ||
|
|
79
|
+
status === QueryStatus.initializing ||
|
|
80
|
+
status === QueryStatus.executing);
|
|
81
|
+
}
|
|
82
|
+
export function isRestartableForEditByRow(table, row) {
|
|
83
|
+
if (table == null || row == null) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
const status = row.get(table.findColumn(QueryColumns.STATUS.name));
|
|
87
|
+
return isRestartableForEdit(status);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Check if the query has a pending update to be applied. That is, that the currently
|
|
91
|
+
* running version of the query is not the latest saved configuration of the query.
|
|
92
|
+
*
|
|
93
|
+
* @param status the status field of the query replica
|
|
94
|
+
* @param configVersion the version of the query configuration
|
|
95
|
+
* @param runningVersion the currently running version of the query replica
|
|
96
|
+
* @returns true if an update is pending, false otherwise
|
|
97
|
+
*/
|
|
98
|
+
export function isQueryUpdatePending(status, configVersion, runningVersion) {
|
|
99
|
+
if (runningVersion == null || configVersion == null) {
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
return isRestartableForEdit(status) && configVersion !== runningVersion;
|
|
103
|
+
}
|
|
104
|
+
export function isUpdatePendingForRow(table, row) {
|
|
105
|
+
var _a, _b;
|
|
106
|
+
if (table == null || row == null) {
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
const status = row.get(table.findColumn(QueryColumns.STATUS.name));
|
|
110
|
+
const currentVersion = (_a = row
|
|
111
|
+
.get(table.findColumn(QueryColumns.CURRENTLY_RUNNING_VERSION.name))) === null || _a === void 0 ? void 0 : _a.valueOf();
|
|
112
|
+
const pendingVersion = (_b = row
|
|
113
|
+
.get(table.findColumn(QueryColumns.VERSION.name))) === null || _b === void 0 ? void 0 : _b.valueOf();
|
|
114
|
+
return isQueryUpdatePending(status, pendingVersion, currentVersion);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if this query is allowed to be saved without a restart.
|
|
118
|
+
* Queries are allowed to be saved without restart as long as:
|
|
119
|
+
* - The Owner has not changed
|
|
120
|
+
* - The Admin Groups have not been removed from
|
|
121
|
+
* - The query type has not changed
|
|
122
|
+
* - The scheduler and scheduler properties have not changed
|
|
123
|
+
* - The query is not a Temporary query
|
|
124
|
+
*
|
|
125
|
+
* @param draft the draft query to compare
|
|
126
|
+
* @param queryInfo the original query to compare to
|
|
127
|
+
*/
|
|
128
|
+
export function isNoRestartAllowed(draft, queryInfo) {
|
|
129
|
+
var _a, _b;
|
|
130
|
+
if (!draft ||
|
|
131
|
+
!queryInfo ||
|
|
132
|
+
!draft.isModified ||
|
|
133
|
+
!isRestartableForEdit((_a = queryInfo === null || queryInfo === void 0 ? void 0 : queryInfo.designated) === null || _a === void 0 ? void 0 : _a.status)) {
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
const origSchedulerParams = queryInfo.scheduling;
|
|
137
|
+
const draftSchedulerParams = draft.scheduler.toStringArray();
|
|
138
|
+
if (origSchedulerParams == null ||
|
|
139
|
+
draftSchedulerParams == null ||
|
|
140
|
+
origSchedulerParams.length !== draftSchedulerParams.length) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
const newParams = new Set(draftSchedulerParams);
|
|
144
|
+
if (!origSchedulerParams.every(param => newParams.has(param))) {
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
if (draft.owner !== queryInfo.owner) {
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
if (draft.type !== queryInfo.type) {
|
|
151
|
+
return false;
|
|
152
|
+
}
|
|
153
|
+
if (draft.type === QueryScheduler.TYPES.TEMPORARY) {
|
|
154
|
+
return false;
|
|
155
|
+
}
|
|
156
|
+
const newAdmins = new Set(draft.adminGroups);
|
|
157
|
+
if (!((_b = queryInfo.adminGroups) !== null && _b !== void 0 ? _b : []).every(group => newAdmins.has(group))) {
|
|
158
|
+
return false;
|
|
159
|
+
}
|
|
160
|
+
return true;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Checks if the query is running or executing, which means it can be restarted.
|
|
164
|
+
*
|
|
165
|
+
* @param queryStatus The status of the query to check
|
|
166
|
+
* @returns true if the query is running or executing, false otherwise
|
|
167
|
+
*/
|
|
168
|
+
export function isRunningForRestart(queryStatus) {
|
|
169
|
+
return (queryStatus === QueryStatus.running || queryStatus === QueryStatus.executing);
|
|
170
|
+
}
|
|
171
|
+
export function isStoppedForPermissions(queryStatus) {
|
|
172
|
+
return (queryStatus === QueryStatus.uninitialized ||
|
|
173
|
+
queryStatus === QueryStatus.stopped ||
|
|
174
|
+
queryStatus === QueryStatus.error ||
|
|
175
|
+
queryStatus === QueryStatus.failed ||
|
|
176
|
+
queryStatus === QueryStatus.disconnected ||
|
|
177
|
+
queryStatus === QueryStatus.completed ||
|
|
178
|
+
queryStatus === QueryStatus.none);
|
|
179
|
+
}
|
|
180
|
+
export function checkAllReplicas(query, statusFunction) {
|
|
181
|
+
var _a, _b;
|
|
182
|
+
const replicasAndSpares = [...query.replicas, ...query.spares];
|
|
183
|
+
if (replicasAndSpares.length === 0) {
|
|
184
|
+
return statusFunction((_b = (_a = query.designated) === null || _a === void 0 ? void 0 : _a.status) !== null && _b !== void 0 ? _b : QueryStatus.none);
|
|
185
|
+
}
|
|
186
|
+
return replicasAndSpares.every(replica => { var _a; return statusFunction((_a = replica.status) !== null && _a !== void 0 ? _a : QueryStatus.none); });
|
|
187
|
+
}
|
package/dist/QueryUtils.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import type { dh } from '@deephaven/jsapi-types';
|
|
2
|
-
import type {
|
|
3
|
-
import type { EnterpriseClient, EnterpriseDhType, QueryInfo, QueryVariableDescriptor, ReplicaStatus, UserInfo } from '@deephaven-enterprise/jsapi-types';
|
|
2
|
+
import type { EnterpriseClient, EnterpriseDhType, QueryConfigurationType, QueryInfo, QueryVariableDescriptor, ReplicaStatus, UserInfo } from '@deephaven-enterprise/jsapi-types';
|
|
4
3
|
import { type Brand } from '@deephaven/utils';
|
|
5
4
|
import DraftQuery, { type DraftQueryConstructorObject } from './DraftQuery';
|
|
6
5
|
import type { CorePlusManager } from './CorePlusManager';
|
|
7
6
|
export type ConsoleType = 'groovy' | 'python';
|
|
8
7
|
export type QuerySerial = Brand<'QuerySerial', string>;
|
|
8
|
+
export type UriVariableDescriptor = string;
|
|
9
9
|
export declare const DEFAULT_TEMPORARY_QUERY_AUTO_DELETE_TIMEOUT_MS: 600000;
|
|
10
10
|
export declare const DEFAULT_TEMPORARY_QUERY_TIMEOUT_MS: 60000;
|
|
11
11
|
export declare const INTERACTIVE_CONSOLE_TEMPORARY_QUEUE_NAME: "InteractiveConsoleTemporaryQueue";
|
|
@@ -96,6 +96,20 @@ export declare function getQueryObjectDefinitionByName(query: QueryInfo, name: s
|
|
|
96
96
|
* @returns Resolves to the ReplicaStatus
|
|
97
97
|
*/
|
|
98
98
|
export declare function getWorkerForSlot(query: QueryInfo, slot?: number | null): ReplicaStatus | undefined;
|
|
99
|
+
/**
|
|
100
|
+
* Parses only the scheduling type out of a QueryInfo's scheduling array.
|
|
101
|
+
* Logic is duplicated from QueryScheduler.parseBaseScheduler()
|
|
102
|
+
* @param schedulingArray Array containing scheduling data received from the server
|
|
103
|
+
* @returns The scheduler type, or undefined if not found
|
|
104
|
+
*/
|
|
105
|
+
export declare function getQuerySchedulerType(schedulingArray: readonly string[]): string | undefined;
|
|
106
|
+
/**
|
|
107
|
+
* Check if the specified query configuration type supports community.
|
|
108
|
+
* @param queryConfigurationTypes The map of query configuration types to check against.
|
|
109
|
+
* @param type The type of query configuration to check.
|
|
110
|
+
* @returns True if the specified query configuration type supports community, false otherwise.
|
|
111
|
+
*/
|
|
112
|
+
export declare function hasCommunitySupport(queryConfigurationTypes: ReadonlyMap<string, QueryConfigurationType>, type: string): boolean;
|
|
99
113
|
/**
|
|
100
114
|
* Indicates that a table should be fetched from the WebClientTableFactoryService rather than the query scope.
|
|
101
115
|
*
|
package/dist/QueryUtils.js
CHANGED
|
@@ -169,6 +169,30 @@ export function getWorkerForSlot(query, slot) {
|
|
|
169
169
|
}
|
|
170
170
|
return query.replicas[slot];
|
|
171
171
|
}
|
|
172
|
+
/**
|
|
173
|
+
* Parses only the scheduling type out of a QueryInfo's scheduling array.
|
|
174
|
+
* Logic is duplicated from QueryScheduler.parseBaseScheduler()
|
|
175
|
+
* @param schedulingArray Array containing scheduling data received from the server
|
|
176
|
+
* @returns The scheduler type, or undefined if not found
|
|
177
|
+
*/
|
|
178
|
+
export function getQuerySchedulerType(schedulingArray) {
|
|
179
|
+
const schedulerType = schedulingArray.find(s => s.startsWith(QueryScheduler.TOKENS.SCHEDULER_TYPE));
|
|
180
|
+
if (schedulerType == null)
|
|
181
|
+
return undefined;
|
|
182
|
+
const splitString = schedulerType.split(QueryScheduler.TOKENS.DELIMITER);
|
|
183
|
+
QueryScheduler.validateSplitLength(schedulerType, splitString, 2);
|
|
184
|
+
return splitString[1];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Check if the specified query configuration type supports community.
|
|
188
|
+
* @param queryConfigurationTypes The map of query configuration types to check against.
|
|
189
|
+
* @param type The type of query configuration to check.
|
|
190
|
+
* @returns True if the specified query configuration type supports community, false otherwise.
|
|
191
|
+
*/
|
|
192
|
+
export function hasCommunitySupport(queryConfigurationTypes, type) {
|
|
193
|
+
var _a, _b;
|
|
194
|
+
return (_b = (_a = queryConfigurationTypes.get(type)) === null || _a === void 0 ? void 0 : _a.supportsCommunity) !== null && _b !== void 0 ? _b : false;
|
|
195
|
+
}
|
|
172
196
|
/**
|
|
173
197
|
* Indicates that a table should be fetched from the WebClientTableFactoryService rather than the query scope.
|
|
174
198
|
*
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export * from './CorePlusManager';
|
|
2
2
|
export * from './DraftQuery';
|
|
3
|
+
export * from './EditableQueryInfoUtils';
|
|
4
|
+
export * from './QueryFinders';
|
|
5
|
+
export * from './QueryPermissions';
|
|
6
|
+
export * from './QueryStateUtils';
|
|
3
7
|
export * from './QueryColumns';
|
|
4
8
|
export * from './QueryDisplayType';
|
|
5
9
|
export * from './QueryScheduler';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
export * from './CorePlusManager';
|
|
2
2
|
export * from './DraftQuery';
|
|
3
|
+
export * from './EditableQueryInfoUtils';
|
|
4
|
+
export * from './QueryFinders';
|
|
5
|
+
export * from './QueryPermissions';
|
|
6
|
+
export * from './QueryStateUtils';
|
|
3
7
|
export * from './QueryColumns';
|
|
4
8
|
export * from './QueryDisplayType';
|
|
5
9
|
export * from './QueryScheduler';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@deephaven-enterprise/query-utils",
|
|
3
|
-
"version": "2026.1.
|
|
3
|
+
"version": "2026.1.39",
|
|
4
4
|
"description": "Deephaven Enterprise Query Utils",
|
|
5
5
|
"author": "Deephaven Data Labs LLC",
|
|
6
6
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"@deephaven-enterprise/jsapi-types": "file:../jsapi-types",
|
|
22
22
|
"@deephaven/log": "^0.97.0",
|
|
23
23
|
"@deephaven/utils": "^0.97.0",
|
|
24
|
-
"@internationalized/date": "^3.
|
|
24
|
+
"@internationalized/date": "^3.12.2",
|
|
25
25
|
"nanoid": "^5.1.6"
|
|
26
26
|
},
|
|
27
27
|
"publishConfig": {
|