Completed
Push — master ( 314506...335380 )
by mw
100:54 queued 62:54
created

includes/storage/SQLStore/SMW_SQLStore3.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
use SMW\DataTypeRegistry;
4
use SMW\DIConcept;
5
use SMW\DIProperty;
6
use SMW\DIWikiPage;
7
use SMW\SemanticData;
8
use SMW\SQLStore\PropertyTableInfoFetcher;
9
use SMW\SQLStore\SQLStoreFactory;
10
use SMW\SQLStore\TableDefinition;
11
12
/**
13
 * SQL-based implementation of SMW's storage abstraction layer.
14
 *
15
 * @author Markus Krötzsch
16
 * @author Jeroen De Dauw
17
 * @author Nischay Nahata
18
 *
19
 * @since 1.8
20
 *
21
 * @ingroup SMWStore
22
 */
23
24
// The use of the following constants is explained in SMWSQLStore3::setup():
25
define( 'SMW_SQL3_SMWIW_OUTDATED', ':smw' ); // virtual "interwiki prefix" for old-style special SMW objects (no longer used)
26
define( 'SMW_SQL3_SMWREDIIW', ':smw-redi' ); // virtual "interwiki prefix" for SMW objects that are redirected
27
define( 'SMW_SQL3_SMWBORDERIW', ':smw-border' ); // virtual "interwiki prefix" separating very important pre-defined properties from the rest
28
define( 'SMW_SQL3_SMWINTDEFIW', ':smw-intprop' ); // virtual "interwiki prefix" marking internal (invisible) predefined properties
29
define( 'SMW_SQL3_SMWDELETEIW', ':smw-delete' ); // virtual "interwiki prefix" marking a deleted subject, see #1100
30
31
/**
32
 * Storage access class for using the standard MediaWiki SQL database for
33
 * keeping semantic data.
34
 *
35
 * @note Regarding the use of interwiki links in the store, there is currently
36
 * no support for storing semantic data about interwiki objects, and hence
37
 * queries that involve interwiki objects really make sense only for them
38
 * occurring in object positions. Most methods still use the given input
39
 * interwiki text as a simple way to filter out results that may be found if an
40
 * interwiki object is given but a local object of the same name exists. It is
41
 * currently not planned to support things like interwiki reuse of properties.
42
 *
43
 * @since 1.8
44
 * @ingroup SMWStore
45
 */
