r91449 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r91448‎ | r91449 | r91450 >
Date:10:53, 5 July 2011
Author:mkroetzsch
Status:deferred (Comments)
Tags:
Comment:
rewritten code related to encoding/storage/retrieval of containers using internal objects;
internal objects now represented by DIWikiPages, no more special cases for "blank nodes";
extended dictionary table for SMWIDs accordingly;
updated read and write methods to use the new encoding
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SqlStubSemanticData.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php
@@ -93,8 +93,8 @@
9494 public function refreshConceptCache( Title $concept ) {
9595 global $smwgQMaxLimit, $smwgQConceptFeatures, $wgDBtype;
9696
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 );
9999
100100 if ( $cid != $cid_c ) {
101101 $this->m_errors[] = "Skipping redirect concept.";
@@ -162,7 +162,7 @@
163163 * @param $concept Title
164164 */
165165 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 );
167167 $this->m_dbs->delete( 'smw_conccache', array( 'o_id' => $cid ), 'SMW::refreshConceptCache' );
168168 $this->m_dbs->update( 'smw_conc2', array( 'cache_date' => null, 'cache_count' => null ), array( 's_id' => $cid ), 'SMW::refreshConceptCache' );
169169 }
@@ -384,7 +384,7 @@
385385 $sortfields = implode( $qobj->sortfields, ',' );
386386
387387 $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" .
389389 ( $wgDBtype == 'postgres' ? ( ( $sortfields ? ',' : '' ) . $sortfields ) : '' ),
390390 $qobj->where, 'SMW::getQueryResult', $sql_options );
391391
@@ -394,9 +394,9 @@
395395
396396 while ( ( $count < $query->getLimit() ) && ( $row = $this->m_dbs->fetchObject( $res ) ) ) {
397397 $count++;
398 - $v = new SMWDIWikiPage( $row->t, $row->ns, $row->iw );
 398+ $v = new SMWDIWikiPage( $row->t, $row->ns, $row->iw, $row->so );
399399 $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 );
401401 }
402402
403403 if ( $this->m_dbs->fetchObject( $res ) ) {
@@ -457,7 +457,7 @@
458458 $cquery->joinfield = array();
459459
460460 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(), '' );
462462 if ( $cid != 0 ) {
463463 $cquery->joinfield[] = $cid;
464464 }
@@ -477,7 +477,7 @@
478478 if ( $description->getDataItem() instanceof SMWDIWikiPage ) {
479479 if ( $description->getComparator() == SMW_CMP_EQ ) {
480480 $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() );
482482 $query->joinfield = array( $oid );
483483 } else { // Join with smw_ids needed for other comparators (apply to title string).
484484 $query->jointable = 'smw_ids';
@@ -500,7 +500,7 @@
501501 }
502502 }
503503 } 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, '', '' );
505505 // We bypass the storage interface here (which is legal as we controll it, and safe if we are careful with changes ...)
506506 // This should be faster, but we must implement the unescaping that concepts do on getWikiValue()
507507 $row = $this->m_dbs->selectRow(
@@ -778,9 +778,9 @@
779779 if ( $i >= count( $keys ) ) break;
780780
781781 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() );
784783 $where .= ( $where ? ' AND ' : '' ) . "{$query->alias}.$fname=" . $this->m_dbs->addQuotes( $oid );
 784+ break;
785785 } elseif ( $ftype != 'l' ) { // plain value, but not a text blob
786786 $where .= ( $where ? ' AND ' : '' ) . "{$query->alias}.$fname=" . $this->m_dbs->addQuotes( $keys[$i] );
787787 }
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SqlStubSemanticData.php
@@ -83,10 +83,21 @@
8484
8585 if ( array_key_exists( $property->getKey(), $this->mStubPropVals ) ) {
8686 $this->unstubProperty( $property->getKey(), $property );
 87+ $propertyTypeId = $property->findPropertyTypeID();
 88+ $propertyDiId = SMWDataValueFactory::getDataItemId( $propertyTypeId );
8789
8890 foreach ( $this->mStubPropVals[$property->getKey()] as $dbkeys ) {
8991 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+
91102 if ( $this->mNoDuplicates ) {
92103 $this->mPropVals[$property->getKey()][$di->getHash()] = $di;
93104 } else {
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2.php
@@ -11,7 +11,7 @@
1212 */
1313
1414 // 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)
1616 define( 'SMW_SQL2_SMWREDIIW', ':smw-redi' ); // virtual "interwiki prefix" for SMW objects that are redirected
1717 define( 'SMW_SQL2_SMWBORDERIW', ':smw-border' ); // virtual "interwiki prefix" separating very important pre-defined properties from the rest
1818 define( 'SMW_SQL2_SMWPREDEFIW', ':smw-preprop' ); // virtual "interwiki prefix" marking predefined objects (non-movable)
@@ -103,7 +103,7 @@
104104 SMWDataItem::TYPE_URI => 'smw_atts2',
105105 SMWDataItem::TYPE_TIME => 'smw_atts2',
106106 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
108108 SMWDataItem::TYPE_WIKIPAGE => 'smw_rels2',
109109 SMWDataItem::TYPE_CONCEPT => 'smw_conc2', // unlikely to occur as value of a normal property
110110 SMWDataItem::TYPE_PROPERTY => 'smw_atts2' // unlikely to occur as value of any property
@@ -119,7 +119,7 @@
120120
121121 // *** Find out if this subject exists ***//
122122 $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 );
124124 if ( $sid == 0 ) { // no data, safe our time
125125 /// NOTE: we consider redirects for getting $sid, so $sid == 0 also means "no redirects"
126126 self::$in_getSemanticData--;
@@ -202,14 +202,30 @@
203203 $proptables = self::getPropertyTables();
204204 $data = $this->fetchSemanticData( $pid, $property, $proptables[$tableid], false, $requestoptions );
205205 $result = array();
 206+ $propertyTypeId = $property->findPropertyTypeID();
 207+ $propertyDiId = SMWDataValueFactory::getDataItemId( $propertyTypeId );
206208
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+ }
213220 }
 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+ }
