r66141 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r66140‎ | r66141 | r66142 >
Date:16:17, 10 May 2010
Author:jeroendedauw
Status:deferred
Tags:
Comment:
Cleaned up code and improved code and doc styles
Modified paths:
  • /trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php (modified) (history)

Diff [purge]

Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php
@@ -29,8 +29,18 @@
3030 public $from = '';
3131 public $where = '';
3232 public $components = array();
33 - public $alias; // the alias to be used for jointable; read-only after construct!
34 - public $sortfields = array(); // property dbkey => db field; passed down during query execution
 33+
 34+ /**
 35+ * The alias to be used for jointable; read-only after construct!
 36+ * @var string
 37+ */
 38+ public $alias;
 39+
 40+ /**
 41+ * property dbkey => db field; passed down during query execution.
 42+ * @var array
 43+ */
 44+ public $sortfields = array();
3545
3646 public static $qnum = 0;
3747
@@ -167,13 +177,15 @@
168178 * processing -- not all DBMS might be able in seeing this by themselves.
169179 */
170180 public function getQueryResult( SMWQuery $query ) {
171 - global $smwgIgnoreQueryErrors;
 181+ global $smwgIgnoreQueryErrors, $smwgQSortingSupport;
 182+
172183 if ( !$smwgIgnoreQueryErrors && ( $query->querymode != SMWQuery::MODE_DEBUG ) && ( count( $query->getErrors() ) > 0 ) ) {
173184 return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false );
174185 // NOTE: We currently check this only once since the below steps do not create further errors
175186 } elseif ( $query->querymode == SMWQuery::MODE_NONE ) { // don't query, but return something to printer
176187 return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, true );
177188 }
 189+
178190 $this->m_qmode = $query->querymode;
179191 $this->m_queries = array();
180192 $this->m_hierarchies = array();
@@ -186,6 +198,7 @@
187199 wfProfileIn( 'SMWSQLStore2Queries::compileMainQuery (SMW)' );
188200 $qid = $this->compileQueries( $query->getDescription() ); // compile query, build query "plan"
189201 wfProfileOut( 'SMWSQLStore2Queries::compileMainQuery (SMW)' );
 202+
190203 if ( $qid < 0 ) { // no valid/supported condition; ensure that at least only proper pages are delivered
191204 $qid = SMWSQLStore2Query::$qnum;
192205 $q = new SMWSQLStore2Query();
@@ -194,6 +207,7 @@
195208 $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 );
196209 $this->m_queries[$qid] = $q;
197210 }
 211+
198212 if ( $this->m_queries[$qid]->jointable != 'smw_ids' ) {
199213 // manually make final root query (to retrieve namespace,title):
200214 $rootid = SMWSQLStore2Query::$qnum;
@@ -206,13 +220,17 @@
207221 } else { // not such a common case, but worth avoiding the additional inner join:
208222 $rootid = $qid;
209223 }
210 - // include order conditions (may extend query if needed for sorting):
211 - $this->applyOrderConditions( $query, $rootid );
 224+
 225+ // Include order conditions (may extend query if needed for sorting):
 226+ if ( $smwgQSortingSupport ) {
 227+ $this->applyOrderConditions( $rootid );
 228+ }
212229
213230 // *** Now execute the computed query ***//
214231 wfProfileIn( 'SMWSQLStore2Queries::executeMainQuery (SMW)' );
215232 $this->executeQueries( $this->m_queries[$rootid] ); // execute query tree, resolve all dependencies
216233 wfProfileOut( 'SMWSQLStore2Queries::executeMainQuery (SMW)' );
 234+
217235 switch ( $query->querymode ) {
218236 case SMWQuery::MODE_DEBUG:
219237 $result = $this->getDebugQueryResult( $query, $rootid );
@@ -224,25 +242,33 @@
225243 $result = $this->getInstanceQueryResult( $query, $rootid );
226244 break;
227245 }
 246+
228247 $this->cleanUp();
229248 $query->addErrors( $this->m_errors );
 249+
