Source for file TypeSorter.php
Documentation is available at TypeSorter.php
* Sorts database types as the Sparql specs want it.
* @author Christian Weiske <cweiske@cweiske.de>
* Defines the sort order for value types in the database,
* so that they get sorted correctly as the specs want it.
public static $arTypeNumbers =
array(
* SQL types to cast XSD schema types to, so that they will get
public static $arCastTypes =
array(
'http://www.w3.org/2001/XMLSchema#integer' =>
'SIGNED INTEGER'
public function __construct(Query $query, ADOConnection $dbConn)
* Needs to be executed before getOrderifiedSqls and willBeDataDependent
* @param SparqlEngineDb_SqlGenerator $sg SQL generator object
public function setData(SparqlEngineDb_SqlGenerator $sg)
$this->arUsedVarTypes =
$sg->getUsedVarTypes();
$this->arUsedVarAssignments =
$sg->getUsedVarAssignments();
$this->arVarAssignments =
$sg->getVarAssignments();
}//public function setData(SparqlEngineDb_SqlGenerator $sg)
* Returns an array of sql statements that need to be executed
* and deliver the full result set when combined.
* Execute setData() before this.
* @internal It is not possible (ok, it is - but it would really complicate
* the queries and the code here) to use UNION to combine the sqls to
* a single one - UNION merges the results and does not keep the order
* of the rows. Citing the mysql manual:
* Use of ORDER BY for individual SELECT statements implies nothing
* about the order in which the rows appear in the final result because
* UNION by default produces an unordered set of rows. If ORDER BY
* appears with LIMIT, it is used to determine the subset of the
* selected rows to retrieve for the SELECT, but does not necessarily
* affect the order of those rows in the final UNION result.
* If ORDER BY appears without LIMIT in a SELECT, it is
* optimized away because it will have no effect anyway.
* @param string $strSelect SELECT clause
* @param string $strFrom FROM clause
* @param string $strWhere WHERE clause
* @return array Array of arrays. Imploding an array will give
* a complete sql statement. The array will have the keys
* select/from/where/order.
if (count($arSqls) ==
0) {
$strSelect =
$arSqls[0]['select'];
$strFrom =
$arSqls[0]['from'];
$strWhere =
$arSqls[0]['where'];
$strResultForm =
$this->query->getResultForm();
if ($strResultForm ==
'ask' ||
$strResultForm ==
'count') {
if (count($arSpecial) ==
0) {
foreach ($arSqls as &$arSql) {
$arSql['order'] =
$strOrder;
foreach ($arTypeSets as $arTypeSet) {
foreach ($arSqls as $arSql) {
$arNewSqls[] =
$arSqlParts;
}//public function getOrderifiedSqls($arUsedVarAssignments, $strSelect, $strFrom, $strWhere)
* Returns wether the returned queries will depend on the data or not.
* If the queries depend on the data, they cannot be prepare()d and
* thus won't be that fast when executing.
* Execute setData() before this.
$strResultForm =
$this->query->getResultForm();
$strResultForm ==
'ask' ||
$strResultForm ==
'count'
}//public function willBeDataDependent()
* Returns an array of variables that the result is going to be
* ordered by and that need to be sorted multiple times
* (because they may contain different data types)
* @return array Array of sparql variable names
$arSM =
$this->query->getSolutionModifier();
if ($arSM['order by'] ===
null) {
foreach ($arSM['order by'] as $arVar) {
$arSpecial[] =
$arVar['val'];
}//protected function getSpecialOrderVariables()
* Checks if a given variable name is a variable that
* needs special care when used in ORDER BY statements.
* @param string $strVar SPARQL variable name
* @return boolean true if the variable needs special care
return !isset
($this->arUsedVarTypes[$strVar]['s'])
&&
!isset
($this->arUsedVarTypes[$strVar]['p']);
}//protected function isSpecialOrderVariable($arVar)
* Determines the type sets in the query results.
* A type set is a distinct set of variables and their types,
* e.g. the variable and its type (r/b/l) and its datatype
* @param array $arSpecialVars Special variables as returned by
* getSpecialOrderVariables()
* @param string $strFrom FROM part of the sql query
* @param string $strWhere WHERE part of the sql query
* @return array Key is the sparql variable name, value is an
* array. This one has one key 'type' with a
* value of b/l/r. It might have another key
* 'datatype' with the resource's datatype.
protected function getTypeSets($arSpecialVars, $strFrom, $strWhere)
foreach ($arSpecialVars as $strSparqlVar) {
if ($this->arVarAssignments[$strSparqlVar][1] ==
'o') {
$arSel[] =
$this->arVarAssignments[$strSparqlVar][0] .
'.l_datatype'
.
' as "' .
$strSparqlVar .
'-datatype"';
$strTypeCol =
$this->arVarAssignments[$strSparqlVar][1] ==
'o'
?
'object_is' :
'subject_is';
$this->arVarAssignments[$strSparqlVar][2] =
$strTypeCol;
$arSel[] =
$this->arVarAssignments[$strSparqlVar][0] .
'.' .
$strTypeCol
.
' as "' .
$strSparqlVar .
'-type"';
$oldmode =
$this->dbConn->SetFetchMode(ADODB_FETCH_ASSOC);
$arResult =
$this->dbConn->execute(
'SELECT DISTINCT ' .
implode(', ', $arSel) .
' ' .
$strFrom .
$strWhere
$this->dbConn->SetFetchMode($oldmode);
foreach ($arResult as $arRow) {
$nLine =
count($arTypes);
foreach ($arRow as $key =>
$value) {
list
($strSparqlVar, $strType) =
explode('-', $key);
$arTypes[$nLine][$strSparqlVar][$strType] =
$value;
}//protected function getTypeSets($arSpecialVars, $strFrom, $strWhere)
* Takes an array of type sets (as returned by getTypeSets()) and
* sorts the variables according to the SPARQL specs.
* @param array $arTypes Array of type sets
* @return array Ordered array of type sets
$arSM =
$this->query->getSolutionModifier();
if ($arSM['order by'] !==
null) {
$this->arDirection =
array();
foreach ($arSM['order by'] as $arVar) {
$this->arDirection[$arVar['val']] =
usort($arTypes, array($this, 'compareTypeSet'));
}//protected function orderTypeSets($arTypes)
* Compares two type sets. Works like a normal comparision
* method that returns -1/0/1 for use in usort()
* @param array $arTs1 First typeset
* @param array $arTs2 Second typeset
* @return int Comparison value
foreach ($arTs1 as $strSparqlVar =>
$arType1) {
$n =
self::$arTypeNumbers[$arType1['type']]
-
self::$arTypeNumbers[$arTs2[$strSparqlVar]['type']];
//and take ASC/DESC into account
return $n *
$this->arDirection[$strSparqlVar];
$n =
self::compareXsdType(
$arTs2[$strSparqlVar]['datatype']
//if they are not equal, return the value
//and take ASC/DESC into account
return $n *
$this->arDirection[$strSparqlVar];
}//public function compareTypeSet($arTs1, $arTs2)
* Compares two XSD data types and returns the comparison number.
* @param string $strType1 First data type
* @param string $strType2 Second data type
* @return int Comparison number (<0 if $strType1 is less than
* $strType2, 0 if equal, >0 if type2 is greater)
return self::getXsdTypeNumber($strType1) -
self::getXsdTypeNumber($strType2);
}//public static function compareXsdType($strType1, $strType2)
* Returns the type number for an xsd data type.
* @param string $strType XSD data type
* @return int Some integer to compare two types.
} else if ($strType ==
'') {
}//public static function getXsdTypeNumber($strType)
* Returns the ORDER BY sql query string
* if neccessary for the query. The returned string
* already has ORDER BY prefixed.
* @internal Also takes care of casting the data if the type
* is listed in $arCastTypes. See getCastMethod() for more info.
* @param arrray $arTypeSet Single typeset
* @return string ORDER BY ... string or empty string
$arSM =
$this->query->getSolutionModifier();
if ($arSM['order by'] ===
null) {
foreach ($arSM['order by'] as $arVar) {
$strSparqlVar =
$arVar['val'];
if (isset
($this->arUsedVarAssignments[$strSparqlVar])) {
if (!isset
($arTypeSet[$strSparqlVar]['datatype'])
||
$arTypeSet[$strSparqlVar]['datatype'] ==
'') {
$sqlOrder[] =
$this->arUsedVarAssignments[$strSparqlVar] .
' ' .
strtoupper($arVar['type']);
$sqlOrder[] =
self::getCastMethod(
$arTypeSet[$strSparqlVar]['datatype'],
$this->arUsedVarAssignments[$strSparqlVar]
return ' ORDER BY ' .
implode(', ', $sqlOrder);
}//function getSqlOrderBy($arTypeSet = array())
* Returns the SQL statement needed to case the given variable to
* @param string $strType XML data type
* @param string $strSqlVar SQL variable name
* @return string SQL command to cast the variable
if (isset
(self::$arCastTypes[$strType])) {
return 'CAST(' .
$strSqlVar .
' as ' .
self::$arCastTypes[$strType] .
')';
throw
new Exception('Unsupported cast type in order by: ' .
$strType);
}//protected static function getCastMethod($strType, $strSqlVar)
* Creates and returns the SQL WHERE clauses needed to get only
* data in the given typeset.
* @param array $arTypeSet Typeset
* @return string Clauses for the WHERE part in an SQL query
foreach ($arTypeSet as $strSparqlVar =>
$arType) {
$strWhereTypes .=
' AND ' .
$this->arVarAssignments[$strSparqlVar][0]
.
'.' .
$this->arVarAssignments[$strSparqlVar][2]
if (isset
($arType['datatype'])) {
$strWhereTypes .=
' AND ' .
$this->arVarAssignments[$strSparqlVar][0]
}//protected function getTypesetWhereClause($arTypeSet)
* Returns the correct sql string comparison method.
* @internal If the string is NULL, an "IS NULL" sql statment
* will be returned, and a normal "= 'something'" if it is
return ' = ' .
$this->dbConn->qstr($str) .
'';
}//protected function getStringNullComparison($str)
}//class SparqlEngineDb_TypeSorter
Documentation generated on Fri, 1 Jun 2007 16:52:35 +0200 by phpDocumentor 1.3.2