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