Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

Don't default to an invalid sqlite config if no database configuration is provided #6573

Merged
merged 6 commits into from
Mar 26, 2020
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/6573.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Don't attempt to use an invalid sqlite config if no database configuration is provided. Contributed by @nekatak.
69 changes: 47 additions & 22 deletions synapse/config/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@

logger = logging.getLogger(__name__)

NON_SQLITE_DATABASE_PATH_WARNING = """\
Ignoring 'database_path' setting: not using a sqlite3 database.
--------------------------------------------------------------------------------
"""


class DatabaseConnectionConfig:
"""Contains the connection config for a particular database.
Expand Down Expand Up @@ -56,6 +61,11 @@ def __init__(self, name: str, db_config: dict):
class DatabaseConfig(Config):
section = "database"

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)

self.databases = []

def read_config(self, config, **kwargs):
self.event_cache_size = self.parse_size(config.get("event_cache_size", "10K"))

Expand All @@ -76,26 +86,31 @@ def read_config(self, config, **kwargs):

multi_database_config = config.get("databases")
database_config = config.get("database")
database_path = config.get("database_path")

if multi_database_config and database_config:
raise ConfigError("Can't specify both 'database' and 'datbases' in config")

if multi_database_config:
if config.get("database_path"):
if database_path:
raise ConfigError("Can't specify 'database_path' with 'databases'")

self.databases = [
DatabaseConnectionConfig(name, db_conf)
for name, db_conf in multi_database_config.items()
]

else:
if database_config is None:
database_config = {"name": "sqlite3", "args": {}}

if database_config:
self.databases = [DatabaseConnectionConfig("master", database_config)]

self.set_databasepath(config.get("database_path"))
if database_path:
if self.databases and self.databases[0].name != "sqlite3":
logger.warning(NON_SQLITE_DATABASE_PATH_WARNING)
return

database_config = {"name": "sqlite3", "args": {}}
self.databases = [DatabaseConnectionConfig("master", database_config)]
self.set_databasepath(database_path)
nekatak marked this conversation as resolved.
Show resolved Hide resolved

def generate_config_section(self, data_dir_path, database_conf, **kwargs):
if not database_conf:
Expand Down Expand Up @@ -127,27 +142,37 @@ def generate_config_section(self, data_dir_path, database_conf, **kwargs):
)

def read_arguments(self, args):
self.set_databasepath(args.database_path)
"""
Cases for the cli input:
- If no databases are configured and no database_path is set, raise.
- No databases and only database_path available ==> sqlite3 db.
- If there are multiple databases and a database_path raise an error.
- If the database set in the config file is sqlite then
overwrite with the command line argument.
"""

def set_databasepath(self, database_path):
if database_path is None:
if args.database_path is None:
if not self.databases:
raise ConfigError("No database config provided")
return

if database_path != ":memory:":
database_path = self.abspath(database_path)
if len(self.databases) == 0:
database_config = {"name": "sqlite3", "args": {}}
self.databases = [DatabaseConnectionConfig("master", database_config)]
self.set_databasepath(args.database_path)
return

if self.get_single_database().name == "sqlite3":
self.set_databasepath(args.database_path)
else:
logger.warning(NON_SQLITE_DATABASE_PATH_WARNING)

# We only support setting a database path if we have a single sqlite3
# database.
if len(self.databases) != 1:
raise ConfigError("Cannot specify 'database_path' with multiple databases")
def set_databasepath(self, database_path):

database = self.get_single_database()
if database.config["name"] != "sqlite3":
# We don't raise here as we haven't done so before for this case.
logger.warn("Ignoring 'database_path' for non-sqlite3 database")
return
if database_path != ":memory:":
database_path = self.abspath(database_path)

database.config["args"]["database"] = database_path
self.databases[0].config["args"]["database"] = database_path

@staticmethod
def add_arguments(parser):
Expand All @@ -162,7 +187,7 @@ def add_arguments(parser):
def get_single_database(self) -> DatabaseConnectionConfig:
"""Returns the database if there is only one, useful for e.g. tests
"""
if len(self.databases) != 1:
if not self.databases:
raise Exception("More than one database exists")

return self.databases[0]