46
class SMWSQLStore3 extends SMWStore {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
47
48
	/**
49
	 * Specifies the border limit (upper bound) for pre-defined properties used
50
	 * in the ID_TABLE
51
	 *
52
	 * When changing the upper bound, please make sure to copy the current upper
53
	 * bound as legcy to the SMWSQLStore3SetupHandlers::checkPredefinedPropertyBorder
54
	 */
55
	const FIXED_PROPERTY_ID_UPPERBOUND = 50;
56
57
	/**
58
	 * Name of the table to store the concept cache in.
59
	 *
60
	 * @note This should never change. If it is changed, the concept caches
61
	 * will appear empty until they are recomputed.
62
	 */
63
	const CONCEPT_CACHE_TABLE = 'smw_concept_cache';
64
	const CONCEPT_TABLE = 'smw_fpt_conc';
65
66
	/**
67
	 * Name of the table to store the concept cache in.
68
	 *
69
	 * @note This should never change, but if it does then its contents can
70
	 * simply be rebuilt by running the setup.
71
	 */
72
	const PROPERTY_STATISTICS_TABLE = 'smw_prop_stats';
73
74
	/**
75
	 * Name of the table that manages the query dependency links
76
	 */
77
	const QUERY_LINKS_TABLE = 'smw_query_links';
78
79
	/**
80
	 * Name of the table that manages the fulltext index
81
	 */
82
	const FT_SEARCH_TABLE = 'smw_ft_search';
83
84
	/**
85
	 * Name of the table that manages the Store IDs
86
	 */
87
	const ID_TABLE = 'smw_object_ids';
88
89
	/**
90
	 * @var SQLStoreFactory
91
	 */
92
	private $factory;
93
94
	/**
95
	 * @var PropertyTableInfoFetcher|null
96
	 */
97
	private $propertyTableInfoFetcher = null;
98
99
	/**
100
	 * @var PropertyTableIdReferenceFinder
101
	 */
102
	private $propertyTableIdReferenceFinder;
103
104
	/**
105
	 * @var RequestOptionsProcessor|null
106
	 */
107
	private $requestOptionsProcessor = null;
108
109
	/**
110
	 * @var DataItemHandlerDispatcher
111
	 */
112
	private $dataItemHandlerDispatcher;
113
114
	/**
115
	 * @var EntityLookup
116
	 */
117
	private $entityLookup;
118
119
	/**
120
	 * Object to access the SMW IDs table.
121
	 *
122
	 * @since 1.8
123
	 * @var SMWSql3SmwIds
124
	 */
125
	public $smwIds;
126
127
	/**
128
	 * The reader object used by this store. Initialized by getReader()
129
	 * Always access using getReader()
130
	 *
131
	 * @since 1.8
132
	 * @var SMWSQLStore3Readers
133
	 */
134
	protected $reader = false;
135
136
	/**
137
	 * The writer object used by this store. Initialized by getWriter(),
138
	 * which is the only way in which it should be accessed.
139
	 *
140
	 * @since 1.8
141
	 * @var SMWSQLStore3Writers
142
	 */
143
	protected $writer = false;
144
145
	/**
146
	 * The SetupHandler object used by this store. Initialized by getSetupHandler(),
147
	 * which is the only way in which it should be accessed.
148
	 *
149
	 * @since 1.8
150
	 * @var SMWSQLStore3SetupHandlers
151
	 */
152
	protected $setupHandler = false;
153
154
	/**
155
	 * Cache for SemanticData objects, indexed by SMW ID.
156
	 *
157
	 * @todo In the future, the cache should be managed by a helper class.
158
	 *
159
	 * @since 1.8
160
	 * @var array
161
	 */
162
	public $m_semdata = array();
163
164
	/**
165
	 * Like SMWSQLStore3::m_semdata, but containing flags indicating
166
	 * completeness of the SemanticData objs.
167
	 *
168
	 * @since 1.8
169
	 * @var array
170
	 */
171
	public $m_sdstate = array();
172
173
	/**
174
	 * @since 1.8
175
	 */
176 16
	public function __construct() {
177 16
		$this->factory = new SQLStoreFactory( $this );
178 16
		$this->smwIds = $this->factory->newIdTableManager();
179 16
	}
180
181
	/**
182
	 * Get an object of the dataitem handler from the dataitem provided.
183
	 *
184
	 * @since 1.8
185
	 * @param integer $diType
186
	 *
187
	 * @return SMWDIHandler
188
	 * @throws RuntimeException if no handler exists for the given type
189
	 */
190 252
	public function getDataItemHandlerForDIType( $diType ) {
191
192 252
		if ( $this->dataItemHandlerDispatcher === null ) {
193 5
			$this->dataItemHandlerDispatcher = $this->factory->newDataItemHandlerDispatcher( $this );
194
		}
195
196 252
		return $this->dataItemHandlerDispatcher->getHandlerByType( $diType );
197
	}
198
199
///// Reading methods /////
200
201 260
	public function getReader() {
202 260
		if( $this->reader == false ) {
203 5
			$this->reader = new SMWSQLStore3Readers( $this );//Initialize if not done already
204
		}
205
206 260
		return $this->reader;
207
	}
208
209 221
	public function getSemanticData( DIWikiPage $subject, $filter = false ) {
210 221
		return $this->getEntityLookup()->getSemanticData( $subject, $filter );
211
	}
212
213
	/**
214
	 * @param mixed $subject
215
	 * @param DIProperty $property
216
	 * @param null $requestOptions
217
	 *
218
	 * @return SMWDataItem[]
219
	 */
220 219
	public function getPropertyValues( $subject, DIProperty $property, $requestOptions = null ) {
221 219
		return $this->getEntityLookup()->getPropertyValues(	$subject, $property, $requestOptions );
222
	}
223
224 2
	public function getProperties( DIWikiPage $subject, $requestOptions = null ) {
225 2
		return $this->getEntityLookup()->getProperties( $subject, $requestOptions );
226
	}
227
228 155
	public function getPropertySubjects( DIProperty $property, $dataItem, $requestOptions = null ) {
229 155
		return $this->getEntityLookup()->getPropertySubjects( $property, $dataItem, $requestOptions );
230
	}
231
232 149
	public function getAllPropertySubjects( DIProperty $property, $requestoptions = null ) {
233 149
		return $this->getEntityLookup()->getAllPropertySubjects( $property, $requestoptions );
234
	}
235
236 17
	public function getInProperties( SMWDataItem $value, $requestoptions = null ) {
237 17
		return $this->getEntityLookup()->getInProperties( $value, $requestoptions );
238
	}
239
240
241
///// Writing methods /////
242
243
244 250
	public function getWriter() {
245 250
		if( $this->writer == false ) {
246 4
			$this->writer = new SMWSQLStore3Writers( $this );//Initialize if not done already
247
		}
248
249 250
		return $this->writer;
250
	}
251
252 230
	public function deleteSubject( Title $title ) {
253
254 230
		$subject = DIWikiPage::newFromTitle( $title );
255
256 230
		$this->getEntityLookup()->resetCacheBy(
257
			$subject
258
		);
259
260 230
		$this->getWriter()->deleteSubject( $title );
261
262 230
		$this->doDeferredCachedListLookupUpdate(
263
			$subject
264
		);
265 230
	}
266
267 242
	protected function doDataUpdate( SemanticData $semanticData ) {
268
269 242
		$this->getEntityLookup()->resetCacheBy(
270 242
			$semanticData->getSubject()
271
		);
272
273 242
		$this->getWriter()->doDataUpdate( $semanticData );
274
275 242
		$this->doDeferredCachedListLookupUpdate(
276 242
			$semanticData->getSubject()
277
		);
278 242
	}
279
280 25
	public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) {
281
282 25
		$this->getEntityLookup()->resetCacheBy(
283 25
			DIWikiPage::newFromTitle( $oldtitle )
284
		);
285
286 25
		$this->getEntityLookup()->resetCacheBy(
287 25
			DIWikiPage::newFromTitle( $newtitle )
288
		);
289
290 25
		$this->getWriter()->changeTitle( $oldtitle, $newtitle, $pageid, $redirid );
291
292 25
		$this->doDeferredCachedListLookupUpdate(
293 25
			DIWikiPage::newFromTitle( $oldtitle )
294
		);
295 25
	}
