/**
  * Generate textual debug output that shows an arbitrary list of informative
  * fields. Used for formatting query debug output.
  *
  * @note All strings given must be usable and safe in wiki and HTML
  * contexts.
  *
  * @param $storeName string name of the storage backend for which this is generated
  * @param $entries array of name => value of informative entries to display
  * @param $query SMWQuery or null, if given add basic data about this query as well
  *
  * @return string
  */
 public static function formatOutputFor($storeName, array $entries, Query $query = null)
 {
     if ($query instanceof Query) {
         $preEntries = array();
         $preEntries['Ask query'] = '<div class="smwpre">' . str_replace('[', '&#x005B;', $query->getDescription()->getQueryString()) . '</div>';
         $entries = array_merge($preEntries, $entries);
         $entries['Query Metrics'] = 'Query-Size:' . $query->getDescription()->getSize() . '<br />' . 'Query-Depth:' . $query->getDescription()->getDepth();
         $errors = '';
         foreach ($query->getErrors() as $error) {
             $errors .= $error . '<br />';
         }
         if ($errors === '') {
             $errors = 'None';
         }
         $entries['Errors and Warnings'] = $errors;
     }
     $result = '<div style="border: 5px dotted #A1FB00; background: #FFF0BD; padding: 20px; ">' . "<h3>Debug Output by {$storeName}</h3>";
     foreach ($entries as $header => $information) {
         $result .= "<h4>{$header}</h4>";
         if ($information !== '') {
             $result .= "{$information}";
         }
     }
     $result .= '</div>';
     return $result;
 }
 /**
  * Generate textual debug output that shows an arbitrary list of informative
  * fields. Used for formatting query debug output.
  *
  * @note All strings given must be usable and safe in wiki and HTML
  * contexts.
  *
  * @param $storeName string name of the storage backend for which this is generated
  * @param $entries array of name => value of informative entries to display
  * @param $query SMWQuery or null, if given add basic data about this query as well
  *
  * @return string
  */
 public static function getStringFrom($storeName, array $entries, Query $query = null)
 {
     if ($query instanceof Query) {
         $preEntries = array();
         $preEntries['ASK Query'] = '<div class="smwpre">' . str_replace('[', '&#x005B;', $query->getDescription()->getQueryString()) . '</div>';
         $entries = array_merge($preEntries, $entries);
         $entries['Query Metrics'] = 'Query-Size:' . $query->getDescription()->getSize() . '<br />' . 'Query-Depth:' . $query->getDescription()->getDepth();
         $errors = '';
         $queryErrors = ProcessingErrorMsgHandler::normalizeMessages($query->getErrors());
         foreach ($queryErrors as $error) {
             $errors .= $error . '<br />';
         }
         if ($errors === '') {
             $errors = 'None';
         }
         $entries['Errors and Warnings'] = $errors;
     }
     $result = '<div style="border: 5px dotted #ffcc00; background: #FFF0BD; padding: 20px; ">' . "<div class='smw-column-header'><big>{$storeName} debug output</big></div>";
     foreach ($entries as $header => $information) {
         $result .= "<div class='smw-column-header'>{$header}</div>";
         if ($information !== '') {
             $result .= "{$information}";
         }
     }
     $result .= '</div>';
     return $result;
 }
