+ $this->orderBy = 'name';
+ $fname = __METHOD__;
+
+ // Because 'userprefix' might produce a huge number of users (e.g.
+ // a wiki with users "Test00000001" to "Test99999999"), use a
+ // generator with batched lookup and continuation.
+ $userIter = call_user_func( function () use ( $dbSecondary, $sort, $op, $fname ) {
+ global $wgActorTableSchemaMigrationStage;
+
+ $from = $fromName = false;
+ if ( !is_null( $this->params['continue'] ) ) {
+ $continue = explode( '|', $this->params['continue'] );
+ $this->dieContinueUsageIf( count( $continue ) != 4 );
+ $this->dieContinueUsageIf( $continue[0] !== 'name' );
+ $fromName = $continue[1];
+ $from = "$op= " . $dbSecondary->addQuotes( $fromName );
+ }
+ $like = $dbSecondary->buildLike( $this->params['userprefix'], $dbSecondary->anyString() );
+
+ $limit = 501;
+
+ do {
+ // For the new schema, pull from the actor table. For the
+ // old, pull from rev_user. For migration a FULL [OUTER]
+ // JOIN would be what we want, except MySQL doesn't support
+ // that so we have to UNION instead.
+ if ( $wgActorTableSchemaMigrationStage === MIGRATION_NEW ) {
+ $res = $dbSecondary->select(
+ 'actor',
+ [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
+ array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
+ $fname,
+ [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ]
+ );
+ } elseif ( $wgActorTableSchemaMigrationStage === MIGRATION_OLD ) {
+ $res = $dbSecondary->select(
+ 'revision',
+ [ 'actor_id' => 'NULL', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
+ array_merge( [ "rev_user_text$like" ], $from ? [ "rev_user_text $from" ] : [] ),
+ $fname,
+ [ 'DISTINCT', 'ORDER BY' => [ "rev_user_text $sort" ], 'LIMIT' => $limit ]
+ );
+ } else {
+ // There are three queries we have to combine to be sure of getting all results:
+ // - actor table (any rows that have been migrated will have empty rev_user_text)
+ // - revision+actor by user id
+ // - revision+actor by name for anons
+ $options = $dbSecondary->unionSupportsOrderAndLimit()
+ ? [ 'ORDER BY' => [ "user_name $sort" ], 'LIMIT' => $limit ] : [];
+ $subsql = [];
+ $subsql[] = $dbSecondary->selectSQLText(
+ 'actor',
+ [ 'actor_id', 'user_id' => 'COALESCE(actor_user,0)', 'user_name' => 'actor_name' ],
+ array_merge( [ "actor_name$like" ], $from ? [ "actor_name $from" ] : [] ),
+ $fname,
+ $options
+ );
+ $subsql[] = $dbSecondary->selectSQLText(
+ [ 'revision', 'actor' ],
+ [ 'actor_id', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
+ array_merge(
+ [ "rev_user_text$like", 'rev_user != 0' ],
+ $from ? [ "rev_user_text $from" ] : []
+ ),
+ $fname,
+ array_merge( [ 'DISTINCT' ], $options ),
+ [ 'actor' => [ 'LEFT JOIN', 'rev_user = actor_user' ] ]
+ );
+ $subsql[] = $dbSecondary->selectSQLText(
+ [ 'revision', 'actor' ],
+ [ 'actor_id', 'user_id' => 'rev_user', 'user_name' => 'rev_user_text' ],
+ array_merge(
+ [ "rev_user_text$like", 'rev_user = 0' ],
+ $from ? [ "rev_user_text $from" ] : []
+ ),
+ $fname,
+ array_merge( [ 'DISTINCT' ], $options ),
+ [ 'actor' => [ 'LEFT JOIN', 'rev_user_text = actor_name' ] ]
+ );
+ $sql = $dbSecondary->unionQueries( $subsql, false ) . " ORDER BY user_name $sort";
+ $sql = $dbSecondary->limitResult( $sql, $limit );
+ $res = $dbSecondary->query( $sql, $fname );
+ }