/**
  * Create a new SMWSQLStore2Query object that can be used to obtain results
  * for the given description. The result is stored in $this->m_queries
  * using a numeric key that is returned as a result of the function.
  * Returns -1 if no query was created.
  * @todo The case of nominal classes (top-level SMWValueDescription) still
  * makes some assumptions about the table structure, especially about the
  * name of the joinfield (o_id). Better extend compileAttributeWhere to
  * deal with this case.
  *
  * @param SMWDescription $description
  *
  * @return integer
  */
 protected function compileQueries(SMWDescription $description)
 {
     $qid = SMWSQLStore2Query::$qnum;
     $query = new SMWSQLStore2Query();
     if ($description instanceof SMWSomeProperty) {
         $this->compilePropertyCondition($query, $description->getProperty(), $description->getDescription());
         // Compilation has set type to NOQUERY: drop condition.
         if ($query->type == SMW_SQL2_NOQUERY) {
             $qid = -1;
         }
     } elseif ($description instanceof SMWNamespaceDescription) {
         // TODO: One instance of smw_ids on s_id always suffices (swm_id is KEY)! Doable in execution ... (PERFORMANCE)
         $query->jointable = 'smw_ids';
         $query->joinfield = "{$query->alias}.smw_id";
         $query->where = "{$query->alias}.smw_namespace=" . $this->m_dbs->addQuotes($description->getNamespace());
     } elseif ($description instanceof SMWConjunction || $description instanceof SMWDisjunction) {
         $query->type = $description instanceof SMWConjunction ? SMW_SQL2_CONJUNCTION : SMW_SQL2_DISJUNCTION;
         foreach ($description->getDescriptions() as $subdesc) {
             $sub = $this->compileQueries($subdesc);
             if ($sub >= 0) {
                 $query->components[$sub] = true;
             }
         }
         // All subconditions failed, drop this as well.
         if (count($query->components) == 0) {
             $qid = -1;
         }
     } elseif ($description instanceof SMWClassDescription) {
         $cqid = SMWSQLStore2Query::$qnum;
         $cquery = new SMWSQLStore2Query();
         $cquery->type = SMW_SQL2_CLASS_HIERARCHY;
         $cquery->joinfield = array();
         foreach ($description->getCategories() as $cat) {
             $cid = $this->m_store->getSMWPageID($cat->getDBkey(), NS_CATEGORY, $cat->getInterwiki());
             if ($cid != 0) {
                 $cquery->joinfield[] = $cid;
             }
         }
         if (count($cquery->joinfield) == 0) {
             // Empty result.
             $query->type = SMW_SQL2_VALUE;
             $query->jointable = '';
             $query->joinfield = '';
         } else {
             // Instance query with dicjunction of classes (categories)
             $query->jointable = 'smw_inst2';
             $query->joinfield = "{$query->alias}.s_id";
             $query->components[$cqid] = "{$query->alias}.o_id";
             $this->m_queries[$cqid] = $cquery;
         }
     } elseif ($description instanceof SMWValueDescription) {
         // Only type '_wpg' objects can appear on query level (essentially as nominal classes).
         if ($description->getDatavalue()->getTypeID() == '_wpg') {
             if ($description->getComparator() == SMW_CMP_EQ) {
                 $query->type = SMW_SQL2_VALUE;
                 $oid = $this->m_store->getSMWPageID($description->getDatavalue()->getDBkey(), $description->getDatavalue()->getNamespace(), $description->getDatavalue()->getInterwiki());
                 $query->joinfield = array($oid);
             } else {
                 // Join with smw_ids needed for other comparators (apply to title string).
                 $query->jointable = 'smw_ids';
                 $query->joinfield = "{$query->alias}.smw_id";
                 $value = $description->getDatavalue()->getSortkey();
                 switch ($description->getComparator()) {
                     case SMW_CMP_LEQ:
                         $comp = '<=';
                         break;
                     case SMW_CMP_GEQ:
                         $comp = '>=';
                         break;
                     case SMW_CMP_NEQ:
                         $comp = '!=';
                         break;
                     case SMW_CMP_LIKE:
                     case SMW_CMP_NLKE:
                         $comp = ' LIKE ';
                         if ($description->getComparator() == SMW_CMP_NLKE) {
                             $comp = " NOT{$comp}";
                         }
                         $value = str_replace(array('%', '_', '*', '?'), array('\\%', '\\_', '%', '_'), $value);
                         break;
                 }
                 $query->where = "{$query->alias}.smw_sortkey{$comp}" . $this->m_dbs->addQuotes($value);
             }
         }
     } elseif ($description instanceof SMWConceptDescription) {
         // fetch concept definition and insert it here
         $cid = $this->m_store->getSMWPageID($description->getConcept()->getDBkey(), SMW_NS_CONCEPT, '');
         $row = $this->m_dbs->selectRow('smw_conc2', array('concept_txt', 'concept_features', 'concept_size', 'concept_depth', 'cache_date'), array('s_id' => $cid), 'SMWSQLStore2Queries::compileQueries');
         if ($row === false) {
             // No description found, concept does not exist.
             // keep the above query object, it yields an empty result
             // TODO: announce an error here? (maybe not, since the query processor can check for
             // non-existing concept pages which is probably the main reason for finding nothing here)
         } else {
             global $smwgQConceptCaching, $smwgQMaxSize, $smwgQMaxDepth, $smwgQFeatures, $smwgQConceptCacheLifetime;
             $may_be_computed = $smwgQConceptCaching == CONCEPT_CACHE_NONE || $smwgQConceptCaching == CONCEPT_CACHE_HARD && ~(~($row->concept_features + 0) | $smwgQFeatures) == 0 && $smwgQMaxSize >= $row->concept_size && $smwgQMaxDepth >= $row->concept_depth;
             if ($row->cache_date && ($row->cache_date > strtotime("now") - $smwgQConceptCacheLifetime * 60 || !$may_be_computed)) {
                 // Cached concept, use cache unless it is dead and can be revived.
                 $query->jointable = 'smw_conccache';
                 $query->joinfield = "{$query->alias}.s_id";
                 $query->where = "{$query->alias}.o_id=" . $this->m_dbs->addQuotes($cid);
             } elseif ($row->concept_txt) {
                 // Parse description and process it recursively.
                 if ($may_be_computed) {
                     $qp = new SMWQueryParser();
                     // No defaultnamespaces here; If any, these are already in the concept.
                     $desc = $qp->getQueryDescription($row->concept_txt);
                     $qid = $this->compileQueries($desc);
                     if ($qid != -1) {
                         $query = $this->m_queries[$qid];
                     } else {
                         // somehow the concept query is no longer valid; maybe some syntax changed (upgrade) or global settings were modified since storing it
                         smwfLoadExtensionMessages('SemanticMediaWiki');
                         $this->m_errors[] = wfMsg('smw_emptysubquery');
                         // not quite the right message, but this case is very rare; let us not make detailed messages for this
                     }
                 } else {
                     smwfLoadExtensionMessages('SemanticMediaWiki');
                     $this->m_errors[] = wfMsg('smw_concept_cache_miss', $description->getConcept()->getText());
                 }
             }
             // else: no cache, no description (this may happen); treat like empty concept
         }
     } else {
         // (e.g. SMWThingDescription)
         $qid = -1;
         // no condition
     }
     if ($qid >= 0) {
         // Success, keep query object, propagate sortkeys from subqueries.
         $this->m_queries[$qid] = $query;
         if ($query->type != SMW_SQL2_DISJUNCTION) {
             // Sortkeys are killed by disjunctions (not all parts may have them),
             // NOTE: preprocessing might try to push disjunctions downwards to safe sortkey, but this seems to be minor
             foreach ($query->components as $cid => $field) {
                 $query->sortfields = array_merge($this->m_queries[$cid]->sortfields, $query->sortfields);
             }
         }
     }
     return $qid;
 }
	public function addDescription( SMWDescription $description ) {
		if ( ! ( $description instanceof SMWThingDescription ) ) {
			if ( $description instanceof SMWConjunction ) { // absorb sub-conjunctions
				foreach ( $description->getDescriptions() as $subdesc ) {
					$this->m_descriptions[] = $subdesc;
				}
			} else {
				$this->m_descriptions[] = $description;
			}
			
			// move print descriptions downwards
			///TODO: This may not be a good solution, since it does modify $description and since it does not react to future changes
			$this->m_printreqs = array_merge( $this->m_printreqs, $description->getPrintRequests() );
			$description->setPrintRequests( array() );
		}
	}
