00001 <?php
00002
00013
00014 define( 'SMW_SQL2_SMWIW_OUTDATED', ':smw' );
00015 define( 'SMW_SQL2_SMWREDIIW', ':smw-redi' );
00016 define( 'SMW_SQL2_SMWBORDERIW', ':smw-border' );
00017 define( 'SMW_SQL2_SMWPREDEFIW', ':smw-preprop' );
00018 define( 'SMW_SQL2_SMWINTDEFIW', ':smw-intprop' );
00019
00033 class SMWSQLStore2 extends SMWStore {
00034
00036 protected $m_idCache;
00037
00039 protected $m_semdata = array();
00041 protected $m_sdstate = array();
00043 protected static $in_getSemanticData = 0;
00044
00047 protected static $prop_tables = array();
00049 protected static $fixed_prop_tables = null;
00050
00052 protected static $special_ids = array(
00053 '_TYPE' => 1,
00054 '_URI' => 2,
00055 '_INST' => 4,
00056 '_UNIT' => 7,
00057 '_IMPO' => 8,
00058 '_CONV' => 12,
00059 '_SERV' => 13,
00060 '_PVAL' => 14,
00061 '_REDI' => 15,
00062 '_SUBP' => 17,
00063 '_SUBC' => 18,
00064 '_CONC' => 19,
00065 '_SF_DF' => 20,
00066 '_SF_AF' => 21,
00067 '_ERRP' => 22,
00068
00069
00070
00071
00072
00073 '_LIST' => 28,
00074 '_MDAT' => 29,
00075 '_CDAT' => 30,
00076 '_NEWP' => 31,
00077 '_LEDT' => 32,
00078 );
00079
00081 protected static $special_tables = array(
00082 '_TYPE' => 'smw_spec2',
00083 '_URI' => 'smw_spec2',
00084 '_INST' => 'smw_inst2',
00085 '_UNIT' => 'smw_spec2',
00086 '_IMPO' => 'smw_spec2',
00087 '_CONV' => 'smw_spec2',
00088 '_SERV' => 'smw_spec2',
00089 '_PVAL' => 'smw_spec2',
00090 '_REDI' => 'smw_redi2',
00091 '_SUBP' => 'smw_subp2',
00092 '_SUBC' => 'smw_subs2',
00093 '_CONC' => 'smw_conc2',
00094 '_SF_DF' => 'smw_spec2',
00095 '_SF_AF' => 'smw_spec2',
00096
00097 '_LIST' => 'smw_spec2',
00098 );
00099
00101 protected static $di_type_tables = array(
00102 SMWDataItem::TYPE_NUMBER => 'smw_atts2',
00103 SMWDataItem::TYPE_STRING => 'smw_atts2',
00104 SMWDataItem::TYPE_BLOB => 'smw_text2',
00105 SMWDataItem::TYPE_BOOLEAN => 'smw_atts2',
00106 SMWDataItem::TYPE_URI => 'smw_atts2',
00107 SMWDataItem::TYPE_TIME => 'smw_atts2',
00108 SMWDataItem::TYPE_GEO => 'smw_coords',
00109 SMWDataItem::TYPE_CONTAINER => 'smw_rels2',
00110 SMWDataItem::TYPE_WIKIPAGE => 'smw_rels2',
00111 SMWDataItem::TYPE_CONCEPT => 'smw_conc2',
00112 SMWDataItem::TYPE_PROPERTY => 'smw_atts2'
00113 );
00114
00115 public function __construct() {
00116 $this->m_idCache = new SMWSqlStore2IdCache( wfGetDB( DB_SLAVE ) );
00117 }
00118
00120
00121 public function getSemanticData( SMWDIWikiPage $subject, $filter = false ) {
00122 wfProfileIn( "SMWSQLStore2::getSemanticData (SMW)" );
00123
00124
00125 self::$in_getSemanticData++;
00126
00127
00128 $sortkey = '';
00129 $sid = $this->getSMWPageIDandSort( $subject->getDBkey(), $subject->getNamespace(),
00130 $subject->getInterwiki(), $subject->getSubobjectName(), $sortkey, true );
00131 if ( $sid == 0 ) {
00133 self::$in_getSemanticData--;
00134 wfProfileOut( "SMWSQLStore2::getSemanticData (SMW)" );
00135 return new SMWSemanticData( $subject );
00136 }
00137
00138
00139 if ( !array_key_exists( $sid, $this->m_semdata ) ) {
00140 $this->m_semdata[$sid] = new SMWSqlStubSemanticData( $subject, false );
00141 if ( $subject->getSubobjectName() === '' ) {
00142 $this->m_semdata[$sid]->addPropertyStubValue( '_SKEY', array( $sortkey ) );
00143 }
00144 $this->m_sdstate[$sid] = array();
00145
00146
00147 }
00148
00149 if ( ( count( $this->m_semdata ) > 20 ) && ( self::$in_getSemanticData == 1 ) ) {
00150
00151
00152
00153 $this->m_semdata = array( $sid => $this->m_semdata[$sid] );
00154 $this->m_sdstate = array( $sid => $this->m_sdstate[$sid] );
00155 }
00156
00157
00158 foreach ( self::getPropertyTables() as $tid => $proptable ) {
00159 if ( array_key_exists( $tid, $this->m_sdstate[$sid] ) ) continue;
00160
00161 if ( $filter !== false ) {
00162 $relevant = false;
00163 foreach ( $filter as $typeid ) {
00164 $relevant = $relevant || self::tableFitsType( $tid, $typeid );
00165 }
00166 if ( !$relevant ) continue;
00167 }
00168
00169 $data = $this->fetchSemanticData( $sid, $subject, $proptable );
00170
00171 foreach ( $data as $d ) {
00172 $this->m_semdata[$sid]->addPropertyStubValue( reset( $d ), end( $d ) );
00173 }
00174
00175 $this->m_sdstate[$sid][$tid] = true;
00176 }
00177
00178 self::$in_getSemanticData--;
00179
00180 wfProfileOut( "SMWSQLStore2::getSemanticData (SMW)" );
00181
00182 return $this->m_semdata[$sid];
00183 }
00184
00194 public function getPropertyValues( $subject, SMWDIProperty $property, $requestoptions = null ) {
00195 wfProfileIn( "SMWSQLStore2::getPropertyValues (SMW)" );
00196
00197 if ( $property->isInverse() ) {
00198 $noninverse = new SMWDIProperty( $property->getKey(), false );
00199 $result = $this->getPropertySubjects( $noninverse, $subject, $requestoptions );
00200 } elseif ( !is_null( $subject ) ) {
00201 $sd = $this->getSemanticData( $subject, array( $property->findPropertyTypeID() ) );
00202 $result = $this->applyRequestOptions( $sd->getPropertyValues( $property ), $requestoptions );
00203 } else {
00204 $pid = $this->getSMWPropertyID( $property );
00205 $tableid = self::findPropertyTableID( $property );
00206
00207 if ( ( $pid == 0 ) || ( $tableid === '' ) ) {
00208 wfProfileOut( "SMWSQLStore2::getPropertyValues (SMW)" );
00209 return array();
00210 }
00211
00212 $proptables = self::getPropertyTables();
00213 $data = $this->fetchSemanticData( $pid, $property, $proptables[$tableid], false, $requestoptions );
00214 $result = array();
00215 $propertyTypeId = $property->findPropertyTypeID();
00216 $propertyDiId = SMWDataValueFactory::getDataItemId( $propertyTypeId );
00217
00218 if ( $propertyDiId == SMWDataItem::TYPE_CONTAINER ) {
00219 foreach ( $data as $dbkeys ) {
00220 try {
00221 $diSubWikiPage = SMWCompatibilityHelpers::dataItemFromDBKeys( '_wpg', $dbkeys );
00222 $semanticData = new SMWContainerSemanticData( $diSubWikiPage );
00223 $semanticData->copyDataFrom( $this->getSemanticData( $diSubWikiPage ) );
00224 $result[] = new SMWDIContainer( $semanticData );
00225 } catch ( SMWDataItemException $e ) {
00226
00227
00228 }
00229 }
00230 } else {
00231 foreach ( $data as $dbkeys ) {
00232 try {
00233 $result[] = SMWCompatibilityHelpers::dataItemFromDBKeys( $propertyTypeId, $dbkeys );
00234 } catch ( SMWDataItemException $e ) {
00235
00236
00237 }
00238 }
00239 }
00240 }
00241
00242 wfProfileOut( "SMWSQLStore2::getPropertyValues (SMW)" );
00243
00244 return $result;
00245 }
00246
00281 protected function fetchSemanticData( $id, $object, $proptable, $issubject = true, $requestoptions = null ) {
00282
00283
00284 if ( ( $id == 0 ) || ( is_null( $object ) && ( !$issubject || !$proptable->idsubject ) ) ) return array();
00285
00286 wfProfileIn( "SMWSQLStore2::fetchSemanticData-" . $proptable->name . " (SMW)" );
00287 $result = array();
00288 $db = wfGetDB( DB_SLAVE );
00289
00290
00291 $from = $db->tableName( $proptable->name );
00292 $select = '';
00293 $where = '';
00294
00295 if ( $issubject != 0 ) {
00296 $where .= ( $proptable->idsubject ) ? 's_id=' . $db->addQuotes( $id ) :
00297 's_title=' . $db->addQuotes( $object->getDBkey() ) .
00298 ' AND s_namespace=' . $db->addQuotes( $object->getNamespace() );
00299 if ( !$proptable->fixedproperty && !$proptable->specpropsonly ) {
00300 $from .= ' INNER JOIN ' . $db->tableName( 'smw_ids' ) . ' AS p ON p_id=p.smw_id';
00301 $select .= 'p.smw_title as prop';
00302 } elseif ( $proptable->specpropsonly ) {
00303 $select .= 'p_id';
00304 }
00305 } elseif ( !$proptable->fixedproperty ) {
00306 $where .= 'p_id=' . $db->addQuotes( $id );
00307 }
00308
00309 $valuecount = 0;
00310 $usedistinct = true;
00311 $selectvalues = array();
00312
00313 foreach ( $proptable->objectfields as $fieldname => $typeid ) {
00314 if ( $typeid == 'p' ) {
00315 $from .= ' INNER JOIN ' . $db->tableName( 'smw_ids' ) . " AS o$valuecount ON $fieldname=o$valuecount.smw_id";
00316 $select .= ( ( $select !== '' ) ? ',' : '' ) . "$fieldname AS id$valuecount";
00317
00318 $selectvalues[$valuecount] = "o$valuecount.smw_title";
00319 $selectvalues[$valuecount + 1] = "o$valuecount.smw_namespace";
00320 $selectvalues[$valuecount + 2] = "o$valuecount.smw_iw";
00321 $selectvalues[$valuecount + 3] = "o$valuecount.smw_sortkey";
00322 $selectvalues[$valuecount + 4] = "o$valuecount.smw_subobject";
00323
00324 $valuecount += 4;
00325 } else {
00326 $selectvalues[$valuecount] = $fieldname;
00327 }
00328
00329 if ( $typeid == 'l' ) $usedistinct = false;
00330 $valuecount += 1;
00331 }
00332
00333 foreach ( $selectvalues as $index => $field ) {
00334 $select .= ( ( $select !== '' ) ? ',' : '' ) . "$field AS v$index";
00335 }
00336
00337 if ( !$issubject ) {
00338 list( $sig, $valueIndex, $labelIndex ) = self::getTypeSignature( $object->findPropertyTypeID() );
00339 $valuecolumn = ( array_key_exists( $valueIndex, $selectvalues ) ) ? $selectvalues[$valueIndex] : '';
00340 $labelcolumn = ( array_key_exists( $labelIndex, $selectvalues ) ) ? $selectvalues[$labelIndex] : '';
00341 $where .= $this->getSQLConditions( $requestoptions, $valuecolumn, $labelcolumn, $where !== '' );
00342 } else {
00343 $valuecolumn = $labelcolumn = '';
00344 }
00345
00346
00347 $res = $db->select( $from, $select, $where, 'SMW::getSemanticData',
00348 ( $usedistinct ? $this->getSQLOptions( $requestoptions, $valuecolumn ) + array( 'DISTINCT' ) :
00349 $this->getSQLOptions( $requestoptions, $valuecolumn ) ) );
00350
00351 foreach ( $res as $row ) {
00352 if ( $issubject && !$proptable->fixedproperty ) {
00353 if ( $proptable->specpropsonly ) {
00354 $propertyname = array_search( $row->p_id, self::$special_ids );
00355
00356
00357
00358 if ( $propertyname == false ) continue;
00359 } else {
00360 $propertyname = $row->prop;
00361 }
00362 } elseif ( $issubject ) {
00363 $propertyname = $proptable->fixedproperty;
00364 }
00365
00366 $valuekeys = array();
00367 for ( $i = 0; $i < $valuecount; $i += 1 ) {
00368 $fieldname = "v$i";
00369 $valuekeys[] = $row->$fieldname;
00370 }
00371
00372
00373 if ( $proptable->getFieldSignature() != 'p' || count( $valuekeys ) < 3 ||
00374 $valuekeys[2] === '' || $valuekeys[2]{0} != ':' ) {
00375 $result[] = $issubject ? array( $propertyname, $valuekeys ) : $valuekeys;
00376 }
00377 }
00378
00379 $db->freeResult( $res );
00380 wfProfileOut( "SMWSQLStore2::fetchSemanticData-" . $proptable->name . " (SMW)" );
00381
00382 return $result;
00383 }
00384
00394 public function getPropertySubjects( SMWDIProperty $property, $value, $requestoptions = null ) {
00396 wfProfileIn( "SMWSQLStore2::getPropertySubjects (SMW)" );
00397
00398 if ( $property->isInverse() ) {
00399 $noninverse = new SMWDIProperty( $property->getKey(), false );
00400 $result = $this->getPropertyValues( $value, $noninverse, $requestoptions );
00401 wfProfileOut( "SMWSQLStore2::getPropertySubjects (SMW)" );
00402 return $result;
00403 }
00404
00405
00406 $where = $from = '';
00407 $pid = $this->getSMWPropertyID( $property );
00408 $tableid = self::findPropertyTableID( $property );
00409
00410 if ( ( $pid == 0 ) || ( $tableid === '' ) ) {
00411 wfProfileOut( "SMWSQLStoreLight::getPropertySubjects (SMW)" );
00412 return array();
00413 }
00414
00415 $proptables = self::getPropertyTables();
00416 $proptable = $proptables[$tableid];
00417 $db = wfGetDB( DB_SLAVE );
00418
00419 if ( $proptable->idsubject ) {
00420 $from = $db->tableName( 'smw_ids' ) . " INNER JOIN " . $db->tableName( $proptable->name ) . " AS t1 ON t1.s_id=smw_id";
00421 $select = 'smw_title, smw_namespace, smw_sortkey, smw_iw, smw_subobject';
00422 } else {
00423 $from = $db->tableName( $proptable->name ) . " AS t1";
00424 $select = 's_title AS smw_title, s_namespace AS smw_namespace, s_title AS smw_sortkey, \'\' AS smw_iw, \'\' AS smw_subobject';
00425 }
00426
00427 if ( $proptable->fixedproperty == false ) {
00428 $where .= ( $where ? ' AND ' : '' ) . "t1.p_id=" . $db->addQuotes( $pid );
00429 }
00430
00431 $this->prepareValueQuery( $from, $where, $proptable, $value, 1 );
00432
00433
00434 $result = array();
00435 $res = $db->select( $from, 'DISTINCT ' . $select,
00436 $where . $this->getSQLConditions( $requestoptions, 'smw_sortkey', 'smw_sortkey', $where !== '' ),
00437 'SMW::getPropertySubjects',
00438 $this->getSQLOptions( $requestoptions, 'smw_sortkey' ) );
00439
00440 foreach ( $res as $row ) {
00441 try {
00442 if ( $row->smw_iw === '' || $row->smw_iw{0} != ':' ) {
00443 $result[] = new SMWDIWikiPage( $row->smw_title, $row->smw_namespace, $row->smw_iw, $row->smw_subobject );
00444 }
00445 } catch ( SMWDataItemException $e ) {
00446
00447 }
00448 }
00449
00450 $db->freeResult( $res );
00451 wfProfileOut( "SMWSQLStore2::getPropertySubjects (SMW)" );
00452
00453 return $result;
00454 }
00455
00456
00473 protected function prepareValueQuery( &$from, &$where, $proptable, $value, $tableindex = 1 ) {
00474 $db = wfGetDB( DB_SLAVE );
00475
00476 if ( $value instanceof SMWDIContainer ) {
00477 $keys = array_keys( $proptable->objectfields );
00478 $joinfield = "t$tableindex." . reset( $keys );
00479 $proptables = self::getPropertyTables();
00480 $semanticData = $value->getSemanticData();
00481
00482 foreach ( $semanticData->getProperties() as $subproperty ) {
00483 $tableid = self::findPropertyTableID( $subproperty );
00484 $subproptable = $proptables[$tableid];
00485
00486 foreach ( $semanticData->getPropertyValues( $subproperty ) as $subvalue ) {
00487 $tableindex++;
00488
00489 if ( $subproptable->idsubject ) {
00490 $from .= " INNER JOIN " . $db->tableName( $subproptable->name ) . " AS t$tableindex ON t$tableindex.s_id=$joinfield";
00491 } else {
00492 $from .= " INNER JOIN " . $db->tableName( 'smw_ids' ) . " AS ids$tableindex ON ids$tableindex.smw_id=$joinfield" .
00493 " INNER JOIN " . $db->tableName( $subproptable->name ) . " AS t$tableindex ON " .
00494 "t$tableindex.s_title=ids$tableindex.smw_title AND t$tableindex.s_namespace=ids$tableindex.smw_namespace";
00495 }
00496
00497 if ( $subproptable->fixedproperty == false ) {
00498 $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.p_id=" . $db->addQuotes( $this->getSMWPropertyID( $subproperty ) );
00499 }
00500
00501 $this->prepareValueQuery( $from, $where, $subproptable, $subvalue, $tableindex );
00502 }
00503 }
00504 } elseif ( !is_null( $value ) ) {
00507 $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem( $value );
00508 $i = 0;
00509
00510 foreach ( $proptable->objectfields as $fieldname => $typeid ) {
00511 if ( $i >= count( $dbkeys ) ) break;
00512
00513 if ( $typeid == 'p' ) {
00514 $oid = $this->getSMWPageID( $value->getDBkey(), $value->getNamespace(), $value->getInterwiki(), $value->getSubobjectName() );
00515 $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $oid );
00516 break;
00517 } elseif ( $typeid != 'l' ) {
00518 $where .= ( $where ? ' AND ' : '' ) . "t$tableindex.$fieldname=" . $db->addQuotes( $dbkeys[$i] );
00519 }
00520
00521 $i += 1;
00522 }
00523 }
00524 }
00525
00534 public function getAllPropertySubjects( SMWDIProperty $property, $requestoptions = null ) {
00535 wfProfileIn( "SMWSQLStore2::getAllPropertySubjects (SMW)" );
00536 $result = $this->getPropertySubjects( $property, null, $requestoptions );
00537 wfProfileOut( "SMWSQLStore2::getAllPropertySubjects (SMW)" );
00538
00539 return $result;
00540 }
00541
00548 public function getProperties( SMWDIWikiPage $subject, $requestoptions = null ) {
00549 wfProfileIn( "SMWSQLStore2::getProperties (SMW)" );
00550 $sid = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName() );
00551
00552 if ( $sid == 0 ) {
00553 wfProfileOut( "SMWSQLStore2::getProperties (SMW)" );
00554 return array();
00555 }
00556
00557 $db = wfGetDB( DB_SLAVE );
00558 $result = array();
00559
00560 if ( $requestoptions !== null ) {
00561 $suboptions = clone $requestoptions;
00562 $suboptions->limit = $requestoptions->limit + $requestoptions->offset;
00563 $suboptions->offset = 0;
00564 } else {
00565 $suboptions = null;
00566 }
00567
00568 foreach ( self::getPropertyTables() as $proptable ) {
00569 $from = $db->tableName( $proptable->name );
00570
00571 if ( $proptable->idsubject ) {
00572 $where = 's_id=' . $db->addQuotes( $sid );
00573 } elseif ( $subject->getInterwiki() === '' ) {
00574 $where = 's_title=' . $db->addQuotes( $subject->getDBkey() ) . ' AND s_namespace=' . $db->addQuotes( $subject->getNamespace() );
00575 } else {
00576 continue;
00577 }
00578
00579 if ( $proptable->fixedproperty == false ) {
00580 $from .= " INNER JOIN " . $db->tableName( 'smw_ids' ) . " ON smw_id=p_id";
00581 $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey',
00582
00583 $where . $this->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey' ),
00584 'SMW::getProperties', $this->getSQLOptions( $suboptions, 'smw_sortkey' ) );
00585
00586 foreach ( $res as $row ) {
00587 $result[] = new SMWDIProperty( $row->smw_title );
00588 }
00589 } else {
00590 $res = $db->select( $from, '*', $where, 'SMW::getProperties', array( 'LIMIT' => 1 ) );
00591
00592 if ( $db->numRows( $res ) > 0 ) {
00593 $result[] = new SMWDIProperty( $proptable->fixedproperty );
00594 }
00595 }
00596
00597 $db->freeResult( $res );
00598 }
00599
00600 $result = $this->applyRequestOptions( $result, $requestoptions );
00601 wfProfileOut( "SMWSQLStore2::getProperties (SMW)" );
00602
00603 return $result;
00604 }
00605
00624 public function getInProperties( SMWDataItem $value, $requestoptions = null ) {
00625 wfProfileIn( "SMWSQLStore2::getInProperties (SMW)" );
00626
00627 $db = wfGetDB( DB_SLAVE );
00628 $result = array();
00629
00630
00631 if ( $requestoptions !== null ) {
00632 $suboptions = clone $requestoptions;
00633 $suboptions->limit = $requestoptions->limit + $requestoptions->offset;
00634 $suboptions->offset = 0;
00635 } else {
00636 $suboptions = null;
00637 }
00638
00639 $tableIds = self::findAllDiTypeTableIds( $value->getDIType() );
00640 $proptables = self::getPropertyTables();
00641 foreach ( $tableIds as $tid ) {
00642 $proptable = $proptables[$tid];
00643 $where = $from = '';
00644 if ( $proptable->fixedproperty == false ) {
00645 $from = $db->tableName( 'smw_ids' ) . " INNER JOIN " . $db->tableName( $proptable->name ) . " AS t1 ON t1.p_id=smw_id";
00646 $this->prepareValueQuery( $from, $where, $proptable, $value, 1 );
00647
00648 $res = $db->select( $from, 'DISTINCT smw_title,smw_sortkey',
00649
00650 $where . $this->getSQLConditions( $suboptions, 'smw_sortkey', 'smw_sortkey', $where !== '' ),
00651 'SMW::getInProperties', $this->getSQLOptions( $suboptions, 'smw_sortkey' ) );
00652
00653 foreach ( $res as $row ) {
00654 try {
00655 $result[] = new SMWDIProperty( $row->smw_title );
00656 } catch (SMWDataItemException $e) {
00657
00658 }
00659 }
00660 } else {
00661 $from = $db->tableName( $proptable->name ) . " AS t1";
00662 $this->prepareValueQuery( $from, $where, $proptable, $value, 1 );
00663 $res = $db->select( $from, '*', $where, 'SMW::getInProperties', array( 'LIMIT' => 1 ) );
00664
00665 if ( $db->numRows( $res ) > 0 ) {
00666 $result[] = new SMWDIProperty( $proptable->fixedproperty );
00667 }
00668 }
00669 $db->freeResult( $res );
00670 }
00671
00672 $result = $this->applyRequestOptions( $result, $requestoptions );
00673 wfProfileOut( "SMWSQLStore2::getInProperties (SMW)" );
00674
00675 return $result;
00676 }
00677
00679
00685 public function deleteSubject( Title $subject ) {
00686 wfProfileIn( 'SMWSQLStore2::deleteSubject (SMW)' );
00687 wfRunHooks( 'SMWSQLStore2::deleteSubjectBefore', array( $this, $subject ) );
00688
00689 $this->deleteSemanticData( SMWDIWikiPage::newFromTitle( $subject ) );
00690 $this->updateRedirects( $subject->getDBkey(), $subject->getNamespace() );
00691
00692 if ( $subject->getNamespace() == SMW_NS_CONCEPT ) {
00693 $db = wfGetDB( DB_MASTER );
00694 $id = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), '', false );
00695 $db->delete( 'smw_conc2', array( 's_id' => $id ), 'SMW::deleteSubject::Conc2' );
00696 $db->delete( 'smw_conccache', array( 'o_id' => $id ), 'SMW::deleteSubject::Conccache' );
00697 }
00698
00703 wfRunHooks( 'SMWSQLStore2::deleteSubjectAfter', array( $this, $subject ) );
00704 wfProfileOut( 'SMWSQLStore2::deleteSubject (SMW)' );
00705 }
00706
00712 public function doDataUpdate( SMWSemanticData $data ) {
00713 wfProfileIn( "SMWSQLStore2::updateData (SMW)" );
00714 wfRunHooks( 'SMWSQLStore2::updateDataBefore', array( $this, $data ) );
00715
00716 $subject = $data->getSubject();
00717 $this->deleteSemanticData( $subject );
00718
00719 $redirects = $data->getPropertyValues( new SMWDIProperty( '_REDI' ) );
00720 if ( count( $redirects ) > 0 ) {
00721 $redirect = end( $redirects );
00722 $this->updateRedirects( $subject->getDBkey(), $subject->getNamespace(), $redirect->getDBkey(), $redirect->getNameSpace() );
00723 wfProfileOut( "SMWSQLStore2::updateData (SMW)" );
00724 return;
00725 } else {
00726 $this->updateRedirects( $subject->getDBkey(), $subject->getNamespace() );
00727 }
00728
00729 $sortkeyDataItems = $data->getPropertyValues( new SMWDIProperty( '_SKEY' ) );
00730 $sortkeyDataItem = end( $sortkeyDataItems );
00731 if ( $sortkeyDataItem instanceof SMWDIString ) {
00732 $sortkey = $sortkeyDataItem->getString();
00733 } else {
00734 $sortkey = str_replace( '_', ' ', $subject->getDBkey() );
00735 }
00736
00737
00738 $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), $subject->getSubobjectName(), true, $sortkey );
00739 $updates = array();
00740 $this->prepareDBUpdates( $updates, $data, $sid, $subject );
00741
00742 $db = wfGetDB( DB_MASTER );
00743 foreach ( $updates as $tablename => $uvals ) {
00744 if ( $tablename != 'smw_conc2' ) $db->insert( $tablename, $uvals, "SMW::updateData$tablename" );
00745 }
00746
00747
00748
00749 if ( $subject->getNamespace() == SMW_NS_CONCEPT ) {
00750 if ( array_key_exists( 'smw_conc2', $updates ) && ( count( $updates['smw_conc2'] ) != 0 ) ) {
00751 $up_conc2 = end( $updates['smw_conc2'] );
00752 unset ( $up_conc2['cache_date'] );
00753 unset ( $up_conc2['cache_count'] );
00754 } else {
00755 $up_conc2 = array(
00756 'concept_txt' => '',
00757 'concept_docu' => '',
00758 'concept_features' => 0,
00759 'concept_size' => -1,
00760 'concept_depth' => -1
00761 );
00762 }
00763
00764 $row = $db->selectRow(
00765 'smw_conc2',
00766 array( 'cache_date', 'cache_count' ),
00767 array( 's_id' => $sid ),
00768 'SMWSQLStore2Queries::updateConst2Data'
00769 );
00770
00771 if ( ( $row === false ) && ( $up_conc2['concept_txt'] !== '' ) ) {
00772 $up_conc2['s_id'] = $sid;
00773 $db->insert( 'smw_conc2', $up_conc2, 'SMW::updateConc2Data' );
00774 } elseif ( $row !== false ) {
00775 $db->update( 'smw_conc2', $up_conc2, array( 's_id' => $sid ), 'SMW::updateConc2Data' );
00776 }
00777 }
00778
00779
00780 $this->m_semdata[$sid] = SMWSqlStubSemanticData::newFromSemanticData( $data );
00781
00782 $this->m_sdstate[$sid] = array();
00783 foreach ( self::getPropertyTables() as $tableId => $tableDeclaration ) {
00784 $this->m_sdstate[$sid][$tableId] = true;
00785 }
00786
00787 wfRunHooks( 'SMWSQLStore2::updateDataAfter', array( $this, $data ) );
00788
00789 wfProfileOut( "SMWSQLStore2::updateData (SMW)" );
00790 }
00791
00808 protected function prepareDBUpdates( &$updates, SMWSemanticData $data, $sid, SMWDIWikiPage $subject ) {
00809 if ( $sid == 0 ) {
00810 $sid = $this->makeSMWPageID( $subject->getDBkey(), $subject->getNamespace(),
00811 $subject->getInterwiki(), $subject->getSubobjectName(), true,
00812 str_replace( '_', ' ', $subject->getDBkey() ) . $subject->getSubobjectName() );
00813 }
00814
00815 $proptables = self::getPropertyTables();
00816
00817 foreach ( $data->getProperties() as $property ) {
00818 if ( ( $property->getKey() == '_SKEY' ) || ( $property->getKey() == '_REDI' ) ) {
00819 continue;
00820 }
00821
00822 $tableid = self::findPropertyTableID( $property );
00823 $proptable = $proptables[$tableid];
00824
00825 foreach ( $data->getPropertyValues( $property ) as $di ) {
00826 if ( $di instanceof SMWDIError ) {
00827 continue;
00828 }
00829
00830
00832 $uvals = $proptable->idsubject ? array( 's_id' => $sid ) :
00833 array( 's_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace() );
00834 if ( $proptable->fixedproperty == false ) {
00835 $uvals['p_id'] = $this->makeSMWPropertyID( $property );
00836 }
00837
00838 if ( $di instanceof SMWDIContainer ) {
00839 $subObject = $di->getSemanticData()->getSubject();
00840 $subObjectId = $this->prepareDBUpdates( $updates, $di->getSemanticData(), 0, $subObject );
00841
00842 reset( $proptable->objectfields );
00843 $uvals[key( $proptable->objectfields )] = $subObjectId;
00844 } else {
00845 $dbkeys = SMWCompatibilityHelpers::getDBkeysFromDataItem( $di );
00846 reset( $dbkeys );
00847
00848 foreach ( $proptable->objectfields as $fieldname => $typeid ) {
00849 if ( $typeid != 'p' ) {
00850 $uvals[$fieldname] = current( $dbkeys );
00851 } else {
00852 $uvals[$fieldname] = $this->makeSMWPageID( $di->getDBkey(), $di->getNamespace(), $di->getInterwiki(), $di->getSubobjectName() );
00853 }
00854
00855 next( $dbkeys );
00856 }
00857 }
00858
00859 if ( !array_key_exists( $proptable->name, $updates ) ) {
00860 $updates[$proptable->name] = array();
00861 }
00862
00863 $updates[$proptable->name][] = $uvals;
00864 }
00865 }
00866
00867 return $sid;
00868 }
00869
00898 public function changeTitle( Title $oldtitle, Title $newtitle, $pageid, $redirid = 0 ) {
00899 global $smwgQEqualitySupport;
00900 wfProfileIn( "SMWSQLStore2::changeTitle (SMW)" );
00901
00902
00903 $sid = $this->getSMWPageID( $oldtitle->getDBkey(), $oldtitle->getNamespace(), '', '', false );
00904 $tid = $this->getSMWPageID( $newtitle->getDBkey(), $newtitle->getNamespace(), '', '', false );
00905 $db = wfGetDB( DB_MASTER );
00906
00907
00908 if ( ( $tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) {
00909
00910
00911
00912
00913 if ( $sid != 0 ) {
00914
00915 $db->update( 'smw_ids', array( 'smw_title' => $newtitle->getDBkey(),
00916 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => '' ),
00917 array( 'smw_title' => $oldtitle->getDBkey(),
00918 'smw_namespace' => $oldtitle->getNamespace(), 'smw_iw' => '' ),
00919 __METHOD__ );
00920 $this->m_idCache->moveSubobjects( $oldtitle->getDBkey(), $oldtitle->getNamespace(),
00921 $newtitle->getDBkey(), $newtitle->getNamespace() );
00922 $this->m_idCache->setId( $oldtitle->getDBkey(), $oldtitle->getNamespace(), '', '', 0 );
00923 $this->m_idCache->setId( $newtitle->getDBkey(), $newtitle->getNamespace(), '', '', $sid );
00924 } else {
00925 $sid = $this->makeSMWPageID( $newtitle->getDBkey(), $newtitle->getNamespace(), '', '' );
00926 }
00927
00928
00929 $this->makeSMWPageID( $oldtitle->getDBkey(), $oldtitle->getNamespace(), SMW_SQL2_SMWREDIIW, '' );
00930 $db->insert( 'smw_redi2', array( 's_title' => $oldtitle->getDBkey(),
00931 's_namespace' => $oldtitle->getNamespace(),
00932 'o_id' => $sid ),
00933 __METHOD__ );
00934
00941 } else {
00942
00943
00944
00945
00946 $this->deleteSemanticData( SMWDIWikiPage::newFromTitle( $newtitle ) );
00947
00948 $this->updateRedirects( $newtitle->getDBkey(), $newtitle->getNamespace() );
00949
00950
00951 if ( $sid != 0 ) {
00952 $this->changeSMWPageID( $sid, $tid, $oldtitle->getNamespace(),
00953 $newtitle->getNamespace(), true, false );
00954 }
00955
00956
00957 $table = $db->tableName( 'smw_ids' );
00958 $values = array( 'smw_title' => $newtitle->getDBkey(), 'smw_namespace' => $newtitle->getNamespace(), 'smw_iw' => '' );
00959 $sql = "UPDATE $table SET " . $db->makeList( $values, LIST_SET ) .
00960 ' WHERE smw_title = ' . $db->addQuotes( $oldtitle->getDBkey() ) . ' AND ' .
00961 'smw_namespace = ' . $db->addQuotes( $oldtitle->getNamespace() ) . ' AND ' .
00962 'smw_iw = ' . $db->addQuotes( '' ) . ' AND ' .
00963 'smw_subobject != ' . $db->addQuotes( '' );
00964 $db->query( $sql, __METHOD__ );
00965
00966
00967
00968
00969
00970 $this->m_idCache->moveSubobjects( $oldtitle->getDBkey(), $oldtitle->getNamespace(),
00971 $newtitle->getDBkey(), $newtitle->getNamespace() );
00972
00973
00974
00976 $this->updateRedirects( $oldtitle->getDBkey(), $oldtitle->getNamespace(), $newtitle->getDBkey(), $newtitle->getNamespace() );
00977 }
00978
00979 wfProfileOut( "SMWSQLStore2::changeTitle (SMW)" );
00980 }
00981
00983
00991 public function getQueryResult( SMWQuery $query ) {
00992 wfProfileIn( 'SMWSQLStore2::getQueryResult (SMW)' );
00993 global $smwgIP;
00994 include_once( "$smwgIP/includes/storage/SMW_SQLStore2_Queries.php" );
00995
00996 $qe = new SMWSQLStore2QueryEngine( $this, wfGetDB( DB_SLAVE ) );
00997 $result = $qe->getQueryResult( $query );
00998 wfProfileOut( 'SMWSQLStore2::getQueryResult (SMW)' );
00999
01000 return $result;
01001 }
01002
01004
01009 public function getPropertiesSpecial( $requestoptions = null ) {
01010 wfProfileIn( "SMWSQLStore2::getPropertiesSpecial (SMW)" );
01011 $db = wfGetDB( DB_SLAVE );
01012
01013 $queries = array();
01014
01015 foreach ( self::getPropertyTables() as $proptable ) {
01016 if ( $proptable->fixedproperty == false ) {
01017 $queries[] = 'SELECT smw_id, smw_title, COUNT(*) as count, smw_sortkey FROM ' .
01018 $db->tableName( $proptable->name ) . ' INNER JOIN ' .
01019 $db->tableName( 'smw_ids' ) . ' ON p_id=smw_id WHERE smw_iw=' .
01020 $db->addQuotes( '' ) . ' OR smw_iw=' . $db->addQuotes( SMW_SQL2_SMWPREDEFIW ) .
01021 ' GROUP BY smw_id,smw_title,smw_sortkey';
01022 }
01023 }
01024
01025 $query = '(' . implode( ') UNION (', $queries ) . ') ORDER BY smw_sortkey';
01026
01027
01028 if ( $requestoptions !== null ) {
01029 if ( $requestoptions->limit > 0 ) {
01030 $query = $db->limitResult( $query, $requestoptions->limit, ( $requestoptions->offset > 0 ) ? $requestoptions->offset:0 );
01031 }
01032 }
01033
01034 $res = $db->query( $query, 'SMW::getPropertySubjects' );
01035 $result = array();
01036
01037 foreach ( $res as $row ) {
01038 $result[] = array( new SMWDIProperty( $row->smw_title ), $row->count );
01039 }
01040
01041 $db->freeResult( $res );
01042 wfProfileOut( "SMWSQLStore2::getPropertiesSpecial (SMW)" );
01043
01044 return $result;
01045 }
01046
01054 public function getUnusedPropertiesSpecial( $requestoptions = null ) {
01055 global $wgDBtype;
01056
01057 wfProfileIn( "SMWSQLStore2::getUnusedPropertiesSpecial (SMW)" );
01058 $db = wfGetDB( DB_SLAVE );
01059
01060
01061 $smw_tmp_unusedprops = $db->tableName( 'smw_tmp_unusedprops' );
01062 if ( $wgDBtype == 'postgres' ) {
01063 $sql = "CREATE OR REPLACE FUNCTION create_smw_tmp_unusedprops() RETURNS void AS "
01064 . "$$ "
01065 . "BEGIN "
01066 . " IF EXISTS(SELECT NULL FROM pg_tables WHERE tablename=" . $smw_tmp_unusedprops . " AND schemaname = ANY (current_schemas(true))) "
01067 . " THEN DELETE FROM " . $smw_tmp_unusedprops . "; "
01068 . " ELSE "
01069 . " CREATE TEMPORARY TABLE " . $smw_tmp_unusedprops . " ( title text ); "
01070 . " END IF; "
01071 . "END; "
01072 . "$$ "
01073 . "LANGUAGE 'plpgsql'; "
01074 . "SELECT create_smw_tmp_unusedprops(); ";
01075 } else {
01076 $sql = "CREATE TEMPORARY TABLE " . $smw_tmp_unusedprops . "( title VARCHAR(255) ) ENGINE=MEMORY";
01077 }
01078
01079 $db->query( $sql, __METHOD__ );
01080
01081 $db->insertSelect( $smw_tmp_unusedprops, 'page', array( 'title' => 'page_title' ),
01082 array( "page_namespace" => SMW_NS_PROPERTY ), __METHOD__ );
01083
01084 $smw_ids = $db->tableName( 'smw_ids' );
01085
01086
01087 $db->deleteJoin( $smw_tmp_unusedprops, $smw_ids, 'title', 'smw_title', array( 'smw_iw' => SMW_SQL2_SMWPREDEFIW ), __METHOD__ );
01088
01089
01090 foreach ( self::getPropertyTables() as $proptable ) {
01091 if ( $proptable->fixedproperty == false ) {
01092
01093 if ( $wgDBtype == 'postgres' ) {
01094 $sql = "DELETE FROM $smw_tmp_unusedprops USING " .
01095 $db->tableName( $proptable->name ) .
01096 " INNER JOIN $smw_ids ON p_id=smw_id WHERE" .
01097 " title=smw_title AND smw_iw=" . $db->addQuotes( '' );
01098 } else {
01099 $sql = "DELETE FROM $smw_tmp_unusedprops USING " .
01100 "$smw_tmp_unusedprops INNER JOIN " . $db->tableName( $proptable->name ) .
01101 " INNER JOIN $smw_ids ON p_id=smw_id AND title=smw_title" .
01102 " AND smw_iw=" . $db->addQuotes( '' );
01103 }
01104 $db->query( $sql, __METHOD__ );
01105 }
01106 }
01107
01108
01109 $propertyTables = self::getPropertyTables();
01110 $subPropertyTableId = self::$special_tables['_SUBP'];
01111 $subPropertyTable = $propertyTables[$subPropertyTableId];
01112
01113
01114 if ( $wgDBtype == 'postgres' ) {
01115 $sql = "DELETE FROM $smw_tmp_unusedprops USING " .
01116 $db->tableName( $subPropertyTable->name ) .
01117 " INNER JOIN $smw_ids ON o_id=smw_id WHERE title=smw_title";
01118 } else {
01119 $sql = "DELETE $smw_tmp_unusedprops.* FROM $smw_tmp_unusedprops," .
01120 $db->tableName( $subPropertyTable->name ) .
01121 " INNER JOIN $smw_ids ON o_id=smw_id WHERE title=smw_title";
01122 }
01123 $db->query( $sql, __METHOD__ );
01124
01125
01126
01127
01128
01129 $db->deleteJoin( $smw_tmp_unusedprops, 'smw_redi2', 'title', 's_title', array( 's_namespace' => SMW_NS_PROPERTY ), __METHOD__ );
01130
01131 $options = $this->getSQLOptions( $requestoptions, 'title' );
01132 $options['ORDER BY'] = 'title';
01133 $res = $db->select( $smw_tmp_unusedprops, 'title', '', __METHOD__, $options );
01134
01135 $result = array();
01136
01137 foreach ( $res as $row ) {
01138 $result[] = new SMWDIProperty( $row->title );
01139 }
01140
01141 $db->freeResult( $res );
01142
01143 $db->query( "DROP " . ( $wgDBtype == 'postgres' ? '' : 'TEMPORARY' ) .
01144 " TABLE $smw_tmp_unusedprops", __METHOD__ );
01145 wfProfileOut( "SMWSQLStore2::getUnusedPropertiesSpecial (SMW)" );
01146
01147 return $result;
01148 }
01149
01159 public function getWantedPropertiesSpecial( $requestoptions = null ) {
01160 global $smwgPDefaultType;
01161
01162 wfProfileIn( "SMWSQLStore2::getWantedPropertiesSpecial (SMW)" );
01163
01164
01165 $proptables = self::getPropertyTables();
01166 $proptable = $proptables[self::findTypeTableId( $smwgPDefaultType )];
01167
01168 $result = array();
01169
01170 if ( $proptable->fixedproperty == false ) {
01171 $db = wfGetDB( DB_SLAVE );
01172 $options = $this->getSQLOptions( $requestoptions, 'title' );
01173 $options['ORDER BY'] = 'count DESC';
01174 $res = $db->select( $db->tableName( $proptable->name ) . ' INNER JOIN ' .
01175 $db->tableName( 'smw_ids' ) . ' ON p_id=smw_id LEFT JOIN ' .
01176 $db->tableName( 'page' ) . ' ON (page_namespace=' .
01177 $db->addQuotes( SMW_NS_PROPERTY ) . ' AND page_title=smw_title)',
01178 'smw_title, COUNT(*) as count',
01179 'smw_id > 50 AND page_id IS NULL GROUP BY smw_title',
01180 'SMW::getWantedPropertiesSpecial', $options );
01181
01182 foreach ( $res as $row ) {
01183 $result[] = array( new SMWDIProperty( $row->smw_title ), $row->count );
01184 }
01185 }
01186
01187 wfProfileOut( "SMWSQLStore2::getWantedPropertiesSpecial (SMW)" );
01188
01189 return $result;
01190 }
01191
01192 public function getStatistics() {
01193 wfProfileIn( 'SMWSQLStore2::getStatistics (SMW)' );
01194
01195 $db = wfGetDB( DB_SLAVE );
01196 $result = array();
01197 $proptables = self::getPropertyTables();
01198
01199
01200 $typeprop = new SMWDIProperty( '_TYPE' );
01201 $typetable = $proptables[self::findPropertyTableID( $typeprop )];
01202 $res = $db->select( $typetable->name, 'COUNT(s_id) AS count', array( 'p_id' => $this->getSMWPropertyID( $typeprop ) ), 'SMW::getStatistics' );
01203 $row = $db->fetchObject( $res );
01204 $result['DECLPROPS'] = $row->count;
01205 $db->freeResult( $res );
01206
01207
01208
01209 $result['PROPUSES'] = 0;
01210 $result['USEDPROPS'] = 0;
01211
01212 foreach ( self::getPropertyTables() as $proptable ) {
01215 $res = $db->select( $proptable->name, 'COUNT(*) AS count', '', 'SMW::getStatistics' );
01216 $row = $db->fetchObject( $res );
01217 $result['PROPUSES'] += $row->count;
01218 $db->freeResult( $res );
01219
01220 if ( $proptable->fixedproperty == false ) {
01221 $res = $db->select( $proptable->name, 'COUNT(DISTINCT(p_id)) AS count', '', 'SMW::getStatistics' );
01222 $row = $db->fetchObject( $res );
01223 $result['USEDPROPS'] += $row->count;
01224 } else {
01225 $res = $db->select( $proptable->name, '*', '', 'SMW::getStatistics', array( 'LIMIT' => 1 ) );
01226 if ( $db->numRows( $res ) > 0 ) $result['USEDPROPS']++;
01227 }
01228
01229 $db->freeResult( $res );
01230 }
01231
01232 wfProfileOut( 'SMWSQLStore2::getStatistics (SMW)' );
01233 return $result;
01234 }
01235
01237
01238 public function setup( $verbose = true ) {
01239 $this->reportProgress( "Setting up standard database configuration for SMW ...\n\n", $verbose );
01240 $this->reportProgress( "Selected storage engine is \"SMWSQLStore2\" (or an extension thereof)\n\n", $verbose );
01241
01242 $db = wfGetDB( DB_MASTER );
01243
01244 $this->setupTables( $verbose, $db );
01245 $this->setupPredefinedProperties( $verbose, $db );
01246
01247 return true;
01248 }
01249
01271 protected function setupTables( $verbose, $db ) {
01272 global $wgDBtype;
01273
01274 $reportTo = $verbose ? $this : null;
01275
01276
01277 $dbtypes = array(
01278 't' => SMWSQLHelpers::getStandardDBType( 'title' ),
01279 'l' => SMWSQLHelpers::getStandardDBType( 'blob' ),
01280 'f' => ( $wgDBtype == 'postgres' ? 'DOUBLE PRECISION' : 'DOUBLE' ),
01281 'i' => ( $wgDBtype == 'postgres' ? 'INTEGER' : 'INT(8)' ),
01282 'j' => ( $wgDBtype == 'postgres' ? 'INTEGER' : 'INT(8) UNSIGNED' ),
01283 'p' => SMWSQLHelpers::getStandardDBType( 'id' ),
01284 'n' => SMWSQLHelpers::getStandardDBType( 'namespace' ),
01285 'w' => SMWSQLHelpers::getStandardDBType( 'iw' )
01286 );
01287
01288 $smw_spec2 = $db->tableName( 'smw_spec2' );
01289
01290
01291 if ( ( $db->tableExists( $smw_spec2 ) ) && ( $db->fieldExists( $smw_spec2, 'sp_id', __METHOD__ ) ) ) {
01292 if ( $wgDBtype == 'postgres' ) {
01293 $db->query( "ALTER TABLE $smw_spec2 ALTER COLUMN sp_id RENAME TO p_id", __METHOD__ );
01294 } else {
01295 $db->query( "ALTER TABLE $smw_spec2 CHANGE `sp_id` `p_id` " . $dbtypes['p'] . " NOT NULL", __METHOD__ );
01296 }
01297 }
01298
01299
01300 SMWSQLHelpers::setupTable(
01301 'smw_ids',
01302 array(
01303 'smw_id' => $dbtypes['p'] . ' NOT NULL' . ( $wgDBtype == 'postgres' ? ' PRIMARY KEY' : ' KEY AUTO_INCREMENT' ),
01304 'smw_namespace' => $dbtypes['n'] . ' NOT NULL',
01305 'smw_title' => $dbtypes['t'] . ' NOT NULL',
01306 'smw_iw' => $dbtypes['w'] . ' NOT NULL',
01307 'smw_subobject' => $dbtypes['t'] . ' NOT NULL',
01308 'smw_sortkey' => $dbtypes['t'] . ' NOT NULL'
01309 ),
01310 $db,
01311 $reportTo
01312 );
01313
01314 SMWSQLHelpers::setupIndex( 'smw_ids', array( 'smw_id', 'smw_title,smw_namespace,smw_iw', 'smw_title,smw_namespace,smw_iw,smw_subobject', 'smw_sortkey' ), $db );
01315
01316
01317 SMWSQLHelpers::setupTable(
01318 'smw_conccache',
01319 array(
01320 's_id' => $dbtypes['p'] . ' NOT NULL',
01321 'o_id' => $dbtypes['p'] . ' NOT NULL'
01322 ),
01323 $db,
01324 $reportTo
01325 );
01326
01327 SMWSQLHelpers::setupIndex( 'smw_conccache', array( 'o_id' ), $db );
01328
01329
01330 $this->setupPropertyTables( $dbtypes, $db, $reportTo );
01331
01332 $this->reportProgress( "Database initialised successfully.\n\n", $verbose );
01333 }
01334
01342 protected function setupPropertyTables( array $dbtypes, $db, $reportTo ) {
01343 $addedCustomTypeSignatures = false;
01344
01345 foreach ( self::getPropertyTables() as $proptable ) {
01346 if ( $proptable->idsubject ) {
01347 $fieldarray = array( 's_id' => $dbtypes['p'] . ' NOT NULL' );
01348 $indexes = array( 's_id' );
01349 } else {
01350 $fieldarray = array( 's_title' => $dbtypes['t'] . ' NOT NULL', 's_namespace' => $dbtypes['n'] . ' NOT NULL' );
01351 $indexes = array( 's_title,s_namespace' );
01352 }
01353
01354 if ( !$proptable->fixedproperty ) {
01355 $fieldarray['p_id'] = $dbtypes['p'] . ' NOT NULL';
01356 $indexes[] = 'p_id';
01357 }
01358
01359 foreach ( $proptable->objectfields as $fieldname => $typeid ) {
01360
01361 if ( !$addedCustomTypeSignatures && !array_key_exists( $typeid, $dbtypes ) ) {
01362 wfRunHooks( 'SMWCustomSQLStoreFieldType', array( &$dbtypes ) );
01363 $addedCustomTypeSignatures = true;
01364 }
01365
01366
01367 if ( array_key_exists( $typeid, $dbtypes ) ) {
01368 $fieldarray[$fieldname] = $dbtypes[$typeid];
01369 }
01370 }
01371
01372 $indexes = array_merge( $indexes, $proptable->indexes );
01373
01374 SMWSQLHelpers::setupTable( $proptable->name, $fieldarray, $db, $reportTo );
01375 SMWSQLHelpers::setupIndex( $proptable->name, $indexes, $db );
01376 }
01377 }
01378
01384 protected function setupPredefinedProperties( $verbose, $db ) {
01385 global $wgDBtype;
01386
01387 $this->reportProgress( "Setting up internal property indices ...\n", $verbose );
01388
01389
01390 $borderiw = $db->selectField( 'smw_ids', 'smw_iw', 'smw_id=' . $db->addQuotes( 50 ) );
01391
01392 if ( $borderiw != SMW_SQL2_SMWBORDERIW ) {
01393 $this->reportProgress( " ... allocating space for internal properties ...\n", $verbose );
01394 $this->moveSMWPageID( 50 );
01395
01396 $db->insert( 'smw_ids', array(
01397 'smw_id' => 50,
01398 'smw_title' => '',
01399 'smw_namespace' => 0,
01400 'smw_iw' => SMW_SQL2_SMWBORDERIW,
01401 'smw_subobject' => '',
01402 'smw_sortkey' => ''
01403 ), 'SMW::setup'
01404 );
01405
01406 $this->reportProgress( ' ', $verbose );
01407
01408 for ( $i = 0; $i < 50; $i++ ) {
01409 $this->moveSMWPageID( $i );
01410 $this->reportProgress( '.', $verbose );
01411 }
01412
01413 $this->reportProgress( " done.\n", $verbose );
01414 } else {
01415 $this->reportProgress( " ... space for internal properties already allocated.\n", $verbose );
01416 }
01417
01418
01419 $this->reportProgress( " ... writing entries for internal properties ...", $verbose );
01420
01421 foreach ( self::$special_ids as $prop => $id ) {
01422 $p = new SMWDIProperty( $prop );
01423 $db->replace( 'smw_ids', array( 'smw_id' ), array(
01424 'smw_id' => $id,
01425 'smw_title' => $p->getKey(),
01426 'smw_namespace' => SMW_NS_PROPERTY,
01427 'smw_iw' => $this->getPropertyInterwiki( $p ),
01428 'smw_subobject' => '',
01429 'smw_sortkey' => $p->getKey()
01430 ), 'SMW::setup'
01431 );
01432 }
01433
01434 $this->reportProgress( " done.\n", $verbose );
01435
01436 if ( $wgDBtype == 'postgres' ) {
01437 $this->reportProgress( " ... updating smw_ids_smw_id_seq sequence accordingly.\n", $verbose );
01438
01439 $max = $db->selectField( 'smw_ids', 'max(smw_id)', array(), __METHOD__ );
01440 $max += 1;
01441
01442 $db->query( "ALTER SEQUENCE smw_ids_smw_id_seq RESTART WITH {$max}", __METHOD__ );
01443 }
01444
01445 $this->reportProgress( "Internal properties initialised successfully.\n", $verbose );
01446 }
01447
01448 public function drop( $verbose = true ) {
01449 global $wgDBtype;
01450
01451 $this->reportProgress( "Deleting all database content and tables generated by SMW ...\n\n", $verbose );
01452 $db = wfGetDB( DB_MASTER );
01453 $tables = array( 'smw_ids', 'smw_conccache' );
01454
01455 foreach ( self::getPropertyTables() as $proptable ) {
01456 $tables[] = $proptable->name;
01457 }
01458
01459 foreach ( $tables as $table ) {
01460 $name = $db->tableName( $table );
01461 $db->query( 'DROP TABLE ' . ( $wgDBtype == 'postgres' ? '' : 'IF EXISTS ' ) . $name, 'SMWSQLStore2::drop' );
01462 $this->reportProgress( " ... dropped table $name.\n", $verbose );
01463 }
01464
01465 $this->reportProgress( "All data removed successfully.\n", $verbose );
01466
01467 return true;
01468 }
01469
01480 public function refreshData( &$index, $count, $namespaces = false, $usejobs = true ) {
01481 $updatejobs = array();
01482 $emptyrange = true;
01483
01484
01485 $tids = array();
01486
01487
01488 for ( $i = $index; $i < $index + $count; $i++ ) {
01489 $tids[] = $i;
01490 }
01491
01492 $titles = Title::newFromIDs( $tids );
01493
01494 foreach ( $titles as $title ) {
01495 if ( ( $namespaces == false ) || ( in_array( $title->getNamespace(), $namespaces ) ) ) {
01496 $updatejobs[] = new SMWUpdateJob( $title );
01497 $emptyrange = false;
01498 }
01499 }
01500
01501
01502 $db = wfGetDB( DB_SLAVE );
01503 $res = $db->select( 'smw_ids', array( 'smw_id', 'smw_title', 'smw_namespace', 'smw_iw', 'smw_subobject' ),
01504 "smw_id >= $index AND smw_id < " . $db->addQuotes( $index + $count ), __METHOD__ );
01505
01506 foreach ( $res as $row ) {
01507 $emptyrange = false;
01508
01509 if ( $namespaces && !in_array( $row->smw_namespace, $namespaces ) ) continue;
01510
01511 if ( $row->smw_subobject !== '' ) {
01512
01513 } elseif ( $row->smw_iw === '' || $row->smw_iw == SMW_SQL2_SMWREDIIW ) {
01514
01515
01516 $title = Title::makeTitleSafe( $row->smw_namespace, $row->smw_title );
01517
01518 if ( $title !== null && !$title->exists() ) {
01519 $updatejobs[] = new SMWUpdateJob( $title );
01520 }
01521 } elseif ( $row->smw_iw == SMW_SQL2_SMWIW_OUTDATED ) {
01522 foreach ( self::getPropertyTables() as $proptable ) {
01523 if ( $proptable->idsubject ) {
01524 $db->delete( $proptable->name, array( 's_id' => $row->smw_id ), __METHOD__ );
01525 }
01526 }
01527 $db->delete( 'smw_ids', array( 'smw_id' => $row->smw_id ), __METHOD__ );
01528 } else {
01529 $diWikiPage = new SMWDIWikiPage( $row->smw_title, $row->smw_namespace, $row->smw_iw );
01530 $this->deleteSemanticData( $diWikiPage );
01531 }
01532 }
01533 $db->freeResult( $res );
01534
01535 wfRunHooks('smwRefreshDataJobs', array(&$updatejobs));
01536
01537 if ( $usejobs ) {
01538 Job::batchInsert( $updatejobs );
01539 } else {
01540 foreach ( $updatejobs as $job ) {
01541 $job->run();
01542 }
01543 }
01544
01545 $nextpos = $index + $count;
01546
01547 if ( $emptyrange ) {
01548 $next1 = $db->selectField( 'page', 'page_id', "page_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "page_id ASC" ) );
01549 $next2 = $db->selectField( 'smw_ids', 'smw_id', "smw_id >= $nextpos", __METHOD__, array( 'ORDER BY' => "smw_id ASC" ) );
01550 $nextpos = ( ( $next2 != 0 ) && ( $next2 < $next1 ) ) ? $next2 : $next1;
01551 }
01552
01553 $max1 = $db->selectField( 'page', 'MAX(page_id)', '', __METHOD__ );
01554 $max2 = $db->selectField( 'smw_ids', 'MAX(smw_id)', '', __METHOD__ );
01555 $index = $nextpos ? $nextpos : -1;
01556
01557 return ( $index > 0 ) ? $index / max( $max1, $max2 ) : 1;
01558 }
01559
01560
01562
01570 public function refreshConceptCache( Title $concept ) {
01571 wfProfileIn( 'SMWSQLStore2::refreshConceptCache (SMW)' );
01572 global $smwgIP;
01573
01574 include_once( "$smwgIP/includes/storage/SMW_SQLStore2_Queries.php" );
01575
01576 $qe = new SMWSQLStore2QueryEngine( $this, wfGetDB( DB_MASTER ) );
01577 $result = $qe->refreshConceptCache( $concept );
01578
01579 wfProfileOut( 'SMWSQLStore2::refreshConceptCache (SMW)' );
01580
01581 return $result;
01582 }
01583
01589 public function deleteConceptCache( $concept ) {
01590 wfProfileIn( 'SMWSQLStore2::deleteConceptCache (SMW)' );
01591 global $smwgIP;
01592
01593 include_once( "$smwgIP/includes/storage/SMW_SQLStore2_Queries.php" );
01594
01595 $qe = new SMWSQLStore2QueryEngine( $this, wfGetDB( DB_MASTER ) );
01596 $result = $qe->deleteConceptCache( $concept );
01597
01598 wfProfileOut( 'SMWSQLStore2::deleteConceptCache (SMW)' );
01599
01600 return $result;
01601 }
01602
01613 public function getConceptCacheStatus( $concept ) {
01614 wfProfileIn( 'SMWSQLStore2::getConceptCacheStatus (SMW)' );
01615
01616 $db = wfGetDB( DB_SLAVE );
01617 $cid = $this->getSMWPageID( $concept->getDBkey(), $concept->getNamespace(), '', '', false );
01618
01619 $row = $db->selectRow( 'smw_conc2',
01620 array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date', 'cache_count' ),
01621 array( 's_id' => $cid ), 'SMWSQLStore2::getConceptCacheStatus (SMW)' );
01622
01623 if ( $row !== false ) {
01624 $result = array( 'size' => $row->concept_size, 'depth' => $row->concept_depth, 'features' => $row->concept_features );
01625
01626 if ( $row->cache_date ) {
01627 $result['status'] = 'full';
01628 $result['date'] = $row->cache_date;
01629 $result['count'] = $row->cache_count;
01630 } else {
01631 $result['status'] = 'empty';
01632 }
01633 } else {
01634 $result = array( 'status' => 'no' );
01635 }
01636
01637 wfProfileOut( 'SMWSQLStore2::getConceptCacheStatus (SMW)' );
01638
01639 return $result;
01640 }
01641
01642
01644
01650 protected function getSQLOptions( $requestoptions, $valuecol = '' ) {
01651 $sql_options = array();
01652
01653 if ( $requestoptions !== null ) {
01654 if ( $requestoptions->limit > 0 ) {
01655 $sql_options['LIMIT'] = $requestoptions->limit;
01656 }
01657
01658 if ( $requestoptions->offset > 0 ) {
01659 $sql_options['OFFSET'] = $requestoptions->offset;
01660 }
01661
01662 if ( ( $valuecol !== '' ) && ( $requestoptions->sort ) ) {
01663 $sql_options['ORDER BY'] = $requestoptions->ascending ? $valuecol : $valuecol . ' DESC';
01664 }
01665 }
01666
01667 return $sql_options;
01668 }
01669
01682 protected function getSQLConditions( $requestoptions, $valuecol = '', $labelcol = '', $addand = true ) {
01683 $sql_conds = '';
01684
01685 if ( $requestoptions !== null ) {
01686 $db = wfGetDB( DB_SLAVE );
01687
01688 if ( ( $valuecol !== '' ) && ( $requestoptions->boundary !== null ) ) {
01689 if ( $requestoptions->ascending ) {
01690 $op = $requestoptions->include_boundary ? ' >= ' : ' > ';
01691 } else {
01692 $op = $requestoptions->include_boundary ? ' <= ' : ' < ';
01693 }
01694 $sql_conds .= ( $addand ? ' AND ' : '' ) . $valuecol . $op . $db->addQuotes( $requestoptions->boundary );
01695 }
01696
01697 if ( $labelcol !== '' ) {
01698 foreach ( $requestoptions->getStringConditions() as $strcond ) {
01699 $string = str_replace( '_', '\_', $strcond->string );
01700
01701 switch ( $strcond->condition ) {
01702 case SMWStringCondition::STRCOND_PRE: $string .= '%'; break;
01703 case SMWStringCondition::STRCOND_POST: $string = '%' . $string; break;
01704 case SMWStringCondition::STRCOND_MID: $string = '%' . $string . '%'; break;
01705 }
01706
01707 $sql_conds .= ( ( $addand || ( $sql_conds !== '' ) ) ? ' AND ' : '' ) . $labelcol . ' LIKE ' . $db->addQuotes( $string );
01708 }
01709 }
01710 }
01711
01712 return $sql_conds;
01713 }
01714
01722 protected function applyRequestOptions( $data, $requestoptions ) {
01723 wfProfileIn( "SMWSQLStore2::applyRequestOptions (SMW)" );
01724
01725 if ( ( count( $data ) == 0 ) || is_null( $requestoptions ) ) {
01726 wfProfileOut( "SMWSQLStore2::applyRequestOptions (SMW)" );
01727 return $data;
01728 }
01729
01730 $result = array();
01731 $sortres = array();
01732
01733 $sampleDataItem = reset( $data );
01734 $numeric = is_numeric( $sampleDataItem->getSortKey() );
01735
01736 $i = 0;
01737
01738 foreach ( $data as $item ) {
01739 $ok = true;
01740
01741 if ( $item instanceof SMWDIWikiPage ) {
01742 $label = $this->getWikiPageSortKey( $item );
01743 $value = $label;
01744 } else {
01745 $label = ( $item instanceof SMWDIBlob ) ? $item->getString() : '';
01746 $value = $item->getSortKey();
01747 }
01748
01749 if ( $requestoptions->boundary !== null ) {
01750 $strc = $numeric ? 0 : strcmp( $value, $requestoptions->boundary );
01751
01752 if ( $requestoptions->ascending ) {
01753 if ( $requestoptions->include_boundary ) {
01754 $ok = $numeric ? ( $value >= $requestoptions->boundary ) : ( $strc >= 0 );
01755 } else {
01756 $ok = $numeric ? ( $value > $requestoptions->boundary ) : ( $strc > 0 );
01757 }
01758 } else {
01759 if ( $requestoptions->include_boundary ) {
01760 $ok = $numeric ? ( $value <= $requestoptions->boundary ) : ( $strc <= 0 );
01761 } else {
01762 $ok = $numeric ? ( $value < $requestoptions->boundary ) : ( $strc < 0 );
01763 }
01764 }
01765 }
01766
01767 foreach ( $requestoptions->getStringConditions() as $strcond ) {
01768 switch ( $strcond->condition ) {
01769 case SMWStringCondition::STRCOND_PRE:
01770 $ok = $ok && ( strpos( $label, $strcond->string ) === 0 );
01771 break;
01772 case SMWStringCondition::STRCOND_POST:
01773 $ok = $ok && ( strpos( strrev( $label ), strrev( $strcond->string ) ) === 0 );
01774 break;
01775 case SMWStringCondition::STRCOND_MID:
01776 $ok = $ok && ( strpos( $label, $strcond->string ) !== false );
01777 break;
01778 }
01779 }
01780
01781 if ( $ok ) {
01782 $result[$i] = $item;
01783 $sortres[$i] = $value;
01784 $i++;
01785 }
01786 }
01787
01788 if ( $requestoptions->sort ) {
01789 $flag = $numeric ? SORT_NUMERIC : SORT_LOCALE_STRING;
01790
01791 if ( $requestoptions->ascending ) {
01792 asort( $sortres, $flag );
01793 } else {
01794 arsort( $sortres, $flag );
01795 }
01796
01797 $newres = array();
01798
01799 foreach ( $sortres as $key => $value ) {
01800 $newres[] = $result[$key];
01801 }
01802
01803 $result = $newres;
01804 }
01805
01806 if ( $requestoptions->limit > 0 ) {
01807 $result = array_slice( $result, $requestoptions->offset, $requestoptions->limit );
01808 } else {
01809 $result = array_slice( $result, $requestoptions->offset );
01810 }
01811
01812 wfProfileOut( "SMWSQLStore2::applyRequestOptions (SMW)" );
01813
01814 return $result;
01815 }
01816
01821 public function reportProgress( $msg, $verbose = true ) {
01822 if ( $verbose ) {
01823 if ( ob_get_level() == 0 ) {
01824 ob_start();
01825 }
01826
01827 print $msg;
01828 ob_flush();
01829 flush();
01830 }
01831 }
01832
01840 public static function getTypeSignature( $typeid ) {
01841 $dataItemId = SMWDataValueFactory::getDataItemId( $typeid );
01842 return array( SMWCompatibilityHelpers::getSignatureFromDataItemId( $dataItemId, $typeid ),
01843 SMWCompatibilityHelpers::getIndexFromDataItemId( $dataItemId, $typeid, false ),
01844 SMWCompatibilityHelpers::getIndexFromDataItemId( $dataItemId, $typeid, true ) );
01845 }
01846
01856 public static function tableFitsType( $tableId, $typeId ) {
01857 $dataItemId = SMWDataValueFactory::getDataItemId( $typeId );
01858 if ( $tableId == self::findDiTypeTableId( $dataItemId ) ) {
01859 return true;
01860 }
01861 foreach ( self::$special_tables as $propertyKey => $specialTableId ) {
01862 if ( $specialTableId == $tableId ) {
01863 $diProperty = new SMWDIProperty( $propertyKey, false );
01864 $propertyTypeId = $diProperty->findPropertyTypeId();
01865 if ( $typeId == $propertyTypeId ) {
01866 return true;
01867 }
01868 }
01869 }
01870 return false;
01871 }
01872
01881 public static function findTypeTableId( $typeid ) {
01882 $dataItemId = SMWDataValueFactory::getDataItemId( $typeid );
01883 return self::findDiTypeTableId( $dataItemId );
01884 }
01885
01893 public static function findDiTypeTableId( $dataItemId ) {
01894 return self::$di_type_tables[$dataItemId];
01895 }
01896
01904 public static function findAllDiTypeTableIds( $dataItemId ) {
01905 $result = array( self::findDiTypeTableId( $dataItemId ) );
01906
01907 foreach ( self::$special_tables as $specialTableId ) {
01908 if ( $dataItemId == SMWDataValueFactory::getDataItemId( $dataItemId ) ) {
01909 $result[] = $specialTableId;
01910 }
01911 }
01912
01913 return $result;
01914 }
01915
01923 public static function findPropertyTableID( SMWDIProperty $diProperty ) {
01924 $propertyKey = $diProperty->getKey();
01925 if ( array_key_exists( $propertyKey, self::$special_tables ) ) {
01926 return self::$special_tables[$propertyKey];
01927 } else {
01928 return self::findTypeTableId( $diProperty->findPropertyTypeID() );
01929 }
01930 }
01931
01938 public function getSMWPageID( $title, $namespace, $iw, $subobjectName, $canonical = true ) {
01939 global $smwgQEqualitySupport;
01940
01941 $id = $this->m_idCache->getId( $title, $namespace, $iw, $subobjectName );
01942 if ( $id == 0 && $smwgQEqualitySupport != SMW_EQ_NONE
01943 && $subobjectName === '' && $iw === '' ) {
01944 $iw = SMW_SQL2_SMWREDIIW;
01945 $id = $this->m_idCache->getId( $title, $namespace, SMW_SQL2_SMWREDIIW, $subobjectName );
01946 }
01947
01948 if ( $id == 0 || !$canonical || $iw != SMW_SQL2_SMWREDIIW ) {
01949 return $id;
01950 } else {
01951 $rediId = $this->getRedirectId( $title, $namespace );
01952 return $rediId != 0 ? $rediId : $id;
01953 }
01954 }
01955
01960 public function getSMWPageIDandSort( $title, $namespace, $iw, $subobjectName, &$sort, $canonical ) {
01961 wfProfileIn( 'SMWSQLStore2::getSMWPageID (SMW)' );
01962
01963 global $smwgQEqualitySupport;
01964
01965 $db = wfGetDB( DB_SLAVE );
01966
01967 if ( $iw !== '' && !is_null( $iw ) ) {
01968 $iwCond = 'smw_iw=' . $db->addQuotes( $iw );
01969 } else {
01970 $iwCond = '(smw_iw=' . $db->addQuotes( '' ) .
01971 ' OR smw_iw=' . $db->addQuotes( SMW_SQL2_SMWREDIIW ) . ')';
01972 }
01973
01974 $row = $db->selectRow( 'smw_ids', array( 'smw_id', 'smw_iw', 'smw_sortkey' ),
01975 'smw_title=' . $db->addQuotes( $title ) .
01976 ' AND smw_namespace=' . $db->addQuotes( $namespace ) .
01977 " AND $iwCond AND smw_subobject=" . $db->addQuotes( $subobjectName ),
01978 __METHOD__ );
01979
01980 if ( $row !== false ) {
01981 $sort = $row->smw_sortkey;
01982 $this->m_idCache->setId( $title, $namespace, $row->smw_iw, $subobjectName, $row->smw_id );
01983
01984 if ( $row->smw_iw == SMW_SQL2_SMWREDIIW && $canonical &&
01985 $subobjectName === '' && $smwgQEqualitySupport != SMW_EQ_NONE ) {
01986 $id = $this->getRedirectId( $title, $namespace );
01987 $this->m_idCache->setId( $title, $namespace, $iw, $subobjectName, 0 );
01988 } else {
01989 $id = $row->smw_id;
01990 }
01991 } else {
01992 $id = 0;
01993 $this->m_idCache->setId( $title, $namespace, $iw, $subobjectName, 0 );
01994 }
01995
01996 wfProfileOut( 'SMWSQLStore2::getSMWPageID (SMW)' );
01997 return $id;
01998 }
01999
02000 public function getRedirectId( $title, $namespace ) {
02001 $db = wfGetDB( DB_SLAVE );
02002 $row = $db->selectRow( 'smw_redi2', 'o_id',
02003 array( 's_title' => $title, 's_namespace' => $namespace ), __METHOD__ );
02004 return ( $row === false ) ? 0 : $row->o_id;
02005 }
02006
02017 protected function makeSMWPageID( $title, $namespace, $iw, $subobjectName, $canonical = true, $sortkey = '' ) {
02018 wfProfileIn( 'SMWSQLStore2::makeSMWPageID (SMW)' );
02019
02020 $oldsort = '';
02021 if ( $sortkey !== '' ) {
02022 $id = $this->getSMWPageIDandSort( $title, $namespace, $iw, $subobjectName, $oldsort, $canonical );
02023 } else {
02024 $id = $this->getSMWPageID( $title, $namespace, $iw, $subobjectName, $canonical );
02025 }
02026
02027 if ( $id == 0 ) {
02028 $db = wfGetDB( DB_MASTER );
02029 $sortkey = $sortkey ? $sortkey : ( str_replace( '_', ' ', $title ) );
02030
02031 $db->insert(
02032 'smw_ids',
02033 array(
02034 'smw_id' => $db->nextSequenceValue( 'smw_ids_smw_id_seq' ),
02035 'smw_title' => $title,
02036 'smw_namespace' => $namespace,
02037 'smw_iw' => $iw,
02038 'smw_subobject' => $subobjectName,
02039 'smw_sortkey' => $sortkey
02040 ),
02041 __METHOD__
02042 );
02043
02044 $id = $db->insertId();
02045
02046 $this->m_idCache->setId( $title, $namespace, $iw, $subobjectName, $id );
02047 } elseif ( ( $sortkey !== '' ) && ( $sortkey != $oldsort ) ) {
02048 $db = wfGetDB( DB_MASTER );
02049 $db->update( 'smw_ids', array( 'smw_sortkey' => $sortkey ), array( 'smw_id' => $id ), __METHOD__ );
02050 }
02051
02052 wfProfileOut( 'SMWSQLStore2::makeSMWPageID (SMW)' );
02053 return $id;
02054 }
02055
02062 protected function getPropertyInterwiki( SMWDIProperty $property ) {
02063 if ( $property->isUserDefined() ) {
02064 return '';
02065 } else {
02066 return ( $property->getLabel() !== '' ) ? SMW_SQL2_SMWPREDEFIW : SMW_SQL2_SMWINTDEFIW;
02067 }
02068 }
02069
02074 public function getSMWPropertyID( SMWDIProperty $property ) {
02075 if ( ( !$property->isUserDefined() ) && ( array_key_exists( $property->getKey(), self::$special_ids ) ) ) {
02076 return self::$special_ids[$property->getKey()];
02077 } else {
02078 return $this->getSMWPageID( $property->getKey(), SMW_NS_PROPERTY, $this->getPropertyInterwiki( $property ), '', true );
02079 }
02080 }
02081
02086 protected function makeSMWPropertyID( SMWDIProperty $property ) {
02087 if ( ( !$property->isUserDefined() ) && ( array_key_exists( $property->getKey(), self::$special_ids ) ) ) {
02088 return self::$special_ids[$property->getKey()];
02089 } else {
02090 return $this->makeSMWPageID( $property->getKey(), SMW_NS_PROPERTY,
02091 $this->getPropertyInterwiki( $property ), '', true );
02092 }
02093 }
02094
02102 public function cacheSMWPageID( $id, $title, $namespace, $iw, $subobjectName ) {
02103 $this->m_idCache->setId( $title, $namespace, $iw, $subobjectName, $id );
02104 }
02105
02114 protected function moveSMWPageID( $curid, $targetid = 0 ) {
02115 $db = wfGetDB( DB_MASTER );
02116
02117 $row = $db->selectRow( 'smw_ids', '*', array( 'smw_id' => $curid ), __METHOD__ );
02118
02119 if ( $row === false ) return;
02120
02121 if ( $targetid == 0 ) {
02122 $db->insert(
02123 'smw_ids',
02124 array(
02125 'smw_id' => $db->nextSequenceValue( 'smw_ids_smw_id_seq' ),
02126 'smw_title' => $row->smw_title,
02127 'smw_namespace' => $row->smw_namespace,
02128 'smw_iw' => $row->smw_iw,
02129 'smw_subobject' => $row->smw_subobject,
02130 'smw_sortkey' => $row->smw_sortkey
02131 ),
02132 __METHOD__
02133 );
02134 $targetid = $db->insertId();
02135 } else {
02136 $db->insert( 'smw_ids',
02137 array( 'smw_id' => $targetid,
02138 'smw_title' => $row->smw_title,
02139 'smw_namespace' => $row->smw_namespace,
02140 'smw_iw' => $row->smw_iw,
02141 'smw_subobject' => $row->smw_subobject,
02142 'smw_sortkey' => $row->smw_sortkey
02143 ),
02144 __METHOD__
02145 );
02146 }
02147
02148 $db->delete( 'smw_ids', array( 'smw_id' => $curid ), 'SMWSQLStore2::moveSMWPageID' );
02149
02150 $this->m_idCache->setId( $row->smw_title, $row->smw_namespace, $row->smw_iw,
02151 $row->smw_subobject, $targetid );
02152
02153 $this->changeSMWPageID( $curid, $targetid, $row->smw_namespace, $row->smw_namespace );
02154 }
02155
02178 protected function changeSMWPageID( $oldid, $newid, $oldnamespace = -1,
02179 $newnamespace = -1, $sdata = true, $podata = true ) {
02180 $db = wfGetDB( DB_MASTER );
02181
02182
02183 foreach ( self::getPropertyTables() as $proptable ) {
02184 if ( $sdata && $proptable->idsubject ) {
02185 $db->update( $proptable->name, array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ );
02186 }
02187
02188 if ( $podata ) {
02189 if ( ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_PROPERTY ) ) && ( $proptable->fixedproperty == false ) ) {
02190 if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_PROPERTY ) ) {
02191 $db->update( $proptable->name, array( 'p_id' => $newid ), array( 'p_id' => $oldid ), __METHOD__ );
02192 } else {
02193 $db->delete( $proptable->name, array( 'p_id' => $oldid ), __METHOD__ );
02194 }
02195 }
02196
02197 foreach ( $proptable->objectfields as $fieldname => $type ) {
02198 if ( $type == 'p' ) {
02199 $db->update( $proptable->name, array( $fieldname => $newid ), array( $fieldname => $oldid ), __METHOD__ );
02200 }
02201 }
02202 }
02203 }
02204
02205
02206 if ( $sdata && ( ( $oldnamespace == -1 ) || ( $oldnamespace == SMW_NS_CONCEPT ) ) ) {
02207 if ( ( $newnamespace == -1 ) || ( $newnamespace == SMW_NS_CONCEPT ) ) {
02208 $db->update( 'smw_conc2', array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ );
02209 $db->update( 'smw_conccache', array( 's_id' => $newid ), array( 's_id' => $oldid ), __METHOD__ );
02210 } else {
02211 $db->delete( 'smw_conc2', array( 's_id' => $oldid ), __METHOD__ );
02212 $db->delete( 'smw_conccache', array( 's_id' => $oldid ), __METHOD__ );
02213 }
02214 }
02215
02216 if ( $podata ) {
02217 $db->update( 'smw_conccache', array( 'o_id' => $newid ), array( 'o_id' => $oldid ), __METHOD__ );
02218 }
02219 }
02220
02227 protected function deleteSemanticData( SMWDIWikiPage $subject ) {
02228 if ( $subject->getSubobjectName() !== '' ) return;
02229
02230 $db = wfGetDB( DB_MASTER );
02231
02232 $id = $this->getSMWPageID( $subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), '', false );
02233
02234 if ( $id == 0 ) {
02235
02236 wfRunHooks( 'smwDeleteSemanticData', array( $subject ) );
02237 return;
02238 }
02239
02240 foreach ( self::getPropertyTables() as $proptable ) {
02241 if ( $proptable->name == 'smw_conc2' ) continue;
02242 if ( $proptable->idsubject ) {
02243 $db->delete( $proptable->name, array( 's_id' => $id ), __METHOD__ );
02244 } elseif ( $proptable->name != 'smw_redi2' ) {
02245 $db->delete( $proptable->name, array( 's_title' => $subject->getDBkey(), 's_namespace' => $subject->getNamespace() ), __METHOD__ );
02246 }
02247 }
02248
02249
02250 $res = $db->select( 'smw_ids', '*',
02251 'smw_title = ' . $db->addQuotes( $subject->getDBkey() ) . ' AND ' .
02252 'smw_namespace = ' . $db->addQuotes( $subject->getNamespace() ) . ' AND ' .
02253 'smw_iw = ' . $db->addQuotes( $subject->getInterwiki() ) . ' AND ' .
02254 'smw_subobject != ' . $db->addQuotes( '' ),
02255
02256
02257
02258
02259
02260 __METHOD__ );
02261 $subobjects = array();
02262
02263
02264 foreach ( $res as $row ) {
02265 $subobjects[] = $row->smw_id;
02266 $this->m_idCache->setId( $row->smw_title, $row->smw_namespace,
02267 $row->smw_iw, $row->smw_subobject, 0 );
02268 foreach ( self::getPropertyTables() as $proptable ) {
02269 if ( $proptable->idsubject ) {
02270 $db->delete( $proptable->name, array( 's_id' => $row->smw_id ), __METHOD__ );
02271 }
02272 }
02273 }
02274
02275 $db->freeResult( $res );
02276
02277
02278 if ( count( $subobjects ) > 0 ) {
02279 $db->delete( 'smw_ids',
02280 array( 'smw_id' => $subobjects),
02281 __METHOD__ );
02282 }
02283
02284 wfRunHooks( 'smwDeleteSemanticData', array( $subject ) );
02285 }
02286
02308 protected function updateRedirects( $subject_t, $subject_ns, $curtarget_t = '', $curtarget_ns = -1 ) {
02309 global $smwgQEqualitySupport, $smwgEnableUpdateJobs;
02310
02311
02312
02313 $sid = $this->getSMWPageID( $subject_t, $subject_ns, '', '', false );
02315 $new_tid = $curtarget_t ? ( $this->makeSMWPageID( $curtarget_t, $curtarget_ns, '', '', false ) ) : 0;
02316
02317 $db = wfGetDB( DB_SLAVE );
02318 $row = $db->selectRow( array( 'smw_redi2' ), 'o_id',
02319 array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), __METHOD__ );
02320 $old_tid = ( $row !== false ) ? $row->o_id : 0;
02322
02323 if ( $old_tid == $new_tid ) {
02324 return ( $new_tid == 0 ) ? $sid : $new_tid;
02325 }
02326
02327
02328
02329 $db = wfGetDB( DB_MASTER );
02330
02331 if ( ( $old_tid == 0 ) && ( $sid != 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) {
02332
02333
02334 $this->changeSMWPageID( $sid, $new_tid, $subject_ns, $curtarget_ns, false, true );
02335 } elseif ( $old_tid != 0 ) {
02336 $db->delete( 'smw_redi2',
02337 array( 's_title' => $subject_t, 's_namespace' => $subject_ns ), __METHOD__ );
02338
02339 if ( $smwgEnableUpdateJobs && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) {
02340
02341
02342 $jobs = array();
02343
02344 foreach ( self::getPropertyTables() as $proptable ) {
02345 if ( $proptable->name == 'smw_redi2' ) continue;
02346
02347 if ( $proptable->idsubject ) {
02348 $from = $db->tableName( $proptable->name ) . ' INNER JOIN ' .
02349 $db->tableName( 'smw_ids' ) . ' ON s_id=smw_id';
02350 $select = 'DISTINCT smw_title AS t,smw_namespace AS ns';
02351 } else {
02352 $from = $db->tableName( $proptable->name );
02353 $select = 'DISTINCT s_title AS t,s_namespace AS ns';
02354 }
02355
02356 if ( $subject_ns == SMW_NS_PROPERTY && !$proptable->fixedproperty ) {
02357 $res = $db->select( $from, $select,
02358 array( 'p_id' => $old_tid ), __METHOD__ );
02359 foreach ( $res as $row ) {
02360 $title = Title::makeTitleSafe( $row->ns, $row->t );
02361 if ( !is_null( $title ) ) {
02362 $jobs[] = new SMWUpdateJob( $title );
02363 }
02364 }
02365 $db->freeResult( $res );
02366 }
02367
02368 foreach ( $proptable->objectfields as $fieldname => $type ) {
02369 if ( $type == 'p' ) {
02370 $res = $db->select( $from, $select,
02371 array( $fieldname => $old_tid ), __METHOD__ );
02372 foreach ( $res as $row ) {
02373 $title = Title::makeTitleSafe( $row->ns, $row->t );
02374 if ( !is_null( $title ) ) {
02375 $jobs[] = new SMWUpdateJob( $title );
02376 }
02377 }
02378 $db->freeResult( $res );
02379 }
02380 }
02381 }
02382
02384
02386 Job::batchInsert( $jobs );
02387 }
02388 }
02389
02390
02391
02392 if ( $new_tid != 0 ) {
02393
02394
02395
02396
02397
02398
02399
02400 if ( ( $old_tid == 0 ) && ( $smwgQEqualitySupport != SMW_EQ_NONE ) ) {
02401
02402 if ( $sid == 0 ) {
02403 $sid = $this->makeSMWPageID( $subject_t, $subject_ns,
02404 SMW_SQL2_SMWREDIIW, '', false );
02405 } else {
02406 $db->update( 'smw_ids', array( 'smw_iw' => SMW_SQL2_SMWREDIIW ),
02407 array( 'smw_id' => $sid ), __METHOD__ );
02408 $this->m_idCache->setId( $subject_t, $subject_ns, '', '', 0 );
02409 $this->m_idCache->setId( $subject_t, $subject_ns, SMW_SQL2_SMWREDIIW, '', $sid );
02410 }
02411 }
02412
02413 $db->insert( 'smw_redi2', array( 's_title' => $subject_t,
02414 's_namespace' => $subject_ns, 'o_id' => $new_tid ), __METHOD__ );
02415 } else {
02416
02417
02418
02419 if ( $smwgQEqualitySupport != SMW_EQ_NONE ) {
02420 $db->update( 'smw_ids', array( 'smw_iw' => '' ), array( 'smw_id' => $sid ), __METHOD__ );
02421 $this->m_idCache->setId( $subject_t, $subject_ns, '', '', $sid );
02422 }
02423 }
02424
02425
02426
02427 unset( $this->m_semdata[$sid] ); unset( $this->m_semdata[$new_tid] ); unset( $this->m_semdata[$old_tid] );
02428 unset( $this->m_sdstate[$sid] ); unset( $this->m_sdstate[$new_tid] ); unset( $this->m_sdstate[$old_tid] );
02429
02430 return ( $new_tid == 0 ) ? $sid : $new_tid;
02431 }
02432
02453 public static function getPropertyTables() {
02454 if ( count( self::$prop_tables ) > 0 ) return self::$prop_tables;
02455
02456 self::$prop_tables['smw_rels2'] = new SMWSQLStore2Table(
02457 'smw_rels2',
02458 array( 'o_id' => 'p' ),
02459 array( 'o_id' )
02460 );
02461
02462 self::$prop_tables['smw_atts2'] = new SMWSQLStore2Table(
02463 'smw_atts2',
02464 array( 'value_xsd' => 't', 'value_num' => 'f' ),
02465 array( 'value_num', 'value_xsd' )
02466 );
02467
02468 self::$prop_tables['smw_text2'] = new SMWSQLStore2Table(
02469 'smw_text2',
02470 array( 'value_blob' => 'l' )
02471 );
02472
02473 self::$prop_tables['smw_spec2'] = new SMWSQLStore2Table(
02474 'smw_spec2',
02475 array( 'value_string' => 't' ),
02476 array( 's_id,p_id' )
02477 );
02478 self::$prop_tables['smw_spec2']->specpropsonly = true;
02479
02480 self::$prop_tables['smw_subs2'] = new SMWSQLStore2Table(
02481 'smw_subs2',
02482 array( 'o_id' => 'p' ),
02483 array( 'o_id' ),
02484 '_SUBC'
02485 );
02486
02487 self::$prop_tables['smw_subp2'] = new SMWSQLStore2Table(
02488 'smw_subp2',
02489 array( 'o_id' => 'p' ),
02490 array( 'o_id' ),
02491 '_SUBP'
02492 );
02493
02494 self::$prop_tables['smw_inst2'] = new SMWSQLStore2Table(
02495 'smw_inst2',
02496 array( 'o_id' => 'p' ),
02497 array( 'o_id' ),
02498 '_INST'
02499 );
02500
02501 self::$prop_tables['smw_redi2'] = new SMWSQLStore2Table(
02502 'smw_redi2',
02503 array( 'o_id' => 'p' ),
02504 array( 'o_id' ),
02505 '_REDI'
02506 );
02507 self::$prop_tables['smw_redi2']->idsubject = false;
02508
02509 self::$prop_tables['smw_conc2'] = new SMWSQLStore2Table(
02510 'smw_conc2',
02511 array( 'concept_txt' => 'l', 'concept_docu' => 'l', 'concept_features' => 'n', 'concept_size' => 'n', 'concept_depth' => 'n','cache_date' => 'j', 'cache_count' => 'j' ),
02512 array( ),
02513 '_CONC'
02514 );
02515
02516 self::$prop_tables['smw_coords'] = new SMWSQLStore2Table(
02517 'sm_coords',
02518 array( 'lat' => 'f', 'lon' => 'f', 'alt' => 'f' ),
02519 array( 'lat', 'lon', 'alt' )
02520 );
02521
02522 wfRunHooks( 'SMWPropertyTables', array( &self::$prop_tables ) );
02523
02524 foreach ( self::$prop_tables as $tid => $proptable ) {
02525 if ( $proptable->fixedproperty != false ) {
02526 self::$special_tables[$proptable->fixedproperty] = $tid;
02527 }
02528 }
02529
02530 return self::$prop_tables;
02531 }
02532
02533 }