Closed williamjacksn closed 4 years ago
surprising! I can't reproduce it on my side.
Could you try 2 twhing:
create_book(uri_conn='postgres://william:secretpassword@db.example.com:5433/my_test_db')
and then try to open it with
open_book(uri_conn='postgres://william:secretpassword@db.example.com:5433/my_test_db')
At piecash.core.session
line 307, uri_conn
is postgres://william:secretpasword@db.example.com:5433/gnucash
It looks like the problem is in sqlalchemy_utils.database_exists
. I can submit a bug over there.
In the meantime, I patched my copy of piecash to add a flag that will bypass the existence check: https://github.com/williamjacksn/piecash/commit/0c090479b301cf0f933180c32a4b22ea12520382
That was a bit my first intuition... And you understand the bug in sqlalchemy_utils?
It's pretty straightforward. sqlalchemy_utils.database_exists()
just assumes I have access to the postgres
database and switches to it on purpose to make the connection. Not a "bug", but a flawed implementation.
so instead of using the database given in the URI, it uses the postgres
database ?
That's right. The logic is pretty easy to follow:
https://github.com/kvesteri/sqlalchemy-utils/blob/master/sqlalchemy_utils/functions/database.py#L433
From the PostgreSQL documentation:
After initialization, a database cluster will contain a database named
postgres
, which is meant as a default database for use by utilities, users and third party applications. The database server itself does not require thepostgres
database to exist, but many external utility programs assume it exists.
So SQLAlchemy-Utils assumes the postgres
database is there and that I have access to it.
Given line 462, why is there a need for lines 463-466?
@williamjacksn with the latest version of piecash (and dependencies), is the issue still there ? or can we close it ?
This is still an issue, but for a slightly different reason. The call to sqlalchemy_utils.database_exists()
still fails, but instead of attempting a connection to the postgres
database, it attempts to connect to a database whose name matches the role I am connecting with. No such database exists, so the connection fails.
I am still using my patched fork of piecash
that bypasses the call to database_exists()
: https://github.com/williamjacksn/piecash/commit/0c090479b301cf0f933180c32a4b22ea12520382.
This has been reported in https://github.com/kvesteri/sqlalchemy-utils/issues/462.
>>> piecash.open_book(uri_conn='postgres://william:secretpassword@db.example.com/gnucash')
Traceback (most recent call last):
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2336, in _wrap_pool_connect
return fn()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 364, in connect
return _ConnectionFairy._checkout(self)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 778, in _checkout
fairy = _ConnectionRecord.checkout(pool)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 495, in checkout
rec = pool._do_get()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 140, in _do_get
self._dec_overflow()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.raise_(
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 137, in _do_get
return self._create_connection()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 309, in _create_connection
return _ConnectionRecord(self)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 440, in __init__
self.__connect(first_connect_check=True)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 661, in __connect
pool.logger.debug("Error on connect(): %s", e)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.raise_(
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 656, in __connect
connection = pool._invoke_creator(self)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/strategies.py", line 114, in connect
return dialect.connect(*cargs, **cparams)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 493, in connect
return self.dbapi.connect(*cargs, **cparams)
File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 127, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
psycopg2.OperationalError: FATAL: database "william" does not exist
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.9/site-packages/piecash/core/session.py", line 366, in open_book
if not database_exists(uri_conn):
File "/usr/local/lib/python3.9/site-packages/sqlalchemy_utils/functions/database.py", line 466, in database_exists
return bool(get_scalar_result(engine, text))
File "/usr/local/lib/python3.9/site-packages/sqlalchemy_utils/functions/database.py", line 445, in get_scalar_result
result_proxy = engine.execute(sql)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2234, in execute
connection = self._contextual_connect(close_with_result=True)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2302, in _contextual_connect
self._wrap_pool_connect(self.pool.connect, None),
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2339, in _wrap_pool_connect
Connection._handle_dbapi_exception_noconnection(
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 1583, in _handle_dbapi_exception_noconnection
util.raise_(
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/base.py", line 2336, in _wrap_pool_connect
return fn()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 364, in connect
return _ConnectionFairy._checkout(self)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 778, in _checkout
fairy = _ConnectionRecord.checkout(pool)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 495, in checkout
rec = pool._do_get()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 140, in _do_get
self._dec_overflow()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.raise_(
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/impl.py", line 137, in _do_get
return self._create_connection()
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 309, in _create_connection
return _ConnectionRecord(self)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 440, in __init__
self.__connect(first_connect_check=True)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 661, in __connect
pool.logger.debug("Error on connect(): %s", e)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/langhelpers.py", line 68, in __exit__
compat.raise_(
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/util/compat.py", line 182, in raise_
raise exception
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/pool/base.py", line 656, in __connect
connection = pool._invoke_creator(self)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/strategies.py", line 114, in connect
return dialect.connect(*cargs, **cparams)
File "/usr/local/lib/python3.9/site-packages/sqlalchemy/engine/default.py", line 493, in connect
return self.dbapi.connect(*cargs, **cparams)
File "/usr/local/lib/python3.9/site-packages/psycopg2/__init__.py", line 127, in connect
conn = _connect(dsn, connection_factory=connection_factory, **kwasync)
sqlalchemy.exc.OperationalError: (psycopg2.OperationalError) FATAL: database "william" does not exist
(Background on this error at: http://sqlalche.me/e/13/e3q8)
Ha! Great to know you have the same issue as myself this early morning! I had to create a database with name my username to pass through the issue. So if I understand well, it is a bug in sqlalchemy-utils that could be worth to workaround now in piecash , hoping a future version of sqla-utils fixes it (and the we can remove the workaround you propose)
@williamjacksn could you try to open your postgres gnucash book (without check_exists=False) but with a
pip install SQLAlchemy-Utils==0.36.7
before as 0.38.8 has the issue of username database ?
I am not sure if, with 0.36.7, you will fall back on the issue of "postgres" db being used for existence or if it had solved the issue (and we just have a regression with 0.38.8).
Released piecash 1.1.1 with your flag check_exists. I will close the issue once the sqlalchemy-utils issue is clearer
Thank you so much, @sdementen !
You're welcome and thank you for the feature/debugging. Could you just confirm if with the previous release of sqla-utils it works (my comment here above)
It works for me with SQLAlchemy-Utils 0.36.7!
# pip list
Package Version
---------------- ---------
certifi 2020.6.20
chardet 3.0.4
click 7.1.2
idna 2.10
piecash 1.1.1
pip 20.2.4
psycopg2 2.8.6
pytz 2020.1
requests 2.24.0
setuptools 50.3.2
six 1.15.0
SQLAlchemy 1.3.20
SQLAlchemy-Utils 0.36.7
tzlocal 2.1
urllib3 1.25.11
wheel 0.35.1
>>> piecash.open_book(uri_conn='postgres://william:secretpassword@db.example.com/gnucash')
Book<postgres://william:secretpassword@db.example.com/gnucash>
Great, then I will release a new version that make sure 0.36.8 is not used
1.1.2 fixes this by installing SQLAlchemy-Utils !=0.36.8
My GnuCash database is on a PostgreSQL server. My user account has access to the GnuCash database (named "gnucash") but not the "postgres" database.
When I call
open_book
,piecash
attempts to connect to the "postgres" database and fails.(passwords, hostnames, and IP addresses obscured)