Example #3
0
 /**
  * Add data about the query and its parameters to the semantic data of
  * the given parser. The $queryKey is a string key that uniquely
  * identifies the query; this is difficult to create in a stable way
  * from the processed query object and parameters, but easy to get from
  * the raw user input.
  *
  * @param string $queryKey
  * @param SMWQuery $query
  * @param array $params
  * @param Parser $parser
  *
  * @since 1.8
  */
 public static function addQueryData($queryKey, SMWQuery $query, array $params, Parser $parser)
 {
     $mainSemanticData = SMWParseData::getSMWData($parser);
     $subject = $mainSemanticData->getSubject();
     $diSubWikiPage = new SMWDIWikiPage($subject->getDBkey(), $subject->getNamespace(), $subject->getInterwiki(), "_QUERY" . $queryKey);
     $semanticData = new SMWContainerSemanticData($diSubWikiPage);
     $description = $query->getDescription();
     // Add query string
     $propertyDi = new SMWDIProperty('_ASKST');
     $valueDi = new SMWDIBlob($description->getQueryString());
     $semanticData->addPropertyObjectValue($propertyDi, $valueDi);
     // Add query size
     $propertyDi = new SMWDIProperty('_ASKSI');
     $valueDi = new SMWDINumber($description->getSize());
     $semanticData->addPropertyObjectValue($propertyDi, $valueDi);
     // Add query depth
     $propertyDi = new SMWDIProperty('_ASKDE');
     $valueDi = new SMWDINumber($description->getDepth());
     $semanticData->addPropertyObjectValue($propertyDi, $valueDi);
     // Add query format
     $propertyDi = new SMWDIProperty('_ASKFO');
     $valueDi = new SMWDIString($params['format']->getValue());
     $semanticData->addPropertyObjectValue($propertyDi, $valueDi);
     $propertyDi = new SMWDIProperty('_ASK');
     $subObjectDi = new SMWDIContainer($semanticData);
     SMWParseData::getSMWData($parser)->addPropertyObjectValue($propertyDi, $subObjectDi);
 }
 /**
  * @since 2.1
  *
  * @param Title $title
  * @param Query $query
  * @param string $format
  * @param integer|null $duration
  *
  * @return ProfileAnnotator
  */
 public function newJointProfileAnnotator(Title $title, Query $query, $format, $duration = null)
 {
     $profiler = new NullProfile(new Subobject($title), $query->getHash());
     $profiler = new DescriptionProfile($profiler, $query->getDescription());
     $profiler = new FormatProfile($profiler, $format);
     $profiler = new DurationProfile($profiler, $duration);
     return $profiler;
 }
 /**
  * @since 2.1
  *
  * @param Query $query
  * @param string $format
  * @param integer|null $duration
  *
  * @return ProfileAnnotator
  */
 public function newJointProfileAnnotator(Query $query, $format, $duration = null)
 {
     $nullProfileAnnotator = new NullProfileAnnotator(new Subobject($query->getSubject()->getTitle()), $query->getQueryId());
     $descriptionProfileAnnotator = new DescriptionProfileAnnotator($nullProfileAnnotator, $query->getDescription());
     $formatProfileAnnotator = new FormatProfileAnnotator($descriptionProfileAnnotator, $format);
     $durationProfileAnnotator = new DurationProfileAnnotator($formatProfileAnnotator, $duration);
     return $durationProfileAnnotator;
 }
 public function testNullQueryResult()
 {
     $term = '[[Some_string_to_query]]';
     $description = new ValueDescription(new DIWikiPage($term, NS_MAIN), null);
     $query = new Query($description, false, false);
     $query->querymode = Query::MODE_INSTANCES;
     $description = $query->getDescription();
     $namespacesDisjunction = new Disjunction(array_map(function ($ns) {
         return new NamespaceDescription($ns);
     }, array(NS_MAIN)));
     $description = new Conjunction(array($description, $namespacesDisjunction));
     $query->setDescription($description);
     $this->assertInstanceOf('\\SMWQueryResult', ApplicationFactory::getInstance()->getStore()->getQueryResult($query));
 }
 /**
  * @since  2.0
  * @param  Query $query
  *
  * @return QueryResult|string
  */
 public function getQueryResult(Query $query)
 {
     if ((!$this->engineOptions->get('smwgIgnoreQueryErrors') || $query->getDescription() instanceof ThingDescription) && $query->querymode != Query::MODE_DEBUG && count($query->getErrors()) > 0) {
         return $this->queryResultFactory->newEmptyQueryResult($query, false);
     }
     // don't query, but return something to the printer
     if ($query->querymode == Query::MODE_NONE || $query->getLimit() < 1) {
         return $this->queryResultFactory->newEmptyQueryResult($query, true);
     }
     $this->compoundConditionBuilder->setSortKeys($query->sortkeys);
     $compoundCondition = $this->compoundConditionBuilder->buildCondition($query->getDescription());
     $query->addErrors($this->compoundConditionBuilder->getErrors());
     if ($query->querymode == Query::MODE_DEBUG) {
         return $this->getDebugQueryResult($query, $compoundCondition);
     } elseif ($query->querymode == Query::MODE_COUNT) {
         return $this->getCountQueryResult($query, $compoundCondition);
     }
     return $this->getInstanceQueryResult($query, $compoundCondition);
 }
