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

Reply via email to