296
297 250
	private function doDeferredCachedListLookupUpdate( DIWikiPage $subject ) {
298
299 250
		if ( $subject->getNamespace() !== SMW_NS_PROPERTY ) {
300 246
			return null;
301
		}
302
303 164
		$deferredCallableUpdate = $this->factory->newDeferredCallableCachedListLookupUpdate();
304 164
		$deferredCallableUpdate->setOrigin( __METHOD__ );
305 164
		$deferredCallableUpdate->pushUpdate();
306 164
	}
307
308
///// Query answering /////
309
310
	/**
311
	 * @note Move hooks to the base class in 3.*
312
	 *
313
	 * @see SMWStore::fetchQueryResult
314
	 *
315
	 * @since 1.8
316
	 * @param SMWQuery $query
317
	 * @return SMWQueryResult|string|integer depends on $query->querymode
318
	 */
319 162
	public function getQueryResult( SMWQuery $query ) {
320
321 162
		$result = null;
322 162
		$start = microtime( true );
323
324 162
		if ( \Hooks::run( 'SMW::Store::BeforeQueryResultLookupComplete', array( $this, $query, &$result ) ) ) {
325 161
			$result = $this->fetchQueryResult( $query );
326
		}
327
328 162
		\Hooks::run( 'SMW::SQLStore::AfterQueryResultLookupComplete', array( $this, &$result ) );
329 162
		\Hooks::run( 'SMW::Store::AfterQueryResultLookupComplete', array( $this, &$result ) );
330
331 162
		$query->setOption( SMWQuery::PROC_QUERY_TIME, microtime( true ) - $start );
332
333 162
		return $result;
334
	}
335
336 158
	protected function fetchQueryResult( SMWQuery $query ) {
337 158
		return $this->factory->newSlaveQueryEngine()->getQueryResult( $query );
338
	}
339
340
///// Special page functions /////
341
342
	/**
343
	 * @param RequestOptions|null $requestOptions
344
	 *
345
	 * @return CachedListLookup
346
	 */
347 1
	public function getPropertiesSpecial( $requestOptions = null ) {
348 1
		return $this->factory->newPropertyUsageCachedListLookup( $requestOptions );
349
	}
350
351
	/**
352
	 * @param RequestOptions|null $requestOptions
353
	 *
354
	 * @return CachedListLookup
355
	 */