Example #8
0
 /**
  * Using a preprocessed internal query description referenced by $rootid,
  * compute the proper result instance output for the given query.
  * @todo The SQL standard requires us to select all fields by which we sort, leading
  * to wrong results regarding the given limit: the user expects limit to be applied to
  * the number of distinct pages, but we can use DISTINCT only to whole rows. Thus, if
  * rows contain sortfields, then pages with multiple values for that field are distinct
  * and appear multiple times in the result. Filtering duplicates in post processing
  * would still allow such duplicates to push aside wanted values, leading to less than
  * "limit" results although there would have been "limit" really distinct results. For
  * this reason, we select sortfields only for POSTGRES. MySQL is able to perform what
  * we want here. It would be nice if we could eliminate the bug in POSTGRES as well.
  *
  * @param Query $query
  * @param integer $rootid
  *
  * @return QueryResult
  */
 private function getInstanceQueryResult(Query $query, $rootid)
 {
     global $wgDBtype;
     $db = $this->store->getConnection();
     $qobj = $this->querySegments[$rootid];
     if ($qobj->joinfield === '') {
         // empty result, no query needed
         $result = new QueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this->store, false);
         return $result;
     }
     $sql_options = $this->getSQLOptions($query, $rootid);
     // Selecting those is required in standard SQL (but MySQL does not require it).
     $sortfields = implode($qobj->sortfields, ',');
     $res = $db->select($db->tableName($qobj->joinTable) . " AS {$qobj->alias}" . $qobj->from, "DISTINCT {$qobj->alias}.smw_id AS id,{$qobj->alias}.smw_title AS t,{$qobj->alias}.smw_namespace AS ns,{$qobj->alias}.smw_iw AS iw,{$qobj->alias}.smw_subobject AS so,{$qobj->alias}.smw_sortkey AS sortkey" . ($wgDBtype == 'postgres' ? ($sortfields ? ',' : '') . $sortfields : ''), $qobj->where, __METHOD__, $sql_options);
     $qr = array();
     $count = 0;
     // the number of fetched results ( != number of valid results in array $qr)
     $missedCount = 0;
     $dataItemCache = array();
     $logToTable = array();
     $hasFurtherResults = false;
     $prs = $query->getDescription()->getPrintrequests();
     $diHandler = $this->store->getDataItemHandlerForDIType(DataItem::TYPE_WIKIPAGE);
     while ($count < $query->getLimit() && ($row = $db->fetchObject($res))) {
         if ($row->iw === '' || $row->iw[0] != ':') {
             // Catch exception for non-existing predefined properties that
             // still registered within non-updated pages (@see bug 48711)
             try {
                 $dataItem = $diHandler->dataItemFromDBKeys(array($row->t, intval($row->ns), $row->iw, '', $row->so));
             } catch (InvalidPredefinedPropertyException $e) {
                 $logToTable[$row->t] = "issue creating a {$row->t} dataitem from a database row";
                 wfDebugLog('smw', __METHOD__ . ' ' . $e->getMessage() . "\n");
                 $dataItem = '';
             }
             if ($dataItem instanceof DIWikiPage && !isset($dataItemCache[$dataItem->getHash()])) {
                 $count++;
                 $dataItemCache[$dataItem->getHash()] = true;
                 $qr[] = $dataItem;
                 // These IDs are usually needed for displaying the page (esp. if more property values are displayed):
                 $this->store->smwIds->setCache($row->t, $row->ns, $row->iw, $row->so, $row->id, $row->sortkey);
             } else {
                 $missedCount++;
                 $logToTable[$row->t] = "skip result for {$row->t} existing cache entry / query " . $query->getHash();
             }
         } else {
             $missedCount++;
             $logToTable[$row->t] = "skip result for {$row->t} due to an internal `{$row->iw}` pointer / query " . $query->getHash();
         }
     }
     if ($db->fetchObject($res)) {
         $count++;
     }
     if ($logToTable !== array()) {
         wfDebugLog('smw', __METHOD__ . ' ' . implode(',', $logToTable) . "\n");
     }
     if ($count > $query->getLimit() || $count + $missedCount > $query->getLimit()) {
         $hasFurtherResults = true;
     }
     $db->freeResult($res);
     $result = new QueryResult($prs, $query, $qr, $this->store, $hasFurtherResults);
     return $result;
 }
Example #9
0
 /**
  * @see SMWStore::getQueryResult()
  * @since 1.6
  */
 public function getQueryResult(SMWQuery $query)
 {
     global $smwgIgnoreQueryErrors;
     if ((!$smwgIgnoreQueryErrors || $query->getDescription() instanceof SMWThingDescription) && $query->querymode != SMWQuery::MODE_DEBUG && count($query->getErrors()) > 0) {
         return new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this, false);
     }
     if ($query->querymode == SMWQuery::MODE_NONE) {
         // don't query, but return something to printer
         return new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this, true);
     } elseif ($query->querymode == SMWQuery::MODE_DEBUG) {
         $queryEngine = new SMWSparqlStoreQueryEngine($this);
         return $queryEngine->getDebugQueryResult($query);
     } elseif ($query->querymode == SMWQuery::MODE_COUNT) {
         $queryEngine = new SMWSparqlStoreQueryEngine($this);
         return $queryEngine->getCountQueryResult($query);
     } else {
         $queryEngine = new SMWSparqlStoreQueryEngine($this);
         return $queryEngine->getInstanceQueryResult($query);
     }
 }
