.pipeline/config.yaml: rename dev stage to publish
[lhc/web/wiklou.git] / tests / phpunit / includes / Revision / RevisionQueryInfoTest.php
1 <?php
2
3 namespace MediaWiki\Tests\Revision;
4
5 use MediaWiki\MediaWikiServices;
6 use MediaWiki\Revision\SlotRecord;
7 use MediaWikiTestCase;
8 use Revision;
9
10 /**
11 * Tests RevisionStore against the post-migration MCR DB schema.
12 *
13 * @group RevisionStore
14 * @group Storage
15 * @group Database
16 */
17 class RevisionQueryInfoTest extends MediaWikiTestCase {
18
19 protected function getRevisionQueryFields( $returnTextIdField = true ) {
20 $fields = [
21 'rev_id',
22 'rev_page',
23 'rev_timestamp',
24 'rev_minor_edit',
25 'rev_deleted',
26 'rev_len',
27 'rev_parent_id',
28 'rev_sha1',
29 ];
30 if ( $returnTextIdField ) {
31 $fields[] = 'rev_text_id';
32 }
33 return $fields;
34 }
35
36 protected function getArchiveQueryFields( $returnTextFields = true ) {
37 $fields = [
38 'ar_id',
39 'ar_page_id',
40 'ar_namespace',
41 'ar_title',
42 'ar_rev_id',
43 'ar_timestamp',
44 'ar_minor_edit',
45 'ar_deleted',
46 'ar_len',
47 'ar_parent_id',
48 'ar_sha1',
49 ];
50 if ( $returnTextFields ) {
51 $fields[] = 'ar_text_id';
52 }
53 return $fields;
54 }
55
56 protected function getNewCommentQueryFields( $prefix ) {
57 return [
58 "{$prefix}_comment_text" => "comment_{$prefix}_comment.comment_text",
59 "{$prefix}_comment_data" => "comment_{$prefix}_comment.comment_data",
60 "{$prefix}_comment_cid" => "comment_{$prefix}_comment.comment_id",
61 ];
62 }
63
64 protected function getNewActorQueryFields( $prefix, $tmp = false ) {
65 return [
66 "{$prefix}_user" => "actor_{$prefix}_user.actor_user",
67 "{$prefix}_user_text" => "actor_{$prefix}_user.actor_name",
68 "{$prefix}_actor" => $tmp ? "temp_{$prefix}_user.{$prefix}actor_actor" : "{$prefix}_actor",
69 ];
70 }
71
72 protected function getTextQueryFields() {
73 return [
74 'old_text',
75 'old_flags',
76 ];
77 }
78
79 protected function getPageQueryFields() {
80 return [
81 'page_namespace',
82 'page_title',
83 'page_id',
84 'page_latest',
85 'page_is_redirect',
86 'page_len',
87 ];
88 }
89
90 protected function getUserQueryFields() {
91 return [
92 'user_name',
93 ];
94 }
95
96 protected function getContentHandlerQueryFields( $prefix ) {
97 return [
98 "{$prefix}_content_format",
99 "{$prefix}_content_model",
100 ];
101 }
102
103 public function provideArchiveQueryInfo() {
104 yield 'MCR, comment, actor' => [
105 [
106 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
107 ],
108 [
109 'tables' => [
110 'archive',
111 'actor_ar_user' => 'actor',
112 'comment_ar_comment' => 'comment',
113 ],
114 'fields' => array_merge(
115 $this->getArchiveQueryFields( false ),
116 $this->getNewActorQueryFields( 'ar' ),
117 $this->getNewCommentQueryFields( 'ar' )
118 ),
119 'joins' => [
120 'comment_ar_comment'
121 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
122 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
123 ],
124 ]
125 ];
126 yield 'read-new MCR, comment, actor' => [
127 [
128 'wgContentHandlerUseDB' => true,
129 'wgMultiContentRevisionSchemaMigrationStage'
130 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
131 ],
132 [
133 'tables' => [
134 'archive',
135 'actor_ar_user' => 'actor',
136 'comment_ar_comment' => 'comment',
137 ],
138 'fields' => array_merge(
139 $this->getArchiveQueryFields( false ),
140 $this->getNewActorQueryFields( 'ar' ),
141 $this->getNewCommentQueryFields( 'ar' )
142 ),
143 'joins' => [
144 'comment_ar_comment'
145 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
146 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
147 ],
148 ]
149 ];
150 yield 'MCR write-both/read-old' => [
151 [
152 'wgContentHandlerUseDB' => true,
153 'wgMultiContentRevisionSchemaMigrationStage'
154 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
155 ],
156 [
157 'tables' => [
158 'archive',
159 'actor_ar_user' => 'actor',
160 'comment_ar_comment' => 'comment',
161 ],
162 'fields' => array_merge(
163 $this->getArchiveQueryFields( true ),
164 $this->getContentHandlerQueryFields( 'ar' ),
165 $this->getNewActorQueryFields( 'ar' ),
166 $this->getNewCommentQueryFields( 'ar' )
167 ),
168 'joins' => [
169 'comment_ar_comment'
170 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
171 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
172 ],
173 ]
174 ];
175 yield 'pre-MCR, no model' => [
176 [
177 'wgContentHandlerUseDB' => false,
178 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
179 ],
180 [
181 'tables' => [
182 'archive',
183 'actor_ar_user' => 'actor',
184 'comment_ar_comment' => 'comment',
185 ],
186 'fields' => array_merge(
187 $this->getArchiveQueryFields( true ),
188 $this->getNewActorQueryFields( 'ar' ),
189 $this->getNewCommentQueryFields( 'ar' )
190 ),
191 'joins' => [
192 'comment_ar_comment'
193 => [ 'JOIN', 'comment_ar_comment.comment_id = ar_comment_id' ],
194 'actor_ar_user' => [ 'JOIN', 'actor_ar_user.actor_id = ar_actor' ],
195 ],
196 ]
197 ];
198 }
199
200 public function provideQueryInfo() {
201 // TODO: more option variations
202 yield 'MCR, page, user, comment, actor' => [
203 [
204 'wgContentHandlerUseDB' => true,
205 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
206 ],
207 [ 'page', 'user' ],
208 [
209 'tables' => [
210 'revision',
211 'page',
212 'user',
213 'temp_rev_user' => 'revision_actor_temp',
214 'temp_rev_comment' => 'revision_comment_temp',
215 'actor_rev_user' => 'actor',
216 'comment_rev_comment' => 'comment',
217 ],
218 'fields' => array_merge(
219 $this->getRevisionQueryFields( false ),
220 $this->getPageQueryFields(),
221 $this->getUserQueryFields(),
222 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
223 $this->getNewCommentQueryFields( 'rev' )
224 ),
225 'joins' => [
226 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
227 'user' => [
228 'LEFT JOIN',
229 [ 'actor_rev_user.actor_user != 0', 'user_id = actor_rev_user.actor_user' ],
230 ],
231 'comment_rev_comment' => [
232 'JOIN',
233 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id',
234 ],
235 'actor_rev_user' => [
236 'JOIN',
237 'actor_rev_user.actor_id = temp_rev_user.revactor_actor',
238 ],
239 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
240 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
241 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
242 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
243 ],
244 ]
245 ];
246 yield 'MCR read-new, page, user, comment, actor' => [
247 [
248 'wgContentHandlerUseDB' => true,
249 'wgMultiContentRevisionSchemaMigrationStage'
250 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
251 ],
252 [ 'page', 'user' ],
253 [
254 'tables' => [
255 'revision',
256 'page',
257 'user',
258 'temp_rev_user' => 'revision_actor_temp',
259 'temp_rev_comment' => 'revision_comment_temp',
260 'actor_rev_user' => 'actor',
261 'comment_rev_comment' => 'comment',
262 ],
263 'fields' => array_merge(
264 $this->getRevisionQueryFields( false ),
265 $this->getPageQueryFields(),
266 $this->getUserQueryFields(),
267 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
268 $this->getNewCommentQueryFields( 'rev' )
269 ),
270 'joins' => [
271 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
272 'user' => [
273 'LEFT JOIN',
274 [
275 'actor_rev_user.actor_user != 0',
276 'user_id = actor_rev_user.actor_user',
277 ]
278 ],
279 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
280 'comment_rev_comment'
281 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
282 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
283 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
284 ],
285 ]
286 ];
287 yield 'MCR read-new' => [
288 [
289 'wgContentHandlerUseDB' => true,
290 'wgMultiContentRevisionSchemaMigrationStage'
291 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
292 ],
293 [ 'page', 'user' ],
294 [
295 'tables' => [
296 'revision',
297 'page',
298 'user',
299 'temp_rev_user' => 'revision_actor_temp',
300 'temp_rev_comment' => 'revision_comment_temp',
301 'actor_rev_user' => 'actor',
302 'comment_rev_comment' => 'comment',
303 ],
304 'fields' => array_merge(
305 $this->getRevisionQueryFields( false ),
306 $this->getPageQueryFields(),
307 $this->getUserQueryFields(),
308 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
309 $this->getNewCommentQueryFields( 'rev' )
310 ),
311 'joins' => [
312 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
313 'user' => [
314 'LEFT JOIN',
315 [
316 'actor_rev_user.actor_user != 0',
317 'user_id = actor_rev_user.actor_user'
318 ]
319 ],
320 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
321 'comment_rev_comment'
322 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
323 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
324 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
325 ],
326 ]
327 ];
328 yield 'MCR write-both/read-old' => [
329 [
330 'wgContentHandlerUseDB' => true,
331 'wgMultiContentRevisionSchemaMigrationStage'
332 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
333 ],
334 [],
335 [
336 'tables' => [
337 'revision',
338 'temp_rev_comment' => 'revision_comment_temp',
339 'comment_rev_comment' => 'comment',
340 'temp_rev_user' => 'revision_actor_temp',
341 'actor_rev_user' => 'actor',
342 ],
343 'fields' => array_merge(
344 $this->getRevisionQueryFields( true ),
345 $this->getContentHandlerQueryFields( 'rev' ),
346 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
347 $this->getNewCommentQueryFields( 'rev' )
348 ),
349 'joins' => [
350 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
351 'comment_rev_comment'
352 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
353 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
354 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
355 ],
356 ]
357 ];
358 yield 'MCR write-both/read-old, page, user' => [
359 [
360 'wgContentHandlerUseDB' => true,
361 'wgMultiContentRevisionSchemaMigrationStage'
362 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
363 ],
364 [ 'page', 'user' ],
365 [
366 'tables' => [
367 'revision',
368 'page',
369 'user',
370 'temp_rev_comment' => 'revision_comment_temp',
371 'comment_rev_comment' => 'comment',
372 'temp_rev_user' => 'revision_actor_temp',
373 'actor_rev_user' => 'actor',
374 ],
375 'fields' => array_merge(
376 $this->getRevisionQueryFields( true ),
377 $this->getContentHandlerQueryFields( 'rev' ),
378 $this->getUserQueryFields(),
379 $this->getPageQueryFields(),
380 $this->getNewActorQueryFields( 'rev', 'temp_rev_user.revactor_actor' ),
381 $this->getNewCommentQueryFields( 'rev' )
382 ),
383 'joins' => [
384 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
385 'user' => [
386 'LEFT JOIN',
387 [
388 'actor_rev_user.actor_user != 0',
389 'user_id = actor_rev_user.actor_user',
390 ]
391 ],
392 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
393 'comment_rev_comment'
394 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
395 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
396 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
397 ],
398 ]
399 ];
400 yield 'pre-MCR' => [
401 [
402 'wgContentHandlerUseDB' => true,
403 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
404 ],
405 [],
406 [
407 'tables' => [
408 'revision',
409 'temp_rev_comment' => 'revision_comment_temp',
410 'comment_rev_comment' => 'comment',
411 'temp_rev_user' => 'revision_actor_temp',
412 'actor_rev_user' => 'actor',
413 ],
414 'fields' => array_merge(
415 $this->getRevisionQueryFields( true ),
416 $this->getContentHandlerQueryFields( 'rev' ),
417 $this->getNewActorQueryFields( 'rev', true ),
418 $this->getNewCommentQueryFields( 'rev' )
419 ),
420 'joins' => [
421 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
422 'comment_rev_comment'
423 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
424 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
425 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
426 ],
427 ]
428 ];
429 yield 'pre-MCR, page, user' => [
430 [
431 'wgContentHandlerUseDB' => true,
432 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
433 ],
434 [ 'page', 'user' ],
435 [
436 'tables' => [
437 'revision', 'page', 'user',
438 'temp_rev_comment' => 'revision_comment_temp',
439 'comment_rev_comment' => 'comment',
440 'temp_rev_user' => 'revision_actor_temp',
441 'actor_rev_user' => 'actor',
442 ],
443 'fields' => array_merge(
444 $this->getRevisionQueryFields( true ),
445 $this->getContentHandlerQueryFields( 'rev' ),
446 $this->getPageQueryFields(),
447 $this->getUserQueryFields(),
448 $this->getNewActorQueryFields( 'rev', true ),
449 $this->getNewCommentQueryFields( 'rev' )
450 ),
451 'joins' => [
452 'page' => [ 'JOIN', [ 'page_id = rev_page' ] ],
453 'user' => [ 'LEFT JOIN', [
454 'actor_rev_user.actor_user != 0',
455 'user_id = actor_rev_user.actor_user',
456 ] ],
457 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
458 'comment_rev_comment'
459 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
460 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
461 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
462 ],
463 ]
464 ];
465 yield 'pre-MCR, no model' => [
466 [
467 'wgContentHandlerUseDB' => false,
468 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
469 ],
470 [],
471 [
472 'tables' => [
473 'revision',
474 'temp_rev_comment' => 'revision_comment_temp',
475 'comment_rev_comment' => 'comment',
476 'temp_rev_user' => 'revision_actor_temp',
477 'actor_rev_user' => 'actor',
478 ],
479 'fields' => array_merge(
480 $this->getRevisionQueryFields( true ),
481 $this->getNewActorQueryFields( 'rev', true ),
482 $this->getNewCommentQueryFields( 'rev' )
483 ),
484 'joins' => [
485 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
486 'comment_rev_comment'
487 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
488 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
489 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
490 ],
491 ],
492 ];
493 yield 'pre-MCR, no model, page' => [
494 [
495 'wgContentHandlerUseDB' => false,
496 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
497 ],
498 [ 'page' ],
499 [
500 'tables' => [
501 'revision', 'page',
502 'temp_rev_comment' => 'revision_comment_temp',
503 'comment_rev_comment' => 'comment',
504 'temp_rev_user' => 'revision_actor_temp',
505 'actor_rev_user' => 'actor',
506 ],
507 'fields' => array_merge(
508 $this->getRevisionQueryFields( true ),
509 $this->getPageQueryFields(),
510 $this->getNewActorQueryFields( 'rev', true ),
511 $this->getNewCommentQueryFields( 'rev' )
512 ),
513 'joins' => [
514 'page' => [ 'JOIN', [ 'page_id = rev_page' ], ],
515 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
516 'comment_rev_comment'
517 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
518 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
519 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
520 ],
521 ],
522 ];
523 yield 'pre-MCR, no model, user' => [
524 [
525 'wgContentHandlerUseDB' => false,
526 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
527 ],
528 [ 'user' ],
529 [
530 'tables' => [
531 'revision', 'user',
532 'temp_rev_comment' => 'revision_comment_temp',
533 'comment_rev_comment' => 'comment',
534 'temp_rev_user' => 'revision_actor_temp',
535 'actor_rev_user' => 'actor',
536 ],
537 'fields' => array_merge(
538 $this->getRevisionQueryFields( true ),
539 $this->getUserQueryFields(),
540 $this->getNewActorQueryFields( 'rev', true ),
541 $this->getNewCommentQueryFields( 'rev' )
542 ),
543 'joins' => [
544 'user' => [ 'LEFT JOIN', [
545 'actor_rev_user.actor_user != 0',
546 'user_id = actor_rev_user.actor_user',
547 ] ],
548 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
549 'comment_rev_comment'
550 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
551 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
552 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
553 ],
554 ],
555 ];
556 yield 'pre-MCR, no model, text' => [
557 [
558 'wgContentHandlerUseDB' => false,
559 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
560 ],
561 [ 'text' ],
562 [
563 'tables' => [
564 'revision', 'text',
565 'temp_rev_comment' => 'revision_comment_temp',
566 'comment_rev_comment' => 'comment',
567 'temp_rev_user' => 'revision_actor_temp',
568 'actor_rev_user' => 'actor',
569 ],
570 'fields' => array_merge(
571 $this->getRevisionQueryFields( true ),
572 $this->getTextQueryFields(),
573 $this->getNewActorQueryFields( 'rev', true ),
574 $this->getNewCommentQueryFields( 'rev' )
575 ),
576 'joins' => [
577 'text' => [ 'JOIN', [ 'rev_text_id=old_id' ] ],
578 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
579 'comment_rev_comment'
580 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
581 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
582 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
583 ],
584 ],
585 ];
586 yield 'pre-MCR, no model, text, page, user' => [
587 [
588 'wgContentHandlerUseDB' => false,
589 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_OLD,
590 ],
591 [ 'text', 'page', 'user' ],
592 [
593 'tables' => [
594 'revision', 'page', 'user', 'text',
595 'temp_rev_comment' => 'revision_comment_temp',
596 'comment_rev_comment' => 'comment',
597 'temp_rev_user' => 'revision_actor_temp',
598 'actor_rev_user' => 'actor',
599 ],
600 'fields' => array_merge(
601 $this->getRevisionQueryFields( true ),
602 $this->getPageQueryFields(),
603 $this->getUserQueryFields(),
604 $this->getTextQueryFields(),
605 $this->getNewActorQueryFields( 'rev', true ),
606 $this->getNewCommentQueryFields( 'rev' )
607 ),
608 'joins' => [
609 'page' => [
610 'JOIN',
611 [ 'page_id = rev_page' ],
612 ],
613 'user' => [
614 'LEFT JOIN',
615 [
616 'actor_rev_user.actor_user != 0',
617 'user_id = actor_rev_user.actor_user',
618 ],
619 ],
620 'text' => [
621 'JOIN',
622 [ 'rev_text_id=old_id' ],
623 ],
624 'temp_rev_comment' => [ 'JOIN', 'temp_rev_comment.revcomment_rev = rev_id' ],
625 'comment_rev_comment'
626 => [ 'JOIN', 'comment_rev_comment.comment_id = temp_rev_comment.revcomment_comment_id' ],
627 'temp_rev_user' => [ 'JOIN', 'temp_rev_user.revactor_rev = rev_id' ],
628 'actor_rev_user' => [ 'JOIN', 'actor_rev_user.actor_id = temp_rev_user.revactor_actor' ],
629 ],
630 ],
631 ];
632 }
633
634 public function provideSlotsQueryInfo() {
635 yield 'MCR, no options' => [
636 [
637 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
638 ],
639 [],
640 [
641 'tables' => [
642 'slots'
643 ],
644 'fields' => [
645 'slot_revision_id',
646 'slot_content_id',
647 'slot_origin',
648 'slot_role_id',
649 ],
650 'joins' => [],
651 ]
652 ];
653 yield 'MCR, role option' => [
654 [
655 'wgMultiContentRevisionSchemaMigrationStage' => SCHEMA_COMPAT_NEW,
656 ],
657 [ 'role' ],
658 [
659 'tables' => [
660 'slots',
661 'slot_roles',
662 ],
663 'fields' => [
664 'slot_revision_id',
665 'slot_content_id',
666 'slot_origin',
667 'slot_role_id',
668 'role_name',
669 ],
670 'joins' => [
671 'slot_roles' => [ 'LEFT JOIN', [ 'slot_role_id = role_id' ] ],
672 ],
673 ]
674 ];
675 yield 'MCR read-new, content option' => [
676 [
677 'wgMultiContentRevisionSchemaMigrationStage'
678 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
679 ],
680 [ 'content' ],
681 [
682 'tables' => [
683 'slots',
684 'content',
685 ],
686 'fields' => [
687 'slot_revision_id',
688 'slot_content_id',
689 'slot_origin',
690 'slot_role_id',
691 'content_size',
692 'content_sha1',
693 'content_address',
694 'content_model',
695 ],
696 'joins' => [
697 'content' => [ 'JOIN', [ 'slot_content_id = content_id' ] ],
698 ],
699 ]
700 ];
701 yield 'MCR read-new, content and model options' => [
702 [
703 'wgMultiContentRevisionSchemaMigrationStage'
704 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_NEW,
705 ],
706 [ 'content', 'model' ],
707 [
708 'tables' => [
709 'slots',
710 'content',
711 'content_models',
712 ],
713 'fields' => [
714 'slot_revision_id',
715 'slot_content_id',
716 'slot_origin',
717 'slot_role_id',
718 'content_size',
719 'content_sha1',
720 'content_address',
721 'content_model',
722 'model_name',
723 ],
724 'joins' => [
725 'content' => [ 'JOIN', [ 'slot_content_id = content_id' ] ],
726 'content_models' => [ 'LEFT JOIN', [ 'content_model = model_id' ] ],
727 ],
728 ]
729 ];
730
731 $db = wfGetDB( DB_REPLICA );
732
733 yield 'MCR write-both/read-old' => [
734 [
735 'wgMultiContentRevisionSchemaMigrationStage'
736 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
737 ],
738 [],
739 [
740 'tables' => [
741 'revision',
742 ],
743 'fields' => array_merge(
744 [
745 'slot_revision_id' => 'rev_id',
746 'slot_content_id' => 'NULL',
747 'slot_origin' => 'rev_id',
748 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
749 ]
750 ),
751 'joins' => [],
752 ]
753 ];
754 yield 'MCR write-both/read-old, content' => [
755 [
756 'wgMultiContentRevisionSchemaMigrationStage'
757 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
758 ],
759 [ 'content' ],
760 [
761 'tables' => [
762 'revision',
763 ],
764 'fields' => array_merge(
765 [
766 'slot_revision_id' => 'rev_id',
767 'slot_content_id' => 'NULL',
768 'slot_origin' => 'rev_id',
769 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
770 'content_size' => 'rev_len',
771 'content_sha1' => 'rev_sha1',
772 'content_address' => $db->buildConcat( [
773 $db->addQuotes( 'tt:' ), 'rev_text_id' ] ),
774 'rev_text_id' => 'rev_text_id',
775 'model_name' => 'rev_content_model',
776 ]
777 ),
778 'joins' => [],
779 ]
780 ];
781 yield 'MCR write-both/read-old, content, model, role' => [
782 [
783 'wgMultiContentRevisionSchemaMigrationStage'
784 => SCHEMA_COMPAT_WRITE_BOTH | SCHEMA_COMPAT_READ_OLD,
785 ],
786 [ 'content', 'model', 'role' ],
787 [
788 'tables' => [
789 'revision',
790 ],
791 'fields' => array_merge(
792 [
793 'slot_revision_id' => 'rev_id',
794 'slot_content_id' => 'NULL',
795 'slot_origin' => 'rev_id',
796 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
797 'content_size' => 'rev_len',
798 'content_sha1' => 'rev_sha1',
799 'content_address' => $db->buildConcat( [
800 $db->addQuotes( 'tt:' ), 'rev_text_id' ] ),
801 'rev_text_id' => 'rev_text_id',
802 'model_name' => 'rev_content_model',
803 ]
804 ),
805 'joins' => [],
806 ]
807 ];
808 yield 'pre-MCR' => [
809 [
810 'wgMultiContentRevisionSchemaMigrationStage'
811 => SCHEMA_COMPAT_OLD,
812 ],
813 [],
814 [
815 'tables' => [
816 'revision',
817 ],
818 'fields' => array_merge(
819 [
820 'slot_revision_id' => 'rev_id',
821 'slot_content_id' => 'NULL',
822 'slot_origin' => 'rev_id',
823 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
824 ]
825 ),
826 'joins' => [],
827 ]
828 ];
829 yield 'pre-MCR, content' => [
830 [
831 'wgMultiContentRevisionSchemaMigrationStage'
832 => SCHEMA_COMPAT_OLD,
833 ],
834 [ 'content' ],
835 [
836 'tables' => [
837 'revision',
838 ],
839 'fields' => array_merge(
840 [
841 'slot_revision_id' => 'rev_id',
842 'slot_content_id' => 'NULL',
843 'slot_origin' => 'rev_id',
844 'role_name' => $db->addQuotes( SlotRecord::MAIN ),
845 'content_size' => 'rev_len',
846 'content_sha1' => 'rev_sha1',
847 'content_address' =>
848 $db->buildConcat( [ $db->addQuotes( 'tt:' ), 'rev_text_id' ] ),
849 'rev_text_id' => 'rev_text_id',
850 'model_name' => 'rev_content_model',
851 ]
852 ),
853 'joins' => [],
854 ]
855 ];
856 }
857
858 /**
859 * @covers Revision::getArchiveQueryInfo
860 * @dataProvider provideArchiveQueryInfo
861 */
862 public function testRevisionGetArchiveQueryInfo( $migrationStageSettings, $expected ) {
863 $this->setMwGlobals( $migrationStageSettings );
864
865 $queryInfo = Revision::getArchiveQueryInfo();
866 $this->assertQueryInfoEquals( $expected, $queryInfo );
867 }
868
869 /**
870 * @covers Revision::getQueryInfo
871 * @dataProvider provideQueryInfo
872 */
873 public function testRevisionGetQueryInfo( $migrationStageSettings, $options, $expected ) {
874 $this->setMwGlobals( $migrationStageSettings );
875
876 $queryInfo = Revision::getQueryInfo( $options );
877 $this->assertQueryInfoEquals( $expected, $queryInfo );
878 }
879
880 /**
881 * @dataProvider provideQueryInfo
882 * @covers \MediaWiki\Revision\RevisionStore::getQueryInfo
883 */
884 public function testRevisionStoreGetQueryInfo( $migrationStageSettings, $options, $expected ) {
885 $this->setMwGlobals( $migrationStageSettings );
886
887 $store = MediaWikiServices::getInstance()->getRevisionStore();
888
889 $queryInfo = $store->getQueryInfo( $options );
890 $this->assertQueryInfoEquals( $expected, $queryInfo );
891 }
892
893 /**
894 * @dataProvider provideSlotsQueryInfo
895 * @covers \MediaWiki\Revision\RevisionStore::getSlotsQueryInfo
896 */
897 public function testRevisionStoreGetSlotsQueryInfo(
898 $migrationStageSettings,
899 $options,
900 $expected
901 ) {
902 $this->setMwGlobals( $migrationStageSettings );
903
904 $store = MediaWikiServices::getInstance()->getRevisionStore();
905
906 $queryInfo = $store->getSlotsQueryInfo( $options );
907 $this->assertQueryInfoEquals( $expected, $queryInfo );
908 }
909
910 /**
911 * @dataProvider provideArchiveQueryInfo
912 * @covers \MediaWiki\Revision\RevisionStore::getArchiveQueryInfo
913 */
914 public function testRevisionStoreGetArchiveQueryInfo( $migrationStageSettings, $expected ) {
915 $this->setMwGlobals( $migrationStageSettings );
916
917 $store = MediaWikiServices::getInstance()->getRevisionStore();
918
919 $queryInfo = $store->getArchiveQueryInfo();
920 $this->assertQueryInfoEquals( $expected, $queryInfo );
921 }
922
923 private function assertQueryInfoEquals( $expected, $queryInfo ) {
924 $this->assertArrayEqualsIgnoringIntKeyOrder(
925 $expected['tables'],
926 $queryInfo['tables'],
927 'tables'
928 );
929 $this->assertArrayEqualsIgnoringIntKeyOrder(
930 $expected['fields'],
931 $queryInfo['fields'],
932 'fields'
933 );
934 $this->assertArrayEqualsIgnoringIntKeyOrder(
935 $expected['joins'],
936 $queryInfo['joins'],
937 'joins'
938 );
939 }
940
941 /**
942 * Assert that the two arrays passed are equal, ignoring the order of the values that integer
943 * keys.
944 *
945 * Note: Failures of this assertion can be slightly confusing as the arrays are actually
946 * split into a string key array and an int key array before assertions occur.
947 *
948 * @param array $expected
949 * @param array $actual
950 */
951 private function assertArrayEqualsIgnoringIntKeyOrder(
952 array $expected,
953 array $actual,
954 $message = null
955 ) {
956 $this->objectAssociativeSort( $expected );
957 $this->objectAssociativeSort( $actual );
958
959 // Separate the int key values from the string key values so that assertion failures are
960 // easier to understand.
961 $expectedIntKeyValues = [];
962 $actualIntKeyValues = [];
963
964 // Remove all int keys and re add them at the end after sorting by value
965 // This will result in all int keys being in the same order with same ints at the end of
966 // the array
967 foreach ( $expected as $key => $value ) {
968 if ( is_int( $key ) ) {
969 unset( $expected[$key] );
970 $expectedIntKeyValues[] = $value;
971 }
972 }
973 foreach ( $actual as $key => $value ) {
974 if ( is_int( $key ) ) {
975 unset( $actual[$key] );
976 $actualIntKeyValues[] = $value;
977 }
978 }
979
980 $this->objectAssociativeSort( $expected );
981 $this->objectAssociativeSort( $actual );
982
983 $this->objectAssociativeSort( $expectedIntKeyValues );
984 $this->objectAssociativeSort( $actualIntKeyValues );
985
986 $this->assertEquals( $expected, $actual, $message );
987 $this->assertEquals( $expectedIntKeyValues, $actualIntKeyValues, $message );
988 }
989
990 }