예제 #3
0
 /**
  * Given an SMWDescription that is just a conjunction or disjunction of
  * SMWValueDescription objects, create a plain WHERE condition string for it.
  */
 protected function compileAttributeWhere(SMWDescription $description, $jointable)
 {
     if ($description instanceof SMWValueDescription) {
         $dv = $description->getDatavalue();
         if (SMWSQLStore2::getStorageMode($dv->getTypeID()) == SMW_SQL2_SPEC2) {
             $keys = $dv->getDBkeys();
             $value = $keys[0];
             $field = "{$jointable}.value_string";
         } else {
             // should be SMW_SQL2_ATTS2
             if ($dv->isNumeric()) {
                 $value = $dv->getNumericValue();
                 $field = "{$jointable}.value_num";
             } else {
                 $keys = $dv->getDBkeys();
                 $value = $keys[0];
                 $field = "{$jointable}.value_xsd";
             }
         }
         switch ($description->getComparator()) {
             case SMW_CMP_LEQ:
                 $comp = '<=';
                 break;
             case SMW_CMP_GEQ:
                 $comp = '>=';
                 break;
             case SMW_CMP_NEQ:
                 $comp = '!=';
                 break;
             case SMW_CMP_LIKE:
                 if ($dv->getTypeID() == '_str') {
                     $comp = ' LIKE ';
                     $value = str_replace(array('%', '_', '*', '?'), array('\\%', '\\_', '%', '_'), $value);
                 } else {
                     // LIKE only supported for strings
                     $comp = '=';
                 }
                 break;
             case SMW_CMP_EQ:
             default:
                 $comp = '=';
                 break;
         }
         $result = "{$field}{$comp}" . $this->m_dbs->addQuotes($value);
     } elseif ($description instanceof SMWConjunction || $description instanceof SMWDisjunction) {
         $op = $description instanceof SMWConjunction ? ' AND ' : ' OR ';
         $result = '';
         foreach ($description->getDescriptions() as $subdesc) {
             $result = $result . ($result != '' ? $op : '') . $this->compileAttributeWhere($subdesc, $jointable);
         }
         $result = "({$result})";
     } else {
         $result = '';
     }
     return $result;
 }