Example #10
0
 private function makeQueryResultForInstance(FederateResultSet $federateResultSet, Query $query)
 {
     $resultDataItems = array();
     foreach ($federateResultSet as $resultRow) {
         if (count($resultRow) > 0) {
             $dataItem = Exporter::findDataItemForExpElement($resultRow[0]);
             if (!is_null($dataItem)) {
                 $resultDataItems[] = $dataItem;
             }
         }
     }
     if ($federateResultSet->numRows() > $query->getLimit()) {
         array_pop($resultDataItems);
         $hasFurtherResults = true;
     } else {
         $hasFurtherResults = false;
     }
     $result = new QueryResult($query->getDescription()->getPrintrequests(), $query, $resultDataItems, $this->store, $hasFurtherResults);
     switch ($federateResultSet->getErrorCode()) {
         case FederateResultSet::ERROR_NOERROR:
             break;
         case FederateResultSet::ERROR_INCOMPLETE:
             $result->addErrors(array(wfMessage('smw_db_sparqlqueryincomplete')->inContentLanguage()->text()));
             break;
         default:
             $result->addErrors(array(wfMessage('smw_db_sparqlqueryproblem')->inContentLanguage()->text()));
             break;
     }
     return $result;
 }
	public function getQueryResult( SMWQuery $query ) {
		global $smwgIgnoreQueryErrors;

		if ( !$smwgIgnoreQueryErrors &&
		     ( $query->querymode != SMWQuery::MODE_DEBUG ) &&
		     ( count( $query->getErrors() ) > 0 ) ) {
			return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this, false );
			// NOTE: we check this here to prevent unnecessary work, but we may need to check it after query processing below again in case more errors occurred
		}

		if ( $query->querymode == SMWQuery::MODE_NONE ) { // don't query, but return something to printer
			return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this, true );
		} elseif ( $query->querymode == SMWQuery::MODE_DEBUG ) {
			$queryEngine = new SMWSparqlStoreQueryEngine( $this );
			return $queryEngine->getDebugQueryResult( $query ); 
		} elseif ( $query->querymode == SMWQuery::MODE_COUNT ) {
			$queryEngine = new SMWSparqlStoreQueryEngine( $this );
			return $queryEngine->getCountQueryResult( $query ); 
		} else {
			$queryEngine = new SMWSparqlStoreQueryEngine( $this );
			return $queryEngine->getInstanceQueryResult( $query ); 
		}
	}
 /**
  * The new SQL store's implementation of query answering.
  */
 public function getQueryResult(SMWQuery $query)
 {
     if ($query->querymode == SMWQuery::MODE_NONE) {
         // don't query, but return something to printer
         $result = new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, true);
         return $result;
     }
     $this->m_qmode = $query->querymode;
     $this->m_queries = array();
     $this->m_hierarchies = array();
     $this->m_querylog = array();
     $this->m_errors = array();
     SMWSQLStore2Query::$qnum = 0;
     $this->m_sortkeys = $query->sortkeys;
     // manually make final root query (to retrieve namespace,title):
     $rootid = SMWSQLStore2Query::$qnum;
     $qobj = new SMWSQLStore2Query();
     $qobj->jointable = 'smw_ids';
     $qobj->joinfield = "{$qobj->alias}.smw_id";
     // build query dependency tree:
     wfProfileIn('SMWSQLStore2Queries::compileMainQuery (SMW)');
     $qid = $this->compileQueries($query->getDescription());
     // compile query, build query "plan"
     wfProfileOut('SMWSQLStore2Queries::compileMainQuery (SMW)');
     if ($qid < 0) {
         // no valid/supported condition; ensure that at least only proper pages are delivered
         $qid = SMWSQLStore2Query::$qnum;
         $q = new SMWSQLStore2Query();
         $q->jointable = 'smw_ids';
         $q->joinfield = "{$q->alias}.smw_id";
         $q->where = "{$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWIW) . " AND {$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWREDIIW) . " AND {$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWBORDERIW) . " AND {$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWINTDEFIW);
         $this->m_queries[$qid] = $q;
     }
     // append query to root:
     $qobj->components = array($qid => "{$qobj->alias}.smw_id");
     $qobj->sortfields = $this->m_queries[$qid]->sortfields;
     $this->m_queries[$rootid] = $qobj;
     $this->applyOrderConditions($query, $rootid);
     // may extend query if needed for sorting
     wfProfileIn('SMWSQLStore2Queries::executeMainQuery (SMW)');
     $this->executeQueries($this->m_queries[$rootid]);
     // execute query tree, resolve all dependencies
     wfProfileOut('SMWSQLStore2Queries::executeMainQuery (SMW)');
     $result = $this->getNMQueryResult($query, $rootid);
     $this->cleanUp();
     $query->addErrors($this->m_errors);
     return $result;
 }
 private function createConceptFor(DIWikiPage $concept, Description $description, $documentation = '')
 {
     $semanticData = $this->semanticDataFactory->setSubject($concept)->newEmptySemanticData();
     $query = new Query($description, false, true);
     $semanticData->addPropertyObjectValue(new DIProperty('_CONC'), new DIConcept($query->getDescription()->getQueryString(), $documentation, $query->getDescription()->getQueryFeatures(), $query->getDescription()->getSize(), $query->getDescription()->getDepth()));
     $this->getStore()->updateData($semanticData);
 }
