Skip to content

Commit fda12d6

Browse files
Handle query execution on View/Edit Data when server is disconnected with server reconnect option. #8608
1 parent ec3d142 commit fda12d6

File tree

3 files changed

+79
-15
lines changed

3 files changed

+79
-15
lines changed

web/pgadmin/tools/sqleditor/__init__.py

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1391,6 +1391,8 @@ def save(trans_id):
13911391
changed_data = json.loads(request.data)
13921392
else:
13931393
changed_data = request.args or request.form
1394+
# Check if connect is passed in the request.
1395+
connect = 'connect' in request.args and request.args['connect'] == '1'
13941396

13951397
# Check the transaction and connection status
13961398
status, error_msg, conn, trans_obj, session_obj = \
@@ -1416,10 +1418,21 @@ def save(trans_id):
14161418
}
14171419
)
14181420

1421+
if connect:
1422+
# This will check if view/edit data tool connection is lost or not,
1423+
# if lost then it will reconnect
1424+
status, error_msg, conn, trans_obj, session_obj, response = \
1425+
query_tool_connection_check(trans_id)
1426+
# This is required for asking user to enter password
1427+
# when password is not saved for the server
1428+
if response is not None:
1429+
return response
1430+
14191431
is_error, errmsg, conn = _check_and_connect(trans_obj)
14201432
if is_error:
1421-
return make_json_response(
1422-
data={'status': status, 'result': "{}".format(errmsg)}
1433+
return service_unavailable(
1434+
gettext("Connection to the server has been lost."),
1435+
info="CONNECTION_LOST"
14231436
)
14241437

14251438
status, res, query_results, _rowid = trans_obj.save(

web/pgadmin/tools/sqleditor/static/js/components/QueryToolComponent.jsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -543,9 +543,8 @@ export default function QueryToolComponent({params, pgWindow, pgAdmin, selectedN
543543
<br />
544544
<span>{gettext('Do you want to continue and establish a new session')}</span>
545545
</p>,
546-
function() {
547-
handleParams?.connectionLostCallback?.();
548-
}, null,
546+
() => handleParams?.connectionLostCallback?.(),
547+
() => handleParams?.cancelCallback?.(),
549548
gettext('Continue'),
550549
gettext('Cancel')
551550
);

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

Lines changed: 62 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ export class ResultSetUtils {
5151
this.historyQuerySource = null;
5252
this.hasQueryCommitted = false;
5353
this.queryToolCtx = queryToolCtx;
54+
this.setLoaderText = null;
5455
}
5556

5657
static generateURLReconnectionFlag(baseUrl, transId, shouldReconnect) {
@@ -445,23 +446,72 @@ export class ResultSetUtils {
445446
);
446447
}
447448

448-
saveData(reqData) {
449+
saveData(reqData, shouldReconnect) {
450+
// Generate the URL with the optional `connect=1` parameter.
451+
const url = ResultSetUtils.generateURLReconnectionFlag('sqleditor.save', this.transId, shouldReconnect);
452+
449453
return this.api.post(
450-
url_for('sqleditor.save', {
451-
'trans_id': this.transId
452-
}),
454+
url,
453455
JSON.stringify(reqData)
454-
).then(response => {
456+
).then((response) => {
455457
if (response.data?.data?.status) {
456458
// Set the commit flag to true if the save was successful
457459
this.hasQueryCommitted = true;
458460
}
459461
return response;
460-
}).catch((error) => {
461-
// Set the commit flag to false if there was an error
462-
this.hasQueryCommitted = false;
463-
throw error;
464-
});
462+
})
463+
.catch(async (error) => {
464+
if (error.response?.status === 428) {
465+
// Handle 428: Show password dialog.
466+
return new Promise((resolve, reject) => {
467+
this.connectServerModal(
468+
error.response?.data?.result,
469+
async (formData) => {
470+
try {
471+
await this.connectServer(
472+
this.queryToolCtx.params.sid,
473+
this.queryToolCtx.params.user,
474+
formData,
475+
async () => {
476+
let retryRespData = await this.saveData(reqData);
477+
// Set the commit flag to true if the save was successful
478+
this.hasQueryCommitted = true;
479+
pgAdmin.Browser.notifier.success(gettext('Server Connected.'));
480+
resolve(retryRespData);
481+
}
482+
);
483+
484+
} catch (retryError) {
485+
reject(retryError);
486+
}
487+
},
488+
() => this.setLoaderText(null)
489+
);
490+
});
491+
} else if (error.response?.status === 503) {
492+
// Handle 503: Fire HANDLE_API_ERROR and wait for connectionLostCallback.
493+
return new Promise((resolve, reject) => {
494+
this.eventBus.fireEvent(QUERY_TOOL_EVENTS.HANDLE_API_ERROR, error, {
495+
connectionLostCallback: async () => {
496+
try {
497+
// Retry saveData with connect=1
498+
let retryRespData = await this.saveData(reqData, true);
499+
resolve(retryRespData);
500+
} catch (retryError) {
501+
reject(retryError);
502+
}
503+
},
504+
checkTransaction: true,
505+
cancelCallback: () => this.setLoaderText(null)
506+
},
507+
);
508+
});
509+
} else {
510+
// Set the commit flag to false if there was an error
511+
this.hasQueryCommitted = false;
512+
throw error;
513+
}
514+
});
465515
}
466516

467517
async saveResultsToFile(fileName) {
@@ -861,6 +911,8 @@ export function ResultSet() {
861911

862912
rsu.current.setEventBus(eventBus);
863913
rsu.current.setQtPref(queryToolCtx.preferences?.sqleditor);
914+
// To use setLoaderText to the ResultSetUtils.
915+
rsu.current.setLoaderText = setLoaderText;
864916

865917
const isDataChanged = ()=>{
866918
return Boolean(_.size(dataChangeStore.updated) || _.size(dataChangeStore.added) || _.size(dataChangeStore.deleted));

0 commit comments

Comments
 (0)