Hi!

First I'd like to thank you for the great software that SMW is! SMW1.0
seem to be in pretty good form, too!

I tried to upgrade my server (which has some custom modifications to
SMW) and hit a limitation, which I'm not quite sure how to overcome.
Maybe you have some suggestions.

I'd like to query attributes in a way where the attribute either has a
certain value or is empty. My use-case:

I have a wiki for games, with each game encoding the number of players
possible in two attributes: minTeilnehmer and maxTeilnehmer.
Both of these may be empty, if there is no minimum number of players, or
if the number of players is unlimited.

Now I'd like to answer the question: If I have 10 people, which games
can I play? (Assuming that, if both attributes are available,
minTeilnehmer <= maxTeilnehmer)

As far as I know, this question cannot be answered currently in SMW.

I see several solutions to this problem:
1) Implement negations in queries - then I could ask "(NOT maxTeilnehmer <=
   9) AND (NOT minTeilnehmer >= 11)". I used this solution with SMW 0.7
   (patch below), but looking at the 1.0RC2 code, I'm not quite sure how
   to implement it cleanly.
2) Add a query that a certain property is not defined for a given page;
   I tried [[minTeilnehmer::!+]], but that doesn't work. If that worked,
   the query could be formulated as ([[minTeilnehmer::<10]]||
   [[minTeilnehmer::!+]]) ([[maxTeilnehmer::>10]][[maxTeilnehmer::!+]])
3) Set minTeilnehmer to 0 or 1 (OK) and set maxTeilnehmer to some large
   value (ugly). If SMW supported infinity (∞) as a value, this would be
   much nicer. Another possibility would be to set maxTeilnehmer to 0 in
   that case, use a disjunct query (0 OR >= 10) and hide the zero.

I'd prefer 1) over 2) over 3), but I'm not sure about the database
overhead for large tables - the implementation below uses a "NOT EXISTS
(SELECT * FROM $table WHERE $condition)" for the negation. I'm not
database guru, so no idea how bad this really is.

Any suggestions?

Thomas

BTW: You can see an example of the data at
http://spiele.j-crew.de/wiki/Kategorie:Quiz
The query interface is
http://spiele.j-crew.de/wiki/Spezial:Spielesuche
an example query is
http://spiele.j-crew.de/wiki/Spezial:Spielesuche?ort=Stadtspiel&teilnehmerzahl=10&leiterzahl=&gruppe=13-15J&suche=Suche
(Sorry, the server is quite slow right now)



PS: The code I used with SMW 0.7 is approximately:

--- a/includes/SMW_InlineQueries.php
+++ b/includes/SMW_InlineQueries.php
@@ -651,12 +669,19 @@ class SMWInlineQuery {
                                }
                        } elseif ( ($this->mConditionCount < 
$smwgIQMaxConditions) && ($this->mTableCount < $smwgIQMaxTables) ) { // 
conjunct is a real condition
                                $sq_title = '';
+                               $negated = false;
+                               $table = '';
+                               if (mb_substr($qparts[2],0,1) == '!') {
+                                       $negated = true;
+                                       $qparts[2] = mb_substr($qparts[2],1);
+                               }
+
                                if (mb_substr($qparts[2],0,1) == '+') { // 
sub-query or wildcard search
                                        $subq_id = mb_substr($qparts[2],1);
                                        if ( ('' != $subq_id) && 
(array_key_exists($subq_id,$this->mSubQueries)) ) {
                                                $sq = 
$this->parseQuery($this->mSubQueries[$subq_id]);
                                                if ( ('' != $sq->mConditions) 
&& ($this->mConditionCount < $smwgIQMaxConditions) && ($this->mTableCount < 
$smwgIQMaxTables) ) {
-                                                       $result->mTables .= ',' 
. $sq->mTables;
+                                                       $table = $sq->mTables;
                                                        if ( '' != 
$result->mConditions ) $result->mConditions .= ' AND ';
                                                        $result->mConditions .= 
'(' . $sq->mConditions . ')';
                                                        $sq_title = 
$sq->mSelect[1];
@@ -676,7 +701,7 @@ class SMWInlineQuery {
                                $curtable = 't' . $this->mRename++; // alias 
for the current table
 
                                if ($cat_sep == $op ) { // condition on 
category membership
-                                       $result->mTables .= ',' . 
$this->dbr->tableName('categorylinks') . " AS $curtable";
+                                       $table = 
$this->dbr->tableName('categorylinks') . " AS $curtable";
                                        $condition = 
"$pagetable.page_id=$curtable.cl_from";
                                        // TODO: make subcat-inclusion more 
efficient
                                        foreach ($values as $idx => $v) {
@@ -688,7 +713,7 @@ class SMWInlineQuery {
                                        }
                                } elseif ('::' == $op ) { // condition on 
relations
                                        $relation = 
smwfNormalTitleDBKey($qparts[0]);
-                                       $result->mTables .= ',' . 
$this->dbr->tableName('smw_relations') . " AS $curtable";
+                                       $table = 
$this->dbr->tableName('smw_relations') . " AS $curtable";
                                        $condition = 
"$pagetable.page_id=$curtable.subject_id AND $curtable.relation_title=" . 
$this->dbr->addQuotes($relation);
                                        if ('' != $sq_title) { // objects 
supplied by subquery
                                                $condition .= " AND 
$curtable.object_title=$sq_title AND $curtable.object_namespace=$sq_namespace";
@@ -761,7 +786,7 @@ class SMWInlineQuery {
                                                        }
                                                }
                                        }
-                                       $result->mTables .= ',' . 
$this->dbr->tableName('smw_attributes') . " AS $curtable";
+                                       $table = 
$this->dbr->tableName('smw_attributes') . " AS $curtable";
                                        $condition = 
"$pagetable.page_id=$curtable.subject_id AND $curtable.attribute_title=" . 
$this->dbr->addQuotes($attribute);
                                        if ($attribute == $this->mSortkey) {
                                                if ($av->isNumeric()) 
$result->mOrderBy = $curtable . '.value_num';
@@ -788,7 +813,12 @@ class SMWInlineQuery {
                                        if ('' != $result->mConditions) 
$result->mConditions .= ' AND ';
                                        $this->mConditionCount++;
                                        $this->mTableCount++;
-                                       $result->mConditions .= $condition;
+                                       if ($negated) {
+                                               $result->mConditions .= " NOT 
EXISTS (SELECT * FROM $table WHERE $condition)";
+                                       } else {
+                                               $result->mConditions .= 
$condition;
+                                               if ('' != $table) 
$result->mTables .= ','. $table;
+                                       }
                                }
                        }
                }

-------------------------------------------------------------------------
This SF.net email is sponsored by: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Semediawiki-devel mailing list
Semediawiki-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/semediawiki-devel

Reply via email to