Example #14
0
 /**
  * Get the output string for a query in debugging mode.
  *
  * @param Query $query
  *
  * @return string
  */
 public function getDebugQueryResult(Query $query)
 {
     $this->sortkeys = $query->sortkeys;
     $this->compoundConditionBuilder->setSortKeys($this->sortkeys);
     $sparqlCondition = $this->compoundConditionBuilder->buildCondition($query->getDescription());
     $query->addErrors($this->compoundConditionBuilder->getErrors());
     $entries = array();
     if ($sparqlCondition instanceof SingletonCondition) {
         if ($sparqlCondition->condition === '') {
             // all URIs exist, no querying
             $sparql = 'None (no conditions).';
         } else {
             $condition = $this->compoundConditionBuilder->convertConditionToString($sparqlCondition);
             $namespaces = $sparqlCondition->namespaces;
             $sparql = $this->connection->getSparqlForAsk($condition, $namespaces);
         }
     } elseif ($sparqlCondition instanceof FalseCondition) {
         $sparql = 'None (conditions can not be satisfied by anything).';
     } else {
         $condition = $this->compoundConditionBuilder->convertConditionToString($sparqlCondition);
         $namespaces = $sparqlCondition->namespaces;
         $options = $this->getOptions($query, $sparqlCondition);
         $options['DISTINCT'] = true;
         $sparql = $this->connection->getSparqlForSelect('?' . self::RESULT_VARIABLE, $condition, $options, $namespaces);
     }
     $sparql = str_replace(array('[', ':', ' '), array('&#x005B;', '&#x003A;', '&#x0020;'), $sparql);
     $entries['SPARQL Query'] = '<div class="smwpre">' . $sparql . '</div>';
     return DebugOutputFormatter::formatOutputFor('SPARQLStore', $entries, $query);
 }
