@@ -31,6 +31,7 @@ import { GraphVisualiser } from './GraphVisualiser';
3131import { usePgAdmin } from '../../../../../../static/js/PgAdminProvider' ;
3232import pgAdmin from 'sources/pgadmin' ;
3333import { connectServer , connectServerModal } from '../connectServer' ;
34+ import { useLatestFunc } from '../../../../../../static/js/custom_hooks' ;
3435
3536const StyledBox = styled ( Box ) ( ( { theme} ) => ( {
3637 display : 'flex' ,
@@ -846,7 +847,7 @@ export function ResultSet() {
846847 const modalId = MODAL_DIALOGS . QT_CONFIRMATIONS ;
847848 // We'll use this track if any changes were saved.
848849 // It will help to decide whether results refresh is required or not on page change.
849- const pageDataDirty = useRef ( false ) ;
850+ const pageDataOutOfSync = useRef ( false ) ;
850851
851852 const selectedCell = useRef ( [ ] ) ;
852853 const selectedRange = useRef ( null ) ;
@@ -873,9 +874,10 @@ export function ResultSet() {
873874 // To use setLoaderText to the ResultSetUtils.
874875 rsu . current . setLoaderText = setLoaderText ;
875876
876- const isDataChanged = ( ) => {
877- return Boolean ( _ . size ( dataChangeStore . updated ) || _ . size ( dataChangeStore . added ) || _ . size ( dataChangeStore . deleted ) ) ;
878- } ;
877+ const isDataChangedRef = useRef ( false ) ;
878+ useEffect ( ( ) => {
879+ isDataChangedRef . current = Boolean ( _ . size ( dataChangeStore . updated ) || _ . size ( dataChangeStore . added ) || _ . size ( dataChangeStore . deleted ) ) ;
880+ } , [ dataChangeStore ] ) ;
879881
880882 const fireRowsColsCellChanged = ( ) => {
881883 eventBus . fireEvent ( QUERY_TOOL_EVENTS . SELECTED_ROWS_COLS_CELL_CHANGED , selectedRows . size , selectedColumns . size , selectedRange . current , selectedCell . current ?. length ) ;
@@ -948,7 +950,7 @@ export function ResultSet() {
948950 } ) ;
949951 } ;
950952
951- if ( isDataChanged ( ) && ! refreshData ) {
953+ if ( isDataChangedRef . current && ! refreshData ) {
952954 queryToolCtx . modal . confirm (
953955 gettext ( 'Unsaved changes' ) ,
954956 gettext ( 'The data has been modified, but not saved. Are you sure you wish to discard the changes?' ) ,
@@ -1093,6 +1095,7 @@ export function ResultSet() {
10931095 setLoaderText ( gettext ( 'Fetching rows...' ) ) ;
10941096 try {
10951097 res = await rsu . current . getWindowRows ( fromRownum , toRownum ) ;
1098+ resetSelectionAndChanges ( ) ;
10961099 const newRows = rsu . current . processRows ( res . data . data . result , columns ) ;
10971100 setRows ( [ ...newRows ] ) ;
10981101 setQueryData ( ( prev ) => ( {
@@ -1119,18 +1122,33 @@ export function ResultSet() {
11191122 useEffect ( ( ) => {
11201123 let deregExecEnd ;
11211124 const deregFetch = eventBus . registerListener ( QUERY_TOOL_EVENTS . FETCH_WINDOW , ( ...args ) => {
1122- if ( pageDataDirty . current ) {
1123- deregExecEnd = eventBus . registerListener ( QUERY_TOOL_EVENTS . EXECUTION_END , ( success ) => {
1124- if ( ! success ) return ;
1125- pageDataDirty . current = false ;
1125+ const impl = ( ) => {
1126+ if ( pageDataOutOfSync . current ) {
1127+ deregExecEnd = eventBus . registerListener ( QUERY_TOOL_EVENTS . EXECUTION_END , ( success ) => {
1128+ if ( ! success ) return ;
1129+ pageDataOutOfSync . current = false ;
1130+ fetchWindow ( ...args ) ;
1131+ } , true ) ;
1132+ eventBus . fireEvent ( QUERY_TOOL_EVENTS . EXECUTION_START , rsu . current . query , { refreshData : true } ) ;
1133+ // executionStartCallback(rsu.current.query, {refreshData: true});
1134+ } else {
1135+ pageDataOutOfSync . current = false ;
11261136 fetchWindow ( ...args ) ;
1127- } , true ) ;
1128- executionStartCallback ( rsu . current . query , { refreshData : true } ) ;
1137+ }
1138+ } ;
1139+
1140+ if ( isDataChangedRef . current ) {
1141+ queryToolCtx . modal . confirm (
1142+ gettext ( 'Unsaved changes' ) ,
1143+ gettext ( 'The data has been modified, but not saved. Are you sure you wish to discard the changes?' ) ,
1144+ impl ,
1145+ function ( ) {
1146+ /* Do nothing */
1147+ }
1148+ ) ;
11291149 } else {
1130- pageDataDirty . current = false ;
1131- fetchWindow ( ...args ) ;
1150+ impl ( ) ;
11321151 }
1133- resetSelectionAndChanges ( ) ;
11341152 } ) ;
11351153 return ( ) => {
11361154 deregFetch ( ) ;
@@ -1144,7 +1162,7 @@ export function ResultSet() {
11441162
11451163 const warnSaveDataClose = ( ) => {
11461164 // No changes.
1147- if ( ! isDataChanged ( ) || ! queryToolCtx . preferences ?. sqleditor . prompt_save_data_changes ) {
1165+ if ( ! isDataChangedRef . current || ! queryToolCtx . preferences ?. sqleditor . prompt_save_data_changes ) {
11481166 eventBus . fireEvent ( QUERY_TOOL_EVENTS . WARN_SAVE_TEXT_CLOSE ) ;
11491167 return ;
11501168 }
@@ -1172,7 +1190,7 @@ export function ResultSet() {
11721190 } ;
11731191 } , [ dataChangeStore ] ) ;
11741192
1175- const triggerSaveData = async ( ) => {
1193+ const triggerSaveData = useLatestFunc ( async ( ) => {
11761194 if ( ! _ . size ( dataChangeStore . updated ) && ! _ . size ( dataChangeStore . added ) && ! _ . size ( dataChangeStore . deleted ) ) {
11771195 return ;
11781196 }
@@ -1210,7 +1228,7 @@ export function ResultSet() {
12101228 } catch { /* History errors should not bother others */ }
12111229
12121230 if ( ! respData . data . status ) {
1213- pageDataDirty . current = false ;
1231+ pageDataOutOfSync . current = false ;
12141232 eventBus . fireEvent ( QUERY_TOOL_EVENTS . SET_MESSAGE , respData . data . result ) ;
12151233 pgAdmin . Browser . notifier . error ( respData . data . result , 20000 ) ;
12161234 // If the transaction is not idle, notify the user that previous queries are not rolled back,
@@ -1223,7 +1241,7 @@ export function ResultSet() {
12231241 return ;
12241242 }
12251243
1226- pageDataDirty . current = true ;
1244+ pageDataOutOfSync . current = true ;
12271245 if ( _ . size ( dataChangeStore . added ) ) {
12281246 // Update the rows in a grid after addition
12291247 respData . data . query_results . forEach ( ( qr ) => {
@@ -1258,18 +1276,19 @@ export function ResultSet() {
12581276 resetSelectionAndChanges ( ) ;
12591277 eventBus . fireEvent ( QUERY_TOOL_EVENTS . SET_CONNECTION_STATUS , respData . data . transaction_status ) ;
12601278 eventBus . fireEvent ( QUERY_TOOL_EVENTS . SET_MESSAGE , '' ) ;
1279+ setLoaderText ( null ) ;
12611280 pgAdmin . Browser . notifier . success ( gettext ( 'Data saved successfully.' ) ) ;
12621281 if ( respData . data . transaction_status > CONNECTION_STATUS . TRANSACTION_STATUS_IDLE ) {
12631282 pgAdmin . Browser . notifier . info ( gettext ( 'Auto-commit is off. You still need to commit changes to the database.' ) ) ;
12641283 }
12651284 } catch ( error ) {
1266- pageDataDirty . current = false ;
1285+ pageDataOutOfSync . current = false ;
12671286 eventBus . fireEvent ( QUERY_TOOL_EVENTS . HANDLE_API_ERROR , error , {
12681287 checkTransaction : true ,
12691288 } ) ;
1289+ setLoaderText ( null ) ;
12701290 }
1271- setLoaderText ( null ) ;
1272- } ;
1291+ } ) ;
12731292
12741293 useEffect ( ( ) => {
12751294 eventBus . registerListener ( QUERY_TOOL_EVENTS . TRIGGER_SAVE_DATA , triggerSaveData ) ;
0 commit comments