From 65ddefad8b9c691a25802b1db72f5ba5c97ab0e9 Mon Sep 17 00:00:00 2001 From: epriestley Date: Sat, 5 Oct 2013 13:48:45 -0700 Subject: [PATCH] Migrate all Differential reviewer data to edges Summary: Ref T1279. @champo did a lot of this work already; we've been doing double writes for a long time. Add "double reads" (reading the edge table as both the "relationship" table and as the "reviewer status" table), and migrate all the data. I'm not bothering to try to recover old reviewer status (e.g., we could infer from transactions who accepted old revisions) because it wold be very complicated and doesn't seem too valuable. Test Plan: - Without doing the migration, used Differential. Verified that reads and writes worked. Most of the data was there anyway since we've been double-writing. - Performed the migration. Verified that everything was still unchanged. - Dropped the edge table, verified all reviweer data vanished. - Migrated again, verified the reviewer stuff was restored. - Did various cc/reviewer/subscriber queries, got consistent results. Reviewers: btrahan Reviewed By: btrahan CC: champo, aran Maniphest Tasks: T1279 Differential Revision: https://secure.phabricator.com/D7227 --- .../sql/patches/20131004.dxreviewers.php | 46 +++++++++++++ src/__phutil_library_map__.php | 6 +- .../query/DifferentialRevisionQuery.php | 66 +++++++++++++------ .../storage/DifferentialRevision.php | 21 +++++- 4 files changed, 117 insertions(+), 22 deletions(-) create mode 100644 resources/sql/patches/20131004.dxreviewers.php diff --git a/resources/sql/patches/20131004.dxreviewers.php b/resources/sql/patches/20131004.dxreviewers.php new file mode 100644 index 0000000000..efe9daf5ab --- /dev/null +++ b/resources/sql/patches/20131004.dxreviewers.php @@ -0,0 +1,46 @@ +establishConnection('w'); + +// NOTE: We migrate by revision because the relationship table doesn't have +// an "id" column. + +foreach (new LiskMigrationIterator($table) as $revision) { + $revision_id = $revision->getID(); + $revision_phid = $revision->getPHID(); + + echo "Migrating reviewers for D{$revision_id}...\n"; + + $reviewer_phids = queryfx_all( + $conn_w, + 'SELECT objectPHID FROM %T WHERE revisionID = %d + AND relation = %s ORDER BY sequence', + 'differential_relationship', + $revision_id, + 'revw'); + $reviewer_phids = ipull($reviewer_phids, 'objectPHID'); + + if (!$reviewer_phids) { + continue; + } + + $editor = id(new PhabricatorEdgeEditor()) + ->setActor(PhabricatorUser::getOmnipotentUser()); + + foreach ($reviewer_phids as $dst) { + $editor->addEdge( + $revision_phid, + PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, + $dst, + array( + 'data' => array( + 'status' => DifferentialReviewerStatus::STATUS_ADDED, + ), + )); + } + + $editor->save(); +} + +echo "Done.\n"; diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php index 047d315afa..c14913bc7a 100644 --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -2751,7 +2751,11 @@ phutil_register_library_map(array( 'HeraldRuleTransactionComment' => 'PhabricatorApplicationTransactionComment', 'HeraldRuleViewController' => 'HeraldController', 'HeraldTestConsoleController' => 'HeraldController', - 'HeraldTranscript' => 'HeraldDAO', + 'HeraldTranscript' => + array( + 0 => 'HeraldDAO', + 1 => 'PhabricatorPolicyInterface', + ), 'HeraldTranscriptController' => 'HeraldController', 'HeraldTranscriptListController' => 'HeraldController', 'HeraldTranscriptQuery' => 'PhabricatorCursorPagedPolicyAwareQuery', diff --git a/src/applications/differential/query/DifferentialRevisionQuery.php b/src/applications/differential/query/DifferentialRevisionQuery.php index fb36174a47..3326c961ce 100644 --- a/src/applications/differential/query/DifferentialRevisionQuery.php +++ b/src/applications/differential/query/DifferentialRevisionQuery.php @@ -599,25 +599,32 @@ final class DifferentialRevisionQuery if ($this->reviewers) { $joins[] = qsprintf( $conn_r, - 'JOIN %T reviewer_rel ON reviewer_rel.revisionID = r.id '. - 'AND reviewer_rel.relation = %s '. - 'AND reviewer_rel.objectPHID in (%Ls)', - DifferentialRevision::RELATIONSHIP_TABLE, - DifferentialRevision::RELATION_REVIEWER, + 'JOIN %T e_reviewers ON e_reviewers.src = r.phid '. + 'AND e_reviewers.type = %s '. + 'AND e_reviewers.dst in (%Ls)', + PhabricatorEdgeConfig::TABLE_NAME_EDGE, + PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, $this->reviewers); } if ($this->subscribers) { + // TODO: These can be expressed as a JOIN again (and the corresponding + // WHERE clause removed) once subscribers move to edges. $joins[] = qsprintf( $conn_r, - 'JOIN %T sub_rel ON sub_rel.revisionID = r.id '. - 'AND sub_rel.relation IN (%Ls) '. - 'AND sub_rel.objectPHID in (%Ls)', + 'LEFT JOIN %T sub_rel_cc ON sub_rel_cc.revisionID = r.id '. + 'AND sub_rel_cc.relation = %s '. + 'AND sub_rel_cc.objectPHID in (%Ls)', DifferentialRevision::RELATIONSHIP_TABLE, - array( - DifferentialRevision::RELATION_SUBSCRIBED, - DifferentialRevision::RELATION_REVIEWER, - ), + DifferentialRevision::RELATION_SUBSCRIBED, + $this->subscribers); + $joins[] = qsprintf( + $conn_r, + 'LEFT JOIN %T sub_rel_reviewer ON sub_rel_reviewer.src = r.phid '. + 'AND sub_rel_reviewer.type = %s '. + 'AND sub_rel_reviewer.dst in (%Ls)', + PhabricatorEdgeConfig::TABLE_NAME_EDGE, + PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER, $this->subscribers); } @@ -710,6 +717,13 @@ final class DifferentialRevisionQuery $this->arcanistProjectPHIDs); } + if ($this->subscribers) { + $where[] = qsprintf( + $conn_r, + '(sub_rel_cc.objectPHID IS NOT NULL) + OR (sub_rel_reviewer.dst IS NOT NULL)'); + } + switch ($this->status) { case self::STATUS_ANY: break; @@ -889,16 +903,30 @@ final class DifferentialRevisionQuery assert_instances_of($revisions, 'DifferentialRevision'); $relationships = queryfx_all( $conn_r, - 'SELECT * FROM %T WHERE revisionID in (%Ld) ORDER BY sequence', + 'SELECT * FROM %T WHERE revisionID in (%Ld) + AND relation != %s ORDER BY sequence', DifferentialRevision::RELATIONSHIP_TABLE, - mpull($revisions, 'getID')); + mpull($revisions, 'getID'), + DifferentialRevision::RELATION_REVIEWER); $relationships = igroup($relationships, 'revisionID'); + + $type_reviewer = PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER; + $edges = id(new PhabricatorEdgeQuery()) + ->withSourcePHIDs(mpull($revisions, 'getPHID')) + ->withEdgeTypes(array($type_reviewer)) + ->execute(); + foreach ($revisions as $revision) { - $revision->attachRelationships( - idx( - $relationships, - $revision->getID(), - array())); + $data = idx($relationships, $revision->getID(), array()); + $revision_edges = $edges[$revision->getPHID()][$type_reviewer]; + foreach ($revision_edges as $dst_phid => $edge_data) { + $data[] = array( + 'relation' => DifferentialRevision::RELATION_REVIEWER, + 'objectPHID' => $dst_phid, + ); + } + + $revision->attachRelationships($data); } } diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php index 2533a3789c..b899848992 100644 --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -223,11 +223,28 @@ final class DifferentialRevision extends DifferentialDAO return; } + // Read "subscribed" and "unsubscribed" data out of the old relationship + // table. $data = queryfx_all( $this->establishConnection('r'), - 'SELECT * FROM %T WHERE revisionID = %d ORDER BY sequence', + 'SELECT * FROM %T WHERE revisionID = %d + AND relation != %s ORDER BY sequence', self::RELATIONSHIP_TABLE, - $this->getID()); + $this->getID(), + self::RELATION_REVIEWER); + + // Read "reviewer" data out of the new table. + $reviewer_phids = PhabricatorEdgeQuery::loadDestinationPHIDs( + $this->getPHID(), + PhabricatorEdgeConfig::TYPE_DREV_HAS_REVIEWER); + + foreach ($reviewer_phids as $phid) { + $data[] = array( + 'relation' => self::RELATION_REVIEWER, + 'objectPHID' => $phid, + ); + } + return $this->attachRelationships($data); }