214230 }
215231 }
216232
@@ -255,7 +271,7 @@
256272 protected function fetchSemanticData( $id, $object, $proptable, $issubject = true, $requestoptions = null ) {
257273 // stop if there is not enough data:
258274 // 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();
260276
261277 wfProfileIn( "SMWSQLStore2::fetchSemanticData-" . $proptable->name . " (SMW)" );
262278 $result = array();
@@ -281,7 +297,6 @@
282298 }
283299
284300 $valuecount = 0;
285 - $pagevalues = array(); // collect indices of page-type components of this table (typically at most 1)
286301 $usedistinct = true; // use DISTINCT option only if no text blobs are among values
287302 $selectvalues = array(); // array for all values to be selected, kept to help finding value and label fields below
288303
@@ -294,15 +309,15 @@
295310 $selectvalues[$valuecount + 1] = "o$valuecount.smw_namespace";
296311 $selectvalues[$valuecount + 2] = "o$valuecount.smw_iw";
297312 $selectvalues[$valuecount + 3] = "o$valuecount.smw_sortkey";
 313+ $selectvalues[$valuecount + 4] = "o$valuecount.smw_subobject";
298314
299 - $pagevalues[] = $valuecount;
300 - $valuecount += 3;
 315+ $valuecount += 4;
301316 } else { // Just use value as given.
302317 $selectvalues[$valuecount] = $fieldname;
303318 }
304319
305320 if ( $typeid == 'l' ) $usedistinct = false;
306 - $valuecount++;
 321+ $valuecount += 1;
307322 }
308323
309324 foreach ( $selectvalues as $index => $field ) {
@@ -321,59 +336,34 @@
322337 // *** Now execute the query and read the results ***//
323338 $res = $db->select( $from, $select, $where, 'SMW::getSemanticData',
324339 ( $usedistinct ? $this->getSQLOptions( $requestoptions, $valuecolumn ) + array( 'DISTINCT' ) :
325 - $this->getSQLOptions( $requestoptions, $valuecolumn ) ) );
 340+ $this->getSQLOptions( $requestoptions, $valuecolumn ) ) );
326341
327342 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
331344 if ( $proptable->specpropsonly ) {
332345 $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;
338350 } else {
339351 $propertyname = $row->prop;
340352 }
341 - } else { // use fixed property name
 353+ } elseif ( $issubject ) { // use fixed property name
342354 $propertyname = $proptable->fixedproperty;
343355 }
344356
345357 $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
349359 $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;
375361 }
376362
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+ }
378368 }
379369
380370 $db->freeResult( $res );
@@ -418,10 +408,10 @@
419409
420410 if ( $proptable->idsubject ) { // join in smw_ids to get title data
421411 $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';
423413 } else { // no join needed, title+namespace as given in proptable
424414 $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';
426416 }
427417
428418 if ( $proptable->fixedproperty == false ) {
@@ -434,12 +424,14 @@
435425 $result = array();
436426 $res = $db->select( $from, 'DISTINCT ' . $select,
437427 $where . $this->getSQLConditions( $requestoptions, 'smw_sortkey', 'smw_sortkey', $where != '' ),
438 - 'SMW::getPropertySubjects',
 428+ 'SMW::getPropertySubjects',
439429 $this->getSQLOptions( $requestoptions, 'smw_sortkey' ) );
440430
441431 foreach ( $res as $row ) {
442432 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+ }
444436 } catch ( SMWDataItemException $e ) {
445437 // silently drop data, should be extremely rare and will usually fix itself at next edit
446438 }
@@ -499,6 +491,8 @@
500492 }
501493 }
502494 } 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
503497 $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem( $value );
504498 $i = 0;
505499
@@ -506,14 +500,14 @@
507501 if ( $i >= count( $dbkeys ) ) break;
508502
509503 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() );
512505 $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $oid );
 506+ break;
