Skip to content

Commit

Permalink
fix (webapi): Fix parsing of FILTER in OPTIONAL (#879).
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjamin Geer committed Jun 5, 2018
1 parent bdf5361 commit c1b97ed
Show file tree
Hide file tree
Showing 5 changed files with 388 additions and 270 deletions.
Expand Up @@ -25,16 +25,15 @@ import org.knora.webapi._
import org.knora.webapi.messages.admin.responder.usersmessages.UserADM
import org.knora.webapi.messages.store.triplestoremessages._
import org.knora.webapi.messages.v1.responder.valuemessages.JulianDayNumberValueV1
import org.knora.webapi.messages.v2.responder._
import org.knora.webapi.messages.v2.responder.resourcemessages._
import org.knora.webapi.messages.v2.responder.searchmessages._
import org.knora.webapi.responders.ResponderWithStandoffV2
import org.knora.webapi.util.ActorUtil._
import org.knora.webapi.util.IriConversions._
import org.knora.webapi.util._
import org.knora.webapi.util.search.ApacheLuceneSupport.{CombineSearchTerms, MatchStringWhileTyping}
import org.knora.webapi.util.search.v2._
import org.knora.webapi.util.search._
import org.knora.webapi.util.search.v2._

import scala.collection.mutable
import scala.concurrent.Future
Expand Down
Expand Up @@ -84,8 +84,8 @@ case class GroupConcat(inputVariable: QueryVariable, separator: Char, outputVari
/**
* Represents a COUNT statement that counts how many instances/rows are returned for [[inputVariable]].
*
* @param inputVariable the variable to count.
* @param distinct indicates whether DISTINCT has to be used inside COUNT.
* @param inputVariable the variable to count.
* @param distinct indicates whether DISTINCT has to be used inside COUNT.
* @param outputVariableName the name of the variable representing the result.
*/
case class Count(inputVariable: QueryVariable, distinct: Boolean, outputVariableName: String) extends SelectQueryColumn {
Expand Down Expand Up @@ -294,8 +294,8 @@ case class OrExpression(leftArg: Expression, rightArg: Expression) extends Expre
* Represents a regex function in a query (in a FILTER).
*
* @param textValueVar the variable representing the text value to be checked against the provided pattern.
* @param pattern the REGEX pattern to be used.
* @param modifier the modifier to be used.
* @param pattern the REGEX pattern to be used.
* @param modifier the modifier to be used.
*/
case class RegexFunction(textValueVar: QueryVariable, pattern: String, modifier: String) extends Expression {
def toSparql: String = s"""regex(${textValueVar.toSparql}, "$pattern", "$modifier")"""
Expand All @@ -314,7 +314,7 @@ case class LangFunction(textValueVar: QueryVariable) extends Expression {
* Represents a function call in a filter.
*
* @param functionIri the IRI of the function.
* @param args the arguments passed to the function.
* @param args the arguments passed to the function.
*/
case class FunctionCallExpression(functionIri: IriRef, args: Seq[Entity]) extends Expression {
def toSparql: String = s"<${functionIri.iri.toString}>(${args.map(_.toSparql).mkString(", ")})"
Expand Down Expand Up @@ -342,7 +342,7 @@ case class FunctionCallExpression(functionIri: IriRef, args: Seq[Entity]) extend
* Gets the argument at the given position as a [[XsdLiteral]] of the given datatype.
* Throws a [[GravsearchException]] no argument exists at the given position or if it is not a [[XsdLiteral]] of the requested datatype.
*
* @param pos the argument to be returned from [[args]].
* @param pos the argument to be returned from [[args]].
* @param xsdDatatype the argeument's datatype.
* @return an [[XsdLiteral]].
*/
Expand Down Expand Up @@ -477,6 +477,10 @@ case class ConstructQuery(constructClause: ConstructClause, whereClause: WhereCl
val stringBuilder = new StringBuilder
stringBuilder.append(constructClause.toSparql).append(whereClause.toSparql)

if (orderBy.nonEmpty) {
stringBuilder.append("ORDER BY ").append(orderBy.map(_.toSparql).mkString(" ")).append("\n")
}

if (offset > 0) {
stringBuilder.append("OFFSET ").append(offset)
}
Expand All @@ -497,36 +501,33 @@ case class ConstructQuery(constructClause: ConstructClause, whereClause: WhereCl
*/
case class SelectQuery(variables: Seq[SelectQueryColumn], useDistinct: Boolean = true, whereClause: WhereClause, groupBy: Seq[QueryVariable] = Seq.empty[QueryVariable], orderBy: Seq[OrderCriterion] = Seq.empty[OrderCriterion], limit: Option[Int] = None, offset: Long = 0) extends SparqlGenerator {
def toSparql: String = {
val selectWhereSparql = "SELECT " + {
if (useDistinct) {
"DISTINCT "
} else {
""
}
} + variables.map(_.toSparql).mkString(" ") + "\n" + whereClause.toSparql + "\n"

val groupBySparql = if (groupBy.nonEmpty) {
"GROUP BY " + groupBy.map(_.toSparql).mkString(" ") + "\n"
} else {
""
}
val stringBuilder = new StringBuilder

stringBuilder.append("SELECT ")

if (useDistinct) {
stringBuilder.append("DISTINCT ")

val orderBySparql = if (orderBy.nonEmpty) {
"ORDER BY " + orderBy.map(_.toSparql).mkString(" ")
} else {
""
}

val offsetSparql = s"\nOFFSET $offset"
stringBuilder.append(variables.map(_.toSparql).mkString(" ")).append("\n").append(whereClause.toSparql)

val limitSparql = if (limit.nonEmpty) {
s"\nLIMIT ${limit.get}"
} else {
""
if (groupBy.nonEmpty) {
stringBuilder.append("GROUP BY ").append(groupBy.map(_.toSparql).mkString(" ")).append("\n")
}

if (orderBy.nonEmpty) {
stringBuilder.append("ORDER BY ").append(orderBy.map(_.toSparql).mkString(" ")).append("\n")
}

selectWhereSparql + groupBySparql + orderBySparql + offsetSparql + limitSparql
if (offset > 0) {
stringBuilder.append("OFFSET ").append(offset).append("\n")
}

if (limit.nonEmpty) {
stringBuilder.append(s"LIMIT ${limit.get}").append("\n")
}

stringBuilder.toString
}
}

0 comments on commit c1b97ed

Please sign in to comment.