Merge ~pappacena/launchpad:db-patch-ociproject-project-pillar into launchpad:db-devel

Proposed by Thiago F. Pappacena
Status: Merged
Approved by: Thiago F. Pappacena
Approved revision: 714e39f042625aaa3e914efe1acae14063a1882b
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~pappacena/launchpad:db-patch-ociproject-project-pillar
Merge into: launchpad:db-devel
Diff against target: 52 lines (+46/-0)
1 file modified
database/schema/patch-2210-08-8.sql (+46/-0)
Reviewer Review Type Date Requested Status
Colin Watson (community) Approve
Review via email: mp+383819@code.launchpad.net

This proposal supersedes a proposal from 2020-05-12.

Commit message

Adding OCIProject.product database column and adjusting the way GitRepository table references OCIProject.

To post a comment you must log in.
Revision history for this message
Colin Watson (cjwatson) wrote :

I would move this patch to 2210-08-8; it might as well be part of the overall OCI series, as long as we haven't yet reached 9 and had to overflow to another minor number.

There are several other things we need to add:

 * Rename OCIProject.product to OCIProject.project. While we still use the term "product" in anything old (partly because there's a lot of code to change, and partly because renaming DB columns/tables is awkward), everything new uses the term "project" instead. Compare GitRepository.project.

 * Add something like this to the `ALTER TABLE OCIProject` statement so that it's actually possible to create an OCIProject row based on a project:
   ALTER COLUMN distribution DROP NOT NULL,
   ADD CONSTRAINT one_container CHECK ((project IS NULL) != (distribution IS NULL))

 * Add a unique index on `OCIProject (project, ociprojectname) WHERE project IS NOT NULL`.

 * Change the GitRepository one_container constraint to allow `(project IS NOT NULL AND distribution IS NULL AND sourcepackagename IS NULL AND ociprojectname IS NOT NULL)`.

 * Alter most of the GitRepository project indexes involving (project) and (owner, project) to add a `WHERE ociprojectname IS NULL` condition, and add parallel indexes for the `ociprojectname IS NOT NULL` case. This is similar to 2210-08-1 and 2210-08-2, which between them do a similar sort of operation to add (distribution, ociprojectname) alongside (distribution, sourcepackagename).
  * Note that there are complexities here because creating indexes on non-trivial tables is generally too slow to be done during a fastdowntime deployment. You'll need the same kind of structure that you see in 2210-08-1 and 2210-08-2: the initial cold patch should rename the relevant existing indexes to add an `old__` prefix; the follow-up hot patch should create new indexes and drop the old ones. These must not be in the same MP; the hot patch should be proposed against master from a branch that doesn't include the cold patch. We'll need to apply the hot patch manually to production with `CONCURRENTLY` shortly after the fastdowntime, and sync up master later.

review: Needs Fixing
Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

cjwatson, I think this MP is good for another round of review.

I also created another MP (pointing to master) here, with statements that we should run as "cold patch" with CONCURRENTLY: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/383897

Revision history for this message
William Grant (wgrant) wrote :

The proposed GitRepository change is not without controversy. I realise I approved something analogous in https://code.launchpad.net/~cjwatson/launchpad/+git/launchpad/+merge/374672, but I think it's worth discussing. Are we sure we want to use GitRepository(project, ociprojectname) rather than GitRepository(ociproject)?

DistributionSourcePackage started off weird because the DistributionSourcePackage table (DistributionSourcePackageInDatabase is the Storm model) was added many years after the DistributionSourcePackage virtual object, to store a couple of metadata fields. That's why they're generally referenced in the DB as (distribution, sourcepackagename) -- for most older tables there was no DistributionSourcePackage to add a foreign key to. This makes renames, moves, etc. impossible, which is somewhat OK because it's not really possible to rename source packages anyway, but that's not something we necessarily want to replicate.

Storing the tuple in GitRepository does make finding all the repositories on a pillar easier, but there are other ways to do that search efficiently. It's also much less clear how we'd implement more generalised subprojects using the tuple model.

Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

I agree that the database would be strongly simplified if we have GitRepository(ociproject).

It will probably require some refactoring and data migration, but I guess it worth it. I'll take a look on what should be changed codewise to adapt to it.

Do you see some downside on having GitRepository(ociproject), cjwatson?

Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Changed GitRepository table to deprecate ociprojectname column and create a new oci_project column.

As discussed with cjwatson, this column is referenced by the code today (so it cannot be dropped until code changes reaches production) but it shouldn't be in use just yet. Therefore, we don't need to migrate any data.

I have also updated the related MP (https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/383897) to create indexes for oci_project, and those we will need to run with CONCURRENTLY.

Revision history for this message
Colin Watson (cjwatson) :
review: Approve
Revision history for this message
Colin Watson (cjwatson) wrote :

It might be a good idea to update the commit message to mention something about GitRepository as well, if you can do so concisely.

Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

Pushed the requested changes. I'll land this, and we need to apply https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/384670 manually.

Revision history for this message
William Grant (wgrant) wrote :

Vanilla ADD CONSTRAINT on a table with non-trivial data isn't generally permitted, as it's too slow. It should be preferred to create the constraint with NOT VALID and then VALIDATE it in a hot patch later.

GitRepository may be small enough that we can get away with it here, but we should confirm on staging.

Revision history for this message
Thiago F. Pappacena (pappacena) wrote :

wgrant, I'm creating a new MP to add the NOT VALID, and updating the hot patch to run the VALIDATE.

- MP to add NOT VALID: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/385005
- Hot patch update: https://code.launchpad.net/~pappacena/launchpad/+git/launchpad/+merge/384670

This branch got merged, but since it's just a CHECK constraint validation, there shouldn't be any problem if it was already applied somewhere (ALTER TABLE ... VALIDATE is idempotent).

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/database/schema/patch-2210-08-8.sql b/database/schema/patch-2210-08-8.sql
2new file mode 100644
3index 0000000..dffbaac
4--- /dev/null
5+++ b/database/schema/patch-2210-08-8.sql
6@@ -0,0 +1,46 @@
7+-- Copyright 2020 Canonical Ltd. This software is licensed under the
8+-- GNU Affero General Public License version 3 (see the file LICENSE).
9+
10+SET client_min_messages=ERROR;
11+
12+ALTER TABLE OCIProject ADD COLUMN project integer REFERENCES product;
13+
14+ALTER TABLE OCIProject
15+ ALTER COLUMN distribution
16+ DROP NOT NULL,
17+ ADD CONSTRAINT one_container
18+ CHECK ((project IS NULL) != (distribution IS NULL));
19+
20+COMMENT ON COLUMN OCIProject.project
21+ IS 'The project that this OCI project is associated with.';
22+
23+CREATE UNIQUE INDEX ociproject__project__ociprojectname__key
24+ ON OCIProject (project, ociprojectname) WHERE project IS NOT NULL;
25+
26+
27+-- Alter GitRepository table to allow oci_project.
28+COMMENT ON COLUMN GitRepository.ociprojectname
29+ IS 'Deprecated column. Check one_container and default_implies_target constraints before removing.';
30+
31+ALTER TABLE GitRepository
32+ ADD COLUMN oci_project integer REFERENCES ociproject,
33+ DROP CONSTRAINT one_container,
34+ ADD CONSTRAINT one_container CHECK (
35+ -- Distribution + OCIProjectName, to keep compatibility temporarily
36+ (project IS NULL AND distribution IS NOT NULL AND sourcepackagename IS NULL AND ociprojectname IS NOT NULL) OR
37+ -- Project
38+ (project IS NOT NULL AND distribution IS NULL AND sourcepackagename IS NULL AND oci_project IS NULL AND ociprojectname IS NULL) OR
39+ -- Distribution source package
40+ (project IS NULL AND distribution IS NOT NULL AND sourcepackagename IS NOT NULL AND oci_project IS NULL AND ociprojectname IS NULL) OR
41+ -- OCI project
42+ (project IS NULL AND distribution IS NULL AND sourcepackagename IS NULL AND oci_project IS NOT NULL AND ociprojectname IS NULL) OR
43+ -- Personal
44+ (project IS NULL AND distribution IS NULL AND sourcepackagename IS NULL AND oci_project IS NULL)),
45+ DROP CONSTRAINT default_implies_target,
46+ ADD CONSTRAINT default_implies_target CHECK (
47+ project IS NOT NULL
48+ OR distribution IS NOT NULL
49+ OR oci_project IS NOT NULL
50+ OR (NOT owner_default AND NOT target_default));
51+
52+INSERT INTO LaunchpadDatabaseRevision VALUES (2210, 8, 8);