/**
  * @since 2.2
  *
  * @param Description $description
  *
  * @return QuerySegment
  */
 public function interpretDescription(Description $description)
 {
     $query = new QuerySegment();
     $cqid = QuerySegment::$qnum;
     $cquery = new QuerySegment();
     $cquery->type = QuerySegment::Q_CLASS_HIERARCHY;
     $cquery->joinfield = array();
     foreach ($description->getCategories() as $category) {
         $categoryId = $this->querySegmentListBuilder->getStore()->getObjectIds()->getSMWPageID($category->getDBkey(), NS_CATEGORY, $category->getInterwiki(), '');
         if ($categoryId != 0) {
             $cquery->joinfield[] = $categoryId;
         }
     }
     if (count($cquery->joinfield) == 0) {
         // Empty result.
         $query->type = QuerySegment::Q_VALUE;
         $query->joinTable = '';
         $query->joinfield = '';
     } else {
         // Instance query with disjunction of classes (categories)
         $query->joinTable = $this->querySegmentListBuilder->getStore()->findPropertyTableID(new DIProperty('_INST'));
         $query->joinfield = "{$query->alias}.s_id";
         $query->components[$cqid] = "{$query->alias}.o_id";
         $this->querySegmentListBuilder->addQuerySegment($cquery);
     }
     return $query;
 }
 /**
  * TODO: One instance of the SMW IDs table on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE)
  *
  * @since 2.2
  *
  * @param Description $description
  *
  * @return QuerySegment
  */
 public function interpretDescription(Description $description)
 {
     $query = new QuerySegment();
     $query->joinTable = SMWSql3SmwIds::TABLE_NAME;
     $query->joinfield = "{$query->alias}.smw_id";
     $query->where = "{$query->alias}.smw_namespace=" . $this->querySegmentListBuilder->getStore()->getConnection('mw.db')->addQuotes($description->getNamespace());
     return $query;
 }
 /**
  * @since 2.2
  *
  * @param Description $description
  *
  * @return QuerySegment
  */
 public function interpretDescription(Description $description)
 {
     $query = new QuerySegment();
     $query->type = $description instanceof Conjunction ? QuerySegment::Q_CONJUNCTION : QuerySegment::Q_DISJUNCTION;
     foreach ($description->getDescriptions() as $subDescription) {
         $subQueryId = $this->querySegmentListBuilder->getQuerySegmentFrom($subDescription);
         if ($subQueryId >= 0) {
             $query->components[$subQueryId] = true;
         }
     }
     // All subconditions failed, drop this as well.
     if (count($query->components) == 0) {
         $query->type = QuerySegment::Q_NOQUERY;
     }
     return $query;
 }
 /**
  * Given an Description that is just a conjunction or disjunction of
  * ValueDescription objects, create and return a plain WHERE condition
  * string for it.
  *
  * @param $query
  * @param ValueDescription $description
  * @param DataItemHandler $diHandler for that table
  * @param string $operator SQL operator "AND" or "OR"
  */
 private function mapValueDescription($query, ValueDescription $description, DataItemHandler $diHandler, $operator)
 {
     $where = '';
     $dataItem = $description->getDataItem();
     $db = $this->querySegmentListBuilder->getStore()->getConnection('mw.db');
     // TODO Better get the handle from the property type
     // Some comparators (e.g. LIKE) could use DI values of
     // a different type; we care about the property table, not
     // about the value
     // Do not support smw_id joined data for now.
     $indexField = $diHandler->getIndexField();
     //Hack to get to the field used as index
     $keys = $diHandler->getWhereConds($dataItem);
     $value = $keys[$indexField];
     // See if the getSQLCondition method exists and call it if this is the case.
     // Invoked by SMAreaValueDescription, SMGeoCoordsValueDescription
     if (method_exists($description, 'getSQLCondition')) {
         $fields = $diHandler->getTableFields();
         $where = $description->getSQLCondition($query->alias, array_keys($fields), $this->querySegmentListBuilder->getStore()->getConnection(DB_SLAVE));
     }
     if ($where == '') {
         $comparator = $this->comparatorMapper->mapComparator($description, $value);
         $where = "{$query->alias}.{$indexField}{$comparator}" . $db->addQuotes($value);
     }
     if ($where !== '') {
         if ($query->where && substr($query->where, -1) != '(') {
             $query->where .= " {$operator} ";
         }
         $query->where .= "({$where})";
     }
 }
 /**
  * @since 2.2
  *
  * @param Description $description
  *
  * @return QuerySegment
  */
 public function interpretDescription(Description $description)
 {
     $query = new QuerySegment();
     $conceptId = $this->querySegmentListBuilder->getStore()->getObjectIds()->getSMWPageID($description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '', '');
     $hash = 'concept-' . $conceptId;
     $this->querySegmentListBuilder->getCircularReferenceGuard()->mark($hash);
     if ($this->querySegmentListBuilder->getCircularReferenceGuard()->isCircularByRecursionFor($hash)) {
         $this->querySegmentListBuilder->addError(wfMessage('smw-query-condition-circular', $description->getQueryString())->text());
         return $query;
     }
     $db = $this->querySegmentListBuilder->getStore()->getConnection('mw.db.queryengine');
     $row = $this->getConceptForId($db, $conceptId);
     // No description found, concept does not exist.
     if ($row === false) {
         $this->querySegmentListBuilder->getCircularReferenceGuard()->unmark('concept-' . $conceptId);
         // keep the above query object, it yields an empty result
         // TODO: announce an error here? (maybe not, since the query processor can check for
         // non-existing concept pages which is probably the main reason for finding nothing here)
         return $query;
     }
     global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime;
     $may_be_computed = $smwgQConceptCaching == CONCEPT_CACHE_NONE || $smwgQConceptCaching == CONCEPT_CACHE_HARD && ~(~($row->concept_features + 0) | $smwgQFeatures) == 0 && $smwgQMaxSize >= $row->concept_size && $smwgQMaxDepth >= $row->concept_depth;
     if ($row->cache_date && ($row->cache_date > strtotime("now") - $smwgQConceptCacheLifetime * 60 || !$may_be_computed)) {
         // Cached concept, use cache unless it is dead and can be revived.
         $query->joinTable = SMWSQLStore3::CONCEPT_CACHE_TABLE;
         $query->joinfield = "{$query->alias}.s_id";
         $query->where = "{$query->alias}.o_id=" . $db->addQuotes($conceptId);
     } elseif ($row->concept_txt) {
         // Parse description and process it recursively.
         if ($may_be_computed) {
             $qid = $this->querySegmentListBuilder->getQuerySegmentFrom($this->getConceptQueryDescriptionFrom($row->concept_txt));
             if ($qid != -1) {
                 $query = $this->querySegmentListBuilder->findQuerySegment($qid);
             } else {
                 // somehow the concept query is no longer valid; maybe some syntax changed (upgrade) or global settings were modified since storing it
                 $this->querySegmentListBuilder->addError(wfMessage('smw_emptysubquery')->text());
                 // not the right message, but this case is very rare; let us not make detailed messages for this
             }
         } else {
             $this->querySegmentListBuilder->addError(wfMessage('smw_concept_cache_miss', $description->getConcept()->getTitle()->getText())->text());
         }
     }
     // else: no cache, no description (this may happen); treat like empty concept
     $this->querySegmentListBuilder->getCircularReferenceGuard()->unmark($hash);
     return $query;
 }
 /**
  * Only type '_wpg' objects can appear on query level (essentially as nominal classes)
  *
  * @since 2.2
  *
  * @param Description $description
  *
  * @return QuerySegment
  */
 public function interpretDescription(Description $description)
 {
     $query = new QuerySegment();
     if (!$description->getDataItem() instanceof DIWikiPage) {
         return $query;
     }
     if ($description->getComparator() === SMW_CMP_EQ) {
         $query->type = QuerySegment::Q_VALUE;
         $oid = $this->querySegmentListBuilder->getStore()->getObjectIds()->getSMWPageID($description->getDataItem()->getDBkey(), $description->getDataItem()->getNamespace(), $description->getDataItem()->getInterwiki(), $description->getDataItem()->getSubobjectName());
         $query->joinfield = array($oid);
     } else {
         // Join with SMW IDs table needed for other comparators (apply to title string).
         $query->joinTable = SMWSql3SmwIds::TABLE_NAME;
         $query->joinfield = "{$query->alias}.smw_id";
         $value = $description->getDataItem()->getSortKey();
         $comparator = $this->comparatorMapper->mapComparator($description, $value);
         $query->where = "{$query->alias}.smw_sortkey{$comparator}" . $this->querySegmentListBuilder->getStore()->getConnection('mw.db')->addQuotes($value);
     }
     return $query;
 }
 private function addFulltextSearchCondition($query, $comparator, &$value)
 {
     // Remove remaining ~ from the search string
     $value = str_replace('~', '', $value);
     $valueMatchConditionBuilder = $this->fulltextSearchTableFactory->newValueMatchConditionBuilderByType($this->querySegmentListBuilder->getStore());
     if (!$valueMatchConditionBuilder->isEnabled() || !$valueMatchConditionBuilder->hasMinTokenLength($value)) {
         return false;
     }
     $query->joinTable = $valueMatchConditionBuilder->getTableName();
     $query->joinfield = "{$query->alias}.s_id";
     $query->components = array();
     $query->where = $valueMatchConditionBuilder->getWhereCondition(new ValueDescription(new DIBlob($value), null, $comparator), $query->alias);
     return $query;
 }