356 2
	public function getUnusedPropertiesSpecial( $requestOptions = null ) {
357 2
		return $this->factory->newUnusedPropertyCachedListLookup( $requestOptions );
358
	}
359
360
	/**
361
	 * @param RequestOptions|null $requestOptions
362
	 *
363
	 * @return CachedListLookup
364
	 */
365 2
	public function getWantedPropertiesSpecial( $requestOptions = null ) {
366 2
		return $this->factory->newUndeclaredPropertyCachedListLookup( $requestOptions );
367
	}
368
369 1
	public function getStatistics() {
370 1
		return $this->factory->newUsageStatisticsCachedListLookup()->fetchList();
371
	}
372
373
374
///// Setup store /////
375
376 3
	public function getSetupHandler() {
377 3
		if( $this->setupHandler == false ) {
378
			$this->setupHandler = new SMWSQLStore3SetupHandlers( $this );//Initialize if not done already
379
		}
380
381 3
		return $this->setupHandler;
382
	}
383
384 3
	public function setup( $verbose = true ) {
385 3
		return $this->getSetupHandler()->setup( $verbose );
386
	}
387
388 1
	public function drop( $verbose = true ) {
389 1
		return $this->getSetupHandler()->drop( $verbose );
390
	}
391
392 7
	public function refreshData( &$id, $count, $namespaces = false, $usejobs = true ) {
393
394 7
		$entityRebuildDispatcher = $this->factory->newEntityRebuildDispatcher();
395
396 7
		$entityRebuildDispatcher->setDispatchRangeLimit( $count );
397 7
		$entityRebuildDispatcher->setRestrictionToNamespaces( $namespaces );
398 7
		$entityRebuildDispatcher->useJobQueueScheduler( $usejobs );
399
400 7
		return $entityRebuildDispatcher;
401
	}
402
403
404
///// Concept caching /////
405
406
	/**
407
	 * Refresh the concept cache for the given concept.
408
	 *
409
	 * @since 1.8
410
	 * @param Title $concept
411
	 * @return array of error strings (empty if no errors occurred)
412
	 */
413 5
	public function refreshConceptCache( Title $concept ) {
414 5
		return $this->factory->newMasterConceptCache()->refreshConceptCache( $concept );
415
	}
416
417
	/**
418
	 * Delete the concept cache for the given concept.
419
	 *
420
	 * @since 1.8
421
	 * @param Title $concept
422
	 */
423 6
	public function deleteConceptCache( $concept ) {
424 6
		$this->factory->newMasterConceptCache()->deleteConceptCache( $concept );
425 6
	}
426
427
	/**
428
	 * Return status of the concept cache for the given concept as an array
429
	 * with key 'status' ('empty': not cached, 'full': cached, 'no': not
430
	 * cachable). If status is not 'no', the array also contains keys 'size'
431
	 * (query size), 'depth' (query depth), 'features' (query features). If
432
	 * status is 'full', the array also contains keys 'date' (timestamp of
433
	 * cache), 'count' (number of results in cache).
434
	 *
435
	 * @since 1.8
436
	 * @param Title|SMWWikiPageValue $concept
437
	 *
438
	 * @return DIConcept|null
439
	 */
440 5
	public function getConceptCacheStatus( $concept ) {
441 5
		return $this->factory->newSlaveConceptCache()->getStatus( $concept );
442
	}
443
444
445
///// Helper methods, mostly protected /////
446
447
	/**
448
	 * @see RequestOptionsProcessor::getSQLOptionsFrom
449
	 *
450
	 * @since 1.8
451
	 *
452
	 * @param SMWRequestOptions|null $requestOptions
453
	 * @param string $valuecol
454
	 *
455
	 * @return array
456
	 */
457 190
	public function getSQLOptions( SMWRequestOptions $requestOptions = null, $valueCol = '' ) {
458 190
		return $this->getRequestOptionsProcessor()->getSQLOptionsFrom( $requestOptions, $valueCol );
459
	}
460
461
	/**
462
	 * @see RequestOptionsProcessor::getSQLConditionsFrom
463
	 *
464
	 * @since 1.8
465
	 *
466
	 * @param SMWRequestOptions|null $requestOptions
467
	 * @param string $valueCol name of SQL column to which conditions apply
468
	 * @param string $labelCol name of SQL column to which string conditions apply, if any
469
	 * @param boolean $addAnd indicate whether the string should begin with " AND " if non-empty
470
	 *
471
	 * @return string
472
	 */