230250 return $result;
231251 }
232252
233253 /**
234254 * Using a preprocessed internal query description referenced by $rootid, compute
235255 * the proper debug output for the given query.
 256+ *
 257+ * @param SMWQuery $query
 258+ * @param $rootid
236259 */
237 - protected function getDebugQueryResult( $query, $rootid ) {
 260+ protected function getDebugQueryResult( SMWQuery $query, $rootid ) {
238261 $qobj = $this->m_queries[$rootid];
239262 $sql_options = $this->getSQLOptions( $query, $rootid );
 263+
240264 list( $startOpts, $useIndex, $tailOpts ) = $this->m_dbs->makeSelectOptions( $sql_options );
 265+
241266 $result = '<div style="border: 1px dotted black; background: #A1FB00; padding: 20px; ">' .
242267 '<b>Debug output by SMWSQLStore2</b><br />' .
243268 'Generated Wiki-Query<br /><tt>' .
244269 str_replace( '[', '&#x005B;', $query->getDescription()->getQueryString() ) . '</tt><br />' .
245270 'Query-Size: ' . $query->getDescription()->getSize() . '<br />' .
246271 'Query-Depth: ' . $query->getDescription()->getDepth() . '<br />';
 272+
247273 if ( $qobj->joinfield !== '' ) {
248274 $result .= 'SQL query<br />' .
249275 "<tt>SELECT DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns FROM " .
@@ -252,21 +278,29 @@
253279 } else {
254280 $result .= '<b>Empty result, no SQL query created.</b>';
255281 }
 282+
256283 $errors = '';
 284+
257285 foreach ( $query->getErrors() as $error ) {
258286 $errors .= $error . '<br />';
259287 }
 288+
260289 $result .= ( $errors ) ? "<br />Errors and warnings:<br />$errors":'<br />No errors or warnings.';
261290 $auxtables = '';
 291+
262292 foreach ( $this->m_querylog as $table => $log ) {
263293 $auxtables .= "<li>Temporary table $table";
 294+
264295 foreach ( $log as $q ) {
265296 $auxtables .= "<br />&nbsp;&nbsp;<tt>$q</tt>";
266297 }
 298+
267299 $auxtables .= '</li>';
268300 }
 301+
269302 $result .= ( $auxtables ) ? "<br />Auxilliary tables used:<ul>$auxtables</ul>":'<br />No auxilliary tables used.';
270303 $result .= '</div>';
 304+
271305 return $result;
272306 }
273307
@@ -302,38 +336,54 @@
303337 * "limit" results although there would have been "limit" really distinct results. For
304338 * this reason, we select sortfields only for POSTGRES. MySQL is able to perform what
305339 * we want here. It would be nice if we could eliminate the bug in POSTGRES as well.
 340+ *
 341+ * @param SMWQuery $query
 342+ * @param $rootid
 343+ *
 344+ * @return SMWQueryResult
306345 */
307 - protected function getInstanceQueryResult( $query, $rootid ) {
 346+ protected function getInstanceQueryResult( SMWQuery $query, $rootid ) {
308347 global $wgDBtype;
 348+
309349 wfProfileIn( 'SMWSQLStore2Queries::getInstanceQueryResult (SMW)' );
310350 $qobj = $this->m_queries[$rootid];
 351+
311352 if ( $qobj->joinfield === '' ) { // empty result, no query needed
312353 $result = new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false );
313354 wfProfileOut( 'SMWSQLStore2Queries::getInstanceQueryResult (SMW)' );
314355 return $result;
315356 }
 357+
316358 $sql_options = $this->getSQLOptions( $query, $rootid );
317 - $sortfields = implode( $qobj->sortfields, ',' ); // selecting those is required in standard SQL (but MySQL does not require it)
 359+
 360+ // Selecting those is required in standard SQL (but MySQL does not require it).
 361+ $sortfields = implode( $qobj->sortfields, ',' );
 362+
318363 $res = $this->m_dbs->select( $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from,
319364 "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_sortkey AS sortkey" .
320 - ( $wgDBtype == 'postgres' ? ( ( $sortfields ? ',':'' ) . $sortfields ) : '' ),
 365+ ( $wgDBtype == 'postgres' ? ( ( $sortfields ? ',' : '' ) . $sortfields ) : '' ),
321366 $qobj->where, 'SMW::getQueryResult', $sql_options );
322367
323368 $qr = array();
324369 $count = 0;
325370 $prs = $query->getDescription()->getPrintrequests();
 371+
326372 while ( ( $count < $query->getLimit() ) && ( $row = $this->m_dbs->fetchObject( $res ) ) ) {
327373 $count++;
328374 $v = SMWWikiPageValue::makePage( $row->t, $row->ns, $row->sortkey );
329375 $qr[] = $v;
330376 $this->m_store->cacheSMWPageID( $row->id, $row->t, $row->ns, $row->iw );
331377 }
 378+
332379 if ( $this->m_dbs->fetchObject( $res ) ) {
333380 $count++;
334381 }
 382+
335383 $this->m_dbs->freeResult( $res );
336384 $result = new SMWQueryResult( $prs, $query, $qr, $this->m_store, ( $count > $query->getLimit() ) );
 385+
337386 wfProfileOut( 'SMWSQLStore2Queries::getInstanceQueryResult (SMW)' );
 387+
338388 return $result;
339389 }
340390
@@ -346,6 +396,10 @@
347397 * makes some assumptions about the table structure, especially about the
348398 * name of the joinfield (o_id). Better extend compileAttributeWhere to
349399 * deal with this case.
 400+ *
 401+ * @param SMWDescription $description
 402+ *
 403+ * @return integer
350404 */
351405 protected function compileQueries( SMWDescription $description ) {
352406 $qid = SMWSQLStore2Query::$qnum;
@@ -384,6 +438,7 @@
385439 $cquery->joinfield[] = $cid;
386440 }
387441 }
 442+
