Added PSQL tool support for the Windows platform.

Fixed following issues:
1. If the database name contains escape characters then PSQL unable to connect.
2. If the user terminates the connection by typing the 'exit' command, PSQL
   will show the connection termination msg.

Fixes #2341
pull/51/head
Nikhil Mohite 2021-06-08 14:58:43 +05:30 committed by Akshay Joshi
parent 5a086a9173
commit 9f12747d9b
10 changed files with 220 additions and 163 deletions

View File

@ -37,6 +37,7 @@ ldap3==2.*
Flask-BabelEx==0.* Flask-BabelEx==0.*
gssapi==1.6.* gssapi==1.6.*
flask-socketio>=5.0.1 flask-socketio>=5.0.1
eventlet==0.30.2 eventlet==0.31.0
httpagentparser==1.9.* httpagentparser==1.9.*
user-agents==2.2.0 user-agents==2.2.0
pywinpty==1.1.1; sys_platform=="win32"

View File

@ -506,61 +506,38 @@ def register_browser_preferences(self):
) )
) )
if sys.platform != 'win32': self.open_in_new_tab = self.preference.register(
self.open_in_new_tab = self.preference.register( 'tab_settings', 'new_browser_tab_open',
'tab_settings', 'new_browser_tab_open', gettext("Open in new browser tab"), 'select2', None,
gettext("Open in new browser tab"), 'select2', None, category_label=PREF_LABEL_OPTIONS,
category_label=PREF_LABEL_OPTIONS, options=[{'label': gettext('Query Tool'), 'value': 'qt'},
options=[{'label': gettext('Query Tool'), 'value': 'qt'}, {'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Debugger'), 'value': 'debugger'}, {'label': gettext('Schema Diff'), 'value': 'schema_diff'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'}, {'label': gettext('ERD Tool'), 'value': 'erd_tool'},
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}, {'label': gettext('PSQL Tool'), 'value': 'psql_tool'}],
{'label': gettext('PSQL Tool'), 'value': 'psql_tool'}], help_str=gettext(
help_str=gettext( 'Select Query Tool, Debugger, Schema Diff, ERD Tool '
'Select Query Tool, Debugger, Schema Diff, ERD Tool ' 'or PSQL Tool from the drop-down to set '
'or PSQL Tool from the drop-down to set ' 'open in new browser tab for that particular module.'
'open in new browser tab for that particular module.' ),
), select2={
select2={ 'multiple': True, 'allowClear': False,
'multiple': True, 'allowClear': False, 'tags': True, 'first_empty': False,
'tags': True, 'first_empty': False, 'selectOnClose': False, 'emptyOptions': True,
'selectOnClose': False, 'emptyOptions': True, 'tokenSeparators': [','],
'tokenSeparators': [','], 'placeholder': gettext('Select open new tab...')
'placeholder': gettext('Select open new tab...') }
} )
)
self.psql_tab_title = self.preference.register( self.psql_tab_title = self.preference.register(
'tab_settings', 'psql_tab_title_placeholder', 'tab_settings', 'psql_tab_title_placeholder',
gettext("PSQL tool tab title"), gettext("PSQL tool tab title"),
'text', '%DATABASE%/%USERNAME%@%SERVER%', 'text', '%DATABASE%/%USERNAME%@%SERVER%',
category_label=PREF_LABEL_DISPLAY, category_label=PREF_LABEL_DISPLAY,
help_str=gettext( help_str=gettext(
'Supported placeholders are %DATABASE%, %USERNAME%, ' 'Supported placeholders are %DATABASE%, %USERNAME%, '
'and %SERVER%. Users can provide any string with or without' 'and %SERVER%. Users can provide any string with or without'
' placeholders of their choice. The blank title will be revert' ' placeholders of their choice. The blank title will be revert'
' back to the default title with placeholders.' ' back to the default title with placeholders.'
)
)
else:
self.open_in_new_tab = self.preference.register(
'tab_settings', 'new_browser_tab_open',
gettext("Open in new browser tab"), 'select2', None,
category_label=PREF_LABEL_OPTIONS,
options=[{'label': gettext('Query Tool'), 'value': 'qt'},
{'label': gettext('Debugger'), 'value': 'debugger'},
{'label': gettext('Schema Diff'), 'value': 'schema_diff'},
{'label': gettext('ERD Tool'), 'value': 'erd_tool'}],
help_str=gettext(
'Select Query Tool, Debugger, Schema Diff, ERD Tool '
'or PSQL Tool from the drop-down to set '
'open in new browser tab for that particular module.'
),
select2={
'multiple': True, 'allowClear': False,
'tags': True, 'first_empty': False,
'selectOnClose': False, 'emptyOptions': True,
'tokenSeparators': [','],
'placeholder': gettext('Select open new tab...')
}
) )
)

