diff --git a/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx index 095ef1611ad..54deaf0aa4f 100644 --- a/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx +++ b/src/vs/workbench/browser/positronDataExplorer/components/dataExplorerPanel/components/rowFilterBar/rowFilterBar.tsx @@ -44,7 +44,7 @@ const createRowFilters = (rowFilterDescriptors: RowFilterDescriptor[]) => { } else if (rowFilterDescriptor instanceof RowFilterDescriptorIsNotEmpty) { rowFilters.push({ filter_id: rowFilterDescriptor.identifier, - filter_type: RowFilterType.IsNull, + filter_type: RowFilterType.NotNull, column_index: rowFilterDescriptor.columnSchema.column_index }); } else if (rowFilterDescriptor instanceof RowFilterDescriptorIsLessThan) { diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/columnNullPercent.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/columnNullPercent.tsx index 7143244f482..cb22c8346d3 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/components/columnNullPercent.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/components/columnNullPercent.tsx @@ -23,11 +23,26 @@ interface ColumnNullPercentProps { */ export const ColumnNullPercent = (props: ColumnNullPercentProps) => { // Render. + let svgWidth = 50; + if (props.columnNullPercent !== undefined) { + svgWidth = props.columnNullPercent === 0.0 ? + 50 : + Math.max(50 * ((100 - props.columnNullPercent) / 100), 3); + } return (
-
- {props.columnNullPercent}% -
+ {props.columnNullPercent !== undefined ? + ( +
+ {props.columnNullPercent}% +
+ ) : + ( +
+ ... +
+ ) + }
@@ -43,10 +58,7 @@ export const ColumnNullPercent = (props: ColumnNullPercentProps) => { { * @returns The profile component. */ const profile = () => { - // Hack just to get things working - props.instance.computeColumnSummaryStats(props.columnIndex); // Determine the alignment based on type. switch (props.columnSchema.type_display) { case ColumnDisplayType.Number: @@ -90,7 +88,10 @@ export const ColumnSummaryCell = (props: ColumnSummaryCellProps) => { return null; case ColumnDisplayType.String: - return ; + return ; case ColumnDisplayType.Date: return null; diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/profileNumber.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/profileNumber.tsx index c726fd20368..e2672d30f91 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/components/profileNumber.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/components/profileNumber.tsx @@ -24,8 +24,8 @@ interface ProfileNumberProps { * @returns The rendered component. */ export const ProfileNumber = (props: ProfileNumberProps) => { - // Hack let stats: any = props.instance.getColumnSummaryStats(props.columnIndex)?.number_stats!; + const nullCount = props.instance.getColumnNullCount(props.columnIndex); if (!stats) { stats = {}; } @@ -41,7 +41,7 @@ export const ProfileNumber = (props: ProfileNumberProps) => {
-
-999999
+
{nullCount}
{stats.mean}
{stats.median}
{stats.stdev}
diff --git a/src/vs/workbench/services/positronDataExplorer/browser/components/profileString.tsx b/src/vs/workbench/services/positronDataExplorer/browser/components/profileString.tsx index 229205cc65b..c8f367aa5d8 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/components/profileString.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/components/profileString.tsx @@ -7,11 +7,14 @@ import 'vs/css!./profileString'; // React. import * as React from 'react'; +import { TableSummaryDataGridInstance } from 'vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance'; /** * ProfileStringProps interface. */ interface ProfileStringProps { + instance: TableSummaryDataGridInstance; + columnIndex: number; } /** @@ -20,6 +23,11 @@ interface ProfileStringProps { * @returns The rendered component. */ export const ProfileString = (props: ProfileStringProps) => { + let stats: any = props.instance.getColumnSummaryStats(props.columnIndex)?.string_stats!; + const nullCount = props.instance.getColumnNullCount(props.columnIndex); + if (!stats) { + stats = {}; + } return (
@@ -29,15 +37,15 @@ export const ProfileString = (props: ProfileStringProps) => {
-
12
-
1
-
4
+
{nullCount}
+
{stats.num_empty}
+
{stats.num_unique}
-
+ {/*
 
.51
.20
-
+
*/}
); diff --git a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts index d35332fafe1..d65ae5cc734 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts +++ b/src/vs/workbench/services/positronDataExplorer/browser/positronDataExplorerInstance.ts @@ -9,6 +9,7 @@ import { DataExplorerClientInstance } from 'vs/workbench/services/languageRuntim import { TableSummaryDataGridInstance } from 'vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance'; import { PositronDataExplorerLayout } from 'vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerService'; import { IPositronDataExplorerInstance } from 'vs/workbench/services/positronDataExplorer/browser/interfaces/positronDataExplorerInstance'; +import { DataExplorerCache } from 'vs/workbench/services/positronDataExplorer/common/dataExplorerCache'; /** * PositronDataExplorerInstance class. @@ -21,6 +22,8 @@ export class PositronDataExplorerInstance extends Disposable implements IPositro */ private readonly _dataExplorerClientInstance: DataExplorerClientInstance; + private readonly _dataCache: DataExplorerCache; + /** * Gets or sets the layout. */ @@ -72,11 +75,14 @@ export class PositronDataExplorerInstance extends Disposable implements IPositro // Initialize. this._dataExplorerClientInstance = dataExplorerClientInstance; + this._dataCache = new DataExplorerCache(dataExplorerClientInstance); this._tableSchemaDataGridInstance = new TableSummaryDataGridInstance( - dataExplorerClientInstance + dataExplorerClientInstance, + this._dataCache ); this._tableDataDataGridInstance = new TableDataDataGridInstance( - dataExplorerClientInstance + dataExplorerClientInstance, + this._dataCache ); // Add event handlers. diff --git a/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx b/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx index b13eab707c7..d175f8d4020 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/tableDataDataGridInstance.tsx @@ -39,7 +39,9 @@ export class TableDataDataGridInstance extends DataGridInstance { * Constructor. * @param dataExplorerClientInstance The DataExplorerClientInstance. */ - constructor(dataExplorerClientInstance: DataExplorerClientInstance) { + constructor(dataExplorerClientInstance: DataExplorerClientInstance, + dataCache: DataExplorerCache + ) { // Call the base class's constructor. super({ columnHeaders: true, @@ -64,8 +66,8 @@ export class TableDataDataGridInstance extends DataGridInstance { // Setup the data explorer client instance. this._dataExplorerClientInstance = dataExplorerClientInstance; - // Allocate and initialize the DataExplorerCache. - this._dataExplorerCache = new DataExplorerCache(dataExplorerClientInstance); + // Set the shared data cache + this._dataExplorerCache = dataCache; // Add the onDidUpdateCache event handler. this._register(this._dataExplorerCache.onDidUpdateCache(() => diff --git a/src/vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance.tsx b/src/vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance.tsx index 8e7d379c53a..19b08d46d9f 100644 --- a/src/vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance.tsx +++ b/src/vs/workbench/services/positronDataExplorer/browser/tableSummaryDataGridInstance.tsx @@ -53,7 +53,9 @@ export class TableSummaryDataGridInstance extends DataGridInstance { * Constructor. * @param dataExplorerClientInstance The DataExplorerClientInstance. */ - constructor(dataExplorerClientInstance: DataExplorerClientInstance) { + constructor(dataExplorerClientInstance: DataExplorerClientInstance, + dataCache: DataExplorerCache + ) { // Call the base class's constructor. super({ columnHeaders: false, @@ -74,19 +76,23 @@ export class TableSummaryDataGridInstance extends DataGridInstance { // Set the data explorer client instance. this._dataExplorerClientInstance = dataExplorerClientInstance; - // Allocate and initialize the DataExplorerCache. - this._dataExplorerCache = new DataExplorerCache(dataExplorerClientInstance); + // Set the shared data cache + this._dataExplorerCache = dataCache; // Add the onDidUpdateCache event handler. - this._register(this._dataExplorerCache.onDidUpdateCache(() => - this._onDidUpdateEmitter.fire() - )); - + this._register(this._dataExplorerCache.onDidUpdateCache(() => { + this._onDidUpdateEmitter.fire(); + this._dataExplorerCache.cacheColumnSummaryStats([...this._expandedColumns]).then( + // Asynchronously update the summary stats for expanded columns then re-render + () => this._onDidUpdateEmitter.fire() + ); + })); // Add the onDidSchemaUpdate event handler. this._register(this._dataExplorerClientInstance.onDidSchemaUpdate(async () => { this.setScreenPosition(0, 0); this._expandedColumns.clear(); this.fetchData(); + })); } @@ -223,6 +229,10 @@ export class TableSummaryDataGridInstance extends DataGridInstance { ); } + getColumnNullCount(columnIndex: number): number | undefined { + return this._dataExplorerCache.getColumnNullCount(columnIndex); + } + getColumnNullPercent(columnIndex: number): number | undefined { const nullCount = this._dataExplorerCache.getColumnNullCount(columnIndex); // TODO: Is floor what we want? @@ -234,10 +244,6 @@ export class TableSummaryDataGridInstance extends DataGridInstance { return this._dataExplorerCache.getColumnSummaryStats(columnIndex); } - computeColumnSummaryStats(columnIndex: number) { - this._dataExplorerCache.updateColumnSummaryStats([columnIndex]); - } - //#endregion DataGridInstance Methods //#region Public Events @@ -265,12 +271,17 @@ export class TableSummaryDataGridInstance extends DataGridInstance { * @param columnIndex The columm index. */ toggleExpandColumn(columnIndex: number) { - // Tottle expand column. + // Toggle expand column. if (this._expandedColumns.has(columnIndex)) { this._expandedColumns.delete(columnIndex); } else { this._expandedColumns.add(columnIndex); this.scrollToRow(columnIndex); + + this._dataExplorerCache.cacheColumnSummaryStats([columnIndex]).then(() => { + // Re-render when the column summary stats return + this._onDidUpdateEmitter.fire(); + }); } // Fire the onDidUpdate event. diff --git a/src/vs/workbench/services/positronDataExplorer/common/dataExplorerCache.ts b/src/vs/workbench/services/positronDataExplorer/common/dataExplorerCache.ts index 2db4a89faa1..2ccfe3da221 100644 --- a/src/vs/workbench/services/positronDataExplorer/common/dataExplorerCache.ts +++ b/src/vs/workbench/services/positronDataExplorer/common/dataExplorerCache.ts @@ -111,19 +111,12 @@ export class DataExplorerCache extends Disposable { this._register(this._dataExplorerClientInstance.onDidSchemaUpdate(async () => { // Clear the column schema cache, row label cache, and data cell cache. this._columnSchemaCache.clear(); - this._columnNullCountCache.clear(); - this._columnSummaryStatsCache.clear(); - this._rowLabelCache.clear(); - this._dataCellCache.clear(); + this.invalidateDataCache(); })); // Add the onDidDataUpdate event handler. this._register(this._dataExplorerClientInstance.onDidDataUpdate(async () => { - // Clear the row label cache and data cell cache. - this._rowLabelCache.clear(); - this._dataCellCache.clear(); - this._columnNullCountCache.clear(); - this._columnSummaryStatsCache.clear(); + this.invalidateDataCache(); })); } @@ -207,7 +200,12 @@ export class DataExplorerCache extends Disposable { return this._columnSummaryStatsCache.get(columnIndex); } - async updateColumnSummaryStats(columnIndices: Array) { + async cacheColumnSummaryStats(columnIndices: Array) { + // Filter out summary stats that are already cached + columnIndices = columnIndices.filter(columnIndex => + !this._columnSummaryStatsCache.has(columnIndex) + ); + // Request the profiles const results = await this._dataExplorerClientInstance.getColumnProfiles( columnIndices.map(column_index => {