473 158
	public function getSQLConditions( SMWRequestOptions $requestOptions = null, $valueCol = '', $labelCol = '', $addAnd = true ) {
474 158
		return $this->getRequestOptionsProcessor()->getSQLConditionsFrom( $requestOptions, $valueCol, $labelCol, $addAnd );
475
	}
476
477
	/**
478
	 * @see RequestOptionsProcessor::applyRequestOptionsTo
479
	 *
480
	 * @since 1.8
481
	 *
482
	 * @param array $data array of SMWDataItem objects
483
	 * @param SMWRequestOptions|null $requestOptions
484
	 *
485
	 * @return SMWDataItem[]
486
	 */
487 180
	public function applyRequestOptions( array $data, SMWRequestOptions $requestOptions = null ) {
488 180
		return $this->getRequestOptionsProcessor()->applyRequestOptionsTo( $data, $requestOptions );
489
	}
490
491
	/**
492
	 * PropertyTableInfoFetcher::findTableIdForDataTypeTypeId
493
	 *
494
	 * @param string $typeid
495
	 *
496
	 * @return string
497
	 */
498 2
	public function findTypeTableId( $typeid ) {
499 2
		return $this->getPropertyTableInfoFetcher()->findTableIdForDataTypeTypeId( $typeid );
500
	}
501
502
	/**
503
	 * PropertyTableInfoFetcher::findTableIdForDataItemTypeId
504
	 *
505
	 * @param integer $dataItemId
506
	 *
507
	 * @return string
508
	 */
509
	public function findDiTypeTableId( $dataItemId ) {
510
		return $this->getPropertyTableInfoFetcher()->findTableIdForDataItemTypeId( $dataItemId );
511
	}
512
513
	/**
514
	 * PropertyTableInfoFetcher::findTableIdForProperty
515
	 *
516
	 * @param DIProperty $property
517
	 *
518
	 * @return string
519
	 */
520 238
	public function findPropertyTableID( DIProperty $property ) {
521 238
		return $this->getPropertyTableInfoFetcher()->findTableIdForProperty( $property );
522
	}
523
524
	/**
525
	 * Change an SMW page id across all relevant tables. The redirect table
526
	 * is also updated (without much effect if the change happended due to
527
	 * some redirect, since the table should not contain the id of the
528
	 * redirected page). If namespaces are given, then they are used to
529
	 * delete any entries that are limited to one particular namespace (e.g.
530
	 * only properties can be used as properties) instead of moving them.
531
	 *
532
	 * The id in the SMW IDs table is not touched.
533
	 *
534
	 * @note This method only changes internal page IDs in SMW. It does not
535
	 * assume any change in (title-related) data, as e.g. in a page move.
536
	 * Internal objects (subobject) do not need to be updated since they
537
	 * refer to the title of their parent page, not to its ID.
538
	 *
539
	 * @since 1.8
540
	 * @param integer $oldid numeric ID that is to be changed
541
	 * @param integer $newid numeric ID to which the records are to be changed
542
	 * @param integer $oldnamespace namespace of old id's page (-1 to ignore it)
543
	 * @param integer $newnamespace namespace of new id's page (-1 to ignore it)
544
	 * @param boolean $sdata stating whether to update subject references
545
	 * @param boolean $podata stating if to update property/object references
546
	 */
547 10
	public function changeSMWPageID( $oldid, $newid, $oldnamespace = -1,
548
				$newnamespace = -1, $sdata = true, $podata = true ) {
549
550 10
		$db = $this->getConnection( 'mw.db' );
551
552
		// Change all id entries in property tables:
553 10
		foreach ( $this->getPropertyTables() as $proptable ) {
554 10
			if ( $sdata && $proptable->usesIdSubject() ) {
555 10
				$db->update( $proptable->getName(), array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ );
556
			}
557
558 10
			if ( $podata ) {
559 10
				if ( ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_PROPERTY ) ) && ( !$proptable->isFixedPropertyTable() ) ) {
560 1
					if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_PROPERTY ) ) {
561 1
						$db->update( $proptable->getName(), array( 'p_id' => $newid ), array( 'p_id' => $oldid ), __METHOD__ );
562
					} else {
563
						$db->delete( $proptable->getName(), array( 'p_id' => $oldid ), __METHOD__ );
564
					}
565
				}
