From: Soft W. <so...@gm...> - 2008-11-11 22:04:52
|
Hello everyone. I'm new to this list, but looks like this is the place to ask questions. I'm trying to use rdfapi-php to load and query large ontology. What I found is that executing the query SELECT distinct ?name WHERE { { ?unique_id rdfs:label ?name. FILTER regex(str(?name), '<value>'). } union { ?unique_id rdfs:label ?name2. FILTER regex(str(?name2), '<value>'). ?unique_id oboInOwl:hasExactSynonym ?another_id . ?another_id rdfs:label ?name . } } Where <value> is some keyword I'm trying to look up in the ontology by matching the regexp against the name with all cross-referenced keywords. Causes a db exception and wrong query. In fact the point of the query was to attach 2 sets of data via union 1. set of data that directly matches the pattern 2. set of data that has synonyms of the matched pattern and return 2 column ?name from the union. The SQLGenerator class generates the QUERY: (SELECT DISTINCT t0.object as "t0.value_v_name", t0.object_is as "t0.is_v_name", t0.l_language as "t0.lang_v_name", t0.l_datatype as "t0.type_v_name" FROM statements as t0 WHERE 1 AND t0.predicate = 'http://www.w3.org/2000/01/rdf-schema#label' AND (CASE t0.object_is WHEN "b" THEN "" ELSE t0.object END) REGEXP "<value>") UNION (SELECT DISTINCT t0.object as "t0.value_v_name", t0.object_is as "t0.is_v_name", t0.l_language as "t0.lang_v_name", t0.l_datatype as "t0.type_v_name" FROM statements as t0 LEFT JOIN statements as t1 ON t0.modelID = t1.modelID LEFT JOIN statements as t0 ON t0.modelID = t0.modelID AND t0.object = t0.object WHERE 1 AND t0.predicate = 'http://www.w3.org/2000/01/rdf-schema#label' AND t1.predicate = 'http://www.geneontology.org/formats/oboInOwl#hasExactSynonym' AND t1.subject = t0.subject AND t1.subject_is = t0.subject_is AND t0.predicate = 'http://www.w3.org/2000/01/rdf-schema#label' AND t0.subject = t1.object AND t0.subject_is = t1.object_is AND (CASE t0.object_is WHEN "b" THEN "" ELSE t0.object END) REGEXP "<value>") Exception: ADOdb error: Not unique table/alias: 't0' In general, you can see that the second query in the union is incorrect. I think the error is in these commented lines: Class SqlGenerator function getTripleSql(QueryTriple $triple, GraphPattern $graphPattern, $arResultVars) ....................... ....................... ....................... /** * SELECT part * We do select only the columns we need for variables */ if (SparqlVariable::isVariable($subject)) { if (isset($this->arUnionVarAssignments[$this->nUnionCount][$subject])) { //already selected -> add equality check $bWhereEqualitySubject = true; $this->arUsedVarTypes[$subject]['s'] = true; } else { -> //if (isset($this->arVarAssignments[$subject][0])) { -> // $strTablePrefix = $this->arVarAssignments[$subject][0]; -> // } $this->arVarAssignments[$subject] = array($strTablePrefix, 's'); $this->arUnionVarAssignments[$this->nUnionCount][$subject] = array($strTablePrefix, 's'); $this->arUsedVarTypes[$subject]['s'] = true; if (self::isResultVar($subject, $arResultVars)) { //new variable that needs to be selected $arSelect[$subject] = $this->createVariableSelectArray( 's', $subject, $strTablePrefix ); if (isset($this->arUsedVarAssignments[$subject])) { $arRefVars[$subject] = $strTablePrefix . '.subject'; } else { $this->arUsedVarAssignments[$subject] = $strTablePrefix . '.subject'; } } } } if (SparqlVariable::isVariable($predicate)) { if (isset($this->arUnionVarAssignments[$this->nUnionCount][$predicate])) { //already selected -> add equality check $bWhereEqualityPredicate = true; $this->arUsedVarTypes[$predicate]['p'] = true; } else { -> // if (isset($this->arVarAssignments[$predicate][0])) { -> // $strTablePrefix = $this->arVarAssignments[$predicate][0]; -> // } $this->arVarAssignments[$predicate] = array($strTablePrefix, 'p'); $this->arUnionVarAssignments[$this->nUnionCount][$predicate] = array($strTablePrefix, 'p'); $this->arUsedVarTypes[$predicate]['p'] = true; if (self::isResultVar($predicate, $arResultVars)) { $arSelect[$predicate] = $this->createVariableSelectArray( 'p', $predicate, $strTablePrefix ); if (isset($this->arUsedVarAssignments[$predicate])) { $arRefVars[$predicate] = $strTablePrefix . '.predicate'; } else { $this->arUsedVarAssignments[$predicate] = $strTablePrefix . '.predicate'; } } } } if (SparqlVariable::isVariable($object)) { if (isset($this->arUnionVarAssignments[$this->nUnionCount][$object])) { //already selected -> add equality check $bWhereEqualityObject = true; $this->arUsedVarTypes[$object]['o'] = true; } else { -> //if (isset($this->arVarAssignments[$object][0])) { -> // $strTablePrefix = $this->arVarAssignments[$object][0]; -> // } $this->arVarAssignments[$object] = array($strTablePrefix, 'o'); $this->arUnionVarAssignments[$this->nUnionCount][$object] = array($strTablePrefix, 'o'); $this->arUsedVarTypes[$object]['o'] = true; if (self::isResultVar($object, $arResultVars)) { $arSelect[$object] = $this->createVariableSelectArray( 'o', $object, $strTablePrefix ); if (isset($this->arUsedVarAssignments[$object])) { $arRefVars[$object] = $strTablePrefix . '.object'; } else { $this->arUsedVarAssignments[$object] = $strTablePrefix . '.object'; } } if (isset($this->query->varLanguages[$object]) && $this->query->varLanguages[$object] !== null ) { $strWhereEquality .= ' AND ' . $strTablePrefix . '.l_language = "' . addslashes($this->query->varLanguages[$object]) . '"'; } if (isset($this->query->varDatatypes[$object]) && $this->query->varDatatypes[$object] !== null ) { $strWhereEquality .= ' AND ' . $strTablePrefix . '.l_datatype = "' . addslashes($this->query->varDatatypes[$object]) . '"'; } } } When commented, the query is produced correctly (SELECT DISTINCT t0.object as ".value_v_name", t0.object_is as ".is_v_name", t0.l_language as ".lang_v_name", t0.l_datatype as ".type_v_name" FROM statements as t0 WHERE 1 AND t0.predicate = 'http://www.w3.org/2000/01/rdf-schema#label' AND (CASE t0.object_is WHEN "b" THEN "" ELSE t0.object END) REGEXP "<value>") UNION (SELECT DISTINCT t2.object as ".value_v_name", t2.object_is as ".is_v_name", t2.l_language as ".lang_v_name", t2.l_datatype as ".type_v_name" FROM statements as t0 LEFT JOIN statements as t1 ON t0.modelID = t1.modelID LEFT JOIN statements as t2 ON t0.modelID = t2.modelID AND t0.object = t2.object WHERE 1 AND t0.predicate = 'http://www.w3.org/2000/01/rdf-schema#label' AND t1.predicate = 'http://www.geneontology.org/formats/oboInOwl#hasExactSynonym' AND t1.subject = t0.subject AND t1.subject_is = t0.subject_is AND t2.predicate = 'http://www.w3.org/2000/01/rdf-schema#label' AND t2.subject = t1.object AND t2.subject_is = t1.object_is AND (CASE t0.object_is WHEN "b" THEN "" ELSE t0.object END) REGEXP "<value>") I also added extra parameter to the createVariableSelectArray method to control the column prefix which is in my case is always empty, since I 'm not sure why do we need a table name prefix here especially if we run union. protected function createVariableSelectArray($chType, $varname, $strTablePrefix, $strColumnNamePrefix = "") { $var = $this->query->getResultVar($varname); if ($var !== false) { if ((string)$var != $varname) { //copy over var assignments $this->arVarAssignments[(string)$var] = $this->arVarAssignments[$varname]; } //works on non-* only $func = $var->getFunc(); if ($func != null) { if ($func == 'datatype') { if ($chType != 'o') { throw new SparqlEngineDb_SqlGeneratorException( 'datatype() works on objects only' ); } return array( $strTablePrefix . '.l_datatype as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameValue($var) . '"', '"r"' . ' as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameIs($var) . '"', '""' . ' as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameLanguage($var) . '"', '""' . ' as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameDatatype($var) . '"', ); } else if ($func == 'lang') { if ($chType != 'o') { throw new SparqlEngineDb_SqlGeneratorException( 'lang() works on objects only' ); } return array( $strTablePrefix . '.l_language as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameValue($var) . '"', '"l"' . ' as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameIs($var) . '"', '""' . ' as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameLanguage($var) . '"', '""' . ' as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameDatatype($var) . '"', ); } else { throw new SparqlEngineDb_SqlGeneratorException( 'Unsupported function for select "' . $func . '"' ); } } } switch ($chType) { case 's': return array( $strTablePrefix . '.subject as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"', $strTablePrefix . '.subject_is as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameIs($varname) . '"' ); case 'p': return array( $strTablePrefix . '.predicate as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"' ); case 'o': return array( $strTablePrefix . '.object as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameValue($varname) . '"', $strTablePrefix . '.object_is as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameIs($varname) . '"', $strTablePrefix . '.l_language as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameLanguage($varname) . '"', $strTablePrefix . '.l_datatype as "' . $strColumnNamePrefix . '.' . $this->getSqlVariableNameDatatype($varname) . '"', ); default: throw new SparqlEngineDb_SqlGeneratorException( 'Unknown sentence type "' . $chType . "', one of (s,p,o) expected" ); } }//protected function createVariableSelectArray($chType, $value, $strTablePrefix) This change needs to be coupled with this snippet of code that skips the check for the table prefix In all of these methods for XML, HTML, Text and Default renderers. createSubjectFromDbRecordSetPart createPredicateFromDbRecordSetPart createObjectFromDbRecordSetPart foreach ( array_keys($dbRecordSet->fields) as $field){ if ( substr($field,0,1) != '.') { $noprefix = false; break; } } if ( $noprefix ){ $strVarBase = ''; } |