mirror: initialize EAV primitives at registration (#1341)

Summary:
This establishes the invariant that every object in the `objects` table
has all relevant rows in the `primitives` table, though those rows’
values are never yet set.

Test Plan:
Unit tests updated. Manually loading `sourcecred/example-github` and
running `.dump primitives` generates reasonable-looking output, with
lots of rows, including entries for nested fields and eggs. Verified
that the set of non-`id` columns on `Issue` equals the set of values for
the `fieldname` column of an `Issue` object, and likewise for `Commit`s,
thus covering each kind of field.

wchargin-branch: mirror-eav-init
This commit is contained in:
William Chargin 2019-09-14 17:24:58 -07:00 committed by GitHub
parent 0418dfe9dd
commit 463f3a073a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 3 deletions

View File

@ -196,7 +196,7 @@ export class Mirror {
// it requires bumping the version, bump it: requiring some extra
// one-time cache resets is okay; doing the wrong thing is not.
const blob = stringify({
version: "MIRROR_v4",
version: "MIRROR_v5",
schema: this._schema,
options: {
blacklistedIds: this._blacklistedIds,
@ -479,6 +479,12 @@ export class Mirror {
`
)
.run(id);
const addPrimitive = this._db.prepare(
dedent`
INSERT INTO primitives (object_id, fieldname, value)
VALUES (:id, :fieldname, NULL)
`
);
const addLink = this._db.prepare(
dedent`\
INSERT INTO links (parent_id, fieldname, child_id)
@ -495,12 +501,20 @@ export class Mirror {
`
);
const objectType = this._schemaInfo.objectTypes[typename];
for (const fieldname of objectType.primitiveFieldNames) {
addPrimitive.run({id, fieldname});
}
for (const fieldname of objectType.linkFieldNames) {
addLink.run({id, fieldname});
}
for (const parentFieldname of objectType.nestedFieldNames) {
const children = objectType.nestedFields[parentFieldname].nodes;
for (const childFieldname of Object.keys(children)) {
addPrimitive.run({id, fieldname: parentFieldname});
const children = objectType.nestedFields[parentFieldname];
for (const childFieldname of Object.keys(children.primitives)) {
const fieldname = `${parentFieldname}.${childFieldname}`;
addPrimitive.run({id, fieldname});
}
for (const childFieldname of Object.keys(children.nodes)) {
const fieldname = `${parentFieldname}.${childFieldname}`;
addLink.run({id, fieldname});
}

View File

@ -360,6 +360,15 @@ describe("graphql/mirror", () => {
title: null,
},
]);
expect(
db
.prepare(
"SELECT fieldname FROM primitives WHERE object_id = ? " +
"ORDER BY fieldname ASC"
)
.pluck()
.all(issueId)
).toEqual(["url", "title"].sort());
expect(
db
@ -369,6 +378,12 @@ describe("graphql/mirror", () => {
.pluck()
.get()
).toBe(0);
expect(
db
.prepare("SELECT COUNT(1) FROM primitives WHERE value IS NOT NULL")
.pluck()
.get()
).toBe(0);
expect(
db
.prepare("SELECT COUNT(1) FROM links WHERE child_id IS NOT NULL")
@ -418,6 +433,15 @@ describe("graphql/mirror", () => {
"author.date": null,
},
]);
expect(
db
.prepare(
"SELECT fieldname FROM primitives WHERE object_id = ? " +
"ORDER BY fieldname ASC"
)
.pluck()
.all(commitId)
).toEqual(["oid", "author", "author.date"].sort());
expect(
db