dbcli / dbcli/pgcli

Connecting via unix socket on a specific DB crashes pgcli

Đang mở
#1,422 3 bình luận 0 reaction 0 người được giao Xem trên GitHub
Ngôn ngữ chính
Python
Star
13.4k
Fork
612
Merge trung bình
6 ngày 14 giờ
Pull request đã merge (30 ngày)
10

Mô tả

## Description
Hello

Installing pgcli 3.5.0 on a Debian server with postgresql 15, when, as unix user postgres, I run a simple `pgcli`, I get a proper prompt, but as soon as I use `pgcli XXX` with `XXX`being another database, pgcli crashes while starting because it tries to mix str and bytes.

```
postgres@pgsql:~$ pgcli
Server: PostgreSQL 15.3 (Debian 15.3-0+deb12u1)
Version: 3.5.0
Home: http://pgcli.com
postgres>
Goodbye!
postgres@pgsql:~$ pgcli icinga2
Server: PostgreSQL 15.3 (Debian 15.3-0+deb12u1)
Version: 3.5.0
Home: http://pgcli.com
Traceback (most recent call last):
File "/usr/bin/pgcli", line 33, in
Exception in thread completion_refresh:
Traceback (most recent call last):
File "/usr/lib/python3.11/threading.py", line 1038, in _bootstrap_inner
sys.exit(load_entry_point('pgcli==3.5.0', 'console_scripts', 'pgcli')())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/click/core.py", line 1130, in __call__
self.run()
File "/usr/lib/python3.11/threading.py", line 975, in run
return self.main(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/click/core.py", line 1055, in main
rv = self.invoke(ctx)
^^^^^^^^^^^^^^^^
self._target(*self._args, **self._kwargs)
File "/usr/lib/python3/dist-packages/pgcli/completion_refresher.py", line 68, in _bg_refresh
File "/usr/lib/python3/dist-packages/click/core.py", line 1404, in invoke
refresher(completer, executor)
File "/usr/lib/python3/dist-packages/pgcli/completion_refresher.py", line 109, in refresh_schemata
return ctx.invoke(self.callback, **ctx.params)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/click/core.py", line 760, in invoke
completer.set_search_path(executor.search_path())
File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 306, in set_search_path
return __callback(*args, **kwargs)
self.search_path = self.escaped_names(search_path)
^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/pgcli/main.py", line 1427, in cli
File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 150, in escaped_names
return [self.escape_name(name) for name in names]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 150, in
pgcli.run_cli()
File "/usr/lib/python3/dist-packages/pgcli/main.py", line 788, in run_cli
return [self.escape_name(name) for name in names]
^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/pgcli/pgcompleter.py", line 131, in escape_name
text = self.prompt_app.prompt()
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/shortcuts/prompt.py", line 1034, in prompt
(not self.name_pattern.match(name))

TypeError: cannot use a string pattern on a bytes-like object
return self.app.run(
^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 978, in run
return loop.run_until_complete(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3.11/asyncio/base_events.py", line 653, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 885, in run_async
return await _run_async(f)
^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 743, in _run_async
self._redraw()
File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 557, in _redraw
self.context.copy().run(run_in_context)
File "/usr/lib/python3/dist-packages/prompt_toolkit/application/application.py", line 540, in run_in_context
self.renderer.render(self, self.layout)
File "/usr/lib/python3/dist-packages/prompt_toolkit/renderer.py", line 640, in render
layout.container.preferred_height(size.columns, size.rows).preferred,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 326, in preferred_height
dimensions = [
^
File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 327, in
c.preferred_height(width, max_available_height) for c in self._all_children
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 796, in preferred_height
return self.content.preferred_height(width, max_available_height)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 326, in preferred_height
dimensions = [
^
File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 327, in
c.preferred_height(width, max_available_height) for c in self._all_children
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/layout/containers.py", line 2642, in preferred_height
if self.filter():
^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/filters/base.py", line 210, in __call__
return self.func()
^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/shortcuts/prompt.py", line 168, in has_before_fragments
for fragment, char, *_ in get_prompt_text():
^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/shortcuts/prompt.py", line 1279, in _get_prompt
return to_formatted_text(self.message, style="class:prompt")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/prompt_toolkit/formatted_text/base.py", line 81, in to_formatted_text
return to_formatted_text(value(), style=style)
^^^^^^^
File "/usr/lib/python3/dist-packages/pgcli/main.py", line 851, in get_message
prompt = self.get_prompt(prompt_format)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib/python3/dist-packages/pgcli/main.py", line 1115, in get_prompt
string = string.replace("\\H", self.pgexecute.host or "(none)")
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: replace() argument 2 must be str, not bytes
postgres@pgsql:~$ ;1R
```

As you see, there are two type errors, and both relate to mixing str and bytes.

After poking a bit, it seems that when I give another database as an argument, pgcli connects to it and then makes queries to the postgres database to get the unix socket configuration and other stufs from the pg_settings database. In the case of a connection to the postgres database, the cursor fetches strings (eg in pgexecute.get_socket_directory function), while when connected to another database, the cursor fetches bytes.

I think some sanitizing is needed.

## Your environment

- [x] Please provide your OS and version information. Debian 12
- [x] Please provide your CLI version. 3.5.0
- [x] What is the output of ``pip freeze`` command: nothing, I don't use pip. psycopg version is 3.1.7

Hướng dẫn đóng góp

Mở hướng dẫn đóng góp

Đánh giá

Issue này chưa được đánh giá.

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.