/** * Returns the set of SQL values needed to insert the data for this * internal object into the database. */ function getStorageSQL($internalObject) { if (method_exists('SMWDIWikiPage', 'getSubobjectName')) { // SMW 1.6 $ioID = $this->makeSMWPageID($internalObject->getName(), $internalObject->getNamespace(), '', ''); } else { $ioID = $this->makeSMWPageID($internalObject->getName(), $internalObject->getNamespace(), ''); } $upRels2 = array(); $upAtts2 = array(); $upText2 = array(); $upCoords = array(); // set all the properties pointing from this internal object foreach ($internalObject->getPropertyValuePairs() as $propertyValuePair) { list($property, $value) = $propertyValuePair; $tableid = SMWSQLStore2::findPropertyTableID($property); $isRelation = $tableid == 'smw_rels2'; $isAttribute = $tableid == 'smw_atts2'; $isText = $tableid == 'smw_text2'; $isCoords = $tableid == 'smw_coords'; if ($isRelation) { if (method_exists('SMWDIWikiPage', 'getSubobjectName')) { // SMW 1.6 $mainPageID = $this->makeSMWPageID($value->getDBkey(), $value->getNamespace(), $value->getInterwiki(), ''); } else { $mainPageID = $this->makeSMWPageID($value->getDBkey(), $value->getNamespace(), $value->getInterwiki()); } $upRels2[] = array('s_id' => $ioID, 'p_id' => $this->makeSMWPropertyID($property), 'o_id' => $mainPageID); } elseif ($isAttribute) { if (class_exists('SMWCompatibilityHelpers')) { // SMW 1.6 $dataItem = $value->getDataItem(); $keys = SMWCompatibilityHelpers::getDBkeysFromDataItem($dataItem); $valueNum = $dataItem->getSortKey(); } else { $keys = $value->getDBkeys(); if (method_exists($value, 'getValueKey')) { $valueNum = $value->getValueKey(); } else { $valueNum = $value->getNumericValue(); } } $upAttr = array('s_id' => $ioID, 'p_id' => $this->makeSMWPropertyID($property), 'value_xsd' => $keys[0], 'value_num' => $valueNum); // 'value_unit' DB field was removed in SMW 1.6 if (version_compare(SMW_VERSION, '1.6 alpha', '<')) { $upAttr['value_unit'] = $value->getUnit(); } $upAtts2[] = $upAttr; } elseif ($isText) { if (method_exists($value, 'getShortWikiText')) { // SMW 1.6 $key = $value->getShortWikiText(); } else { $keys = $value->getDBkeys(); $key = $keys[0]; } $upText2[] = array('s_id' => $ioID, 'p_id' => $this->makeSMWPropertyID($property), 'value_blob' => $key); } elseif ($isCoords) { $keys = $value->getDBkeys(); $upCoords[] = array('s_id' => $ioID, 'p_id' => $this->makeSMWPropertyID($property), 'lat' => $keys[0], 'lon' => $keys[1]); } } return array($upRels2, $upAtts2, $upText2, $upCoords); }
/** * Modify the given query object to account for some property condition for * the given property. If it is not possible to generate a query for the * given data, the query type is changed to SMW_SQL2_NOQUERY. Callers need * to check for this and discard the query in this case. * @todo Check if hierarchy queries work as expected. */ protected function compilePropertyCondition(SMWSQLStore2Query $query, $property, SMWDescription $valuedesc) { $tableid = SMWSQLStore2::findPropertyTableID($property); if ($tableid == '') { // probably a type-polymorphic property $typeid = $valuedesc->getTypeID(); $tableid = SMWSQLStore2::findTypeTableID($typeid); } else { // normal property $typeid = $property->getPropertyTypeID(); } if ($tableid == '') { // Still no table to query? Give up. $query->type = SMW_SQL2_NOQUERY; return; } $proptables = SMWSQLStore2::getPropertyTables(); $proptable = $proptables[$tableid]; if (!$proptable->idsubject) { // no queries with such tables (there is really no demand, as only redirects are affected) $query->type = SMW_SQL2_NOQUERY; return; } list($sig, $valueindex, $labelindex) = SMWSQLStore2::getTypeSignature($typeid); $sortkey = $property->getDBkey(); // TODO: strictly speaking, the DB key is not what we want here, since sortkey is based on a "wiki value" // *** Basic settings: table, joinfield, and objectfields ***// $query->jointable = $proptable->name; if ($property->isInverse()) { // see if we can support inverses by inverting the proptable data if (count($proptable->objectfields) == 1 && reset($proptable->objectfields) == 'p') { $query->joinfield = $query->alias . '.' . reset(array_keys($proptable->objectfields)); $objectfields = array('s_id' => 'p'); $valueindex = $labelindex = 3; // should normally not change, but let's be strict } else { // no inverses supported for this property, stop here $query->type = SMW_SQL2_NOQUERY; return; } } else { // normal forward property $query->joinfield = "{$query->alias}.s_id"; $objectfields = $proptable->objectfields; } // *** Add conditions for selecting rows for this property, maybe with a hierarchy ***// if ($proptable->fixedproperty == false) { $pid = $this->m_store->getSMWPropertyID($property); if (!$property->getPropertyID() || $property->getPropertyTypeID() != '__err') { // also make property hierarchy (may or may not be executed later on) // exclude type-polymorphic properties _1, _2, ... (2nd check above suffices, but 1st is faster to check) // we could also exclude other cases here, if desired $pqid = SMWSQLStore2Query::$qnum; $pquery = new SMWSQLStore2Query(); $pquery->type = SMW_SQL2_PROP_HIERARCHY; $pquery->joinfield = array($pid); $query->components[$pqid] = "{$query->alias}.p_id"; $this->m_queries[$pqid] = $pquery; } else { $query->where = "{$query->alias}.p_id=" . $this->m_dbs->addQuotes($pid); } } // else: no property column, no hierarchy queries // *** Add conditions on the value of the property ***// if (count($objectfields) == 1 && reset($objectfields) == 'p') { // page description, process like main query $sub = $this->compileQueries($valuedesc); $objectfield = reset(array_keys($objectfields)); if ($sub >= 0) { $query->components[$sub] = "{$query->alias}.{$objectfield}"; } } else { // non-page value description; expressive features mainly based on value $this->compileAttributeWhere($query, $valuedesc, $proptable, $valueindex); // (no need to pass on $objectfields since they are just as in $proptable in this case) } // *** Incorporate ordering if desired ***// if ($valueindex >= 0 && array_key_exists($sortkey, $this->m_sortkeys)) { // This code might be overly general: it supports datatypes of arbitrary signatures // and valueindex (sortkeys). It can even order pages by something other than their // sortkey (e.g. by their namespace?!), and it can handle values consisting of a page // and some more data fields before or after. Supporting pages in this way requires us // to iterate over the table fields since one page corresponds to four values in a // type's signature. Thankfully, signatures are short so this iteration is not notable. $smwidjoinfield = false; $fieldName = $this->getDBFieldsForDVIndex($objectfields, $valueindex, $smwidjoinfield); if ($fieldName) { if ($smwidjoinfield) { // TODO: is this smw_ids possibly duplicated in the query? Can we prevent that? (PERFORMANCE) $query->from = ' INNER JOIN ' . $this->m_dbs->tableName('smw_ids') . " AS ids{$query->alias} ON ids{$query->alias}.smw_id={$query->alias}.{$smwidjoinfield}"; $query->sortfields[$sortkey] = "ids{$query->alias}.{$fieldName}"; } else { $query->sortfields[$sortkey] = "{$query->alias}.{$fieldName}"; } } } }