513507 } elseif ( $typeid != 'l' ) { // plain value, but not a text blob
514508 $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $dbkeys[$i] );
515509 }
516510
517 - $i++;
 511+ $i += 1;
518512 }
519513 }
520514 }
@@ -542,7 +536,7 @@
543537 */
544538 public function getProperties( SMWDIWikiPage $subject, $requestoptions = null ) {
545539 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() );
547541
548542 if ( $sid == 0 ) { // no id, no page, no properties
549543 wfProfileOut( "SMWSQLStore2::getProperties (SMW)" );
@@ -573,9 +567,10 @@
574568
575569 if ( $proptable->fixedproperty == false ) { // select all properties
576570 $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' ) );
580575
581576 foreach ( $res as $row ) {
582577 $result[] = new SMWDIProperty( $row->smw_title );
@@ -639,9 +634,10 @@
640635 $from = $db->tableName( 'smw_ids' ) . " INNER JOIN " . $db->tableName( $proptable->name ) . " AS t1 ON t1.p_id=smw_id";
641636 $this->prepareValueQuery( $from, $where, $proptable, $value, 1 );
642637
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' ) );
646642
647643 foreach ( $res as $row ) {
648644 try {
@@ -684,7 +680,7 @@
685681
686682 if ( $subject->getNamespace() == SMW_NS_CONCEPT ) { // make sure to clear caches
687683 $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 );
689685 $db->delete( 'smw_conc2', array( 's_id' => $id ), 'SMW::deleteSubject::Conc2' );
690686 $db->delete( 'smw_conccache', array( 'o_id' => $id ), 'SMW::deleteSubject::Conccache' );
691687 }
@@ -728,9 +724,9 @@
729725 }
730726
731727 // 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 );
733729 $updates = array(); // collect data for bulk updates; format: tableid => updatearray
734 - $this->prepareDBUpdates( $updates, $data, $sid );
 730+ $this->prepareDBUpdates( $updates, $data, $sid, $subject );
735731
736732 $db = wfGetDB( DB_MASTER );
737733 foreach ( $updates as $tablename => $uvals ) {
@@ -783,25 +779,26 @@
784780 }
785781
786782 /**
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.
792789 *
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.
795792 *
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
799797 */
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() );
806803 }
807804
808805 $proptables = self::getPropertyTables();
@@ -828,10 +825,11 @@
829826 }
830827
831828 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 );
833831 // Note: tables for container objects MUST have objectfields == array(<somename> => 'p')
834832 reset( $proptable->objectfields );
835 - $uvals[key( $proptable->objectfields )] = $bnode;
 833+ $uvals[key( $proptable->objectfields )] = $subObjectId;
836834 } else {
837835 $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem( $di );
838836 reset( $dbkeys );
@@ -840,11 +838,12 @@
841839 if ( $typeid != 'p' ) {
842840 $uvals[$fieldname] = current( $dbkeys );
843841 } else {
 842+ /// TODO The dbkeys hanlding here is obsolete; a clean handling for the DI system is needed
844843 $title = current( $dbkeys );
845844 $namespace = next( $dbkeys );
846845 $iw = next( $dbkeys );
847846 $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() );
849848 }
850849
851850 next( $dbkeys );
@@ -858,7 +857,7 @@
859858 $updates[$proptable->name][] = $uvals;
860859 }
861860 }
862 -
 861+
863862 return $sid;
864863 }
865864
@@ -895,48 +894,68 @@
896895 wfProfileIn( "SMWSQLStore2::changeTitle (SMW)" );
897896
898897 // 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 );
901900 $db = wfGetDB( DB_MASTER );
902901
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.
906908 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__ );
909913 } 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(), '', '' );
911915 } // at this point, $sid is the id of the target page (according to smw_ids)
912916
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;
917925 // $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;
920928 /// NOTE: there is the (bad) case that the moved page is a redirect. As chains of
921929 /// redirects are not supported by MW or SMW, the above is maximally correct in this case too.
922930 /// NOTE: this temporarily leaves existing redirects to oldtitle point to newtitle as well, which
923931 /// will be lost after the next update. Since double redirects are an error anyway, this is not
924932 /// a bad behaviour: everything will continue to work until the existing redirects are updated,
925933 /// 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+
927937 // Delete any existing data from new title:
928938 // $newtitle should not have data, but let's be sure
929939 $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() );
931942
932943 // Move all data of old title to new position:
933944 if ( $sid != 0 ) {
934945 $this->changeSMWPageID( $sid, $tid, $oldtitle->getNamespace(), $newtitle->getNamespace(), true, false );
935946 }
936947
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.)
938950 /// TODO: may not be optimal for the standard case that newtitle existed and redirected to oldtitle (PERFORMANCE)
939951 $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__ );
940958 }
 959+
