public inbox for [email protected]  
help / color / mirror / Atom feed
From: Nikhil Mohite <[email protected]>
To: pgadmin-hackers <[email protected]>
Cc: Dave Page <[email protected]>
Cc: Akshay Joshi <[email protected]>
Subject: Re: [pgAdmin][RM-2341]: Add menu option for starting PSQL
Date: Mon, 7 Jun 2021 11:15:29 +0530
Message-ID: <CAOBg0ANMJTzaEQdcEwUnLLGJXSbsT6=0L8Jvs_MTuBTfj0YtrQ@mail.gmail.com> (raw)
In-Reply-To: <CANxoLDcfbqO5qYOV=LE8x1ocVEUoLD7bCm_UXYHmXL2=n9kX7A@mail.gmail.com>
References: <CAOBg0AO6Tjksb+EOA_-O13yRzdL_2d3y6G74m=GGQS+Ymjv=0g@mail.gmail.com>
	<CA+OCxow9+UDMrsBBvJKW2AeAYaN4cO3w7kBGNKtsWhSM6_D7gQ@mail.gmail.com>
	<CAOBg0AMVyLBma8wsbZ-VQWF4q3OAhqWeRLpmrxVcM_YOKH+MDQ@mail.gmail.com>
	<CANxoLDd2xMu7ym9PFdhYUSy4ucNuPoZ2fvaRkuwyB+EqowLXwA@mail.gmail.com>
	<CA+OCxowoz1oFE=eMKEnfFtf=oDrkPKHGfZpUGRW-sG_tpfMBTw@mail.gmail.com>
	<CAOBg0ANFNvtD-LoFxXcLY5JJ4BVH5zNyrmdBED6B++-nKf012g@mail.gmail.com>
	<CA+OCxowW7BEZzULbEpn73ygqWtWkUwdCAB3PMcHocUeQXcM3ow@mail.gmail.com>
	<CAOBg0APGPTA4qNNryAXMwKP63uFLxQdQwnFdDXMjSr4OeH-HAg@mail.gmail.com>
	<CA+OCxozYus58i3BhP37E-2Xc6Nq5zrJegcq+eANWpvN++_LtXw@mail.gmail.com>
	<CAOBg0AO7NfJjLLFD8g5NkkbbnKiCSR5g9yshxc-65sWk2sFyBA@mail.gmail.com>
	<CA+OCxoxdaBmh6e4Fo1F_+vZExq8SPUyGAByRzOPy2kz_vgRiSA@mail.gmail.com>
	<CAOBg0AO6A10OHiQAOOguagW1mNzfK1oVPHG9W+JSCkYjR+xQkA@mail.gmail.com>
	<CA+OCxoxpyfJabnycSGmtUK1-QEndNfZV3q2d1xP-oftDn-pGDw@mail.gmail.com>
	<CANxoLDexHsJQcrd6ZrkjCub+xj_Ke+dDp_Av5no84MOJH1uC_g@mail.gmail.com>
	<CAOBg0AN6Gb9gp1F=jKeefAz6d0U2GSjC40qAJ8i7psor2KmQLA@mail.gmail.com>
	<CANxoLDd3QdOPY7Y6kDCSy99s3DFrbdhP9LNxphsEg9B5G14Dbg@mail.gmail.com>
	<CAOBg0AN3eSLvS_cG7R3WiTpfBxiJfi2YB6sV8NBWiakioXRAsQ@mail.gmail.com>
	<CANxoLDdGeNOBZJu-v9YaefKeTSGcCcU2DQic1MQU9jYYLJ6K_Q@mail.gmail.com>
	<CAOBg0AO-gsDJSrLoGPJGKsq772Okgg3BWDuERaaGSDvoGbhQAA@mail.gmail.com>
	<CA+OCxozEBo7-8hSeWo8K9mAL5E5MkeW3JG+JnjJXMEkT6q8SNg@mail.gmail.com>
	<CANxoLDcfbqO5qYOV=LE8x1ocVEUoLD7bCm_UXYHmXL2=n9kX7A@mail.gmail.com>

Hi Team,

Please find the updated patch for added psql tool for windows platform.
Also fixed a few issues reported by Fahar.
1. If the database name contains escape characters psql unable to connect.
2. If the user terminates the connection by entering "exit", psql will show
connection termination msg.


Regards,
Nikhil Mohite.

On Thu, Jun 3, 2021 at 2:10 PM Akshay Joshi <[email protected]>
wrote:

