Skip to content

Commit c76ba59

Browse files
committed
Update docs on db upgrade and downgrade
1 parent d723645 commit c76ba59

1 file changed

Lines changed: 62 additions & 32 deletions

File tree

Lines changed: 62 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ This document explains how to write or generate those scripts.
1313
2. Run `misc/scripts/prepare-db-upgrade.sh --lang <lang>`. This will generate skeleton upgrade/downgrade scripts in the appropriate directories.
1414
3. Fill in the details in the two `upgrade.properties` files that it generated, and add any required upgrade queries.
1515

16+
The generated directory names are hashes of the old and new `.dbscheme` files. If the
17+
schema changes after generating the scripts, delete the generated directories and run the
18+
script again so that the directory names and schema snapshots use the correct hashes.
19+
1620
It may be helpful to look at some of the existing upgrade/downgrade scripts, to see how they work.
1721

1822
## Details
@@ -25,7 +29,9 @@ compatibility: partial
2529
some_relation.rel: run some_relation.qlo
2630
```
2731

28-
The `description` field is a textual description of the aim of the upgrade.
32+
The `description` field is a textual description of the aim of the step. Describe the
33+
operation in its actual direction: for example, a downgrade that removes a newly added
34+
table should say that it removes the table.
2935

3036
The `compatibility` field takes one of four values:
3137

@@ -37,14 +43,36 @@ The `compatibility` field takes one of four values:
3743

3844
* **breaking**: the step is unsafe and will prevent certain queries from working.
3945

40-
The `some_relation.rel` line(s) are the actions required to perform the database upgrade. Do a diff on the new vs old `.dbscheme` file to get an idea of what they have to achieve. Sometimes you won't need any upgrade commands – this happens when the dbscheme has changed in "cosmetic" ways, for example by adding/removing comments or changing union type relationships, but still retains the same on-disk format for all tables; the purpose of the upgrade script is then to document the fact that it's safe to replace the old dbscheme with the new one.
46+
Choose compatibility independently for the upgrade and downgrade, because the two directions
47+
may preserve different amounts of information.
48+
49+
The `some_relation.rel` line(s) are the actions required to transform the database in the
50+
direction of the step. Upgrade and downgrade directories use the same file name and command
51+
syntax, even though a file in a downgrade directory describes a downgrade. Diff `old.dbscheme`
52+
against the target `.dbscheme` in the generated directory to determine which actions are
53+
needed.
54+
55+
No action is needed for a relation added by the target schema if it should be empty in the
56+
transformed database. A missing relation is treated as empty, so do not add a `.rel` line just
57+
to create an empty file. If extraction would populate the new relation, however, the upgrade
58+
is not `full`: it will usually be `backwards`, because queries using the new relation may have
59+
degraded results on upgraded databases.
60+
61+
A relation that exists in `old.dbscheme` but not in the target schema should normally be
62+
deleted explicitly with `relation.rel: delete` so that the transformation does not leave
63+
obsolete data behind.
64+
65+
Sometimes no commands are needed because the schema changed only cosmetically, for example
66+
by adding or removing comments or changing union type relationships without changing the
67+
on-disk format. The script then documents that it is safe to replace the old schema with the
68+
new one.
4169

4270
Ideally, your downgrade script will perfectly revert the changes applied by the upgrade script, such that applying the upgrade and then the downgrade will result in the same database you started with.
4371

44-
Some typical upgrade commands look like this:
72+
Some typical upgrade or downgrade commands look like this:
4573

4674
```
47-
// Delete a relation that has been replaced in the new scheme
75+
// Delete a relation that does not exist in the target schema
4876
obsolete.rel: delete
4977
5078
// Create a new version of a table by applying an expression (using a simple
@@ -83,7 +111,7 @@ To test the upgrade script, run:
83111
codeql test run --search-path=<old-extractor-pack> --search-path=<codeql-root> <test-dir>
84112
```
85113

86-
Where `<old-extractor-pack>` is an extractor pack containing the old extractor and dbscheme that pre-date your changes, `<test-dir>` is the directory containing the qltests for your language, and `<codeql-root>` is the root directory directory of the `github/codeql` clone that contains `<test-dir>`. This will run the tests using an old extractor, and the test databases will all be upgraded in place using your new upgrade script.
114+
Where `<old-extractor-pack>` is an extractor pack containing the old extractor and dbscheme that pre-date your changes, `<test-dir>` is the directory containing the qltests for your language, and `<codeql-root>` is the root directory of the `github/codeql` clone that contains `<test-dir>`. This will run the tests using an old extractor, and the test databases will all be upgraded in place using your new upgrade script.
87115

88116
To test the downgrade script, create an extractor pack that includes your new dbscheme and extractor changes. Then checkout the `main` branch of `codeql` (i.e. a branch that does not include your changes), and run:
89117

@@ -107,43 +135,45 @@ You might also choose to test with a real-world database.
107135

108136
5. Verify that your queries produced sensible results.
109137

110-
#### Doing the upgrade manually
111-
112-
To create the upgrade directory manually, without using `prepare-db-upgrade.sh`:
113-
114-
1. Get a hash of the old `.dbscheme` file from `main` (i.e. from just before your changes). You can do this by checking out the code prior to your changes and running `git hash-object ql/lib/<mylang>.dbscheme`
115-
116-
2. Go back to your branch and create an upgrade directory with that hash as its name, for example:
117-
```
118-
mkdir ql/lib/upgrades/454f1e15151422355049dc4f1f0486a03baeffef
119-
```
138+
#### Creating the scripts manually
120139

140+
To create both directions manually, without using `prepare-db-upgrade.sh`:
121141

122-
3. Copy the old `.dbscheme` file to that directory, using the name old.dbscheme.
142+
1. Get the hashes of the old `.dbscheme` from `main` and the new `.dbscheme` from
143+
your branch. For example:
123144

124-
```
125-
cp ql/lib/<mylang>.dbscheme ql/lib/upgrades/454f1e15151422355049dc4f1f0486a03baeffef/old.dbscheme
126-
```
145+
```sh
146+
old_hash=$(git show main:ql/lib/<mylang>.dbscheme | git hash-object --stdin)
147+
new_hash=$(git hash-object ql/lib/<mylang>.dbscheme)
148+
```
127149

128-
4. Put a copy of your new `.dbscheme` file in that directory and create an `upgrade.properties` file (as described above).
150+
2. Create the upgrade directory using the old hash and the downgrade directory using the
151+
new hash:
129152

130-
#### Doing the downgrade manually
153+
```sh
154+
mkdir -p ql/lib/upgrades/$old_hash
155+
mkdir -p downgrades/$new_hash
156+
```
131157

132-
The process is similar for downgrade scripts, but there is a reversal in terminology: your **new** dbscheme will now be the one called `old.dbscheme`.
158+
3. Populate the upgrade directory. Here, `old.dbscheme` is the schema from `main`, and
159+
`<mylang>.dbscheme` is the new target schema:
133160

134-
1. Get a hash of your new `.dbscheme` file, with `git hash-object ql/lib/<mylang>.dbscheme`
161+
```sh
162+
git show main:ql/lib/<mylang>.dbscheme > ql/lib/upgrades/$old_hash/old.dbscheme
163+
cp ql/lib/<mylang>.dbscheme ql/lib/upgrades/$old_hash/<mylang>.dbscheme
164+
```
135165

136-
2. Create a downgrade directory with that hash as its name, for example:
137-
```
138-
mkdir downgrades/9fdd1d40fd3c3f8f9db8fabf5a353580d14c663a
139-
```
166+
4. Populate the downgrade directory in the opposite direction. For a downgrade, the new
167+
schema is called `old.dbscheme`, because it is the schema before the downgrade step:
140168

141-
3. Copy your new `.dbscheme` file to that directory, using the name `old.dbscheme`.
142-
```
143-
cp ql/lib/<mylang>.dbscheme ql/lib/upgrades/454f1e15151422355049dc4f1f0486a03baeffef/old.dbscheme
144-
```
169+
```sh
170+
cp ql/lib/<mylang>.dbscheme downgrades/$new_hash/old.dbscheme
171+
git show main:ql/lib/<mylang>.dbscheme > downgrades/$new_hash/<mylang>.dbscheme
172+
```
145173

146-
4. Put a copy of the `.dbscheme` from `main` in that directory and create an `upgrade.properties` file that performs the downgrade (as described above).
174+
5. Create an `upgrade.properties` file in each directory. The file in the upgrade directory
175+
describes the forward transformation, while the file in the downgrade directory describes
176+
the reverse transformation.
147177

148178
### Debugging your scripts
149179

0 commit comments

Comments
 (0)