941960 wfProfileOut( "SMWSQLStore2::changeTitle (SMW)" );
942961 }
943962
@@ -976,8 +995,10 @@
977996 foreach ( self::getPropertyTables() as $proptable ) {
978997 if ( $proptable->fixedproperty == false ) {
979998 $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';
9821003 } // else: properties with special tables are ignored for now; maybe fix in the future
9831004 }
9841005
@@ -1015,7 +1036,6 @@
10161037
10171038 wfProfileIn( "SMWSQLStore2::getUnusedPropertiesSpecial (SMW)" );
10181039 $db = wfGetDB( DB_SLAVE );
1019 - $fname = 'SMW::getUnusedPropertySubjects';
10201040
10211041 // we use a temporary table for executing this costly operation on the DB side
10221042 $smw_tmp_unusedprops = $db->tableName( 'smw_tmp_unusedprops' );
@@ -1036,21 +1056,21 @@
10371057 $sql = "CREATE TEMPORARY TABLE " . $smw_tmp_unusedprops . "( title VARCHAR(255) ) ENGINE=MEMORY";
10381058 }
10391059
1040 - $db->query( $sql, $fname );
 1060+ $db->query( $sql, __METHOD__ );
10411061
10421062 $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__ );
10441064
10451065 $smw_ids = $db->tableName( 'smw_ids' );
10461066
10471067 // 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__ );
10491069
10501070 // all tables occurring in some property table are used:
10511071 foreach ( self::getPropertyTables() as $proptable ) {
10521072 if ( $proptable->fixedproperty == false ) { // MW does not seem to have a suitable wrapper for this
10531073 $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__ );
10551075 } // else: todo
10561076 }
10571077
@@ -1061,16 +1081,16 @@
10621082
10631083 // (again we have no fitting MW wrapper here:)
10641084 $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__ );
10661086 // properties that are redirects are considered to be used:
10671087 // (a stricter and more costy approach would be to delete only redirects to used properties;
10681088 // this would need to be done with an addtional query in the above loop)
10691089 // 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__ );
10711091
10721092 $options = $this->getSQLOptions( $requestoptions, 'title' );
10731093 $options['ORDER BY'] = 'title';
1074 - $res = $db->select( $smw_tmp_unusedprops, 'title', '', $fname, $options );
 1094+ $res = $db->select( $smw_tmp_unusedprops, 'title', '', __METHOD__, $options );
10751095
10761096 $result = array();
10771097
@@ -1080,7 +1100,7 @@
10811101
10821102 $db->freeResult( $res );
10831103
1084 - $db->query( "DROP TEMPORARY table $smw_tmp_unusedprops", $fname );
 1104+ $db->query( "DROP TEMPORARY table $smw_tmp_unusedprops", __METHOD__ );
10851105 wfProfileOut( "SMWSQLStore2::getUnusedPropertiesSpecial (SMW)" );
10861106
10871107 return $result;
@@ -1110,11 +1130,13 @@
11111131 $db = wfGetDB( DB_SLAVE );
11121132 $options = $this->getSQLOptions( $requestoptions, 'title' );
11131133 $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 );
11191141
11201142 foreach ( $res as $row ) {
11211143 $result[] = array( new SMWDIProperty( $row->smw_title ), $row->count );
@@ -1185,29 +1207,25 @@
11861208 }
11871209
11881210 /**
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.
11911213 *
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:
11961219 *
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.
12051224 *
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".
12121230 */
12131231 protected function setupTables( $verbose, $db ) {
12141232 global $wgDBtype;
@@ -1229,11 +1247,11 @@
12301248 $smw_spec2 = $db->tableName( 'smw_spec2' );
12311249
12321250 // 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__ ) ) ) {
12341252 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__ );
12361254 } 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__ );
12381256 }
12391257 }
12401258
@@ -1244,14 +1262,15 @@
12451263 'smw_id' => $dbtypes['p'] . ' NOT NULL' . ( $wgDBtype == 'postgres' ? ' PRIMARY KEY' : ' KEY AUTO_INCREMENT' ),
12461264 'smw_namespace' => $dbtypes['n'] . ' NOT NULL',
12471265 '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',
12491268 'smw_sortkey' => $dbtypes['t'] . ' NOT NULL'
12501269 ),
12511270 $db,
12521271 $reportTo
12531272 );
12541273
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 );
12561275
12571276 // Set up concept cache: member elements (s)->concepts (o)
12581277 SMWSQLHelpers::setupTable(
@@ -1330,7 +1349,7 @@
13311350 $borderiw = $db->selectField( 'smw_ids', 'smw_iw', 'smw_id=' . $db->addQuotes( 50 ) );
13321351
13331352 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 );
13351354 $this->moveSMWPageID( 50 ); // make sure position 50 is empty
13361355
13371356 $db->insert( 'smw_ids', array(
@@ -1338,6 +1357,7 @@
13391358 'smw_title' => '',
13401359 'smw_namespace' => 0,
13411360 'smw_iw' => SMW_SQL2_SMWBORDERIW,
 1361+ 'smw_subobject' => '',
13421362 'smw_sortkey' => ''
13431363 ), 'SMW::setup'
13441364 ); // put dummy "border element" on index 50
@@ -1355,7 +1375,7 @@
13561376 }
13571377
13581378 // 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 );
13601380
13611381 foreach ( self::$special_ids as $prop => $id ) {
13621382 $p = new SMWDIProperty( $prop );
@@ -1364,12 +1384,13 @@
13651385 'smw_title' => $p->getKey(),
13661386 'smw_namespace' => SMW_NS_PROPERTY,
13671387 'smw_iw' => $this->getPropertyInterwiki( $p ),
 1388+ 'smw_subobject' => '',
13681389 'smw_sortkey' => $p->getKey()
13691390 ), 'SMW::setup'
13701391 );
13711392 }
13721393
1373 - $this->reportProgress( " done.\n", $verbose );
 1394+ $this->reportProgress( " done.\n", $verbose );