Example #15
0
 /**
  * Parses a SPARQL XML-Result and returns an SMWHaloQueryResult.
  *
  * @param SMWQuery $query
  * @param xml string $sparqlXMLResult
  * @return SMWHaloQueryResult
  */
 protected function parseSPARQLXMLResult(&$query, &$sparqlXMLResult)
 {
     // parse xml results
     $dom = simplexml_load_string($sparqlXMLResult);
     if ($dom === FALSE) {
         return new SMWHaloQueryResult(array(), $query, array(), $this);
     }
     $variables = $dom->xpath('//variable');
     $results = $dom->xpath('//result');
     // if no results return empty result object
     if (count($results) == 0) {
         return new SMWHaloQueryResult(array(), $query, array(), $this);
     }
     $variableSet = array();
     foreach ($variables as $var) {
         $variableSet[] = (string) $var->attributes()->name;
     }
     // PrinterRequests to use
     $prs = array();
     // Use PrintRequests to determine which variable denotes what type of entity. If no PrintRequest is given use first result row
     // (which exist!) to determine which variable denotes what type of entity.
     // maps print requests (variable name) to result columns ( var_name => index )
     $mapPRTOColumns = array();
     // use user-given PrintRequests if possible
     $print_requests = $query->getDescription()->getPrintRequests();
     // _X_ is used for the main variable.
     $hasMainColumn = false;
     $index = 0;
     if ($query->fromASK) {
         // SPARQL query which was transformed from ASK
         // x variable is handeled specially as main variable
         foreach ($print_requests as $pr) {
             $data = $pr->getData();
             if ($data == NULL) {
                 // main column
                 $hasMainColumn = true;
                 if (in_array('_X_', $variableSet)) {
                     // x is missing for INSTANCE queries
                     $mapPRTOColumns['_X_'] = $index;
                     $prs[] = $pr;
                     $index++;
                 }
             } else {
                 $label = $data instanceof Title ? $data->getDBkey() : array_shift($data->getDBkeys());
                 $mapPRTOColumns[$label] = $index;
                 $rewritten_pr = $this->rewritePrintrequest($pr);
                 $prs[] = $rewritten_pr;
                 $index++;
             }
         }
     } else {
         // native SPARQL query, no main variable
         foreach ($print_requests as $pr) {
             $data = $pr->getData();
             if ($data != NULL) {
                 $label = $data instanceof Title ? $data->getDBkey() : array_shift($data->getDBkeys());
                 $mapPRTOColumns[$label] = $index;
                 $rewritten_pr = $this->rewritePrintrequest($pr);
                 $prs[] = $rewritten_pr;
                 $index++;
             }
         }
     }
     // generate PrintRequests for all bindings (if they do not exist already)
     $var_index = 0;
     $bindings = $results[0]->children()->binding;
     foreach ($bindings as $b) {
         $var_name = ucfirst((string) $variables[$var_index]->attributes()->name);
         $var_index++;
         // if no mainlabel, do not create a printrequest for _X_ (instance variable for ASK-converted queries)
         if ($query->mainLabelMissing && $var_name == "_X_") {
             continue;
         }
         // do not generate new printRequest if already given
         if ($this->containsPrintRequest($var_name, $print_requests, $query)) {
             continue;
         }
         // otherwise create one
         $var_path = explode(".", $var_name);
         $sel_var = ucfirst($var_path[count($var_path) - 1]);
         $data = SMWPropertyValue::makeUserProperty($sel_var);
         $prs[] = new SMWPrintRequest(SMWPrintRequest::PRINT_THIS, str_replace("_", " ", $sel_var), $data);
         $mapPRTOColumns[$var_name] = $index;
         $index++;
     }
     // get resultpage, ie. the pages which "define" a result row.
     if ($query->fromASK) {
         // ASK queries usually always have a result column,
         // except if a single instance is requested
         // result column is available if first variable is "_X_"
         $var_name = ucfirst((string) $variables[0]->attributes()->name);
         // not available, so set dummys
         foreach ($results as $r) {
             // SPARQL queries do not, so just set a dummy
             $resultPages[] = SMWDataValueFactory::newTypeIDValue('_wpg');
         }
     } else {
         foreach ($results as $r) {
             // SPARQL queries do not, so just set a dummy
             $resultPages[] = SMWDataValueFactory::newTypeIDValue('_wpg');
         }
     }
     // create and add result rows
     // iterate result rows and add an SMWResultArray object for each field
     $qresults = array();
     $rowIndex = 0;
     foreach ($results as $r) {
         $row = array();
         $columnIndex = 0;
         // column = n-th XML binding node
         $children = $r->children();
         // $chilren->binding denote all binding nodes
         foreach ($children->binding as $b) {
             $var_name = ucfirst((string) $children[$columnIndex]->attributes()->name);
             // ignore main variable if not displayed
             if (!$hasMainColumn && $var_name == '_X_') {
                 $columnIndex++;
                 continue;
             }
             $resultColumn = $mapPRTOColumns[$var_name];
             $allValues = array();
             $this->parseBindungs($b, $var_name, $prs[$resultColumn], $allValues);
             // note: ignore bnodes
             $columnIndex++;
             $row[$resultColumn] = new SMWHaloResultArray($resultPages[$rowIndex], $prs[$resultColumn], $this, $allValues);
         }
         $rowIndex++;
         ksort($row);
         $qresults[] = $row;
     }
     // Query result object
     $queryResult = new SMWHaloQueryResult($prs, $query, $qresults, $this, count($results) > $query->getLimit());
     return $queryResult;
 }
 /**
  * Using a preprocessed internal query description referenced by $rootid,
  * compute the proper result instance output for the given query.
  * @todo The SQL standard requires us to select all fields by which we sort, leading
  * to wrong results regarding the given limit: the user expects limit to be applied to
  * the number of distinct pages, but we can use DISTINCT only to whole rows. Thus, if
  * rows contain sortfields, then pages with multiple values for that field are distinct
  * and appear multiple times in the result. Filtering duplicates in post processing
  * would still allow such duplicates to push aside wanted values, leading to less than
  * "limit" results although there would have been "limit" really distinct results. For
  * this reason, we select sortfields only for POSTGRES. MySQL is able to perform what
  * we want here. It would be nice if we could eliminate the bug in POSTGRES as well.
  *
  * @param SMWQuery $query
  * @param integer $rootid
  *
  * @return SMWQueryResult
  */
 protected function getInstanceQueryResult(SMWQuery $query, $rootid)
 {
     global $wgDBtype;
     wfProfileIn('SMWSQLStore3Queries::getInstanceQueryResult (SMW)');
     $qobj = $this->m_queries[$rootid];
     if ($qobj->joinfield === '') {
         // empty result, no query needed
         $result = new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false);
         wfProfileOut('SMWSQLStore3Queries::getInstanceQueryResult (SMW)');
         return $result;
     }
     $sql_options = $this->getSQLOptions($query, $rootid);
     // Selecting those is required in standard SQL (but MySQL does not require it).
     $sortfields = implode($qobj->sortfields, ',');
     $res = $this->m_dbs->select($this->m_dbs->tableName($qobj->jointable) . " AS {$qobj->alias}" . $qobj->from, "DISTINCT {$qobj->alias}.smw_id AS id,{$qobj->alias}.smw_title AS t,{$qobj->alias}.smw_namespace AS ns,{$qobj->alias}.smw_iw AS iw,{$qobj->alias}.smw_subobject AS so,{$qobj->alias}.smw_sortkey AS sortkey" . ($wgDBtype == 'postgres' ? ($sortfields ? ',' : '') . $sortfields : ''), $qobj->where, 'SMW::getQueryResult', $sql_options);
     $qr = array();
     $count = 0;
     // the number of fetched results ( != number of valid results in array $qr)
     $prs = $query->getDescription()->getPrintrequests();
     $diHandler = $this->m_store->getDataItemHandlerForDIType(SMWDataItem::TYPE_WIKIPAGE);
     while ($count < $query->getLimit() && ($row = $this->m_dbs->fetchObject($res))) {
         $count++;
         if ($row->iw === '' || $row->iw[0] != ':') {
             $qr[] = $diHandler->dataItemFromDBKeys(array($row->t, intval($row->ns), $row->iw, '', $row->so));
             // These IDs are usually needed for displaying the page (esp. if more property values are displayed):
             $this->m_store->smwIds->setCache($row->t, $row->ns, $row->iw, $row->so, $row->id, $row->sortkey);
         }
     }
     if ($this->m_dbs->fetchObject($res)) {
         $count++;
     }
     $this->m_dbs->freeResult($res);
     $result = new SMWQueryResult($prs, $query, $qr, $this->m_store, $count > $query->getLimit());
     wfProfileOut('SMWSQLStore3Queries::getInstanceQueryResult (SMW)');
     return $result;
 }
 /**
  * Build an SMWQueryResult object from a SMWSparqlResultWrapper. This
  * function is used to generate instance query results, and the given
  * result wrapper must have an according format (one result column that
  * contains URIs of wiki pages).
  *
  * @param $sparqlResultWrapper SMWSparqlResultWrapper
  * @param $query SMWQuery, SMWQueryResults hold a reference to original query
  * @return SMWQueryResult
  */
 protected function getQueryResultFromSparqlResult(SMWSparqlResultWrapper $sparqlResultWrapper, SMWQuery $query)
 {
     $resultDataItems = array();
     foreach ($sparqlResultWrapper as $resultRow) {
         if (count($resultRow) > 0) {
             $dataItem = SMWExporter::findDataItemForExpElement($resultRow[0]);
             if (!is_null($dataItem)) {
                 $resultDataItems[] = $dataItem;
             }
         }
     }
     if ($sparqlResultWrapper->numRows() > $query->getLimit()) {
         array_pop($resultDataItems);
         $hasFurtherResults = true;
     } else {
         $hasFurtherResults = false;
     }
     $result = new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, $resultDataItems, $this->m_store, $hasFurtherResults);
     switch ($sparqlResultWrapper->getErrorCode()) {
         case SMWSparqlResultWrapper::ERROR_NOERROR:
             break;
         case SMWSparqlResultWrapper::ERROR_INCOMPLETE:
             $result->addErrors(array(wfMessage('smw_db_sparqlqueryincomplete')->inContentLanguage()->text()));
             break;
         default:
             $result->addErrors(array(wfMessage('smw_db_sparqlqueryproblem')->inContentLanguage()->text()));
             break;
     }
     return $result;
 }
