jenkins-bot has submitted this change and it was merged.
Change subject: Add artificial primary key to flow_wiki_ref and flow_ext_ref
......................................................................
Add artificial primary key to flow_wiki_ref and flow_ext_ref
The newly added ref_id is not used in the code, it's
only meant to make DB maintenance easier.
There shouldn't be any conflicts with old/new records being
confused with each other since the code is mostly unaware
of this ID: it still uses all the other columns as "fake"
PK (to compare records when figuring out if references are
new)
Deployment plan:
* Run db-patches/patch-ref_id-phase1.sql (prepare schema)
* Merge & deploy this code (start writing to ref_id)
* Run maintenance/FlowPopulateRefId.php (migrate existing ref_id)
* Run db-patches/patch-ref_id-phase2.sql (make not null & PK)
Bug: T109676
Change-Id: Icd1673ed642efc838809ae249f9544a364962886
---
M Hooks.php
A db_patches/patch-ref_id-phase1.sql
A db_patches/patch-ref_id-phase2.sql
A db_patches/patch-ref_id-phase2.sqlite.sql
M flow.sql
M includes/Model/Reference.php
M includes/Model/URLReference.php
M includes/Model/WikiReference.php
M includes/Parsoid/ReferenceFactory.php
A maintenance/FlowPopulateRefId.php
10 files changed, 198 insertions(+), 16 deletions(-)
Approvals:
Jcrespo: Looks good to me, but someone else must approve
Mattflaschen: Looks good to me, approved
jenkins-bot: Verified
diff --git a/Hooks.php b/Hooks.php
index c3249b1..f94bc0b 100644
--- a/Hooks.php
+++ b/Hooks.php
@@ -230,6 +230,7 @@
$updater->dropExtensionIndex( 'flow_ext_ref',
'flow_ext_ref_pk', "$dir/db_patches/patch-remove_unique_ref_indices.sql" );
$updater->addExtensionIndex( 'flow_workflow',
'flow_workflow_update_timestamp',
"$dir/db_patches/patch-flow_workflow_update_timestamp_idx.sql" );
$updater->addExtensionField( 'flow_wiki_ref', 'ref_src_wiki',
"$dir/db_patches/patch-reference_wiki.sql" );
+ $updater->addExtensionField( 'flow_wiki_ref', 'ref_id',
"$dir/db_patches/patch-ref_id-phase1.sql" );
require_once __DIR__.'/maintenance/FlowUpdateRecentChanges.php';
$updater->addPostDatabaseUpdateMaintenance(
'FlowUpdateRecentChanges' );
@@ -272,6 +273,21 @@
require_once
__DIR__.'/maintenance/FlowUpdateBetaFeaturePreference.php';
$updater->addPostDatabaseUpdateMaintenance(
'FlowUpdateBetaFeaturePreference' );
+ require_once __DIR__.'/maintenance/FlowPopulateRefId.php';
+ $updater->addPostDatabaseUpdateMaintenance( 'FlowPopulateRefId'
);
+
+ /*
+ * Add primary key, but only after we've made sure the newly
added
+ * column has been populated (otherwise they'd all be null
values)
+ */
+ if ( $updater->updateRowExists( 'FlowPopulateRefId' ) ) {
+ if ( $updater->getDB()->getType() === 'sqlite' ) {
+ $updater->addExtensionIndex( 'flow_wiki_ref',
'PRIMARY', "$dir/db_patches/patch-ref_id-phase2.sqlite.sql" );
+ } else {
+ $updater->addExtensionIndex( 'flow_wiki_ref',
'PRIMARY', "$dir/db_patches/patch-ref_id-phase2.sql" );
+ }
+ }
+
return true;
}
diff --git a/db_patches/patch-ref_id-phase1.sql
b/db_patches/patch-ref_id-phase1.sql
new file mode 100644
index 0000000..4ab5393
--- /dev/null
+++ b/db_patches/patch-ref_id-phase1.sql
@@ -0,0 +1,2 @@
+ALTER TABLE /*_*/flow_wiki_ref ADD COLUMN ref_id binary(11) null;
+ALTER TABLE /*_*/flow_ext_ref ADD COLUMN ref_id binary(11) null;
diff --git a/db_patches/patch-ref_id-phase2.sql
b/db_patches/patch-ref_id-phase2.sql
new file mode 100644
index 0000000..6ae67e5
--- /dev/null
+++ b/db_patches/patch-ref_id-phase2.sql
@@ -0,0 +1,5 @@
+ALTER TABLE /*_*/flow_wiki_ref CHANGE ref_id ref_id BINARY(11) NOT NULL;
+ALTER TABLE /*_*/flow_ext_ref CHANGE ref_id ref_id BINARY(11) NOT NULL;
+
+ALTER TABLE /*_*/flow_wiki_ref ADD PRIMARY KEY (ref_id);
+ALTER TABLE /*_*/flow_ext_ref ADD PRIMARY KEY (ref_id);
diff --git a/db_patches/patch-ref_id-phase2.sqlite.sql
b/db_patches/patch-ref_id-phase2.sqlite.sql
new file mode 100644
index 0000000..cbfebc6
--- /dev/null
+++ b/db_patches/patch-ref_id-phase2.sqlite.sql
@@ -0,0 +1,65 @@
+-- SQLite won't allow us to just alter the columns, so we'll move this table
+-- out of the way, create it anew the way we want it, and then copy the
+-- data over before dropping the old table
+ALTER TABLE /*_*/flow_wiki_ref RENAME TO /*_*/temp_flow_wiki_ref;
+ALTER TABLE /*_*/flow_ext_ref RENAME TO /*_*/temp_flow_ext_ref;
+
+
+CREATE TABLE /*_*/flow_wiki_ref (
+ ref_id binary(11) not null,
+ ref_src_wiki varchar(16) binary not null,
+ ref_src_object_id binary(11) not null,
+ ref_src_object_type varbinary(32) not null,
+ ref_src_workflow_id binary(11) not null,
+ ref_src_namespace int not null,
+ ref_src_title varbinary(255) not null,
+ ref_target_namespace int not null,
+ ref_target_title varbinary(255) not null,
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
+) /*$wgDBTableOptions*/;
+
+CREATE INDEX /*i*/flow_wiki_ref_idx_v2 ON /*_*/flow_wiki_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_type,
ref_target_namespace, ref_target_title, ref_src_object_type, ref_src_object_id);
+
+CREATE INDEX /*i*/flow_wiki_ref_revision_v2 ON /*_*/flow_wiki_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_src_object_type,
ref_src_object_id, ref_type, ref_target_namespace, ref_target_title);
+
+CREATE TABLE /*_*/flow_ext_ref (
+ ref_id binary(11) not null,
+ ref_src_wiki varchar(16) binary not null,
+ ref_src_object_id binary(11) not null,
+ ref_src_object_type varbinary(32) not null,
+ ref_src_workflow_id binary(11) not null,
+ ref_src_namespace int not null,
+ ref_src_title varbinary(255) not null,
+ ref_target blob not null,
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
+) /*$wgDBTableOptions*/;
+
+CREATE INDEX /*i*/flow_ext_ref_idx_v2 ON /*_*/flow_ext_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_type,
ref_target(255), ref_src_object_type, ref_src_object_id);
+
+CREATE INDEX /*i*/flow_ext_ref_revision_v2 ON /*_*/flow_ext_ref
+ (ref_src_wiki, ref_src_namespace, ref_src_title, ref_src_object_type,
ref_src_object_id, ref_type, ref_target(255));
+
+
+INSERT INTO /*_*/flow_wiki_ref
+ (ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type,
ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target_namespace,
ref_target_title, ref_type)
+SELECT
+ ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type,
ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target_namespace,
ref_target_title, ref_type
+FROM
+ /*_*/temp_flow_wiki_ref;
+
+INSERT INTO /*_*/flow_ext_ref
+ (ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type,
ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target, ref_type)
+SELECT
+ ref_id, ref_src_wiki, ref_src_object_id, ref_src_object_type,
ref_src_workflow_id, ref_src_namespace, ref_src_title, ref_target, ref_type
+FROM
+ /*_*/temp_flow_ext_ref;
+
+DROP TABLE /*_*/temp_flow_wiki_ref;
+DROP TABLE /*_*/temp_flow_ext_ref;
diff --git a/flow.sql b/flow.sql
index cb48050..f6365b1 100644
--- a/flow.sql
+++ b/flow.sql
@@ -139,6 +139,7 @@
CREATE UNIQUE INDEX /*i*/flow_tree_constraint ON /*_*/flow_tree_node
(tree_descendant_id, tree_depth);
CREATE TABLE /*_*/flow_wiki_ref (
+ ref_id binary(11) not null,
ref_src_wiki varchar(16) binary not null,
ref_src_object_id binary(11) not null,
ref_src_object_type varbinary(32) not null,
@@ -147,7 +148,9 @@
ref_src_title varbinary(255) not null,
ref_target_namespace int not null,
ref_target_title varbinary(255) not null,
- ref_type varbinary(16) not null
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/flow_wiki_ref_idx_v2 ON /*_*/flow_wiki_ref
@@ -157,6 +160,7 @@
(ref_src_wiki, ref_src_namespace, ref_src_title, ref_src_object_type,
ref_src_object_id, ref_type, ref_target_namespace, ref_target_title);
CREATE TABLE /*_*/flow_ext_ref (
+ ref_id binary(11) not null,
ref_src_wiki varchar(16) binary not null,
ref_src_object_id binary(11) not null,
ref_src_object_type varbinary(32) not null,
@@ -164,7 +168,9 @@
ref_src_namespace int not null,
ref_src_title varbinary(255) not null,
ref_target blob not null,
- ref_type varbinary(16) not null
+ ref_type varbinary(16) not null,
+
+ PRIMARY KEY (ref_id)
) /*$wgDBTableOptions*/;
CREATE INDEX /*i*/flow_ext_ref_idx_v2 ON /*_*/flow_ext_ref
diff --git a/includes/Model/Reference.php b/includes/Model/Reference.php
index 8853954..fa52657 100644
--- a/includes/Model/Reference.php
+++ b/includes/Model/Reference.php
@@ -11,6 +11,11 @@
/**
* @var UUID
*/
+ protected $id;
+
+ /**
+ * @var UUID
+ */
protected $workflowId;
/**
@@ -43,15 +48,17 @@
/**
* Standard constructor. Called from subclasses only
*
- * @param String $wiki Wiki ID of the reference source
+ * @param UUID $id Id of the reference
+ * @param string $wiki Wiki ID of the reference source
* @param UUID $srcWorkflow Source Workflow's ID
* @param Title $srcTitle Title of the Workflow from which this
reference comes.
- * @param String $objectType Output of getRevisionType for the
AbstractRevision that this reference comes from.
+ * @param string $objectType Output of getRevisionType for the
AbstractRevision that this reference comes from.
* @param UUID $objectId Unique identifier for the revisioned
object containing the reference.
* @param string $type The type of reference
* @throws InvalidReferenceException
*/
- protected function __construct( $wiki, UUID $srcWorkflow, Title
$srcTitle, $objectType, UUID $objectId, $type ) {
+ protected function __construct( UUID $id, $wiki, UUID $srcWorkflow,
Title $srcTitle, $objectType, UUID $objectId, $type ) {
+ $this->id = $id;
$this->wikiId = $wiki;
$this->workflowId = $srcWorkflow;
$this->objectType = $objectType;
@@ -125,6 +132,7 @@
*/
public function getStorageRow() {
return array(
+ 'ref_id' => $this->id->getAlphadecimal(),
'ref_src_wiki' => $this->wikiId,
'ref_src_workflow_id' =>
$this->workflowId->getAlphadecimal(),
'ref_src_namespace' => $this->srcTitle->getNamespace(),
diff --git a/includes/Model/URLReference.php b/includes/Model/URLReference.php
index 9111d3f..de4c13f 100644
--- a/includes/Model/URLReference.php
+++ b/includes/Model/URLReference.php
@@ -9,16 +9,17 @@
protected $url;
/**
- * @param String $wiki Wiki ID of the reference source
+ * @param UUID $id Id of the reference
+ * @param string $wiki Wiki ID of the reference source
* @param UUID $srcWorkflow ID of the source Workflow
* @param Title $srcTitle Title of the page that the Workflow
exists on
- * @param String $objectType Output of getRevisionType for the
AbstractRevision that this reference comes from.
+ * @param string $objectType Output of getRevisionType for the
AbstractRevision that this reference comes from.
* @param UUID $objectId Unique identifier for the revisioned
object containing the reference.
* @param string $type Type of reference
* @param string $url URL of the reference's target.
* @throws InvalidReferenceException
*/
- public function __construct( $wiki, UUID $srcWorkflow, Title $srcTitle,
$objectType, UUID $objectId, $type, $url ) {
+ public function __construct( UUID $id, $wiki, UUID $srcWorkflow, Title
$srcTitle, $objectType, UUID $objectId, $type, $url ) {
$this->url = $url;
if ( !is_array( wfParseUrl( $url ) ) ) {
@@ -27,7 +28,7 @@
);
}
- parent::__construct( $wiki, $srcWorkflow, $srcTitle,
$objectType, $objectId, $type );
+ parent::__construct( $id, $wiki, $srcWorkflow, $srcTitle,
$objectType, $objectId, $type );
}
/**
@@ -44,10 +45,13 @@
/**
* Instantiates a URLReference object from a storage row.
*
- * @param \StdClass $row
+ * @param array $row
* @return URLReference
*/
public static function fromStorageRow( $row ) {
+ // TODO: Remove this UUID::create() call when the field is
populated
+ // everywhere relevant.
+ $id = $row['ref_id'] === null ? UUID::create() : UUID::create(
$row['ref_id'] );
$workflow = UUID::create( $row['ref_src_workflow_id'] );
$objectType = $row['ref_src_object_type'];
$objectId = UUID::create( $row['ref_src_object_id'] );
@@ -56,7 +60,7 @@
$srcTitle = Title::makeTitle( $row['ref_src_namespace'],
$row['ref_src_title'] );
$wiki = $row['ref_src_wiki'];
- return new URLReference( $wiki, $workflow, $srcTitle,
$objectType, $objectId, $type, $url );
+ return new URLReference( $id, $wiki, $workflow, $srcTitle,
$objectType, $objectId, $type, $url );
}
/**
diff --git a/includes/Model/WikiReference.php b/includes/Model/WikiReference.php
index d36e2d0..086c31f 100644
--- a/includes/Model/WikiReference.php
+++ b/includes/Model/WikiReference.php
@@ -13,7 +13,8 @@
protected $target;
/**
- * @param String $wiki Wiki ID of the reference source
+ * @param UUID $id Id of the reference
+ * @param string $wiki Wiki ID of the reference source
* @param UUID $srcWorkflow ID of the source Workflow
* @param Title $srcTitle Title of the Workflow from which this
reference comes.
* @param string $objectType Output of getRevisionType for the
AbstractRevision that this reference comes from.
@@ -21,7 +22,7 @@
* @param string $type Type of reference
* @param Title $targetTitle Title of the reference's target.
*/
- public function __construct( $wiki, UUID $srcWorkflow, Title $srcTitle,
$objectType, UUID $objectId, $type, Title $targetTitle ) {
+ public function __construct( UUID $id, $wiki, UUID $srcWorkflow, Title
$srcTitle, $objectType, UUID $objectId, $type, Title $targetTitle ) {
$this->target = $targetTitle;
$this->validTypes = array_merge( $this->validTypes,
@@ -32,7 +33,7 @@
)
);
- parent::__construct( $wiki, $srcWorkflow, $srcTitle,
$objectType, $objectId, $type );
+ parent::__construct( $id, $wiki, $srcWorkflow, $srcTitle,
$objectType, $objectId, $type );
}
/**
@@ -50,10 +51,13 @@
/**
* Instantiates a WikiReference object from a storage row.
*
- * @param \StdClass $row
+ * @param array $row
* @return WikiReference
*/
public static function fromStorageRow( $row ) {
+ // TODO: Remove this UUID::create() call when the field is
populated
+ // everywhere relevant.
+ $id = $row['ref_id'] === null ? UUID::create() : UUID::create(
$row['ref_id'] );
$workflow = UUID::create( $row['ref_src_workflow_id'] );
$objectType = $row['ref_src_object_type'];
$objectId = UUID::create( $row['ref_src_object_id'] );
@@ -62,7 +66,7 @@
$type = $row['ref_type'];
$wiki = $row['ref_src_wiki'];
- return new WikiReference( $wiki, $workflow, $srcTitle,
$objectType, $objectId, $type, $targetTitle );
+ return new WikiReference( $id, $wiki, $workflow, $srcTitle,
$objectType, $objectId, $type, $targetTitle );
}
/**
diff --git a/includes/Parsoid/ReferenceFactory.php
b/includes/Parsoid/ReferenceFactory.php
index 5e768be..1646faa 100644
--- a/includes/Parsoid/ReferenceFactory.php
+++ b/includes/Parsoid/ReferenceFactory.php
@@ -54,6 +54,7 @@
*/
public function createUrlReference( $refType, $value ) {
return new URLReference(
+ UUID::create(),
$this->wikiId,
$this->workflowId,
$this->title,
@@ -82,6 +83,7 @@
}
return new WikiReference(
+ UUID::create(),
$this->wikiId,
$this->workflowId,
$this->title,
diff --git a/maintenance/FlowPopulateRefId.php
b/maintenance/FlowPopulateRefId.php
new file mode 100644
index 0000000..1879170
--- /dev/null
+++ b/maintenance/FlowPopulateRefId.php
@@ -0,0 +1,70 @@
+<?php
+
+use Flow\Container;
+use Flow\Data\ObjectManager;
+
+$installPath = getenv( 'MW_INSTALL_PATH' ) !== false ?
+ getenv( 'MW_INSTALL_PATH' ) :
+ __DIR__ . '/../../..';
+
+require_once( $installPath . '/maintenance/Maintenance.php' );
+// extending these - autoloader not yet wired up at the point these are
interpreted
+require_once( $installPath .'/includes/utils/BatchRowWriter.php' );
+require_once( $installPath . '/includes/utils/RowUpdateGenerator.php' );
+
+/**
+ * Populates ref_id in flow_wiki_ref & flow_ext_ref.
+ *
+ * @ingroup Maintenance
+ */
+class FlowPopulateRefId extends LoggedUpdateMaintenance {
+ public function __construct() {
+ parent::__construct();
+
+ $this->mDescription = 'Populates ref_id in flow_wiki_ref &
flow_ext_ref';
+
+ $this->setBatchSize( 300 );
+ }
+
+ protected function getUpdateKey() {
+ return __CLASS__;
+ }
+
+ protected function doDBUpdates() {
+ $types = array(
+ 'flow_wiki_ref' => Container::get(
'storage.wiki_reference' ),
+ 'flow_ext_ref' => Container::get(
'storage.url_reference' ),
+ );
+
+ foreach ( $types as $table => $storage ) {
+ $this->update( $storage );
+ }
+
+ $this->output( "Completed\n" );
+
+ return true;
+ }
+
+ /**
+ * @param ObjectManager $storage
+ * @throws \Flow\Exception\InvalidInputException
+ */
+ protected function update( ObjectManager $storage ) {
+ global $wgFlowCluster;
+
+ while ( true ) {
+ $references = (array) $storage->find( array( 'ref_id'
=> null ), array( 'limit' => $this->mBatchSize ) );
+ if ( !$references ) {
+ break;
+ }
+
+ $storage->multiPut( $references, array() );
+ $this->output( "Ensured ref_id for " . count(
$references ) . " " . get_class( $references[0] ) . " references...\n" );
+ wfWaitForSlaves( false, false, $wgFlowCluster );
+ }
+
+ }
+}
+
+$maintClass = 'FlowPopulateRefId';
+require_once( RUN_MAINTENANCE_IF_MAIN );
--
To view, visit https://gerrit.wikimedia.org/r/238393
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Icd1673ed642efc838809ae249f9544a364962886
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/Flow
Gerrit-Branch: master
Gerrit-Owner: Matthias Mullie <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Jcrespo <[email protected]>
Gerrit-Reviewer: Mattflaschen <[email protected]>
Gerrit-Reviewer: Matthias Mullie <[email protected]>
Gerrit-Reviewer: Springle <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits