Skip to content

Commit 84fd198

Browse files
authored
Merge pull request #2242 from github/nora/query-history-refactoring
Query History: create and map data model to domain model
2 parents 20e9370 + e62142b commit 84fd198

File tree

9 files changed

+473
-115
lines changed

9 files changed

+473
-115
lines changed

extensions/ql-vscode/src/legacy-query-server/run-queries.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,6 @@ async function runQuery(
172172
*/
173173
export class QueryInProgress {
174174
public queryEvalInfo: QueryEvaluationInfo;
175-
/**
176-
* Note that in the {@link readQueryHistoryFromFile} method, we create a QueryEvaluationInfo instance
177-
* by explicitly setting the prototype in order to avoid calling this constructor.
178-
*/
179175
constructor(
180176
readonly querySaveDir: string,
181177
readonly dbItemPath: string,
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import {
2+
LocalQueryInfo,
3+
CompletedQueryInfo,
4+
InitialQueryInfo,
5+
} from "../../query-results";
6+
import { QueryEvaluationInfo } from "../../run-queries-shared";
7+
import { QueryHistoryInfo } from "../query-history-info";
8+
import { VariantAnalysisHistoryItem } from "../variant-analysis-history-item";
9+
import {
10+
CompletedQueryInfoData,
11+
QueryEvaluationInfoData,
12+
InitialQueryInfoData,
13+
LocalQueryDataItem,
14+
} from "./local-query-data-item";
15+
import { QueryHistoryDataItem } from "./query-history-data";
16+
17+
// Maps Query History Data Models to Domain Models
18+
19+
export function mapQueryHistoryToDomainModels(
20+
queries: QueryHistoryDataItem[],
21+
): QueryHistoryInfo[] {
22+
return queries.map((d) => {
23+
if (d.t === "variant-analysis") {
24+
const query: VariantAnalysisHistoryItem = d;
25+
return query;
26+
} else if (d.t === "local") {
27+
return mapLocalQueryDataItemToDomainModel(d);
28+
}
29+
30+
throw Error(
31+
`Unexpected or corrupted query history file. Unknown query history item: ${JSON.stringify(
32+
d,
33+
)}`,
34+
);
35+
});
36+
}
37+
38+
function mapLocalQueryDataItemToDomainModel(
39+
localQuery: LocalQueryDataItem,
40+
): LocalQueryInfo {
41+
return new LocalQueryInfo(
42+
mapInitialQueryInfoDataToDomainModel(localQuery.initialInfo),
43+
undefined,
44+
localQuery.failureReason,
45+
localQuery.completedQuery &&
46+
mapCompletedQueryInfoDataToDomainModel(localQuery.completedQuery),
47+
localQuery.evalLogLocation,
48+
localQuery.evalLogSummaryLocation,
49+
localQuery.jsonEvalLogSummaryLocation,
50+
localQuery.evalLogSummarySymbolsLocation,
51+
);
52+
}
53+
54+
function mapCompletedQueryInfoDataToDomainModel(
55+
completedQuery: CompletedQueryInfoData,
56+
): CompletedQueryInfo {
57+
return new CompletedQueryInfo(
58+
mapQueryEvaluationInfoDataToDomainModel(completedQuery.query),
59+
{
60+
runId: completedQuery.result.runId,
61+
queryId: completedQuery.result.queryId,
62+
resultType: completedQuery.result.resultType,
63+
evaluationTime: completedQuery.result.evaluationTime,
64+
message: completedQuery.result.message,
65+
logFileLocation: completedQuery.result.logFileLocation,
66+
},
67+
completedQuery.logFileLocation,
68+
completedQuery.successful ?? completedQuery.sucessful,
69+
completedQuery.message,
70+
completedQuery.interpretedResultsSortState,
71+
completedQuery.resultCount,
72+
completedQuery.sortedResultsInfo,
73+
);
74+
}
75+
76+
function mapInitialQueryInfoDataToDomainModel(
77+
initialInfo: InitialQueryInfoData,
78+
): InitialQueryInfo {
79+
return {
80+
userSpecifiedLabel: initialInfo.userSpecifiedLabel,
81+
queryText: initialInfo.queryText,
82+
isQuickQuery: initialInfo.isQuickQuery,
83+
isQuickEval: initialInfo.isQuickEval,
84+
quickEvalPosition: initialInfo.quickEvalPosition,
85+
queryPath: initialInfo.queryPath,
86+
databaseInfo: {
87+
databaseUri: initialInfo.databaseInfo.databaseUri,
88+
name: initialInfo.databaseInfo.name,
89+
},
90+
start: new Date(initialInfo.start),
91+
id: initialInfo.id,
92+
};
93+
}
94+
95+
function mapQueryEvaluationInfoDataToDomainModel(
96+
evaluationInfo: QueryEvaluationInfoData,
97+
): QueryEvaluationInfo {
98+
return new QueryEvaluationInfo(
99+
evaluationInfo.querySaveDir,
100+
evaluationInfo.dbItemPath,
101+
evaluationInfo.databaseHasMetadataFile,
102+
evaluationInfo.quickEvalPosition,
103+
evaluationInfo.metadata,
104+
);
105+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
import { assertNever } from "../../pure/helpers-pure";
2+
import { LocalQueryInfo, InitialQueryInfo } from "../../query-results";
3+
import { QueryEvaluationInfo } from "../../run-queries-shared";
4+
import { QueryHistoryInfo } from "../query-history-info";
5+
import {
6+
LocalQueryDataItem,
7+
InitialQueryInfoData,
8+
QueryEvaluationInfoData,
9+
} from "./local-query-data-item";
10+
import { QueryHistoryDataItem } from "./query-history-data";
11+
import { VariantAnalysisDataItem } from "./variant-analysis-data-item";
12+
13+
// Maps Query History Domain Models to Data Models
14+
15+
export function mapQueryHistoryToDataModels(
16+
queries: QueryHistoryInfo[],
17+
): QueryHistoryDataItem[] {
18+
return queries.map((q) => {
19+
if (q.t === "variant-analysis") {
20+
const query: VariantAnalysisDataItem = q;
21+
return query;
22+
} else if (q.t === "local") {
23+
return mapLocalQueryInfoToDataModel(q);
24+
} else {
25+
assertNever(q);
26+
}
27+
});
28+
}
29+
30+
function mapLocalQueryInfoToDataModel(
31+
query: LocalQueryInfo,
32+
): LocalQueryDataItem {
33+
return {
34+
initialInfo: mapInitialQueryInfoToDataModel(query.initialInfo),
35+
t: "local",
36+
evalLogLocation: query.evalLogLocation,
37+
evalLogSummaryLocation: query.evalLogSummaryLocation,
38+
jsonEvalLogSummaryLocation: query.jsonEvalLogSummaryLocation,
39+
evalLogSummarySymbolsLocation: query.evalLogSummarySymbolsLocation,
40+
failureReason: query.failureReason,
41+
completedQuery: query.completedQuery && {
42+
query: mapQueryEvaluationInfoToDataModel(query.completedQuery.query),
43+
result: {
44+
runId: query.completedQuery.result.runId,
45+
queryId: query.completedQuery.result.queryId,
46+
resultType: query.completedQuery.result.resultType,
47+
evaluationTime: query.completedQuery.result.evaluationTime,
48+
message: query.completedQuery.result.message,
49+
logFileLocation: query.completedQuery.result.logFileLocation,
50+
},
51+
logFileLocation: query.completedQuery.logFileLocation,
52+
successful: query.completedQuery.successful,
53+
message: query.completedQuery.message,
54+
resultCount: query.completedQuery.resultCount,
55+
sortedResultsInfo: query.completedQuery.sortedResultsInfo,
56+
},
57+
};
58+
}
59+
60+
function mapInitialQueryInfoToDataModel(
61+
localQueryInitialInfo: InitialQueryInfo,
62+
): InitialQueryInfoData {
63+
return {
64+
userSpecifiedLabel: localQueryInitialInfo.userSpecifiedLabel,
65+
queryText: localQueryInitialInfo.queryText,
66+
isQuickQuery: localQueryInitialInfo.isQuickQuery,
67+
isQuickEval: localQueryInitialInfo.isQuickEval,
68+
quickEvalPosition: localQueryInitialInfo.quickEvalPosition,
69+
queryPath: localQueryInitialInfo.queryPath,
70+
databaseInfo: {
71+
databaseUri: localQueryInitialInfo.databaseInfo.databaseUri,
72+
name: localQueryInitialInfo.databaseInfo.name,
73+
},
74+
start: localQueryInitialInfo.start,
75+
id: localQueryInitialInfo.id,
76+
};
77+
}
78+
79+
function mapQueryEvaluationInfoToDataModel(
80+
queryEvaluationInfo: QueryEvaluationInfo,
81+
): QueryEvaluationInfoData {
82+
return {
83+
querySaveDir: queryEvaluationInfo.querySaveDir,
84+
dbItemPath: queryEvaluationInfo.dbItemPath,
85+
databaseHasMetadataFile: queryEvaluationInfo.databaseHasMetadataFile,
86+
quickEvalPosition: queryEvaluationInfo.quickEvalPosition,
87+
metadata: queryEvaluationInfo.metadata,
88+
resultsPaths: queryEvaluationInfo.resultsPaths,
89+
};
90+
}
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
export interface LocalQueryDataItem {
2+
initialInfo: InitialQueryInfoData;
3+
t: "local";
4+
evalLogLocation?: string;
5+
evalLogSummaryLocation?: string;
6+
jsonEvalLogSummaryLocation?: string;
7+
evalLogSummarySymbolsLocation?: string;
8+
completedQuery?: CompletedQueryInfoData;
9+
failureReason?: string;
10+
}
11+
12+
export interface InitialQueryInfoData {
13+
userSpecifiedLabel?: string;
14+
queryText: string;
15+
isQuickQuery: boolean;
16+
isQuickEval: boolean;
17+
quickEvalPosition?: PositionData;
18+
queryPath: string;
19+
databaseInfo: DatabaseInfoData;
20+
start: Date;
21+
id: string;
22+
}
23+
24+
interface DatabaseInfoData {
25+
name: string;
26+
databaseUri: string;
27+
}
28+
29+
interface PositionData {
30+
line: number;
31+
column: number;
32+
endLine: number;
33+
endColumn: number;
34+
fileName: string;
35+
}
36+
37+
export interface CompletedQueryInfoData {
38+
query: QueryEvaluationInfoData;
39+
message?: string;
40+
successful?: boolean;
41+
42+
// There once was a typo in the data model, which is why we need to support both
43+
sucessful?: boolean;
44+
result: EvaluationResultData;
45+
logFileLocation?: string;
46+
resultCount: number;
47+
sortedResultsInfo: Record<string, SortedResultSetInfo>;
48+
interpretedResultsSortState?: InterpretedResultsSortState;
49+
}
50+
51+
interface InterpretedResultsSortState {
52+
sortBy: InterpretedResultsSortColumn;
53+
sortDirection: SortDirection;
54+
}
55+
56+
type InterpretedResultsSortColumn = "alert-message";
57+
58+
interface SortedResultSetInfo {
59+
resultsPath: string;
60+
sortState: RawResultsSortState;
61+
}
62+
63+
interface RawResultsSortState {
64+
columnIndex: number;
65+
sortDirection: SortDirection;
66+
}
67+
68+
enum SortDirection {
69+
asc,
70+
desc,
71+
}
72+
73+
interface EvaluationResultData {
74+
runId: number;
75+
queryId: number;
76+
resultType: number;
77+
evaluationTime: number;
78+
message?: string;
79+
logFileLocation?: string;
80+
}
81+
82+
export interface QueryEvaluationInfoData {
83+
querySaveDir: string;
84+
dbItemPath: string;
85+
databaseHasMetadataFile: boolean;
86+
quickEvalPosition?: PositionData;
87+
metadata?: QueryMetadataData;
88+
resultsPaths: {
89+
resultsPath: string;
90+
interpretedResultsPath: string;
91+
};
92+
}
93+
94+
interface QueryMetadataData {
95+
name?: string;
96+
description?: string;
97+
id?: string;
98+
kind?: string;
99+
scored?: string;
100+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// Contains models and consts for the data we want to store in the query history store.
2+
// Changes to these models should be done carefully and account for backwards compatibility of data.
3+
4+
import { LocalQueryDataItem } from "./local-query-data-item";
5+
import { VariantAnalysisDataItem } from "./variant-analysis-data-item";
6+
7+
export const ALLOWED_QUERY_HISTORY_VERSIONS = [1, 2];
8+
9+
export interface QueryHistoryData {
10+
version: number;
11+
queries: QueryHistoryDataItem[];
12+
}
13+
14+
export type QueryHistoryDataItem = LocalQueryDataItem | VariantAnalysisDataItem;

0 commit comments

Comments
 (0)