jenkins-bot has submitted this change and it was merged.
Change subject: Added gl_perm & gl_updated columns to gather_list
......................................................................
Added gl_perm & gl_updated columns to gather_list
* Two new fields for the lists table
* New list index by permission + updated TS
This will allow api to iterate over public+last updated
* list=lists & lstprop=updated gets the timestamp of the last update
* lstmode=allpublic ordering is now by gl_updated DESC
* The original SQL schema has been updated but commented out
for now until betalabs is updated. I plan to delete the
GatherListPermissions.php file once all dev machines
and betalabs are updated - will create it properly on
production cluster without updating.
* Bugfix - PHP 5.3 would have crashed because of clousure $this access
Bug: T93303
Bug: T92690
Change-Id: I6ab326f98b2fa4778f83f867507b8e52dcc38e62
---
M includes/api/ApiEditList.php
M includes/api/ApiQueryListPages.php
M includes/api/ApiQueryLists.php
A schema/GatherListPermissions.php
M schema/Updater.hooks.php
A schema/gather_list-perm-ts.sql
A schema/gather_list-perm-ts2.sql
A schema/gather_list-perm-ts2.sqlite.sql
M schema/gather_list.sql
M schema/gather_list_item.sql
10 files changed, 278 insertions(+), 80 deletions(-)
Approvals:
Robmoen: Looks good to me, but someone else must approve
Jdlrobson: Looks good to me, approved
jenkins-bot: Verified
diff --git a/includes/api/ApiEditList.php b/includes/api/ApiEditList.php
index 6af5668..6b62e90 100644
--- a/includes/api/ApiEditList.php
+++ b/includes/api/ApiEditList.php
@@ -126,10 +126,7 @@
$listId = $this->createRow( $dbw, $user, $params,
$isWatchlist );
} else {
// Find existing list
- $row = $dbw->selectRow( 'gather_list',
- array( 'gl_id', 'gl_user', 'gl_label',
'gl_info' ), array( 'gl_id' => $listId ),
- __METHOD__
- );
+ $row = $this->getListRow( $dbw, array( 'gl_id' =>
$listId ) );
if ( $row === false ) {
// No database record with the given ID
$this->dieUsage( "List {$p}id was not found",
'badid' );
@@ -230,13 +227,18 @@
private function updateInfo( stdClass $v, array $params, $isWatchlist )
{
$updated = false;
+ if ( $isWatchlist && $params['perm'] === 'public' ) {
+ // Per team discussion, introducing artificial
limitation for now
+ // until we establish that making watchlist public
would cause no harm.
+ // This check can be deleted at any time since all
other API code supports it.
+ $this->dieUsage( 'Making watchlist public is not
supported for security reasons',
+ 'publicwatchlist' );
+ }
+
//
// Set default
if ( !property_exists( $v, 'description' ) ) {
$v->description = '';
- }
- if ( !property_exists( $v, 'perm' ) ) {
- $v->perm = 'private';
}
if ( !property_exists( $v, 'image' ) ) {
$v->image = '';
@@ -246,17 +248,6 @@
// Update from api parameters
if ( $params['description'] !== null && $v->description !==
$params['description'] ) {
$v->description = $params['description'];
- $updated = true;
- }
- if ( $params['perm'] !== null && $v->perm !== $params['perm'] )
{
- if ( $isWatchlist && $params['perm'] !== 'private' ) {
- // Per team discussion, introducing artificial
limitation for now
- // until we establish that making watchlist
public would cause no harm.
- // This check can be deleted at any time since
all other API code supports it.
- $this->dieUsage( 'Making watchlist public is
not supported for security reasons',
- 'publicwatchlist' );
- }
- $v->perm = $params['perm'];
$updated = true;
}
if ( $params['image'] !== null && $v->image !==
$params['image'] ) {
@@ -279,6 +270,7 @@
* Check if the info is a public list
* @param stdClass $info
* @return bool
+ * @deprecated must use DB column instead (To be deleted once DB is
updated)
*/
public static function isPublic( $info ) {
if ( $info && property_exists( $info, 'perm' ) ) {
@@ -308,6 +300,8 @@
'gl_user' => $user->getId(),
'gl_label' => $label,
'gl_info' => $info,
+ 'gl_perm' => $params['perm'] === 'public' ? 1 :
0,
+ 'gl_updated' => $dbw->timestamp(
wfTimestampNow() ),
), __METHOD__, 'IGNORE' );
$id = $dbw->insertId();
} else {
@@ -316,11 +310,9 @@
if ( $id === 0 ) {
// List already exists, update instead, or might not
need it
- $row = $dbw->selectRow( 'gather_list',
- array( 'gl_id', 'gl_user', 'gl_label',
'gl_info' ),
- array( 'gl_user' => $user->getId(), 'gl_label'
=> $label ),
- __METHOD__
- );
+ $row = $this->getListRow( $dbw, array(
+ 'gl_user' => $user->getId(), 'gl_label' =>
$label
+ ) );
if ( $row === false ) {
if ( $createRow ) {
// If creation failed, the second query
should have succeeded
@@ -356,6 +348,12 @@
if ( $params['label'] !== null && $row->gl_label !==
$params['label'] ) {
$update['gl_label'] = $params['label'];
}
+ if ( $params['perm'] !== null ) {
+ $perm = $params['perm'] === 'public' ? 1 : 0;
+ if ( $row->gl_perm !== $perm ) {
+ $update['gl_perm'] = $perm;
+ }
+ }
$info = self::parseListInfo( $row->gl_info, $row->gl_id, true );
$json = $this->updateInfo( $info, $params, $row->gl_label ===
'' );
if ( $json ) {
@@ -363,6 +361,7 @@
}
if ( $update ) {
// ACTION: update list record
+ $update['gl_updated'] = $dbw->timestamp(
wfTimestampNow() );
$dbw->update( 'gather_list', $update, array( 'gl_id' =>
$row->gl_id ), __METHOD__, 'IGNORE' );
if ( $dbw->affectedRows() === 0 ) {
// update failed due to the duplicate label
restriction. Report
@@ -522,4 +521,16 @@
}
return new stdClass();
}
+
+ /**
+ * @param DatabaseBase $dbw
+ * @param array $conds
+ * @return bool|stdClass
+ */
+ private function getListRow( DatabaseBase $dbw, $conds ) {
+ return $dbw->selectRow( 'gather_list',
+ array( 'gl_id', 'gl_user', 'gl_label', 'gl_perm',
'gl_info' ),
+ $conds,
+ __METHOD__ );
+ }
}
diff --git a/includes/api/ApiQueryListPages.php
b/includes/api/ApiQueryListPages.php
index 7ecf1f9..dca0811 100644
--- a/includes/api/ApiQueryListPages.php
+++ b/includes/api/ApiQueryListPages.php
@@ -79,7 +79,7 @@
// Id was given, this could be public or private list,
legacy watchlist or regular
// Allow access to any public list/watchlist, and to
private with proper owner/self
$db = $this->getDB();
- $listRow = $db->selectRow( 'gather_list', array(
'gl_label', 'gl_user', 'gl_info' ),
+ $listRow = $db->selectRow( 'gather_list', array(
'gl_label', 'gl_user' ),
array( 'gl_id' => $params['id'] ), __METHOD__ );
if ( $listRow === false ) {
$this->dieUsage( "List does not exist", 'badid'
);
@@ -101,11 +101,8 @@
}
// Check if this is a public list (if required)
- if ( !$showPrivate ) {
- $info = ApiEditList::parseListInfo(
$listRow->gl_info, $params['id'], false );
- if ( !ApiEditList::isPublic( $info ) ) {
- $this->dieUsage( "You have no rights to
see this list", 'badid' );
- }
+ if ( !$showPrivate && $listRow->perm !== 1 ) {
+ $this->dieUsage( "You have no rights to see
this list", 'badid' );
}
if ( $listRow->gl_label === '' ) {
diff --git a/includes/api/ApiQueryLists.php b/includes/api/ApiQueryLists.php
index 17c3f9f..0528d8f 100644
--- a/includes/api/ApiQueryLists.php
+++ b/includes/api/ApiQueryLists.php
@@ -44,6 +44,7 @@
}
public function execute() {
+ $self = $this; // php 5.3 support - closures can't access $this
$p = $this->getModulePrefix();
$params = $this->extractRequestParams();
$continue = $params['continue'];
@@ -55,6 +56,7 @@
$fld_description = in_array( 'description', $params['prop'] );
$fld_public = in_array( 'public', $params['prop'] );
$fld_image = in_array( 'image', $params['prop'] );
+ $fld_updated = in_array( 'updated', $params['prop'] );
// Watchlist, having the label set to '', should always appear
first
// If it doesn't, make sure to insert a fake one in the result
@@ -92,17 +94,23 @@
/** @var User $owner */
list( $owner, $showPrivate ) = $this->calcPermissions(
$params, $ids );
$userId = $owner ? $owner->getId() :
$this->getUser()->getId();
+ if ( $showPrivate !== true ) {
+ $injectWatchlist = false;
+ }
}
$db = $this->getDB();
$this->addTables( 'gather_list' );
$this->addFields( 'gl_id' );
$this->addFieldsIf( 'gl_label', $fld_label || !$modeAll );
- // won't know if private until later
- $this->addFieldsIf( 'gl_user', $showPrivate === null ||
$modeAll );
+ $this->addFieldsIf( 'gl_updated', $fld_updated || $modeAll );
+ $this->addFieldsIf( 'gl_user', $modeAll );
+ $this->addFieldsIf( 'gl_perm', $fld_public );
+
if ( $owner ) {
$this->addWhereFld( 'gl_user', $owner->getId() );
}
+
if ( $ids || $findWatchlist ) {
$cond = array();
if ( $ids ) {
@@ -114,16 +122,41 @@
$this->addWhere( $db->makeList( $cond, LIST_OR ) );
}
+ if ( $showPrivate !== true ) {
+ $cond = array( 'gl_perm' => 1 );
+ if ( $showPrivate === null ) {
+ $cond['gl_user'] = $this->getUser()->getId();
+ }
+ $this->addWhere( $db->makeList( $cond, LIST_OR ) );
+ }
+
if ( $continue ) {
if ( $modeAll ) {
- $cont = intval( $continue );
- $this->dieContinueUsageIf( strval( $cont ) !==
$continue );
- $cont = $db->addQuotes( $cont );
- $this->addWhere( "gl_id >= $cont" );
+ $cont = explode( '|', $params['continue'] );
+ $this->dieContinueUsageIf( count( $cont ) != 2
);
+ $cont_upd = $db->addQuotes( $cont[0] );
+ $cont_id = intval( $cont[1] );
+ $this->dieContinueUsageIf( strval( $cont_id )
!== $cont[1] );
+ $cont_id = $db->addQuotes( $cont_id );
+ $this->addWhere( "gl_updated < $cont_upd OR " .
+ "(gl_updated =
$cont_upd AND gl_id <= $cont_id)" );
} else {
$cont = $db->addQuotes( $continue );
$this->addWhere( "gl_label >= $cont" );
}
+ }
+ if ( $modeAll ) {
+ // The ordering has to be unique so that we can safely
+ // continue iteration even if subsequent timestamps are
the same
+ $this->addOption( 'ORDER BY', 'gl_perm, gl_updated
DESC, gl_id DESC' );
+ $setContinue = function( $row ) use ( $self ) {
+ $self->setContinueEnumParameter( 'continue',
"{$row->gl_updated}|{$row->gl_id}" );
+ };
+ } else {
+ $this->addOption( 'ORDER BY', 'gl_user, gl_label' );
+ $setContinue = function( $row ) use ( $self ) {
+ $self->setContinueEnumParameter( 'continue',
$row->gl_label );
+ };
}
if ( $title ) {
@@ -147,29 +180,19 @@
}
}
- // If we need it for privacy checks or we need to return a prop
field
- $useInfo = $showPrivate !== true || $fld_description ||
$fld_public || $fld_image;
-
+ $useInfo = $fld_description || $fld_image;
$this->addFieldsIf( 'gl_info', $useInfo );
$limit = $params['limit'];
- // TODO: Disabling this until we stop skipping rows in
processing
- // $this->addOption( 'LIMIT', $limit + 1 );
-
- if ( $modeAll ) {
- $this->addOption( 'ORDER BY', 'gl_id' );
- } else {
- $this->addOption( 'ORDER BY', 'gl_user, gl_label' );
- }
+ $this->addOption( 'LIMIT', $limit + 1 );
$count = 0;
$path = array( 'query', $this->getModuleName() );
- $currUserId = strval( $this->getUser()->getId() );
// This closure will process one row, even if that row is fake
watchlist
- $processRow = function( $row ) use ( &$count, $modeAll, $limit,
$useInfo, $title,
- $fld_label, $fld_description, $fld_public, $fld_image,
$path, $showPrivate,
- $currUserId, $userId
+ $processRow = function( $row ) use ( $self, &$count, $modeAll,
$limit, $useInfo, $title,
+ $fld_label, $fld_description, $fld_public, $fld_image,
$fld_updated, $path, $userId,
+ $setContinue
) {
if ( $row === null ) {
// Fake watchlist row
@@ -177,32 +200,17 @@
'gl_id' => '0',
'gl_label' => '',
'gl_user' => false,
+ 'gl_perm' => 0,
+ 'gl_updated' => '',
'gl_info' => '',
);
}
- $info = $useInfo ?
- ApiEditList::parseListInfo( $row->gl_info,
$row->gl_id, false ) : null;
-
- // Determine if this gather_list row is viewable by the
current user
- // TODO: this should be part of the SQL query once
fields are cerated
- $show = $showPrivate;
- if ( $show === null && $row->gl_user === $currUserId ) {
- $show = true;
- } elseif ( $show !== true && ApiEditList::isPublic(
$info ) ) {
- $show = true;
- }
- if ( !$show ) {
- return true;
- }
-
$count++;
- $continueValue = $modeAll ? $row->gl_id :
$row->gl_label;
-
if ( $count > $limit ) {
// We've reached the one extra which shows that
there are
// additional pages to be had. Stop here...
- $this->setContinueEnumParameter( 'continue',
$continueValue );
+ $setContinue( $row );
return false;
}
@@ -221,17 +229,18 @@
}
if ( $title ) {
if ( $isWatchlist ) {
- $data['title'] =
$this->isTitleInWatchlist( $userId, $title );
+ $data['title'] =
$self->isTitleInWatchlist( $userId, $title );
} else {
$data['title'] = $row->isIn !== null;
}
}
+ if ( $fld_public ) {
+ $data['public'] = $row->gl_perm === 1;
+ }
if ( $useInfo ) {
+ $info = ApiEditList::parseListInfo(
$row->gl_info, $row->gl_id, false );
if ( $fld_description ) {
$data['description'] = property_exists(
$info, 'description' ) ? $info->description : '';
- }
- if ( $fld_public ) {
- $data['public'] =
ApiEditList::isPublic( $info );
}
if ( $fld_image ) {
if ( property_exists( $info, 'image' )
&& $info->image ) {
@@ -249,10 +258,13 @@
}
}
}
+ if ( $fld_updated ) {
+ $data['updated'] = wfTimestamp( TS_ISO_8601,
$row->gl_updated );
+ }
- $fit = $this->getResult()->addValue( $path, null, $data
);
+ $fit = $self->getResult()->addValue( $path, null, $data
);
if ( !$fit ) {
- $this->setContinueEnumParameter( 'continue',
$continueValue );
+ $setContinue( $row );
return false;
}
return true;
@@ -303,6 +315,7 @@
'public',
'image',
'count',
+ 'updated',
)
),
'ids' => array(
@@ -380,7 +393,7 @@
if ( !$this->getUser()->isLoggedIn() ) {
$showPrivate = false;
} else {
- $showPrivate = null; // check each id against
$currUserId
+ $showPrivate = null; // check each id against
current user's ID
}
}
if ( $showPrivate !== false ) {
diff --git a/schema/GatherListPermissions.php b/schema/GatherListPermissions.php
new file mode 100644
index 0000000..7b2961d
--- /dev/null
+++ b/schema/GatherListPermissions.php
@@ -0,0 +1,84 @@
+<?php
+/**
+ * @ingroup Maintenance
+ */
+
+namespace Gather;
+
+use FormatJson;
+use Gather\api\ApiEditList;
+use LoggedUpdateMaintenance;
+
+$IP = getenv( 'MW_INSTALL_PATH' );
+if ( $IP === false ) {
+ $IP = __DIR__ . '/../../..';
+}
+require_once ( "$IP/maintenance/Maintenance.php" );
+
+/**
+ * @ingroup Maintenance
+ */
+class GatherListPermissions extends LoggedUpdateMaintenance {
+ public function __construct() {
+ parent::__construct();
+ $this->mDescription = 'Fix permissions and timestamp fields on
gather_list';
+ }
+
+ protected function getUpdateKey() {
+ return 'update gather list permissions';
+ }
+
+ protected function updateSkippedMessage() {
+ return 'gather list permissions already updated';
+ }
+
+ protected function doDBUpdates() {
+ $this->output( "Populating gl_perm column in gather_list
table\n" );
+
+ $db = wfGetDB( DB_MASTER );
+
+ $totalCount = 0;
+ $batchSize = $count = $this->mBatchSize;
+
+ while ( $batchSize === $count ) {
+ $count = 0;
+
+ $res = $db->select(
+ 'gather_list',
+ array( 'gl_id', 'gl_info', 'gl_label' ),
+ array( 'gl_perm' => null ),
+ __METHOD__,
+ array( 'LIMIT' => $batchSize )
+ );
+
+ foreach ( $res as $row ) {
+ $count++;
+
+ $info = ApiEditList::parseListInfo(
$row->gl_info, $row->gl_id, true );
+ $perm = ( ApiEditList::isPublic( $info ) &&
$row->gl_label !== '' ) ? 1 : 0;
+ unset( $info->perm );
+ unset( $info->public );
+
+ $db->update(
+ 'gather_list',
+ array(
+ 'gl_perm' => $perm,
+ 'gl_info' =>
FormatJson::encode( $info, false, FormatJson::ALL_OK ),
+ 'gl_updated' => $db->timestamp(
wfTimestampNow() ),
+ ),
+ array( 'gl_id' => $row->gl_id ),
+ __METHOD__ );
+ }
+
+ $totalCount += $count;
+
+ wfWaitForSlaves();
+ }
+
+ $this->output( "Done, $totalCount rows updated.\n" );
+ return true;
+ }
+}
+
+$maintClass = 'GatherListPermissions';
+require_once ( RUN_MAINTENANCE_IF_MAIN );
diff --git a/schema/Updater.hooks.php b/schema/Updater.hooks.php
index a9ffd98..1caaed4 100644
--- a/schema/Updater.hooks.php
+++ b/schema/Updater.hooks.php
@@ -9,10 +9,19 @@
*/
class UpdaterHooks {
public static function onLoadExtensionSchemaUpdates( DatabaseUpdater
$du ) {
- $base = dirname( __FILE__ );
+ $dir = __DIR__;
+ $du->addExtensionTable( 'gather_list', "$dir/gather_list.sql",
true );
+ $du->addExtensionTable( 'gather_list_item',
"$dir/gather_list_item.sql", true );
+ $du->addExtensionField( 'gather_list', 'gl_perm',
"$dir/gather_list-perm-ts.sql" );
- $du->addExtensionTable( 'gather_list', "$base/gather_list.sql",
true );
- $du->addExtensionTable( 'gather_list_item',
"$base/gather_list_item.sql", true );
+ require_once "$dir/GatherListPermissions.php";
+ $du->addPostDatabaseUpdateMaintenance(
'Gather\GatherListPermissions' );
+
+ if ( $du->getDB()->getType() === 'sqlite' ) {
+ $du->modifyExtensionField( 'gather_list', 'gl_perm',
"$dir/gather_list-perm-ts2.sqlite.sql" );
+ } else {
+ $du->modifyExtensionField( 'gather_list', 'gl_perm',
"$dir/gather_list-perm-ts2.sql" );
+ }
return true;
}
diff --git a/schema/gather_list-perm-ts.sql b/schema/gather_list-perm-ts.sql
new file mode 100644
index 0000000..067b41c
--- /dev/null
+++ b/schema/gather_list-perm-ts.sql
@@ -0,0 +1,16 @@
+-- Licence: GNU GPL v2+
+
+ALTER TABLE /*_*/gather_list
+ -- The list permissions type (NULL=not migrated, GATHER_PRIVATE=0,
GATHER_PUBLIC=1)
+ ADD COLUMN gl_perm TINYINT UNSIGNED NULL DEFAULT NULL; -- AFTER gl_label;
+
+
+ALTER TABLE /*_*/gather_list
+ -- The timestamp is updated whenever the list's meta data is modified.
+ -- It is possible we might update this field when modifying watchlist / list
pages
+ ADD COLUMN gl_updated VARBINARY(14) NOT NULL DEFAULT ''; -- AFTER gl_perm;
+
+
+-- Show all public lists, sorted by the last updated timestamp
+-- gl_id is included to allow for safe continuation of the query
+CREATE INDEX /*i*/gl_user_perm_updated ON /*_*/gather_list (gl_perm,
gl_updated DESC, gl_id);
diff --git a/schema/gather_list-perm-ts2.sql b/schema/gather_list-perm-ts2.sql
new file mode 100644
index 0000000..608f108
--- /dev/null
+++ b/schema/gather_list-perm-ts2.sql
@@ -0,0 +1,5 @@
+-- Licence: GNU GPL v2+
+
+ALTER TABLE /*_*/gather_list
+ -- The list permissions type (NULL=not migrated, GATHER_PRIVATE=0,
GATHER_PUBLIC=1)
+ MODIFY COLUMN gl_perm TINYINT UNSIGNED NOT NULL DEFAULT 0;
diff --git a/schema/gather_list-perm-ts2.sqlite.sql
b/schema/gather_list-perm-ts2.sqlite.sql
new file mode 100644
index 0000000..1b35147
--- /dev/null
+++ b/schema/gather_list-perm-ts2.sqlite.sql
@@ -0,0 +1,51 @@
+-- Sqlites alter table statement can NOT change existing columns. The only
+-- option since we need to change the nullability of event_variant is to
+-- recreate the table and copy the data over.
+
+-- Rename current table to temporary name
+ALTER TABLE /*_*/gather_list RENAME TO
/*_*/temp_gather_list_variant_nullability;
+
+CREATE TABLE /*_*/gather_list (
+
+ -- Primary key
+ gl_id INT UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
+
+ -- Key to user.user_id
+ gl_user INT UNSIGNED NOT NULL,
+
+ -- Name of the collection is kept outside of the blob for easy lookup and
ordering
+ -- Must be unique per user - makes it easier for querying/looking up
+ gl_label VARCHAR(255) BINARY NOT NULL,
+
+ -- The list permissions type (NULL=not migrated, GATHER_PRIVATE=0,
GATHER_PUBLIC=1)
+ gl_perm TINYINT UNSIGNED NOT NULL DEFAULT 0,
+
+ -- The timestamp is updated whenever the list's meta data is modified.
+ -- It is possible we might update this field when modifying watchlist / list
pages
+ gl_updated VARBINARY(14) NOT NULL DEFAULT '',
+
+ -- All other values are stored here to allow for rapid design changes.
+ -- At this point we do not foresee any value in using indexes
+ -- thus blob is a perfect storage medium. Stored as JSON blob.
+ gl_info blob NOT NULL
+
+) /*$wgDBTableOptions*/;
+
+-- Copy over all the old data into the new table
+INSERT INTO /*_*/gather_list
+ (gl_id, gl_user, gl_label, gl_perm, gl_updated, gl_info)
+SELECT
+ gl_id, gl_user, gl_label, gl_perm, gl_updated, gl_info
+FROM
+ /*_*/temp_gather_list_variant_nullability;
+
+-- Drop the original table
+DROP TABLE /*_*/temp_gather_list_variant_nullability;
+
+
+-- Gets lists of a specific user, sorted by label, watchlist first
+CREATE UNIQUE INDEX /*i*/gl_user_label ON /*_*/gather_list (gl_user, gl_label);
+
+-- Show all public lists, sorted by the last updated timestamp
+-- gl_id is included to allow for safe continuation of the query
+CREATE INDEX /*i*/gl_user_perm_updated ON /*_*/gather_list (gl_perm,
gl_updated DESC, gl_id);
diff --git a/schema/gather_list.sql b/schema/gather_list.sql
index cd4f745..ca5767f 100644
--- a/schema/gather_list.sql
+++ b/schema/gather_list.sql
@@ -16,6 +16,13 @@
-- Must be unique per user - makes it easier for querying/looking up
gl_label VARCHAR(255) BINARY NOT NULL,
+ -- The list permissions type (NULL=not migrated, GATHER_PRIVATE=0,
GATHER_PUBLIC=1)
+ -- gl_perm TINYINT UNSIGNED NOT NULL DEFAULT 0,
+
+ -- The timestamp is updated whenever the list's meta data is modified.
+ -- It is possible we might update this field when modifying watchlist / list
pages
+ -- gl_updated VARBINARY(14) NOT NULL DEFAULT '',
+
-- All other values are stored here to allow for rapid design changes.
-- At this point we do not foresee any value in using indexes
-- thus blob is a perfect storage medium. Stored as JSON blob.
@@ -24,5 +31,9 @@
) /*$wgDBTableOptions*/;
--- Index to iterate by label
+-- Gets lists of a specific user, sorted by label, watchlist first
CREATE UNIQUE INDEX /*i*/gl_user_label ON /*_*/gather_list (gl_user, gl_label);
+
+-- Show all public lists, sorted by the last updated timestamp
+-- gl_id is included to allow for safe continuation of the query
+-- CREATE INDEX /*i*/gl_user_perm_updated ON /*_*/gather_list (gl_perm,
gl_updated DESC, gl_id);
diff --git a/schema/gather_list_item.sql b/schema/gather_list_item.sql
index 7bdb7f5..f6b1358 100644
--- a/schema/gather_list_item.sql
+++ b/schema/gather_list_item.sql
@@ -17,13 +17,14 @@
-- Sort order uses real to simplify item insertion
-- without modifying other items
- gli_order REAL NOT NULL DEFAULT 0
+ gli_order FLOAT NOT NULL DEFAULT 0
) /*$wgDBTableOptions*/;
-- Define clustered index (must be first unique) -- most common operations
will enumerate in order
CREATE UNIQUE INDEX /*i*/gli_id_order_ns_title ON /*_*/gather_list_item
(gli_gl_id, gli_order, gli_namespace, gli_title);
+
-- In case all lists for a specific title need to be shown / updated
-- Also, enforce one title per list uniqueness
CREATE UNIQUE INDEX /*i*/gli_ns_title ON /*_*/gather_list_item (gli_namespace,
gli_title, gli_gl_id);
--
To view, visit https://gerrit.wikimedia.org/r/198181
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I6ab326f98b2fa4778f83f867507b8e52dcc38e62
Gerrit-PatchSet: 10
Gerrit-Project: mediawiki/extensions/Gather
Gerrit-Branch: master
Gerrit-Owner: Yurik <[email protected]>
Gerrit-Reviewer: Aaron Schulz <[email protected]>
Gerrit-Reviewer: CSteipp <[email protected]>
Gerrit-Reviewer: Jdlrobson <[email protected]>
Gerrit-Reviewer: Jhernandez <[email protected]>
Gerrit-Reviewer: Robmoen <[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