13741395
13751396 if ( $wgDBtype == 'postgres' ) {
13761397 $this->reportProgress( " ... updating smw_ids_smw_id_seq sequence accordingly.\n", $verbose );
@@ -1417,7 +1438,7 @@
14181439 */
14191440 public function refreshData( &$index, $count, $namespaces = false, $usejobs = true ) {
14201441 $updatejobs = array();
1421 - $emptyrange = true; // was nothing found in this run?
 1442+ $emptyrange = true; // was nothing done in this run?
14221443
14231444 // Update by MediaWiki page id --> make sure we get all pages.
14241445 $tids = array();
@@ -1438,26 +1459,35 @@
14391460
14401461 // update by internal SMW id --> make sure we get all objects in SMW
14411462 $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__ );
14441465
14451466 foreach ( $res as $row ) {
14461467 $emptyrange = false; // note this even if no jobs were created
14471468
14481469 if ( $namespaces && !in_array( $row->smw_namespace, $namespaces ) ) continue;
14491470
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
14521476 $title = Title::makeTitleSafe( $row->smw_namespace, $row->smw_title );
14531477
14541478 if ( $title !== null && !$title->exists() ) {
14551479 $updatejobs[] = new SMWUpdateJob( $title );
14561480 }
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+ }
14621492 }
14631493 $db->freeResult( $res );
14641494
@@ -1476,12 +1506,12 @@
14771507 if ( $emptyrange ) { // nothing found, check if there will be more pages later on
14781508 $next1 = $db->selectField( 'page', 'page_id', "page_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "page_id ASC" ) );
14791509 $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;
14811511 }
14821512
14831513 $max1 = $db->selectField( 'page', 'MAX(page_id)', '', __METHOD__ );
14841514 $max2 = $db->selectField( 'smw_ids', 'MAX(smw_id)', '', __METHOD__ );
1485 - $index = $nextpos ? $nextpos: - 1;
 1515+ $index = $nextpos ? $nextpos : -1;
14861516
14871517 return ( $index > 0 ) ? $index / max( $max1, $max2 ) : 1;
14881518 }
@@ -1543,7 +1573,7 @@
15441574 wfProfileIn( 'SMWSQLStore2::getConceptCacheStatus (SMW)' );
15451575
15461576 $db = wfGetDB( DB_SLAVE );
1547 - $cid = $this->getSMWPageID( $concept->getDBkey(), $concept->getNamespace(), '', false );
 1577+ $cid = $this->getSMWPageID( $concept->getDBkey(), $concept->getNamespace(), '', '', false );
