285 $this->author_list =
"<contributors>";
288 $res = $this->revisionStore->newSelectQueryBuilder( $this->db )
291 ->where( $this->db->bitAnd(
'rev_deleted', RevisionRecord::DELETED_USER ) .
' = 0' )
293 ->caller( __METHOD__ )->fetchResultSet();
295 foreach ( $res as $row ) {
296 $this->author_list .=
"<contributor>" .
298 htmlspecialchars( $row->rev_user_text ) .
301 ( (int)$row->rev_user ) .
305 $this->author_list .=
"</contributors>";
326 $hideLogs = LogEventsList::getExcludeClause( $this->db );
328 $where[] = $hideLogs;
330 # Add on any caller specified conditions
335 $commentQuery = $this->commentStore->getJoin(
'log_comment' );
339 $result = $this->db->newSelectQueryBuilder()
341 'log_id',
'log_type',
'log_action',
'log_timestamp',
'log_namespace',
342 'log_title',
'log_params',
'log_deleted',
'actor_user',
'actor_name'
345 ->join(
'actor',
null,
'actor_id=log_actor' )
347 ->andWhere( $this->db->expr(
'log_id',
'>', intval( $lastLogId ) ) )
348 ->orderBy(
'log_id' )
349 ->useIndex( [
'logging' =>
'PRIMARY' ] )
350 ->limit( self::BATCH_SIZE )
351 ->queryInfo( $commentQuery )
352 ->caller( __METHOD__ )
355 if ( !$result->numRows() ) {
360 $this->reloadDBConfig();
369 $revQuery = $this->revisionStore->getQueryInfo( [
'page' ] );
370 $slotQuery = $this->revisionStore->getSlotsQueryInfo( [
'content' ] );
377 $tables = array_merge( [
'page' ], array_diff( $revQuery[
'tables'], [
'page' ] ) );
378 $tables = array_merge( $tables, array_diff( $slotQuery[
'tables'], $tables ) );
379 $join = $revQuery[
'joins'] + [
380 'revision' => $revQuery[
'joins'][
'page'],
381 'slots' => [
'JOIN', [
'slot_revision_id = rev_id' ] ],
382 'content' => [
'JOIN', [
'content_id = slot_content_id' ] ],
384 unset( $join[
'page'] );
386 $fields = array_merge( $revQuery[
'fields'], $slotQuery[
'fields'] );
388 if ( $this->text != self::STUB ) {
389 $fields[
'_load_content'] =
'1';
393 if ( $cond !==
'' ) {
396 $opts = [
'ORDER BY' => [
'rev_page ASC',
'rev_id ASC' ] ];
397 $opts[
'USE INDEX'] = [];
400 if ( is_array( $this->history ) ) {
401 # Time offset/limit for all pages/history...
403 if ( $this->history[
'dir'] ==
'asc' ) {
404 $opts[
'ORDER BY'] =
'rev_timestamp ASC';
407 $opts[
'ORDER BY'] =
'rev_timestamp DESC';
410 if ( !empty( $this->history[
'offset'] ) ) {
411 $conds[] =
"rev_timestamp $op " .
412 $this->db->addQuotes( $this->db->timestamp( $this->history[
'offset'] ) );
415 if ( !empty( $this->history[
'limit'] ) ) {
416 $maxRowCount = intval( $this->history[
'limit'] );
418 } elseif ( $this->history & self::FULL ) {
419 # Full history dumps...
420 # query optimization for history stub dumps
421 if ( $this->text == self::STUB ) {
422 $opts[] =
'STRAIGHT_JOIN';
423 unset( $join[
'revision'] );
424 $join[
'page'] = [
'JOIN',
'rev_page=page_id' ];
426 } elseif ( $this->history & self::CURRENT ) {
427 # Latest revision dumps...
428 if ( $this->list_authors && $cond !=
'' ) {
431 $join[
'revision'] = [
'JOIN',
'page_id=rev_page AND page_latest=rev_id' ];
432 $opts[
'ORDER BY' ] = [
'page_id ASC' ];
433 } elseif ( $this->history & self::STABLE ) {
434 # "Stable" revision dumps...
435 # Default JOIN, to be overridden...
436 $join[
'revision'] = [
'JOIN',
'page_id=rev_page AND page_latest=rev_id' ];
437 # One, and only one hook should set this, and return false
438 if ( $this->hookRunner->onWikiExporter__dumpStableQuery( $tables, $opts, $join ) ) {
439 throw new LogicException( __METHOD__ .
" given invalid history dump type." );
441 } elseif ( $this->history & self::RANGE ) {
442 # Dump of revisions within a specified range. Condition already set in revsByRange().
444 # Unknown history specification parameter?
445 throw new UnexpectedValueException( __METHOD__ .
" given invalid history dump type." );
454 $opts[
'LIMIT'] = self::BATCH_SIZE;
456 $this->hookRunner->onModifyExportQuery(
457 $this->db, $tables, $cond, $opts, $join, $conds );
461 if ( !empty( $maxRowCount ) && $rowCount + self::BATCH_SIZE > $maxRowCount ) {
462 $opts[
'LIMIT'] = $maxRowCount - $rowCount;
466 # Do the query and process any results, remembering max ids for the next iteration.
467 $result = $this->db->newSelectQueryBuilder()
471 ->andWhere( $this->db->expr(
'rev_page',
'>', intval( $revPage ) )->orExpr(
472 $this->db->expr(
'rev_page',
'=', intval( $revPage ) )->and(
'rev_id', $op, intval( $revId ) )
474 ->caller( __METHOD__ )
478 if ( $result->numRows() > 0 ) {
480 $rowCount += $result->numRows();
481 $revPage = $lastRow->rev_page;
482 $revId = $lastRow->rev_id;
488 if ( $done && $lastRow ) {
493 $this->reloadDBConfig();
518 $revRow = $slotRows[0];
520 if ( $this->limitNamespaces &&
521 !in_array( $revRow->page_namespace, $this->limitNamespaces ) ) {
526 if ( $lastRow ===
null ||
527 $lastRow->page_namespace !== $revRow->page_namespace ||
528 $lastRow->page_title !== $revRow->page_title ) {
529 if ( $lastRow !==
null ) {
531 if ( $this->dumpUploads ) {
532 $output .= $this->writer->writeUploads( $lastRow, $this->dumpUploadFileContents );
534 $output .= $this->writer->closePage();
535 $this->sink->writeClosePage( $output );
537 $output = $this->writer->openPage( $revRow );
538 $this->sink->writeOpenPage( $revRow, $output );
541 $output = $this->writer->writeRevision( $revRow, $slotRows );
542 $this->sink->writeRevision( $revRow, $output );
544 MWDebug::warning(
'Problem encountered retrieving rev and slot metadata for'
545 .
' revision ' . $revRow->rev_id .
': ' . $ex->getMessage() );
551 throw new LogicException(
'Error while processing a stream of slot rows' );