Ensure Open Query Text works for in progress queries

Same with "Open query that produced these results".

In order to do this, needed to move the query id generation into the
InitialQueryInfo.
This commit is contained in:
Andrew Eisenberg
2022-01-26 14:10:54 -08:00
parent afe3c56ca8
commit dc1bace4c6
7 changed files with 22 additions and 59 deletions

View File

@@ -82,12 +82,12 @@ export class CompareInterfaceManager extends DisposableObject {
// otherwise we will wind up with duplicated rows
name: from.getShortLabel(),
status: from.completedQuery.statusString,
time: from.time,
time: from.startTime,
},
toQuery: {
name: to.getShortLabel(),
status: to.completedQuery.statusString,
time: to.time,
time: to.startTime,
},
},
columns: fromResultSet.schema.columns,

View File

@@ -500,11 +500,11 @@ async function activateWithInstalledDistribution(
const initialInfo = await createInitialQueryInfo(selectedQuery, databaseInfo, quickEval, range);
const item = new FullQueryInfo(initialInfo, queryHistoryConfigurationListener);
qhm.addCompletedQuery(item);
qhm.addQuery(item);
await qhm.refreshTreeView(item);
try {
const info = await compileAndRunQueryAgainstDatabase(
const completedQueryInfo = await compileAndRunQueryAgainstDatabase(
cliServer,
qs,
databaseItem,
@@ -512,7 +512,7 @@ async function activateWithInstalledDistribution(
progress,
token,
);
item.completeThisQuery(info);
item.completeThisQuery(completedQueryInfo);
await showResultsForCompletedQuery(item as FullCompletedQueryInfo, WebviewReveal.NotForced);
// Note we must update the query history view after showing results as the
// display and sorting might depend on the number of results

View File

@@ -406,12 +406,8 @@ export class QueryHistoryManager extends DisposableObject {
throw new Error(NO_QUERY_SELECTED);
}
if (!finalSingleItem.completedQuery) {
throw new Error('Select a completed query.');
}
const textDocument = await workspace.openTextDocument(
Uri.file(finalSingleItem.completedQuery.query.program.queryPath)
Uri.file(finalSingleItem.initialInfo.queryPath)
);
const editor = await window.showTextDocument(
textDocument,
@@ -580,18 +576,14 @@ export class QueryHistoryManager extends DisposableObject {
throw new Error(NO_QUERY_SELECTED);
}
if (!singleItem.completedQuery) {
return;
}
const rawQueryName = singleItem.getQueryName();
const queryName = rawQueryName.endsWith('.ql') ? rawQueryName : rawQueryName + '.ql';
const params = new URLSearchParams({
isQuickEval: String(!!singleItem.completedQuery.query.quickEvalPosition),
isQuickEval: String(!!singleItem.initialInfo.quickEvalPosition),
queryText: encodeURIComponent(await this.getQueryText(singleItem)),
});
const uri = Uri.parse(
`codeql:${singleItem.completedQuery.query.queryID}-${queryName}?${params.toString()}`, true
`codeql:${singleItem.initialInfo.id}-${queryName}?${params.toString()}`, true
);
const doc = await workspace.openTextDocument(uri);
await window.showTextDocument(doc, { preview: false });
@@ -670,32 +662,10 @@ export class QueryHistoryManager extends DisposableObject {
}
async getQueryText(queryHistoryItem: FullQueryInfo): Promise<string> {
if (queryHistoryItem.initialInfo.queryText) {
return queryHistoryItem.initialInfo.queryText;
}
if (!queryHistoryItem.completedQuery) {
return '<No label>';
}
const query = queryHistoryItem.completedQuery.query;
if (query.quickEvalPosition) {
// capture all selected lines
const startLine = query.quickEvalPosition.line;
const endLine = query.quickEvalPosition.endLine;
const textDocument = await workspace.openTextDocument(
query.quickEvalPosition.fileName
);
return textDocument.getText(
new Range(startLine - 1, 0, endLine, 0)
);
} else {
return '';
}
return queryHistoryItem.initialInfo.queryText;
}
addCompletedQuery(item: FullQueryInfo) {
addQuery(item: FullQueryInfo) {
this.treeDataProvider.pushQuery(item);
this.updateTreeViewSelectionIfVisible();
}

View File

@@ -22,13 +22,14 @@ import { DatabaseInfo } from './pure/interface-types';
*/
export interface InitialQueryInfo {
userSpecifiedLabel?: string; // if missing, use a default label
readonly queryText?: string; // text of the selected file
readonly queryText: string; // text of the selected file, or the selected text when doing quick eval
readonly isQuickQuery: boolean;
readonly isQuickEval: boolean;
readonly quickEvalPosition?: messages.Position;
readonly queryPath: string;
readonly databaseInfo: DatabaseInfo
readonly start: Date;
readonly id: number; // an incrementing number for each query
}
export enum QueryStatus {
@@ -183,14 +184,14 @@ export class FullQueryInfo {
/**/
}
get time() {
get startTime() {
return this.initialInfo.start.toLocaleString(env.language);
}
interpolate(template: string): string {
const { resultCount = 0, statusString = 'in progress' } = this.completedQuery || {};
const replacements: { [k: string]: string } = {
t: this.time,
t: this.startTime,
q: this.getQueryName(),
d: this.initialInfo.databaseInfo.name,
r: resultCount.toString(),

View File

@@ -54,24 +54,21 @@ export const tmpDirDisposal = {
* output and results.
*/
export class QueryEvaluatonInfo {
private static nextQueryId = 0;
readonly compiledQueryPath: string;
readonly dilPath: string;
readonly csvPath: string;
readonly resultsPaths: ResultsPaths;
readonly dataset: Uri; // guarantee the existence of a well-defined dataset dir at this point
readonly queryID: number;
constructor(
public readonly queryID: number,
public readonly program: messages.QlProgram,
public readonly dbItem: DatabaseItem,
public readonly queryDbscheme: string, // the dbscheme file the query expects, based on library path resolution
public readonly quickEvalPosition?: messages.Position,
public readonly metadata?: QueryMetadata,
public readonly templates?: messages.TemplateDefinitions,
public readonly templates?: messages.TemplateDefinitions
) {
this.queryID = QueryEvaluatonInfo.nextQueryId++;
this.compiledQueryPath = path.join(tmpDir.name, `compiledQuery${this.queryID}.qlo`);
this.dilPath = path.join(tmpDir.name, `results${this.queryID}.dil`);
this.csvPath = path.join(tmpDir.name, `results${this.queryID}.csv`);
@@ -617,7 +614,7 @@ export async function compileAndRunQueryAgainstDatabase(
}
}
const query = new QueryEvaluatonInfo(qlProgram, db, packConfig.dbscheme, initialInfo.quickEvalPosition, metadata, templates);
const query = new QueryEvaluatonInfo(initialInfo.id, qlProgram, db, packConfig.dbscheme, initialInfo.quickEvalPosition, metadata, templates);
const upgradeDir = await tmp.dir({ dir: upgradesTmpDir.name, unsafeCleanup: true });
try {
@@ -688,6 +685,7 @@ export async function compileAndRunQueryAgainstDatabase(
}
}
let queryId = 0;
export async function createInitialQueryInfo(
selectedQueryUri: Uri | undefined,
databaseInfo: DatabaseInfo,
@@ -701,9 +699,10 @@ export async function createInitialQueryInfo(
isQuickEval,
isQuickQuery: isQuickQueryPath(queryPath),
databaseInfo,
id: queryId++,
start: new Date(),
... (isQuickEval ? {
queryText: quickEvalText,
queryText: quickEvalText!, // if this query is quick eval, it must have quick eval text
quickEvalPosition: quickEvalPosition
} : {
queryText: await fs.readFile(queryPath, 'utf8')

View File

@@ -170,15 +170,6 @@ describe('query-results', () => {
await completedQuery.updateSortState(mockServer, 'result-name');
expect(completedQuery.sortedResultsInfo.size).to.eq(0);
});
// interpolate
// time
// label
// getShortLabel
// getQueryFileName
// getQueryName
// status
});
it('should interpretResults', async () => {

View File

@@ -84,8 +84,10 @@ describe('run-queries', () => {
});
});
let queryNum = 0;
function createMockQueryInfo() {
return new QueryEvaluatonInfo(
queryNum++,
'my-program' as unknown as QlProgram,
{
contents: {