15481578
15491579 $row = $db->selectRow( 'smw_conc2',
15501580 array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date', 'cache_count' ),
@@ -1775,18 +1805,6 @@
17761806
17771807 /**
17781808 * 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
17911809 * type. This is needed to apply the type-based filtering in
17921810 * getSemanticData().
17931811 *
@@ -1878,9 +1896,9 @@
18791897 * the canonical alias ID for the given page. If no such ID exists, 0 is
18801898 * returned.
18811899 */
1882 - public function getSMWPageID( $title, $namespace, $iw, $canonical = true ) {
 1900+ public function getSMWPageID( $title, $namespace, $iw, $subobjectId, $canonical = true ) {
18831901 $sort = '';
1884 - return $this->getSMWPageIDandSort( $title, $namespace, $iw, $sort, $canonical );
 1902+ return $this->getSMWPageIDandSort( $title, $namespace, $iw, $subobjectId, $sort, $canonical );
18851903 }
18861904
18871905 /**
@@ -1888,16 +1906,16 @@
18891907 * the current sortkey.
18901908 * @todo Ensuring that properties redirect to properties only should not be done here.
18911909 * @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).
18931911 */
1894 - public function getSMWPageIDandSort( $title, $namespace, $iw, &$sort, $canonical ) {
 1912+ public function getSMWPageIDandSort( $title, $namespace, $iw, $subobjectId, &$sort, $canonical ) {
18951913 global $smwgQEqualitySupport;
18961914
18971915 wfProfileIn( 'SMWSQLStore2::getSMWPageID (SMW)' );
18981916
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 );
19021920
19031921 if ( array_key_exists( $key, $this->m_ids ) ) {
19041922 wfProfileOut( 'SMWSQLStore2::getSMWPageID (SMW)' );
@@ -1915,7 +1933,7 @@
19161934 $res = $db->select(
19171935 'smw_ids',
19181936 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 ),
19201938 'SMW::getSMWPageID', array( 'LIMIT' => 1 )
19211939 );
19221940 $row = $db->fetchObject( $res );
@@ -1924,20 +1942,24 @@
19251943 $sort = $row->smw_sortkey;
19261944 }
19271945
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!
19291947 } else { // check for potential redirects also
19301948 $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 ),
19331954 'SMW::getSMWPageID', array( 'LIMIT' => 1 ) );
19341955 $row = $db->fetchObject( $res );
 1956+
19351957 if ( $row ) {
19361958 $id = $row->smw_id; // set id in any case, the below check for properties will use even the redirect id in emergency
19371959 $sort = $row->smw_sortkey;
19381960
19391961 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
19421964 if ( $namespace == SMW_NS_PROPERTY ) { // redirect properties only to properties
19431965 ///TODO: Shouldn't this condition be ensured during writing?
19441966 $res2 = $db->select( array( 'smw_redi2', 'smw_ids' ), 'o_id',
@@ -1956,6 +1978,7 @@
19571979 $db->freeResult( $res2 );
19581980 }
19591981 }
 1982+
19601983 }
19611984
19621985 $db->freeResult( $res );
@@ -1976,15 +1999,15 @@
19772000 * the title is a redirect target (we do not want chains of redirects).
19782001 * But it is of no relevance if the title does not have an id yet.
19792002 */
1980 - protected function makeSMWPageID( $title, $namespace, $iw, $canonical = true, $sortkey = '' ) {
 2003+ protected function makeSMWPageID( $title, $namespace, $iw, $subobjectId, $canonical = true, $sortkey = '' ) {
19812004 wfProfileIn( 'SMWSQLStore2::makeSMWPageID (SMW)' );
19822005
19832006 $oldsort = '';
1984 - $id = $this->getSMWPageIDandSort( $title, $namespace, $iw, $oldsort, $canonical );
 2007+ $id = $this->getSMWPageIDandSort( $title, $namespace, $iw, $subobjectId, $oldsort, $canonical );
19852008
19862009 if ( $id == 0 ) {
19872010 $db = wfGetDB( DB_MASTER );
1988 - $sortkey = $sortkey ? $sortkey:( str_replace( '_', ' ', $title ) );
 2011+ $sortkey = $sortkey ? $sortkey : ( str_replace( '_', ' ', $title ) );
19892012
19902013 $db->insert(
19912014 'smw_ids',
@@ -1993,18 +2016,19 @@
19942017 'smw_title' => $title,
19952018 'smw_namespace' => $namespace,
19962019 'smw_iw' => $iw,
 2020+ 'smw_subobject' => $subobjectId,
19972021 'smw_sortkey' => $sortkey
19982022 ),
19992023 'SMW::makeSMWPageID'
20002024 );
20012025
20022026 $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
20042028
20052029 // This ID is also authorative for the canonical version.
20062030 // This is always the case: if $canonical===false and $id===0, then there is no redi-entry in
20072031 // 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;
20092033 } elseif ( ( $sortkey != '' ) && ( $sortkey != $oldsort ) ) {
20102034 $db = wfGetDB( DB_MASTER );
20112035 $db->update( 'smw_ids', array( 'smw_sortkey' => $sortkey ), array( 'smw_id' => $id ), 'SMW::makeSMWPageID' );
@@ -2037,7 +2061,7 @@
20382062 if ( ( !$property->isUserDefined() ) && ( array_key_exists( $property->getKey(), self::$special_ids ) ) ) {
20392063 return self::$special_ids[$property->getKey()]; // very important property with fixed id
20402064 } 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 );
20422066 }
20432067 }
20442068
@@ -2049,7 +2073,7 @@
20502074 if ( ( !$property->isUserDefined() ) && ( array_key_exists( $property->getKey(), self::$special_ids ) ) ) {
20512075 return self::$special_ids[$property->getKey()]; // very important property with fixed id
20522076 } 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 );
20542078 }
20552079 }
20562080
@@ -2060,9 +2084,9 @@
20612085 * with iw being SMW_SQL2_SMWREDIIW. This information is used to determine
20622086 * whether the given ID is canonical or not.
20632087 */
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 -";
20672091
20682092 if ( count( $this->m_ids ) > 1500 ) { // prevent memory leak in very long PHP runs
20692093 $this->m_ids = array();
@@ -2076,62 +2100,6 @@
20772101 }
20782102
20792103 /**
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 - /**
21362104 * Change an internal id to another value. If no target value is given, the
21372105 * value is changed to become the last id entry (based on the automatic id
21382106 * increment of the database). Whatever currently occupies this id will be
@@ -2143,10 +2111,10 @@
21442112 */
21452113 protected function moveSMWPageID( $curid, $targetid = 0 ) {
21462114 $db = wfGetDB( DB_MASTER );
2147 -
 2115+
21482116 $row = $db->selectRow(
21492117 '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' ),
21512119 array( 'smw_id' => $curid ), 'SMWSQLStore2::moveSMWPageID'
21522120 );
21532121
@@ -2160,6 +2128,7 @@
21612129 'smw_title' => $row->smw_title,
21622130 'smw_namespace' => $row->smw_namespace,
21632131 'smw_iw' => $row->smw_iw,
 2132+ 'smw_subobject' => $row->smw_subobject,
