/** * @since 2.2 * * @return QueryEngine */ public function newMasterQueryEngine() { $hierarchyTempTableBuilder = new HierarchyTempTableBuilder($this->store->getConnection('mw.db'), $this->newTemporaryIdTableCreator()); $hierarchyTempTableBuilder->setPropertyHierarchyTableDefinition($this->store->findPropertyTableID(new DIProperty('_SUBP')), $GLOBALS['smwgQSubpropertyDepth']); $hierarchyTempTableBuilder->setClassHierarchyTableDefinition($this->store->findPropertyTableID(new DIProperty('_SUBC')), $GLOBALS['smwgQSubcategoryDepth']); $querySegmentListProcessor = new QuerySegmentListProcessor($this->store->getConnection('mw.db'), $this->newTemporaryIdTableCreator(), $hierarchyTempTableBuilder); return new QueryEngine($this->store, new QuerySegmentListBuilder($this->store), $querySegmentListProcessor, new EngineOptions()); }
/** * @since 2.4 * * @return QuerySegmentListProcessor */ public function newQuerySegmentListProcessor() { $connection = $this->store->getConnection('mw.db.queryengine'); $temporaryTableBuilder = $this->newTemporaryTableBuilder(); $hierarchyTempTableBuilder = new HierarchyTempTableBuilder($connection, $temporaryTableBuilder); $hierarchyTempTableBuilder->setPropertyHierarchyTableDefinition($this->store->findPropertyTableID(new DIProperty('_SUBP')), $this->applicationFactory->getSettings()->get('smwgQSubpropertyDepth')); $hierarchyTempTableBuilder->setClassHierarchyTableDefinition($this->store->findPropertyTableID(new DIProperty('_SUBC')), $this->applicationFactory->getSettings()->get('smwgQSubcategoryDepth')); $querySegmentListProcessor = new QuerySegmentListProcessor($connection, $temporaryTableBuilder, $hierarchyTempTableBuilder); return $querySegmentListProcessor; }
public function testCreateHierarchyTempTable() { $this->connection->expects($this->once())->method('tableName')->with($this->stringContains('bar'))->will($this->returnValue('_bar')); $this->connection->expects($this->atLeastOnce())->method('query'); $instance = new HierarchyTempTableBuilder($this->connection, $this->temporaryIdTableCreator); $instance->setClassHierarchyTableDefinition('bar', 3); $instance->createHierarchyTempTableFor('class', 'foobar', '(42)'); $expected = array('(42)' => 'foobar'); $this->assertEquals($expected, $instance->getHierarchyCache()); $instance->emptyHierarchyCache(); $this->assertEmpty($instance->getHierarchyCache()); }
/** * Find subproperties or subcategories. This may require iterative computation, * and temporary tables are used in many cases. * * @param QuerySegment $query */ private function resolveHierarchyForSegment(QuerySegment &$query) { switch ($query->type) { case QuerySegment::Q_PROP_HIERARCHY: $type = 'property'; break; case QuerySegment::Q_CLASS_HIERARCHY: $type = 'class'; break; } list($smwtable, $depth) = $this->hierarchyTempTableBuilder->getHierarchyTableDefinitionForType($type); if ($depth <= 0) { // treat as value, no recursion $query->type = QuerySegment::Q_VALUE; return; } $values = ''; $valuecond = ''; $db = $this->connection; foreach ($query->joinfield as $value) { $values .= ($values ? ',' : '') . '(' . $db->addQuotes($value) . ')'; $valuecond .= ($valuecond ? ' OR ' : '') . 'o_id=' . $db->addQuotes($value); } // Try to safe time (SELECT is cheaper than creating/dropping 3 temp tables): $res = $db->select($smwtable, 's_id', $valuecond, __METHOD__, array('LIMIT' => 1)); if (!$db->fetchObject($res)) { // no subobjects, we are done! $db->freeResult($res); $query->type = QuerySegment::Q_VALUE; return; } $db->freeResult($res); $tablename = $db->tableName($query->alias); $this->executedQueries[$query->alias] = array("Recursively computed hierarchy for element(s) {$values}."); $query->joinTable = $query->alias; $query->joinfield = "{$query->alias}.id"; $db->query($this->getCreateTempIDTableSQL($tablename), __METHOD__); $this->hierarchyTempTableBuilder->createHierarchyTempTableFor($type, $tablename, $values); }