>
>
> On Thu, Jun 3, 2021 at 2:07 PM Dave Page <[email protected]> wrote:
>
>> Hi
>>
>> On Tue, Jun 1, 2021 at 12:58 PM Nikhil Mohite <
>> [email protected]> wrote:
>>
>>> Hi Team,
>>>
>>> Following are few points related to PSQL tool on windows:
>>>
>>>    1.  Currently using the *pywinpty* library on windows to create pty
>>>    process and execute the  psql.exe.
>>>    2. To read the stderr (errors) currently using '2>>&1' arguments to
>>>    psql.exe command. (It will redirect stderr to stdout )
>>>    3. Windows conPTY is available on Windows 10 only (released after
>>>    2018).
>>>    4. Windows conPTY does not support the Asynchronous I/O, so to get
>>>    the terminal output, need to add the read function after every command
>>>    execution. (something like select() is not available)
>>>    5. Also found some performance issues with psql on windows.
>>>       1. To read the output from the terminal need to add some sleep
>>>       time as it will take time to return the output.
>>>       2. Resize the terminal is also not consistent and causing the
>>>       issue if we resize the window faster or multiple times very quickly.
>>>       3. Loading large dataset sometimes cause system to non-responsive
>>>       state.(In this state restart requires)
>>>
>>> Please find the patch for disable the psql tool for windows
>>> platform.(Windows builds are falling due to this sending patch for disable
>>> psql on windows.)
>>>
>>
>> Disabling major features on our most common deployment platform really
>> isn't a good option. I assume all of the above options are related to lack
>> of async I/O?
>>
>
>     We have temporarily disabled the feature until found a solution, to
> generate the nightly build for testing.
>
>>
>> Have you tried forcing the use of winpty rather than conpty?
>>
>>
>>>
>>> Reference  links:
>>>
>>>    1. https://github.com/microsoft/terminal/issues/262
>>>    2.
>>>    https://devblogs.microsoft.com/commandline/windows-command-line-introducing-the-windows-pseudo-conso....
>>>    3. https://pypi.org/project/pywinpty/
>>>
>>>
>>> If any suggestions or questions please let me know.
>>>
>>> Regards,
>>> Nikhil Mohite.
>>>
>>> On Tue, May 25, 2021 at 8:20 PM Akshay Joshi <
>>> [email protected]> wrote:
>>>
>>>> Thanks, patch applied.
>>>>
>>>> I have updated the screenshot and some documentation stuff.
>>>>
>>>> On Tue, May 25, 2021 at 3:08 PM Nikhil Mohite <
>>>> [email protected]> wrote:
>>>>
>>>>> Hi Akshay,
>>>>>
>>>>>
>>>>> Please find the updated patch. (V6)
>>>>> On Tue, May 25, 2021 at 2:55 PM Akshay Joshi <
>>>>> [email protected]> wrote:
>>>>>
>>>>>> Hi Nikhil
>>>>>>
>>>>>> Please rebase and send the patch again.
>>>>>>
>>>>>> On Tue, May 25, 2021 at 2:52 PM Nikhil Mohite <
>>>>>> [email protected]> wrote:
>>>>>>
>>>>>>> Hi Akshay/ Team
>>>>>>>
>>>>>>> On Mon, May 24, 2021 at 9:19 PM Akshay Joshi <
>>>>>>> [email protected]> wrote:
>>>>>>>
>>>>>>>> Hi Nikhil
>>>>>>>>
>>>>>>>> Following are the review comments:
>>>>>>>>
>>>>>>>>    - Set "ENABLE_PSQL = False", PSQL button from browser tree and
>>>>>>>>    context menu option should not be visible.
>>>>>>>>    - Documentation screenshot should be in standard theme for
>>>>>>>>    consistency, and check the size it's very large. Take the screenshot with
>>>>>>>>    the new PSQL button on the browser tree.
>>>>>>>>    - Update 'menu_bar.rst' and 'toolbar.rst' with new changes.
>>>>>>>>    - Remove commented code (if any)
>>>>>>>>    - Check SonarQube (I haven't run)
>>>>>>>>
>>>>>>>> Please find the updated patch, resolve all the review comments, and
>>>>>>> update the code to resolve the SonarQube issues.
>>>>>>>
>>>>>>>>
>>>>>>>> On Thu, May 20, 2021 at 2:52 PM Dave Page <[email protected]>
>>>>>>>> wrote:
>>>>>>>>
>>>>>>>>> Thanks Nikhil. Can someone else review this version please?
>>>>>>>>>
>>>>>>>>> On Wed, May 19, 2021 at 2:42 PM Nikhil Mohite <
>>>>>>>>> [email protected]> wrote:
>>>>>>>>>
>>>>>>>>>> Hi Dave/ Team,
>>>>>>>>>>
>>>>>>>>>> On Wed, May 19, 2021 at 1:43 PM Dave Page <[email protected]>
>>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>>> Hi
>>>>>>>>>>>
>>>>>>>>>>> On Wed, May 19, 2021 at 8:58 AM Nikhil Mohite <
>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>
>>>>>>>>>>>> Hi Dave/ Team,
>>>>>>>>>>>>
>>>>>>>>>>>> On Tue, May 18, 2021 at 8:41 PM Dave Page <[email protected]>
>>>>>>>>>>>> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Hi
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Tue, May 18, 2021 at 12:12 PM Nikhil Mohite <
>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>
>>>>>>>>>>>>> Hi Dave/Team,
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> On Mon, May 17, 2021 at 6:47 PM Dave Page <[email protected]>
>>>>>>>>>>>>> wrote:
>>>>>>>>>>>>>
>>>>>>>>>>>>>> Hi
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> On Mon, May 17, 2021 at 11:01 AM Nikhil Mohite <
>>>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Hi Akshay/ Team,
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> Please find the attached updated patch for the psql tool.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Hmm, this version is also broken. There's a typo in
>>>>>>>>>>>>>> editor_template.html on line 138 - it splits a string across two lines
>>>>>>>>>>>>>> which throws an error. Having fixed that...
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I also note there's a lot of Javascript in that HTML file.
>>>>>>>>>>>>>> That should be pushed into the webpacked bundle I think, and not included
>>>>>>>>>>>>>> inline in HTML.
>>>>>>>>>>>>>>
>>>>>>>>>>>>> I have moved most of the code in the js file, few things are
>>>>>>>>>>>>> still in HTML.
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Hmm, yes - in particular, colours for the different themes.
>>>>>>>>>>>> Please move them into the css for the themes. You have a mix of style,
>>>>>>>>>>>> layout and code in this file which needs to be cleaned up.
>>>>>>>>>>>> xterm V3 onwards they have provided the API to set the theme
>>>>>>>>>>>> and other settings, earlier I tried with CSS to override the theme but
>>>>>>>>>>>> couldn’t able to apply the theme properly as some style get applied as
>>>>>>>>>>>> in-line style for the HTML, so used the API to set the theme.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> OK, but either way we can't hard-code styles from themes in HTML
>>>>>>>>>>> templates for individual features; that way leads to madness.
>>>>>>>>>>>
>>>>>>>>>>> Perhaps Aditya or one of the other team members can give some
>>>>>>>>>>> assistance?
>>>>>>>>>>>
>>>>>>>>>> I have moved the color settings to the respective theme files.
>>>>>>>>>> Aditya helped in this.
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>> Speaking of themes, the background colour for selected text
>>>>>>>>>>>>> doesn't seem right (it's barely visible) in the dark theme. Can you fix
>>>>>>>>>>>>> that to match the colouring in the SQL text boxes please?
>>>>>>>>>>>>>
>>>>>>>>>>>> I tried the default selection color from SQL for the dark and
>>>>>>>>>> standard themes but still, it was not readable so just updated the color
>>>>>>>>>> code with another color as follows.
>>>>>>>>>> 1. Dark Theme:
>>>>>>>>>> [image: Screenshot 2021-05-19 at 6.29.43 PM.png]
>>>>>>>>>> 2. High Contrast: (using default SQL selection color)
>>>>>>>>>> [image: Screenshot 2021-05-19 at 6.59.52 PM.png]
>>>>>>>>>> 3. Standard:
>>>>>>>>>> [image: image.png]
>>>>>>>>>> can we go with the colors or should we update it?
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> A couple of other things I noticed:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - The button is enabled if the treeview has a Server
>>>>>>>>>>>>>>> selected. It could be argued that the query tool should do the same
>>>>>>>>>>>>>>> (defaulting to the maintenance database), however, that would be a separate
>>>>>>>>>>>>>>> change, and psql should be consistent with the query tool.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>> It is now consistent with the query tool.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - If I do a "select * from pg_class;" I still get:
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> postgres=# select * from pg_class;
>>>>>>>>>>>>>>> WARNING: terminal is not fully functional
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I am not able to reproduce the warning for the terminal (I am
>>>>>>>>>>>>>> working on Catalina 10.15.7), I checked on browsers (chrome, firefox,
>>>>>>>>>>>>>> Safari) and also checked on local nwjs runtime but still not able to
>>>>>>>>>>>>>> reproduce the warning. but found one limitation:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> It looks like that can be fixed by adding:
>>>>>>>>>>>>>
>>>>>>>>>>>>> env={'TERM': 'xterm'}
>>>>>>>>>>>>>
>>>>>>>>>>>> Added this in the environment when opening the psql panel.
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>> to the subprocess.Popen() call.
>>>>>>>>>>>>>
>>>>>>>>>>>>> I noticed while I was playing with that, that you are passing
>>>>>>>>>>>>> the password as part of the connection string. As I've mentioned in the
>>>>>>>>>>>>> past, that is absolutely not acceptable; it will expose the password to all
>>>>>>>>>>>>> manner of tools (such as ps -ef). You *must* pass the password to psql
>>>>>>>>>>>>> using the PGPASSWORD environment variable.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>> if we try to load data from the table containing millions of
>>>>>>>>>>>>>> records, UI gets very slow.
>>>>>>>>>>>>>>
>>>>>>>>>>>>> Removed the password from the connection string and added
>>>>>>>>>> 'PGPASSWORD' in the environment.
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>> Is xtermjs discarding the older buffer contents when it fills
>>>>>>>>>>>>> up? Can you tell where the memory usage is?
>>>>>>>>>>>>>
>>>>>>>>>>>> I checked the psql memory consumption in terminal and pgAdmin
>>>>>>>>>>>> psql tool memory consumption is the similar. Also tested the performance
>>>>>>>>>>>> and query execution timing is also  similar.
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> OK, so there's probably not much we can do here.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> - I'm sure using \q in the previous version displayed a
>>>>>>>>>>>>>>> message saying the session exited (the one on line 138 of
>>>>>>>>>>>>>>> editor_template.html). It no longer seems to do so.
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>> In addition to the issue above, it looks like the \! blocking
>>>>>>>>>>>>> may have lost it's ability to ignore quoted strings:
>>>>>>>>>>>>>
>>>>>>>>>>>>> pgweb=# select '\!';
>>>>>>>>>>>>> ERROR: Shell commands are disabled in psql for security
>>>>>>>>>>>>>
>>>>>>>>>>>> Fixed the issue now it is consistent with the psql terminal.
>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>> On Tue, May 11, 2021 at 3:40 PM Dave Page <
>>>>>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Hi
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> On Tue, May 11, 2021 at 9:02 AM Akshay Joshi <
>>>>>>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Hi Nikhil
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> Following are the review comments:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> *GUI specific*:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>    - We need a panel icon for PSQL like query tool, we
>>>>>>>>>>>>>>>>>>    can also add that on the browser tree toolbar.
>>>>>>>>>>>>>>>>>>    - PSQL Tool menu should be visible for all the child
>>>>>>>>>>>>>>>>>>    nodes of the database node. Follow the same as Query Tool.
>>>>>>>>>>>>>>>>>>    - PSQL tab title should be only database server name
>>>>>>>>>>>>>>>>>>    as the user can change the database/user from PSQL command, so it's been
>>>>>>>>>>>>>>>>>>    difficult to update the tab title.
>>>>>>>>>>>>>>>>>>    - PSQL connection is still open even if we disconnect
>>>>>>>>>>>>>>>>>>    the database server from the browser tree.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> *Code specific:*
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>    - Remove an extra space from requirements.txt and
>>>>>>>>>>>>>>>>>>    package.json
>>>>>>>>>>>>>>>>>>    - Documentation needs to be updated to let the user
>>>>>>>>>>>>>>>>>>    know from where the PSQL tool will open and on which node it is applicable.
>>>>>>>>>>>>>>>>>>    - psql/__init__.py check there are so many unused
>>>>>>>>>>>>>>>>>>    imports please remove them.
>>>>>>>>>>>>>>>>>>    - We are not using cheroot so it should be removed
>>>>>>>>>>>>>>>>>>    from requirements.txt and also remove the import statement from pgAdmin4.py
>>>>>>>>>>>>>>>>>>    - Test cases are showing successful but actually,
>>>>>>>>>>>>>>>>>>    there are some routing errors please check.
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> A few other things I noticed:
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> - I was prompted to enter a password. This should be
>>>>>>>>>>>>>>>>> passed in the environment to psql as it is for pg_dump etc.
>>>>>>>>>>>>>>>>> - There seems to be an issue with terminal compatibility
>>>>>>>>>>>>>>>>> (which I didn't have on my prototype):
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> ml=# select * from pg_class;
>>>>>>>>>>>>>>>>> WARNING: terminal is not fully functional
>>>>>>>>>>>>>>>>> -[ RECORD 1
>>>>>>>>>>>>>>>>> ]-------+----------------------------------------------
>>>>>>>>>>>>>>>>> oid                 | 79354
>>>>>>>>>>>>>>>>> relname             | housing
>>>>>>>>>>>>>>>>> ...
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> - The panel should honour the styleguide. I'm running in
>>>>>>>>>>>>>>>>> dark mode, and see a jet black background. I would expect to see the same
>>>>>>>>>>>>>>>>> background/foreground colours as the treeview.
>>>>>>>>>>>>>>>>> - I spotted at least one print() statement that shouldn't
>>>>>>>>>>>>>>>>> be there (debug output should go through the logger) - psql/__init__.py:235
>>>>>>>>>>>>>>>>> - This seems suspect - why would there be a password in a
>>>>>>>>>>>>>>>>> connection string we've built? And why would it be xxx?
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>     if 'password=xxx' in conn_attr:
>>>>>>>>>>>>>>>>>         conn_attr = conn_attr.replace('password=xxx', '')
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> - There's a thick white line at the bottom of the panel,
>>>>>>>>>>>>>>>>> where a horizontal scrollbar might be if there was one.
>>>>>>>>>>>>>>>>> - The trailing semi-colon should be removed from: "ERROR:
>>>>>>>>>>>>>>>>> Shell commands are disabled in psql for security;"
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Once we're happy with the patch in general, I'll do a
>>>>>>>>>>>>>>>>> string review before committing. In particular, I want to be sure the text
>>>>>>>>>>>>>>>>> in config.py is appropriately worded.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> This is shaping up nicely! Good work.
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> On Mon, May 10, 2021 at 7:32 PM Nikhil Mohite <
>>>>>>>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Hi Dave/ Team,
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> PFA updated patch, sorry for the inconvenience, while
>>>>>>>>>>>>>>>>>>> cleanup I removed the unwanted libraries but forgot to remove the code
>>>>>>>>>>>>>>>>>>> related to them.
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> On Mon, May 10, 2021 at 7:10 PM Dave Page <
>>>>>>>>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Hi
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> On Mon, May 10, 2021 at 1:45 PM Nikhil Mohite <
>>>>>>>>>>>>>>>>>>>> [email protected]> wrote:
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Hi Hackers,
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>> Please find the attached patch for RM-2341
>>>>>>>>>>>>>>>>>>>>> <https://redmine.postgresql.org/issues/2341;: Add
>>>>>>>>>>>>>>>>>>>>> Menu option for starting PSQL.
>>>>>>>>>>>>>>>>>>>>> 1. Added new Option PSQL Tool in Tools menu.
>>>>>>>>>>>>>>>>>>>>> 2. Added the same option for Server and Database nodes
>>>>>>>>>>>>>>>>>>>>> from the tree view.
>>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> Unfortunately there's a trailing comma in package.json
>>>>>>>>>>>>>>>>>>>> that makes it invalid. If I fix that, then I get the error below, so I'm
>>>>>>>>>>>>>>>>>>>> guessing the intention was to actually include another package there?
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> ERROR in ./pgadmin/tools/psql/static/js/psql_module.js
>>>>>>>>>>>>>>>>>>>> 23:50-82
>>>>>>>>>>>>>>>>>>>> Module not found: Error: Can't resolve
>>>>>>>>>>>>>>>>>>>> 'local-echo-controller' in
>>>>>>>>>>>>>>>>>>>> '/Users/dpage/git/pgadmin4/web/pgadmin/tools/psql/static/js'
>>>>>>>>>>>>>>>>>>>> resolve 'local-echo-controller' in
>>>>>>>>>>>>>>>>>>>> '/Users/dpage/git/pgadmin4/web/pgadmin/tools/psql/static/js'
>>>>>>>>>>>>>>>>>>>>   Parsed request is a module
>>>>>>>>>>>>>>>>>>>>   using description file:
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/package.json (relative path:
>>>>>>>>>>>>>>>>>>>> ./pgadmin/tools/psql/static/js)
>>>>>>>>>>>>>>>>>>>>     aliased with mapping 'local-echo-controller':
>>>>>>>>>>>>>>>>>>>> '/Users/dpage/git/pgadmin4/web/node_modules/local-echo' to
>>>>>>>>>>>>>>>>>>>> '/Users/dpage/git/pgadmin4/web/node_modules/local-echo'
>>>>>>>>>>>>>>>>>>>>       using description file:
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/package.json (relative path:
>>>>>>>>>>>>>>>>>>>> ./pgadmin/tools/psql/static/js)
>>>>>>>>>>>>>>>>>>>>         Field 'browser' doesn't contain a valid alias
>>>>>>>>>>>>>>>>>>>> configuration
>>>>>>>>>>>>>>>>>>>>         root path /Users/dpage/git/pgadmin4/web
>>>>>>>>>>>>>>>>>>>>           using description file:
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/package.json (relative path:
>>>>>>>>>>>>>>>>>>>> ./Users/dpage/git/pgadmin4/web/node_modules/local-echo)
>>>>>>>>>>>>>>>>>>>>             no extension
>>>>>>>>>>>>>>>>>>>>               Field 'browser' doesn't contain a valid
>>>>>>>>>>>>>>>>>>>> alias configuration
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/Users/dpage/git/pgadmin4/web/node_modules/local-echo
>>>>>>>>>>>>>>>>>>>> doesn't exist
>>>>>>>>>>>>>>>>>>>>             .js
>>>>>>>>>>>>>>>>>>>>               Field 'browser' doesn't contain a valid
>>>>>>>>>>>>>>>>>>>> alias configuration
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/Users/dpage/git/pgadmin4/web/node_modules/local-echo.js
>>>>>>>>>>>>>>>>>>>> doesn't exist
>>>>>>>>>>>>>>>>>>>>             .jsx
>>>>>>>>>>>>>>>>>>>>               Field 'browser' doesn't contain a valid
>>>>>>>>>>>>>>>>>>>> alias configuration
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/Users/dpage/git/pgadmin4/web/node_modules/local-echo.jsx
>>>>>>>>>>>>>>>>>>>> doesn't exist
>>>>>>>>>>>>>>>>>>>>             as directory
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/Users/dpage/git/pgadmin4/web/node_modules/local-echo
>>>>>>>>>>>>>>>>>>>> doesn't exist
>>>>>>>>>>>>>>>>>>>>         using description file:
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/package.json (relative path:
>>>>>>>>>>>>>>>>>>>> ./node_modules/local-echo)
>>>>>>>>>>>>>>>>>>>>           no extension
>>>>>>>>>>>>>>>>>>>>             Field 'browser' doesn't contain a valid
>>>>>>>>>>>>>>>>>>>> alias configuration
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/node_modules/local-echo doesn't exist
>>>>>>>>>>>>>>>>>>>>           .js
>>>>>>>>>>>>>>>>>>>>             Field 'browser' doesn't contain a valid
>>>>>>>>>>>>>>>>>>>> alias configuration
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/node_modules/local-echo.js doesn't exist
>>>>>>>>>>>>>>>>>>>>           .jsx
>>>>>>>>>>>>>>>>>>>>             Field 'browser' doesn't contain a valid
>>>>>>>>>>>>>>>>>>>> alias configuration
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/node_modules/local-echo.jsx doesn't exist
>>>>>>>>>>>>>>>>>>>>           as directory
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> /Users/dpage/git/pgadmin4/web/node_modules/local-echo doesn't exist
>>>>>>>>>>>>>>>>>>>>  @ ./pgadmin/tools/psql/static/js/index.js 17:19-43
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> 2021-05-10 14:38:37: webpack 5.21.2 compiled with 1
>>>>>>>>>>>>>>>>>>>> error in 60041 ms
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>>>>>> Dave Page
>>>>>>>>>>>>>>>>>>>> Blog: https://pgsnake.blogspot.com
>>>>>>>>>>>>>>>>>>>> Twitter: @pgsnake
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>> EDB: https://www.enterprisedb.com
>>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>> Regards,
>>>>>>>>>>>>>>>>>>> Nikhil Mohite
>>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>>>> *Thanks & Regards*
>>>>>>>>>>>>>>>>>> *Akshay Joshi*
>>>>>>>>>>>>>>>>>> *pgAdmin Hacker | Principal Software Architect*
>>>>>>>>>>>>>>>>>> *EDB Postgres <http://edbpostgres.com>*
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>> *Mobile: +91 976-788-8246*
>>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>>>> Dave Page
>>>>>>>>>>>>>>>>> Blog: https://pgsnake.blogspot.com
>>>>>>>>>>>>>>>>> Twitter: @pgsnake
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> EDB: https://www.enterprisedb.com
>>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>>> Regards,
>>>>>>>>>>>>>>>> Nikhil Mohite
>>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> --
>>>>>>>>>>>>>>> Dave Page
>>>>>>>>>>>>>>> Blog: https://pgsnake.blogspot.com
>>>>>>>>>>>>>>> Twitter: @pgsnake
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>> EDB: https://www.enterprisedb.com
>>>>>>>>>>>>>>>
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Regards,
>>>>>>>>>>>>>> Nikhil Mohite
>>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> --
>>>>>>>>>>>>> Dave Page
>>>>>>>>>>>>> Blog: https://pgsnake.blogspot.com
>>>>>>>>>>>>> Twitter: @pgsnake
>>>>>>>>>>>>>
>>>>>>>>>>>>> EDB: https://www.enterprisedb.com
>>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> Regards,
>>>>>>>>>>>> Nikhil Mohite
>>>>>>>>>>>>
>>>>>>>>>>>>> <https://www.enterprisedb.com;
>>>>>>>>>>>>>
>>>>>>>>>>>>> --
>>>>>>>>>>>> *Thanks & Regards,*
>>>>>>>>>>>> *Nikhil Mohite*
>>>>>>>>>>>> *Software Engineer.*
>>>>>>>>>>>> *EDB Postgres* <https://www.enterprisedb.com/;
>>>>>>>>>>>> *Mob.No: +91-7798364578.*
>>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> --
>>>>>>>>>>> Dave Page
>>>>>>>>>>> Blog: https://pgsnake.blogspot.com
>>>>>>>>>>> Twitter: @pgsnake
>>>>>>>>>>>
>>>>>>>>>>> EDB: https://www.enterprisedb.com
>>>>>>>>>>>
>>>>>>>>>>> Regards,
>>>>>>>>>> Nikhil Mohite
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> --
>>>>>>>>> Dave Page
>>>>>>>>> Blog: https://pgsnake.blogspot.com
>>>>>>>>> Twitter: @pgsnake
>>>>>>>>>
>>>>>>>>> EDB: https://www.enterprisedb.com
>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>> --
>>>>>>>> *Thanks & Regards*
>>>>>>>> *Akshay Joshi*
>>>>>>>> *pgAdmin Hacker | Principal Software Architect*
>>>>>>>> *EDB Postgres <http://edbpostgres.com>*
>>>>>>>>
>>>>>>>> *Mobile: +91 976-788-8246*
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>> --
>>>>>> *Thanks & Regards*
>>>>>> *Akshay Joshi*
>>>>>> *pgAdmin Hacker | Principal Software Architect*
>>>>>> *EDB Postgres <http://edbpostgres.com>*
>>>>>>
>>>>>> *Mobile: +91 976-788-8246*
>>>>>>
>>>>>
>>>>
>>>> --
>>>> *Thanks & Regards*
>>>> *Akshay Joshi*
>>>> *pgAdmin Hacker | Principal Software Architect*
>>>> *EDB Postgres <http://edbpostgres.com>*
>>>>
>>>> *Mobile: +91 976-788-8246*
>>>>
>>>
>>
>> --
>> Dave Page
>> Blog: https://pgsnake.blogspot.com
>> Twitter: @pgsnake
>>
>> EDB: https://www.enterprisedb.com
>>
>>
>
> --
> *Thanks & Regards*
> *Akshay Joshi*
> *pgAdmin Hacker | Principal Software Architect*
> *EDB Postgres <http://edbpostgres.com>*
>
> *Mobile: +91 976-788-8246*
>


Attachments:

  [image/png] Screenshot 2021-05-19 at 6.29.43 PM.png (81.5K, 3-Screenshot%202021-05-19%20at%206.29.43%20PM.png)
  download | view image

  [image/png] Screenshot 2021-05-19 at 6.59.52 PM.png (76.3K, 4-Screenshot%202021-05-19%20at%206.59.52%20PM.png)
  download | view image

  [image/png] image.png (52.6K, 5-image.png)
  download | view image

  [application/octet-stream] RM_2341_v7.patch (26.3K, 6-RM_2341_v7.patch)
  download | inline diff:
diff --git a/requirements.txt b/requirements.txt
index ebdb1b21..469aa964 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -37,6 +37,7 @@ ldap3==2.*
 Flask-BabelEx==0.*
 gssapi==1.6.*
 flask-socketio>=5.0.1
-eventlet==0.30.2
+eventlet==0.31.0
 httpagentparser==1.9.*
 user-agents==2.2.0
+pywinpty==1.1.*
diff --git a/web/pgadmin/browser/register_browser_preferences.py b/web/pgadmin/browser/register_browser_preferences.py
index 0e464c06..0dbe589c 100644
--- a/web/pgadmin/browser/register_browser_preferences.py
+++ b/web/pgadmin/browser/register_browser_preferences.py
@@ -506,61 +506,38 @@ def register_browser_preferences(self):
         )
     )
 
