public function setup($verbose = true)
 {
     $this->reportProgress("Setting up standard database configuration for SMW ...\n\n", $verbose);
     $this->reportProgress("Selected storage engine is \"SMWSQLStore3\" (or an extension thereof)\n\n", $verbose);
     $db = $this->store->getConnection(DB_MASTER);
     $this->setupTables($verbose, $db);
     $this->setupPredefinedProperties($verbose, $db);
     return true;
 }
 /**
  * Get a SQL option array for the given query and preprocessed query object at given id.
  *
  * @param Query $query
  * @param integer $rootId
  *
  * @return array
  */
 private function getSQLOptions(Query $query, $rootId)
 {
     $result = array('LIMIT' => $query->getLimit() + 5, 'OFFSET' => $query->getOffset());
     // Build ORDER BY options using discovered sorting fields.
     if ($this->engineOptions->get('smwgQSortingSupport')) {
         $qobj = $this->querySegments[$rootId];
         foreach ($this->sortKeys as $propkey => $order) {
             if (!is_string($propkey)) {
                 throw new RuntimeException("Expected a string value as sortkey");
             }
             // #835
             // SELECT DISTINCT and ORDER BY RANDOM causes an issue for postgres
             // Disable RANDOM support for postgres
             if ($this->store->getConnection()->getType() === 'postgres') {
                 $this->engineOptions->set('smwgQRandSortingSupport', false);
             }
             if ($order != 'RANDOM' && array_key_exists($propkey, $qobj->sortfields)) {
                 // Field was successfully added.
                 $result['ORDER BY'] = (array_key_exists('ORDER BY', $result) ? $result['ORDER BY'] . ', ' : '') . $qobj->sortfields[$propkey] . " {$order} ";
             } elseif ($order == 'RANDOM' && $this->engineOptions->get('smwgQRandSortingSupport')) {
                 $result['ORDER BY'] = (array_key_exists('ORDER BY', $result) ? $result['ORDER BY'] . ', ' : '') . ' RAND() ';
             }
         }
     }
     return $result;
 }
 public function drop($verbose = true)
 {
     global $wgDBtype;
     $this->reportProgress("Deleting all database content and tables generated by SMW ...\n\n", $verbose);
     $dbw = $this->store->getConnection('mw.db');
     $tables = array(SMWSQLStore3::ID_TABLE, SMWSQLStore3::CONCEPT_CACHE_TABLE, SMWSQLStore3::PROPERTY_STATISTICS_TABLE, SMWSQLStore3::QUERY_LINKS_TABLE);
     foreach ($this->store->getPropertyTables() as $proptable) {
         $tables[] = $proptable->getName();
     }
     foreach ($tables as $table) {
         $name = $dbw->tableName($table);
         $dbw->query('DROP TABLE ' . ($wgDBtype == 'postgres' ? '' : 'IF EXISTS ') . $name, 'SMWSQLStore3::drop');
         $this->reportProgress(" ... dropped table {$name}.\n", $verbose);
     }
     $this->reportProgress("All data removed successfully.\n", $verbose);
     return true;
 }
 /**
  * Implementation of SMWStore::getInProperties(). This function is meant to
  * be used for finding properties that link to wiki pages.
  *
  * @since 1.8
  * @see SMWStore::getInProperties
  *
  * @param SMWDataItem $value
  * @param SMWRequestOptions|null $requestOptions
  *
  * @return array of SMWWikiPageValue
  */
 public function getInProperties(SMWDataItem $value, SMWRequestOptions $requestOptions = null)
 {
     $db = $this->store->getConnection();
     $result = array();
     // Potentially need to get more results, since options apply to union.
     if ($requestOptions !== null) {
         $subOptions = clone $requestOptions;
         $subOptions->limit = $requestOptions->limit + $requestOptions->offset;
         $subOptions->offset = 0;
     } else {
         $subOptions = null;
     }
     $diType = $value->getDIType();
     foreach ($this->store->getPropertyTables() as $proptable) {
         if ($diType != $proptable->getDiType()) {
             continue;
         }
         $where = $from = '';
         if (!$proptable->isFixedPropertyTable()) {
             // join ID table to get property titles
             $from = $db->tableName(SMWSql3SmwIds::TABLE_NAME) . " INNER JOIN " . $db->tableName($proptable->getName()) . " AS t1 ON t1.p_id=smw_id";
             $this->prepareValueQuery($from, $where, $proptable, $value, 1);
             $where .= " AND smw_iw!=" . $db->addQuotes(SMW_SQL3_SMWIW_OUTDATED) . " AND smw_iw!=" . $db->addQuotes(SMW_SQL3_SMWDELETEIW);
             $res = $db->select($from, 'DISTINCT smw_title,smw_sortkey,smw_iw', $where . $this->store->getSQLConditions($subOptions, 'smw_sortkey', 'smw_sortkey', $where !== ''), __METHOD__, $this->store->getSQLOptions($subOptions, 'smw_sortkey'));
             foreach ($res as $row) {
                 try {
                     $result[] = new SMW\DIProperty($row->smw_title);
                 } catch (SMWDataItemException $e) {
                     // has been observed to happen (empty property title); cause unclear; ignore this data
                 }
             }
         } else {
             $from = $db->tableName($proptable->getName()) . " AS t1";
             $this->prepareValueQuery($from, $where, $proptable, $value, 1);
             $res = $db->select($from, '*', $where, __METHOD__, array('LIMIT' => 1));
             if ($db->numRows($res) > 0) {
                 $result[] = new SMW\DIProperty($proptable->getFixedProperty());
             }
         }
         $db->freeResult($res);
     }
     $result = $this->store->applyRequestOptions($result, $requestOptions);
     // apply options to overall result
     return $result;
 }
 /**
  * Helper method to write information about some redirect. Various updates
  * can be necessary if redirects are resolved as identities in SMW. The
  * title and namespace of the affected page and of its updated redirect
  * target are given. The target can be empty ('') to delete any redirect.
  * Returns the canonical ID that is now to be used for the subject.
  *
  * This method does not change the ids of the affected pages, and thus it
  * is not concerned with updates of the data that is currently stored for
  * the subject. Normally, a subject that is a redirect will not have other
  * data, but this method does not depend on this.
  *
  * @note Please make sure you fully understand this code before making any
  * changes here. Keeping the redirect structure consistent is important,
  * and errors in this code can go unnoticed for quite some time.
  *
  * @note This method merely handles the addition or deletion of a redirect
  * statement in the wiki. It does not assume that any page contents has
  * been changed (e.g. moved). See changeTitle() for additional handling in
  * this case.
  *
  * @todo Clean up this code.
  *
  * @since 1.8
  * @param string $subject_t
  * @param integer $subject_ns
  * @param string $curtarget_t
  * @param integer $curtarget_ns
  * @return integer the new canonical ID of the subject
  */
 protected function updateRedirects($subject_t, $subject_ns, $curtarget_t = '', $curtarget_ns = -1)
 {
     global $smwgQEqualitySupport, $smwgEnableUpdateJobs;
     $count = 0;
     //track count changes for redi property
     $db = $this->store->getConnection();
     // *** First get id of subject, old redirect target, and current (new) redirect target ***//
     $sid_sort = '';
     // find real id of subject, if any
     $sid = $this->store->getObjectIds()->getSMWPageIDandSort($subject_t, $subject_ns, '', '', $sid_sort, false);
     /// NOTE: $sid can be 0 here; this is useful to know since it means that fewer table updates are needed
     $new_tid = $curtarget_t ? $this->store->getObjectIds()->makeSMWPageID($curtarget_t, $curtarget_ns, '', '', false) : 0;
     // real id of new target, if given
     $old_tid = $this->store->getObjectIds()->findRedirectIdFor($subject_t, $subject_ns);
     /// NOTE: $old_tid and $new_tid both (intentionally) ignore further redirects: no redirect chains
     if ($old_tid == $new_tid) {
         // no change, all happy
         return $new_tid == 0 ? $sid : $new_tid;
     }
     // note that this means $old_tid != $new_tid in all cases below
     // *** Make relevant changes in property tables (don't write the new redirect yet) ***//
     $jobs = array();
     if ($old_tid == 0 && $sid != 0 && $smwgQEqualitySupport != SMW_EQ_NONE) {
         // new redirect
         // $smwgQEqualitySupport requires us to change all tables' page references from $sid to $new_tid.
         // Since references must not be 0, we don't have to do this is $sid == 0.
         $this->store->changeSMWPageID($sid, $new_tid, $subject_ns, $curtarget_ns, false, true);
         $jobs = $this->makeUpdateJobsForNewRedirect($subject_t, $subject_ns, $curtarget_t, $curtarget_ns);
     } elseif ($old_tid != 0) {
         // existing redirect is changed or deleted
         $this->store->getObjectIds()->deleteRedirectEntry($subject_t, $subject_ns);
         $count--;
         if ($this->store->getUpdateJobsEnabledState() && $smwgQEqualitySupport != SMW_EQ_NONE) {
             // entries that refer to old target may in fact refer to subject,
             // but we don't know which: schedule affected pages for update
             $propertyTables = $this->store->getPropertyTables();
             foreach ($propertyTables as $proptable) {
                 if ($proptable->getName() == 'smw_fpt_redi') {
                     continue;
                     // can safely be skipped
                 }
                 if ($proptable->usesIdSubject()) {
                     $from = $db->tableName($proptable->getName()) . ' INNER JOIN ' . $db->tableName(SMWSql3SmwIds::tableName) . ' ON s_id=smw_id';
                     $select = 'DISTINCT smw_title AS t,smw_namespace AS ns';
                 } else {
                     $from = $db->tableName($proptable->getName());
                     $select = 'DISTINCT s_title AS t,s_namespace AS ns';
                 }
                 if ($subject_ns === SMW_NS_PROPERTY && !$proptable->isFixedPropertyTable()) {
                     $res = $db->select($from, $select, array('p_id' => $old_tid), __METHOD__);
                     foreach ($res as $row) {
                         $title = Title::makeTitleSafe($row->ns, $row->t);
                         if (!is_null($title)) {
                             $jobs[] = new UpdateJob($title);
                         }
                     }
                     $db->freeResult($res);
                 }
                 foreach ($proptable->getFields($this->store) as $fieldname => $type) {
                     if ($type == 'p') {
                         $res = $db->select($from, $select, array($fieldname => $old_tid), __METHOD__);
                         foreach ($res as $row) {
                             $title = Title::makeTitleSafe($row->ns, $row->t);
                             if (!is_null($title)) {
                                 $jobs[] = new UpdateJob($title);
                             }
                         }
                         $db->freeResult($res);
                     }
                 }
             }
             /// NOTE: we do not update the concept cache here; this remains an offline task
         }
     }
     if ($this->store->getUpdateJobsEnabledState()) {
         JobBase::batchInsert($jobs);
     }
     // *** Finally, write the new redirect data ***//
     if ($new_tid != 0) {
         // record a new redirect
         // Redirecting done right:
         // (1) make a new ID with iw SMW_SQL3_SMWREDIIW or
         //     change iw field of current ID in this way,
         // (2) write smw_fpt_redi table,
         // (3) update canonical cache.
         // This order must be obeyed unless you really understand what you are doing!
         if ($old_tid == 0 && $smwgQEqualitySupport != SMW_EQ_NONE) {
             // mark subject as redirect (if it was no redirect before)
             if ($sid == 0) {
                 // every redirect page must have an ID
                 $sid = $this->store->getObjectIds()->makeSMWPageID($subject_t, $subject_ns, SMW_SQL3_SMWREDIIW, '', false);
             } else {
                 $db->update(SMWSql3SmwIds::tableName, array('smw_iw' => SMW_SQL3_SMWREDIIW), array('smw_id' => $sid), __METHOD__);
                 $this->store->getObjectIds()->setCache($subject_t, $subject_ns, '', '', 0, '');
                 $this->store->getObjectIds()->setCache($subject_t, $subject_ns, SMW_SQL3_SMWREDIIW, '', $sid, $sid_sort);
             }
         }
         $this->store->getObjectIds()->addRedirectForId($new_tid, $subject_t, $subject_ns);
         $count++;
     } else {
         // delete old redirect
         // This case implies $old_tid != 0 (or we would have new_tid == old_tid above).
         // Therefore $subject had a redirect, and it must also have an ID.
         // This shows that $sid != 0 here.
         if ($smwgQEqualitySupport != SMW_EQ_NONE) {
             // mark subject as non-redirect
             $db->update(SMWSql3SmwIds::tableName, array('smw_iw' => ''), array('smw_id' => $sid), __METHOD__);
             $this->store->getObjectIds()->setCache($subject_t, $subject_ns, SMW_SQL3_SMWREDIIW, '', 0, '');
             $this->store->getObjectIds()->setCache($subject_t, $subject_ns, '', '', $sid, $sid_sort);
         }
     }
     // *** Flush some caches to be safe, though they are not essential in runs with redirect updates ***//
     unset($this->store->m_semdata[$sid]);
     unset($this->store->m_semdata[$new_tid]);
     unset($this->store->m_semdata[$old_tid]);
     unset($this->store->m_sdstate[$sid]);
     unset($this->store->m_sdstate[$new_tid]);
     unset($this->store->m_sdstate[$old_tid]);
     // *** Update reference count for _REDI property ***//
     $statsTable = new PropertyStatisticsTable($db, SMWSQLStore3::PROPERTY_STATISTICS_TABLE);
     $statsTable->addToUsageCount($this->store->getObjectIds()->getSMWPropertyID(new SMWDIProperty('_REDI')), $count);
     return $new_tid == 0 ? $sid : $new_tid;
 }
 /**
  * Update the proptable_hash for a given page.
  *
  * @since 1.8
  * @param integer $sid ID of the page as stored in SMW IDs table
  * @param string[] of hash values with table names as keys
  */
 public function setPropertyTableHashes($sid, array $newTableHashes)
 {
     $db = $this->store->getConnection();
     $propertyTableHash = serialize($newTableHashes);
     $db->update(self::tableName, array('smw_proptable_hash' => $propertyTableHash), array('smw_id' => $sid), __METHOD__);
     if ($sid == $this->hashCacheId) {
         $this->setPropertyTableHashesCache($sid, $propertyTableHash);
     }
 }
 private function newTemporaryTableBuilder()
 {
     $temporaryTableBuilder = new TemporaryTableBuilder($this->store->getConnection('mw.db.queryengine'));
     $temporaryTableBuilder->withAutoCommit($this->applicationFactory->getSettings()->get('smwgQTemporaryTablesAutoCommitMode'));
     return $temporaryTableBuilder;
 }