566
567 10
				foreach ( $proptable->getFields( $this ) as $fieldname => $type ) {
568 10
					if ( $type == 'p' ) {
569 10
						$db->update( $proptable->getName(), array( $fieldname => $newid ), array( $fieldname => $oldid ), __METHOD__ );
570
					}
571
				}
572
			}
573
		}
574
575
		// Change id entries in concept-related tables:
576 10
		if ( $sdata && ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_CONCEPT ) ) ) {
577
			if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_CONCEPT ) ) {
578
				$db->update( 'smw_fpt_conc', array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ );
579
				$db->update( self::CONCEPT_CACHE_TABLE, array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ );
580
			} else {
581
				$db->delete( 'smw_fpt_conc', array( 's_id' => $oldid ), __METHOD__ );
582
				$db->delete( self::CONCEPT_CACHE_TABLE, array( 's_id' => $oldid ), __METHOD__ );
583
			}
584
		}
585
586 10
		if ( $podata ) {
587 10
			$db->update( self::CONCEPT_CACHE_TABLE, array( 'o_id' => $newid ), array( 'o_id' => $oldid ), __METHOD__ );
588
		}
589 10
	}
590
591
	/**
592
	 * PropertyTableInfoFetcher::getPropertyTableDefinitions
593
	 *
594
	 * @return TableDefinition[]
595
	 */
596 255
	public function getPropertyTables() {
597 255
		return $this->getPropertyTableInfoFetcher()->getPropertyTableDefinitions();
598
	}
599
600
	/**
601
	 * Returns SMW Id object
602
	 *
603
	 * @since 1.9
604
	 *
605
	 * @return SMWSql3SmwIds
606
	 */
607 258
	public function getObjectIds() {
608 258
		return $this->smwIds;
609
	}
610
611
	/**
612
	 * Returns the statics table
613
	 *
614
	 * @since 1.9
615
	 *
616
	 * @return string
617
	 */
618 2
	public function getStatisticsTable() {
619 2
		return self::PROPERTY_STATISTICS_TABLE;
620
	}
621
622
	/**
623
	 * Resets internal objects
624
	 *
625
	 * @since 1.9.1.1
626
	 */
627 30
	public function clear() {
628 30
		parent::clear();
629 30
		$this->m_semdata = array();
630 30
		$this->m_sdstate = array();
631 30
		$this->propertyTableInfoFetcher = null;
632 30
		$this->getObjectIds()->clearCaches();
633 30
	}
634
635
	/**
636
	 * @since 2.1
637
	 *
638
	 * @param string $connectionTypeId
639
	 *
640
	 * @return \SMW\MediaWiki\Database
641
	 */
642 288
	public function getConnection( $connectionTypeId = 'mw.db' ) {
643 288
		return parent::getConnection( $connectionTypeId );
644
	}
645
646
	/**
647
	 * @since 2.2
648
	 *
649
	 * @return PropertyTableInfoFetcher
650
	 */
651 258
	public function getPropertyTableInfoFetcher() {
652
653 258
		if ( $this->propertyTableInfoFetcher === null ) {
654 237
			$this->propertyTableInfoFetcher = $this->factory->newPropertyTableInfoFetcher();
655
		}
656
657 258
		return $this->propertyTableInfoFetcher;
658
	}
659
660
	/**
661
	 * @since 2.4
662
	 *
663
	 * @return PropertyTableIdReferenceFinder
664
	 */
665 2
	public function getPropertyTableIdReferenceFinder() {
666
667 2
		if ( $this->propertyTableIdReferenceFinder === null ) {
668 1
			$this->propertyTableIdReferenceFinder = $this->factory->newPropertyTableIdReferenceFinder();
669
		}
670
671 2
		return $this->propertyTableIdReferenceFinder;
672
	}
673
674
	/**
675
	 * @return RequestOptionsProcessor
676
	 */
677 193
	private function getRequestOptionsProcessor() {
678
679 193
		if ( $this->requestOptionsProcessor === null ) {
680 1
			$this->requestOptionsProcessor = $this->factory->newRequestOptionsProcessor();
681
		}
682
683 193
		return $this->requestOptionsProcessor;
684
	}
685
686
	/**
687
	 * @return EntityLookup
688
	 */
689 263
	private function getEntityLookup() {
690
691 263
		if ( $this->entityLookup === null ) {
692 5
			$this->entityLookup = $this->factory->newEntityLookup();
693
		}
694
695 263
		return $this->entityLookup;
696
	}
697
698
}
699