diff --git a/extensions/ql-vscode/CHANGELOG.md b/extensions/ql-vscode/CHANGELOG.md index 1390cc6c272..57decf05f16 100644 --- a/extensions/ql-vscode/CHANGELOG.md +++ b/extensions/ql-vscode/CHANGELOG.md @@ -9,6 +9,7 @@ - Add more structured output for tests. [#626](https://github.com/github/vscode-codeql/pull/626) - Whenever the extension restarts, orphaned databases will be cleaned up. These are databases whose files are located inside of the extension's storage area, but are not imported into the workspace. - After renaming a database, the database list is re-sorted. [#685](https://github.com/github/vscode-codeql/pull/685) +- Add a `codeQl.resultsDisplay.pageSize` setting to configure the number of results displayed in a single results view page. Increase the default page size from 100 to 200. [#686](https://github.com/github/vscode-codeql/pull/686) ## 1.3.6 - 4 November 2020 diff --git a/extensions/ql-vscode/package.json b/extensions/ql-vscode/package.json index e4183741cd7..875c830a1f2 100644 --- a/extensions/ql-vscode/package.json +++ b/extensions/ql-vscode/package.json @@ -157,6 +157,11 @@ "default": 20, "description": "Max number of simultaneous queries to run using the 'CodeQL: Run Queries' command." }, + "codeQL.resultsDisplay.pageSize": { + "type": "integer", + "default": 200, + "description": "Number of queries displayed per page of the results view." + }, "codeQL.queryHistory.format": { "type": "string", "default": "[%t] %q on %d - %s", diff --git a/extensions/ql-vscode/src/config.ts b/extensions/ql-vscode/src/config.ts index 21f1c49ba65..830d35f1420 100644 --- a/extensions/ql-vscode/src/config.ts +++ b/extensions/ql-vscode/src/config.ts @@ -68,10 +68,12 @@ const TIMEOUT_SETTING = new Setting('timeout', RUNNING_QUERIES_SETTING); const MEMORY_SETTING = new Setting('memory', RUNNING_QUERIES_SETTING); const DEBUG_SETTING = new Setting('debug', RUNNING_QUERIES_SETTING); const RUNNING_TESTS_SETTING = new Setting('runningTests', ROOT_SETTING); +const RESULTS_DISPLAY_SETTING = new Setting('resultsDisplay', ROOT_SETTING); export const NUMBER_OF_TEST_THREADS_SETTING = new Setting('numberOfThreads', RUNNING_TESTS_SETTING); export const MAX_QUERIES = new Setting('maxQueries', RUNNING_QUERIES_SETTING); export const AUTOSAVE_SETTING = new Setting('autoSave', RUNNING_QUERIES_SETTING); +export const PAGE_SIZE = new Setting('pageSize', RESULTS_DISPLAY_SETTING); /** When these settings change, the running query server should be restarted. */ const QUERY_SERVER_RESTARTING_SETTINGS = [NUMBER_OF_THREADS_SETTING, MEMORY_SETTING, DEBUG_SETTING]; diff --git a/extensions/ql-vscode/src/interface.ts b/extensions/ql-vscode/src/interface.ts index 7f0099c8399..6c8133414c5 100644 --- a/extensions/ql-vscode/src/interface.ts +++ b/extensions/ql-vscode/src/interface.ts @@ -26,8 +26,6 @@ import { SortedResultsMap, InterpretedResultsSortState, SortDirection, - RAW_RESULTS_PAGE_SIZE, - INTERPRETED_RESULTS_PAGE_SIZE, ALERTS_TABLE_NAME, RawResultsSortState, } from './pure/interface-types'; @@ -48,6 +46,7 @@ import { } from './interface-utils'; import { getDefaultResultSetName, ParsedResultSets } from './pure/interface-types'; import { RawResultSet, transformBqrsResultSet, ResultSetSchema } from './pure/bqrs-cli-types'; +import { PAGE_SIZE } from './config'; /** * interface.ts @@ -89,11 +88,11 @@ function sortInterpretedResults( } function numPagesOfResultSet(resultSet: RawResultSet): number { - return Math.ceil(resultSet.schema.rows / RAW_RESULTS_PAGE_SIZE); + return Math.ceil(resultSet.schema.rows / PAGE_SIZE.getValue()); } function numInterpretedPages(interpretation: Interpretation | undefined): number { - return Math.ceil((interpretation?.sarif.runs[0].results?.length || 0) / INTERPRETED_RESULTS_PAGE_SIZE); + return Math.ceil((interpretation?.sarif.runs[0].results?.length || 0) / PAGE_SIZE.getValue()); } export class InterfaceManager extends DisposableObject { @@ -378,7 +377,7 @@ export class InterfaceManager extends DisposableObject { // Use sorted results path if it exists. This may happen if we are // reloading the results view after it has been sorted in the past. const resultsPath = results.getResultsPath(selectedTable); - + const pageSize = PAGE_SIZE.getValue(); const chunk = await this.cliServer.bqrsDecode( resultsPath, schema.name, @@ -388,12 +387,13 @@ export class InterfaceManager extends DisposableObject { // if there are interpreted results, but speculatively // send anyway. offset: schema.pagination?.offsets[0], - pageSize: RAW_RESULTS_PAGE_SIZE + pageSize } ); const resultSet = transformBqrsResultSet(schema, chunk); const parsedResultSets: ParsedResultSets = { pageNumber: 0, + pageSize, numPages: numPagesOfResultSet(resultSet), numInterpretedPages: numInterpretedPages(this._interpretation), resultSet: { ...resultSet, t: 'RawResultSet' }, @@ -442,6 +442,7 @@ export class InterfaceManager extends DisposableObject { metadata: this._displayedQuery.query.metadata, pageNumber, resultSetNames, + pageSize: PAGE_SIZE.getValue(), numPages: numInterpretedPages(this._interpretation), }); } @@ -450,7 +451,7 @@ export class InterfaceManager extends DisposableObject { const resultsPath = results.getResultsPath(selectedTable); const schemas = await this.cliServer.bqrsInfo( resultsPath, - RAW_RESULTS_PAGE_SIZE + PAGE_SIZE.getValue() ); return schemas['result-sets']; } @@ -483,18 +484,20 @@ export class InterfaceManager extends DisposableObject { if (schema === undefined) throw new Error(`Query result set '${selectedTable}' not found.`); + const pageSize = PAGE_SIZE.getValue(); const chunk = await this.cliServer.bqrsDecode( results.getResultsPath(selectedTable, sorted), schema.name, { offset: schema.pagination?.offsets[pageNumber], - pageSize: RAW_RESULTS_PAGE_SIZE + pageSize } ); const resultSet = transformBqrsResultSet(schema, chunk); const parsedResultSets: ParsedResultSets = { pageNumber, + pageSize, resultSet: { t: 'RawResultSet', ...resultSet }, numPages: numPagesOfResultSet(resultSet), numInterpretedPages: numInterpretedPages(this._interpretation), @@ -559,8 +562,8 @@ export class InterfaceManager extends DisposableObject { function getPageOfRun(run: Sarif.Run): Sarif.Run { return { ...run, results: run.results?.slice( - INTERPRETED_RESULTS_PAGE_SIZE * pageNumber, - INTERPRETED_RESULTS_PAGE_SIZE * (pageNumber + 1) + PAGE_SIZE.getValue() * pageNumber, + PAGE_SIZE.getValue() * (pageNumber + 1) ) }; } diff --git a/extensions/ql-vscode/src/pure/interface-types.ts b/extensions/ql-vscode/src/pure/interface-types.ts index 408e74d18aa..099385c7195 100644 --- a/extensions/ql-vscode/src/pure/interface-types.ts +++ b/extensions/ql-vscode/src/pure/interface-types.ts @@ -23,16 +23,6 @@ export type ResultSet = RawTableResultSet | PathTableResultSet; */ export const RAW_RESULTS_LIMIT = 10000; -/** - * Show this many rows in a raw result table at a time. - */ -export const RAW_RESULTS_PAGE_SIZE = 100; - -/** - * Show this many rows in an interpreted results table at a time. - */ -export const INTERPRETED_RESULTS_PAGE_SIZE = 100; - export interface DatabaseInfo { name: string; databaseUri: string; @@ -124,6 +114,7 @@ export interface ShowInterpretedPageMsg { metadata?: QueryMetadata; pageNumber: number; numPages: number; + pageSize: number; resultSetNames: string[]; } @@ -352,6 +343,7 @@ export function getDefaultResultSetName( export interface ParsedResultSets { pageNumber: number; + pageSize: number; numPages: number; numInterpretedPages: number; selectedTable?: string; // when undefined, means 'show default table' diff --git a/extensions/ql-vscode/src/view/result-tables.tsx b/extensions/ql-vscode/src/view/result-tables.tsx index a7cf2b4ad6d..ffb44a2c236 100644 --- a/extensions/ql-vscode/src/view/result-tables.tsx +++ b/extensions/ql-vscode/src/view/result-tables.tsx @@ -6,7 +6,6 @@ import { QueryMetadata, ResultsPaths, InterpretedResultsSortState, - RAW_RESULTS_PAGE_SIZE, ResultSet, ALERTS_TABLE_NAME, SELECT_TABLE_NAME, @@ -100,7 +99,7 @@ export class ResultTables return resultSets; } - private getResultSetNames(resultSets: ResultSet[]): string[] { + private getResultSetNames(): string[] { return this.props.parsedResultSets.resultSetNames.concat([ALERTS_TABLE_NAME]); } @@ -169,7 +168,7 @@ export class ResultTables getOffset(): number { const { parsedResultSets } = this.props; - return parsedResultSets.pageNumber * RAW_RESULTS_PAGE_SIZE; + return parsedResultSets.pageNumber * parsedResultSets.pageSize; } renderPageButtons(): JSX.Element { @@ -220,6 +219,8 @@ export class ResultTables type="number" size={3} value={this.state.selectedPage} + min="1" + max={numPages} onChange={onChange} onBlur={e => choosePage(e.target.value)} onKeyDown={e => { @@ -239,7 +240,7 @@ export class ResultTables render(): React.ReactNode { const { selectedTable } = this.state; const resultSets = this.getResultSets(); - const resultSetNames = this.getResultSetNames(resultSets); + const resultSetNames = this.getResultSetNames(); const resultSet = resultSets.find(resultSet => resultSet.schema.name == selectedTable); const nonemptyRawResults = resultSets.some(resultSet => resultSet.t == 'RawResultSet' && resultSet.rows.length > 0); diff --git a/extensions/ql-vscode/src/view/results.tsx b/extensions/ql-vscode/src/view/results.tsx index e8f4c80b191..842b8ca6407 100644 --- a/extensions/ql-vscode/src/view/results.tsx +++ b/extensions/ql-vscode/src/view/results.tsx @@ -105,6 +105,7 @@ class App extends React.Component<{}, ResultsViewState> { resultsPath: '', // FIXME: Not used for interpreted, refactor so this is not needed parsedResultSets: { numPages: msg.numPages, + pageSize: msg.pageSize, numInterpretedPages: msg.numPages, resultSetNames: msg.resultSetNames, pageNumber: msg.pageNumber,