Mercurial > p > roundup > code
changeset 7714:b41750bf9f03
fix: figure out dbname when using pg_service.
See: https://issues.roundup-tracker.org/msg7890 where drop database
is missing the dbname.
| author | John Rouillard <rouilj@ieee.org> |
|---|---|
| date | Mon, 18 Dec 2023 16:56:49 -0500 |
| parents | 2c1d30467909 |
| children | 95f0002e85c4 |
| files | roundup/backends/back_postgresql.py |
| diffstat | 1 files changed, 52 insertions(+), 3 deletions(-) [+] |
line wrap: on
line diff
--- a/roundup/backends/back_postgresql.py Mon Dec 18 16:40:55 2023 -0500 +++ b/roundup/backends/back_postgresql.py Mon Dec 18 16:56:49 2023 -0500 @@ -50,7 +50,8 @@ def db_create(config): """Clear all database contents and drop database itself""" - command = "CREATE DATABASE \"%s\" WITH ENCODING='UNICODE'" % config.RDBMS_NAME + command = ("CREATE DATABASE \"%s\" WITH ENCODING='UNICODE'" % + get_database_name(config)) if config.RDBMS_TEMPLATE: command = command + " TEMPLATE=%s" % config.RDBMS_TEMPLATE logging.getLogger('roundup.hyperdb').info(command) @@ -59,7 +60,8 @@ def db_nuke(config): """Clear all database contents and drop database itself""" - command = 'DROP DATABASE "%s"' % config.RDBMS_NAME + command = 'DROP DATABASE "%s"' % get_database_name(config) + logging.getLogger('roundup.hyperdb').info(command) db_command(config, command) @@ -67,6 +69,53 @@ shutil.rmtree(config.DATABASE) +def get_database_name(config): + '''Get database name using config.RDBMS_NAME or config.RDBMS_SERVICE. + + If database specifed using RDBMS_SERVICE does not exist, + the error message is parsed for the database name. This + will fail if the error message changes. The alternative is + to try to find and parse the .pg_service .ini style file on + unix/windows. This is less palatable. + + If the database specified using RDBMS_SERVICE does exist, (i.e. we + are doing a nuke operation), use psycopg.extenstion.ConnectionInfo + to get the dbname. This requires psycopg2 > 2.8 from 2018. + ''' + + if config.RDBMS_NAME: + return config.RDBMS_NAME + + template1 = connection_dict(config) + try: + conn = psycopg2.connect(**template1) + except psycopg2.OperationalError as message: + import re + # extract db name from error: + # 'connection to server at "127.0.0.1", port 5432 failed: \ + # FATAL: database "rounduptest" does not exist\n' + # ugh. + # + # Database name is any character sequence not including a " or + # whitespace. Arguably both are allowed by: + # + # https://www.postgresql.org/docs/current/sql-syntax-lexical.html#SQL-SYNTAX-IDENTIFIERS + # + # with suitable quoting but ... really. + search = re.search( + 'FATAL:\s+database\s+"([^"\s]*)"\s+does\s+not\s+exist', + message.args[0]) + if search: + dbname = search.groups()[0] + return dbname + + raise hyperdb.DatabaseError( + "Unable to determine database from service: %s" % message) + + dbname = psycopg2.extensions.ConnectionInfo(conn).dbname + conn.close() + return dbname + def db_command(config, command, database='postgres'): '''Perform some sort of database-level command. Retry 10 times if we fail by conflicting with another user. @@ -93,7 +142,7 @@ return finally: conn.close() - raise RuntimeError('10 attempts to create database failed') + raise RuntimeError('10 attempts to create database failed when running: %s' % commandb) def pg_command(cursor, command):