-    if sys.platform != 'win32':
-        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'},
-                     {'label': gettext('PSQL Tool'), 'value': 'psql_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...')
-            }
-        )
-
-        self.psql_tab_title = self.preference.register(
-            'tab_settings', 'psql_tab_title_placeholder',
-            gettext("PSQL tool tab title"),
-            'text', '%DATABASE%/%USERNAME%@%SERVER%',
-            category_label=PREF_LABEL_DISPLAY,
-            help_str=gettext(
-                'Supported placeholders are %DATABASE%, %USERNAME%, '
-                'and %SERVER%. Users can provide any string with or without'
-                ' placeholders of their choice. The blank title will be revert'
-                ' 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...')
-            }
+    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'},
+                 {'label': gettext('PSQL Tool'), 'value': 'psql_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...')
+        }
+    )
+
+    self.psql_tab_title = self.preference.register(
+        'tab_settings', 'psql_tab_title_placeholder',
+        gettext("PSQL tool tab title"),
+        'text', '%DATABASE%/%USERNAME%@%SERVER%',
+        category_label=PREF_LABEL_DISPLAY,
+        help_str=gettext(
+            'Supported placeholders are %DATABASE%, %USERNAME%, '
+            'and %SERVER%. Users can provide any string with or without'
+            ' placeholders of their choice. The blank title will be revert'
+            ' back to the default title with placeholders.'
         )
+    )
diff --git a/web/pgadmin/browser/static/js/collection.js b/web/pgadmin/browser/static/js/collection.js
index 64442189..47c87715 100644
--- a/web/pgadmin/browser/static/js/collection.js
+++ b/web/pgadmin/browser/static/js/collection.js
@@ -66,7 +66,7 @@ define([
             }]);
 
             // show psql tool same as query tool.