Example #18
0
 /**
  * Using a preprocessed internal query description referenced by $rootid,
  * compute the proper result instance output for the given query.
  * @todo The SQL standard requires us to select all fields by which we sort, leading
  * to wrong results regarding the given limit: the user expects limit to be applied to
  * the number of distinct pages, but we can use DISTINCT only to whole rows. Thus, if
  * rows contain sortfields, then pages with multiple values for that field are distinct
  * and appear multiple times in the result. Filtering duplicates in post processing
  * would still allow such duplicates to push aside wanted values, leading to less than
  * "limit" results although there would have been "limit" really distinct results. For
  * this reason, we select sortfields only for POSTGRES. MySQL is able to perform what
  * we want here. It would be nice if we could eliminate the bug in POSTGRES as well.
  *
  * @param SMWQuery $query
  * @param integer $rootid
  *
  * @return SMWQueryResult
  */
 protected function getInstanceQueryResult(SMWQuery $query, $rootid)
 {
     global $wgDBtype;
     wfProfileIn('SMWSQLStore2Queries::getInstanceQueryResult (SMW)');
     $qobj = $this->m_queries[$rootid];
     if ($qobj->joinfield === '') {
         // empty result, no query needed
         $result = new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false);
         wfProfileOut('SMWSQLStore2Queries::getInstanceQueryResult (SMW)');
         return $result;
     }
     $sql_options = $this->getSQLOptions($query, $rootid);
     // Selecting those is required in standard SQL (but MySQL does not require it).
     $sortfields = implode($qobj->sortfields, ',');
     $res = $this->m_dbs->select($this->m_dbs->tableName($qobj->jointable) . " AS {$qobj->alias}" . $qobj->from, "DISTINCT {$qobj->alias}.smw_id AS id,{$qobj->alias}.smw_title AS t,{$qobj->alias}.smw_namespace AS ns,{$qobj->alias}.smw_iw AS iw,{$qobj->alias}.smw_subobject AS so,{$qobj->alias}.smw_sortkey AS sortkey" . ($wgDBtype == 'postgres' ? ($sortfields ? ',' : '') . $sortfields : ''), $qobj->where, 'SMW::getQueryResult', $sql_options);
     $qr = array();
     $count = 0;
     // the number of fetched results ( != number of valid results in array $qr)
     $prs = $query->getDescription()->getPrintrequests();
     while ($count < $query->getLimit() && ($row = $this->m_dbs->fetchObject($res))) {
         $count++;
         if ($row->iw === '' || $row->iw[0] != ':') {
             $v = new SMWDIWikiPage($row->t, intval($row->ns), $row->iw, $row->so);
             $qr[] = $v;
             $this->m_store->cacheSMWPageID($row->id, $row->t, $row->ns, $row->iw, $row->so);
         }
     }
     if ($this->m_dbs->fetchObject($res)) {
         $count++;
     }
     $this->m_dbs->freeResult($res);
     // TODO: for some reason this line makes PHPunit complain "This test printed output: ".
     $result = new SMWQueryResult($prs, $query, $qr, $this->m_store, $count > $query->getLimit());
     wfProfileOut('SMWSQLStore2Queries::getInstanceQueryResult (SMW)');
     return $result;
 }
 /**
  * @since 2.5
  *
  * @param Store $store
  * @param Query $query
  * @param DIWikiPage[]|[] $results = array()
  * @param boolean $continue
  *
  * @return QueryResult
  */
 public function newQueryResult(Store $store, Query $query, $results = array(), $continue = false)
 {
     $queryResult = new QueryResult($query->getDescription()->getPrintrequests(), $query, $results, $store, $continue);
     return $queryResult;
 }
 /**
  * The new SQL store's implementation of query answering. This function
  * works in two stages: First, the nested conditions of the given query
  * object are preprocessed to compute an abstract representation of the
  * SQL query that is to be executed. Since query conditions correspond to
  * joins with property tables in most cases, this abstract representation
  * is essentially graph-like description of how property tables are joined.
  * Moreover, this graph is tree-shaped, since all query conditions are
  * tree-shaped. Each part of this abstract query structure is represented
  * by an SMWSQLStore2Query object in the array m_queries.
  *
  * As a second stage of processing, the thus prepared SQL query is actually
  * executed. Typically, this means that the joins are collapsed into one
  * SQL query to retrieve results. In some cases, such as in dbug mode, the
  * execution might be restricted and not actually perform the whole query.
  *
  * The two-stage process helps to separate tasks, and it also allows for
  * better optimisations: it is left to the execution engine how exactly the
  * query result is to be obtained. For example, one could pre-compute
  * partial suib-results in temporary tables (or even cache them somewhere),
  * instead of passing one large join query to the DB (of course, it might
  * be large only if the configuration of SMW allows it). For some DBMS, a
  * step-wise execution of the query might lead to better performance, since
  * it exploits the tree-structure of the joins, which is important for fast
  * processing -- not all DBMS might be able in seeing this by themselves.
  *
  * @param SMWQuery $query
  */
 public function getQueryResult(SMWQuery $query)
 {
     global $smwgIgnoreQueryErrors, $smwgQSortingSupport;
     if (!$smwgIgnoreQueryErrors && $query->querymode != SMWQuery::MODE_DEBUG && count($query->getErrors()) > 0) {
         return new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false);
         // NOTE: we check this here to prevent unnecessary work, but we check it after query processing below again in case more errors occurred
     } elseif ($query->querymode == SMWQuery::MODE_NONE) {
         // don't query, but return something to printer
         return new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, true);
     }
     $this->m_qmode = $query->querymode;
     $this->m_queries = array();
     $this->m_hierarchies = array();
     $this->m_querylog = array();
     $this->m_errors = array();
     SMWSQLStore2Query::$qnum = 0;
     $this->m_sortkeys = $query->sortkeys;
     // *** First compute abstract representation of the query (compilation) ***//
     wfProfileIn('SMWSQLStore2Queries::compileMainQuery (SMW)');
     $qid = $this->compileQueries($query->getDescription());
     // compile query, build query "plan"
     wfProfileOut('SMWSQLStore2Queries::compileMainQuery (SMW)');
     if ($qid < 0) {
         // no valid/supported condition; ensure that at least only proper pages are delivered
         $qid = SMWSQLStore2Query::$qnum;
         $q = new SMWSQLStore2Query();
         $q->jointable = 'smw_ids';
         $q->joinfield = "{$q->alias}.smw_id";
         $q->where = "{$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWIW) . " AND {$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWREDIIW) . " AND {$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWBORDERIW) . " AND {$q->alias}.smw_iw!=" . $this->m_dbs->addQuotes(SMW_SQL2_SMWINTDEFIW);
         $this->m_queries[$qid] = $q;
     }
     if ($this->m_queries[$qid]->jointable != 'smw_ids') {
         // manually make final root query (to retrieve namespace,title):
         $rootid = SMWSQLStore2Query::$qnum;
         $qobj = new SMWSQLStore2Query();
         $qobj->jointable = 'smw_ids';
         $qobj->joinfield = "{$qobj->alias}.smw_id";
         $qobj->components = array($qid => "{$qobj->alias}.smw_id");
         $qobj->sortfields = $this->m_queries[$qid]->sortfields;
         $this->m_queries[$rootid] = $qobj;
     } else {
         // not such a common case, but worth avoiding the additional inner join:
         $rootid = $qid;
     }
     // commented by ning, no need to sort
     //		// Include order conditions (may extend query if needed for sorting):
     //		if ( $smwgQSortingSupport ) {
     //			$this->applyOrderConditions( $rootid );
     //		}
     if (!$smwgIgnoreQueryErrors && $query->querymode != SMWQuery::MODE_DEBUG && count($this->m_errors) > 0) {
         // stop here if new errors happened
         $query->addErrors($this->m_errors);
         return new SMWQueryResult($query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false);
     }
     // *** Now execute the computed query ***//
     wfProfileIn('SMWSQLStore2Queries::executeMainQuery (SMW)');
     $this->executeQueries($this->m_queries[$rootid]);
     // execute query tree, resolve all dependencies
     wfProfileOut('SMWSQLStore2Queries::executeMainQuery (SMW)');
     $result = $this->getNMQueryResult($query, $rootid);
     $this->cleanUp();
     $query->addErrors($this->m_errors);
     return $result;
 }