388443 if ( count( $cquery->joinfield ) == 0 ) { // Empty result.
389444 $query->type = SMW_SQL2_VALUE;
390445 $query->jointable = '';
@@ -404,6 +459,7 @@
405460 $query->jointable = 'smw_ids';
406461 $query->joinfield = "$query->alias.smw_id";
407462 $value = $description->getDatavalue()->getSortkey();
 463+
408464 switch ( $description->getComparator() ) {
409465 case SMW_CMP_LEQ: $comp = '<='; break;
410466 case SMW_CMP_GEQ: $comp = '>='; break;
@@ -413,33 +469,40 @@
414470 $value = str_replace( array( '%', '_', '*', '?' ), array( '\%', '\_', '%', '_' ), $value );
415471 break;
416472 }
 473+
417474 $query->where = "$query->alias.smw_sortkey$comp" . $this->m_dbs->addQuotes( $value );
418475 }
419476 }
420477 } elseif ( $description instanceof SMWConceptDescription ) { // fetch concept definition and insert it here
421478 $cid = $this->m_store->getSMWPageID( $description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '' );
422 - $row = $this->m_dbs->selectRow( 'smw_conc2',
423 - array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date' ),
424 - array( 's_id' => $cid ), 'SMWSQLStore2Queries::compileQueries' );
 479+ $row = $this->m_dbs->selectRow(
 480+ 'smw_conc2',
 481+ array( 'concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date' ),
 482+ array( 's_id' => $cid ),
 483+ 'SMWSQLStore2Queries::compileQueries'
 484+ );
 485+
425486 if ( $row === false ) { // No description found, concept does not exist.
426487 // keep the above query object, it yields an empty result
427488 // TODO: announce an error here? (maybe not, since the query processor can check for
428489 // non-existing concept pages which is probably the main reason for finding nothing here
429490 } else {
430491 global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime;
 492+
431493 $may_be_computed = ( $smwgQConceptCaching == CONCEPT_CACHE_NONE ) ||
432494 ( ( $smwgQConceptCaching == CONCEPT_CACHE_HARD ) && ( ( ~( ~( $row->concept_features + 0 ) | $smwgQFeatures ) ) == 0 ) &&
433495 ( $smwgQMaxSize >= $row->concept_size ) && ( $smwgQMaxDepth >= $row->concept_depth ) );
 496+
434497 if ( $row->cache_date &&
435498 ( ( $row->cache_date > ( strtotime( "now" ) - $smwgQConceptCacheLifetime * 60 ) ) ||
436 - !$may_be_computed ) ) { // cached concept, use cache unless it is dead and can be revived
 499+ !$may_be_computed ) ) { // Cached concept, use cache unless it is dead and can be revived.
437500 $query->jointable = 'smw_conccache';
438501 $query->joinfield = "$query->alias.s_id";
439502 $query->where = "$query->alias.o_id=" . $this->m_dbs->addQuotes( $cid );
440 - } elseif ( $row->concept_txt ) { // parse description and process it recursively
 503+ } elseif ( $row->concept_txt ) { // Parse description and process it recursively.
441504 if ( $may_be_computed ) {
442505 $qp = new SMWQueryParser();
443 - // no defaultnamespaces here; if any, these are already in the concept
 506+ //No defaultnamespaces here; If any, these are already in the concept.
444507 $desc = $qp->getQueryDescription( $row->concept_txt );
445508 $qid = $this->compileQueries( $desc );
446509 $query = $this->m_queries[$qid];
@@ -453,15 +516,16 @@
454517 $qid = - 1; // no condition
455518 }
456519
457 - if ( $qid >= 0 ) { // success, keep query object, propagate sortkeys from subqueries
 520+ if ( $qid >= 0 ) { // Success, keep query object, propagate sortkeys from subqueries.
458521 $this->m_queries[$qid] = $query;
459 - if ( $query->type != SMW_SQL2_DISJUNCTION ) { // sortkeys are killed by disjunctions (not all parts may have them),
 522+ if ( $query->type != SMW_SQL2_DISJUNCTION ) { // Sortkeys are killed by disjunctions (not all parts may have them),
460523 // NOTE: preprocessing might try to push disjunctions downwards to safe sortkey, but this seems to be minor
461524 foreach ( $query->components as $cid => $field ) {
462525 $query->sortfields = array_merge( $this->m_queries[$cid]->sortfields, $query->sortfields );
463526 }
464527 }
465528 }
 529+
466530 return $qid;
467531 }
468532
@@ -472,29 +536,35 @@
473537 * to check for this and discard the query in this case.
474538 * @todo Check if hierarchy queries work as expected.
475539 */
476 - protected function compilePropertyCondition( $query, $property, SMWDescription $valuedesc ) {
 540+ protected function compilePropertyCondition( SMWSQLStore2Query $query, $property, SMWDescription $valuedesc ) {
477541 $tableid = SMWSQLStore2::findPropertyTableID( $property );
 542+
478543 if ( $tableid == '' ) { // probably a type-polymorphic property
479544 $typeid = $valuedesc->getTypeID();
480545 $tableid = SMWSQLStore2::findTypeTableID( $typeid );
481546 } else { // normal property
482547 $typeid = $property->getPropertyTypeID();
483548 }
 549+
484550 if ( $tableid == '' ) { // Still no table to query? Give up.
485551 $query->type = SMW_SQL2_NOQUERY;
486552 return;
487553 }
 554+
488555 $proptables = SMWSQLStore2::getPropertyTables();
489556 $proptable = $proptables[$tableid];
 557+
490558 if ( !$proptable->idsubject ) { // no queries with such tables (there is really no demand, as only redirects are affected)
491559 $query->type = SMW_SQL2_NOQUERY;
492560 return;
493561 }
 562+
494563 list( $sig, $valueindexes, $labelindexes ) = SMWSQLStore2::getTypeSignature( $typeid );
495564 $sortkey = $property->getDBkey(); // TODO: strictly speaking, the DB key is not what we want here, since sortkey is based on a "wiki value"
496565
497566 // *** Basic settings: table, joinfield, and objectfields ***//
498567 $query->jointable = $proptable->name;
 568+
499569 if ( $property->isInverse() ) { // see if we can support inverses by inverting the proptable data
500570 if ( ( count( $proptable->objectfields ) == 1 ) && ( reset( $proptable->objectfields ) == 'p' ) ) {
501571 $query->joinfield = $query->alias . '.' . reset( array_keys( $proptable->objectfields ) );
@@ -512,6 +582,7 @@
513583 // *** Add conditions for selecting rows for this property, maybe with a hierarchy ***//
514584 if ( $proptable->fixedproperty == false ) {
515585 $pid = $this->m_store->getSMWPropertyID( $property );
 586+
516587 if ( !$property->getPropertyID() || ( $property->getPropertyTypeID() != '__err' ) ) {
517588 // also make property hierarchy (may or may not be executed later on)
518589 // exclude type-polymorphic properties _1, _2, ... (2nd check above suffices, but 1st is faster to check)
@@ -531,6 +602,7 @@
532603 if ( ( count( $objectfields ) == 1 ) && ( reset( $objectfields ) == 'p' ) ) { // page description, process like main query
533604 $sub = $this->compileQueries( $valuedesc );
534605 $objectfield = reset( array_keys( $objectfields ) );
 606+
535607 if ( $sub >= 0 ) {
536608 $query->components[$sub] = "{$query->alias}.{$objectfield}";
537609 }
@@ -549,6 +621,7 @@
550622 // type's signature. Thankfully, signatures are short so this iteration is not notable.
551623 $smwidjoinfield = false;
552624 $fieldNames = $this->getDBFieldsForDVIndexes( $objectfields, $valueindexes, $smwidjoinfield );
 625+
553626 if ( $fieldNames ) { // TODO //.//
554627 if ( $smwidjoinfield ) {
555628 // TODO: is this smw_ids possibly duplicated in the query? Can we prevent that? (PERFORMANCE)
@@ -886,37 +959,40 @@
887960 * This function modifies the given query object at $qid to account for all ordering conditions
888961 * in the SMWQuery $query. It is always required that $qid is the id of a query that joins with
889962 * smw_ids so that the field alias.smw_title is $available for default sorting.
 963+ *
 964+ * @param $qid
890965 */
891 - protected function applyOrderConditions( $query, $qid ) {
892 - global $smwgQSortingSupport;
893 - if ( !$smwgQSortingSupport ) {
894 - return;
895 - }
 966+ protected function applyOrderConditions( $qid ) {
896967 $qobj = $this->m_queries[$qid];
897968 // (1) collect required extra property descriptions:
898969 $extraproperties = array();
 970+
899971 foreach ( $this->m_sortkeys as $propkey => $order ) {
900 - if ( !array_key_exists( $propkey, $qobj->sortfields ) ) { // find missing property to sort by
901 - if ( $propkey == '' ) { // sort by first result column (page titles)
 972+ if ( !array_key_exists( $propkey, $qobj->sortfields ) ) { // Find missing property to sort by.
 973+ if ( $propkey == '' ) { // Sort by first result column (page titles).
902974 $qobj->sortfields[$propkey] = "$qobj->alias.smw_sortkey";
903 - } else { // try to extend query
 975+ } else { // Try to extend query.
904976 $extrawhere = '';
905977 $sortprop = SMWPropertyValue::makeUserProperty( $propkey );
 978+
906979 if ( $sortprop->isValid() ) {
907980 $extraproperties[] = new SMWSomeProperty( $sortprop, new SMWThingDescription() );
908981 }
909982 }
910983 }
911984 }
 985+
912986 // (2) compile according conditions and hack them into $qobj:
913987 if ( count( $extraproperties ) > 0 ) {
914988 $desc = new SMWConjunction( $extraproperties );
915989 $newqid = $this->compileQueries( $desc );
916 - $newqobj = $this->m_queries[$newqid]; // this is always an SMW_SQL2_CONJUNCTION ...
 990+ $newqobj = $this->m_queries[$newqid]; // This is always an SMW_SQL2_CONJUNCTION ...
 991+
917992 foreach ( $newqobj->components as $cid => $field ) { // ... so just re-wire its dependencies
918993 $qobj->components[$cid] = $qobj->joinfield;
919994 $qobj->sortfields = array_merge( $qobj->sortfields, $this->m_queries[$cid]->sortfields );
920995 }
 996+
921997 $this->m_queries[$qid] = $qobj;
922998 }
923999 }
@@ -924,17 +1000,20 @@
9251001 /**
9261002 * Get a SQL option array for the given query and preprocessed query object at given id.
9271003 */
928 - protected function getSQLOptions( $query, $rootid ) {
 1004+ protected function getSQLOptions( SMWQuery $query, $rootid ) {
9291005 global $smwgQSortingSupport, $smwgQRandSortingSupport;
 1006+
9301007 $result = array( 'LIMIT' => $query->getLimit() + 1, 'OFFSET' => $query->getOffset() );
931 - // build ORDER BY options using discovered sorting fields:
 1008+
 1009+ // Build ORDER BY options using discovered sorting fields.
9321010 if ( $smwgQSortingSupport ) {
9331011 $qobj = $this->m_queries[$rootid];
 1012+
9341013 foreach ( $this->m_sortkeys as $propkey => $order ) {
935 - if ( ( 'RANDOM' != $order ) && array_key_exists( $propkey, $qobj->sortfields ) ) { // field successfully added
936 - $result['ORDER BY'] = ( array_key_exists( 'ORDER BY', $result ) ? $result['ORDER BY'] . ', ':'' ) . $qobj->sortfields[$propkey] . " $order ";
 1014+ if ( ( 'RANDOM' != $order ) && array_key_exists( $propkey, $qobj->sortfields ) ) { // Field was successfully added.
 1015+ $result['ORDER BY'] = ( array_key_exists( 'ORDER BY', $result ) ? $result['ORDER BY'] . ', ' : '' ) . $qobj->sortfields[$propkey] . " $order ";
9371016 } elseif ( ( 'RANDOM' == $order ) && $smwgQRandSortingSupport ) {
938 - $result['ORDER BY'] = ( array_key_exists( 'ORDER BY', $result ) ? $result['ORDER BY'] . ', ':'' ) . ' RAND() ';
 1017+ $result['ORDER BY'] = ( array_key_exists( 'ORDER BY', $result ) ? $result['ORDER BY'] . ', ' : '' ) . ' RAND() ';
9391018 }
9401019 }
9411020 }

Follow-up revisions

RevisionCommit summaryAuthorDate
r66143Follow up to r66141jeroendedauw16:33, 10 May 2010

Status & tagging log