-            if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') {
+            if(pgAdmin['enable_psql']) {
               pgAdmin.Browser.add_menus([{
                 name: 'show_psql_tool', node: this.type, module: this,
                 applies: ['context'], callback: 'show_psql_tool',
diff --git a/web/pgadmin/browser/static/js/node.js b/web/pgadmin/browser/static/js/node.js
index c2e73931..f7c04d0d 100644
--- a/web/pgadmin/browser/static/js/node.js
+++ b/web/pgadmin/browser/static/js/node.js
@@ -210,7 +210,7 @@ define('pgadmin.browser.node', [
           icon: 'fa fa-search', enable: enable,
         }]);
 
-        if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') {
+        if(pgAdmin['enable_psql']) {
           // show psql tool same as query tool.
           pgAdmin.Browser.add_menus([{
             name: 'show_psql_tool', node: this.type, module: this,
diff --git a/web/pgadmin/browser/static/js/toolbar.js b/web/pgadmin/browser/static/js/toolbar.js
index 4aaa41ce..bc9c13a3 100644
--- a/web/pgadmin/browser/static/js/toolbar.js
+++ b/web/pgadmin/browser/static/js/toolbar.js
@@ -59,7 +59,7 @@ let _defaultToolBarButtons = [
   }
 ];
 
-if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') {
+if(pgAdmin['enable_psql']) {
   _defaultToolBarButtons.unshift({
     label: 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());
     else if ('name' in data && data.name === gettext('Search objects'))
       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 = {},
         t = pgAdmin.Browser.tree,
         i = input.item || t.selected(),
diff --git a/web/pgadmin/browser/utils.py b/web/pgadmin/browser/utils.py
index 5e22f2d5..139ac673 100644
--- a/web/pgadmin/browser/utils.py
+++ b/web/pgadmin/browser/utils.py
@@ -63,7 +63,8 @@ def underscore_unescape(text):
         "&quot;": '"',
         "&#96;": '`',
         "&#x27;": "'",
-        "&#39;": "'"
+        "&#39;": "'",
+        "&#34;": '"'
     }
 
     # always replace & first
diff --git a/web/pgadmin/tools/psql/__init__.py b/web/pgadmin/tools/psql/__init__.py
index 7f5adae9..f62e0743 100644
--- a/web/pgadmin/tools/psql/__init__.py
+++ b/web/pgadmin/tools/psql/__init__.py
@@ -1,5 +1,4 @@
 #!/usr/bin/env python3
-
 import os
 import re
 import select
@@ -20,7 +19,9 @@ from pgadmin.utils.driver import get_driver
 from ... import socketio as sio
 from pgadmin.utils import get_complete_file_path
 
-if _platform != 'win32':
+if _platform == 'win32':
+    from winpty import PtyProcess
+else:
     import fcntl
     import termios
     import pty
@@ -101,8 +102,8 @@ def panel(trans_id):
 
     return render_template('editor_template.html',
                            sid=params['sid'],
-                           db=underscore_unescape(params['db']) if params[
-                               'db'] else 'postgres',
+                           db=underscore_unescape(
+                               o_db_name) if o_db_name else 'postgres',
                            server_type=params['server_type'],
                            is_enable=config.ENABLE_PSQL,
                            title=underscore_unescape(params['title']),
@@ -120,8 +121,13 @@ def set_term_size(fd, row, col, xpix=0, ypix=0):
     :param xpix:
     :param ypix:
     """
-    term_size = struct.pack('HHHH', row, col, xpix, ypix)
-    fcntl.ioctl(fd, termios.TIOCSWINSZ, term_size)
+    if _platform == 'win32':
+        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')
@@ -216,6 +222,19 @@ def read_terminal_data(parent, data_ready, max_read_bytes, sid):
             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')
 def start_process(data):
     """
@@ -227,8 +246,24 @@ def start_process(data):
     def read_and_forward_pty_output(sid, data):
 
         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)
 
             while p and p.poll() is None:
@@ -248,12 +283,6 @@ def start_process(data):
                                                        timeout)
 
                     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.
     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.
     :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.append(psql_utility)
     conn_attr_list.append(conn_attr)
     return conn_attr_list
 
 
-def get_conn_str(manager, db):
+def get_conn_str_win(manager, db):
     """
     Get connection attributes for psql connection.
     :param manager:
@@ -357,46 +386,48 @@ def get_conn_str(manager, db):
     :return:
     """
     manager.export_password_env('PGPASSWORD')
+    db = db.replace('"', '\\"')
+    db = db.replace("'", "\\'")
     conn_attr =\
-        'host={0} port={1} dbname={2} user={3} sslmode={4} ' \
-        'sslcompression={5} ' \
+        'host=\'{0}\' port=\'{1}\' dbname=\'{2}\' user=\'{3}\' ' \
+        'sslmode=\'{4}\' sslcompression=\'{5}\' ' \
         ''.format(
             manager.local_bind_host if manager.use_ssh_tunnel else
             manager.host,
             manager.local_bind_port if manager.use_ssh_tunnel else
             manager.port,
-            underscore_unescape(db) if db != '' else 'postgres',
+            db if db != '' else 'postgres',
             underscore_unescape(manager.user) if manager.user else 'postgres',
             manager.ssl_mode,
             True if manager.sslcompression else False,
         )
 
     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:
-        conn_attr = " {0} passfile={1}".format(conn_attr,
-                                               get_complete_file_path(
-                                                   manager.passfile))
+        conn_attr = " {0} passfile='{1}'".format(conn_attr,
+                                                 get_complete_file_path(
+                                                     manager.passfile))
 
     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))
 
     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))
 
     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))
 
     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))
 
     if manager.service:
