Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php |
— | — | @@ -93,8 +93,8 @@ |
94 | 94 | public function refreshConceptCache( Title $concept ) { |
95 | 95 | global $smwgQMaxLimit, $smwgQConceptFeatures, $wgDBtype; |
96 | 96 | |
97 | | - $cid = $this->m_store->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '' ); |
98 | | - $cid_c = $this->m_store->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', false ); |
| 97 | + $cid = $this->m_store->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', '' ); |
| 98 | + $cid_c = $this->m_store->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', '', false ); |
99 | 99 | |
100 | 100 | if ( $cid != $cid_c ) { |
101 | 101 | $this->m_errors[] = "Skipping redirect concept."; |
— | — | @@ -162,7 +162,7 @@ |
163 | 163 | * @param $concept Title |
164 | 164 | */ |
165 | 165 | public function deleteConceptCache( $concept ) { |
166 | | - $cid = $this->m_store->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', false ); |
| 166 | + $cid = $this->m_store->getSMWPageID( $concept->getDBkey(), SMW_NS_CONCEPT, '', '', false ); |
167 | 167 | $this->m_dbs->delete( 'smw_conccache', array( 'o_id' => $cid ), 'SMW::refreshConceptCache' ); |
168 | 168 | $this->m_dbs->update( 'smw_conc2', array( 'cache_date' => null, 'cache_count' => null ), array( 's_id' => $cid ), 'SMW::refreshConceptCache' ); |
169 | 169 | } |
— | — | @@ -384,7 +384,7 @@ |
385 | 385 | $sortfields = implode( $qobj->sortfields, ',' ); |
386 | 386 | |
387 | 387 | $res = $this->m_dbs->select( $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from, |
388 | | - "DISTINCT $qobj->alias.smw_id AS id,$qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns,$qobj->alias.smw_iw AS iw,$qobj->alias.smw_sortkey AS sortkey" . |
| 388 | + "DISTINCT $qobj->alias.smw_id AS id,$qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns,$qobj->alias.smw_iw AS iw,$qobj->alias.smw_subobject AS so,$qobj->alias.smw_sortkey AS sortkey" . |
389 | 389 | ( $wgDBtype == 'postgres' ? ( ( $sortfields ? ',' : '' ) . $sortfields ) : '' ), |
390 | 390 | $qobj->where, 'SMW::getQueryResult', $sql_options ); |
391 | 391 | |
— | — | @@ -394,9 +394,9 @@ |
395 | 395 | |
396 | 396 | while ( ( $count < $query->getLimit() ) && ( $row = $this->m_dbs->fetchObject( $res ) ) ) { |
397 | 397 | $count++; |
398 | | - $v = new SMWDIWikiPage( $row->t, $row->ns, $row->iw ); |
| 398 | + $v = new SMWDIWikiPage( $row->t, $row->ns, $row->iw, $row->so ); |
399 | 399 | $qr[] = $v; |
400 | | - $this->m_store->cacheSMWPageID( $row->id, $row->t, $row->ns, $row->iw ); |
| 400 | + $this->m_store->cacheSMWPageID( $row->id, $row->t, $row->ns, $row->iw, $row->so ); |
401 | 401 | } |
402 | 402 | |
403 | 403 | if ( $this->m_dbs->fetchObject( $res ) ) { |
— | — | @@ -457,7 +457,7 @@ |
458 | 458 | $cquery->joinfield = array(); |
459 | 459 | |
460 | 460 | foreach ( $description->getCategories() as $cat ) { |
461 | | - $cid = $this->m_store->getSMWPageID( $cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki() ); |
| 461 | + $cid = $this->m_store->getSMWPageID( $cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki(), '' ); |
462 | 462 | if ( $cid != 0 ) { |
463 | 463 | $cquery->joinfield[] = $cid; |
464 | 464 | } |
— | — | @@ -477,7 +477,7 @@ |
478 | 478 | if ( $description->getDataItem() instanceof SMWDIWikiPage ) { |
479 | 479 | if ( $description->getComparator() == SMW_CMP_EQ ) { |
480 | 480 | $query->type = SMW_SQL2_VALUE; |
481 | | - $oid = $this->m_store->getSMWPageID( $description->getDataItem()->getDBkey(), $description->getDataItem()->getNamespace(), $description->getDataItem()->getInterwiki() ); |
| 481 | + $oid = $this->m_store->getSMWPageID( $description->getDataItem()->getDBkey(), $description->getDataItem()->getNamespace(), $description->getDataItem()->getInterwiki(), $description->getDataItem()->getSubobjectId() ); |
482 | 482 | $query->joinfield = array( $oid ); |
483 | 483 | } else { // Join with smw_ids needed for other comparators (apply to title string). |
484 | 484 | $query->jointable = 'smw_ids'; |
— | — | @@ -500,7 +500,7 @@ |
501 | 501 | } |
502 | 502 | } |
503 | 503 | } elseif ( $description instanceof SMWConceptDescription ) { // fetch concept definition and insert it here |
504 | | - $cid = $this->m_store->getSMWPageID( $description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '' ); |
| 504 | + $cid = $this->m_store->getSMWPageID( $description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '', '' ); |
505 | 505 | // We bypass the storage interface here (which is legal as we controll it, and safe if we are careful with changes ...) |
506 | 506 | // This should be faster, but we must implement the unescaping that concepts do on getWikiValue() |
507 | 507 | $row = $this->m_dbs->selectRow( |
— | — | @@ -778,9 +778,9 @@ |
779 | 779 | if ( $i >= count( $keys ) ) break; |
780 | 780 | |
781 | 781 | if ( $ftype == 'p' ) { // Special case: page id, resolve this in advance |
782 | | - $oid = $this->getSMWPageID( $keys[$i], $keys[$i + 1], $keys[$i + 2] ); |
783 | | - $i += 3; // skip these additional values (sortkey not needed here) |
| 782 | + $oid = $this->getSMWPageID( $dataItem->getDBkey(), $dataItem->getNamespace(), $dataItem->getInterwiki(), $dataItem->getSubobjectId() ); |
784 | 783 | $where .= ( $where ? ' AND ' : '' ) . "{$query->alias}.$fname=" . $this->m_dbs->addQuotes( $oid ); |
| 784 | + break; |
785 | 785 | } elseif ( $ftype != 'l' ) { // plain value, but not a text blob |
786 | 786 | $where .= ( $where ? ' AND ' : '' ) . "{$query->alias}.$fname=" . $this->m_dbs->addQuotes( $keys[$i] ); |
787 | 787 | } |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SqlStubSemanticData.php |
— | — | @@ -83,10 +83,21 @@ |
84 | 84 | |
85 | 85 | if ( array_key_exists( $property->getKey(), $this->mStubPropVals ) ) { |
86 | 86 | $this->unstubProperty( $property->getKey(), $property ); |
| 87 | + $propertyTypeId = $property->findPropertyTypeID(); |
| 88 | + $propertyDiId = SMWDataValueFactory::getDataItemId( $propertyTypeId ); |
87 | 89 | |
88 | 90 | foreach ( $this->mStubPropVals[$property->getKey()] as $dbkeys ) { |
89 | 91 | try { |
90 | | - $di = SMWCompatibilityHelpers::dataItemFromDBKeys( $property->findPropertyTypeID(), $dbkeys ); |
| 92 | + if ( $propertyDiId == SMWDataItem::TYPE_CONTAINER ) { |
| 93 | + $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys ); |
| 94 | + $semanticData = new SMWContainerSemanticData(); |
| 95 | + $semanticData->copyDataFrom( smwfGetStore()->getSemanticData( $diSubWikiPage ) ); |
| 96 | + |
| 97 | + $di = new SMWDIContainer( $semanticData ); |
| 98 | + } else { |
| 99 | + $di = SMWCompatibilityHelpers::dataItemFromDBKeys( $propertyTypeId, $dbkeys ); |
| 100 | + } |
| 101 | + |
91 | 102 | if ( $this->mNoDuplicates ) { |
92 | 103 | $this->mPropVals[$property->getKey()][$di->getHash()] = $di; |
93 | 104 | } else { |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php |
— | — | @@ -11,7 +11,7 @@ |
12 | 12 | */ |
13 | 13 | |
14 | 14 | // The use of the following constants is explained in SMWSQLStore2::setup(): |
15 | | -define( 'SMW_SQL2_SMWIW', ':smw' ); // virtual "interwiki prefix" for special SMW objects |
| 15 | +define( 'SMW_SQL2_SMWIW_OUTDATED', ':smw' ); // virtual "interwiki prefix" for old-style special SMW objects (no longer used) |
16 | 16 | define( 'SMW_SQL2_SMWREDIIW', ':smw-redi' ); // virtual "interwiki prefix" for SMW objects that are redirected |
17 | 17 | define( 'SMW_SQL2_SMWBORDERIW', ':smw-border' ); // virtual "interwiki prefix" separating very important pre-defined properties from the rest |
18 | 18 | define( 'SMW_SQL2_SMWPREDEFIW', ':smw-preprop' ); // virtual "interwiki prefix" marking predefined objects (non-movable) |
— | — | @@ -103,7 +103,7 @@ |
104 | 104 | SMWDataItem::TYPE_URI => 'smw_atts2', |
105 | 105 | SMWDataItem::TYPE_TIME => 'smw_atts2', |
106 | 106 | SMWDataItem::TYPE_GEO => 'smw_coords', // currently created only if Semantic Maps are installed |
107 | | - SMWDataItem::TYPE_CONTAINER => 'smw_rels2', // this is where the bnode is stored |
| 107 | + SMWDataItem::TYPE_CONTAINER => 'smw_rels2', // values of this type represented by internal objects, stored like pages in smw_rels2 |
108 | 108 | SMWDataItem::TYPE_WIKIPAGE => 'smw_rels2', |
109 | 109 | SMWDataItem::TYPE_CONCEPT => 'smw_conc2', // unlikely to occur as value of a normal property |
110 | 110 | SMWDataItem::TYPE_PROPERTY => 'smw_atts2' // unlikely to occur as value of any property |
— | — | @@ -119,7 +119,7 @@ |
120 | 120 | |
121 | 121 | // *** Find out if this subject exists ***// |
122 | 122 | $sortkey = ''; |
123 | | - $sid = $this->getSMWPageIDandSort( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $sortkey, true ); |
| 123 | + $sid = $this->getSMWPageIDandSort( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectId(), $sortkey, true ); |
124 | 124 | if ( $sid == 0 ) { // no data, safe our time |
125 | 125 | /// NOTE: we consider redirects for getting $sid, so $sid == 0 also means "no redirects" |
126 | 126 | self::$in_getSemanticData--; |
— | — | @@ -202,14 +202,30 @@ |
203 | 203 | $proptables = self::getPropertyTables(); |
204 | 204 | $data = $this->fetchSemanticData( $pid, $property, $proptables[$tableid], false, $requestoptions ); |
205 | 205 | $result = array(); |
| 206 | + $propertyTypeId = $property->findPropertyTypeID(); |
| 207 | + $propertyDiId = SMWDataValueFactory::getDataItemId( $propertyTypeId ); |
206 | 208 | |
207 | | - foreach ( $data as $dbkeys ) { |
208 | | - try { |
209 | | - $result[] = SMWCompatibilityHelpers::dataItemFromDBKeys( $property->findPropertyTypeID(), $dbkeys ); |
210 | | - } catch ( SMWDataItemException $e ) { |
211 | | - // maybe some type assignment changed since the data was stored; |
212 | | - // don't worry, but we can ony drop the data here |
| 209 | + if ( $propertyDiId == SMWDataItem::TYPE_CONTAINER ) { |
| 210 | + foreach ( $data as $dbkeys ) { |
| 211 | + try { |
| 212 | + $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys ); |
| 213 | + $semanticData = new SMWContainerSemanticData(); |
| 214 | + $semanticData->copyDataFrom( $this->getSemanticData( $diSubWikiPage ) ); |
| 215 | + $result[] = new SMWDIContainer( $semanticData ); |
| 216 | + } catch ( SMWDataItemException $e ) { |
| 217 | + // maybe type assignment changed since data was stored; |
| 218 | + // don't worry, but we can only drop the data here |
| 219 | + } |
213 | 220 | } |
| 221 | + } else { |
| 222 | + foreach ( $data as $dbkeys ) { |
| 223 | + try { |
| 224 | + $result[] = SMWCompatibilityHelpers::dataItemFromDBKeys( $propertyTypeId, $dbkeys ); |
| 225 | + } catch ( SMWDataItemException $e ) { |
| 226 | + // maybe type assignment changed since data was stored; |
| 227 | + // don't worry, but we can only drop the data here |
| 228 | + } |
| 229 | + } |
214 | 230 | } |
215 | 231 | } |
216 | 232 | |
— | — | @@ -255,7 +271,7 @@ |
256 | 272 | protected function fetchSemanticData( $id, $object, $proptable, $issubject = true, $requestoptions = null ) { |
257 | 273 | // stop if there is not enough data: |
258 | 274 | // properties always need to be given as object, subjects at least if !$proptable->idsubject |
259 | | - if ( ( $id == 0 ) || ( ( $object === null ) && ( !$issubject || !$proptable->idsubject ) ) ) return array(); |
| 275 | + if ( ( $id == 0 ) || ( is_null( $object ) && ( !$issubject || !$proptable->idsubject ) ) ) return array(); |
260 | 276 | |
261 | 277 | wfProfileIn( "SMWSQLStore2::fetchSemanticData-" . $proptable->name . " (SMW)" ); |
262 | 278 | $result = array(); |
— | — | @@ -281,7 +297,6 @@ |
282 | 298 | } |
283 | 299 | |
284 | 300 | $valuecount = 0; |
285 | | - $pagevalues = array(); // collect indices of page-type components of this table (typically at most 1) |
286 | 301 | $usedistinct = true; // use DISTINCT option only if no text blobs are among values |
287 | 302 | $selectvalues = array(); // array for all values to be selected, kept to help finding value and label fields below |
288 | 303 | |
— | — | @@ -294,15 +309,15 @@ |
295 | 310 | $selectvalues[$valuecount + 1] = "o$valuecount.smw_namespace"; |
296 | 311 | $selectvalues[$valuecount + 2] = "o$valuecount.smw_iw"; |
297 | 312 | $selectvalues[$valuecount + 3] = "o$valuecount.smw_sortkey"; |
| 313 | + $selectvalues[$valuecount + 4] = "o$valuecount.smw_subobject"; |
298 | 314 | |
299 | | - $pagevalues[] = $valuecount; |
300 | | - $valuecount += 3; |
| 315 | + $valuecount += 4; |
301 | 316 | } else { // Just use value as given. |
302 | 317 | $selectvalues[$valuecount] = $fieldname; |
303 | 318 | } |
304 | 319 | |
305 | 320 | if ( $typeid == 'l' ) $usedistinct = false; |
306 | | - $valuecount++; |
| 321 | + $valuecount += 1; |
307 | 322 | } |
308 | 323 | |
309 | 324 | foreach ( $selectvalues as $index => $field ) { |
— | — | @@ -321,59 +336,34 @@ |
322 | 337 | // *** Now execute the query and read the results ***// |
323 | 338 | $res = $db->select( $from, $select, $where, 'SMW::getSemanticData', |
324 | 339 | ( $usedistinct ? $this->getSQLOptions( $requestoptions, $valuecolumn ) + array( 'DISTINCT' ) : |
325 | | - $this->getSQLOptions( $requestoptions, $valuecolumn ) ) ); |
| 340 | + $this->getSQLOptions( $requestoptions, $valuecolumn ) ) ); |
326 | 341 | |
327 | 342 | foreach ( $res as $row ) { |
328 | | - if ( !$issubject ) { |
329 | | - $propertyname = 'fixed'; // irrelevant, but use this to check if the data is good |
330 | | - } elseif ( !$proptable->fixedproperty ) { // use joined or predefined property name |
| 343 | + if ( $issubject && !$proptable->fixedproperty ) { // use joined or predefined property name |
331 | 344 | if ( $proptable->specpropsonly ) { |
332 | 345 | $propertyname = array_search( $row->p_id, self::$special_ids ); |
333 | | - |
334 | | - if ( $propertyname === false ) { // unknown property that uses a special type, maybe by some extension; look it up in the DB |
335 | | - // NOTE: this is just an emergency fallback but not a fast solution; extensions may prefer to use non-special datatypes for new properties! |
336 | | - $propertyname = $db->selectField( 'smw_ids', 'smw_title', array( 'smw_id' => $row->p_id ), 'SMW::getSemanticData-LatePropertyFetch' ); |
337 | | - } |
| 346 | + // Note: this may leave $propertyname false if a special type |
| 347 | + // has been assigned to a proerty not in self::$special_ids. |
| 348 | + // Extensions could do this, but this will not work. |
| 349 | + if ( $propertyname == false ) continue; |
338 | 350 | } else { |
339 | 351 | $propertyname = $row->prop; |
340 | 352 | } |
341 | | - } else { // use fixed property name |
| 353 | + } elseif ( $issubject ) { // use fixed property name |
342 | 354 | $propertyname = $proptable->fixedproperty; |
343 | 355 | } |
344 | 356 | |
345 | 357 | $valuekeys = array(); |
346 | | - reset( $pagevalues ); |
347 | | - |
348 | | - for ( $i = 0; $i < $valuecount; $i++ ) { // read the value fields from the current row |
| 358 | + for ( $i = 0; $i < $valuecount; $i += 1 ) { // read the value fields from the current row |
349 | 359 | $fieldname = "v$i"; |
350 | | - $newvalue = $row->$fieldname; |
351 | | - |
352 | | - if ( $i === current( $pagevalues ) ) { // special check for pages to filter out internal objects |
353 | | - $iwfield = 'v' . ( $i + 2 ); |
354 | | - $iw = $row->$iwfield; |
355 | | - |
356 | | - if ( ( $iw == SMW_SQL2_SMWIW ) && ( $valuecount == 4 ) && ( $object !== null ) ) { |
357 | | - // read container objects recursively; but only if proptable is of form "p" |
358 | | - // also avoid (hypothetical) double recursion by requiring $object!==null |
359 | | - $i += 3; // skip other page fields of this bnode |
360 | | - $oidfield = 'id' . current( $pagevalues ); |
361 | | - |
362 | | - $newvalue = array(); |
363 | | - |
364 | | - foreach ( self::getPropertyTables() as $tid => $pt ) { // just read all |
365 | | - $newvalue = array_merge( $newvalue, $this->fetchSemanticData( $row->$oidfield, null, $pt ) ); |
366 | | - } |
367 | | - } elseif ( ( $iw != '' ) && ( $iw { 0 } == ' : ' ) ) { // other internal object, maybe a DB inconsistency; ignore row |
368 | | - $propertyname = ''; |
369 | | - } |
370 | | - |
371 | | - next( $pagevalues ); |
372 | | - } |
373 | | - |
374 | | - $valuekeys[] = $newvalue; |
| 360 | + $valuekeys[] = $row->$fieldname; |
375 | 361 | } |
376 | 362 | |
377 | | - if ( $propertyname != '' ) $result[] = $issubject ? array( $propertyname, $valuekeys ):$valuekeys; |
| 363 | + // Filter out any accidentally retrieved internal things (interwiki starts with ":"): |
| 364 | + if ( $proptable->getFieldSignature() != 'p' || count( $valuekeys ) < 3 || |
| 365 | + $valuekeys[2] == '' || $valuekeys[2]{0} != ':' ) { |
| 366 | + $result[] = $issubject ? array( $propertyname, $valuekeys ) : $valuekeys; |
| 367 | + } |
378 | 368 | } |
379 | 369 | |
380 | 370 | $db->freeResult( $res ); |
— | — | @@ -418,10 +408,10 @@ |
419 | 409 | |
420 | 410 | if ( $proptable->idsubject ) { // join in smw_ids to get title data |
421 | 411 | $from = $db->tableName( 'smw_ids' ) . " INNER JOIN " . $db->tableName( $proptable->name ) . " AS t1 ON t1.s_id=smw_id"; |
422 | | - $select = 'smw_title AS title, smw_namespace AS namespace, smw_sortkey'; |
| 412 | + $select = 'smw_title, smw_namespace, smw_sortkey, smw_iw, smw_subobject'; |
423 | 413 | } else { // no join needed, title+namespace as given in proptable |
424 | 414 | $from = $db->tableName( $proptable->name ) . " AS t1"; |
425 | | - $select = 's_title AS title, s_namespace AS namespace, s_title AS smw_sortkey'; |
| 415 | + $select = 's_title AS smw_title, s_namespace AS smw_namespace, s_title AS smw_sortkey, \'\' AS smw_iw, \'\' AS smw_subobject'; |
426 | 416 | } |
427 | 417 | |
428 | 418 | if ( $proptable->fixedproperty == false ) { |
— | — | @@ -434,12 +424,14 @@ |
435 | 425 | $result = array(); |
436 | 426 | $res = $db->select( $from, 'DISTINCT ' . $select, |
437 | 427 | $where . $this->getSQLConditions( $requestoptions, 'smw_sortkey', 'smw_sortkey', $where != '' ), |
438 | | - 'SMW::getPropertySubjects', |
| 428 | + 'SMW::getPropertySubjects', |
439 | 429 | $this->getSQLOptions( $requestoptions, 'smw_sortkey' ) ); |
440 | 430 | |
441 | 431 | foreach ( $res as $row ) { |
442 | 432 | try { |
443 | | - $result[] = new SMWDIWikiPage( $row->title, $row->namespace, '' ); |
| 433 | + if ( $row->smw_iw == '' || $row->smw_iw{0} != ':' ) { // filter special objects |
| 434 | + $result[] = new SMWDIWikiPage( $row->smw_title, $row->smw_namespace, $row->smw_iw, $row->smw_subobject ); |
| 435 | + } |
444 | 436 | } catch ( SMWDataItemException $e ) { |
445 | 437 | // silently drop data, should be extremely rare and will usually fix itself at next edit |
446 | 438 | } |
— | — | @@ -499,6 +491,8 @@ |
500 | 492 | } |
501 | 493 | } |
502 | 494 | } elseif ( $value !== null ) { // add conditions for given value |
| 495 | + /// TODO This code still partly supports some abandoned flexibility of the DBkeys system; |
| 496 | + /// this is not very clean (see break; below) and should be improved |
503 | 497 | $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem( $value ); |
504 | 498 | $i = 0; |
505 | 499 | |
— | — | @@ -506,14 +500,14 @@ |
507 | 501 | if ( $i >= count( $dbkeys ) ) break; |
508 | 502 | |
509 | 503 | if ( $typeid == 'p' ) { // Special case: page id, resolve this in advance |
510 | | - $oid = $this->getSMWPageID( $dbkeys[$i], $dbkeys[$i + 1], $dbkeys[$i + 2] ); |
511 | | - $i += 3; // skip these additional values (sortkey not needed here) |
| 504 | + $oid = $this->getSMWPageID( $value->getDBkey(), $value->getNamespace(), $value->getInterwiki(), $value->getSubobjectId() ); |
512 | 505 | $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $oid ); |
| 506 | + break; |
513 | 507 | } elseif ( $typeid != 'l' ) { // plain value, but not a text blob |
514 | 508 | $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $dbkeys[$i] ); |
515 | 509 | } |
516 | 510 | |
517 | | - $i++; |
| 511 | + $i += 1; |
518 | 512 | } |
519 | 513 | } |
520 | 514 | } |
— | — | @@ -542,7 +536,7 @@ |
543 | 537 | */ |
544 | 538 | public function getProperties( SMWDIWikiPage $subject, $requestoptions = null ) { |
545 | 539 | wfProfileIn( "SMWSQLStore2::getProperties (SMW)" ); |
546 | | - $sid = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki() ); |
| 540 | + $sid = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectId() ); |
547 | 541 | |
548 | 542 | if ( $sid == 0 ) { // no id, no page, no properties |
549 | 543 | wfProfileOut( "SMWSQLStore2::getProperties (SMW)" ); |
— | — | @@ -573,9 +567,10 @@ |
574 | 568 | |
575 | 569 | if ( $proptable->fixedproperty == false ) { // select all properties |
576 | 570 | $from .= " INNER JOIN " . $db->tableName( 'smw_ids' ) . " ON smw_id=p_id"; |
577 | | - $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey', // select sortkey since it might be used in ordering (needed by Postgres) |
578 | | - $where . $this->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey' ), |
579 | | - 'SMW::getProperties', $this->getSQLOptions( $suboptions, 'smw_sortkey' ) ); |
| 571 | + $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey', |
| 572 | + // (select sortkey since it might be used in ordering (needed by Postgres)) |
| 573 | + $where . $this->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey' ), |
| 574 | + 'SMW::getProperties', $this->getSQLOptions( $suboptions, 'smw_sortkey' ) ); |
580 | 575 | |
581 | 576 | foreach ( $res as $row ) { |
582 | 577 | $result[] = new SMWDIProperty( $row->smw_title ); |
— | — | @@ -639,9 +634,10 @@ |
640 | 635 | $from = $db->tableName( 'smw_ids' ) . " INNER JOIN " . $db->tableName( $proptable->name ) . " AS t1 ON t1.p_id=smw_id"; |
641 | 636 | $this->prepareValueQuery( $from, $where, $proptable, $value, 1 ); |
642 | 637 | |
643 | | - $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey', // select sortkey since it might be used in ordering (needed by Postgres) |
644 | | - $where . $this->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey', $where != '' ), |
645 | | - 'SMW::getInProperties', $this->getSQLOptions( $suboptions, 'smw_sortkey' ) ); |
| 638 | + $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey', |
| 639 | + // select sortkey since it might be used in ordering (needed by Postgres) |
| 640 | + $where . $this->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey', $where != '' ), |
| 641 | + 'SMW::getInProperties', $this->getSQLOptions( $suboptions, 'smw_sortkey' ) ); |
646 | 642 | |
647 | 643 | foreach ( $res as $row ) { |
648 | 644 | try { |
— | — | @@ -684,7 +680,7 @@ |
685 | 681 | |
686 | 682 | if ( $subject->getNamespace() == SMW_NS_CONCEPT ) { // make sure to clear caches |
687 | 683 | $db = wfGetDB( DB_MASTER ); |
688 | | - $id = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), false ); |
| 684 | + $id = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), '', false ); |
689 | 685 | $db->delete( 'smw_conc2', array( 's_id' => $id ), 'SMW::deleteSubject::Conc2' ); |
690 | 686 | $db->delete( 'smw_conccache', array( 'o_id' => $id ), 'SMW::deleteSubject::Conccache' ); |
691 | 687 | } |
— | — | @@ -728,9 +724,9 @@ |
729 | 725 | } |
730 | 726 | |
731 | 727 | // Always make an ID (pages without ID cannot be in query results, not even in fixed value queries!): |
732 | | - $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(), '', true, $sortkey ); |
| 728 | + $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectId(), true, $sortkey ); |
733 | 729 | $updates = array(); // collect data for bulk updates; format: tableid => updatearray |
734 | | - $this->prepareDBUpdates( $updates, $data, $sid ); |
| 730 | + $this->prepareDBUpdates( $updates, $data, $sid, $subject ); |
735 | 731 | |
736 | 732 | $db = wfGetDB( DB_MASTER ); |
737 | 733 | foreach ( $updates as $tablename => $uvals ) { |
— | — | @@ -783,25 +779,26 @@ |
784 | 780 | } |
785 | 781 | |
786 | 782 | /** |
787 | | - * Extend the given update array to account for the data in the SMWSemanticData object. |
788 | | - * The subject page of the data container is ignored, and the given $pageid is used directly. |
789 | | - * However, if the subject is empty, then a blank node (internal id) is generated instead |
790 | | - * of using the given $pageid directly (note that internal objects always belong to one |
791 | | - * proper object which in this case is the given $pageid). |
| 783 | + * Extend the given update array to account for the data in the |
| 784 | + * SMWSemanticData object. The subject page of the data container is |
| 785 | + * ignored, and the given $sid (subject page id) is used directly. If |
| 786 | + * this ID is 0, then $subject is used to find an ID. This is usually |
| 787 | + * the case for all internal objects that are created in writing |
| 788 | + * container values. |
792 | 789 | * |
793 | | - * The function returns the id that was used for writing. Especially, any newly created |
794 | | - * internal id is returned. |
| 790 | + * The function returns the id that was used for writing. Especially, |
| 791 | + * any newly created internal id is returned. |
795 | 792 | * |
796 | | - * @param $updates |
797 | | - * @param SMWSemanticData $data |
798 | | - * @param $pageid |
| 793 | + * @param $updates array |
| 794 | + * @param $data SMWSemanticData |
| 795 | + * @param $sid integer pre-computed id if available or 0 if ID should be sought |
| 796 | + * @param $subject SMWDIWikiPage subject to which the data refers |
799 | 797 | */ |
800 | | - protected function prepareDBUpdates( &$updates, SMWSemanticData $data, $pageid ) { |
801 | | - if ( $data instanceof SMWContainerSemanticData ) { |
802 | | - $sid = $this->makeSMWBnodeID( $pageid ); |
803 | | - } else { |
804 | | - $subject = $data->getSubject(); |
805 | | - $sid = $pageid; |
| 798 | + protected function prepareDBUpdates( &$updates, SMWSemanticData $data, $sid, SMWDIWikiPage $subject ) { |
| 799 | + if ( $sid == 0 ) { |
| 800 | + $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(), |
| 801 | + $subject->getInterwiki(), $subject->getSubobjectId(), true, |
| 802 | + str_replace( '_', ' ', $subject->getDBkey() ) . $subject->getSubobjectId() ); |
806 | 803 | } |
807 | 804 | |
808 | 805 | $proptables = self::getPropertyTables(); |
— | — | @@ -828,10 +825,11 @@ |
829 | 826 | } |
830 | 827 | |
831 | 828 | if ( $di instanceof SMWDIContainer ) { // process subobjects recursively |
832 | | - $bnode = $this->prepareDBUpdates( $updates, $di->getSemanticData(), $pageid ); |
| 829 | + $subObject = $di->getSubjectPage( $subject ); |
| 830 | + $subObjectId = $this->prepareDBUpdates( $updates, $di->getSemanticData(), 0, $subObject ); |
833 | 831 | // Note: tables for container objects MUST have objectfields == array(<somename> => 'p') |
834 | 832 | reset( $proptable->objectfields ); |
835 | | - $uvals[key( $proptable->objectfields )] = $bnode; |
| 833 | + $uvals[key( $proptable->objectfields )] = $subObjectId; |
836 | 834 | } else { |
837 | 835 | $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem( $di ); |
838 | 836 | reset( $dbkeys ); |
— | — | @@ -840,11 +838,12 @@ |
841 | 839 | if ( $typeid != 'p' ) { |
842 | 840 | $uvals[$fieldname] = current( $dbkeys ); |
843 | 841 | } else { |
| 842 | + /// TODO The dbkeys hanlding here is obsolete; a clean handling for the DI system is needed |
844 | 843 | $title = current( $dbkeys ); |
845 | 844 | $namespace = next( $dbkeys ); |
846 | 845 | $iw = next( $dbkeys ); |
847 | 846 | $sortkey = next( $dbkeys ); // not used; sortkeys are not set on writing objects |
848 | | - $uvals[$fieldname] = $this->makeSMWPageID( $title, $namespace, $iw ); |
| 847 | + $uvals[$fieldname] = $this->makeSMWPageID( $di->getDBkey(), $di->getNamespace(), $di->getInterwiki(), $di->getSubobjectId() ); |
849 | 848 | } |
850 | 849 | |
851 | 850 | next( $dbkeys ); |
— | — | @@ -858,7 +857,7 @@ |
859 | 858 | $updates[$proptable->name][] = $uvals; |
860 | 859 | } |
861 | 860 | } |
862 | | - |
| 861 | + |
863 | 862 | return $sid; |
864 | 863 | } |
865 | 864 | |
— | — | @@ -895,48 +894,68 @@ |
896 | 895 | wfProfileIn( "SMWSQLStore2::changeTitle (SMW)" ); |
897 | 896 | |
898 | 897 | // get IDs but do not resolve redirects: |
899 | | - $sid = $this->getSMWPageID( $oldtitle->getDBkey(), $oldtitle->getNamespace(), '', false ); |
900 | | - $tid = $this->getSMWPageID( $newtitle->getDBkey(), $newtitle->getNamespace(), '', false ); |
| 898 | + $sid = $this->getSMWPageID( $oldtitle->getDBkey(), $oldtitle->getNamespace(), '', '', false ); |
| 899 | + $tid = $this->getSMWPageID( $newtitle->getDBkey(), $newtitle->getNamespace(), '', '', false ); |
901 | 900 | $db = wfGetDB( DB_MASTER ); |
902 | 901 | |
903 | | - if ( ( $tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // target not used anywhere yet, just hijack its title for our current id |
904 | | - // This condition may not hold even if $newtitle is currently unused/non-existing since we keep old IDs. |
905 | | - // If equality support is off, then this simple move does too much; fall back to general case below. |
| 902 | + // Easy case: target not used anywhere yet, just hijack its title for our current id |
| 903 | + if ( ( $tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { |
| 904 | + // This condition may not hold even if $newtitle is |
| 905 | + // currently unused/non-existing since we keep old IDs. |
| 906 | + // If equality support is off, then this simple move |
| 907 | + // does too much; fall back to general case below. |
906 | 908 | if ( $sid != 0 ) { // change id entry to refer to the new title |
907 | | - $db->update( 'smw_ids', array( 'smw_title' => $newtitle->getDBkey(), 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => '' ), |
908 | | - array( 'smw_id' => $sid ), 'SMWSQLStore2::changeTitle' ); |
| 909 | + // Note that is also changes the reference for internal objects (subobjects) |
| 910 | + $db->update( 'smw_ids', |
| 911 | + array( 'smw_title' => $newtitle->getDBkey(), 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => '' ), |
| 912 | + array( 'smw_title' => $oldtitle->getDBkey(), 'smw_namespace' => $oldtitle->getNamespace(), 'smw_iw' => '' ), __METHOD__ ); |
909 | 913 | } else { // make new (target) id for use in redirect table |
910 | | - $sid = $this->makeSMWPageID( $newtitle->getDBkey(), $newtitle->getNamespace(), '' ); |
| 914 | + $sid = $this->makeSMWPageID( $newtitle->getDBkey(), $newtitle->getNamespace(), '', '' ); |
911 | 915 | } // at this point, $sid is the id of the target page (according to smw_ids) |
912 | 916 | |
913 | | - $this->makeSMWPageID( $oldtitle->getDBkey(), $oldtitle->getNamespace(), SMW_SQL2_SMWREDIIW ); // make redirect id for oldtitle |
914 | | - $db->insert( 'smw_redi2', array( 's_title' => $oldtitle->getDBkey(), 's_namespace' => $oldtitle->getNamespace(), 'o_id' => $sid ), |
915 | | - 'SMWSQLStore2::changeTitle' ); |
916 | | - $this->m_ids[" " . $oldtitle->getNamespace() . ' ' . $oldtitle->getDBkey() . ' C'] = $sid; |
| 917 | + // make redirect id for oldtitle: |
| 918 | + $this->makeSMWPageID( $oldtitle->getDBkey(), $oldtitle->getNamespace(), SMW_SQL2_SMWREDIIW, '' ); |
| 919 | + $db->insert( 'smw_redi2', array( 's_title' => $oldtitle->getDBkey(), |
| 920 | + 's_namespace' => $oldtitle->getNamespace(), |
| 921 | + 'o_id' => $sid ), |
| 922 | + __METHOD__ ); |
| 923 | + // update caches: |
| 924 | + $this->m_ids[' ' . $oldtitle->getNamespace() . ' ' . $oldtitle->getDBkey() . ' C'] = $sid; |
917 | 925 | // $this->m_ids[" " . $oldtitle->getNamespace() . " " . $oldtitle->getDBkey() . " -"] = Already OK after makeSMWPageID above |
918 | | - $this->m_ids[" " . $newtitle->getNamespace() . ' ' . $newtitle->getDBkey() . ' C'] = $sid; |
919 | | - $this->m_ids[" " . $newtitle->getNamespace() . ' ' . $newtitle->getDBkey() . ' -'] = $sid; |
| 926 | + $this->m_ids[' ' . $newtitle->getNamespace() . ' ' . $newtitle->getDBkey() . ' C'] = $sid; |
| 927 | + $this->m_ids[' ' . $newtitle->getNamespace() . ' ' . $newtitle->getDBkey() . ' -'] = $sid; |
920 | 928 | /// NOTE: there is the (bad) case that the moved page is a redirect. As chains of |
921 | 929 | /// redirects are not supported by MW or SMW, the above is maximally correct in this case too. |
922 | 930 | /// NOTE: this temporarily leaves existing redirects to oldtitle point to newtitle as well, which |
923 | 931 | /// will be lost after the next update. Since double redirects are an error anyway, this is not |
924 | 932 | /// a bad behaviour: everything will continue to work until the existing redirects are updated, |
925 | 933 | /// which will hopefully be done to fix the double redirect. |
926 | | - } else { // general move method that should be correct in all cases (equality support respected when updating redirects) |
| 934 | + } else { // General move method: should always be correct |
| 935 | + // (equality support respected when updating redirects) |
| 936 | + |
927 | 937 | // Delete any existing data from new title: |
928 | 938 | // $newtitle should not have data, but let's be sure |
929 | 939 | $this->deleteSemanticData( SMWDIWikiPage::newFromTitle( $newtitle ) ); |
930 | | - $this->updateRedirects( $newtitle->getDBkey(), $newtitle->getNamespace() ); // may trigger update jobs! |
| 940 | + // Update (i.e. delete) redirects (may trigger update jobs): |
| 941 | + $this->updateRedirects( $newtitle->getDBkey(), $newtitle->getNamespace() ); |
931 | 942 | |
932 | 943 | // Move all data of old title to new position: |
933 | 944 | if ( $sid != 0 ) { |
934 | 945 | $this->changeSMWPageID( $sid, $tid, $oldtitle->getNamespace(), $newtitle->getNamespace(), true, false ); |
935 | 946 | } |
936 | 947 | |
937 | | - // Now write a redirect from old title to new one; this also updates references in other tables as needed. |
| 948 | + // Write a redirect from old title to new one: |
| 949 | + // (this also updates references in other tables as needed.) |
938 | 950 | /// TODO: may not be optimal for the standard case that newtitle existed and redirected to oldtitle (PERFORMANCE) |
939 | 951 | $this->updateRedirects( $oldtitle->getDBkey(), $oldtitle->getNamespace(), $newtitle->getDBkey(), $newtitle->getNamespace() ); |
| 952 | + |
| 953 | + // Associate internal objects (subobjects) with the new title: |
| 954 | + $db->update( 'smw_ids', |
| 955 | + array( 'smw_title' => $newtitle->getDBkey(), 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => '' ), |
| 956 | + array( 'smw_title' => $oldtitle->getDBkey(), 'smw_namespace' => $oldtitle->getNamespace(), 'smw_iw' => '', 'smw_subobject!' => array( '' ) ), // array() needed for ! to work |
| 957 | + __METHOD__ ); |
940 | 958 | } |
| 959 | + |
941 | 960 | wfProfileOut( "SMWSQLStore2::changeTitle (SMW)" ); |
942 | 961 | } |
943 | 962 | |
— | — | @@ -976,8 +995,10 @@ |
977 | 996 | foreach ( self::getPropertyTables() as $proptable ) { |
978 | 997 | if ( $proptable->fixedproperty == false ) { |
979 | 998 | $queries[] = 'SELECT smw_id, smw_title, COUNT(*) as count, smw_sortkey FROM ' . |
980 | | - $db->tableName( $proptable->name ) . ' INNER JOIN ' . $db->tableName( 'smw_ids' ) . ' ON p_id=smw_id WHERE smw_iw=' . |
981 | | - $db->addQuotes( '' ) . ' OR smw_iw=' . $db->addQuotes( SMW_SQL2_SMWPREDEFIW ) . ' GROUP BY smw_id,smw_title,smw_sortkey'; |
| 999 | + $db->tableName( $proptable->name ) . ' INNER JOIN ' . |
| 1000 | + $db->tableName( 'smw_ids' ) . ' ON p_id=smw_id WHERE smw_iw=' . |
| 1001 | + $db->addQuotes( '' ) . ' OR smw_iw=' . $db->addQuotes( SMW_SQL2_SMWPREDEFIW ) . |
| 1002 | + ' GROUP BY smw_id,smw_title,smw_sortkey'; |
982 | 1003 | } // else: properties with special tables are ignored for now; maybe fix in the future |
983 | 1004 | } |
984 | 1005 | |
— | — | @@ -1015,7 +1036,6 @@ |
1016 | 1037 | |
1017 | 1038 | wfProfileIn( "SMWSQLStore2::getUnusedPropertiesSpecial (SMW)" ); |
1018 | 1039 | $db = wfGetDB( DB_SLAVE ); |
1019 | | - $fname = 'SMW::getUnusedPropertySubjects'; |
1020 | 1040 | |
1021 | 1041 | // we use a temporary table for executing this costly operation on the DB side |
1022 | 1042 | $smw_tmp_unusedprops = $db->tableName( 'smw_tmp_unusedprops' ); |
— | — | @@ -1036,21 +1056,21 @@ |
1037 | 1057 | $sql = "CREATE TEMPORARY TABLE " . $smw_tmp_unusedprops . "( title VARCHAR(255) ) ENGINE=MEMORY"; |
1038 | 1058 | } |
1039 | 1059 | |
1040 | | - $db->query( $sql, $fname ); |
| 1060 | + $db->query( $sql, __METHOD__ ); |
1041 | 1061 | |
1042 | 1062 | $db->insertSelect( $smw_tmp_unusedprops, 'page', array( 'title' => 'page_title' ), |
1043 | | - array( "page_namespace" => SMW_NS_PROPERTY ), $fname ); |
| 1063 | + array( "page_namespace" => SMW_NS_PROPERTY ), __METHOD__ ); |
1044 | 1064 | |
1045 | 1065 | $smw_ids = $db->tableName( 'smw_ids' ); |
1046 | 1066 | |
1047 | 1067 | // all predefined properties are assumed to be used: |
1048 | | - $db->deleteJoin( $smw_tmp_unusedprops, $smw_ids, 'title', 'smw_title', array( 'smw_iw' => SMW_SQL2_SMWPREDEFIW ), $fname ); |
| 1068 | + $db->deleteJoin( $smw_tmp_unusedprops, $smw_ids, 'title', 'smw_title', array( 'smw_iw' => SMW_SQL2_SMWPREDEFIW ), __METHOD__ ); |
1049 | 1069 | |
1050 | 1070 | // all tables occurring in some property table are used: |
1051 | 1071 | foreach ( self::getPropertyTables() as $proptable ) { |
1052 | 1072 | if ( $proptable->fixedproperty == false ) { // MW does not seem to have a suitable wrapper for this |
1053 | 1073 | $db->query( "DELETE FROM $smw_tmp_unusedprops USING $smw_tmp_unusedprops INNER JOIN " . $db->tableName( $proptable->name ) . |
1054 | | - " INNER JOIN $smw_ids ON p_id=smw_id AND title=smw_title AND smw_iw=" . $db->addQuotes( '' ), $fname ); |
| 1074 | + " INNER JOIN $smw_ids ON p_id=smw_id AND title=smw_title AND smw_iw=" . $db->addQuotes( '' ), __METHOD__ ); |
1055 | 1075 | } // else: todo |
1056 | 1076 | } |
1057 | 1077 | |
— | — | @@ -1061,16 +1081,16 @@ |
1062 | 1082 | |
1063 | 1083 | // (again we have no fitting MW wrapper here:) |
1064 | 1084 | $db->query( "DELETE $smw_tmp_unusedprops.* FROM $smw_tmp_unusedprops," . $db->tableName( $subPropertyTable->name ) . |
1065 | | - " INNER JOIN $smw_ids ON o_id=smw_id WHERE title=smw_title", $fname ); |
| 1085 | + " INNER JOIN $smw_ids ON o_id=smw_id WHERE title=smw_title", __METHOD__ ); |
1066 | 1086 | // properties that are redirects are considered to be used: |
1067 | 1087 | // (a stricter and more costy approach would be to delete only redirects to used properties; |
1068 | 1088 | // this would need to be done with an addtional query in the above loop) |
1069 | 1089 | // The redirect table is a fixed part of this store, no need to find its name. |
1070 | | - $db->deleteJoin( $smw_tmp_unusedprops, 'smw_redi2', 'title', 's_title', array( 's_namespace' => SMW_NS_PROPERTY ), $fname ); |
| 1090 | + $db->deleteJoin( $smw_tmp_unusedprops, 'smw_redi2', 'title', 's_title', array( 's_namespace' => SMW_NS_PROPERTY ), __METHOD__ ); |
1071 | 1091 | |
1072 | 1092 | $options = $this->getSQLOptions( $requestoptions, 'title' ); |
1073 | 1093 | $options['ORDER BY'] = 'title'; |
1074 | | - $res = $db->select( $smw_tmp_unusedprops, 'title', '', $fname, $options ); |
| 1094 | + $res = $db->select( $smw_tmp_unusedprops, 'title', '', __METHOD__, $options ); |
1075 | 1095 | |
1076 | 1096 | $result = array(); |
1077 | 1097 | |
— | — | @@ -1080,7 +1100,7 @@ |
1081 | 1101 | |
1082 | 1102 | $db->freeResult( $res ); |
1083 | 1103 | |
1084 | | - $db->query( "DROP TEMPORARY table $smw_tmp_unusedprops", $fname ); |
| 1104 | + $db->query( "DROP TEMPORARY table $smw_tmp_unusedprops", __METHOD__ ); |
1085 | 1105 | wfProfileOut( "SMWSQLStore2::getUnusedPropertiesSpecial (SMW)" ); |
1086 | 1106 | |
1087 | 1107 | return $result; |
— | — | @@ -1110,11 +1130,13 @@ |
1111 | 1131 | $db = wfGetDB( DB_SLAVE ); |
1112 | 1132 | $options = $this->getSQLOptions( $requestoptions, 'title' ); |
1113 | 1133 | $options['ORDER BY'] = 'count DESC'; |
1114 | | - $res = $db->select( $db->tableName( $proptable->name ) . ' INNER JOIN ' . $db->tableName( 'smw_ids' ) . |
1115 | | - ' ON p_id=smw_id LEFT JOIN ' . $db->tableName( 'page' ) . ' ON (page_namespace=' . |
1116 | | - $db->addQuotes( SMW_NS_PROPERTY ) . ' AND page_title=smw_title)', |
1117 | | - 'smw_title, COUNT(*) as count', 'smw_id > 50 AND page_id IS NULL GROUP BY smw_title', |
1118 | | - 'SMW::getWantedPropertiesSpecial', $options ); |
| 1134 | + $res = $db->select( $db->tableName( $proptable->name ) . ' INNER JOIN ' . |
| 1135 | + $db->tableName( 'smw_ids' ) . ' ON p_id=smw_id LEFT JOIN ' . |
| 1136 | + $db->tableName( 'page' ) . ' ON (page_namespace=' . |
| 1137 | + $db->addQuotes( SMW_NS_PROPERTY ) . ' AND page_title=smw_title)', |
| 1138 | + 'smw_title, COUNT(*) as count', |
| 1139 | + 'smw_id > 50 AND page_id IS NULL GROUP BY smw_title', |
| 1140 | + 'SMW::getWantedPropertiesSpecial', $options ); |
1119 | 1141 | |
1120 | 1142 | foreach ( $res as $row ) { |
1121 | 1143 | $result[] = array( new SMWDIProperty( $row->smw_title ), $row->count ); |
— | — | @@ -1185,29 +1207,25 @@ |
1186 | 1208 | } |
1187 | 1209 | |
1188 | 1210 | /** |
1189 | | - * Create required SQL tables. This function also performs upgrades of table contents |
1190 | | - * when required. |
| 1211 | + * Create required SQL tables. This function also performs upgrades of |
| 1212 | + * table contents when required. |
1191 | 1213 | * |
1192 | | - * Documentation for the table smw_ids: This table is normally used to store references to wiki |
1193 | | - * pages (possibly with some external interwiki prefix). There are, however, some special objects |
1194 | | - * that are also stored therein. These are marked by special interwiki prefixes (iw) that cannot |
1195 | | - * occcur in real life: |
| 1214 | + * Documentation for the table smw_ids: This table is normally used to |
| 1215 | + * store references to wiki pages (possibly with some external interwiki |
| 1216 | + * prefix). There are, however, some special objects that are also |
| 1217 | + * stored therein. These are marked by special interwiki prefixes (iw) |
| 1218 | + * that cannot occcur in real life: |
1196 | 1219 | * |
1197 | | - * - Rows with iw SMW_SQL2_SMWIW describe "virtual" objects that have no page or other reference in the wiki. |
1198 | | - * These are specifically the auxilliary objects ("bnodes") required to encode multi-valued properties, |
1199 | | - * which are recognised by their empty title field. As a namespace, they use the id of the object that |
1200 | | - * "owns" them, so that the can be reused/maintained more easily. |
1201 | | - * A second object type that can occur in SMW_SQL2_SMWIW rows are the internal properties used to |
1202 | | - * refer to some position in a multivalued property value. They have titles like "1", "2", "3", ... |
1203 | | - * and occur only once (i.e. there is just one such property for the whoel wiki, and it has no type). |
1204 | | - * The namespace of those entries is the usual property namespace. |
| 1220 | + * - Rows with iw SMW_SQL2_SMWREDIIW are similar to normal entries for |
| 1221 | + * (internal) wiki pages, but the iw indicates that the page is a |
| 1222 | + * redirect, the target of which should be sought using the smw_redi2 |
| 1223 | + * table. |
1205 | 1224 | * |
1206 | | - * - Rows with iw SMW_SQL2_SMWREDIIW are similar to normal entries for (internal) wiki pages, but the iw |
1207 | | - * indicates that the page is a redirect, the target of which should be sought using the smw_redi2 table. |
1208 | | - * |
1209 | | - * - The (unique) row with iw SMW_SQL2_SMWBORDERIW just marks the border between predefined ids (rows that |
1210 | | - * are reserved for hardcoded ids built into SMW) and normal entries. It is no object, but makes sure that |
1211 | | - * SQL's auto increment counter is high enough to not add any objects before that marked "border". |
| 1225 | + * - The (unique) row with iw SMW_SQL2_SMWBORDERIW just marks the |
| 1226 | + * border between predefined ids (rows that are reserved for hardcoded |
| 1227 | + * ids built into SMW) and normal entries. It is no object, but makes |
| 1228 | + * sure that SQL's auto increment counter is high enough to not add any |
| 1229 | + * objects before that marked "border". |
1212 | 1230 | */ |
1213 | 1231 | protected function setupTables( $verbose, $db ) { |
1214 | 1232 | global $wgDBtype; |
— | — | @@ -1229,11 +1247,11 @@ |
1230 | 1248 | $smw_spec2 = $db->tableName( 'smw_spec2' ); |
1231 | 1249 | |
1232 | 1250 | // DB update: field renaming between SMW 1.3 and SMW 1.4. |
1233 | | - if ( ( $db->tableExists( $smw_spec2 ) ) && ( $db->fieldExists( $smw_spec2, 'sp_id', 'SMWSQLStore2::setup' ) ) ) { |
| 1251 | + if ( ( $db->tableExists( $smw_spec2 ) ) && ( $db->fieldExists( $smw_spec2, 'sp_id', __METHOD__ ) ) ) { |
1234 | 1252 | if ( $wgDBtype == 'postgres' ) { |
1235 | | - $db->query( "ALTER TABLE $smw_spec2 ALTER COLUMN sp_id RENAME TO p_id", 'SMWSQLStore2::setup' ); |
| 1253 | + $db->query( "ALTER TABLE $smw_spec2 ALTER COLUMN sp_id RENAME TO p_id", __METHOD__ ); |
1236 | 1254 | } else { |
1237 | | - $db->query( "ALTER TABLE $smw_spec2 CHANGE `sp_id` `p_id` " . $dbtypes['p'] . " NOT NULL", 'SMWSQLStore2::setup' ); |
| 1255 | + $db->query( "ALTER TABLE $smw_spec2 CHANGE `sp_id` `p_id` " . $dbtypes['p'] . " NOT NULL", __METHOD__ ); |
1238 | 1256 | } |
1239 | 1257 | } |
1240 | 1258 | |
— | — | @@ -1244,14 +1262,15 @@ |
1245 | 1263 | 'smw_id' => $dbtypes['p'] . ' NOT NULL' . ( $wgDBtype == 'postgres' ? ' PRIMARY KEY' : ' KEY AUTO_INCREMENT' ), |
1246 | 1264 | 'smw_namespace' => $dbtypes['n'] . ' NOT NULL', |
1247 | 1265 | 'smw_title' => $dbtypes['t'] . ' NOT NULL', |
1248 | | - 'smw_iw' => $dbtypes['w'], |
| 1266 | + 'smw_iw' => $dbtypes['w'] . ' NOT NULL', |
| 1267 | + 'smw_subobject' => $dbtypes['w'] . ' NOT NULL', |
1249 | 1268 | 'smw_sortkey' => $dbtypes['t'] . ' NOT NULL' |
1250 | 1269 | ), |
1251 | 1270 | $db, |
1252 | 1271 | $reportTo |
1253 | 1272 | ); |
1254 | 1273 | |
1255 | | - SMWSQLHelpers::setupIndex( 'smw_ids', array( 'smw_id', 'smw_title,smw_namespace,smw_iw', 'smw_sortkey' ), $db ); |
| 1274 | + SMWSQLHelpers::setupIndex( 'smw_ids', array( 'smw_id', 'smw_title,smw_namespace,smw_iw,smw_subobject', 'smw_sortkey' ), $db ); |
1256 | 1275 | |
1257 | 1276 | // Set up concept cache: member elements (s)->concepts (o) |
1258 | 1277 | SMWSQLHelpers::setupTable( |
— | — | @@ -1330,7 +1349,7 @@ |
1331 | 1350 | $borderiw = $db->selectField( 'smw_ids', 'smw_iw', 'smw_id=' . $db->addQuotes( 50 ) ); |
1332 | 1351 | |
1333 | 1352 | if ( $borderiw != SMW_SQL2_SMWBORDERIW ) { |
1334 | | - $this->reportProgress( " ... allocating space for internal properties...\n", $verbose ); |
| 1353 | + $this->reportProgress( " ... allocating space for internal properties ...\n", $verbose ); |
1335 | 1354 | $this->moveSMWPageID( 50 ); // make sure position 50 is empty |
1336 | 1355 | |
1337 | 1356 | $db->insert( 'smw_ids', array( |
— | — | @@ -1338,6 +1357,7 @@ |
1339 | 1358 | 'smw_title' => '', |
1340 | 1359 | 'smw_namespace' => 0, |
1341 | 1360 | 'smw_iw' => SMW_SQL2_SMWBORDERIW, |
| 1361 | + 'smw_subobject' => '', |
1342 | 1362 | 'smw_sortkey' => '' |
1343 | 1363 | ), 'SMW::setup' |
1344 | 1364 | ); // put dummy "border element" on index 50 |
— | — | @@ -1355,7 +1375,7 @@ |
1356 | 1376 | } |
1357 | 1377 | |
1358 | 1378 | // now write actual properties; do that each time, it is cheap enough and we can update sortkeys by current language |
1359 | | - $this->reportProgress( " ... writing entries for internal properties.", $verbose ); |
| 1379 | + $this->reportProgress( " ... writing entries for internal properties ...", $verbose ); |
1360 | 1380 | |
1361 | 1381 | foreach ( self::$special_ids as $prop => $id ) { |
1362 | 1382 | $p = new SMWDIProperty( $prop ); |
— | — | @@ -1364,12 +1384,13 @@ |
1365 | 1385 | 'smw_title' => $p->getKey(), |
1366 | 1386 | 'smw_namespace' => SMW_NS_PROPERTY, |
1367 | 1387 | 'smw_iw' => $this->getPropertyInterwiki( $p ), |
| 1388 | + 'smw_subobject' => '', |
1368 | 1389 | 'smw_sortkey' => $p->getKey() |
1369 | 1390 | ), 'SMW::setup' |
1370 | 1391 | ); |
1371 | 1392 | } |
1372 | 1393 | |
1373 | | - $this->reportProgress( " done.\n", $verbose ); |
| 1394 | + $this->reportProgress( " done.\n", $verbose ); |
1374 | 1395 | |
1375 | 1396 | if ( $wgDBtype == 'postgres' ) { |
1376 | 1397 | $this->reportProgress( " ... updating smw_ids_smw_id_seq sequence accordingly.\n", $verbose ); |
— | — | @@ -1417,7 +1438,7 @@ |
1418 | 1439 | */ |
1419 | 1440 | public function refreshData( &$index, $count, $namespaces = false, $usejobs = true ) { |
1420 | 1441 | $updatejobs = array(); |
1421 | | - $emptyrange = true; // was nothing found in this run? |
| 1442 | + $emptyrange = true; // was nothing done in this run? |
1422 | 1443 | |
1423 | 1444 | // Update by MediaWiki page id --> make sure we get all pages. |
1424 | 1445 | $tids = array(); |
— | — | @@ -1438,26 +1459,35 @@ |
1439 | 1460 | |
1440 | 1461 | // update by internal SMW id --> make sure we get all objects in SMW |
1441 | 1462 | $db = wfGetDB( DB_SLAVE ); |
1442 | | - $res = $db->select( 'smw_ids', array( 'smw_id', 'smw_title', 'smw_namespace', 'smw_iw' ), |
1443 | | - "smw_id >= $index AND smw_id < " . $db->addQuotes( $index + $count ), __METHOD__ ); |
| 1463 | + $res = $db->select( 'smw_ids', array( 'smw_id', 'smw_title', 'smw_namespace', 'smw_iw', 'smw_subobject' ), |
| 1464 | + "smw_id >= $index AND smw_id < " . $db->addQuotes( $index + $count ), __METHOD__ ); |
1444 | 1465 | |
1445 | 1466 | foreach ( $res as $row ) { |
1446 | 1467 | $emptyrange = false; // note this even if no jobs were created |
1447 | 1468 | |
1448 | 1469 | if ( $namespaces && !in_array( $row->smw_namespace, $namespaces ) ) continue; |
1449 | 1470 | |
1450 | | - if ( $row->smw_iw == '' || $row->smw_iw == SMW_SQL2_SMWREDIIW ) { // objects representing pages in the wiki, even special pages |
1451 | | - // TODO: special treament of redirects needed, since the store will not act on redirects that did not change according to its records |
| 1471 | + if ( $row->smw_subobject != '' ) { |
| 1472 | + // leave subobjects alone; they ought to be changed with their pages |
| 1473 | + } elseif ( $row->smw_iw == '' || $row->smw_iw == SMW_SQL2_SMWREDIIW ) { // objects representing pages |
| 1474 | + // TODO: special treament of redirects needed, since the store will |
| 1475 | + // not act on redirects that did not change according to its records |
1452 | 1476 | $title = Title::makeTitleSafe( $row->smw_namespace, $row->smw_title ); |
1453 | 1477 | |
1454 | 1478 | if ( $title !== null && !$title->exists() ) { |
1455 | 1479 | $updatejobs[] = new SMWUpdateJob( $title ); |
1456 | 1480 | } |
1457 | | - } elseif ( $row->smw_iw { 0 } != ':' ) { // refresh all "normal" interwiki pages by just clearing their content |
1458 | | - $this->deleteSemanticData( |
1459 | | - new SMWDIWikiPage( $row->smw_title, $row->smw_namespace, $row->smw_iw ) |
1460 | | - ); |
1461 | | - } |
| 1481 | + } elseif ( $row->smw_iw == SMW_SQL2_SMWIW_OUTDATED ) { // remove outdated internal object references |
| 1482 | + foreach ( self::getPropertyTables() as $proptable ) { |
| 1483 | + if ( $proptable->idsubject ) { |
| 1484 | + $db->delete( $proptable->name, array( 's_id' => $row->smw_id ), __METHOD__ ); |
| 1485 | + } |
| 1486 | + } |
| 1487 | + $db->delete( 'smw_ids', array( 'smw_id' => $sow->smw_id ), __METHOD__ ); |
| 1488 | + } else { // "normal" interwiki pages or outdated internal objects |
| 1489 | + $diWikiPage = new SMWDIWikiPage( $row->smw_title, $row->smw_namespace, $row->smw_iw ); |
| 1490 | + $this->deleteSemanticData( $diWikiPage ); |
| 1491 | + } |
1462 | 1492 | } |
1463 | 1493 | $db->freeResult( $res ); |
1464 | 1494 | |
— | — | @@ -1476,12 +1506,12 @@ |
1477 | 1507 | if ( $emptyrange ) { // nothing found, check if there will be more pages later on |
1478 | 1508 | $next1 = $db->selectField( 'page', 'page_id', "page_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "page_id ASC" ) ); |
1479 | 1509 | $next2 = $db->selectField( 'smw_ids', 'smw_id', "smw_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "smw_id ASC" ) ); |
1480 | | - $nextpos = ( ( $next2 != 0 ) && ( $next2 < $next1 ) ) ? $next2:$next1; |
| 1510 | + $nextpos = ( ( $next2 != 0 ) && ( $next2 < $next1 ) ) ? $next2 : $next1; |
1481 | 1511 | } |
1482 | 1512 | |
1483 | 1513 | $max1 = $db->selectField( 'page', 'MAX(page_id)', '', __METHOD__ ); |
1484 | 1514 | $max2 = $db->selectField( 'smw_ids', 'MAX(smw_id)', '', __METHOD__ ); |
1485 | | - $index = $nextpos ? $nextpos: - 1; |
| 1515 | + $index = $nextpos ? $nextpos : -1; |
1486 | 1516 | |
1487 | 1517 | return ( $index > 0 ) ? $index / max( $max1, $max2 ) : 1; |
1488 | 1518 | } |
— | — | @@ -1543,7 +1573,7 @@ |
1544 | 1574 | wfProfileIn( 'SMWSQLStore2::getConceptCacheStatus (SMW)' ); |
1545 | 1575 | |
1546 | 1576 | $db = wfGetDB( DB_SLAVE ); |
1547 | | - $cid = $this->getSMWPageID( $concept->getDBkey(), $concept->getNamespace(), '', false ); |
| 1577 | + $cid = $this->getSMWPageID( $concept->getDBkey(), $concept->getNamespace(), '', '', false ); |
1548 | 1578 | |
1549 | 1579 | $row = $db->selectRow( 'smw_conc2', |
1550 | 1580 | array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date', 'cache_count' ), |
— | — | @@ -1775,18 +1805,6 @@ |
1776 | 1806 | |
1777 | 1807 | /** |
1778 | 1808 | * Check if the given table can be used to store values of the given |
1779 | | - * signature, where $signature is as returned by getTypeSignature(). |
1780 | | - * @todo Maybe rather use SMWSQLStore2Table object as parameter. |
1781 | | - */ |
1782 | | -// private static function tableFitsSignature( $tableid, $signature ) { |
1783 | | -// $proptables = self::getPropertyTables(); |
1784 | | -// $tablesig = str_replace( 'p', 'tnwt', $proptables[$tableid]->getFieldSignature() ); // expand internal page type to single fields |
1785 | | -// $valuesig = reset( $signature ); |
1786 | | -// return ( $valuesig == substr( $tablesig, 0, strlen( $valuesig ) ) ); |
1787 | | -// } |
1788 | | - |
1789 | | - /** |
1790 | | - * Check if the given table can be used to store values of the given |
1791 | 1809 | * type. This is needed to apply the type-based filtering in |
1792 | 1810 | * getSemanticData(). |
1793 | 1811 | * |
— | — | @@ -1878,9 +1896,9 @@ |
1879 | 1897 | * the canonical alias ID for the given page. If no such ID exists, 0 is |
1880 | 1898 | * returned. |
1881 | 1899 | */ |
1882 | | - public function getSMWPageID( $title, $namespace, $iw, $canonical = true ) { |
| 1900 | + public function getSMWPageID( $title, $namespace, $iw, $subobjectId, $canonical = true ) { |
1883 | 1901 | $sort = ''; |
1884 | | - return $this->getSMWPageIDandSort( $title, $namespace, $iw, $sort, $canonical ); |
| 1902 | + return $this->getSMWPageIDandSort( $title, $namespace, $iw, $subobjectId, $sort, $canonical ); |
1885 | 1903 | } |
1886 | 1904 | |
1887 | 1905 | /** |
— | — | @@ -1888,16 +1906,16 @@ |
1889 | 1907 | * the current sortkey. |
1890 | 1908 | * @todo Ensuring that properties redirect to properties only should not be done here. |
1891 | 1909 | * @todo Centralise creation of id cache keys, and make sure non-local pages have only one key |
1892 | | - * (no need to distniguish canonical/non-canonical in this case). |
| 1910 | + * (no need to distinguish canonical/non-canonical in this case). |
1893 | 1911 | */ |
1894 | | - public function getSMWPageIDandSort( $title, $namespace, $iw, &$sort, $canonical ) { |
| 1912 | + public function getSMWPageIDandSort( $title, $namespace, $iw, $subobjectId, &$sort, $canonical ) { |
1895 | 1913 | global $smwgQEqualitySupport; |
1896 | 1914 | |
1897 | 1915 | wfProfileIn( 'SMWSQLStore2::getSMWPageID (SMW)' ); |
1898 | 1916 | |
1899 | | - $ckey = "$iw $namespace $title C"; |
1900 | | - $nkey = "$iw $namespace $title -"; |
1901 | | - $key = ( $canonical ? $ckey:$nkey ); |
| 1917 | + $ckey = "$iw $namespace $title $subobjectId C"; |
| 1918 | + $nkey = "$iw $namespace $title $subobjectId -"; |
| 1919 | + $key = ( $canonical ? $ckey : $nkey ); |
1902 | 1920 | |
1903 | 1921 | if ( array_key_exists( $key, $this->m_ids ) ) { |
1904 | 1922 | wfProfileOut( 'SMWSQLStore2::getSMWPageID (SMW)' ); |
— | — | @@ -1915,7 +1933,7 @@ |
1916 | 1934 | $res = $db->select( |
1917 | 1935 | 'smw_ids', |
1918 | 1936 | array( 'smw_id', 'smw_sortkey' ), |
1919 | | - array( 'smw_title' => $title, 'smw_namespace' => $namespace, 'smw_iw' => $iw ), |
| 1937 | + array( 'smw_title' => $title, 'smw_namespace' => $namespace, 'smw_iw' => $iw, 'smw_subobject' => $subobjectId ), |
1920 | 1938 | 'SMW::getSMWPageID', array( 'LIMIT' => 1 ) |
1921 | 1939 | ); |
1922 | 1940 | $row = $db->fetchObject( $res ); |
— | — | @@ -1924,20 +1942,24 @@ |
1925 | 1943 | $sort = $row->smw_sortkey; |
1926 | 1944 | } |
1927 | 1945 | |
1928 | | - $this->m_ids[ $canonical ? $nkey:$ckey ] = $id; // unique id, make sure cache for canonical+non-cacnonical gets filled |
| 1946 | + $this->m_ids[ $canonical ? $nkey : $ckey ] = $id; // unique id, make sure cache for canonical+non-cacnonical gets filled: this line fills the cache that is not $key! |
1929 | 1947 | } else { // check for potential redirects also |
1930 | 1948 | $res = $db->select( 'smw_ids', array( 'smw_id', 'smw_iw', 'smw_sortkey' ), |
1931 | | - 'smw_title=' . $db->addQuotes( $title ) . ' AND smw_namespace=' . $db->addQuotes( $namespace ) . |
1932 | | - ' AND (smw_iw=' . $db->addQuotes( '' ) . ' OR smw_iw=' . $db->addQuotes( SMW_SQL2_SMWREDIIW ) . ')', |
| 1949 | + 'smw_title=' . $db->addQuotes( $title ) . |
| 1950 | + ' AND smw_namespace=' . $db->addQuotes( $namespace ) . |
| 1951 | + ' AND (smw_iw=' . $db->addQuotes( '' ) . |
| 1952 | + ' OR smw_iw=' . $db->addQuotes( SMW_SQL2_SMWREDIIW ) . ')' . |
| 1953 | + ' AND smw_subobject=' . $db->addQuotes( $subobjectId ), |
1933 | 1954 | 'SMW::getSMWPageID', array( 'LIMIT' => 1 ) ); |
1934 | 1955 | $row = $db->fetchObject( $res ); |
| 1956 | + |
1935 | 1957 | if ( $row ) { |
1936 | 1958 | $id = $row->smw_id; // set id in any case, the below check for properties will use even the redirect id in emergency |
1937 | 1959 | $sort = $row->smw_sortkey; |
1938 | 1960 | |
1939 | 1961 | if ( ( $row->smw_iw == '' ) ) { // the id found is unique (canonical and non-canonical); fill cache also for the case *not* asked for |
1940 | | - $this->m_ids[ $canonical ? $nkey:$ckey ] = $id; // (the other cache is filled below) |
1941 | | - } elseif ( $canonical && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // get redirect alias |
| 1962 | + $this->m_ids[ $canonical ? $nkey : $ckey ] = $id; // (the other cache is filled below) |
| 1963 | + } elseif ( $canonical && ( $subobjectId == '' ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // check for redirect alias |
1942 | 1964 | if ( $namespace == SMW_NS_PROPERTY ) { // redirect properties only to properties |
1943 | 1965 | ///TODO: Shouldn't this condition be ensured during writing? |
1944 | 1966 | $res2 = $db->select( array( 'smw_redi2', 'smw_ids' ), 'o_id', |
— | — | @@ -1956,6 +1978,7 @@ |
1957 | 1979 | $db->freeResult( $res2 ); |
1958 | 1980 | } |
1959 | 1981 | } |
| 1982 | + |
1960 | 1983 | } |
1961 | 1984 | |
1962 | 1985 | $db->freeResult( $res ); |
— | — | @@ -1976,15 +1999,15 @@ |
1977 | 2000 | * the title is a redirect target (we do not want chains of redirects). |
1978 | 2001 | * But it is of no relevance if the title does not have an id yet. |
1979 | 2002 | */ |
1980 | | - protected function makeSMWPageID( $title, $namespace, $iw, $canonical = true, $sortkey = '' ) { |
| 2003 | + protected function makeSMWPageID( $title, $namespace, $iw, $subobjectId, $canonical = true, $sortkey = '' ) { |
1981 | 2004 | wfProfileIn( 'SMWSQLStore2::makeSMWPageID (SMW)' ); |
1982 | 2005 | |
1983 | 2006 | $oldsort = ''; |
1984 | | - $id = $this->getSMWPageIDandSort( $title, $namespace, $iw, $oldsort, $canonical ); |
| 2007 | + $id = $this->getSMWPageIDandSort( $title, $namespace, $iw, $subobjectId, $oldsort, $canonical ); |
1985 | 2008 | |
1986 | 2009 | if ( $id == 0 ) { |
1987 | 2010 | $db = wfGetDB( DB_MASTER ); |
1988 | | - $sortkey = $sortkey ? $sortkey:( str_replace( '_', ' ', $title ) ); |
| 2011 | + $sortkey = $sortkey ? $sortkey : ( str_replace( '_', ' ', $title ) ); |
1989 | 2012 | |
1990 | 2013 | $db->insert( |
1991 | 2014 | 'smw_ids', |
— | — | @@ -1993,18 +2016,19 @@ |
1994 | 2017 | 'smw_title' => $title, |
1995 | 2018 | 'smw_namespace' => $namespace, |
1996 | 2019 | 'smw_iw' => $iw, |
| 2020 | + 'smw_subobject' => $subobjectId, |
1997 | 2021 | 'smw_sortkey' => $sortkey |
1998 | 2022 | ), |
1999 | 2023 | 'SMW::makeSMWPageID' |
2000 | 2024 | ); |
2001 | 2025 | |
2002 | 2026 | $id = $db->insertId(); |
2003 | | - $this->m_ids["$iw $namespace $title -"] = $id; // fill that cache, even if canonical was given |
| 2027 | + $this->m_ids["$iw $namespace $title $subobjectId -"] = $id; // fill that cache, even if canonical was given |
2004 | 2028 | |
2005 | 2029 | // This ID is also authorative for the canonical version. |
2006 | 2030 | // This is always the case: if $canonical===false and $id===0, then there is no redi-entry in |
2007 | 2031 | // smw_ids either, hence the object just did not exist at all. |
2008 | | - $this->m_ids["$iw $namespace $title C"] = $id; |
| 2032 | + $this->m_ids["$iw $namespace $title $subobjectId C"] = $id; |
2009 | 2033 | } elseif ( ( $sortkey != '' ) && ( $sortkey != $oldsort ) ) { |
2010 | 2034 | $db = wfGetDB( DB_MASTER ); |
2011 | 2035 | $db->update( 'smw_ids', array( 'smw_sortkey' => $sortkey ), array( 'smw_id' => $id ), 'SMW::makeSMWPageID' ); |
— | — | @@ -2037,7 +2061,7 @@ |
2038 | 2062 | if ( ( !$property->isUserDefined() ) && ( array_key_exists( $property->getKey(), self::$special_ids ) ) ) { |
2039 | 2063 | return self::$special_ids[$property->getKey()]; // very important property with fixed id |
2040 | 2064 | } else { |
2041 | | - return $this->getSMWPageID( $property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki( $property ), true ); |
| 2065 | + return $this->getSMWPageID( $property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki( $property ), '', true ); |
2042 | 2066 | } |
2043 | 2067 | } |
2044 | 2068 | |
— | — | @@ -2049,7 +2073,7 @@ |
2050 | 2074 | if ( ( !$property->isUserDefined() ) && ( array_key_exists( $property->getKey(), self::$special_ids ) ) ) { |
2051 | 2075 | return self::$special_ids[$property->getKey()]; // very important property with fixed id |
2052 | 2076 | } else { |
2053 | | - return $this->makeSMWPageID( $property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki( $property ), true ); |
| 2077 | + return $this->makeSMWPageID( $property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki( $property ), '', true ); |
2054 | 2078 | } |
2055 | 2079 | } |
2056 | 2080 | |
— | — | @@ -2060,9 +2084,9 @@ |
2061 | 2085 | * with iw being SMW_SQL2_SMWREDIIW. This information is used to determine |
2062 | 2086 | * whether the given ID is canonical or not. |
2063 | 2087 | */ |
2064 | | - public function cacheSMWPageID( $id, $title, $namespace, $iw ) { |
2065 | | - $ckey = "$iw $namespace $title C"; |
2066 | | - $nkey = "$iw $namespace $title -"; |
| 2088 | + public function cacheSMWPageID( $id, $title, $namespace, $iw, $subobjectId ) { |
| 2089 | + $ckey = "$iw $namespace $title $subobjectId C"; |
| 2090 | + $nkey = "$iw $namespace $title $subobjectId -"; |
2067 | 2091 | |
2068 | 2092 | if ( count( $this->m_ids ) > 1500 ) { // prevent memory leak in very long PHP runs |
2069 | 2093 | $this->m_ids = array(); |
— | — | @@ -2076,62 +2100,6 @@ |
2077 | 2101 | } |
2078 | 2102 | |
2079 | 2103 | /** |
2080 | | - * Get a numeric ID for some Bnode ("internal object") that is to be used |
2081 | | - * to encode a container property value. Bnodes are managed through the |
2082 | | - * smw_ids table but will always have an empty smw_title, and smw_namespace |
2083 | | - * being set to the parent object (the id of the page that uses the Bnode). |
2084 | | - * Unused Bnodes are not deleted but marked as available by setting |
2085 | | - * smw_namespace to 0. This method then tries to reuse an unused bnode |
2086 | | - * before making a new one. |
2087 | | - * @note Every call to this function, even if the same parameter id is |
2088 | | - * used, returns a new bnode id! |
2089 | | - */ |
2090 | | - protected function makeSMWBnodeID( $sid ) { |
2091 | | - $db = wfGetDB( DB_MASTER ); |
2092 | | - |
2093 | | - // check if there is an unused bnode to take: |
2094 | | - $res = $db->select( |
2095 | | - 'smw_ids', |
2096 | | - 'smw_id', |
2097 | | - array( |
2098 | | - 'smw_title' => '', |
2099 | | - 'smw_namespace' => 0, |
2100 | | - 'smw_iw' => SMW_SQL2_SMWIW |
2101 | | - ), |
2102 | | - 'SMW::makeSMWBnodeID', |
2103 | | - array( 'LIMIT' => 1 ) |
2104 | | - ); |
2105 | | - |
2106 | | - $id = ( $row = $db->fetchObject( $res ) ) ? $row->smw_id:0; |
2107 | | - $db->freeResult( $res ); |
2108 | | - |
2109 | | - // claim that bnode: |
2110 | | - if ( $id != 0 ) { |
2111 | | - $db->update( 'smw_ids', array( 'smw_namespace' => $sid ), |
2112 | | - array( 'smw_id' => $id, |
2113 | | - 'smw_title' => '', |
2114 | | - 'smw_namespace' => 0, |
2115 | | - 'smw_iw' => SMW_SQL2_SMWIW ), 'SMW::makeSMWBnodeID', array( 'LIMIT' => 1 ) ); |
2116 | | - |
2117 | | - if ( $db->affectedRows() == 0 ) { // Oops, someone was faster (collisions are possible here, no locks) |
2118 | | - $id = 0; // fallback: make a new node (TODO: we could also repeat to try another ID) |
2119 | | - } |
2120 | | - } |
2121 | | - // if no node was found yet, make a new one: |
2122 | | - if ( $id == 0 ) { |
2123 | | - $db->insert( 'smw_ids', |
2124 | | - array( 'smw_id' => $db->nextSequenceValue( 'smw_ids_smw_id_seq' ), |
2125 | | - 'smw_title' => '', |
2126 | | - 'smw_namespace' => $sid, |
2127 | | - 'smw_iw' => SMW_SQL2_SMWIW ), 'SMW::makeSMWBnodeID' ); |
2128 | | - |
2129 | | - $id = $db->insertId(); |
2130 | | - } |
2131 | | - |
2132 | | - return $id; |
2133 | | - } |
2134 | | - |
2135 | | - /** |
2136 | 2104 | * Change an internal id to another value. If no target value is given, the |
2137 | 2105 | * value is changed to become the last id entry (based on the automatic id |
2138 | 2106 | * increment of the database). Whatever currently occupies this id will be |
— | — | @@ -2143,10 +2111,10 @@ |
2144 | 2112 | */ |
2145 | 2113 | protected function moveSMWPageID( $curid, $targetid = 0 ) { |
2146 | 2114 | $db = wfGetDB( DB_MASTER ); |
2147 | | - |
| 2115 | + |
2148 | 2116 | $row = $db->selectRow( |
2149 | 2117 | 'smw_ids', |
2150 | | - array( 'smw_id', 'smw_namespace', 'smw_title', 'smw_iw', 'smw_sortkey' ), |
| 2118 | + array( 'smw_id', 'smw_namespace', 'smw_title', 'smw_iw', 'smw_subobject', 'smw_sortkey' ), |
2151 | 2119 | array( 'smw_id' => $curid ), 'SMWSQLStore2::moveSMWPageID' |
2152 | 2120 | ); |
2153 | 2121 | |
— | — | @@ -2160,6 +2128,7 @@ |
2161 | 2129 | 'smw_title' => $row->smw_title, |
2162 | 2130 | 'smw_namespace' => $row->smw_namespace, |
2163 | 2131 | 'smw_iw' => $row->smw_iw, |
| 2132 | + 'smw_subobject' => $row->smw_subobject, |
2164 | 2133 | 'smw_sortkey' => $row->smw_sortkey |
2165 | 2134 | ), |
2166 | 2135 | 'SMW::moveSMWPageID' |
— | — | @@ -2172,6 +2141,7 @@ |
2173 | 2142 | 'smw_title' => $row->smw_title, |
2174 | 2143 | 'smw_namespace' => $row->smw_namespace, |
2175 | 2144 | 'smw_iw' => $row->smw_iw, |
| 2145 | + 'smw_subobject' => $row->smw_subobject, |
2176 | 2146 | 'smw_sortkey' => $row->smw_sortkey |
2177 | 2147 | ), |
2178 | 2148 | 'SMW::moveSMWPageID' |
— | — | @@ -2183,15 +2153,20 @@ |
2184 | 2154 | } |
2185 | 2155 | |
2186 | 2156 | /** |
2187 | | - * Change an SMW page id across all relevant tables. The id in smw_ids as |
2188 | | - * such is not touched, but bnodes refering to the old object will be moved |
2189 | | - * along. The redirect table is also updated (without much effect if the |
2190 | | - * change happended due to some redirect, since the table should not |
2191 | | - * contain the id of the redirected page). If namespaces are given, then |
2192 | | - * they are used to delete any entries that are limited to one particular |
2193 | | - * namespace (e.g. only properties can be used as properties) instead of |
2194 | | - * moving them. |
| 2157 | + * Change an SMW page id across all relevant tables. The redirect table |
| 2158 | + * is also updated (without much effect if the change happended due to |
| 2159 | + * some redirect, since the table should not contain the id of the |
| 2160 | + * redirected page). If namespaces are given, then they are used to |
| 2161 | + * delete any entries that are limited to one particular namespace (e.g. |
| 2162 | + * only properties can be used as properties) instead of moving them. |
2195 | 2163 | * |
| 2164 | + * The id in smw_ids as such is not touched. |
| 2165 | + * |
| 2166 | + * @note This method only changes internal page IDs in SMW. It does not |
| 2167 | + * assume any change in (title-related) data, as e.g. in a page move. |
| 2168 | + * Internal objects (subobject) do not need to be updated since they |
| 2169 | + * refer to the title of their parent page, not to its ID. |
| 2170 | + * |
2196 | 2171 | * @param $oldid numeric ID that is to be changed |
2197 | 2172 | * @param $newid numeric ID to which the records are to be changed |
2198 | 2173 | * @param $oldnamespace namespace of old id's page (-1 to ignore it) |
— | — | @@ -2199,38 +2174,28 @@ |
2200 | 2175 | * @param $sdata boolean stating whether to update subject references |
2201 | 2176 | * @param $podata boolean stating if to update property/object references |
2202 | 2177 | */ |
2203 | | - protected function changeSMWPageID( $oldid, $newid, $oldnamespace = -1, $newnamespace = -1, $sdata = true, $podata = true ) { |
2204 | | - $fname = 'SMW::changeSMWPageID'; |
| 2178 | + protected function changeSMWPageID( $oldid, $newid, $oldnamespace = -1, |
| 2179 | + $newnamespace = -1, $sdata = true, $podata = true ) { |
2205 | 2180 | $db = wfGetDB( DB_MASTER ); |
2206 | 2181 | |
2207 | | - // Update bnode references that use namespace field to store ids: |
2208 | | - if ( $sdata ) { // bnodes are part of the data of a subject |
2209 | | - $db->update( |
2210 | | - 'smw_ids', |
2211 | | - array( 'smw_namespace' => $newid ), |
2212 | | - array( 'smw_title' => '', 'smw_namespace' => $oldid, 'smw_iw' => SMW_SQL2_SMWIW ), |
2213 | | - $fname |
2214 | | - ); |
2215 | | - } |
2216 | | - |
2217 | 2182 | // Change all id entries in property tables: |
2218 | 2183 | foreach ( self::getPropertyTables() as $proptable ) { |
2219 | 2184 | if ( $sdata && $proptable->idsubject ) { |
2220 | | - $db->update( $proptable->name, array( 's_id' => $newid ), array( 's_id' => $oldid ), $fname ); |
| 2185 | + $db->update( $proptable->name, array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ ); |
2221 | 2186 | } |
2222 | 2187 | |
2223 | 2188 | if ( $podata ) { |
2224 | 2189 | if ( ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_PROPERTY ) ) && ( $proptable->fixedproperty == false ) ) { |
2225 | 2190 | if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_PROPERTY ) ) { |
2226 | | - $db->update( $proptable->name, array( 'p_id' => $newid ), array( 'p_id' => $oldid ), $fname ); |
| 2191 | + $db->update( $proptable->name, array( 'p_id' => $newid ), array( 'p_id' => $oldid ), __METHOD__ ); |
2227 | 2192 | } else { |
2228 | | - $db->delete( $proptable->name, array( 'p_id' => $oldid ), $fname ); |
| 2193 | + $db->delete( $proptable->name, array( 'p_id' => $oldid ), __METHOD__ ); |
2229 | 2194 | } |
2230 | 2195 | } |
2231 | 2196 | |
2232 | 2197 | foreach ( $proptable->objectfields as $fieldname => $type ) { |
2233 | 2198 | if ( $type == 'p' ) { |
2234 | | - $db->update( $proptable->name, array( $fieldname => $newid ), array( $fieldname => $oldid ), $fname ); |
| 2199 | + $db->update( $proptable->name, array( $fieldname => $newid ), array( $fieldname => $oldid ), __METHOD__ ); |
2235 | 2200 | } |
2236 | 2201 | } |
2237 | 2202 | } |
— | — | @@ -2239,30 +2204,31 @@ |
2240 | 2205 | // Change id entries in concept-related tables: |
2241 | 2206 | if ( $sdata && ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_CONCEPT ) ) ) { |
2242 | 2207 | if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_CONCEPT ) ) { |
2243 | | - $db->update( 'smw_conc2', array( 's_id' => $newid ), array( 's_id' => $oldid ), $fname ); |
2244 | | - $db->update( 'smw_conccache', array( 's_id' => $newid ), array( 's_id' => $oldid ), $fname ); |
| 2208 | + $db->update( 'smw_conc2', array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ ); |
| 2209 | + $db->update( 'smw_conccache', array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ ); |
2245 | 2210 | } else { |
2246 | | - $db->delete( 'smw_conc2', array( 's_id' => $oldid ), $fname ); |
2247 | | - $db->delete( 'smw_conccache', array( 's_id' => $oldid ), $fname ); |
| 2211 | + $db->delete( 'smw_conc2', array( 's_id' => $oldid ), __METHOD__ ); |
| 2212 | + $db->delete( 'smw_conccache', array( 's_id' => $oldid ), __METHOD__ ); |
2248 | 2213 | } |
2249 | 2214 | } |
2250 | 2215 | |
2251 | 2216 | if ( $podata ) { |
2252 | | - $db->update( 'smw_conccache', array( 'o_id' => $newid ), array( 'o_id' => $oldid ), $fname ); |
| 2217 | + $db->update( 'smw_conccache', array( 'o_id' => $newid ), array( 'o_id' => $oldid ), __METHOD__ ); |
2253 | 2218 | } |
2254 | 2219 | } |
2255 | 2220 | |
2256 | 2221 | /** |
2257 | 2222 | * Delete all semantic data stored for the given subject. Used for |
2258 | 2223 | * update purposes. |
2259 | | - * |
| 2224 | + * |
2260 | 2225 | * @param $subject SMWDIWikiPage the data of which is deleted |
2261 | 2226 | */ |
2262 | 2227 | protected function deleteSemanticData( SMWDIWikiPage $subject ) { |
| 2228 | + if ( $subject->getSubobjectId() != '' ) return; // not needed, and would mess up data |
| 2229 | + |
2263 | 2230 | $db = wfGetDB( DB_MASTER ); |
2264 | 2231 | |
2265 | | - $fname = 'SMW::deleteSemanticData'; |
2266 | | - $id = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), false ); |
| 2232 | + $id = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), '', false ); |
2267 | 2233 | |
2268 | 2234 | if ( $id == 0 ) { |
2269 | 2235 | // not (directly) used anywhere yet, may be a redirect but we do not care here |
— | — | @@ -2273,28 +2239,39 @@ |
2274 | 2240 | foreach ( self::getPropertyTables() as $proptable ) { |
2275 | 2241 | if ( $proptable->name == 'smw_conc2' ) continue; // skip concepts, since they have chache data in their table which should be kept while the cache is intact |
2276 | 2242 | if ( $proptable->idsubject ) { |
2277 | | - $db->delete( $proptable->name, array( 's_id' => $id ), "$fname::deleteById" ); |
| 2243 | + $db->delete( $proptable->name, array( 's_id' => $id ), __METHOD__ ); |
2278 | 2244 | } elseif ( $proptable->name != 'smw_redi2' ) { /// NOTE: redirects are handled by updateRedirects(), not here! |
2279 | | - $db->delete( $proptable->name, array( 's_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace() ), "$fname::deleteByTitle" ); |
| 2245 | + $db->delete( $proptable->name, array( 's_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace() ), __METHOD__ ); |
2280 | 2246 | } |
2281 | 2247 | } |
2282 | 2248 | |
2283 | | - // also find bnodes used by this ID ... |
2284 | | - $res = $db->select( 'smw_ids', 'smw_id', array( 'smw_title' => '', 'smw_namespace' => $id, 'smw_iw' => SMW_SQL2_SMWIW ), "$fname::selectBnodes" ); |
| 2249 | + // also find subobjects used by this ID ... |
| 2250 | + $res = $db->select( 'smw_ids', 'smw_id', |
| 2251 | + array( 'smw_title' => $subject->getDBkey(), |
| 2252 | + 'smw_namespace' => $subject->getNamespace(), |
| 2253 | + 'smw_iw' => $subject->getInterwiki(), |
| 2254 | + 'smw_subobject!' => array( '' ) ), // ! (NOT) in MW only supported for array values! |
| 2255 | + __METHOD__ ); |
| 2256 | + $subobjects = array(); |
2285 | 2257 | |
2286 | 2258 | // ... and delete them as well |
2287 | 2259 | foreach ( $res as $row ) { |
| 2260 | + $subobjects[] = $row->smw_id; |
2288 | 2261 | foreach ( self::getPropertyTables() as $proptable ) { |
2289 | 2262 | if ( $proptable->idsubject ) { |
2290 | | - $db->delete( $proptable->name, array( 's_id' => $row->smw_id ), "$fname::deleteBnodes" ); |
| 2263 | + $db->delete( $proptable->name, array( 's_id' => $row->smw_id ), __METHOD__ ); |
2291 | 2264 | } |
2292 | 2265 | } |
2293 | 2266 | } |
2294 | 2267 | |
2295 | 2268 | $db->freeResult( $res ); |
2296 | 2269 | |
2297 | | - // free all affected bnodes in one call: |
2298 | | - $db->update( 'smw_ids', array( 'smw_namespace' => 0 ), array( 'smw_title' => '', 'smw_namespace' => $id, 'smw_iw' => SMW_SQL2_SMWIW ), "$fname::updateBnodes" ); |
| 2270 | + // free all affected subobjects in one call: |
| 2271 | + if ( count( $subobjects ) > 0 ) { |
| 2272 | + $db->delete( 'smw_ids', |
| 2273 | + array( 'smw_id' => $subobjects), |
| 2274 | + __METHOD__ ); |
| 2275 | + } |
2299 | 2276 | |
2300 | 2277 | wfRunHooks( 'smwDeleteSemanticData', array( $subject ) ); |
2301 | 2278 | } |
— | — | @@ -2309,32 +2286,38 @@ |
2310 | 2287 | * This method does not change the ids of the affected pages, and thus it |
2311 | 2288 | * is not concerned with updates of the data that is currently stored for |
2312 | 2289 | * the subject. Normally, a subject that is a redirect will not have other |
2313 | | - * data, but this method does not depend upon this in any way. |
| 2290 | + * data, but this method does not depend on this. |
2314 | 2291 | * |
2315 | 2292 | * @note Please make sure you fully understand this code before making any |
2316 | 2293 | * changes here. Keeping the redirect structure consistent is important, |
2317 | 2294 | * and errors in this code can go unnoticed for quite some time. |
| 2295 | + * |
| 2296 | + * @note This method merely handles the addition or deletion of a redirect |
| 2297 | + * statement in the wiki. It does not assume that any page contents has |
| 2298 | + * been changed (e.g. moved). See changeTitle() for additional handling in |
| 2299 | + * this case. |
2318 | 2300 | */ |
2319 | 2301 | protected function updateRedirects( $subject_t, $subject_ns, $curtarget_t = '', $curtarget_ns = -1 ) { |
2320 | 2302 | global $smwgQEqualitySupport, $smwgEnableUpdateJobs; |
2321 | | - $fname = 'SMW::updateRedirects'; |
2322 | 2303 | |
2323 | 2304 | // *** First get id of subject, old redirect target, and current (new) redirect target ***// |
2324 | | - $sid = $this->getSMWPageID( $subject_t, $subject_ns, '', false ); // find real id of subject, if any |
| 2305 | + |
| 2306 | + $sid = $this->getSMWPageID( $subject_t, $subject_ns, '', '', false ); // find real id of subject, if any |
2325 | 2307 | /// NOTE: $sid can be 0 here; this is useful to know since it means that fewer table updates are needed |
2326 | | - $new_tid = $curtarget_t ? ( $this->makeSMWPageID( $curtarget_t, $curtarget_ns, '', false ) ):0; // real id of new target, if given |
| 2308 | + $new_tid = $curtarget_t ? ( $this->makeSMWPageID( $curtarget_t, $curtarget_ns, '', '', false ) ) : 0; // real id of new target, if given |
| 2309 | + |
2327 | 2310 | $db = wfGetDB( DB_SLAVE ); |
| 2311 | + $row = $db->selectRow( array( 'smw_redi2' ), 'o_id', |
| 2312 | + array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), __METHOD__ ); |
| 2313 | + $old_tid = ( $row !== false ) ? $row->o_id : 0; // real id of old target, if any |
| 2314 | + /// NOTE: $old_tid and $new_tid both (intentionally) ignore further redirects: no redirect chains |
2328 | 2315 | |
2329 | | - $res = $db->select( array( 'smw_redi2' ), 'o_id', array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), $fname, array( 'LIMIT' => 1 ) ); |
2330 | | - $old_tid = ( $row = $db->fetchObject( $res ) ) ? $row->o_id:0; // real id of old target, if any |
2331 | | - $db->freeResult( $res ); |
2332 | | - /// NOTE: $old_tid and $new_tid both ignore further redirects, (intentionally) no redirect chains! |
2333 | | - |
2334 | 2316 | if ( $old_tid == $new_tid ) { // no change, all happy |
2335 | | - return ( $new_tid == 0 ) ? $sid:$new_tid; |
2336 | | - } // note that this means $old_tid!=$new_tid in all cases below |
| 2317 | + return ( $new_tid == 0 ) ? $sid : $new_tid; |
| 2318 | + } // note that this means $old_tid != $new_tid in all cases below |
2337 | 2319 | |
2338 | 2320 | // *** Make relevant changes in property tables (don't write the new redirect yet) ***// |
| 2321 | + |
2339 | 2322 | $db = wfGetDB( DB_MASTER ); // now we need to write something |
2340 | 2323 | |
2341 | 2324 | if ( ( $old_tid == 0 ) && ( $sid != 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // new redirect |
— | — | @@ -2342,83 +2325,98 @@ |
2343 | 2326 | // Since references must not be 0, we don't have to do this is $sid == 0. |
2344 | 2327 | $this->changeSMWPageID( $sid, $new_tid, $subject_ns, $curtarget_ns, false, true ); |
2345 | 2328 | } elseif ( $old_tid != 0 ) { // existing redirect is changed or deleted |
2346 | | - $db->delete( 'smw_redi2', array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), $fname ); |
| 2329 | + $db->delete( 'smw_redi2', |
| 2330 | + array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), __METHOD__ ); |
2347 | 2331 | |
2348 | 2332 | if ( $smwgEnableUpdateJobs && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { |
2349 | | - // entries that refer to old target may in fact refer to subject, but we don't know which: schedule affected pages for update |
| 2333 | + // entries that refer to old target may in fact refer to subject, |
| 2334 | + // but we don't know which: schedule affected pages for update |
2350 | 2335 | $jobs = array(); |
2351 | 2336 | |
2352 | 2337 | foreach ( self::getPropertyTables() as $proptable ) { |
2353 | 2338 | if ( $proptable->name == 'smw_redi2' ) continue; // can safely be skipped |
2354 | 2339 | |
2355 | 2340 | if ( $proptable->idsubject ) { |
2356 | | - $from = $db->tableName( $proptable->name ) . ' INNER JOIN ' . $db->tableName( 'smw_ids' ) . ' ON s_id=smw_id'; |
2357 | | - $select = 'DISTINCT smw_title AS title,smw_namespace AS namespace'; |
| 2341 | + $from = $db->tableName( $proptable->name ) . ' INNER JOIN ' . |
| 2342 | + $db->tableName( 'smw_ids' ) . ' ON s_id=smw_id'; |
| 2343 | + $select = 'DISTINCT smw_title AS t,smw_namespace AS ns'; |
2358 | 2344 | } else { |
2359 | | - $from = $db->tableName( $proptable->name ); |
2360 | | - $select = 'DISTINCT s_title AS title,s_namespace AS namespace'; |
| 2345 | + $from = $db->tableName( $proptable->name ); |
| 2346 | + $select = 'DISTINCT s_title AS t,s_namespace AS ns'; |
2361 | 2347 | } |
2362 | 2348 | |
2363 | | - if ( ( $subject_ns == SMW_NS_PROPERTY ) && ( $proptable->fixedproperty == false ) ) { |
2364 | | - $res = $db->select( $from, $select, array( 'p_id' => $old_tid ), $fname ); |
2365 | | - |
| 2349 | + if ( $subject_ns == SMW_NS_PROPERTY && !$proptable->fixedproperty ) { |
| 2350 | + $res = $db->select( $from, $select, |
| 2351 | + array( 'p_id' => $old_tid ), __METHOD__ ); |
2366 | 2352 | foreach ( $res as $row ) { |
2367 | | - $title = Title::makeTitleSafe( $row->namespace, $row->title ); |
2368 | | - if ( $title !== null ) { |
| 2353 | + $title = Title::makeTitleSafe( $row->ns, $row->t ); |
| 2354 | + if ( !is_null( $title ) ) { |
2369 | 2355 | $jobs[] = new SMWUpdateJob( $title ); |
2370 | 2356 | } |
2371 | 2357 | } |
2372 | | - |
2373 | 2358 | $db->freeResult( $res ); |
2374 | 2359 | } |
2375 | 2360 | |
2376 | 2361 | foreach ( $proptable->objectfields as $fieldname => $type ) { |
2377 | 2362 | if ( $type == 'p' ) { |
2378 | | - $res = $db->select( $from, $select, array( $fieldname => $old_tid ), $fname ); |
2379 | | - |
| 2363 | + $res = $db->select( $from, $select, |
| 2364 | + array( $fieldname => $old_tid ), __METHOD__ ); |
2380 | 2365 | foreach ( $res as $row ) { |
2381 | | - $title = Title::makeTitleSafe( $row->namespace, $row->title ); |
2382 | | - if ( $title !== null ) { |
| 2366 | + $title = Title::makeTitleSafe( $row->ns, $row->t ); |
| 2367 | + if ( !is_null( $title ) ) { |
2383 | 2368 | $jobs[] = new SMWUpdateJob( $title ); |
2384 | 2369 | } |
2385 | 2370 | } |
2386 | | - |
2387 | 2371 | $db->freeResult( $res ); |
2388 | 2372 | } |
2389 | 2373 | } |
2390 | 2374 | } |
2391 | | - |
| 2375 | + |
2392 | 2376 | /// NOTE: we do not update the concept cache here; this remains an offline task |
2393 | | - Job::batchInsert( $jobs ); ///NOTE: this only happens if $smwgEnableUpdateJobs was true above |
| 2377 | + |
| 2378 | + /// NOTE: this only happens if $smwgEnableUpdateJobs was true above: |
| 2379 | + Job::batchInsert( $jobs ); |
2394 | 2380 | } |
2395 | 2381 | } |
2396 | 2382 | |
2397 | 2383 | // *** Finally, write the new redirect data ***// |
2398 | | - if ( $new_tid != 0 ) { // record new redirect |
| 2384 | + |
| 2385 | + if ( $new_tid != 0 ) { // record a new redirect |
2399 | 2386 | // Redirecting done right: |
2400 | | - // make a new ID with iw SMW_SQL2_SMWREDIIW or change iw field of current ID in this way, write smw_redi2 table, update canonical cache |
| 2387 | + // (1) make a new ID with iw SMW_SQL2_SMWREDIIW or |
| 2388 | + // change iw field of current ID in this way, |
| 2389 | + // (2) write smw_redi2 table, |
| 2390 | + // (3) update canonical cache. |
2401 | 2391 | // This order must be obeyed unless you really understand what you are doing! |
2402 | | - if ( ( $old_tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // mark subject as redirect (if it was no redirect before) |
| 2392 | + |
| 2393 | + if ( ( $old_tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { |
| 2394 | + // mark subject as redirect (if it was no redirect before) |
2403 | 2395 | if ( $sid == 0 ) { // every redirect page must have an ID |
2404 | | - $sid = $this->makeSMWPageID( $subject_t, $subject_ns, SMW_SQL2_SMWREDIIW, false ); |
| 2396 | + $sid = $this->makeSMWPageID( $subject_t, $subject_ns, |
| 2397 | + SMW_SQL2_SMWREDIIW, '', false ); |
2405 | 2398 | } else { |
2406 | | - $db->update( 'smw_ids', array( 'smw_iw' => SMW_SQL2_SMWREDIIW ), array( 'smw_id' => $sid ), $fname ); |
| 2399 | + $db->update( 'smw_ids', array( 'smw_iw' => SMW_SQL2_SMWREDIIW ), |
| 2400 | + array( 'smw_id' => $sid ), __METHOD__ ); |
2407 | 2401 | } |
2408 | 2402 | } |
2409 | 2403 | |
2410 | | - $db->insert( 'smw_redi2', array( 's_title' => $subject_t, 's_namespace' => $subject_ns, 'o_id' => $new_tid ), $fname ); |
2411 | | - $this->m_ids[" $subject_ns $subject_t C"] = $new_tid; // "iw" is empty here |
| 2404 | + $db->insert( 'smw_redi2', array( 's_title' => $subject_t, |
| 2405 | + 's_namespace' => $subject_ns, |
| 2406 | + 'o_id' => $new_tid ), __METHOD__ ); |
| 2407 | + $this->m_ids[" $subject_ns $subject_t C"] = $new_tid; |
2412 | 2408 | } else { // delete old redirect |
2413 | 2409 | // This case implies $old_tid != 0 (or we would have new_tid == old_tid above). |
2414 | | - // Therefore $subject had a redirect, and it must also have an ID. This shows that $sid != 0 here. |
2415 | | - $this->m_ids[" $subject_ns $subject_t C"] = $sid; // "iw" is empty here |
| 2410 | + // Therefore $subject had a redirect, and it must also have an ID. |
| 2411 | + // This shows that $sid != 0 here. |
| 2412 | + $this->m_ids[" $subject_ns $subject_t C"] = $sid; |
2416 | 2413 | |
2417 | 2414 | if ( $smwgQEqualitySupport != SMW_EQ_NONE ) { // mark subject as non-redirect |
2418 | | - $db->update( 'smw_ids', array( 'smw_iw' => '' ), array( 'smw_id' => $sid ), $fname ); |
| 2415 | + $db->update( 'smw_ids', array( 'smw_iw' => '' ), array( 'smw_id' => $sid ), __METHOD__ ); |
2419 | 2416 | } |
2420 | 2417 | } |
2421 | 2418 | |
2422 | | - // *** Flush some caches to be safe, though they are not essential in program runs with redirect updates ***// |
| 2419 | + // *** Flush some caches to be safe, though they are not essential in runs with redirect updates ***// |
| 2420 | + |
2423 | 2421 | unset( $this->m_semdata[$sid] ); unset( $this->m_semdata[$new_tid] ); unset( $this->m_semdata[$old_tid] ); |
2424 | 2422 | unset( $this->m_sdstate[$sid] ); unset( $this->m_sdstate[$new_tid] ); unset( $this->m_sdstate[$old_tid] ); |
2425 | 2423 | |