Skip to content

Commit e121e05

Browse files
authored
Merge pull request #4211 from paldepind/bqrs-diff-result-sets
Use `bqrs diff` for all cases in the compare view when `--result-sets` is supported
2 parents aaeb6ca + 01d4bb5 commit e121e05

File tree

7 files changed

+52
-42
lines changed

7 files changed

+52
-42
lines changed

extensions/ql-vscode/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
- Rename command "CodeQL: Trim Overlay Base Cache" to "CodeQL: Trim Cache to Overlay-Base" for consistency with "CodeQL: Warm Overlay-Base Cache for [...]" commands. [#4204](https://github.com/github/vscode-codeql/pull/4204)
66
- Deprecate the setting (`codeQL.runningQueries.saveCache`) that aggressively saved intermediate results to the disk cache. [#4210](https://github.com/github/vscode-codeql/pull/4210)
7+
- The CodeQL CLI's `bqrs diff` command is now used in the "Compare Results" view. This makes the view faster, more accurate, and fixes a bug where it would error when comparing a large amount of results. [#4194](https://github.com/github/vscode-codeql/pull/4194) & [#4211](https://github.com/github/vscode-codeql/pull/4211)
78

89
## 1.17.6 - 24 October 2025
910

extensions/ql-vscode/src/codeql-cli/cli-version.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ interface VersionResult {
1111

1212
export interface CliFeatures {
1313
queryServerRunQueries?: boolean;
14+
bqrsDiffResultSets?: boolean;
1415
}
1516

1617
export interface VersionAndFeatures {

extensions/ql-vscode/src/codeql-cli/cli.ts

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,12 @@ import { ExitCodeError, getCliError } from "./cli-errors";
4141
import { UserCancellationException } from "../common/vscode/progress";
4242
import type { LanguageClient } from "vscode-languageclient/node";
4343

44+
/**
45+
* The oldest version of the CLI that we support. This is used to determine
46+
* whether to show a warning about the CLI being too old on startup.
47+
*/
48+
export const OLDEST_SUPPORTED_CLI_VERSION = new SemVer("2.20.7");
49+
4450
/**
4551
* The version of the SARIF format that we are using.
4652
*/
@@ -205,6 +211,7 @@ interface BqrsDecodeOptions {
205211

206212
interface BqrsDiffOptions {
207213
retainResultSets?: string[];
214+
resultSets?: Array<[string, string]>;
208215
}
209216

210217
type OnLineCallback = (line: string) => Promise<string | undefined>;
@@ -273,8 +280,6 @@ export class CodeQLCliServer implements Disposable {
273280
/** Path to current codeQL executable, or undefined if not running yet. */
274281
codeQlPath: string | undefined;
275282

276-
cliConstraints = new CliVersionConstraint(this);
277-
278283
/**
279284
* When set to true, ignore some modal popups and assume user has clicked "yes".
280285
*/
@@ -1279,6 +1284,12 @@ export class CodeQLCliServer implements Disposable {
12791284
...(options?.retainResultSets
12801285
? ["--retain-result-sets", options.retainResultSets.join(",")]
12811286
: []),
1287+
...(options?.resultSets
1288+
? options.resultSets.flatMap(([left, right]) => [
1289+
"--result-sets",
1290+
`${left},${right}`,
1291+
])
1292+
: []),
12821293
bqrsPath1,
12831294
bqrsPath2,
12841295
],
@@ -1816,6 +1827,11 @@ export class CodeQLCliServer implements Disposable {
18161827
public async setUseExtensionPacks(useExtensionPacks: boolean) {
18171828
await this.cliConfig.setUseExtensionPacks(useExtensionPacks);
18181829
}
1830+
1831+
/** Checks if the CLI supports a specific feature. */
1832+
public async supportsFeature(feature: keyof CliFeatures): Promise<boolean> {
1833+
return (await this.getFeatures())[feature] === true;
1834+
}
18191835
}
18201836

18211837
/**
@@ -1922,17 +1938,3 @@ export function shouldDebugQueryServer() {
19221938
function shouldDebugCliServer() {
19231939
return isEnvTrue("CLI_SERVER_JAVA_DEBUG");
19241940
}
1925-
1926-
export class CliVersionConstraint {
1927-
// The oldest version of the CLI that we support. This is used to determine
1928-
// whether to show a warning about the CLI being too old on startup.
1929-
public static OLDEST_SUPPORTED_CLI_VERSION = new SemVer("2.20.7");
1930-
1931-
constructor(private readonly cli: CodeQLCliServer) {
1932-
/**/
1933-
}
1934-
1935-
async supportsQueryServerRunQueries(): Promise<boolean> {
1936-
return (await this.cli.getFeatures()).queryServerRunQueries === true;
1937-
}
1938-
}

extensions/ql-vscode/src/compare/compare-view.ts

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import type { CodeQLCliServer } from "../codeql-cli/cli";
1919
import type { DatabaseManager } from "../databases/local-databases";
2020
import { jumpToLocation } from "../databases/local-databases/locations";
2121
import type { BqrsInfo, BqrsResultSetSchema } from "../common/bqrs-cli-types";
22+
// eslint-disable-next-line import/no-deprecated
2223
import resultsDiff from "./resultsDiff";
2324
import type { CompletedLocalQueryInfo } from "../query-results";
2425
import { assertNever, getErrorMessage } from "../common/helpers-pure";
@@ -403,13 +404,18 @@ export class CompareView extends AbstractWebview<
403404
toResultSetName,
404405
);
405406

406-
// If the result set names are the same, we use `bqrs diff`. This is more
407-
// efficient, but we can't use it in general as it does not support
408-
// comparing different result sets.
409-
if (fromResultSetName === toResultSetName) {
407+
// We use `bqrs diff` when the `--result-sets` option is supported, or when
408+
// the result set names are the same (in which case we don't need the
409+
// option).
410+
const supportsBqrsDiffResultSets =
411+
await this.cliServer.supportsFeature("bqrsDiffResultSets");
412+
if (supportsBqrsDiffResultSets || fromResultSetName === toResultSetName) {
410413
const { uniquePath1, uniquePath2, cleanup } =
411414
await this.cliServer.bqrsDiff(fromPath, toPath, {
412415
retainResultSets: [],
416+
resultSets: supportsBqrsDiffResultSets
417+
? [[fromResultSetName, toResultSetName]]
418+
: [],
413419
});
414420
try {
415421
const uniqueInfo1 = await this.cliServer.bqrsInfo(uniquePath1);
@@ -443,10 +449,13 @@ export class CompareView extends AbstractWebview<
443449
await cleanup();
444450
}
445451
} else {
452+
// Legacy code path: Perform the diff directly in the extension when we
453+
// can't use `bqrs diff`.
446454
const [fromResultSet, toResultSet] = await Promise.all([
447455
this.getResultSet(fromInfo.schemas, fromResultSetName, fromPath),
448456
this.getResultSet(toInfo.schemas, toResultSetName, toPath),
449457
]);
458+
// eslint-disable-next-line import/no-deprecated
450459
return resultsDiff(fromResultSet, toResultSet);
451460
}
452461
}

extensions/ql-vscode/src/compare/resultsDiff.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@ import type { RawResultSet } from "../common/raw-result-types";
1818
* 1. number of columns do not match
1919
* 2. If either query is empty
2020
* 3. If the queries are 100% disjoint
21+
*
22+
* @deprecated This function is only used when the `bqrs diff` command does not
23+
* support `--result-sets`. It should be removed when all supported CLI versions
24+
* support this option.
2125
*/
2226
export default function resultsDiff(
2327
fromResults: RawResultSet,

extensions/ql-vscode/src/extension.ts

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@ import {
2121
activate as archiveFilesystemProvider_activate,
2222
zipArchiveScheme,
2323
} from "./common/vscode/archive-filesystem-provider";
24-
import { CliVersionConstraint, CodeQLCliServer } from "./codeql-cli/cli";
24+
import {
25+
CodeQLCliServer,
26+
OLDEST_SUPPORTED_CLI_VERSION,
27+
} from "./codeql-cli/cli";
2528
import {
2629
ADD_DATABASE_SOURCE_TO_WORKSPACE_SETTING,
2730
addDatabaseSourceToWorkspace,
@@ -451,29 +454,19 @@ export async function activate(
451454

452455
let unsupportedWarningShown = false;
453456
codeQlExtension.cliServer.addVersionChangedListener((ver) => {
454-
if (!ver) {
455-
return;
456-
}
457-
458-
if (unsupportedWarningShown) {
459-
return;
460-
}
461-
462457
if (
463-
CliVersionConstraint.OLDEST_SUPPORTED_CLI_VERSION.compare(
464-
ver.version,
465-
) <= 0
458+
ver &&
459+
!unsupportedWarningShown &&
460+
OLDEST_SUPPORTED_CLI_VERSION.compare(ver.version) === 1
466461
) {
467-
return;
462+
void showAndLogWarningMessage(
463+
extLogger,
464+
`You are using an unsupported version of the CodeQL CLI (${ver.version.toString()}). ` +
465+
`The minimum supported version is ${OLDEST_SUPPORTED_CLI_VERSION.toString()}. ` +
466+
`Please upgrade to a newer version of the CodeQL CLI.`,
467+
);
468+
unsupportedWarningShown = true;
468469
}
469-
470-
void showAndLogWarningMessage(
471-
extLogger,
472-
`You are using an unsupported version of the CodeQL CLI (${ver.version.toString()}). ` +
473-
`The minimum supported version is ${CliVersionConstraint.OLDEST_SUPPORTED_CLI_VERSION.toString()}. ` +
474-
`Please upgrade to a newer version of the CodeQL CLI.`,
475-
);
476-
unsupportedWarningShown = true;
477470
});
478471

479472
// Expose the CodeQL CLI features to the extension context under `codeQL.cliFeatures.*`.

extensions/ql-vscode/src/query-server/query-server-client.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ export class QueryServerClient extends DisposableObject {
101101
* queries at once.
102102
*/
103103
async supportsRunQueriesMethod(): Promise<boolean> {
104-
return await this.cliServer.cliConstraints.supportsQueryServerRunQueries();
104+
return await this.cliServer.supportsFeature("queryServerRunQueries");
105105
}
106106

107107
/** Stops the query server by disposing of the current server process. */

0 commit comments

Comments
 (0)