Skip to content

Commit 40b6c1a

Browse files
committed
Fixed review comments
1. Used hash function in place of JSON.stringify(row) 2. Storing row identifiers in place of complete row object.
1 parent bc672e2 commit 40b6c1a

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

web/pgadmin/tools/sqleditor/static/js/components/sections/GeometryViewer.jsx

Lines changed: 41 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -198,26 +198,35 @@ function findPkColumn(columns) {
198198
return columns.find(c => PK_COLUMN_NAMES.includes(c.name));
199199
}
200200

201+
// Hash function for row objects
202+
function hashRow(row) {
203+
const str = Object.keys(row).sort().map(k => `${k}:${row[k]}`).join('|');
204+
let hash = 0;
205+
for (let i = 0; i < str.length; i++) {
206+
const char = str.charCodeAt(i);
207+
hash = ((hash << 5) - hash) + char;
208+
hash = hash & hash;
209+
}
210+
return `hash_${hash}`;
211+
}
212+
201213
// Get unique row identifier using PK column or first column
202214
function getRowIdentifier(row, pkColumn, columns) {
203215
if (pkColumn?.key && row[pkColumn.key] !== undefined) {
204216
return row[pkColumn.key];
205217
}
206218
const firstKey = columns[0]?.key;
207-
return firstKey && row[firstKey] !== undefined ? row[firstKey] : JSON.stringify(row);
208-
}
209-
210-
// Create Set of row identifiers
211-
function createIdentifierSet(rowData, pkColumn, columns) {
212-
return new Set(rowData.map(row => getRowIdentifier(row, pkColumn, columns)));
219+
if (firstKey && row[firstKey] !== undefined) {
220+
return row[firstKey];
221+
}
222+
return hashRow(row);
213223
}
214224

215225
// Match rows from previous selection to current rows
216-
function matchRowSelection(prevRowData, currentRows, pkColumn, columns) {
217-
if (prevRowData.length === 0) return [];
226+
function matchRowSelection(prevIdentifiers, currentRows, pkColumn, columns) {
227+
if (prevIdentifiers.size === 0) return [];
218228

219-
const prevIdSet = createIdentifierSet(prevRowData, pkColumn, columns);
220-
return currentRows.filter(row => prevIdSet.has(getRowIdentifier(row, pkColumn, columns)));
229+
return currentRows.filter(row => prevIdentifiers.has(getRowIdentifier(row, pkColumn, columns)));
221230
}
222231

223232
function PopupTable({data}) {
@@ -492,7 +501,7 @@ export function GeometryViewer({rows, columns, column}) {
492501
const prevStateRef = React.useRef({
493502
columnKey: null,
494503
columnNames: null,
495-
selectedRowData: [],
504+
selectedRowIdentifiers: new Set(),
496505
});
497506

498507
const [mapKey, setMapKey] = React.useState(0);
@@ -513,7 +522,7 @@ export function GeometryViewer({rows, columns, column}) {
513522
prevStateRef.current = {
514523
columnKey: null,
515524
columnNames: null,
516-
selectedRowData: [],
525+
selectedRowIdentifiers: new Set(),
517526
};
518527
return;
519528
}
@@ -524,32 +533,46 @@ export function GeometryViewer({rows, columns, column}) {
524533
prevStateRef.current = {
525534
columnKey: currentColumnKey,
526535
columnNames: currentColumnNames,
527-
selectedRowData: rows,
536+
selectedRowIdentifiers: new Set(rows.map(r => getRowIdentifier(r, pkColumn, columns))),
528537
};
529538
return;
530539
}
531540

532541
if (currentColumnKey === prevState.columnKey &&
533542
currentColumnNames === prevState.columnNames &&
534543
rows.length > 0) {
535-
prevStateRef.current.selectedRowData = displayRows;
544+
prevStateRef.current.selectedRowIdentifiers = new Set(
545+
displayRows.map(r => getRowIdentifier(r, pkColumn, columns))
546+
);
536547
}
537548
}, [currentColumnKey, currentColumnNames, rows, pkColumn, columns]);
538549

539550
// Get rows to display based on selection
540551
const displayRows = React.useMemo(() => {
552+
// No geometry column selected or no rows available - nothing to display
541553
if (!currentColumnKey || rows.length === 0) return [];
542554
const prevState = prevStateRef.current;
555+
556+
// Column context changed (different geometry column or different query schema)
557+
// Show all new rows since previous selection is no longer valid
543558
if (currentColumnKey !== prevState.columnKey || currentColumnNames !== prevState.columnNames) {
544559
return rows;
545560
}
546561

547-
const prevSelected = prevState.selectedRowData;
548-
if (prevSelected.length === 0) return rows;
549-
if (prevSelected.length < rows.length) {
550-
const matched = matchRowSelection(prevSelected, rows, pkColumn, columns);
562+
const prevIdentifiers = prevState.selectedRowIdentifiers;
563+
// No previous selection recorded - show all rows
564+
if (prevIdentifiers.size === 0) return rows;
565+
566+
// Previous selection was a subset of total rows, meaning user had specific rows selected.
567+
// Try to match those previously selected rows in the new result set using stable
568+
// row identifiers (PK value, first column value, or hash fallback).
569+
// This handles the case where same query reruns with more/fewer rows
570+
if (prevIdentifiers.size < rows.length) {
571+
const matched = matchRowSelection(prevIdentifiers, rows, pkColumn, columns);
572+
// If matched rows found, show only those; otherwise fall back to all rows
551573
return matched.length > 0 ? matched : rows;
552574
}
575+
// Previous selection covered all rows (or same count) - show all current rows
553576
return rows;
554577
}, [rows, currentColumnKey, currentColumnNames, pkColumn, columns]);
555578

0 commit comments

Comments
 (0)