mirror of https://github.com/apache/druid.git
Web console: correctly cancel JSON shaped SQL queries (#12134)
* misc fixes * type typo
This commit is contained in:
parent
7c17341caa
commit
2a41b7bffa
|
@ -5107,7 +5107,7 @@ license_category: binary
|
||||||
module: web-console
|
module: web-console
|
||||||
license_name: Apache License version 2.0
|
license_name: Apache License version 2.0
|
||||||
copyright: Palantir Technologies
|
copyright: Palantir Technologies
|
||||||
version: 3.26.1
|
version: 3.31.0
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -5574,7 +5574,7 @@ license_category: binary
|
||||||
module: web-console
|
module: web-console
|
||||||
license_name: Apache License version 2.0
|
license_name: Apache License version 2.0
|
||||||
copyright: Imply Data
|
copyright: Imply Data
|
||||||
version: 0.14.4
|
version: 0.14.6
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -5992,7 +5992,7 @@ license_category: binary
|
||||||
module: web-console
|
module: web-console
|
||||||
license_name: MIT License
|
license_name: MIT License
|
||||||
copyright: Javier Blanco
|
copyright: Javier Blanco
|
||||||
version: 1.0.6
|
version: 1.0.7
|
||||||
license_file_path: licenses/bin/path-parse.MIT
|
license_file_path: licenses/bin/path-parse.MIT
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
@ -3057,9 +3057,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@blueprintjs/icons": {
|
"@blueprintjs/icons": {
|
||||||
"version": "3.26.1",
|
"version": "3.31.0",
|
||||||
"resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.26.1.tgz",
|
"resolved": "https://registry.npmjs.org/@blueprintjs/icons/-/icons-3.31.0.tgz",
|
||||||
"integrity": "sha512-qxAnqhzt5WqYuWN+7p3Pk7bOrhj56YXzD8n79Met8+VIQ14IpKnxr7YAYmNB5X/dVweqXpEk6tKyUjnDjBhulw==",
|
"integrity": "sha512-6pXhHC8zEvoDKN5KNsIHNuCRKsemmRbXNv1jweB95VaFzR1M+Mik+Qi+13Wd+VtZrzes2ZcWttIeyuK91NoLCw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"classnames": "^2.2",
|
"classnames": "^2.2",
|
||||||
"tslib": "~1.13.0"
|
"tslib": "~1.13.0"
|
||||||
|
@ -8091,9 +8091,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"druid-query-toolkit": {
|
"druid-query-toolkit": {
|
||||||
"version": "0.14.4",
|
"version": "0.14.6",
|
||||||
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.14.4.tgz",
|
"resolved": "https://registry.npmjs.org/druid-query-toolkit/-/druid-query-toolkit-0.14.6.tgz",
|
||||||
"integrity": "sha512-PmD5vwoHQxNxZ8E8vRdHvh5OjuvA+yHD5dhiKDzIzPtnFiwRHLJKyOLSQ6rmN1VAKbOdU4JCZIzPFUB8bEMBAQ==",
|
"integrity": "sha512-Dv/oXD80+2SEV8J8m8Ib6giIU5fWcHK0hr/l04NbZMCpZhX/9NLDWW9HEQltRp9EyD3UEHbkoMChcbyRPAgc8w==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"tslib": "^2.2.0"
|
"tslib": "^2.2.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@blueprintjs/core": "^3.45.0",
|
"@blueprintjs/core": "^3.45.0",
|
||||||
"@blueprintjs/datetime": "^3.23.4",
|
"@blueprintjs/datetime": "^3.23.4",
|
||||||
"@blueprintjs/icons": "^3.26.1",
|
"@blueprintjs/icons": "^3.31.0",
|
||||||
"@blueprintjs/popover2": "^0.10.1",
|
"@blueprintjs/popover2": "^0.10.1",
|
||||||
"ace-builds": "^1.4.13",
|
"ace-builds": "^1.4.13",
|
||||||
"axios": "^0.21.4",
|
"axios": "^0.21.4",
|
||||||
|
@ -79,7 +79,7 @@
|
||||||
"d3-axis": "^1.0.12",
|
"d3-axis": "^1.0.12",
|
||||||
"d3-scale": "^3.2.0",
|
"d3-scale": "^3.2.0",
|
||||||
"d3-selection": "^1.4.0",
|
"d3-selection": "^1.4.0",
|
||||||
"druid-query-toolkit": "^0.14.4",
|
"druid-query-toolkit": "^0.14.6",
|
||||||
"file-saver": "^2.0.2",
|
"file-saver": "^2.0.2",
|
||||||
"fontsource-open-sans": "^3.0.9",
|
"fontsource-open-sans": "^3.0.9",
|
||||||
"has-own-prop": "^2.0.0",
|
"has-own-prop": "^2.0.0",
|
||||||
|
|
|
@ -148,6 +148,7 @@ export const JsonInput = React.memo(function JsonInput(props: JsonInputProps) {
|
||||||
enableLiveAutocompletion: false,
|
enableLiveAutocompletion: false,
|
||||||
showLineNumbers: false,
|
showLineNumbers: false,
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
|
newLineMode: 'unix' as any, // newLineMode is incorrectly assumed to be boolean in the typings
|
||||||
}}
|
}}
|
||||||
style={{}}
|
style={{}}
|
||||||
onLoad={editor => {
|
onLoad={editor => {
|
||||||
|
|
|
@ -66,6 +66,7 @@ export const SpecDialog = React.memo(function SpecDialog(props: SpecDialogProps)
|
||||||
setOptions={{
|
setOptions={{
|
||||||
showLineNumbers: true,
|
showLineNumbers: true,
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
|
newLineMode: 'unix' as any, // newLineMode is incorrectly assumed to be boolean in the typings
|
||||||
}}
|
}}
|
||||||
style={{}}
|
style={{}}
|
||||||
placeholder="{ JSON spec... }"
|
placeholder="{ JSON spec... }"
|
||||||
|
|
|
@ -29,16 +29,16 @@ describe('StatusDialog', () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
it('filters data that contains input', () => {
|
it('filters data that contains input', () => {
|
||||||
const data = [
|
const row = [
|
||||||
'org.apache.druid.common.gcp.GcpModule',
|
'org.apache.druid.common.gcp.GcpModule',
|
||||||
'org.apache.druid.common.aws.AWSModule',
|
'org.apache.druid.common.aws.AWSModule',
|
||||||
'io.imply.druid.UtilityBeltModule',
|
'org.apache.druid.OtherModule',
|
||||||
];
|
];
|
||||||
|
|
||||||
expect(anywhereMatcher({ id: '0', value: 'common' }, data)).toEqual(true);
|
expect(anywhereMatcher({ id: '0', value: 'common' }, row)).toEqual(true);
|
||||||
expect(anywhereMatcher({ id: '1', value: 'common' }, data)).toEqual(true);
|
expect(anywhereMatcher({ id: '1', value: 'common' }, row)).toEqual(true);
|
||||||
expect(anywhereMatcher({ id: '0', value: 'org' }, data)).toEqual(true);
|
expect(anywhereMatcher({ id: '0', value: 'org' }, row)).toEqual(true);
|
||||||
expect(anywhereMatcher({ id: '1', value: 'org' }, data)).toEqual(true);
|
expect(anywhereMatcher({ id: '1', value: 'org' }, row)).toEqual(true);
|
||||||
expect(anywhereMatcher({ id: '2', value: 'common' }, data)).toEqual(false);
|
expect(anywhereMatcher({ id: '2', value: 'common' }, row)).toEqual(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -28,7 +28,7 @@ import {
|
||||||
} from './ingestion-spec';
|
} from './ingestion-spec';
|
||||||
|
|
||||||
describe('ingestion-spec', () => {
|
describe('ingestion-spec', () => {
|
||||||
it('upgrades / downgrades task spec', () => {
|
it('upgrades / downgrades task spec 1', () => {
|
||||||
const oldTaskSpec = {
|
const oldTaskSpec = {
|
||||||
type: 'index_parallel',
|
type: 'index_parallel',
|
||||||
spec: {
|
spec: {
|
||||||
|
@ -36,7 +36,7 @@ describe('ingestion-spec', () => {
|
||||||
type: 'index_parallel',
|
type: 'index_parallel',
|
||||||
firehose: {
|
firehose: {
|
||||||
type: 'http',
|
type: 'http',
|
||||||
uris: ['https://static.imply.io/data/wikipedia.json.gz'],
|
uris: ['https://website.com/wikipedia.json.gz'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
tuningConfig: {
|
tuningConfig: {
|
||||||
|
@ -157,7 +157,46 @@ describe('ingestion-spec', () => {
|
||||||
},
|
},
|
||||||
inputSource: {
|
inputSource: {
|
||||||
type: 'http',
|
type: 'http',
|
||||||
uris: ['https://static.imply.io/data/wikipedia.json.gz'],
|
uris: ['https://website.com/wikipedia.json.gz'],
|
||||||
|
},
|
||||||
|
type: 'index_parallel',
|
||||||
|
},
|
||||||
|
tuningConfig: {
|
||||||
|
type: 'index_parallel',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
type: 'index_parallel',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('upgrades / downgrades task spec (without parser)', () => {
|
||||||
|
const oldTaskSpec = {
|
||||||
|
type: 'index_parallel',
|
||||||
|
ioConfig: {
|
||||||
|
type: 'index_parallel',
|
||||||
|
firehose: { type: 'http', uris: ['https://website.com/wikipedia.json.gz'] },
|
||||||
|
},
|
||||||
|
tuningConfig: { type: 'index_parallel' },
|
||||||
|
dataSchema: {
|
||||||
|
dataSource: 'new-data-source',
|
||||||
|
granularitySpec: { type: 'uniform', segmentGranularity: 'DAY', queryGranularity: 'HOUR' },
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(upgradeSpec(oldTaskSpec)).toEqual({
|
||||||
|
spec: {
|
||||||
|
dataSchema: {
|
||||||
|
dataSource: 'new-data-source',
|
||||||
|
granularitySpec: {
|
||||||
|
queryGranularity: 'HOUR',
|
||||||
|
segmentGranularity: 'DAY',
|
||||||
|
type: 'uniform',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
ioConfig: {
|
||||||
|
inputSource: {
|
||||||
|
type: 'http',
|
||||||
|
uris: ['https://website.com/wikipedia.json.gz'],
|
||||||
},
|
},
|
||||||
type: 'index_parallel',
|
type: 'index_parallel',
|
||||||
},
|
},
|
||||||
|
@ -364,7 +403,7 @@ describe('spec utils', () => {
|
||||||
type: 'index_parallel',
|
type: 'index_parallel',
|
||||||
inputSource: {
|
inputSource: {
|
||||||
type: 'http',
|
type: 'http',
|
||||||
uris: ['https://static.imply.io/data/wikipedia.json.gz'],
|
uris: ['https://website.com/wikipedia.json.gz'],
|
||||||
},
|
},
|
||||||
inputFormat: {
|
inputFormat: {
|
||||||
type: 'json',
|
type: 'json',
|
||||||
|
@ -439,7 +478,7 @@ describe('spec utils', () => {
|
||||||
"inputSource": Object {
|
"inputSource": Object {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"uris": Array [
|
"uris": Array [
|
||||||
"https://static.imply.io/data/wikipedia.json.gz",
|
"https://website.com/wikipedia.json.gz",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"type": "index_parallel",
|
"type": "index_parallel",
|
||||||
|
@ -490,7 +529,7 @@ describe('spec utils', () => {
|
||||||
"inputSource": Object {
|
"inputSource": Object {
|
||||||
"type": "http",
|
"type": "http",
|
||||||
"uris": Array [
|
"uris": Array [
|
||||||
"https://static.imply.io/data/wikipedia.json.gz",
|
"https://website.com/wikipedia.json.gz",
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
"type": "index_parallel",
|
"type": "index_parallel",
|
||||||
|
|
|
@ -1325,7 +1325,7 @@ export interface TuningConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PartitionsSpec {
|
export interface PartitionsSpec {
|
||||||
type: 'string';
|
type: string;
|
||||||
|
|
||||||
// For type: dynamic
|
// For type: dynamic
|
||||||
maxTotalRows?: number;
|
maxTotalRows?: number;
|
||||||
|
@ -2261,8 +2261,7 @@ export function upgradeSpec(spec: any): Partial<IngestionSpec> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deepGet(spec, 'spec.dataSchema.parser')) return spec;
|
// Upgrade firehose if exists
|
||||||
|
|
||||||
if (deepGet(spec, 'spec.ioConfig.firehose')) {
|
if (deepGet(spec, 'spec.ioConfig.firehose')) {
|
||||||
switch (deepGet(spec, 'spec.ioConfig.firehose.type')) {
|
switch (deepGet(spec, 'spec.ioConfig.firehose.type')) {
|
||||||
case 'static-s3':
|
case 'static-s3':
|
||||||
|
@ -2278,6 +2277,8 @@ export function upgradeSpec(spec: any): Partial<IngestionSpec> {
|
||||||
spec = deepMove(spec, 'spec.ioConfig.firehose', 'spec.ioConfig.inputSource');
|
spec = deepMove(spec, 'spec.ioConfig.firehose', 'spec.ioConfig.inputSource');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Decompose parser if exists
|
||||||
|
if (deepGet(spec, 'spec.dataSchema.parser')) {
|
||||||
spec = deepMove(
|
spec = deepMove(
|
||||||
spec,
|
spec,
|
||||||
'spec.dataSchema.parser.parseSpec.timestampSpec',
|
'spec.dataSchema.parser.parseSpec.timestampSpec',
|
||||||
|
@ -2291,6 +2292,7 @@ export function upgradeSpec(spec: any): Partial<IngestionSpec> {
|
||||||
spec = deepMove(spec, 'spec.dataSchema.parser.parseSpec', 'spec.ioConfig.inputFormat');
|
spec = deepMove(spec, 'spec.dataSchema.parser.parseSpec', 'spec.ioConfig.inputFormat');
|
||||||
spec = deepDelete(spec, 'spec.dataSchema.parser');
|
spec = deepDelete(spec, 'spec.dataSchema.parser');
|
||||||
spec = deepMove(spec, 'spec.ioConfig.inputFormat.format', 'spec.ioConfig.inputFormat.type');
|
spec = deepMove(spec, 'spec.ioConfig.inputFormat.format', 'spec.ioConfig.inputFormat.type');
|
||||||
|
}
|
||||||
|
|
||||||
return spec;
|
return spec;
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,8 +57,17 @@ export function parseHtmlError(htmlStr: string): string | undefined {
|
||||||
.replace(/>/g, '>');
|
.replace(/>/g, '>');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDruidErrorObject(e: any): DruidErrorResponse | string {
|
||||||
|
if (e.response) {
|
||||||
|
// This is a direct axios response error
|
||||||
|
return e.response.data || {};
|
||||||
|
} else {
|
||||||
|
return e; // Assume the error was passed in directly
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export function getDruidErrorMessage(e: any): string {
|
export function getDruidErrorMessage(e: any): string {
|
||||||
const data: DruidErrorResponse | string = (e.response || {}).data || {};
|
const data = getDruidErrorObject(e);
|
||||||
switch (typeof data) {
|
switch (typeof data) {
|
||||||
case 'object':
|
case 'object':
|
||||||
return (
|
return (
|
||||||
|
@ -241,7 +250,7 @@ export class DruidError extends Error {
|
||||||
if (axios.isCancel(e)) {
|
if (axios.isCancel(e)) {
|
||||||
this.canceled = true;
|
this.canceled = true;
|
||||||
} else {
|
} else {
|
||||||
const data: DruidErrorResponse | string = (e.response || {}).data || {};
|
const data = getDruidErrorObject(e);
|
||||||
|
|
||||||
let druidErrorResponse: DruidErrorResponse;
|
let druidErrorResponse: DruidErrorResponse;
|
||||||
switch (typeof data) {
|
switch (typeof data) {
|
||||||
|
|
|
@ -40,7 +40,7 @@ import {
|
||||||
import { Api } from '../singletons';
|
import { Api } from '../singletons';
|
||||||
|
|
||||||
import { getDruidErrorMessage, queryDruidRune } from './druid-query';
|
import { getDruidErrorMessage, queryDruidRune } from './druid-query';
|
||||||
import { arrangeWithPrefixSuffix, EMPTY_ARRAY, filterMap, oneOf } from './general';
|
import { arrangeWithPrefixSuffix, EMPTY_ARRAY, filterMap } from './general';
|
||||||
import { deepGet, deepSet } from './object-change';
|
import { deepGet, deepSet } from './object-change';
|
||||||
|
|
||||||
const SAMPLER_URL = `/druid/indexer/v1/sampler`;
|
const SAMPLER_URL = `/druid/indexer/v1/sampler`;
|
||||||
|
@ -65,7 +65,6 @@ export interface SampleResponse {
|
||||||
export type CacheRows = Record<string, any>[];
|
export type CacheRows = Record<string, any>[];
|
||||||
|
|
||||||
export interface SampleResponseWithExtraInfo extends SampleResponse {
|
export interface SampleResponseWithExtraInfo extends SampleResponse {
|
||||||
queryGranularity?: any;
|
|
||||||
rollup?: boolean;
|
rollup?: boolean;
|
||||||
columns?: Record<string, any>;
|
columns?: Record<string, any>;
|
||||||
aggregators?: Record<string, any>;
|
aggregators?: Record<string, any>;
|
||||||
|
@ -236,26 +235,6 @@ function fixSamplerTypes(sampleSpec: SampleSpec): SampleSpec {
|
||||||
return sampleSpec;
|
return sampleSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanupQueryGranularity(queryGranularity: any): any {
|
|
||||||
let queryGranularityType = deepGet(queryGranularity, 'type');
|
|
||||||
if (typeof queryGranularityType !== 'string') return queryGranularity;
|
|
||||||
queryGranularityType = queryGranularityType.toUpperCase();
|
|
||||||
|
|
||||||
const knownGranularity = oneOf(
|
|
||||||
queryGranularityType,
|
|
||||||
'NONE',
|
|
||||||
'SECOND',
|
|
||||||
'MINUTE',
|
|
||||||
'HOUR',
|
|
||||||
'DAY',
|
|
||||||
'WEEK',
|
|
||||||
'MONTH',
|
|
||||||
'YEAR',
|
|
||||||
);
|
|
||||||
|
|
||||||
return knownGranularity ? queryGranularityType : queryGranularity;
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function sampleForConnect(
|
export async function sampleForConnect(
|
||||||
spec: Partial<IngestionSpec>,
|
spec: Partial<IngestionSpec>,
|
||||||
sampleStrategy: SampleStrategy,
|
sampleStrategy: SampleStrategy,
|
||||||
|
@ -305,14 +284,11 @@ export async function sampleForConnect(
|
||||||
intervals: [deepGet(ioConfig, 'inputSource.interval')],
|
intervals: [deepGet(ioConfig, 'inputSource.interval')],
|
||||||
merge: true,
|
merge: true,
|
||||||
lenientAggregatorMerge: true,
|
lenientAggregatorMerge: true,
|
||||||
analysisTypes: ['timestampSpec', 'queryGranularity', 'aggregators', 'rollup'],
|
analysisTypes: ['aggregators', 'rollup'],
|
||||||
});
|
});
|
||||||
|
|
||||||
if (Array.isArray(segmentMetadataResponse) && segmentMetadataResponse.length === 1) {
|
if (Array.isArray(segmentMetadataResponse) && segmentMetadataResponse.length === 1) {
|
||||||
const segmentMetadataResponse0 = segmentMetadataResponse[0];
|
const segmentMetadataResponse0 = segmentMetadataResponse[0];
|
||||||
samplerResponse.queryGranularity = cleanupQueryGranularity(
|
|
||||||
segmentMetadataResponse0.queryGranularity,
|
|
||||||
);
|
|
||||||
samplerResponse.rollup = segmentMetadataResponse0.rollup;
|
samplerResponse.rollup = segmentMetadataResponse0.rollup;
|
||||||
samplerResponse.columns = segmentMetadataResponse0.columns;
|
samplerResponse.columns = segmentMetadataResponse0.columns;
|
||||||
samplerResponse.aggregators = segmentMetadataResponse0.aggregators;
|
samplerResponse.aggregators = segmentMetadataResponse0.aggregators;
|
||||||
|
|
|
@ -28,7 +28,7 @@ describe('utils', () => {
|
||||||
type: 'index_parallel',
|
type: 'index_parallel',
|
||||||
inputSource: {
|
inputSource: {
|
||||||
type: 'http',
|
type: 'http',
|
||||||
uris: ['https://static.imply.io/data/wikipedia.json.gz'],
|
uris: ['https://website.com/wikipedia.json.gz'],
|
||||||
},
|
},
|
||||||
inputFormat: {
|
inputFormat: {
|
||||||
type: 'json',
|
type: 'json',
|
||||||
|
|
|
@ -1277,13 +1277,11 @@ export class LoadDataView extends React.PureComponent<LoadDataViewProps, LoadDat
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (inputData.queryGranularity) {
|
|
||||||
newSpec = deepSet(
|
newSpec = deepSet(
|
||||||
newSpec,
|
newSpec,
|
||||||
'spec.dataSchema.granularitySpec.queryGranularity',
|
'spec.dataSchema.granularitySpec.queryGranularity',
|
||||||
inputData.queryGranularity,
|
'none',
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
if (inputData.columns) {
|
if (inputData.columns) {
|
||||||
const aggregators = inputData.aggregators || {};
|
const aggregators = inputData.aggregators || {};
|
||||||
|
|
|
@ -262,6 +262,7 @@ export class QueryInput extends React.PureComponent<QueryInputProps, QueryInputS
|
||||||
enableLiveAutocompletion: !runeMode,
|
enableLiveAutocompletion: !runeMode,
|
||||||
showLineNumbers: true,
|
showLineNumbers: true,
|
||||||
tabSize: 2,
|
tabSize: 2,
|
||||||
|
newLineMode: 'unix' as any, // newLineMode is incorrectly assumed to be boolean in the typings
|
||||||
}}
|
}}
|
||||||
style={{}}
|
style={{}}
|
||||||
placeholder="SELECT * FROM ..."
|
placeholder="SELECT * FROM ..."
|
||||||
|
|
|
@ -114,6 +114,11 @@ export class QueryView extends React.PureComponent<QueryViewProps, QueryViewStat
|
||||||
return queryString.trim().startsWith('{');
|
return queryString.trim().startsWith('{');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static isSql(query: any): boolean {
|
||||||
|
if (typeof query === 'string') return true;
|
||||||
|
return typeof query.query === 'string';
|
||||||
|
}
|
||||||
|
|
||||||
static validRune(queryString: string): boolean {
|
static validRune(queryString: string): boolean {
|
||||||
try {
|
try {
|
||||||
Hjson.parse(queryString);
|
Hjson.parse(queryString);
|
||||||
|
@ -204,20 +209,20 @@ export class QueryView extends React.PureComponent<QueryViewProps, QueryViewStat
|
||||||
cancelToken,
|
cancelToken,
|
||||||
): Promise<QueryResult> => {
|
): Promise<QueryResult> => {
|
||||||
const { queryString, queryContext, wrapQueryLimit } = queryWithContext;
|
const { queryString, queryContext, wrapQueryLimit } = queryWithContext;
|
||||||
const isSql = !QueryView.isJsonLike(queryString);
|
const query = QueryView.isJsonLike(queryString) ? Hjson.parse(queryString) : queryString;
|
||||||
const query = isSql ? queryString : Hjson.parse(queryString);
|
const isSql = QueryView.isSql(query);
|
||||||
const context = { ...queryContext, ...(mandatoryQueryContext || {}) };
|
const extraQueryContext = { ...queryContext, ...(mandatoryQueryContext || {}) };
|
||||||
|
|
||||||
if (typeof wrapQueryLimit !== 'undefined') {
|
if (isSql && typeof wrapQueryLimit !== 'undefined') {
|
||||||
context.sqlOuterLimit = wrapQueryLimit + 1;
|
extraQueryContext.sqlOuterLimit = wrapQueryLimit + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const queryIdKey = isSql ? 'sqlQueryId' : 'queryId';
|
const queryIdKey = isSql ? 'sqlQueryId' : 'queryId';
|
||||||
// Look for the queryId in the JSON itself (if native) or in the context object.
|
// Look for an existing queryId in the JSON itself or in the extra context object.
|
||||||
let cancelQueryId = (isSql ? undefined : query.context?.queryId) || context[queryIdKey];
|
let cancelQueryId = query.context?.[queryIdKey] || extraQueryContext[queryIdKey];
|
||||||
if (!cancelQueryId) {
|
if (!cancelQueryId) {
|
||||||
// If the queryId (sqlQueryId) is not explicitly set on the context generate one so it is possible to cancel the query.
|
// If the queryId (sqlQueryId) is not explicitly set on the context generate one thus making it possible to cancel the query.
|
||||||
cancelQueryId = context[queryIdKey] = uuidv4();
|
cancelQueryId = extraQueryContext[queryIdKey] = uuidv4();
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelToken.promise
|
void cancelToken.promise
|
||||||
|
@ -231,7 +236,7 @@ export class QueryView extends React.PureComponent<QueryViewProps, QueryViewStat
|
||||||
try {
|
try {
|
||||||
return await queryRunner.runQuery({
|
return await queryRunner.runQuery({
|
||||||
query,
|
query,
|
||||||
extraQueryContext: context,
|
extraQueryContext,
|
||||||
cancelToken,
|
cancelToken,
|
||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
Loading…
Reference in New Issue