21642133 'smw_sortkey' => $row->smw_sortkey
21652134 ),
21662135 'SMW::moveSMWPageID'
@@ -2172,6 +2141,7 @@
21732142 'smw_title' => $row->smw_title,
21742143 'smw_namespace' => $row->smw_namespace,
21752144 'smw_iw' => $row->smw_iw,
 2145+ 'smw_subobject' => $row->smw_subobject,
21762146 'smw_sortkey' => $row->smw_sortkey
21772147 ),
21782148 'SMW::moveSMWPageID'
@@ -2183,15 +2153,20 @@
21842154 }
21852155
21862156 /**
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.
21952163 *
 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+ *
21962171 * @param $oldid numeric ID that is to be changed
21972172 * @param $newid numeric ID to which the records are to be changed
21982173 * @param $oldnamespace namespace of old id's page (-1 to ignore it)
@@ -2199,38 +2174,28 @@
22002175 * @param $sdata boolean stating whether to update subject references
22012176 * @param $podata boolean stating if to update property/object references
22022177 */
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 ) {
22052180 $db = wfGetDB( DB_MASTER );
22062181
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 -
22172182 // Change all id entries in property tables:
22182183 foreach ( self::getPropertyTables() as $proptable ) {
22192184 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__ );
22212186 }
22222187
22232188 if ( $podata ) {
22242189 if ( ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_PROPERTY ) ) && ( $proptable->fixedproperty == false ) ) {
22252190 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__ );
22272192 } else {
2228 - $db->delete( $proptable->name, array( 'p_id' => $oldid ), $fname );
 2193+ $db->delete( $proptable->name, array( 'p_id' => $oldid ), __METHOD__ );
22292194 }
22302195 }
22312196
22322197 foreach ( $proptable->objectfields as $fieldname => $type ) {
22332198 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__ );
22352200 }
22362201 }
22372202 }
@@ -2239,30 +2204,31 @@
22402205 // Change id entries in concept-related tables:
22412206 if ( $sdata && ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_CONCEPT ) ) ) {
22422207 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__ );
22452210 } 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__ );
22482213 }
22492214 }
22502215
22512216 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__ );
22532218 }
22542219 }
22552220
22562221 /**
22572222 * Delete all semantic data stored for the given subject. Used for
22582223 * update purposes.
2259 - *
 2224+ *
22602225 * @param $subject SMWDIWikiPage the data of which is deleted
22612226 */
22622227 protected function deleteSemanticData( SMWDIWikiPage $subject ) {
 2228+ if ( $subject->getSubobjectId() != '' ) return; // not needed, and would mess up data
 2229+
22632230 $db = wfGetDB( DB_MASTER );
22642231
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 );
22672233
22682234 if ( $id == 0 ) {
22692235 // not (directly) used anywhere yet, may be a redirect but we do not care here
@@ -2273,28 +2239,39 @@
22742240 foreach ( self::getPropertyTables() as $proptable ) {
22752241 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
22762242 if ( $proptable->idsubject ) {
2277 - $db->delete( $proptable->name, array( 's_id' => $id ), "$fname::deleteById" );
 2243+ $db->delete( $proptable->name, array( 's_id' => $id ), __METHOD__ );
22782244 } 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__ );
22802246 }
22812247 }
22822248
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();
22852257
22862258 // ... and delete them as well
22872259 foreach ( $res as $row ) {
 2260+ $subobjects[] = $row->smw_id;
22882261 foreach ( self::getPropertyTables() as $proptable ) {
22892262 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__ );
22912264 }
22922265 }
22932266 }
22942267
22952268 $db->freeResult( $res );
22962269
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+ }
22992276
23002277 wfRunHooks( 'smwDeleteSemanticData', array( $subject ) );
23012278 }
@@ -2309,32 +2286,38 @@
23102287 * This method does not change the ids of the affected pages, and thus it
23112288 * is not concerned with updates of the data that is currently stored for
23122289 * 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.
23142291 *
23152292 * @note Please make sure you fully understand this code before making any
23162293 * changes here. Keeping the redirect structure consistent is important,
23172294 * 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.
23182300 */
23192301 protected function updateRedirects( $subject_t, $subject_ns, $curtarget_t = '', $curtarget_ns = -1 ) {
23202302 global $smwgQEqualitySupport, $smwgEnableUpdateJobs;
2321 - $fname = 'SMW::updateRedirects';
23222303
23232304 // *** 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
23252307 /// 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+
23272310 $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
23282315
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 -
23342316 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
23372319
23382320 // *** Make relevant changes in property tables (don't write the new redirect yet) ***//
 2321+
23392322 $db = wfGetDB( DB_MASTER ); // now we need to write something
23402323
23412324 if ( ( $old_tid == 0 ) && ( $sid != 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) { // new redirect
@@ -2342,83 +2325,98 @@
23432326 // Since references must not be 0, we don't have to do this is $sid == 0.
23442327 $this->changeSMWPageID( $sid, $new_tid, $subject_ns, $curtarget_ns, false, true );
23452328 } 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__ );
23472331
23482332 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
23502335 $jobs = array();
23512336
23522337 foreach ( self::getPropertyTables() as $proptable ) {
23532338 if ( $proptable->name == 'smw_redi2' ) continue; // can safely be skipped
23542339
23552340 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';
23582344 } 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';
23612347 }
23622348
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__ );
23662352 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 ) ) {
23692355 $jobs[] = new SMWUpdateJob( $title );
23702356 }
23712357 }
2372 -
23732358 $db->freeResult( $res );
23742359 }
23752360
23762361 foreach ( $proptable->objectfields as $fieldname => $type ) {
23772362 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__ );
23802365 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 ) ) {
23832368 $jobs[] = new SMWUpdateJob( $title );
23842369 }
23852370 }
2386 -
23872371 $db->freeResult( $res );
23882372 }
23892373 }
23902374 }
2391 -
 2375+
