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

Commit fc8598b

Browse files
authored
Minor updates, and docs, for schema delta files (#11823)
* Make functions in python deltas optional It's annoying to always have to write stubs for these. * Documentation for delta files * changelog
1 parent 4210143 commit fc8598b

File tree

3 files changed

+61
-3
lines changed

3 files changed

+61
-3
lines changed

changelog.d/11823.misc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Minor updates and documentation for database schema delta files.

docs/development/database_schema.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,60 @@ Ensure postgres is installed, then run:
9696
NB at the time of writing, this script predates the split into separate `state`/`main`
9797
databases so will require updates to handle that correctly.
9898

99+
## Delta files
100+
101+
Delta files define the steps required to upgrade the database from an earlier version.
102+
They can be written as either a file containing a series of SQL statements, or a Python
103+
module.
104+
105+
Synapse remembers which delta files it has applied to a database (they are stored in the
106+
`applied_schema_deltas` table) and will not re-apply them (even if a given file is
107+
subsequently updated).
108+
109+
Delta files should be placed in a directory named `synapse/storage/schema/<database>/delta/<version>/`.
110+
They are applied in alphanumeric order, so by convention the first two characters
111+
of the filename should be an integer such as `01`, to put the file in the right order.
112+
113+
### SQL delta files
114+
115+
These should be named `*.sql`, or — for changes which should only be applied for a
116+
given database engine — `*.sql.posgres` or `*.sql.sqlite`. For example, a delta which
117+
adds a new column to the `foo` table might be called `01add_bar_to_foo.sql`.
118+
119+
Note that our SQL parser is a bit simple - it understands comments (`--` and `/*...*/`),
120+
but complex statements which require a `;` in the middle of them (such as `CREATE
121+
TRIGGER`) are beyond it and you'll have to use a Python delta file.
122+
123+
### Python delta files
124+
125+
For more flexibility, a delta file can take the form of a python module. These should
126+
be named `*.py`. Note that database-engine-specific modules are not supported here –
127+
instead you can write `if isinstance(database_engine, PostgresEngine)` or similar.
128+
129+
A Python delta module should define either or both of the following functions:
130+
131+
```python
132+
import synapse.config.homeserver
133+
import synapse.storage.engines
134+
import synapse.storage.types
135+
136+
137+
def run_create(
138+
cur: synapse.storage.types.Cursor,
139+
database_engine: synapse.storage.engines.BaseDatabaseEngine,
140+
) -> None:
141+
"""Called whenever an existing or new database is to be upgraded"""
142+
...
143+
144+
def run_upgrade(
145+
cur: synapse.storage.types.Cursor,
146+
database_engine: synapse.storage.engines.BaseDatabaseEngine,
147+
config: synapse.config.homeserver.HomeServerConfig,
148+
) -> None:
149+
"""Called whenever an existing database is to be upgraded."""
150+
...
151+
```
152+
99153
## Boolean columns
100154

101155
Boolean columns require special treatment, since SQLite treats booleans the

synapse/storage/prepare_database.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -499,9 +499,12 @@ def _upgrade_existing_database(
499499
module = importlib.util.module_from_spec(spec)
500500
spec.loader.exec_module(module) # type: ignore
501501

502-
logger.info("Running script %s", relative_path)
503-
module.run_create(cur, database_engine) # type: ignore
504-
if not is_empty:
502+
if hasattr(module, "run_create"):
503+
logger.info("Running %s:run_create", relative_path)
504+
module.run_create(cur, database_engine) # type: ignore
505+
506+
if not is_empty and hasattr(module, "run_upgrade"):
507+
logger.info("Running %s:run_upgrade", relative_path)
505508
module.run_upgrade(cur, database_engine, config=config) # type: ignore
506509
elif ext == ".pyc" or file_name == "__pycache__":
507510
# Sometimes .pyc files turn up anyway even though we've

0 commit comments

Comments
 (0)