@@ -10,14 +10,15 @@ import { CodeQLCliServer } from './cli';
1010import { DatabaseItem , DatabaseManager } from './databases' ;
1111import { showAndLogErrorMessage } from './helpers' ;
1212import { assertNever } from './helpers-pure' ;
13- import { FromResultsViewMsg , Interpretation , INTERPRETED_RESULTS_PER_RUN_LIMIT , IntoResultsViewMsg , QueryMetadata , ResultsPaths , SortedResultSetInfo , SortedResultsMap , InterpretedResultsSortState , SortDirection } from './interface-types' ;
13+ import { FromResultsViewMsg , Interpretation , INTERPRETED_RESULTS_PER_RUN_LIMIT , IntoResultsViewMsg , QueryMetadata , ResultsPaths , SortedResultSetInfo , SortedResultsMap , InterpretedResultsSortState , SortDirection , RAW_RESULTS_PAGE_SIZE } from './interface-types' ;
1414import { Logger } from './logging' ;
1515import * as messages from './messages' ;
1616import { CompletedQuery , interpretResults } from './query-results' ;
1717import { QueryInfo , tmpDir } from './run-queries' ;
1818import { parseSarifLocation , parseSarifPlainTextMessage } from './sarif-utils' ;
19- import { adaptSchema , adaptBqrs , RawResultSet } from './adapt' ;
19+ import { adaptSchema , adaptBqrs , RawResultSet , ParsedResultSets } from './adapt' ;
2020import { EXPERIMENTAL_BQRS_SETTING } from './config' ;
21+ import { getDefaultResultSetName } from './interface-utils' ;
2122
2223/**
2324 * interface.ts
@@ -115,8 +116,13 @@ function sortInterpretedResults(results: Sarif.Result[], sortState: InterpretedR
115116 }
116117}
117118
119+ function numPagesOfResultSet ( resultSet : RawResultSet ) : number {
120+ return Math . ceil ( resultSet . schema . tupleCount / RAW_RESULTS_PAGE_SIZE ) ;
121+ }
122+
118123export class InterfaceManager extends DisposableObject {
119124 private _displayedQuery ?: CompletedQuery ;
125+ private _interpretation ?: Interpretation ;
120126 private _panel : vscode . WebviewPanel | undefined ;
121127 private _panelLoaded = false ;
122128 private _panelLoadedCallBacks : ( ( ) => void ) [ ] = [ ] ;
@@ -288,6 +294,9 @@ export class InterfaceManager extends DisposableObject {
288294 query . updateInterpretedSortState ( this . cliServer , msg . sortState )
289295 ) ;
290296 break ;
297+ case "changePage" :
298+ await this . showPageOfResults ( msg . selectedTable , msg . pageNumber ) ;
299+ break ;
291300 default :
292301 assertNever ( msg ) ;
293302 }
@@ -339,6 +348,7 @@ export class InterfaceManager extends DisposableObject {
339348 ) ;
340349
341350 this . _displayedQuery = results ;
351+ this . _interpretation = interpretation ;
342352
343353 const panel = this . getPanel ( ) ;
344354 await this . waitForPanelLoaded ( ) ;
@@ -364,18 +374,37 @@ export class InterfaceManager extends DisposableObject {
364374 } ) ;
365375 }
366376
367- let resultSets : RawResultSet [ ] | undefined ;
377+ const getParsedResultSets = async ( ) : Promise < ParsedResultSets > => {
378+ if ( EXPERIMENTAL_BQRS_SETTING . getValue ( ) ) {
379+ const schemas = await this . cliServer . bqrsInfo ( results . query . resultsPaths . resultsPath , RAW_RESULTS_PAGE_SIZE ) ;
380+
381+ const resultSetNames = schemas [ "result-sets" ] . map ( resultSet => resultSet . name ) ;
382+
383+ // This may not wind up being the page we actually show, if there are interpreted results,
384+ // but speculatively send it anyway.
385+ const selectedTable = getDefaultResultSetName ( resultSetNames ) ;
386+ const schema = schemas [ "result-sets" ] . find ( resultSet => resultSet . name == selectedTable ) ! ;
387+ if ( schema === undefined ) {
388+ return { t : 'WebviewParsed' } ;
389+ }
368390
369- if ( EXPERIMENTAL_BQRS_SETTING . getValue ( ) ) {
370- resultSets = [ ] ;
371- const schemas = await this . cliServer . bqrsInfo ( results . query . resultsPaths . resultsPath ) ;
372- for ( const schema of schemas [ "result-sets" ] ) {
373- const chunk = await this . cliServer . bqrsDecode ( results . query . resultsPaths . resultsPath , schema . name ) ;
391+ const chunk = await this . cliServer . bqrsDecode ( results . query . resultsPaths . resultsPath , schema . name , RAW_RESULTS_PAGE_SIZE , schema . pagination ?. offsets [ 0 ] ) ;
374392 const adaptedSchema = adaptSchema ( schema ) ;
375393 const resultSet = adaptBqrs ( adaptedSchema , chunk ) ;
376- resultSets . push ( resultSet ) ;
394+
395+ return {
396+ t : 'ExtensionParsed' ,
397+ pageNumber : 0 ,
398+ numPages : numPagesOfResultSet ( resultSet ) ,
399+ resultSet,
400+ selectedTable : undefined ,
401+ resultSetNames
402+ } ;
377403 }
378- }
404+ else {
405+ return { t : 'WebviewParsed' } ;
406+ }
407+ } ;
379408
380409 await this . postMessage ( {
381410 t : "setState" ,
@@ -384,14 +413,67 @@ export class InterfaceManager extends DisposableObject {
384413 resultsPath : this . convertPathToWebviewUri (
385414 results . query . resultsPaths . resultsPath
386415 ) ,
387- resultSets ,
416+ parsedResultSets : await getParsedResultSets ( ) ,
388417 sortedResultsMap,
389418 database : results . database ,
390419 shouldKeepOldResultsWhileRendering,
391420 metadata : results . query . metadata
392421 } ) ;
393422 }
394423
424+ /**
425+ * Show a page of raw results from the chosen table.
426+ */
427+ public async showPageOfResults ( selectedTable : string , pageNumber : number ) : Promise < void > {
428+ const results = this . _displayedQuery ;
429+ if ( results === undefined ) {
430+ throw new Error ( 'trying to view a page of a query that is not loaded' ) ;
431+ }
432+
433+ const sortedResultsMap : SortedResultsMap = { } ;
434+ results . sortedResultsInfo . forEach (
435+ ( v , k ) =>
436+ ( sortedResultsMap [ k ] = this . convertPathPropertiesToWebviewUris (
437+ v
438+ ) )
439+ ) ;
440+
441+ const schemas = await this . cliServer . bqrsInfo ( results . query . resultsPaths . resultsPath , RAW_RESULTS_PAGE_SIZE ) ;
442+
443+ const resultSetNames = schemas [ "result-sets" ] . map ( resultSet => resultSet . name ) ;
444+
445+ const schema = schemas [ "result-sets" ] . find ( resultSet => resultSet . name == selectedTable ) ! ;
446+ if ( schema === undefined )
447+ throw new Error ( `Query result set '${ selectedTable } ' not found.` ) ;
448+
449+ const chunk = await this . cliServer . bqrsDecode ( results . query . resultsPaths . resultsPath , schema . name , RAW_RESULTS_PAGE_SIZE , schema . pagination ?. offsets [ pageNumber ] ) ;
450+ const adaptedSchema = adaptSchema ( schema ) ;
451+ const resultSet = adaptBqrs ( adaptedSchema , chunk ) ;
452+
453+ const parsedResultSets : ParsedResultSets = {
454+ t : 'ExtensionParsed' ,
455+ pageNumber,
456+ resultSet,
457+ numPages : numPagesOfResultSet ( resultSet ) ,
458+ selectedTable : selectedTable ,
459+ resultSetNames
460+ } ;
461+
462+ await this . postMessage ( {
463+ t : "setState" ,
464+ interpretation : this . _interpretation ,
465+ origResultsPaths : results . query . resultsPaths ,
466+ resultsPath : this . convertPathToWebviewUri (
467+ results . query . resultsPaths . resultsPath
468+ ) ,
469+ parsedResultSets,
470+ sortedResultsMap,
471+ database : results . database ,
472+ shouldKeepOldResultsWhileRendering : false ,
473+ metadata : results . query . metadata
474+ } ) ;
475+ }
476+
395477 private async getTruncatedResults (
396478 metadata : QueryMetadata | undefined ,
397479 resultsPaths : ResultsPaths ,
0 commit comments