| Index: appengine/monorail/sql/tracker.sql
|
| diff --git a/appengine/monorail/sql/tracker.sql b/appengine/monorail/sql/tracker.sql
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..27c9e444106fbfa5f77822b154be407af1065271
|
| --- /dev/null
|
| +++ b/appengine/monorail/sql/tracker.sql
|
| @@ -0,0 +1,646 @@
|
| +-- Copyright 2016 The Chromium Authors. All Rights Reserved.
|
| +--
|
| +-- Use of this source code is governed by a BSD-style
|
| +-- license that can be found in the LICENSE file or at
|
| +-- https://developers.google.com/open-source/licenses/bsd
|
| +
|
| +
|
| +-- Create issue-realted tables in monorail db.
|
| +
|
| +
|
| +CREATE TABLE StatusDef (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + status VARCHAR(80) BINARY NOT NULL,
|
| + rank SMALLINT UNSIGNED,
|
| + means_open BOOLEAN,
|
| + docstring TEXT,
|
| + deprecated BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (id),
|
| + UNIQUE KEY (project_id, status),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE ComponentDef (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| +
|
| + -- Note: parent components have paths that are prefixes of child components.
|
| + path VARCHAR(255) BINARY NOT NULL,
|
| + docstring TEXT,
|
| + deprecated BOOLEAN DEFAULT FALSE,
|
| + created INT,
|
| + creator_id INT UNSIGNED,
|
| + modified INT,
|
| + modifier_id INT UNSIGNED,
|
| +
|
| + PRIMARY KEY (id),
|
| + UNIQUE KEY (project_id, path),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id),
|
| + FOREIGN KEY (creator_id) REFERENCES User(user_id),
|
| + FOREIGN KEY (modifier_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Component2Admin (
|
| + component_id INT NOT NULL,
|
| + admin_id INT UNSIGNED NOT NULL,
|
| +
|
| + PRIMARY KEY (component_id, admin_id),
|
| +
|
| + FOREIGN KEY (component_id) REFERENCES ComponentDef(id),
|
| + FOREIGN KEY (admin_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Component2Cc (
|
| + component_id INT NOT NULL,
|
| + cc_id INT UNSIGNED NOT NULL,
|
| +
|
| + PRIMARY KEY (component_id, cc_id),
|
| +
|
| + FOREIGN KEY (component_id) REFERENCES ComponentDef(id),
|
| + FOREIGN KEY (cc_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE LabelDef (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + label VARCHAR(80) BINARY NOT NULL,
|
| + rank SMALLINT UNSIGNED,
|
| + docstring TEXT,
|
| + deprecated BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (id),
|
| + UNIQUE KEY (project_id, label),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE FieldDef (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + rank SMALLINT UNSIGNED,
|
| +
|
| + field_name VARCHAR(80) BINARY NOT NULL,
|
| + -- TODO(jrobbins): more types
|
| + field_type ENUM ('enum_type', 'int_type', 'str_type', 'user_type') NOT NULL,
|
| + applicable_type VARCHAR(80), -- No value means: offered for all issue types
|
| + applicable_predicate TEXT, -- No value means: TRUE
|
| + is_required BOOLEAN, -- true means required if applicable
|
| + is_multivalued BOOLEAN,
|
| + -- TODO(jrobbins): access controls: restrict, grant
|
| + -- Validation for int_type fields
|
| + min_value INT,
|
| + max_value INT,
|
| + -- Validation for str_type fields
|
| + regex VARCHAR(80),
|
| + -- Validation for user_type fields
|
| + needs_member BOOLEAN, -- User value can only be set to users who are members
|
| + needs_perm VARCHAR(80), -- User value can only be set to users w/ that perm
|
| + grants_perm VARCHAR(80), -- User named in this field gains this perm in the issue
|
| + -- notification options for user_type fields
|
| + notify_on ENUM ('never', 'any_comment') DEFAULT 'never' NOT NULL,
|
| +
|
| + -- TODO(jrobbins): default value
|
| + -- TODO(jrobbins): deprecated boolean?
|
| + docstring TEXT,
|
| + is_deleted BOOLEAN, -- If true, reap this field def after all values reaped.
|
| +
|
| + PRIMARY KEY (id),
|
| + UNIQUE KEY (project_id, field_name),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE FieldDef2Admin (
|
| + field_id INT NOT NULL,
|
| + admin_id INT UNSIGNED NOT NULL,
|
| +
|
| + PRIMARY KEY (field_id, admin_id),
|
| + FOREIGN KEY (field_id) REFERENCES FieldDef(id),
|
| + FOREIGN KEY (admin_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Issue (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + shard SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + local_id INT NOT NULL,
|
| +
|
| + reporter_id INT UNSIGNED NOT NULL,
|
| + owner_id INT UNSIGNED,
|
| + status_id INT,
|
| +
|
| + -- These are each timestamps in seconds since the epoch.
|
| + modified INT NOT NULL,
|
| + opened INT,
|
| + closed INT,
|
| +
|
| + derived_owner_id INT UNSIGNED,
|
| + derived_status_id INT,
|
| +
|
| + deleted BOOLEAN,
|
| +
|
| + -- These are denormalized fields that should be updated when child
|
| + -- records are added or removed for stars or attachments. If they
|
| + -- get out of sync, they can be updated via an UPDATE ... SELECT statement.
|
| + star_count INT DEFAULT 0,
|
| + attachment_count INT DEFAULT 0,
|
| +
|
| + is_spam BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY(id),
|
| + UNIQUE KEY (project_id, local_id),
|
| + INDEX (shard, status_id),
|
| + INDEX (shard, project_id),
|
| +
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id),
|
| + FOREIGN KEY (reporter_id) REFERENCES User(user_id),
|
| + FOREIGN KEY (owner_id) REFERENCES User(user_id),
|
| + FOREIGN KEY (status_id) REFERENCES StatusDef(id),
|
| + FOREIGN KEY (derived_owner_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- This is a parallel table to the Issue table because we don't want
|
| +-- any very wide columns in the Issue table that would slow it down.
|
| +CREATE TABLE IssueSummary (
|
| + issue_id INT NOT NULL,
|
| + summary TEXT,
|
| +
|
| + PRIMARY KEY (issue_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Issue2Component (
|
| + issue_id INT NOT NULL,
|
| + issue_shard SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
|
| + component_id INT NOT NULL,
|
| + derived BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (issue_id, component_id, derived),
|
| + INDEX (component_id, issue_shard),
|
| +
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (component_id) REFERENCES ComponentDef(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Issue2Label (
|
| + issue_id INT NOT NULL,
|
| + issue_shard SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
|
| + label_id INT NOT NULL,
|
| + derived BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (issue_id, label_id, derived),
|
| + INDEX (label_id, issue_shard),
|
| +
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (label_id) REFERENCES LabelDef(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Issue2FieldValue (
|
| + issue_id INT NOT NULL,
|
| + issue_shard SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
|
| + field_id INT NOT NULL,
|
| +
|
| + int_value INT,
|
| + str_value VARCHAR(1024),
|
| + user_id INT UNSIGNED,
|
| +
|
| + derived BOOLEAN DEFAULT FALSE,
|
| +
|
| + INDEX (issue_id, field_id),
|
| + INDEX (field_id, issue_shard, int_value),
|
| + INDEX (field_id, issue_shard, str_value(255)),
|
| + INDEX (field_id, issue_shard, user_id),
|
| +
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (field_id) REFERENCES FieldDef(id),
|
| + FOREIGN KEY (user_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Issue2Cc (
|
| + issue_id INT NOT NULL,
|
| + issue_shard SMALLINT UNSIGNED DEFAULT 0 NOT NULL,
|
| + cc_id INT UNSIGNED NOT NULL,
|
| + derived BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (issue_id, cc_id),
|
| + INDEX (cc_id, issue_shard),
|
| +
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (cc_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Issue2Notify (
|
| + issue_id INT NOT NULL,
|
| + email VARCHAR(80) NOT NULL,
|
| +
|
| + PRIMARY KEY (issue_id, email),
|
| +
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE IssueStar (
|
| + issue_id INT NOT NULL,
|
| + user_id INT UNSIGNED NOT NULL,
|
| +
|
| + PRIMARY KEY (issue_id, user_id),
|
| + INDEX (user_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (user_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE IssueRelation (
|
| + issue_id INT NOT NULL,
|
| + dst_issue_id INT NOT NULL,
|
| +
|
| + -- Read as: src issue is blocked on dst issue.
|
| + kind ENUM ('blockedon', 'mergedinto') NOT NULL,
|
| +
|
| + PRIMARY KEY (issue_id, dst_issue_id, kind),
|
| + INDEX (issue_id),
|
| + INDEX (dst_issue_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (dst_issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE DanglingIssueRelation (
|
| + issue_id INT NOT NULL,
|
| + dst_issue_project VARCHAR(80),
|
| + dst_issue_local_id INT,
|
| +
|
| + -- This table uses 'blocking' so that it can guarantee the src issue
|
| + -- always exists, while the dst issue is always the dangling one.
|
| + kind ENUM ('blockedon', 'blocking', 'mergedinto') NOT NULL,
|
| +
|
| + PRIMARY KEY (issue_id, dst_issue_project, dst_issue_local_id, kind),
|
| + INDEX (issue_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Comment (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + issue_id INT NOT NULL,
|
| + created INT NOT NULL,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| +
|
| + commenter_id INT UNSIGNED NOT NULL,
|
| + content TEXT,
|
| + inbound_message TEXT,
|
| +
|
| + was_escaped BOOLEAN DEFAULT FALSE,
|
| + deleted_by INT UNSIGNED,
|
| + is_spam BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY(id),
|
| + INDEX (is_spam, project_id, created),
|
| + INDEX (commenter_id, created),
|
| +
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (commenter_id) REFERENCES User(user_id),
|
| + FOREIGN KEY (deleted_by) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Attachment (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| +
|
| + issue_id INT NOT NULL,
|
| + comment_id INT,
|
| +
|
| + filename VARCHAR(255) NOT NULL,
|
| + filesize INT NOT NULL,
|
| + mimetype VARCHAR(255) NOT NULL,
|
| + deleted BOOLEAN,
|
| + gcs_object_id VARCHAR(1024) NOT NULL,
|
| +
|
| + PRIMARY KEY (id),
|
| + INDEX (issue_id),
|
| + INDEX (comment_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE IssueUpdate (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + issue_id INT NOT NULL,
|
| + comment_id INT,
|
| +
|
| + field ENUM (
|
| + 'summary', 'status', 'owner', 'cc', 'labels', 'blockedon', 'blocking', 'mergedinto',
|
| + 'project', 'components', 'custom', 'is_spam' ) NOT NULL,
|
| + old_value TEXT,
|
| + new_value TEXT,
|
| + added_user_id INT UNSIGNED,
|
| + removed_user_id INT UNSIGNED,
|
| + custom_field_name VARCHAR(255),
|
| + is_spam BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (id),
|
| + INDEX (issue_id),
|
| + INDEX (comment_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| + -- FOREIGN KEY (added_user_id) REFERENCES User(user_id),
|
| + -- FOREIGN KEY (removed_user_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE IssueFormerLocations (
|
| + issue_id INT NOT NULL,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + local_id INT NOT NULL,
|
| +
|
| + INDEX (issue_id),
|
| + UNIQUE KEY (project_id, local_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Template (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + name VARCHAR(255) BINARY NOT NULL,
|
| +
|
| + content TEXT,
|
| + summary TEXT,
|
| + summary_must_be_edited BOOLEAN,
|
| + owner_id INT UNSIGNED,
|
| + status VARCHAR(255),
|
| + members_only BOOLEAN,
|
| + owner_defaults_to_member BOOLEAN,
|
| + component_required BOOLEAN DEFAULT FALSE,
|
| +
|
| + PRIMARY KEY (id),
|
| + UNIQUE KEY (project_id, name),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Template2Label (
|
| + template_id INT NOT NULL,
|
| + label VARCHAR(255) NOT NULL,
|
| +
|
| + PRIMARY KEY (template_id, label),
|
| + FOREIGN KEY (template_id) REFERENCES Template(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Template2Admin (
|
| + template_id INT NOT NULL,
|
| + admin_id INT UNSIGNED NOT NULL,
|
| +
|
| + PRIMARY KEY (template_id, admin_id),
|
| + FOREIGN KEY (template_id) REFERENCES Template(id),
|
| + FOREIGN KEY (admin_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Template2FieldValue (
|
| + template_id INT NOT NULL,
|
| + field_id INT NOT NULL,
|
| +
|
| + int_value INT,
|
| + str_value VARCHAR(1024),
|
| + user_id INT UNSIGNED,
|
| +
|
| + INDEX (template_id, field_id),
|
| +
|
| + FOREIGN KEY (template_id) REFERENCES Template(id),
|
| + FOREIGN KEY (field_id) REFERENCES FieldDef(id),
|
| + FOREIGN KEY (user_id) REFERENCES User(user_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE Template2Component (
|
| + template_id INT NOT NULL,
|
| + component_id INT NOT NULL,
|
| +
|
| + PRIMARY KEY (template_id, component_id),
|
| +
|
| + FOREIGN KEY (template_id) REFERENCES Template(id),
|
| + FOREIGN KEY (component_id) REFERENCES ComponentDef(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE ProjectIssueConfig (
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| +
|
| + statuses_offer_merge VARCHAR(255) NOT NULL,
|
| + exclusive_label_prefixes VARCHAR(255) NOT NULL,
|
| + default_template_for_developers INT NOT NULL,
|
| + default_template_for_users INT NOT NULL,
|
| +
|
| + default_col_spec TEXT,
|
| + default_sort_spec TEXT,
|
| + default_x_attr TEXT,
|
| + default_y_attr TEXT,
|
| +
|
| + custom_issue_entry_url TEXT,
|
| +
|
| + PRIMARY KEY (project_id),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +CREATE TABLE FilterRule (
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + rank SMALLINT UNSIGNED,
|
| +
|
| + -- TODO: or should this be broken down into structured fields?
|
| + predicate TEXT NOT NULL,
|
| + -- TODO: or should this be broken down into structured fields?
|
| + consequence TEXT NOT NULL,
|
| +
|
| + INDEX (project_id),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- Each row in this table indicates an issue that needs to be reindexed
|
| +-- in the GAE fulltext index by our batch indexing cron job.
|
| +CREATE TABLE ReindexQueue (
|
| + issue_id INT NOT NULL,
|
| + created TIMESTAMP,
|
| +
|
| + PRIMARY KEY (issue_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- This holds counters with the highest issue local_id that is
|
| +-- already used in each project. Clients should atomically increment
|
| +-- the value for current project and then use the new counter value
|
| +-- when creating an issue.
|
| +CREATE TABLE LocalIDCounter (
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + used_local_id INT NOT NULL,
|
| + used_spam_id INT NOT NULL,
|
| +
|
| + PRIMARY KEY (project_id),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- This is a saved query. It can be configured by a project owner to
|
| +-- be used by all visitors to that project. Or, it can be a a
|
| +-- personal saved query that appears on a user's "Saved queries" page
|
| +-- and executes in the scope of one or more projects.
|
| +CREATE TABLE SavedQuery (
|
| + id INT NOT NULL AUTO_INCREMENT,
|
| + name VARCHAR(80) NOT NULL,
|
| +
|
| + -- For now, we only allow saved queries to be based off ane of the built-in
|
| + -- query scopes, and those can never be deleted, so there can be no nesting,
|
| + -- dangling references, and thus no need for cascading deletes.
|
| + base_query_id INT,
|
| + query TEXT NOT NULL,
|
| +
|
| + PRIMARY KEY (id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- Rows for built-in queries. These are in the database soley so that
|
| +-- foreign key constraints are satisfied. These rows ar never read or updated.
|
| +INSERT IGNORE INTO SavedQuery VALUES
|
| + (1, 'All issues', 0, ''),
|
| + (2, 'Open issues', 0, 'is:open'),
|
| + (3, 'Open and owned by me', 0, 'is:open owner:me'),
|
| + (4, 'Open and reported by me', 0, 'is:open reporter:me'),
|
| + (5, 'Open and starred by me', 0, 'is:open is:starred'),
|
| + (6, 'New issues', 0, 'status:new'),
|
| + (7, 'Issues to verify', 0, 'status=fixed,done'),
|
| + (8, 'Open with comment by me', 0, 'is:open commentby:me');
|
| +
|
| +-- The sole purpose of this statement is to force user defined saved queries
|
| +-- to have IDs greater than 100 so that 1-100 are reserved for built-ins.
|
| +INSERT IGNORE INTO SavedQuery VALUES (100, '', 0, '');
|
| +
|
| +
|
| +-- User personal queries default to executing in the context of the
|
| +-- project where they were created, but the user can edit them to make
|
| +-- them into cross-project queries. Project saved queries always
|
| +-- implicitly execute in the context of a project.
|
| +CREATE TABLE SavedQueryExecutesInProject (
|
| + query_id INT NOT NULL,
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| +
|
| + PRIMARY KEY (query_id, project_id),
|
| + INDEX (project_id),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id),
|
| + FOREIGN KEY (query_id) REFERENCES SavedQuery(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- These are the queries edited by the project owner on the project
|
| +-- admin pages.
|
| +CREATE TABLE Project2SavedQuery (
|
| + project_id SMALLINT UNSIGNED NOT NULL,
|
| + rank SMALLINT UNSIGNED NOT NULL,
|
| + query_id INT NOT NULL,
|
| +
|
| + -- TODO(jrobbins): visibility: owners, committers, contributors, anyone
|
| +
|
| + PRIMARY KEY (project_id, rank),
|
| + FOREIGN KEY (project_id) REFERENCES Project(project_id),
|
| + FOREIGN KEY (query_id) REFERENCES SavedQuery(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- These are personal saved queries.
|
| +CREATE TABLE User2SavedQuery (
|
| + user_id INT UNSIGNED NOT NULL,
|
| + rank SMALLINT UNSIGNED NOT NULL,
|
| + query_id INT NOT NULL,
|
| +
|
| + -- TODO(jrobbins): daily and weekly digests, and the ability to have
|
| + -- certain subscriptions go to username+SOMETHING@example.com.
|
| + subscription_mode ENUM ('noemail', 'immediate') DEFAULT 'noemail' NOT NULL,
|
| +
|
| + PRIMARY KEY (user_id, rank),
|
| + FOREIGN KEY (user_id) REFERENCES User(user_id),
|
| + FOREIGN KEY (query_id) REFERENCES SavedQuery(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- Created whenever a user reports an issue or comment as spam.
|
| +-- Note this is distinct from a SpamVerdict, which is issued by
|
| +-- the system rather than a human user.
|
| +CREATE TABLE SpamReport (
|
| + -- when this report was generated
|
| + created TIMESTAMP NOT NULL,
|
| + -- when the reported content was generated
|
| + -- TODO(jrobbins): needs default current_time in MySQL 5.7.
|
| + content_created TIMESTAMP NOT NULL,
|
| + -- id of the reporting user
|
| + user_id INT UNSIGNED NOT NULL,
|
| + -- id of the reported user
|
| + reported_user_id INT UNSIGNED NOT NULL,
|
| + -- either this or issue_id must be set
|
| + comment_id INT,
|
| + -- either this or comment_id must be set
|
| + issue_id INT,
|
| +
|
| + INDEX (issue_id),
|
| + INDEX (comment_id),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (comment_id) REFERENCES Comment(id)
|
| +) ENGINE=INNODB;
|
| +
|
| +
|
| +-- Any time a human or the system sets is_spam to true,
|
| +-- or changes it from true to false, we want to have a
|
| +-- record of who did it and why.
|
| +CREATE TABLE SpamVerdict (
|
| + -- when this verdict was generated
|
| + created TIMESTAMP NOT NULL,
|
| +
|
| + -- id of the reporting user, may be null if it was
|
| + -- an automatic classification.
|
| + user_id INT UNSIGNED,
|
| +
|
| + -- id of the containing project.
|
| + project_id INT NOT NULL,
|
| +
|
| + -- either this or issue_id must be set.
|
| + comment_id INT,
|
| +
|
| + -- either this or comment_id must be set.
|
| + issue_id INT,
|
| +
|
| + -- If the classifier issued the verdict, this should be set.
|
| + classifier_confidence FLOAT,
|
| +
|
| + -- This should reflect the new is_spam value that was applied
|
| + -- by this verdict, not the value it had prior.
|
| + is_spam BOOLEAN NOT NULL,
|
| +
|
| + -- owner: a project owner marked it as spam
|
| + -- threshhold: number of SpamReports from non-members was exceeded.
|
| + -- classifier: the automatic classifier reports it as spam.
|
| + reason ENUM ("manual", "threshold", "classifier") NOT NULL,
|
| +
|
| + overruled BOOL NOT NULL,
|
| +
|
| + INDEX (issue_id),
|
| + INDEX (comment_id),
|
| + INDEX (classifier_confidence),
|
| + FOREIGN KEY (issue_id) REFERENCES Issue(id),
|
| + FOREIGN KEY (comment_id) REFERENCES Comment(id)
|
| +
|
| +) ENGINE=INNODB;
|
|
|