/**
  * 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}";
             }
         }
     }
 }