23922376 /// 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 );
23942380 }
23952381 }
23962382
23972383 // *** Finally, write the new redirect data ***//
2398 - if ( $new_tid != 0 ) { // record new redirect
 2384+
 2385+ if ( $new_tid != 0 ) { // record a new redirect
23992386 // 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.
24012391 // 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)
24032395 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 );
24052398 } 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__ );
24072401 }
24082402 }
24092403
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;
24122408 } else { // delete old redirect
24132409 // 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;
24162413
24172414 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__ );
24192416 }
24202417 }
24212418
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+
24232421 unset( $this->m_semdata[$sid] ); unset( $this->m_semdata[$new_tid] ); unset( $this->m_semdata[$old_tid] );
24242422 unset( $this->m_sdstate[$sid] ); unset( $this->m_sdstate[$new_tid] ); unset( $this->m_sdstate[$old_tid] );
24252423

Follow-up revisions

RevisionCommit summaryAuthorDate
r91953follow up to r91449jeroendedauw13:03, 12 July 2011

Comments

#Comment by Raymond (talk | contribs)   20:37, 5 July 2011

Seen at translatewiki. Hopefully I found the correct culprit:

A database query syntax error has occurred.
The last attempted database query was:
"SELECT  smw_id,smw_title,smw_namespace,smw_iw,smw_subobject  FROM `bw_smw_ids`  WHERE smw_id >= 189966 AND smw_id < '189986'  "
from within function "SMWSQLStore2::refreshData".
Database returned error "1054: Unknown column 'smw_subobject' in 'field list' (localhost)"
#Comment by Raymond (talk | contribs)   21:36, 5 July 2011

never mind. Nikerabbit learned how to update SMW.

#Comment by Raymond (talk | contribs)   21:36, 5 July 2011

... learned _me_ ...

#Comment by Nikerabbit (talk | contribs)   07:25, 6 July 2011

taught you :)

Status & tagging log