Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore2_Queries.php |
— | — | @@ -29,8 +29,18 @@ |
30 | 30 | public $from = ''; |
31 | 31 | public $where = ''; |
32 | 32 | 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(); |
35 | 45 | |
36 | 46 | public static $qnum = 0; |
37 | 47 | |
— | — | @@ -167,13 +177,15 @@ |
168 | 178 | * processing -- not all DBMS might be able in seeing this by themselves. |
169 | 179 | */ |
170 | 180 | public function getQueryResult( SMWQuery $query ) { |
171 | | - global $smwgIgnoreQueryErrors; |
| 181 | + global $smwgIgnoreQueryErrors, $smwgQSortingSupport; |
| 182 | + |
172 | 183 | if ( !$smwgIgnoreQueryErrors && ( $query->querymode != SMWQuery::MODE_DEBUG ) && ( count( $query->getErrors() ) > 0 ) ) { |
173 | 184 | return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false ); |
174 | 185 | // NOTE: We currently check this only once since the below steps do not create further errors |
175 | 186 | } elseif ( $query->querymode == SMWQuery::MODE_NONE ) { // don't query, but return something to printer |
176 | 187 | return new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, true ); |
177 | 188 | } |
| 189 | + |
178 | 190 | $this->m_qmode = $query->querymode; |
179 | 191 | $this->m_queries = array(); |
180 | 192 | $this->m_hierarchies = array(); |
— | — | @@ -186,6 +198,7 @@ |
187 | 199 | wfProfileIn( 'SMWSQLStore2Queries::compileMainQuery (SMW)' ); |
188 | 200 | $qid = $this->compileQueries( $query->getDescription() ); // compile query, build query "plan" |
189 | 201 | wfProfileOut( 'SMWSQLStore2Queries::compileMainQuery (SMW)' ); |
| 202 | + |
190 | 203 | if ( $qid < 0 ) { // no valid/supported condition; ensure that at least only proper pages are delivered |
191 | 204 | $qid = SMWSQLStore2Query::$qnum; |
192 | 205 | $q = new SMWSQLStore2Query(); |
— | — | @@ -194,6 +207,7 @@ |
195 | 208 | $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 ); |
196 | 209 | $this->m_queries[$qid] = $q; |
197 | 210 | } |
| 211 | + |
198 | 212 | if ( $this->m_queries[$qid]->jointable != 'smw_ids' ) { |
199 | 213 | // manually make final root query (to retrieve namespace,title): |
200 | 214 | $rootid = SMWSQLStore2Query::$qnum; |
— | — | @@ -206,13 +220,17 @@ |
207 | 221 | } else { // not such a common case, but worth avoiding the additional inner join: |
208 | 222 | $rootid = $qid; |
209 | 223 | } |
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 | + } |
212 | 229 | |
213 | 230 | // *** Now execute the computed query ***// |
214 | 231 | wfProfileIn( 'SMWSQLStore2Queries::executeMainQuery (SMW)' ); |
215 | 232 | $this->executeQueries( $this->m_queries[$rootid] ); // execute query tree, resolve all dependencies |
216 | 233 | wfProfileOut( 'SMWSQLStore2Queries::executeMainQuery (SMW)' ); |
| 234 | + |
217 | 235 | switch ( $query->querymode ) { |
218 | 236 | case SMWQuery::MODE_DEBUG: |
219 | 237 | $result = $this->getDebugQueryResult( $query, $rootid ); |
— | — | @@ -224,25 +242,33 @@ |
225 | 243 | $result = $this->getInstanceQueryResult( $query, $rootid ); |
226 | 244 | break; |
227 | 245 | } |
| 246 | + |
228 | 247 | $this->cleanUp(); |
229 | 248 | $query->addErrors( $this->m_errors ); |
| 249 | + |
230 | 250 | return $result; |
231 | 251 | } |
232 | 252 | |
233 | 253 | /** |
234 | 254 | * Using a preprocessed internal query description referenced by $rootid, compute |
235 | 255 | * the proper debug output for the given query. |
| 256 | + * |
| 257 | + * @param SMWQuery $query |
| 258 | + * @param $rootid |
236 | 259 | */ |
237 | | - protected function getDebugQueryResult( $query, $rootid ) { |
| 260 | + protected function getDebugQueryResult( SMWQuery $query, $rootid ) { |
238 | 261 | $qobj = $this->m_queries[$rootid]; |
239 | 262 | $sql_options = $this->getSQLOptions( $query, $rootid ); |
| 263 | + |
240 | 264 | list( $startOpts, $useIndex, $tailOpts ) = $this->m_dbs->makeSelectOptions( $sql_options ); |
| 265 | + |
241 | 266 | $result = '<div style="border: 1px dotted black; background: #A1FB00; padding: 20px; ">' . |
242 | 267 | '<b>Debug output by SMWSQLStore2</b><br />' . |
243 | 268 | 'Generated Wiki-Query<br /><tt>' . |
244 | 269 | str_replace( '[', '[', $query->getDescription()->getQueryString() ) . '</tt><br />' . |
245 | 270 | 'Query-Size: ' . $query->getDescription()->getSize() . '<br />' . |
246 | 271 | 'Query-Depth: ' . $query->getDescription()->getDepth() . '<br />'; |
| 272 | + |
247 | 273 | if ( $qobj->joinfield !== '' ) { |
248 | 274 | $result .= 'SQL query<br />' . |
249 | 275 | "<tt>SELECT DISTINCT $qobj->alias.smw_title AS t,$qobj->alias.smw_namespace AS ns FROM " . |
— | — | @@ -252,21 +278,29 @@ |
253 | 279 | } else { |
254 | 280 | $result .= '<b>Empty result, no SQL query created.</b>'; |
255 | 281 | } |
| 282 | + |
256 | 283 | $errors = ''; |
| 284 | + |
257 | 285 | foreach ( $query->getErrors() as $error ) { |
258 | 286 | $errors .= $error . '<br />'; |
259 | 287 | } |
| 288 | + |
260 | 289 | $result .= ( $errors ) ? "<br />Errors and warnings:<br />$errors":'<br />No errors or warnings.'; |
261 | 290 | $auxtables = ''; |
| 291 | + |
262 | 292 | foreach ( $this->m_querylog as $table => $log ) { |
263 | 293 | $auxtables .= "<li>Temporary table $table"; |
| 294 | + |
264 | 295 | foreach ( $log as $q ) { |
265 | 296 | $auxtables .= "<br /> <tt>$q</tt>"; |
266 | 297 | } |
| 298 | + |
267 | 299 | $auxtables .= '</li>'; |
268 | 300 | } |
| 301 | + |
269 | 302 | $result .= ( $auxtables ) ? "<br />Auxilliary tables used:<ul>$auxtables</ul>":'<br />No auxilliary tables used.'; |
270 | 303 | $result .= '</div>'; |
| 304 | + |
271 | 305 | return $result; |
272 | 306 | } |
273 | 307 | |
— | — | @@ -302,38 +336,54 @@ |
303 | 337 | * "limit" results although there would have been "limit" really distinct results. For |
304 | 338 | * this reason, we select sortfields only for POSTGRES. MySQL is able to perform what |
305 | 339 | * 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 |
306 | 345 | */ |
307 | | - protected function getInstanceQueryResult( $query, $rootid ) { |
| 346 | + protected function getInstanceQueryResult( SMWQuery $query, $rootid ) { |
308 | 347 | global $wgDBtype; |
| 348 | + |
309 | 349 | wfProfileIn( 'SMWSQLStore2Queries::getInstanceQueryResult (SMW)' ); |
310 | 350 | $qobj = $this->m_queries[$rootid]; |
| 351 | + |
311 | 352 | if ( $qobj->joinfield === '' ) { // empty result, no query needed |
312 | 353 | $result = new SMWQueryResult( $query->getDescription()->getPrintrequests(), $query, array(), $this->m_store, false ); |
313 | 354 | wfProfileOut( 'SMWSQLStore2Queries::getInstanceQueryResult (SMW)' ); |
314 | 355 | return $result; |
315 | 356 | } |
| 357 | + |
316 | 358 | $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 | + |
318 | 363 | $res = $this->m_dbs->select( $this->m_dbs->tableName( $qobj->jointable ) . " AS $qobj->alias" . $qobj->from, |
319 | 364 | "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 ) : '' ), |
321 | 366 | $qobj->where, 'SMW::getQueryResult', $sql_options ); |
322 | 367 | |
323 | 368 | $qr = array(); |
324 | 369 | $count = 0; |
325 | 370 | $prs = $query->getDescription()->getPrintrequests(); |
| 371 | + |
326 | 372 | while ( ( $count < $query->getLimit() ) && ( $row = $this->m_dbs->fetchObject( $res ) ) ) { |
327 | 373 | $count++; |
328 | 374 | $v = SMWWikiPageValue::makePage( $row->t, $row->ns, $row->sortkey ); |
329 | 375 | $qr[] = $v; |
330 | 376 | $this->m_store->cacheSMWPageID( $row->id, $row->t, $row->ns, $row->iw ); |
331 | 377 | } |
| 378 | + |
332 | 379 | if ( $this->m_dbs->fetchObject( $res ) ) { |
333 | 380 | $count++; |
334 | 381 | } |
| 382 | + |
335 | 383 | $this->m_dbs->freeResult( $res ); |
336 | 384 | $result = new SMWQueryResult( $prs, $query, $qr, $this->m_store, ( $count > $query->getLimit() ) ); |
| 385 | + |
337 | 386 | wfProfileOut( 'SMWSQLStore2Queries::getInstanceQueryResult (SMW)' ); |
| 387 | + |
338 | 388 | return $result; |
339 | 389 | } |
340 | 390 | |
— | — | @@ -346,6 +396,10 @@ |
347 | 397 | * makes some assumptions about the table structure, especially about the |
348 | 398 | * name of the joinfield (o_id). Better extend compileAttributeWhere to |
349 | 399 | * deal with this case. |
| 400 | + * |
| 401 | + * @param SMWDescription $description |
| 402 | + * |
| 403 | + * @return integer |
350 | 404 | */ |
351 | 405 | protected function compileQueries( SMWDescription $description ) { |
352 | 406 | $qid = SMWSQLStore2Query::$qnum; |
— | — | @@ -384,6 +438,7 @@ |
385 | 439 | $cquery->joinfield[] = $cid; |
386 | 440 | } |
387 | 441 | } |
| 442 | + |
388 | 443 | if ( count( $cquery->joinfield ) == 0 ) { // Empty result. |
389 | 444 | $query->type = SMW_SQL2_VALUE; |
390 | 445 | $query->jointable = ''; |
— | — | @@ -404,6 +459,7 @@ |
405 | 460 | $query->jointable = 'smw_ids'; |
406 | 461 | $query->joinfield = "$query->alias.smw_id"; |
407 | 462 | $value = $description->getDatavalue()->getSortkey(); |
| 463 | + |
408 | 464 | switch ( $description->getComparator() ) { |
409 | 465 | case SMW_CMP_LEQ: $comp = '<='; break; |
410 | 466 | case SMW_CMP_GEQ: $comp = '>='; break; |
— | — | @@ -413,33 +469,40 @@ |
414 | 470 | $value = str_replace( array( '%', '_', '*', '?' ), array( '\%', '\_', '%', '_' ), $value ); |
415 | 471 | break; |
416 | 472 | } |
| 473 | + |
417 | 474 | $query->where = "$query->alias.smw_sortkey$comp" . $this->m_dbs->addQuotes( $value ); |
418 | 475 | } |
419 | 476 | } |
420 | 477 | } elseif ( $description instanceof SMWConceptDescription ) { // fetch concept definition and insert it here |
421 | 478 | $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 | + |
425 | 486 | if ( $row === false ) { // No description found, concept does not exist. |
426 | 487 | // keep the above query object, it yields an empty result |
427 | 488 | // TODO: announce an error here? (maybe not, since the query processor can check for |
428 | 489 | // non-existing concept pages which is probably the main reason for finding nothing here |
429 | 490 | } else { |
430 | 491 | global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime; |
| 492 | + |
431 | 493 | $may_be_computed = ( $smwgQConceptCaching == CONCEPT_CACHE_NONE ) || |
432 | 494 | ( ( $smwgQConceptCaching == CONCEPT_CACHE_HARD ) && ( ( ~( ~( $row->concept_features + 0 ) | $smwgQFeatures ) ) == 0 ) && |
433 | 495 | ( $smwgQMaxSize >= $row->concept_size ) && ( $smwgQMaxDepth >= $row->concept_depth ) ); |
| 496 | + |
434 | 497 | if ( $row->cache_date && |
435 | 498 | ( ( $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. |
437 | 500 | $query->jointable = 'smw_conccache'; |
438 | 501 | $query->joinfield = "$query->alias.s_id"; |
439 | 502 | $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. |
441 | 504 | if ( $may_be_computed ) { |
442 | 505 | $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. |
444 | 507 | $desc = $qp->getQueryDescription( $row->concept_txt ); |
445 | 508 | $qid = $this->compileQueries( $desc ); |
446 | 509 | $query = $this->m_queries[$qid]; |
— | — | @@ -453,15 +516,16 @@ |
454 | 517 | $qid = - 1; // no condition |
455 | 518 | } |
456 | 519 | |
457 | | - if ( $qid >= 0 ) { // success, keep query object, propagate sortkeys from subqueries |
| 520 | + if ( $qid >= 0 ) { // Success, keep query object, propagate sortkeys from subqueries. |
458 | 521 | $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), |
460 | 523 | // NOTE: preprocessing might try to push disjunctions downwards to safe sortkey, but this seems to be minor |
461 | 524 | foreach ( $query->components as $cid => $field ) { |
462 | 525 | $query->sortfields = array_merge( $this->m_queries[$cid]->sortfields, $query->sortfields ); |
463 | 526 | } |
464 | 527 | } |
465 | 528 | } |
| 529 | + |
466 | 530 | return $qid; |
467 | 531 | } |
468 | 532 | |
— | — | @@ -472,29 +536,35 @@ |
473 | 537 | * to check for this and discard the query in this case. |
474 | 538 | * @todo Check if hierarchy queries work as expected. |
475 | 539 | */ |
476 | | - protected function compilePropertyCondition( $query, $property, SMWDescription $valuedesc ) { |
| 540 | + protected function compilePropertyCondition( SMWSQLStore2Query $query, $property, SMWDescription $valuedesc ) { |
477 | 541 | $tableid = SMWSQLStore2::findPropertyTableID( $property ); |
| 542 | + |
478 | 543 | if ( $tableid == '' ) { // probably a type-polymorphic property |
479 | 544 | $typeid = $valuedesc->getTypeID(); |
480 | 545 | $tableid = SMWSQLStore2::findTypeTableID( $typeid ); |
481 | 546 | } else { // normal property |
482 | 547 | $typeid = $property->getPropertyTypeID(); |
483 | 548 | } |
| 549 | + |
484 | 550 | if ( $tableid == '' ) { // Still no table to query? Give up. |
485 | 551 | $query->type = SMW_SQL2_NOQUERY; |
486 | 552 | return; |
487 | 553 | } |
| 554 | + |
488 | 555 | $proptables = SMWSQLStore2::getPropertyTables(); |
489 | 556 | $proptable = $proptables[$tableid]; |
| 557 | + |
490 | 558 | if ( !$proptable->idsubject ) { // no queries with such tables (there is really no demand, as only redirects are affected) |
491 | 559 | $query->type = SMW_SQL2_NOQUERY; |
492 | 560 | return; |
493 | 561 | } |
| 562 | + |
494 | 563 | list( $sig, $valueindexes, $labelindexes ) = SMWSQLStore2::getTypeSignature( $typeid ); |
495 | 564 | $sortkey = $property->getDBkey(); // TODO: strictly speaking, the DB key is not what we want here, since sortkey is based on a "wiki value" |
496 | 565 | |
497 | 566 | // *** Basic settings: table, joinfield, and objectfields ***// |
498 | 567 | $query->jointable = $proptable->name; |
| 568 | + |
499 | 569 | if ( $property->isInverse() ) { // see if we can support inverses by inverting the proptable data |
500 | 570 | if ( ( count( $proptable->objectfields ) == 1 ) && ( reset( $proptable->objectfields ) == 'p' ) ) { |
501 | 571 | $query->joinfield = $query->alias . '.' . reset( array_keys( $proptable->objectfields ) ); |
— | — | @@ -512,6 +582,7 @@ |
513 | 583 | // *** Add conditions for selecting rows for this property, maybe with a hierarchy ***// |
514 | 584 | if ( $proptable->fixedproperty == false ) { |
515 | 585 | $pid = $this->m_store->getSMWPropertyID( $property ); |
| 586 | + |
516 | 587 | if ( !$property->getPropertyID() || ( $property->getPropertyTypeID() != '__err' ) ) { |
517 | 588 | // also make property hierarchy (may or may not be executed later on) |
518 | 589 | // exclude type-polymorphic properties _1, _2, ... (2nd check above suffices, but 1st is faster to check) |
— | — | @@ -531,6 +602,7 @@ |
532 | 603 | if ( ( count( $objectfields ) == 1 ) && ( reset( $objectfields ) == 'p' ) ) { // page description, process like main query |
533 | 604 | $sub = $this->compileQueries( $valuedesc ); |
534 | 605 | $objectfield = reset( array_keys( $objectfields ) ); |
| 606 | + |
535 | 607 | if ( $sub >= 0 ) { |
536 | 608 | $query->components[$sub] = "{$query->alias}.{$objectfield}"; |
537 | 609 | } |
— | — | @@ -549,6 +621,7 @@ |
550 | 622 | // type's signature. Thankfully, signatures are short so this iteration is not notable. |
551 | 623 | $smwidjoinfield = false; |
552 | 624 | $fieldNames = $this->getDBFieldsForDVIndexes( $objectfields, $valueindexes, $smwidjoinfield ); |
| 625 | + |
553 | 626 | if ( $fieldNames ) { // TODO //.// |
554 | 627 | if ( $smwidjoinfield ) { |
555 | 628 | // TODO: is this smw_ids possibly duplicated in the query? Can we prevent that? (PERFORMANCE) |
— | — | @@ -886,37 +959,40 @@ |
887 | 960 | * This function modifies the given query object at $qid to account for all ordering conditions |
888 | 961 | * in the SMWQuery $query. It is always required that $qid is the id of a query that joins with |
889 | 962 | * smw_ids so that the field alias.smw_title is $available for default sorting. |
| 963 | + * |
| 964 | + * @param $qid |
890 | 965 | */ |
891 | | - protected function applyOrderConditions( $query, $qid ) { |
892 | | - global $smwgQSortingSupport; |
893 | | - if ( !$smwgQSortingSupport ) { |
894 | | - return; |
895 | | - } |
| 966 | + protected function applyOrderConditions( $qid ) { |
896 | 967 | $qobj = $this->m_queries[$qid]; |
897 | 968 | // (1) collect required extra property descriptions: |
898 | 969 | $extraproperties = array(); |
| 970 | + |
899 | 971 | 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). |
902 | 974 | $qobj->sortfields[$propkey] = "$qobj->alias.smw_sortkey"; |
903 | | - } else { // try to extend query |
| 975 | + } else { // Try to extend query. |
904 | 976 | $extrawhere = ''; |
905 | 977 | $sortprop = SMWPropertyValue::makeUserProperty( $propkey ); |
| 978 | + |
906 | 979 | if ( $sortprop->isValid() ) { |
907 | 980 | $extraproperties[] = new SMWSomeProperty( $sortprop, new SMWThingDescription() ); |
908 | 981 | } |
909 | 982 | } |
910 | 983 | } |
911 | 984 | } |
| 985 | + |
912 | 986 | // (2) compile according conditions and hack them into $qobj: |
913 | 987 | if ( count( $extraproperties ) > 0 ) { |
914 | 988 | $desc = new SMWConjunction( $extraproperties ); |
915 | 989 | $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 | + |
917 | 992 | foreach ( $newqobj->components as $cid => $field ) { // ... so just re-wire its dependencies |
918 | 993 | $qobj->components[$cid] = $qobj->joinfield; |
919 | 994 | $qobj->sortfields = array_merge( $qobj->sortfields, $this->m_queries[$cid]->sortfields ); |
920 | 995 | } |
| 996 | + |
921 | 997 | $this->m_queries[$qid] = $qobj; |
922 | 998 | } |
923 | 999 | } |
— | — | @@ -924,17 +1000,20 @@ |
925 | 1001 | /** |
926 | 1002 | * Get a SQL option array for the given query and preprocessed query object at given id. |
927 | 1003 | */ |
928 | | - protected function getSQLOptions( $query, $rootid ) { |
| 1004 | + protected function getSQLOptions( SMWQuery $query, $rootid ) { |
929 | 1005 | global $smwgQSortingSupport, $smwgQRandSortingSupport; |
| 1006 | + |
930 | 1007 | $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. |
932 | 1010 | if ( $smwgQSortingSupport ) { |
933 | 1011 | $qobj = $this->m_queries[$rootid]; |
| 1012 | + |
934 | 1013 | 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 "; |
937 | 1016 | } 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() '; |
939 | 1018 | } |
940 | 1019 | } |
941 | 1020 | } |