View File

@ -66,7 +66,7 @@ define([
}]); }]);
// show psql tool same as query tool. // show psql tool same as query tool.
if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') { if(pgAdmin['enable_psql']) {
pgAdmin.Browser.add_menus([{ pgAdmin.Browser.add_menus([{
name: 'show_psql_tool', node: this.type, module: this, name: 'show_psql_tool', node: this.type, module: this,
applies: ['context'], callback: 'show_psql_tool', applies: ['context'], callback: 'show_psql_tool',

View File

@ -210,7 +210,7 @@ define('pgadmin.browser.node', [
icon: 'fa fa-search', enable: enable, icon: 'fa fa-search', enable: enable,
}]); }]);
if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') { if(pgAdmin['enable_psql']) {
// show psql tool same as query tool. // show psql tool same as query tool.
pgAdmin.Browser.add_menus([{ pgAdmin.Browser.add_menus([{
name: 'show_psql_tool', node: this.type, module: this, name: 'show_psql_tool', node: this.type, module: this,

View File

@ -59,7 +59,7 @@ let _defaultToolBarButtons = [
} }
]; ];
if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') { if(pgAdmin['enable_psql']) {
_defaultToolBarButtons.unshift({ _defaultToolBarButtons.unshift({
label: gettext('PSQL Tool'), label: gettext('PSQL Tool'),
ariaLabel: gettext('PSQL Tool'), ariaLabel: gettext('PSQL Tool'),
@ -119,7 +119,7 @@ export function initializeToolbar(panel, wcDocker) {
pgAdmin.DataGrid.show_filtered_row({mnuid: 4}, pgAdmin.Browser.tree.selected()); pgAdmin.DataGrid.show_filtered_row({mnuid: 4}, pgAdmin.Browser.tree.selected());
else if ('name' in data && data.name === gettext('Search objects')) else if ('name' in data && data.name === gettext('Search objects'))
pgAdmin.SearchObjects.show_search_objects('', pgAdmin.Browser.tree.selected()); pgAdmin.SearchObjects.show_search_objects('', pgAdmin.Browser.tree.selected());
else if ('name' in data && data.name === gettext('PSQL Tool') && pgAdmin['platform'] != 'win32'){ else if ('name' in data && data.name === gettext('PSQL Tool')){
var input = {}, var input = {},
t = pgAdmin.Browser.tree, t = pgAdmin.Browser.tree,
i = input.item || t.selected(), i = input.item || t.selected(),

View File

@ -63,7 +63,8 @@ def underscore_unescape(text):
""": '"', """: '"',
"`": '`', "`": '`',
"'": "'", "'": "'",
"'": "'" "'": "'",
""": '"'
} }
# always replace & first # always replace & first

View File

@ -1,5 +1,4 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import os import os
import re import re
import select import select
@ -20,7 +19,9 @@ from pgadmin.utils.driver import get_driver
from ... import socketio as sio from ... import socketio as sio
from pgadmin.utils import get_complete_file_path from pgadmin.utils import get_complete_file_path
if _platform != 'win32': if _platform == 'win32':
from winpty import PtyProcess
else:
import fcntl import fcntl
import termios import termios
import pty import pty
@ -101,8 +102,8 @@ def panel(trans_id):
return render_template('editor_template.html', return render_template('editor_template.html',
sid=params['sid'], sid=params['sid'],
db=underscore_unescape(params['db']) if params[ db=underscore_unescape(
'db'] else 'postgres', o_db_name) if o_db_name else 'postgres',
server_type=params['server_type'], server_type=params['server_type'],
is_enable=config.ENABLE_PSQL, is_enable=config.ENABLE_PSQL,
title=underscore_unescape(params['title']), title=underscore_unescape(params['title']),
@ -120,8 +121,13 @@ def set_term_size(fd, row, col, xpix=0, ypix=0):
:param xpix: :param xpix:
:param ypix: :param ypix:
""" """
term_size = struct.pack('HHHH', row, col, xpix, ypix) if _platform == 'win32':
fcntl.ioctl(fd, termios.TIOCSWINSZ, term_size) app.config['sessions'][request.sid].setwinsize(row, col)
# data = {'key_name': 'Enter', 'input': '\n'}
# socket_input(data)
else:
term_size = struct.pack('HHHH', row, col, xpix, ypix)
fcntl.ioctl(fd, termios.TIOCSWINSZ, term_size)
@sio.on('connect', namespace='/pty') @sio.on('connect', namespace='/pty')
@ -216,6 +222,19 @@ def read_terminal_data(parent, data_ready, max_read_bytes, sid):
session_last_cmd[request.sid]['invalid_cmd'] = False session_last_cmd[request.sid]['invalid_cmd'] = False
def read_stdout(process, sid, max_read_bytes, win_emit_output=True):
(data_ready, _, _) = select.select([process.fd], [], [], 0)
if process.fd in data_ready:
output = process.read(max_read_bytes)
if win_emit_output:
sio.emit('pty-output',
{'result': output,
'error': False},
namespace='/pty', room=sid)
sio.sleep(0)
@sio.on('start_process', namespace='/pty') @sio.on('start_process', namespace='/pty')
def start_process(data): def start_process(data):
""" """
@ -227,8 +246,24 @@ def start_process(data):
def read_and_forward_pty_output(sid, data): def read_and_forward_pty_output(sid, data):
max_read_bytes = 1024 * 20 max_read_bytes = 1024 * 20
import time
if _platform == 'win32':
os.environ['PYWINPTY_BACKEND'] = '1'
process = PtyProcess.spawn('cmd.exe')
process.write(r'"{0}" "{1}" 2>>&1'.format(connection_data[0],
connection_data[1]))
process.write("\r\n")
app.config['sessions'][request.sid] = process
pdata[request.sid] = process
set_term_size(process, 50, 50)
while True:
read_stdout(process, sid, max_read_bytes,
win_emit_output=True)
else:
if _platform != 'win32':
p, parent, fd = create_pty_terminal(connection_data) p, parent, fd = create_pty_terminal(connection_data)
while p and p.poll() is None: while p and p.poll() is None:
@ -248,12 +283,6 @@ def start_process(data):
timeout) timeout)
read_terminal_data(parent, data_ready, max_read_bytes, sid) read_terminal_data(parent, data_ready, max_read_bytes, sid)
else:
sio.emit(
'conn_error',
{
'error': 'PSQL tool not supported.',
}, namespace='/pty', room=request.sid)
# Check user is authenticated and PSQL is enabled in config. # Check user is authenticated and PSQL is enabled in config.
if current_user.is_authenticated and config.ENABLE_PSQL: if current_user.is_authenticated and config.ENABLE_PSQL:
@ -342,14 +371,14 @@ def get_connection_str(psql_utility, db, manager):
:param db: database name to connect specific db. :param db: database name to connect specific db.
:return: connection attribute list for PSQL connection. :return: connection attribute list for PSQL connection.
""" """
conn_attr = get_conn_str(manager, db) conn_attr = get_conn_str_win(manager, db)
conn_attr_list = list() conn_attr_list = list()
conn_attr_list.append(psql_utility) conn_attr_list.append(psql_utility)
conn_attr_list.append(conn_attr) conn_attr_list.append(conn_attr)
return conn_attr_list return conn_attr_list
def get_conn_str(manager, db): def get_conn_str_win(manager, db):
""" """
Get connection attributes for psql connection. Get connection attributes for psql connection.
:param manager: :param manager:
@ -357,46 +386,48 @@ def get_conn_str(manager, db):
:return: :return:
""" """
manager.export_password_env('PGPASSWORD') manager.export_password_env('PGPASSWORD')
db = db.replace('"', '\\"')
db = db.replace("'", "\\'")
conn_attr =\ conn_attr =\
'host={0} port={1} dbname={2} user={3} sslmode={4} ' \ 'host=\'{0}\' port=\'{1}\' dbname=\'{2}\' user=\'{3}\' ' \
'sslcompression={5} ' \ 'sslmode=\'{4}\' sslcompression=\'{5}\' ' \
''.format( ''.format(
manager.local_bind_host if manager.use_ssh_tunnel else manager.local_bind_host if manager.use_ssh_tunnel else
manager.host, manager.host,
manager.local_bind_port if manager.use_ssh_tunnel else manager.local_bind_port if manager.use_ssh_tunnel else
manager.port, manager.port,
underscore_unescape(db) if db != '' else 'postgres', db if db != '' else 'postgres',
underscore_unescape(manager.user) if manager.user else 'postgres', underscore_unescape(manager.user) if manager.user else 'postgres',
manager.ssl_mode, manager.ssl_mode,
True if manager.sslcompression else False, True if manager.sslcompression else False,
) )
if manager.hostaddr: if manager.hostaddr:
conn_attr = " {0} hostaddr={1}".format(conn_attr, manager.hostaddr) conn_attr = " {0} hostaddr='{1}'".format(conn_attr, manager.hostaddr)
if manager.passfile: if manager.passfile:
conn_attr = " {0} passfile={1}".format(conn_attr, conn_attr = " {0} passfile='{1}'".format(conn_attr,
get_complete_file_path( get_complete_file_path(
manager.passfile)) manager.passfile))
if get_complete_file_path(manager.sslcert): if get_complete_file_path(manager.sslcert):
conn_attr = " {0} sslcert={1}".format( conn_attr = " {0} sslcert='{1}'".format(
conn_attr, get_complete_file_path(manager.sslcert)) conn_attr, get_complete_file_path(manager.sslcert))
if get_complete_file_path(manager.sslkey): if get_complete_file_path(manager.sslkey):
conn_attr = " {0} sslkey={1}".format( conn_attr = " {0} sslkey='{1}'".format(
conn_attr, get_complete_file_path(manager.sslkey)) conn_attr, get_complete_file_path(manager.sslkey))
if get_complete_file_path(manager.sslrootcert): if get_complete_file_path(manager.sslrootcert):
conn_attr = " {0} sslrootcert={1}".format( conn_attr = " {0} sslrootcert='{1}'".format(
conn_attr, get_complete_file_path(manager.sslrootcert)) conn_attr, get_complete_file_path(manager.sslrootcert))
if get_complete_file_path(manager.sslcrl): if get_complete_file_path(manager.sslcrl):
conn_attr = " {0} sslcrl={1}".format( conn_attr = " {0} sslcrl='{1}'".format(
conn_attr, get_complete_file_path(manager.sslcrl)) conn_attr, get_complete_file_path(manager.sslcrl))
if manager.service: if manager.service:
conn_attr = " {0} service={1}".format( conn_attr = " {0} service='{1}'".format(
conn_attr, get_complete_file_path(manager.service)) conn_attr, get_complete_file_path(manager.service))
return conn_attr return conn_attr
@ -433,12 +464,27 @@ def invalid_cmd():
:rtype: :rtype:
""" """
session_last_cmd[request.sid]['invalid_cmd'] = True session_last_cmd[request.sid]['invalid_cmd'] = True
for i in range(len(session_input[request.sid])): if _platform == 'win32':
os.write(app.config['sessions'][request.sid], for i in range(len(session_input[request.sid])):
'\b \b'.encode()) app.config['sessions'][request.sid].write('\b \b')
app.config['sessions'][request.sid].write('\r\n')
os.write(app.config['sessions'][request.sid], sio.emit(
'\n'.encode()) 'pty-output',
{
'result': gettext(
"ERROR: Shell commands are disabled "
"in psql for security\r\n"),
'error': True
},
namespace='/pty', room=request.sid)
else:
for i in range(len(session_input[request.sid])):
os.write(app.config['sessions'][request.sid],
'\b \b'.encode())
os.write(app.config['sessions'][request.sid],
'\n'.encode())
session_input[request.sid] = '' session_input[request.sid] = ''
@ -464,18 +510,36 @@ def check_valid_cmd(user_input):
if stop_execution: if stop_execution:
session_last_cmd[request.sid]['invalid_cmd'] = True session_last_cmd[request.sid]['invalid_cmd'] = True
if _platform == 'win32':
# Remove already added command from terminal.
for i in range(len(user_input)):
app.config['sessions'][request.sid].write('\b \b')
app.config['sessions'][request.sid].write('\n')
# Remove already added command from terminal. sio.emit(
for i in range(len(user_input)): 'pty-output',
{
'result': gettext(
"ERROR: Shell commands are disabled "
"in psql for security\r\n"),
'error': True
},
namespace='/pty', room=request.sid)
else:
# Remove already added command from terminal.
for i in range(len(user_input)):
os.write(app.config['sessions'][request.sid],
'\b \b'.encode())
# Add Enter event to execute the command.
os.write(app.config['sessions'][request.sid], os.write(app.config['sessions'][request.sid],
'\b \b'.encode()) '\n'.encode())
# Add Enter event to execute the command.
os.write(app.config['sessions'][request.sid],
'\n'.encode())
else: else:
session_last_cmd[request.sid]['invalid_cmd'] = False session_last_cmd[request.sid]['invalid_cmd'] = False
os.write(app.config['sessions'][request.sid], if _platform == 'win32':
'\n'.encode()) app.config['sessions'][request.sid].write('\n')
else:
os.write(app.config['sessions'][request.sid],
'\n'.encode())
def enter_key_press(data): def enter_key_press(data):
@ -501,8 +565,8 @@ def enter_key_press(data):
not config.ALLOW_PSQL_SHELL_COMMANDS and\ not config.ALLOW_PSQL_SHELL_COMMANDS and\
not session_last_cmd[request.sid]['is_new_connection']: not session_last_cmd[request.sid]['is_new_connection']:
check_valid_cmd(user_input) check_valid_cmd(user_input)
elif user_input == '\q' or user_input == 'q\\q' or \ elif user_input == '\q' or user_input == 'q\\q' or user_input in ['exit',
user_input in ['exit', 'exit;']: 'exit;']:
# If user enter \q to terminate the PSQL, emit the msg to # If user enter \q to terminate the PSQL, emit the msg to
# notify user connection is terminated. # notify user connection is terminated.
sio.emit('pty-output', sio.emit('pty-output',
@ -514,12 +578,20 @@ def enter_key_press(data):
'error': True}, 'error': True},
namespace='/pty', room=request.sid) namespace='/pty', room=request.sid)
os.write(app.config['sessions'][request.sid], if _platform == 'win32':
'\n'.encode()) app.config['sessions'][request.sid].write('\n')
del app.config['sessions'][request.sid]
else:
os.write(app.config['sessions'][request.sid],
'\n'.encode())
else: else:
os.write(app.config['sessions'][request.sid], if _platform == 'win32':
data['input'].encode()) app.config['sessions'][request.sid].write(
"{0}".format(data['input']))
else:
os.write(app.config['sessions'][request.sid],
data['input'].encode())
session_input[request.sid] = '' session_input[request.sid] = ''
session_last_cmd[request.sid]['is_new_connection'] = False session_last_cmd[request.sid]['is_new_connection'] = False
@ -619,9 +691,13 @@ def other_key_press(data):
session_input[request.sid] = data['input'] session_input[request.sid] = data['input']
session_input_cursor[request.sid] += 1 session_input_cursor[request.sid] += 1
# Write user input to terminal parent fd. if _platform == 'win32':
os.write(app.config['sessions'][request.sid], app.config['sessions'][request.sid].write(
data['input'].encode()) "{0}".format(data['input']))
else:
# Write user input to terminal parent fd.
os.write(app.config['sessions'][request.sid],
data['input'].encode())
@sio.on('socket_input', namespace='/pty') @sio.on('socket_input', namespace='/pty')
@ -697,11 +773,17 @@ def server_disconnect(data):
def disconnect_socket(): def disconnect_socket():
os.write(app.config['sessions'][request.sid], '\q\n'.encode()) if _platform == 'win32':
sio.sleep(1) if request.sid in app.config['sessions']:
os.close(app.config['sessions'][request.sid]) process = app.config['sessions'][request.sid]
os.close(cdata[request.sid]) process.terminate()
del app.config['sessions'][request.sid] del app.config['sessions'][request.sid]
else:
os.write(app.config['sessions'][request.sid], '\q\n'.encode())
sio.sleep(1)
os.close(app.config['sessions'][request.sid])
os.close(cdata[request.sid])
del app.config['sessions'][request.sid]
def _get_database(sid, did): def _get_database(sid, did):

View File

@ -55,7 +55,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
}]; }];
this.enable_psql_tool = pgAdmin['enable_psql']; this.enable_psql_tool = pgAdmin['enable_psql'];
if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') { if(pgAdmin['enable_psql']) {
pgBrowser.add_menus(menus); pgBrowser.add_menus(menus);
} }
@ -156,11 +156,12 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
var tab_title_placeholder = pgBrowser.get_preferences_for_module('browser').psql_tab_title_placeholder; var tab_title_placeholder = pgBrowser.get_preferences_for_module('browser').psql_tab_title_placeholder;
panelTitle = generateTitle(tab_title_placeholder, title_data); panelTitle = generateTitle(tab_title_placeholder, title_data);
const [panelUrl, panelCloseUrl] = this.getPanelUrls(transId, panelTitle, parentData, gen); const [panelUrl, panelCloseUrl, db_label] = this.getPanelUrls(transId, panelTitle, parentData, gen);
let psqlToolForm = ` let psqlToolForm = `
<form id="psqlToolForm" action="${panelUrl}" method="post"> <form id="psqlToolForm" action="${panelUrl}" method="post">
<input id="title" name="title" hidden /> <input id="title" name="title" hidden />
<input id='db' value='${db_label}' hidden />
<input name="close_url" value="${panelCloseUrl}" hidden /> <input name="close_url" value="${panelCloseUrl}" hidden />
</form> </form>
<script> <script>
@ -228,9 +229,11 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
+`&did=${parentData.database._id}` +`&did=${parentData.database._id}`
+`&server_type=${parentData.server.server_type}` +`&server_type=${parentData.server.server_type}`
+ `&theme=${theme}`; + `&theme=${theme}`;
let db_label = '';
if(parentData.database && parentData.database._id) { if(parentData.database && parentData.database._id) {
let db_label = parentData.database._label.replace('\\', '\\\\'); db_label = _.escape(parentData.database._label.replace('\\', '\\\\'));
db_label = db_label.replace('\'', '\'');
db_label = db_label.replace('"', '\"');
openUrl += `&db=${db_label}`; openUrl += `&db=${db_label}`;
} else { } else {
openUrl += `&db=${''}`; openUrl += `&db=${''}`;
@ -239,7 +242,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
let closeUrl = url_for('psql.close', { let closeUrl = url_for('psql.close', {
trans_id: transId, trans_id: transId,
}); });
return [openUrl, closeUrl]; return [openUrl, closeUrl, db_label];
}, },
psql_terminal: function() { psql_terminal: function() {
// theme colors // theme colors
@ -375,4 +378,3 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
return pgBrowser.psql; return pgBrowser.psql;
} }

View File

@ -23,41 +23,36 @@
require( require(
['sources/generated/psql_tool'], ['sources/generated/psql_tool'],
function(pgBrowser) { function(pgBrowser) {
if (self.pgAdmin['platform'] != 'win32') { const term = self.pgAdmin.Browser.psql.psql_terminal();
const term = self.pgAdmin.Browser.psql.psql_terminal(); <!--Addon for fitAddon, webLinkAddon, SearchAddon -->
<!--Addon for fitAddon, webLinkAddon, SearchAddon --> const fitAddon = self.pgAdmin.Browser.psql.psql_Addon(term);
const fitAddon = self.pgAdmin.Browser.psql.psql_Addon(term); <!-- Update the theme for terminal as per pgAdmin 4 theme.-->
<!-- Update the theme for terminal as per pgAdmin 4 theme.--> self.pgAdmin.Browser.psql.set_theme(term);
self.pgAdmin.Browser.psql.set_theme(term); <!-- Open the terminal -->
<!-- Open the terminal --> term.open(document.getElementById('psql-terminal'));
term.open(document.getElementById('psql-terminal')); <!-- Socket-->
<!-- Socket--> const socket = self.pgAdmin.Browser.psql.psql_socket();
const socket = self.pgAdmin.Browser.psql.psql_socket(); self.pgAdmin.Browser.psql.psql_socket_io(socket, '{{is_enable}}', '{{sid}}', '{{db | replace("'", "\'")| replace('"', '\"') | replace('\\', '\\\\')}}', '{{server_type}}', fitAddon, term);
self.pgAdmin.Browser.psql.psql_socket_io(socket, '{{is_enable}}', '{{sid}}', '{{db}}', '{{server_type}}', fitAddon, term); self.pgAdmin.Browser.psql.psql_terminal_io(term, socket);
self.pgAdmin.Browser.psql.psql_terminal_io(term, socket); self.pgAdmin.Browser.psql.check_db_name_change('{{db}}', '{{o_db_name}}');
self.pgAdmin.Browser.psql.check_db_name_change('{{db}}', '{{o_db_name}}');
<!-- Resize the terminal --> <!-- Resize the terminal -->
function fitToscreen(){ function fitToscreen(){
fitAddon.fit() fitAddon.fit()
socket.emit("resize", {"cols": term.cols, "rows": term.rows}) socket.emit("resize", {"cols": term.cols, "rows": term.rows})
}
function debounce(func, wait_ms) {
let timeout
return function(...args) {
const context = this
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(context, args), wait_ms)
}
}
const wait_ms = 50;;
window.onresize = debounce(fitToscreen, wait_ms)
} else {
document.getElementById('psql-terminal').innterHTML = 'PSQL not supported'
} }
function debounce(func, wait_ms) {
let timeout
return function(...args) {
const context = this
clearTimeout(timeout)
timeout = setTimeout(() => func.apply(context, args), wait_ms)
}
}
const wait_ms = 50;;
window.onresize = debounce(fitToscreen, wait_ms)
}); });
{% endblock %} {% endblock %}

View File

@ -769,6 +769,10 @@ def configure_preferences(default_binary_path=None):
set_default_binary_path( set_default_binary_path(
default_binary_path[server], bin_paths, server) default_binary_path[server], bin_paths, server)
bin_paths_server_based = json.dumps(bin_paths['pg_bin_paths'])
if server == 'ppas':
bin_paths_server_based = json.dumps(bin_paths['as_bin_paths'])
pref_bin_path = paths_pref.preference('{0}_bin_dir'.format(server)) pref_bin_path = paths_pref.preference('{0}_bin_dir'.format(server))
user_pref = cur.execute( user_pref = cur.execute(
'SELECT pid, uid FROM user_preferences ' 'SELECT pid, uid FROM user_preferences '
@ -779,15 +783,10 @@ def configure_preferences(default_binary_path=None):
if user_pref_data: if user_pref_data:
cur.execute( cur.execute(
'UPDATE user_preferences SET value = ? WHERE pid = ?', 'UPDATE user_preferences SET value = ? WHERE pid = ?',
(pref_bin_path.default, pref_bin_path.pid) (bin_paths_server_based, pref_bin_path.pid)
) )
else: else:
if server == 'ppas': params = (pref_bin_path.pid, 1, bin_paths_server_based)
params = (pref_bin_path.pid, 1,
json.dumps(bin_paths['as_bin_paths']))
else:
params = (pref_bin_path.pid, 1,
json.dumps(bin_paths['pg_bin_paths']))
cur.execute( cur.execute(
insert_preferences_query, params insert_preferences_query, params
) )