示例#8
0
 private function compileAccordingConditionsAndHackThemIntoQobj(array $extraProperties, $qobj, $qid)
 {
     $this->querySegmentListBuilder->setSortKeys($this->sortKeys);
     $this->querySegmentListBuilder->buildQuerySegmentFor(new Conjunction($extraProperties));
     $newQuerySegmentId = $this->querySegmentListBuilder->getLastQuerySegmentId();
     $this->querySegmentList = $this->querySegmentListBuilder->getQuerySegmentList();
     $this->errors = $this->querySegmentListBuilder->getErrors();
     $newQuerySegment = $this->querySegmentList[$newQuerySegmentId];
     // This is always an QuerySegment::Q_CONJUNCTION ...
     foreach ($newQuerySegment->components as $cid => $field) {
         // ... so just re-wire its dependencies
         $qobj->components[$cid] = $qobj->joinfield;
         $qobj->sortfields = array_merge($qobj->sortfields, $this->querySegmentList[$cid]->sortfields);
     }
     $this->querySegmentList[$qid] = $qobj;
 }
 /**
  * @dataProvider descriptionProvider
  */
 public function testinterpretDescription($description, $isFixedPropertyTable, $indexField, $sortKeys, $expected)
 {
     $dataItemHandler = $this->getMockBuilder('\\SMWDataItemHandler')->disableOriginalConstructor()->getMockForAbstractClass();
     $dataItemHandler->expects($this->any())->method('getIndexField')->will($this->returnValue($indexField));
     $dataItemHandler->expects($this->any())->method('getTableFields')->will($this->returnValue(array('one', 'two')));
     $dataItemHandler->expects($this->any())->method('getWhereConds')->will($this->returnValue(array($indexField => 'fixedFooWhereCond')));
     $objectIds = $this->getMockBuilder('\\stdClass')->setMethods(array('getSMWPropertyID', 'getSMWPageID'))->getMock();
     $objectIds->expects($this->any())->method('getSMWPropertyID')->will($this->returnValue(42));
     $objectIds->expects($this->any())->method('getSMWPageID')->will($this->returnValue(91));
     $connection = $this->getMockBuilder('\\SMW\\MediaWiki\\Database')->disableOriginalConstructor()->getMock();
     $connection->expects($this->any())->method('addQuotes')->will($this->returnArgument(0));
     $store = $this->getMockBuilder('\\SMW\\SQLStore\\SQLStore')->disableOriginalConstructor()->getMock();
     $proptable = $this->getMockBuilder('\\SMWSQLStore3Table')->disableOriginalConstructor()->getMock();
     $proptable->expects($this->any())->method('usesIdSubject')->will($this->returnValue(true));
     $proptable->expects($this->any())->method('getName')->will($this->returnValue('FooPropTable'));
     $proptable->expects($this->any())->method('isFixedPropertyTable')->will($this->returnValue($isFixedPropertyTable));
     $store = $this->getMockBuilder('\\SMW\\SQLStore\\SQLStore')->disableOriginalConstructor()->getMock();
     $store->expects($this->once())->method('findPropertyTableID')->will($this->returnValue('Foo'));
     $store->expects($this->once())->method('getPropertyTables')->will($this->returnValue(array('Foo' => $proptable)));
     $store->expects($this->any())->method('getConnection')->will($this->returnValue($connection));
     $store->expects($this->any())->method('getObjectIds')->will($this->returnValue($objectIds));
     $store->expects($this->any())->method('getDataItemHandlerForDIType')->will($this->returnValue($dataItemHandler));
     $querySegmentListBuilder = new QuerySegmentListBuilder($store);
     $querySegmentListBuilder->setSortKeys($sortKeys);
     $instance = new SomePropertyInterpreter($querySegmentListBuilder);
     $this->assertTrue($instance->canInterpretDescription($description));
     $this->querySegmentValidator->assertThatContainerHasProperties($expected, $instance->interpretDescription($description));
 }
 public function testWhenSomeQuerySegments_getQuerySegmentListReturnsThemAll()
 {
     $instance = new QuerySegmentListBuilder($this->store);
     $firstQuerySegment = new QuerySegment();
     $firstQuerySegment->segmentNumber = 42;
     $instance->addQuerySegment($firstQuerySegment);
     $secondQuerySegment = new QuerySegment();
     $secondQuerySegment->segmentNumber = 23;
     $instance->addQuerySegment($secondQuerySegment);
     $expected = array(42 => $firstQuerySegment, 23 => $secondQuerySegment);
     $this->assertSame($expected, $instance->getQuerySegmentList());
 }
 public function testWhenSomeQuerySegments_getQuerySegmentListReturnsThemAll()
 {
     $instance = new QuerySegmentListBuilder($this->store, $this->descriptionInterpreterFactory);
     $firstQuerySegment = new QuerySegment();
     $instance->addQuerySegment($firstQuerySegment);
     $secondQuerySegment = new QuerySegment();
     $instance->addQuerySegment($secondQuerySegment);
     $expected = array(0 => $firstQuerySegment, 1 => $secondQuerySegment);
     $this->assertSame($expected, $instance->getQuerySegmentList());
 }
 /**
  * We bypass the storage interface here (which is legal as we control it,
  * and safe if we are careful with changes ...)
  *
  * This should be faster, but we must implement the unescaping that concepts
  * do on getWikiValue
  */
 private function getConceptForId($id)
 {
     return $this->querySegmentListBuilder->getStore()->getConnection('mw.db')->selectRow('smw_fpt_conc', array('concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date'), array('s_id' => $id), __METHOD__);
 }