@@ -2,7 +2,6 @@ import { ViewColumn } from "vscode";
22
33import type {
44 FromCompareViewMessage ,
5- InterpretedQueryCompareResult ,
65 QueryCompareResult ,
76 RawQueryCompareResult ,
87 ToCompareViewMessage ,
@@ -14,7 +13,7 @@ import { extLogger } from "../common/logging/vscode";
1413import type { CodeQLCliServer } from "../codeql-cli/cli" ;
1514import type { DatabaseManager } from "../databases/local-databases" ;
1615import { jumpToLocation } from "../databases/local-databases/locations" ;
17- import type { BqrsInfo } from "../common/bqrs-cli-types" ;
16+ import type { BqrsInfo , BqrsResultSetSchema } from "../common/bqrs-cli-types" ;
1817import resultsDiff from "./resultsDiff" ;
1918import type { CompletedLocalQueryInfo } from "../query-results" ;
2019import { assertNever , getErrorMessage } from "../common/helpers-pure" ;
@@ -36,7 +35,7 @@ import { compareInterpretedResults } from "./interpreted-results";
3635import { isCanary } from "../config" ;
3736import { nanoid } from "nanoid" ;
3837
39- interface ComparePair {
38+ export interface ComparePair {
4039 from : CompletedLocalQueryInfo ;
4140 fromInfo : CompareQueryInfo ;
4241 to : CompletedLocalQueryInfo ;
@@ -45,7 +44,7 @@ interface ComparePair {
4544 commonResultSetNames : readonly string [ ] ;
4645}
4746
48- function findSchema ( info : BqrsInfo , name : string ) {
47+ export function findSchema ( info : BqrsInfo , name : string ) {
4948 const schema = info [ "result-sets" ] . find ( ( schema ) => schema . name === name ) ;
5049 if ( schema === undefined ) {
5150 throw new Error ( `Schema ${ name } not found.` ) ;
@@ -182,8 +181,7 @@ export class CompareView extends AbstractWebview<
182181 result = await compareInterpretedResults (
183182 this . databaseManager ,
184183 this . cliServer ,
185- this . comparePair . from ,
186- this . comparePair . to ,
184+ this . comparePair ,
187185 ) ;
188186 } else {
189187 result = await this . compareResults (
@@ -373,18 +371,12 @@ export class CompareView extends AbstractWebview<
373371 const fromPath = from . completedQuery . query . resultsPath ;
374372 const toPath = to . completedQuery . query . resultsPath ;
375373
376- const fromSchema = findSchema ( fromInfo . schemas , fromResultSetName ) ;
377- const toSchema = findSchema ( toInfo . schemas , toResultSetName ) ;
378-
379- if ( fromSchema . columns . length !== toSchema . columns . length ) {
380- throw new Error ( "CodeQL Compare: Columns do not match." ) ;
381- }
382- if ( fromSchema . rows === 0 ) {
383- throw new Error ( "CodeQL Compare: Source query has no results." ) ;
384- }
385- if ( toSchema . rows === 0 ) {
386- throw new Error ( "CodeQL Compare: Target query has no results." ) ;
387- }
374+ const { fromSchema, toSchema } = getComparableSchemas (
375+ fromInfo ,
376+ toInfo ,
377+ fromResultSetName ,
378+ toResultSetName ,
379+ ) ;
388380
389381 // If the result set names are the same, we use `bqrs diff`. This is more
390382 // efficient, but we can't use it in general as it does not support
@@ -393,13 +385,13 @@ export class CompareView extends AbstractWebview<
393385 const { uniquePath1, uniquePath2, cleanup } =
394386 await this . cliServer . bqrsDiff ( fromPath , toPath ) ;
395387 try {
396- const info1 = await this . cliServer . bqrsInfo ( uniquePath1 ) ;
397- const info2 = await this . cliServer . bqrsInfo ( uniquePath2 ) ;
388+ const uniqueInfo1 = await this . cliServer . bqrsInfo ( uniquePath1 ) ;
389+ const uniqueInfo2 = await this . cliServer . bqrsInfo ( uniquePath2 ) ;
398390
399391 // We avoid decoding the results sets if there is no overlap
400392 if (
401- fromSchema . rows === findSchema ( info1 , fromResultSetName ) . rows &&
402- toSchema . rows === findSchema ( info2 , toResultSetName ) . rows
393+ fromSchema . rows === findSchema ( uniqueInfo1 , fromResultSetName ) . rows &&
394+ toSchema . rows === findSchema ( uniqueInfo2 , toResultSetName ) . rows
403395 ) {
404396 throw new Error (
405397 "CodeQL Compare: No overlap between the selected queries." ,
@@ -440,3 +432,28 @@ export class CompareView extends AbstractWebview<
440432 }
441433 }
442434}
435+
436+ /**
437+ * Check that `fromInfo` and `toInfo` have comparable schemas for the given
438+ * result set names and get them if so.
439+ */
440+ export function getComparableSchemas (
441+ fromInfo : CompareQueryInfo ,
442+ toInfo : CompareQueryInfo ,
443+ fromResultSetName : string ,
444+ toResultSetName : string ,
445+ ) : { fromSchema : BqrsResultSetSchema ; toSchema : BqrsResultSetSchema } {
446+ const fromSchema = findSchema ( fromInfo . schemas , fromResultSetName ) ;
447+ const toSchema = findSchema ( toInfo . schemas , toResultSetName ) ;
448+
449+ if ( fromSchema . columns . length !== toSchema . columns . length ) {
450+ throw new Error ( "CodeQL Compare: Columns do not match." ) ;
451+ }
452+ if ( fromSchema . rows === 0 ) {
453+ throw new Error ( "CodeQL Compare: Source query has no results." ) ;
454+ }
455+ if ( toSchema . rows === 0 ) {
456+ throw new Error ( "CodeQL Compare: Target query has no results." ) ;
457+ }
458+ return { fromSchema, toSchema } ;
459+ }
0 commit comments