r87817 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r87816‎ | r87817 | r87818 >
Date:13:20, 10 May 2011
Author:mkroetzsch
Status:deferred
Tags:
Comment:
added support for format=count
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/sparql/SMW_SparqlDatabase.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/sparql/SMW_SparqlResultWrapper.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStore.php (modified) (history)
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStoreQueryEngine.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/sparql/SMW_SparqlDatabase.php
@@ -243,6 +243,34 @@
244244 }
245245
246246 /**
 247+ * SELECT wrapper for counting results.
 248+ * The function declares the standard namespaces wiki, swivt, rdf, owl,
 249+ * rdfs, property, xsd, so these do not have to be included in
 250+ * $extraNamespaces.
 251+ *
 252+ * @param $variable string variable name or '*'
 253+ * @param $where string WHERE part of the query, without surrounding { }
 254+ * @param $options array (associative) of options, e.g. array('LIMIT' => '10')
 255+ * @param $extraNamespaces array (associative) of namespaceId => namespaceUri
 256+ * @return SMWSparqlResultWrapper
 257+ */
 258+ public function selectCount( $variable, $where, $options = array(), $extraNamespaces = array() ) {
 259+ $sparql = self::getPrefixString( $extraNamespaces ) . 'SELECT (COUNT(';
 260+ if ( array_key_exists( 'DISTINCT', $options ) ) {
 261+ $sparql .= 'DISTINCT ';
 262+ }
 263+ $sparql .= $variable . ") AS ?count) WHERE {\n" . $where . "\n}";
 264+ if ( array_key_exists( 'OFFSET', $options ) ) {
 265+ $sparql .= "\nOFFSET " . $options['OFFSET'];
 266+ }
 267+ if ( array_key_exists( 'LIMIT', $options ) ) {
 268+ $sparql .= "\nLIMIT " . $options['LIMIT'];
 269+ }
 270+
 271+ return $this->doQuery( $sparql );
 272+ }
 273+
 274+ /**
247275 * DELETE wrapper.
248276 * The function declares the standard namespaces wiki, swivt, rdf, owl,
249277 * rdfs, property, xsd, so these do not have to be included in
Index: trunk/extensions/SemanticMediaWiki/includes/sparql/SMW_SparqlResultWrapper.php
@@ -97,6 +97,26 @@
9898 }
9999
100100 /**
 101+ * Check if the result is what one would get for a SPARQL SELECT COUNT
 102+ * query, and return the corresponding integer value. Returns 0 in all
 103+ * other cases (including the case that the results do not look at all
 104+ * like the result of a SELECT COUNT query).
 105+ *
 106+ * @return integer
 107+ */
 108+ public function getNumericValue() {
 109+ if ( count( $this->m_data ) == 1 ) {
 110+ $row = reset( $this->m_data );
 111+ $expElement = reset( $row );
 112+ if ( ( count( $row ) == 1 ) && ( $expElement instanceof SMWExpLiteral ) &&
 113+ ( $expElement->getDatatype() == 'http://www.w3.org/2001/XMLSchema#integer' ) ) {
 114+ return (int)$expElement->getLexicalForm();
 115+ }
 116+ }
 117+ return 0;
 118+ }
 119+
 120+ /**
101121 * Reset iterator to position 0. Standard method of Iterator.
102122 */
103123 public function rewind() {
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStoreQueryEngine.php
@@ -260,50 +260,114 @@
261261 $this->m_store = $store;
262262 }
263263
 264+ public function getCountQueryResult( SMWQuery $query ) {
 265+ $this->m_sortkeys = array(); // ignore sorting, just count
 266+ $sparqlCondition = $this->getSparqlCondition( $query->getDescription() );
 267+
 268+ if ( $sparqlCondition instanceof SMWSparqlSingletonCondition ) {
 269+ $matchElement = $sparqlCondition->matchElement;
 270+ if ( $sparqlCondition->condition == '' ) { // all URIs exist, no querying
 271+ return 1;
 272+ } else {
 273+ $condition = $this->getSparqlConditionString( $sparqlCondition );
 274+ $namespaces = $sparqlCondition->namespaces;
 275+ $askQueryResult = smwfGetSparqlDatabase()->ask( $condition, $namespaces );
 276+ return $askQueryResult->isBooleanTrue() ? 1 : 0;
 277+ }
 278+ } elseif ( $sparqlCondition instanceof SMWSparqlFalseCondition ) {
 279+ return 0;
 280+ } else {
 281+ //debug_zval_dump( $condition );
 282+ $condition = $this->getSparqlConditionString( $sparqlCondition );
 283+ $namespaces = $sparqlCondition->namespaces;
 284+ $options = $this->getSparqlOptions( $query );
 285+ $options['DISTINCT'] = true;
 286+ $sparqlResultWrapper = smwfGetSparqlDatabase()->selectCount( '?' . self::RESULT_VARIABLE,
 287+ $condition, $options, $namespaces );
 288+ if ( $sparqlResultWrapper->getErrorCode() == SMWSparqlResultWrapper::ERROR_NOERROR ) {
 289+ return (int)$sparqlResultWrapper->getNumericValue();
 290+ } else {
 291+ ///@todo Implement error reporting for counting queries.
 292+// smwfLoadExtensionMessages( 'SemanticMediaWiki' );
 293+// $result->addErrors( array( wfMsgForContent( 'smw_db_sparqlqueryproblem' ) ) );
 294+ }
 295+ }
 296+ }
 297+
