Index: trunk/extensions/SemanticMediaWiki/includes/SMW_QueryProcessor.php |
— | — | @@ -55,8 +55,12 @@ |
56 | 56 | * |
57 | 57 | * If an error occurs during parsing, an error-message is returned |
58 | 58 | * as a string. Otherwise an object of type SMWQuery is returned. |
| 59 | + * |
| 60 | + * The format string is used to specify the output format if already |
| 61 | + * known. Otherwise it will be determined from the parameters when |
| 62 | + * needed. This parameter is just for optimisation in a common case. |
59 | 63 | */ |
60 | | - static public function createQuery($querystring, $params, $inline = true) { |
| 64 | + static public function createQuery($querystring, $params, $inline = true, $format = '') { |
61 | 65 | // This should be the proper way of substituting templates in a safe and comprehensive way: |
62 | 66 | global $wgTitle; |
63 | 67 | $parser = new Parser(); |
— | — | @@ -80,6 +84,18 @@ |
81 | 85 | $desc->prependPrintRequest(new SMWPrintRequest(SMW_PRINT_THIS, $mainlabel)); |
82 | 86 | |
83 | 87 | $query = new SMWQuery($desc); |
| 88 | + if ($format == '') { |
| 89 | + $format = SMWQueryProcessor::getResultFormat($params); |
| 90 | + } |
| 91 | + switch ($format) { |
| 92 | + case 'count': |
| 93 | + $query->querymode = SMWQuery::MODE_COUNT; |
| 94 | + break; |
| 95 | + case 'debug': |
| 96 | + $query->querymode = SMWQuery::MODE_DEBUG; |
| 97 | + break; |
| 98 | + default: break; |
| 99 | + } |
84 | 100 | |
85 | 101 | //print '### Query:' . htmlspecialchars($desc->getQueryString()) . ' ###'; // DEBUG |
86 | 102 | |
— | — | @@ -92,10 +108,16 @@ |
93 | 109 | if ( !$inline && (array_key_exists('offset',$params)) && (is_int($params['offset'] + 0)) ) { |
94 | 110 | $query->offset = min($maxlimit - 1, max(0,$params['offset'] + 0)); //select integer between 0 and maximal limit -1 |
95 | 111 | } |
96 | | - // set limit small enough to stay in range with chosen offset |
97 | | - // it makes sense to have limit=0 in order to only show the link to the search special |
98 | | - if ( (array_key_exists('limit',$params)) && (is_int($params['limit'] + 0)) ) { |
99 | | - $query->limit = min($maxlimit - $query->offset, max(0,$params['limit'] + 0)); |
| 112 | + if ($query->querymode != SMWQuery::MODE_COUNT) { |
| 113 | + // set limit small enough to stay in range with chosen offset |
| 114 | + // it makes sense to have limit=0 in order to only show the link to the search special |
| 115 | + if ( (array_key_exists('limit',$params)) && (is_int($params['limit'] + 0)) ) { |
| 116 | + $query->limit = min($maxlimit - $query->offset, max(0,$params['limit'] + 0)); |
| 117 | + } else { |
| 118 | + $query->limit = $maxlimit; |
| 119 | + } |
| 120 | + } else { // largest possible limit for "count" |
| 121 | + $query->limit = $smwgIQMaxLimit; |
100 | 122 | } |
101 | 123 | if (array_key_exists('sort', $params)) { |
102 | 124 | $query->sort = true; |
— | — | @@ -117,13 +139,16 @@ |
118 | 140 | * being part of some special search page. |
119 | 141 | */ |
120 | 142 | static public function getResultHTML($querystring, $params, $inline = true) { |
121 | | - $query = SMWQueryProcessor::createQuery($querystring, $params, $inline); |
| 143 | + $format = SMWQueryProcessor::getResultFormat($params); |
| 144 | + $query = SMWQueryProcessor::createQuery($querystring, $params, $inline, $format); |
122 | 145 | if ($query instanceof SMWQuery) { // query parsing successful |
123 | | - $format = SMWQueryProcessor::getResultFormat($params); |
124 | | - /// TODO: incorporate the case $format=='debug' and $format=='count' into the following |
125 | 146 | $res = smwfGetStore()->getQueryResult($query); |
126 | | - $printer = SMWQueryProcessor::getResultPrinter($format, $inline, $res); |
127 | | - return $printer->getResultHTML($res, $params); |
| 147 | + if ($query->querymode == SMWQuery::MODE_INSTANCES) { |
| 148 | + $printer = SMWQueryProcessor::getResultPrinter($format, $inline, $res); |
| 149 | + return $printer->getResultHTML($res, $params); |
| 150 | + } else { // result for counting or debugging is just a string |
| 151 | + return $res; |
| 152 | + } |
128 | 153 | } else { // error string: return escaped version |
129 | 154 | return htmlspecialchars($query); ///TODO: improve error reporting format ... |
130 | 155 | } |
— | — | @@ -400,7 +425,6 @@ |
401 | 426 | } |
402 | 427 | switch ($value) { |
403 | 428 | case '*': // print statement |
404 | | - /// TODO: no support for selecting output unit yet |
405 | 429 | if ($chunk == '|') { |
406 | 430 | $label = $this->readChunk('\]\]'); |
407 | 431 | if ($label != ']]') { |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Description.php |
— | — | @@ -14,7 +14,7 @@ |
15 | 15 | define('SMW_CMP_ANY',5); // matches every datavalue of the given datatype and, if set, desired unit |
16 | 16 | |
17 | 17 | // print request |
18 | | -define('SMW_PRINT_CATS', 0); // print all direct categories of the current element |
| 18 | +define('SMW_PRINT_CATS', 0); // print all direct cateories of the current element |
19 | 19 | define('SMW_PRINT_RELS', 1); // print all relations objects of a certain relation of the current element |
20 | 20 | define('SMW_PRINT_ATTS', 2); // print all attribute values of a certain attribute of the current element |
21 | 21 | define('SMW_PRINT_THIS', 3); // print the current element |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Query.php |
— | — | @@ -19,13 +19,20 @@ |
20 | 20 | * additional settings). |
21 | 21 | */ |
22 | 22 | class SMWQuery { |
23 | | - protected $m_description; |
| 23 | + |
| 24 | + const MODE_INSTANCES = 1; |
| 25 | + const MODE_COUNT = 2; |
| 26 | + const MODE_DEBUG = 3; |
| 27 | + |
24 | 28 | public $limit = -1; |
25 | 29 | public $offset = 0; |
26 | 30 | public $sort = false; |
27 | 31 | public $ascending = true; |
28 | 32 | public $sortkey = false; |
| 33 | + public $querymode = SMWQuery::MODE_INSTANCES; |
29 | 34 | |
| 35 | + protected $m_description; |
| 36 | + |
30 | 37 | public function SMWQuery($description = NULL) { |
31 | 38 | $this->m_description = $description; |
32 | 39 | } |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_SQLStore.php |
— | — | @@ -534,8 +534,8 @@ |
535 | 535 | * are not "subqueries" from a user perspective, it also has a good insight in the query structure for |
536 | 536 | * applying structural limits) |
537 | 537 | * TODO: implement namespace restrictions |
538 | | - * TODO: do we support category wildcards? -> No, they have no useful semantics in OWL |
539 | 538 | * TODO: we now have sorting even for subquery conditions. Does this work? Is it slow/problematic? |
| 539 | + * NOTE: we do not support category wildcards, as they have no useful semantics in OWL/RDFS/LP/whatever |
540 | 540 | */ |
541 | 541 | function getQueryResult(SMWQuery $query) { |
542 | 542 | global $smwgIQSortingEnabled; |
— | — | @@ -576,11 +576,34 @@ |
577 | 577 | // print $this->m_sortkey . " --> " . $this->m_sortfield . "<br />\n"; //DEBUG |
578 | 578 | |
579 | 579 | // Execute query and format result as array |
| 580 | + if ($query->querymode == SMWQuery::MODE_COUNT) { |
| 581 | + $res = $db->select($from, |
| 582 | + 'COUNT(DISTINCT page.page_id) AS count', |
| 583 | + $where, |
| 584 | + 'SMW::getQueryResult', |
| 585 | + $sql_options ); |
| 586 | + $row = $db->fetchObject($res); |
| 587 | + return $row->count; |
| 588 | + } elseif ($query->querymode == SMWQuery::MODE_DEBUG) { |
| 589 | + list( $startOpts, $useIndex, $tailOpts ) = $db->makeSelectOptions( $sql_options ); |
| 590 | + $result = '<div style="border: 1px dotted black; background: #A1FB00; padding: 20px; ">' . |
| 591 | + '<b>SQL-Query</b><br />' . |
| 592 | + 'SELECT DISTINCT page.page_title as title, page.page_namespace as namespace' . |
| 593 | + ' FROM ' . $from . ' WHERE ' . $where . $tailOpts . '<br />' . |
| 594 | + '<b>SQL-Query options</b><br />'; |
| 595 | + foreach ($sql_options as $key => $value) { |
| 596 | + $result .= " $key=$value"; |
| 597 | + } |
| 598 | + $result .= '</div>'; |
| 599 | + return $result; |
| 600 | + } // else: continue |
| 601 | + |
580 | 602 | $res = $db->select($from, |
581 | 603 | 'DISTINCT page.page_title as title, page.page_namespace as namespace', |
582 | 604 | $where, |
583 | 605 | 'SMW::getQueryResult', |
584 | 606 | $sql_options ); |
| 607 | + |
585 | 608 | $qr = array(); |
586 | 609 | $count = 0; |
587 | 610 | while ( ( ($count<$query->limit) || ($query->limit < 0) ) && ($row = $db->fetchObject($res)) ) { |
— | — | @@ -593,7 +616,7 @@ |
594 | 617 | $db->freeResult($res); |
595 | 618 | |
596 | 619 | // Create result by executing print statements for everything that was fetched |
597 | | - ///TODO: use limit (and offset?) values |
| 620 | + ///TODO: use limit (and offset?) values for printouts? |
598 | 621 | $result = new SMWQueryResult($prs, ( ($count > $query->limit) && ($query->limit >= 0) ) ); |
599 | 622 | foreach ($qr as $qt) { |
600 | 623 | $row = array(); |
Index: trunk/extensions/SemanticMediaWiki/includes/storage/SMW_Store.php |
— | — | @@ -213,7 +213,10 @@ |
214 | 214 | ///// Query answering ///// |
215 | 215 | |
216 | 216 | /** |
217 | | - * Execute the provided query and return the result as an SMWQueryResult. |
| 217 | + * Execute the provided query and return the result as an SMWQueryResult if the query |
| 218 | + * was a usual instance retrieval query. In the case that the query asked for a plain |
| 219 | + * string (querymode MODE_COUNT or MODE_DEBUG) a plain wiki and HTML-compatible string |
| 220 | + * is returned. |
218 | 221 | */ |
219 | 222 | abstract function getQueryResult(SMWQuery $query); |
220 | 223 | |