Skip to content

Commit 8c66242

Browse files
Display a confirmation message for the server-side cursor transaction status when closing the query tool.
Resolve the pagination issue by fetching an additional row to determine the availability of the next record set when using a server-side cursor.
1 parent 13ade4c commit 8c66242

3 files changed

Lines changed: 27 additions & 10 deletions

File tree

web/pgadmin/tools/sqleditor/__init__.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,8 +1252,12 @@ def fetch_window(trans_id, from_rownum=0, to_rownum=0):
12521252

12531253
if status and conn is not None and session_obj is not None:
12541254
# rownums start from 0 but UI will ask from 1
1255+
# to_rownum: Fetch 1 extra row to check whether next
1256+
# recordset is available or not, this is required for server cursor.
1257+
12551258
status, result = conn.async_fetchmany_2darray(
1256-
records=None, from_rownum=from_rownum - 1, to_rownum=to_rownum - 1)
1259+
records=None, from_rownum=from_rownum - 1, to_rownum=to_rownum if
1260+
trans_obj.server_cursor else to_rownum - 1)
12571261
if not status:
12581262
status = 'Error'
12591263
else:
@@ -1270,14 +1274,22 @@ def fetch_window(trans_id, from_rownum=0, to_rownum=0):
12701274
result = error_msg
12711275

12721276
page_size = to_rownum - from_rownum + 1
1277+
1278+
# Check whether the next recordset/page is available or not
1279+
next_page = 0
1280+
if trans_obj.server_cursor and len(result) > 0 and len(result) > page_size:
1281+
result = result[0:len(result) - 1]
1282+
next_page = 1
1283+
rows_fetched_to = rows_fetched_to - 1
1284+
12731285
pagination = {
12741286
'page_size': page_size,
12751287
'page_count': math.ceil(conn.total_rows / page_size),
12761288
'page_no': math.floor((rows_fetched_from - 1) / page_size) + 1,
12771289
'rows_from': rows_fetched_from,
1278-
'rows_to': rows_fetched_to
1290+
'rows_to': rows_fetched_to,
1291+
'next_page': next_page
12791292
}
1280-
12811293
return make_json_response(
12821294
data={
12831295
'status': status,

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

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -249,11 +249,17 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
249249
return;
250250
}
251251
}
252+
let _confirm_msg = gettext('The current transaction is not committed to the database. '
253+
+'Do you want to commit or rollback the transaction?');
254+
if (queryToolCtx.server_cursor) {
255+
_confirm_msg = gettext('The query was executed with a server-side cursor, '
256+
+ 'which runs within a transaction.') + _confirm_msg;
257+
}
258+
252259
queryToolCtx.modal.showModal(gettext('Commit transaction?'), (closeModal)=>(
253260
<ConfirmTransactionContent
254261
closeModal={closeModal}
255-
text={gettext('The current transaction is not committed to the database. '
256-
+'Do you want to commit or rollback the transaction?')}
262+
text={_confirm_msg}
257263
onRollback={()=>{
258264
onExecutionDone();
259265
onRollbackClick();
@@ -267,8 +273,8 @@ export function MainToolBar({containerRef, onFilterClick, onManageMacros, onAddT
267273
};
268274
useEffect(()=>{
269275
if(isInTxn()) {
270-
setDisableButton('commit', queryToolCtx.params.server_cursor && !queryToolCtx.params.is_query_tool ?true:false);
271-
setDisableButton('rollback', queryToolCtx.params.server_cursor && !queryToolCtx.params.is_query_tool ?true:false);
276+
setDisableButton('commit', queryToolCtx.params.server_cursor && !queryToolCtx.params.is_query_tool ? true : false);
277+
setDisableButton('rollback', queryToolCtx.params.server_cursor && !queryToolCtx.params.is_query_tool ? true : false);
272278
setDisableButton('execute-options', true);
273279
} else {
274280
setDisableButton('commit', true);

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

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,15 +228,14 @@ function PaginationInputs({pagination, totalRowCount, clearSelection, serverCurs
228228
value={inputs.pageNo}
229229
onChange={(value)=>onInputChange('pageNo', value)}
230230
onKeyDown={onInputKeydownPageNo}
231-
disabled={serverCursor}
232231
error={errorInputs['pageNo']}
233232
/>
234233
<span> {gettext('of')} {pagination.page_count}</span>
235234
<div className='PaginationInputs-divider'>&nbsp;</div>
236235
<PgButtonGroup size="small">
237-
<PgIconButton title={gettext('First Page')} disabled={pagination.page_no <= 1 || serverCursor} onClick={()=>goToPage(1)} icon={<SkipPreviousRoundedIcon />}/>
236+
<PgIconButton title={gettext('First Page')} disabled={pagination.page_no <= 1} onClick={()=>goToPage(1)} icon={<SkipPreviousRoundedIcon />}/>
238237
<PgIconButton title={gettext('Previous Page')} disabled={pagination.page_no <= 1} onClick={()=>goToPage(pagination.page_no-1)} icon={<FastRewindRoundedIcon />}/>
239-
<PgIconButton title={gettext('Next Page')} disabled={pagination.page_no == pagination.page_count && !serverCursor} onClick={()=>goToPage(pagination.page_no+1)} icon={<FastForwardRoundedIcon />}/>
238+
<PgIconButton title={gettext('Next Page')} disabled={(pagination.page_no == pagination.page_count && !serverCursor) || (serverCursor && pagination.next_page == 0)} onClick={()=>goToPage(pagination.page_no+1)} icon={<FastForwardRoundedIcon />}/>
240239
<PgIconButton title={gettext('Last Page')} disabled={pagination.page_no == pagination.page_count || serverCursor} onClick={()=>goToPage(pagination.page_count)} icon={<SkipNextRoundedIcon />} />
241240
</PgButtonGroup>
242241
</Box>

0 commit comments

Comments
 (0)