264298 public function getInstanceQueryResult( SMWQuery $query ) {
265299 $this->m_sortkeys = $query->sortkeys;
266300 $sparqlCondition = $this->getSparqlCondition( $query->getDescription() );
267 -
268301 //debug_zval_dump($sparqlCondition);
269 - $namespaces = $sparqlCondition->namespaces;
270 - $condition = $sparqlCondition->getWeakConditionString();
271 - if ( ( $condition == '' ) && !$sparqlCondition->isSafe() ) {
272 - $swivtPageResource = SMWExporter::getSpecialNsResource( 'swivt', 'page' );
273 - $condition = '?' . self::RESULT_VARIABLE . $swivtPageResource->getQName() . " ?url .\n";
274 - }
275 - $condition .= $sparqlCondition->getCondition();
276302
277303 if ( $sparqlCondition instanceof SMWSparqlSingletonCondition ) {
278304 $matchElement = $sparqlCondition->matchElement;
279 - if ( $sparqlCondition->condition == '' ) {
 305+ if ( $sparqlCondition->condition == '' ) { // all URIs exist, no querying
280306 $results = array( array ( $matchElement ) );
281307 } else {
282 - $matchElementName = SMWTurtleSerializer::getTurtleNameForExpElement( $matchElement );
283 - if ( $matchElement instanceof SMWExpNsResource ) {
284 - $namespaces[$matchElement->getNamespaceId()] = $matchElement->getNamespace();
285 - }
286 - $condition = str_replace( '?' . self::RESULT_VARIABLE, "$matchElementName ", $condition );
 308+ $condition = $this->getSparqlConditionString( $sparqlCondition );
 309+ $namespaces = $sparqlCondition->namespaces;
287310 $askQueryResult = smwfGetSparqlDatabase()->ask( $condition, $namespaces );
288 - if ( $askQueryResult->isBooleanTrue() ) {
289 - $results = array( array ( $matchElement ) );
290 - } else {
291 - $results = array();
292 - }
 311+ $results = $askQueryResult->isBooleanTrue() ? array( array ( $matchElement ) ) : array();
293312 }
294 - $sparqlResult = new SMWSparqlResultWrapper( array( self::RESULT_VARIABLE => 0 ), $results );
 313+ $sparqlResultWrapper = new SMWSparqlResultWrapper( array( self::RESULT_VARIABLE => 0 ), $results );
295314 } elseif ( $sparqlCondition instanceof SMWSparqlFalseCondition ) {
296 - $sparqlResult = new SMWSparqlResultWrapper( array( self::RESULT_VARIABLE => 0 ), array() );
 315+ $sparqlResultWrapper = new SMWSparqlResultWrapper( array( self::RESULT_VARIABLE => 0 ), array() );
297316 } else {
298317 //debug_zval_dump( $condition );
 318+ $condition = $this->getSparqlConditionString( $sparqlCondition );
 319+ $namespaces = $sparqlCondition->namespaces;
299320 $options = $this->getSparqlOptions( $query );
300321 $options['DISTINCT'] = true;
301 - $sparqlResult = smwfGetSparqlDatabase()->select( '?' . self::RESULT_VARIABLE,
302 - $condition, $options, $namespaces );
 322+ $sparqlResultWrapper = smwfGetSparqlDatabase()->select( '?' . self::RESULT_VARIABLE,
 323+ $condition, $options, $namespaces );
303324 }
304325
305 - //debug_zval_dump( $sparqlResult );
 326+ //debug_zval_dump( $sparqlResultWrapper );
 327+ return $this->getQueryResultFromSparqlResult( $sparqlResultWrapper, $query );
 328+ }
 329+
 330+ /**
 331+ * Build the condition (WHERE) string for a given SMWSparqlCondition.
 332+ * The function also expresses the single value of
 333+ * SMWSparqlSingletonCondition objects in the condition, which may
 334+ * lead to additional namespaces for serializing its URI.
 335+ *
 336+ * @param SMWSparqlCondition $sparqlCondition
 337+ * @return string
 338+ */
 339+ protected function getSparqlConditionString( SMWSparqlCondition &$sparqlCondition ) {
 340+ $condition = $sparqlCondition->getWeakConditionString();
 341+ if ( ( $condition == '' ) && !$sparqlCondition->isSafe() ) {
 342+ $swivtPageResource = SMWExporter::getSpecialNsResource( 'swivt', 'page' );
 343+ $condition = '?' . self::RESULT_VARIABLE . ' ' . $swivtPageResource->getQName() . " ?url .\n";
 344+ }
 345+ $condition .= $sparqlCondition->getCondition();
 346+
 347+ if ( $sparqlCondition instanceof SMWSparqlSingletonCondition ) { // prepare for ASK, maybe rather use BIND?
 348+ $matchElement = $sparqlCondition->matchElement;
 349+ $matchElementName = SMWTurtleSerializer::getTurtleNameForExpElement( $matchElement );
 350+ if ( $matchElement instanceof SMWExpNsResource ) {
 351+ $sparqlCondition->namespaces[$matchElement->getNamespaceId()] = $matchElement->getNamespace();
 352+ }
 353+ $condition = str_replace( '?' . self::RESULT_VARIABLE, "$matchElementName ", $condition );
 354+ }
 355+
 356+ return $condition;
 357+ }
 358+
 359+ /**
 360+ * Build an SMWQueryResult object from a SMWSparqlResultWrapper. This
 361+ * function is used to generate instance query results, and the given
 362+ * result wrapper must have an according format (one result column that
 363+ * contains URIs of wiki pages).
 364+ *
 365+ * @param SMWSparqlResultWrapper $sparqlResultWrapper
 366+ * @param SMWQuery $query SMWQueryResults hold a reference to original query
 367+ * @return SMWQueryResult
 368+ */
 369+ protected function getQueryResultFromSparqlResult( SMWSparqlResultWrapper $sparqlResultWrapper, SMWQuery $query ) {
306370 $resultDataItems = array();
307 - foreach ( $sparqlResult as $resultRow ) {
 371+ foreach ( $sparqlResultWrapper as $resultRow ) {
308372 if ( count( $resultRow ) > 0 ) {
309373 $dataItem = SMWExporter::findDataItemForExpElement( $resultRow[0] );
310374 if ( $dataItem !== null ) {
@@ -311,6 +375,7 @@
312376 }
313377 }
314378 }
 379+
315380 if ( count( $resultDataItems ) > $query->getLimit() ) {
316381 array_pop( $resultDataItems );
317382 $hasFurtherResults = true;
@@ -319,10 +384,12 @@
320385 }
321386
322387 $result = new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, $resultDataItems, $this->m_store, $hasFurtherResults );
323 - if ( $sparqlResult->getErrorCode() != SMWSparqlResultWrapper::ERROR_NOERROR ) {
 388+
 389+ if ( $sparqlResultWrapper->getErrorCode() != SMWSparqlResultWrapper::ERROR_NOERROR ) {
324390 smwfLoadExtensionMessages( 'SemanticMediaWiki' );
325391 $result->addErrors( array( wfMsgForContent( 'smw_db_sparqlqueryproblem' ) ) );
326392 }
 393+
327394 return $result;
328395 }
329396
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SparqlStore.php
@@ -177,13 +177,14 @@
178178
179179 if ( $query->querymode == SMWQuery::MODE_NONE ) { // don't query, but return something to printer
180180 return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this, true );
181 - } elseif ( $query->querymode == SMWQuery::MODE_DEBUG || $query->querymode == SMWQuery::MODE_COUNT ) {
 181+ } elseif ( $query->querymode == SMWQuery::MODE_DEBUG ) {
182182 return "Not implemented.\n";
 183+ } elseif ( $query->querymode == SMWQuery::MODE_COUNT ) {
 184+ $queryEngine = new SMWSparqlStoreQueryEngine( $this );
 185+ return $queryEngine->getCountQueryResult( $query );
183186 } else {
184187 $queryEngine = new SMWSparqlStoreQueryEngine( $this );
185 - $queryResult = $queryEngine->getInstanceQueryResult( $query );
186 -// debug_zval_dump( $queryResult );
187 - return $queryResult;
 188+ return $queryEngine->getInstanceQueryResult( $query );
188189 }
189190 }
190191

Status & tagging log