Skip to content

Commit 0433f89

Browse files
authored
Merge pull request #2750 from github/starcke/fetch-queries-out-of-view
Starcke/fetch queries out of view
2 parents c82f00e + 9543ab3 commit 0433f89

3 files changed

Lines changed: 95 additions & 89 deletions

File tree

extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts

Lines changed: 3 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,8 @@ import { runFlowModelQueries } from "./flow-model-queries";
2626
import { promptImportGithubDatabase } from "../databases/database-fetcher";
2727
import { App } from "../common/app";
2828
import { showResolvableLocation } from "../databases/local-databases/locations";
29-
import { decodeBqrsToExternalApiUsages } from "./bqrs";
3029
import { redactableError } from "../common/errors";
31-
import { readQueryResults, runQuery } from "./external-api-usage-queries";
30+
import { runExternalApiQueries } from "./external-api-usage-queries";
3231
import { ExternalApiUsage, Usage } from "./external-api-usage";
3332
import { ModeledMethod } from "./modeled-method";
3433
import { ExtensionPack } from "./shared/extension-pack";
@@ -304,7 +303,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
304303
async (progress) => {
305304
try {
306305
const cancellationTokenSource = new CancellationTokenSource();
307-
const queryResult = await runQuery(this.mode, {
306+
const queryResult = await runExternalApiQueries(this.mode, {
308307
cliServer: this.cliServer,
309308
queryRunner: this.queryRunner,
310309
databaseItem: this.databaseItem,
@@ -316,28 +315,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
316315
if (!queryResult) {
317316
return;
318317
}
319-
320-
progress({
321-
message: "Decoding results",
322-
step: 1100,
323-
maxStep: 1500,
324-
});
325-
326-
const bqrsChunk = await readQueryResults({
327-
cliServer: this.cliServer,
328-
bqrsPath: queryResult.outputDir.bqrsPath,
329-
});
330-
if (!bqrsChunk) {
331-
return;
332-
}
333-
334-
progress({
335-
message: "Finalizing results",
336-
step: 1450,
337-
maxStep: 1500,
338-
});
339-
340-
this.externalApiUsages = decodeBqrsToExternalApiUsages(bqrsChunk);
318+
this.externalApiUsages = queryResult;
341319

342320
await this.postMessage({
343321
t: "setExternalApiUsages",

extensions/ql-vscode/src/data-extensions-editor/external-api-usage-queries.ts

Lines changed: 43 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
1-
import { CoreCompletedQuery, QueryRunner } from "../query-server";
1+
import { QueryRunner } from "../query-server";
22
import { getOnDiskWorkspaceFolders } from "../common/vscode/workspace-folders";
33
import { extLogger } from "../common/logging/vscode";
4-
import { showAndLogExceptionWithTelemetry, TeeLogger } from "../common/logging";
4+
import { showAndLogExceptionWithTelemetry } from "../common/logging";
55
import { CancellationToken } from "vscode";
66
import { CodeQLCliServer } from "../codeql-cli/cli";
77
import { DatabaseItem } from "../databases/local-databases";
88
import { ProgressCallback } from "../common/vscode/progress";
9-
import { QueryResultType } from "../query-server/new-messages";
109
import { redactableError } from "../common/errors";
1110
import { telemetryListener } from "../common/vscode/telemetry";
1211
import { join } from "path";
1312
import { Mode } from "./shared/mode";
1413
import { writeFile } from "fs-extra";
1514
import { QueryLanguage } from "../common/query-language";
1615
import { fetchExternalApiQueries } from "./queries";
16+
import { ExternalApiUsage } from "./external-api-usage";
17+
import { runQuery } from "../local-queries/run-query";
18+
import { decodeBqrsToExternalApiUsages } from "./bqrs";
1719

1820
type RunQueryOptions = {
19-
cliServer: Pick<CodeQLCliServer, "resolveQlpacks">;
20-
queryRunner: Pick<QueryRunner, "createQueryRun" | "logger">;
21-
databaseItem: Pick<DatabaseItem, "contents" | "databaseUri" | "language">;
21+
cliServer: CodeQLCliServer;
22+
queryRunner: QueryRunner;
23+
databaseItem: DatabaseItem;
2224
queryStorageDir: string;
2325
queryDir: string;
2426

@@ -56,7 +58,7 @@ export async function prepareExternalApiQuery(
5658
return true;
5759
}
5860

59-
export async function runQuery(
61+
export async function runExternalApiQueries(
6062
mode: Mode,
6163
{
6264
cliServer,
@@ -67,7 +69,7 @@ export async function runQuery(
6769
progress,
6870
token,
6971
}: RunQueryOptions,
70-
): Promise<CoreCompletedQuery | undefined> {
72+
): Promise<ExternalApiUsage[] | undefined> {
7173
// The below code is temporary to allow for rapid prototyping of the queries. Once the queries are stabilized, we will
7274
// move these queries into the `github/codeql` repository and use them like any other contextual (e.g. AST) queries.
7375
// This is intentionally not pretty code, as it will be removed soon.
@@ -79,44 +81,47 @@ export async function runQuery(
7981
await cliServer.resolveQlpacks(additionalPacks, true),
8082
);
8183

82-
const queryFile = join(
83-
queryDir,
84-
`FetchExternalApis${mode.charAt(0).toUpperCase() + mode.slice(1)}Mode.ql`,
85-
);
84+
const queryPath = join(queryDir, queryNameFromMode(mode));
8685

87-
const queryRun = queryRunner.createQueryRun(
88-
databaseItem.databaseUri.fsPath,
89-
{
90-
queryPath: queryFile,
91-
quickEvalPosition: undefined,
92-
quickEvalCountOnly: false,
93-
},
94-
false,
95-
getOnDiskWorkspaceFolders(),
96-
extensionPacks,
86+
// Run the actual query
87+
const completedQuery = await runQuery({
88+
cliServer,
89+
queryRunner,
90+
databaseItem,
91+
queryPath,
9792
queryStorageDir,
98-
undefined,
99-
undefined,
100-
);
101-
102-
const completedQuery = await queryRun.evaluate(
93+
additionalPacks,
94+
extensionPacks,
10395
progress,
10496
token,
105-
new TeeLogger(queryRunner.logger, queryRun.outputDir.logPath),
106-
);
97+
});
10798

108-
if (completedQuery.resultType !== QueryResultType.SUCCESS) {
109-
void showAndLogExceptionWithTelemetry(
110-
extLogger,
111-
telemetryListener,
112-
redactableError`External API usage query failed: ${
113-
completedQuery.message ?? "No message"
114-
}`,
115-
);
99+
if (!completedQuery) {
100+
return;
101+
}
102+
103+
// Read the results and covert to internal representation
104+
progress({
105+
message: "Decoding results",
106+
step: 1100,
107+
maxStep: 1500,
108+
});
109+
110+
const bqrsChunk = await readQueryResults({
111+
cliServer,
112+
bqrsPath: completedQuery.outputDir.bqrsPath,
113+
});
114+
if (!bqrsChunk) {
116115
return;
117116
}
118117

119-
return completedQuery;
118+
progress({
119+
message: "Finalizing results",
120+
step: 1450,
121+
maxStep: 1500,
122+
});
123+
124+
return decodeBqrsToExternalApiUsages(bqrsChunk);
120125
}
121126

122127
type GetResultsOptions = {

extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/external-api-usage-query.test.ts

Lines changed: 49 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,25 @@
11
import {
22
readQueryResults,
3-
runQuery,
3+
runExternalApiQueries,
44
} from "../../../../src/data-extensions-editor/external-api-usage-queries";
55
import { createMockLogger } from "../../../__mocks__/loggerMock";
6-
import { DatabaseKind } from "../../../../src/databases/local-databases";
6+
import {
7+
DatabaseItem,
8+
DatabaseKind,
9+
} from "../../../../src/databases/local-databases";
710
import { dirSync, file } from "tmp-promise";
811
import { QueryResultType } from "../../../../src/query-server/new-messages";
912
import { fetchExternalApiQueries } from "../../../../src/data-extensions-editor/queries";
1013
import * as log from "../../../../src/common/logging/notifications";
1114
import { RedactableError } from "../../../../src/common/errors";
1215
import { showAndLogExceptionWithTelemetry } from "../../../../src/common/logging";
1316
import { QueryLanguage } from "../../../../src/common/query-language";
14-
import { mockedUri } from "../../utils/mocking.helpers";
17+
import { mockedObject, mockedUri } from "../../utils/mocking.helpers";
1518
import { Mode } from "../../../../src/data-extensions-editor/shared/mode";
19+
import { join } from "path";
20+
import { CodeQLCliServer } from "../../../../src/codeql-cli/cli";
21+
import { QueryRunner } from "../../../../src/query-server";
22+
import { QueryOutputDir } from "../../../../src/run-queries-shared";
1623

1724
describe("external api usage query", () => {
1825
describe("runQuery", () => {
@@ -27,39 +34,44 @@ describe("external api usage query", () => {
2734
typeof showAndLogExceptionWithTelemetry
2835
> = jest.spyOn(log, "showAndLogExceptionWithTelemetry");
2936

30-
const logPath = (await file()).path;
37+
const outputDir = new QueryOutputDir(join((await file()).path, "1"));
3138

3239
const query = fetchExternalApiQueries[language];
3340
if (!query) {
3441
throw new Error(`No query found for language ${language}`);
3542
}
3643

3744
const options = {
38-
cliServer: {
45+
cliServer: mockedObject<CodeQLCliServer>({
3946
resolveQlpacks: jest.fn().mockResolvedValue({
4047
"my/extensions": "/a/b/c/",
4148
}),
42-
},
43-
queryRunner: {
49+
packPacklist: jest
50+
.fn()
51+
.mockResolvedValue([
52+
"/a/b/c/qlpack.yml",
53+
"/a/b/c/qlpack.lock.yml",
54+
"/a/b/c/qlpack2.yml",
55+
]),
56+
}),
57+
queryRunner: mockedObject<QueryRunner>({
4458
createQueryRun: jest.fn().mockReturnValue({
4559
evaluate: jest.fn().mockResolvedValue({
4660
resultType: QueryResultType.CANCELLATION,
4761
}),
48-
outputDir: {
49-
logPath,
50-
},
62+
outputDir,
5163
}),
5264
logger: createMockLogger(),
53-
},
54-
databaseItem: {
65+
}),
66+
databaseItem: mockedObject<DatabaseItem>({
5567
databaseUri: mockedUri("/a/b/c/src.zip"),
5668
contents: {
5769
kind: DatabaseKind.Database,
5870
name: "foo",
5971
datasetUri: mockedUri(),
6072
},
6173
language,
62-
},
74+
}),
6375
queryStorageDir: "/tmp/queries",
6476
queryDir,
6577
progress: jest.fn(),
@@ -69,7 +81,9 @@ describe("external api usage query", () => {
6981
},
7082
};
7183

72-
expect(await runQuery(Mode.Application, options)).toBeUndefined();
84+
expect(
85+
await runExternalApiQueries(Mode.Application, options),
86+
).toBeUndefined();
7387
expect(showAndLogExceptionWithTelemetrySpy).toHaveBeenCalledWith(
7488
expect.anything(),
7589
undefined,
@@ -78,39 +92,48 @@ describe("external api usage query", () => {
7892
});
7993

8094
it("should run query for random language", async () => {
81-
const logPath = (await file()).path;
95+
const outputDir = new QueryOutputDir(join((await file()).path, "1"));
8296

8397
const query = fetchExternalApiQueries[language];
8498
if (!query) {
8599
throw new Error(`No query found for language ${language}`);
86100
}
87101

88102
const options = {
89-
cliServer: {
103+
cliServer: mockedObject<CodeQLCliServer>({
90104
resolveQlpacks: jest.fn().mockResolvedValue({
91105
"my/extensions": "/a/b/c/",
92106
}),
93-
},
94-
queryRunner: {
107+
packPacklist: jest
108+
.fn()
109+
.mockResolvedValue([
110+
"/a/b/c/qlpack.yml",
111+
"/a/b/c/qlpack.lock.yml",
112+
"/a/b/c/qlpack2.yml",
113+
]),
114+
bqrsInfo: jest.fn().mockResolvedValue({
115+
"result-sets": [],
116+
}),
117+
}),
118+
queryRunner: mockedObject<QueryRunner>({
95119
createQueryRun: jest.fn().mockReturnValue({
96120
evaluate: jest.fn().mockResolvedValue({
97121
resultType: QueryResultType.SUCCESS,
122+
outputDir,
98123
}),
99-
outputDir: {
100-
logPath,
101-
},
124+
outputDir,
102125
}),
103126
logger: createMockLogger(),
104-
},
105-
databaseItem: {
127+
}),
128+
databaseItem: mockedObject<DatabaseItem>({
106129
databaseUri: mockedUri("/a/b/c/src.zip"),
107130
contents: {
108131
kind: DatabaseKind.Database,
109132
name: "foo",
110133
datasetUri: mockedUri(),
111134
},
112135
language,
113-
},
136+
}),
114137
queryStorageDir: "/tmp/queries",
115138
queryDir,
116139
progress: jest.fn(),
@@ -120,9 +143,9 @@ describe("external api usage query", () => {
120143
},
121144
};
122145

123-
const result = await runQuery(Mode.Framework, options);
146+
const result = await runExternalApiQueries(Mode.Framework, options);
124147

125-
expect(result?.resultType).toEqual(QueryResultType.SUCCESS);
148+
expect(result).not.toBeUndefined;
126149

127150
expect(options.cliServer.resolveQlpacks).toHaveBeenCalledTimes(1);
128151
expect(options.cliServer.resolveQlpacks).toHaveBeenCalledWith([], true);

0 commit comments

Comments
 (0)