diff --git a/apps/zbugs/api/index.ts b/apps/zbugs/api/index.ts index 7e1b2b391e..8c30e1d3e8 100644 --- a/apps/zbugs/api/index.ts +++ b/apps/zbugs/api/index.ts @@ -63,12 +63,12 @@ fastify.get<{ let userId = nanoid(); const existingUserId = - await sql`SELECT id FROM "user" WHERE "githubID" = ${userDetails.data.id}`; + await sql`SELECT user_id FROM "users" WHERE "githubID" = ${userDetails.data.id}`; if (existingUserId.length > 0) { - userId = existingUserId[0].id; + userId = existingUserId[0].user_id; } else { - await sql`INSERT INTO "user" - ("id", "login", "name", "avatar", "githubID") VALUES ( + await sql`INSERT INTO "users" + ("user_id", "login", "name", "avatar", "githubID") VALUES ( ${userId}, ${userDetails.data.login}, ${userDetails.data.name}, @@ -77,7 +77,7 @@ fastify.get<{ )`; } - const userRows = await sql`SELECT * FROM "user" WHERE "id" = ${userId}`; + const userRows = await sql`SELECT * FROM "users" WHERE "user_id" = ${userId}`; const jwtPayload = { sub: userId, diff --git a/apps/zbugs/docker/init_upstream/init.sql b/apps/zbugs/docker/init_upstream/init.sql index e292e0c5a3..ba9e0c18a2 100644 --- a/apps/zbugs/docker/init_upstream/init.sql +++ b/apps/zbugs/docker/init_upstream/init.sql @@ -1,37 +1,39 @@ -DROP TABLE IF EXISTS "user", -"issue", +CREATE SCHEMA IF NOT EXISTS mojo; +DROP TABLE IF EXISTS "users", +"issues", "comment", "label", "issueLabel", "emoji", +"mojo"."emoji", "userPref", -"zero.schemaVersions" CASCADE; +"zero"."schemaVersions" CASCADE; --- user +-- users -CREATE TABLE "user" ( - "id" VARCHAR PRIMARY KEY, +CREATE TABLE "users" ( + "user_id" VARCHAR PRIMARY KEY, "login" VARCHAR NOT NULL, "name" VARCHAR, "avatar" VARCHAR, - "role" VARCHAR DEFAULT 'user' NOT NULL, + "role" VARCHAR DEFAULT 'users' NOT NULL, "githubID" INTEGER NOT NULL ); -CREATE UNIQUE INDEX user_login_idx ON "user" (login); -CREATE UNIQUE INDEX user_githubid_idx ON "user" ("githubID"); +CREATE UNIQUE INDEX user_login_idx ON "users" (login); +CREATE UNIQUE INDEX user_githubid_idx ON "users" ("githubID"); --- issue +-- issues -CREATE TABLE issue ( - "id" VARCHAR PRIMARY KEY, +CREATE TABLE issues ( + "issue_id" VARCHAR PRIMARY KEY, "shortID" INTEGER GENERATED BY DEFAULT AS IDENTITY (START WITH 3000), "title" VARCHAR(128) NOT NULL, "open" BOOLEAN NOT NULL, "modified" double precision DEFAULT (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000), "created" double precision DEFAULT (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000), - "creatorID" VARCHAR REFERENCES "user"(id) NOT NULL, - "assigneeID" VARCHAR REFERENCES "user"(id), + "creatorID" VARCHAR REFERENCES "users"(user_id) NOT NULL, + "assigneeID" VARCHAR REFERENCES "users"(user_id), -- Size chosen because max we currently have in legacy data is ~9KB. "description" VARCHAR(10240) DEFAULT '', "visibility" VARCHAR DEFAULT 'public' NOT NULL @@ -47,7 +49,7 @@ END; $$ LANGUAGE plpgsql; CREATE TRIGGER issue_set_last_modified -BEFORE INSERT OR UPDATE ON issue +BEFORE INSERT OR UPDATE ON issues FOR EACH ROW EXECUTE FUNCTION update_modified_column(); @@ -60,15 +62,15 @@ END; $$ LANGUAGE plpgsql; CREATE TRIGGER issue_set_created_on_insert_trigger -BEFORE INSERT ON issue +BEFORE INSERT ON issues FOR EACH ROW EXECUTE FUNCTION issue_set_created_on_insert(); -- viewState CREATE TABLE "viewState" ( - "userID" VARCHAR REFERENCES "user"(id) ON DELETE CASCADE, - "issueID" VARCHAR REFERENCES issue(id) ON DELETE CASCADE, + "userID" VARCHAR REFERENCES "users"(user_id) ON DELETE CASCADE, + "issueID" VARCHAR REFERENCES issues(issue_id) ON DELETE CASCADE, "viewed" double precision, PRIMARY KEY ("userID", "issueID") ); @@ -77,18 +79,18 @@ CREATE TABLE "viewState" ( CREATE TABLE comment ( id VARCHAR PRIMARY KEY, - "issueID" VARCHAR REFERENCES issue(id) ON DELETE CASCADE, + "issueID" VARCHAR REFERENCES issues(issue_id) ON DELETE CASCADE, "created" double precision, "body" TEXT NOT NULL, - "creatorID" VARCHAR REFERENCES "user"(id) + "creatorID" VARCHAR REFERENCES "users"(user_id) ); CREATE OR REPLACE FUNCTION update_issue_modified_time() RETURNS TRIGGER AS $$ BEGIN - UPDATE issue + UPDATE issues SET modified = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 - WHERE id = NEW."issueID"; + WHERE issue_id = NEW."issueID"; RETURN NEW; END; $$ LANGUAGE plpgsql; @@ -145,38 +147,37 @@ CREATE TABLE label ( CREATE TABLE "issueLabel" ( "labelID" VARCHAR REFERENCES label(id), - "issueID" VARCHAR REFERENCES issue(id) ON DELETE CASCADE, + "issueID" VARCHAR REFERENCES issues(issue_id) ON DELETE CASCADE, PRIMARY KEY ("labelID", "issueID") ); -- emoji - -CREATE TABLE emoji ( - "id" VARCHAR PRIMARY KEY, +CREATE TABLE mojo.emoji ( + "idz_yo" VARCHAR PRIMARY KEY, "value" VARCHAR NOT NULL, "annotation" VARCHAR, - -- The PK of the "subject" (either issue or comment) that the emoji is attached to + -- The PK of the "subject" (either issues or comment) that the emoji is attached to -- We cannot use a FK to enforce referential integrity. Instead we use a trigger to enforce this. -- We wil also need a custom secondary index on this since the FK won't give it to us. "subjectID" VARCHAR NOT NULL, - "creatorID" VARCHAR REFERENCES "user"(id) ON DELETE CASCADE, + "creatorID" VARCHAR REFERENCES "users"(user_id) ON DELETE CASCADE, "created" double precision DEFAULT (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000), UNIQUE ("subjectID", "creatorID", "value") ); -CREATE INDEX emoji_created_idx ON emoji (created); -CREATE INDEX emoji_subject_id_idx ON emoji ("subjectID"); +CREATE INDEX emoji_created_idx ON mojo.emoji (created); +CREATE INDEX emoji_subject_id_idx ON mojo.emoji ("subjectID"); CREATE OR REPLACE FUNCTION emoji_check_subject_id() RETURNS TRIGGER AS $$ BEGIN - -- Check if subjectID exists in the issue table - IF EXISTS (SELECT 1 FROM issue WHERE id = NEW."subjectID") THEN + -- Check if subjectID exists in the issues table + IF EXISTS (SELECT 1 FROM issues WHERE issue_id = NEW."subjectID") THEN NULL; -- Do nothing ELSIF EXISTS (SELECT 1 FROM comment WHERE id = NEW."subjectID") THEN NULL; -- Do nothing ELSE - RAISE EXCEPTION 'id ''%'' does not exist in issue or comment', NEW."subjectID"; + RAISE EXCEPTION 'id ''%'' does not exist in issues or comment', NEW."subjectID"; END IF; PERFORM update_issue_modified_on_emoji_change(NEW."subjectID"); @@ -186,7 +187,7 @@ END; $$ LANGUAGE plpgsql; CREATE OR REPLACE TRIGGER emoji_check_subject_id_update_trigger -BEFORE INSERT OR UPDATE ON emoji +BEFORE INSERT OR UPDATE ON mojo.emoji FOR EACH ROW EXECUTE FUNCTION emoji_check_subject_id(); @@ -199,21 +200,21 @@ END; $$ LANGUAGE plpgsql; CREATE OR REPLACE TRIGGER emoji_set_created_on_insert_trigger -BEFORE INSERT ON emoji +BEFORE INSERT ON mojo.emoji FOR EACH ROW EXECUTE FUNCTION emoji_set_created_on_insert(); --- Delete emoji when issue is deleted +-- Delete emoji when issues is deleted CREATE OR REPLACE FUNCTION delete_emoji_on_issue_delete() RETURNS TRIGGER AS $$ BEGIN - DELETE FROM emoji WHERE "subjectID" = OLD.id; + DELETE FROM mojo.emoji WHERE "subjectID" = OLD.id; RETURN OLD; END; $$ LANGUAGE plpgsql; CREATE TRIGGER delete_emoji_on_issue_delete_trigger -AFTER DELETE ON issue +AFTER DELETE ON issues FOR EACH ROW EXECUTE FUNCTION delete_emoji_on_issue_delete(); @@ -221,7 +222,7 @@ EXECUTE FUNCTION delete_emoji_on_issue_delete(); CREATE OR REPLACE FUNCTION delete_emoji_on_comment_delete() RETURNS TRIGGER AS $$ BEGIN - DELETE FROM emoji WHERE "subjectID" = OLD.id; + DELETE FROM mojo.emoji WHERE "subjectID" = OLD.id; RETURN OLD; END; $$ LANGUAGE plpgsql; @@ -231,18 +232,18 @@ AFTER DELETE ON comment FOR EACH ROW EXECUTE FUNCTION delete_emoji_on_comment_delete(); --- When an emoji is added or deleted we find the issue and update the modified time +-- When an emoji is added or deleted we find the issues and update the modified time CREATE OR REPLACE FUNCTION update_issue_modified_on_emoji_change("subjectID" VARCHAR) RETURNS VOID AS $$ BEGIN - UPDATE issue + UPDATE issues SET modified = EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) * 1000 FROM ( - SELECT issue.id AS id - FROM issue JOIN comment ON issue.id=comment."issueID" - WHERE comment.id = "subjectID" OR issue.id = "subjectID" + SELECT issues.issue_id AS id + FROM issues JOIN comment ON issues.issue_id=comment."issueID" + WHERE comment.id = "subjectID" OR issues.issue_id = "subjectID" ) AS subquery - WHERE issue.id = subquery.id; + WHERE issues.issue_id = subquery.id; END; $$ LANGUAGE plpgsql; @@ -251,7 +252,7 @@ $$ LANGUAGE plpgsql; CREATE TABLE "userPref" ( "key" VARCHAR NOT NULL, "value" VARCHAR NOT NULL, - "userID" VARCHAR REFERENCES "user"(id) ON DELETE CASCADE, + "userID" VARCHAR REFERENCES "users"(user_id) ON DELETE CASCADE, PRIMARY KEY ("userID", "key") ); @@ -275,7 +276,7 @@ INSERT INTO zero."schemaVersions" ("lock", "minSupportedVersion", "maxSupportedV VALUES (true, 3, 5) ON CONFLICT DO NOTHING; -COPY "user" +COPY "users" FROM '/docker-entrypoint-initdb.d/users.csv' WITH CSV HEADER; @@ -283,7 +284,7 @@ COPY "label" FROM '/docker-entrypoint-initdb.d/labels.csv' WITH CSV HEADER; -COPY "issue" ("id","shortID","title","open","modified","created","creatorID","assigneeID","description") +COPY "issues" ("issue_id","shortID","title","open","modified","created","creatorID","assigneeID","description") FROM '/docker-entrypoint-initdb.d/issues.csv' WITH CSV HEADER; @@ -308,12 +309,15 @@ FROM -- place to manage indices and it saves us a step in setting up our demo apps. CREATE INDEX issuelabel_issueid_idx ON "issueLabel" ("issueID"); -CREATE INDEX issue_modified_idx ON issue (modified); +CREATE INDEX issue_modified_idx ON issues (modified); -CREATE INDEX issue_created_idx ON issue (created); +CREATE INDEX issue_created_idx ON issues (created); -CREATE INDEX issue_open_modified_idx ON issue (open, modified); +CREATE INDEX issue_open_modified_idx ON issues (open, modified); CREATE INDEX comment_issueid_idx ON "comment" ("issueID"); + +CREATE PUBLICATION zero_all_the_data FOR TABLES IN SCHEMA public, TABLES IN SCHEMA mojo; + VACUUM; \ No newline at end of file diff --git a/apps/zbugs/docker/init_upstream/issues.csv b/apps/zbugs/docker/init_upstream/issues.csv index c5cb6da97e..af74b036c9 100644 --- a/apps/zbugs/docker/init_upstream/issues.csv +++ b/apps/zbugs/docker/init_upstream/issues.csv @@ -1,4 +1,4 @@ -id,shortID,title,open,modified,created,creatorID,assigneeID,description +issue_id,shortID,title,open,modified,created,creatorID,assigneeID,description HdpMkgbHpK3_OcOIiQOuW,2383,Leaking listeners on AbortSignal,True,1726473766000.0,1726473756000.0,nqYkxAGMnzk7Y5STjZryV,,"Node.js is complaining about ![image](https://github.com/user-attachments/assets/fabb10ce-e684-4e9a-bb02-e36f77dc0c93) diff --git a/apps/zbugs/docker/init_upstream/users.csv b/apps/zbugs/docker/init_upstream/users.csv index 164519405d..0361b194fa 100644 --- a/apps/zbugs/docker/init_upstream/users.csv +++ b/apps/zbugs/docker/init_upstream/users.csv @@ -1,4 +1,4 @@ -id,login,name,avatar,role,githubID +user_id,login,name,avatar,role,githubID nqYkxAGMnzk7Y5STjZryV,arv,Erik Arvidsson,https://avatars.githubusercontent.com/u/45845?v=4,crew,45845 ieK09sy2C_AIWE8KRkrQR,darkgnotic,Darick Tong,https://avatars.githubusercontent.com/u/132324914?v=4,crew,132324914 pFCse65icLsHqrf1TJMuV,linear[bot],linear[bot],https://avatars.githubusercontent.com/in/20150?v=4,user,44709815 diff --git a/apps/zbugs/schema.ts b/apps/zbugs/schema.ts index f5661bd896..1ab7fdd9a9 100644 --- a/apps/zbugs/schema.ts +++ b/apps/zbugs/schema.ts @@ -14,8 +14,9 @@ import type {Condition} from 'zero-protocol/src/ast.js'; // Table definitions const user = table('user') + .from('users') .columns({ - id: string(), + id: string().from('user_id'), login: string(), name: string().optional(), avatar: string(), @@ -24,8 +25,9 @@ const user = table('user') .primaryKey('id'); const issue = table('issue') + .from('issues') .columns({ - id: string(), + id: string().from('issue_id'), shortID: number().optional(), title: string(), open: boolean(), @@ -71,8 +73,9 @@ const issueLabel = table('issueLabel') .primaryKey('issueID', 'labelID'); const emoji = table('emoji') + .from('mojo.emoji') .columns({ - id: string(), + id: string().from('idz_yo'), value: string(), annotation: string(), subjectID: string(),