-        conn_attr = " {0} service={1}".format(
+        conn_attr = " {0} service='{1}'".format(
             conn_attr, get_complete_file_path(manager.service))
 
     return conn_attr
@@ -433,12 +464,27 @@ def invalid_cmd():
     :rtype:
     """
     session_last_cmd[request.sid]['invalid_cmd'] = True
-    for i in range(len(session_input[request.sid])):
-        os.write(app.config['sessions'][request.sid],
-                 '\b \b'.encode())
+    if _platform == 'win32':
+        for i in range(len(session_input[request.sid])):
+            app.config['sessions'][request.sid].write('\b \b')
+        app.config['sessions'][request.sid].write('\r\n')
+
+        sio.emit(
+            '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())
+        os.write(app.config['sessions'][request.sid],
+                 '\n'.encode())
     session_input[request.sid] = ''
 
 
@@ -464,18 +510,36 @@ def check_valid_cmd(user_input):
 
     if stop_execution:
         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.
-        for i in range(len(user_input)):
+            sio.emit(
+                '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],
-                     '\b \b'.encode())
-        # Add Enter event to execute the command.
-        os.write(app.config['sessions'][request.sid],
-                 '\n'.encode())
+                     '\n'.encode())
     else:
         session_last_cmd[request.sid]['invalid_cmd'] = False
-        os.write(app.config['sessions'][request.sid],
-                 '\n'.encode())
+        if _platform == 'win32':
+            app.config['sessions'][request.sid].write('\n')
+        else:
+            os.write(app.config['sessions'][request.sid],
+                     '\n'.encode())
 
 
 def enter_key_press(data):
@@ -501,8 +565,8 @@ def enter_key_press(data):
         not config.ALLOW_PSQL_SHELL_COMMANDS and\
             not session_last_cmd[request.sid]['is_new_connection']:
         check_valid_cmd(user_input)
-    elif user_input == '\q' or user_input == 'q\\q' or \
-            user_input in ['exit', 'exit;']:
+    elif user_input == '\q' or user_input == 'q\\q' or user_input in ['exit',
+                                                                      'exit;']:
         # If user enter \q to terminate the PSQL, emit the msg to
         # notify user connection is terminated.
         sio.emit('pty-output',
@@ -514,12 +578,20 @@ def enter_key_press(data):
                      'error': True},
                  namespace='/pty', room=request.sid)
 
-        os.write(app.config['sessions'][request.sid],
-                 '\n'.encode())
+        if _platform == 'win32':
+            app.config['sessions'][request.sid].write('\n')
+            del app.config['sessions'][request.sid]
+        else:
+            os.write(app.config['sessions'][request.sid],
+                     '\n'.encode())
 
     else:
-        os.write(app.config['sessions'][request.sid],
-                 data['input'].encode())
+        if _platform == 'win32':
+            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_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_cursor[request.sid] += 1
 
-    # Write user input to terminal parent fd.
-    os.write(app.config['sessions'][request.sid],
-             data['input'].encode())
+    if _platform == 'win32':
+        app.config['sessions'][request.sid].write(
+            "{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')
@@ -697,11 +773,17 @@ def server_disconnect(data):
 
 
 def disconnect_socket():
-    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]
+    if _platform == 'win32':
+        if request.sid in app.config['sessions']:
+            process = app.config['sessions'][request.sid]
+            process.terminate()
+            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):
diff --git a/web/pgadmin/tools/psql/static/js/psql_module.js b/web/pgadmin/tools/psql/static/js/psql_module.js
index 6a0ae191..85bccb1a 100644
--- a/web/pgadmin/tools/psql/static/js/psql_module.js
+++ b/web/pgadmin/tools/psql/static/js/psql_module.js
@@ -55,7 +55,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
       }];
 
       this.enable_psql_tool = pgAdmin['enable_psql'];
-      if(pgAdmin['enable_psql'] && pgAdmin['platform'] != 'win32') {
+      if(pgAdmin['enable_psql']) {
         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;
       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 = `
         <form id="psqlToolForm" action="${panelUrl}" method="post">
           <input id="title" name="title" hidden />
+          <input id='db' value='${db_label}' hidden />
           <input name="close_url" value="${panelCloseUrl}" hidden />
         </form>
         <script>
@@ -228,9 +229,11 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
         +`&did=${parentData.database._id}`
         +`&server_type=${parentData.server.server_type}`
         + `&theme=${theme}`;
-
+      let db_label = '';
       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}`;
       } else {
         openUrl += `&db=${''}`;
@@ -239,7 +242,7 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
       let closeUrl = url_for('psql.close', {
         trans_id: transId,
       });
-      return [openUrl, closeUrl];
+      return [openUrl, closeUrl, db_label];
     },
     psql_terminal: function() {
       // theme colors
@@ -375,4 +378,3 @@ export function initialize(gettext, url_for, $, _, pgAdmin, csrfToken, Browser)
 
   return pgBrowser.psql;
 }
-
diff --git a/web/pgadmin/tools/psql/templates/editor_template.html b/web/pgadmin/tools/psql/templates/editor_template.html
index 0568ad71..17b8a04d 100644
--- a/web/pgadmin/tools/psql/templates/editor_template.html
+++ b/web/pgadmin/tools/psql/templates/editor_template.html
@@ -23,41 +23,36 @@
 require(
     ['sources/generated/psql_tool'],
     function(pgBrowser) {
-        if (self.pgAdmin['platform'] != 'win32') {
-            const term = self.pgAdmin.Browser.psql.psql_terminal();
-            <!--Addon for fitAddon, webLinkAddon, SearchAddon  -->
-            const fitAddon = self.pgAdmin.Browser.psql.psql_Addon(term);
-            <!-- Update the theme for terminal as per pgAdmin 4 theme.-->
-            self.pgAdmin.Browser.psql.set_theme(term);
-            <!-- Open the terminal -->
-            term.open(document.getElementById('psql-terminal'));
-            <!-- Socket-->
-            const socket = self.pgAdmin.Browser.psql.psql_socket();
-            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.check_db_name_change('{{db}}', '{{o_db_name}}');
+        const term = self.pgAdmin.Browser.psql.psql_terminal();
+        <!--Addon for fitAddon, webLinkAddon, SearchAddon  -->
+        const fitAddon = self.pgAdmin.Browser.psql.psql_Addon(term);
+        <!-- Update the theme for terminal as per pgAdmin 4 theme.-->
+        self.pgAdmin.Browser.psql.set_theme(term);
+        <!-- Open the terminal -->
+        term.open(document.getElementById('psql-terminal'));
+        <!-- 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_terminal_io(term, socket);
+        self.pgAdmin.Browser.psql.check_db_name_change('{{db}}', '{{o_db_name}}');
+
+        <!-- Resize the terminal -->
+        function fitToscreen(){
+            fitAddon.fit()
+            socket.emit("resize", {"cols": term.cols, "rows": term.rows})
+        }
 
-            <!-- Resize the terminal -->
-            function fitToscreen(){
-                fitAddon.fit()
-                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)
             }
+        }
 
-            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)
 
-            const wait_ms = 50;;
-            window.onresize = debounce(fitToscreen, wait_ms)
-        } else {
-            document.getElementById('psql-terminal').innterHTML = 'PSQL not supported'
-        }
     });
 {% endblock %}
-
-


view thread (54+ messages)  latest in thread

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected]
  Subject: Re: [pgAdmin][RM-2341]: Add menu option for starting PSQL
  In-Reply-To: <CAOBg0ANMJTzaEQdcEwUnLLGJXSbsT6=0L8Jvs_MTuBTfj0YtrQ@mail.gmail.com>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox