diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/Resource.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/Resource.java index 65f540f95ee..125dc0fb754 100644 --- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/Resource.java +++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/Resource.java @@ -17,6 +17,12 @@ public interface Resource extends Value { // Empty place holder as common supertype of IRI and BNode + default Type getValueType(){ + if(isIRI()) return Type.IRI; + if(isBNode()) return Type.BNODE; + return Type.TRIPLE; + } + @Override default boolean isResource() { return true; diff --git a/core/model-api/src/main/java/org/eclipse/rdf4j/model/Value.java b/core/model-api/src/main/java/org/eclipse/rdf4j/model/Value.java index d83f25c1a6d..cf4ee2c3cb6 100644 --- a/core/model-api/src/main/java/org/eclipse/rdf4j/model/Value.java +++ b/core/model-api/src/main/java/org/eclipse/rdf4j/model/Value.java @@ -24,7 +24,12 @@ public enum Type { TRIPLE } - Type getValueType(); + default Type getValueType(){ + if(isIRI()) return Type.IRI; + if(isLiteral()) return Type.LITERAL; + if(isBNode()) return Type.BNODE; + return Type.TRIPLE; + } /** * Check if the object is an instance of the given type. Typically 2x than using instanceof. diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java index f21e472ae9f..f06caf9083d 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparator.java @@ -43,11 +43,11 @@ public class OrderComparator implements Comparator { private final static Logger logger = LoggerFactory.getLogger(OrderComparator.class); - private final ValueComparator cmp; + private final Comparator cmp; private final Comparator bindingContentsComparator; - public OrderComparator(EvaluationStrategy strategy, Order order, ValueComparator cmp, + public OrderComparator(EvaluationStrategy strategy, Order order, Comparator cmp, QueryEvaluationContext context) { this.cmp = cmp; this.bindingContentsComparator = precompileComparator(strategy, order, context); diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java index 10a46bcc073..3f168ee1ad9 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/QueryEvaluationUtility.java @@ -10,17 +10,6 @@ *******************************************************************************/ package org.eclipse.rdf4j.query.algebra.evaluation.util; -import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED; - -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneOffset; -import java.util.Objects; - -import javax.xml.datatype.DatatypeConstants; -import javax.xml.datatype.Duration; -import javax.xml.datatype.XMLGregorianCalendar; - import org.eclipse.rdf4j.common.annotation.InternalUseOnly; import org.eclipse.rdf4j.model.Literal; import org.eclipse.rdf4j.model.Value; @@ -29,6 +18,16 @@ import org.eclipse.rdf4j.model.util.Literals; import org.eclipse.rdf4j.query.algebra.Compare.CompareOp; +import javax.xml.datatype.DatatypeConstants; +import javax.xml.datatype.Duration; +import javax.xml.datatype.XMLGregorianCalendar; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneOffset; +import java.util.Objects; + +import static javax.xml.datatype.DatatypeConstants.FIELD_UNDEFINED; + /** * This class will take over for QueryEvaluationUtil. Currently marked as InternalUseOnly because there may still be * changes to how this class works. @@ -107,12 +106,12 @@ public static Result compare(Value leftVal, Value rightVal, CompareOp operator, } else { // All other value combinations switch (operator) { - case EQ: - return Result.fromBoolean(Objects.equals(leftVal, rightVal)); - case NE: - return Result.fromBoolean(!Objects.equals(leftVal, rightVal)); - default: - return Result.incompatibleValueExpression; + case EQ: + return Result.fromBoolean(Objects.equals(leftVal, rightVal)); + case NE: + return Result.fromBoolean(!Objects.equals(leftVal, rightVal)); + default: + return Result.incompatibleValueExpression; } } } @@ -125,7 +124,7 @@ public static Result compare(Value leftVal, Value rightVal, CompareOp operator, * @param rightLit the right literal argument of the comparison. * @param operator the comparison operator to use. * @return {@code true} if execution of the supplied operator on the supplied arguments succeeds, {@code false} - * otherwise. + * otherwise. */ public static Result compareLiterals(Literal leftLit, Literal rightLit, CompareOp operator) { return compareLiterals(leftLit, rightLit, operator, true); @@ -149,7 +148,7 @@ public static Order compareLiterals(Literal leftLit, Literal rightLit, boolean s if (leftCoreDatatype == CoreDatatype.XSD.STRING && rightCoreDatatype == CoreDatatype.XSD.STRING) { return Order.from(leftLit.getLabel().compareTo(rightLit.getLabel())); } else if (leftCoreDatatype != null - && rightCoreDatatype != null) { + && rightCoreDatatype != null) { if (leftCoreDatatype.isXSDDatatype() && rightCoreDatatype.isXSDDatatype()) { @@ -159,8 +158,8 @@ public static Order compareLiterals(Literal leftLit, Literal rightLit, boolean s try { Order order = handleCommonDatatype(leftLit, rightLit, strict, leftCoreDatatype, - rightCoreDatatype, - commonDatatype); + rightCoreDatatype, + commonDatatype); if (order == Order.illegalArgument) { if (leftLit.equals(rightLit)) { @@ -188,8 +187,8 @@ public static Order compareLiterals(Literal leftLit, Literal rightLit, boolean s // operator return otherCases(leftLit, rightLit, leftCoreDatatype, - rightCoreDatatype, leftCoreDatatype == null && leftLit.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING, - rightCoreDatatype == null && rightLit.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING); + rightCoreDatatype, leftCoreDatatype == null && leftLit.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING, + rightCoreDatatype == null && rightLit.getCoreDatatype() == CoreDatatype.RDF.LANGSTRING); } @@ -202,7 +201,7 @@ public static Order compareLiterals(Literal leftLit, Literal rightLit, boolean s * @param strict boolean indicating whether comparison should use strict (minimally-conforming) SPARQL 1.1 * operator behavior, or extended behavior. * @return {@code true} if execution of the supplied operator on the supplied arguments succeeds, {@code false} - * otherwise. + * otherwise. */ public static Result compareLiterals(Literal leftLit, Literal rightLit, CompareOp operator, boolean strict) { Order order = compareLiterals(leftLit, rightLit, strict); @@ -241,16 +240,16 @@ public static Instant xmlGregorianCalendarToInstant(XMLGregorianCalendar xmlGreg } int nanosecond = xmlGregCal.getFractionalSecond() != null - ? xmlGregCal.getFractionalSecond().movePointRight(9).intValue() - : 0; + ? xmlGregCal.getFractionalSecond().movePointRight(9).intValue() + : 0; if (nanosecond < 0) { return null; } LocalDateTime localDateTime = LocalDateTime.of(year, month, day, hour, minute, second, nanosecond); ZoneOffset zoneOffset = xmlGregCal.getTimezone() == FIELD_UNDEFINED - ? ZoneOffset.UTC - : ZoneOffset.ofTotalSeconds(xmlGregCal.getTimezone() * 60); + ? ZoneOffset.UTC + : ZoneOffset.ofTotalSeconds(xmlGregCal.getTimezone() * 60); return localDateTime.toInstant(zoneOffset); } @@ -277,12 +276,12 @@ public static Instant xmlGregorianCalendarDateToInstant(XMLGregorianCalendar xml LocalDateTime localDateTime = LocalDateTime.of(year, month, day, 0, 0, 0, 0); ZoneOffset zoneOffset = xmlGregCal.getTimezone() == FIELD_UNDEFINED - ? ZoneOffset.UTC - : ZoneOffset.ofTotalSeconds(xmlGregCal.getTimezone() * 60); + ? ZoneOffset.UTC + : ZoneOffset.ofTotalSeconds(xmlGregCal.getTimezone() * 60); return localDateTime.toInstant(zoneOffset); } - private final static int[] daysInMonth = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; + private final static int[] daysInMonth = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; public static Instant yearMonthDayToInstant(int year, int month, int day) { @@ -310,8 +309,8 @@ public static Instant yearMonthDayToInstant(int year, int month, int day) { public static long toEpoch(int year, int month, int day, int hour, int minute, int second) { long dateEpoch = ((long) day + (long) (year - ((14 - month) / 12)) + ((long) (year - ((14 - month) / 12))) / 4 - - ((long) (year - ((14 - month) / 12))) / 100 + ((long) (year - ((14 - month) / 12))) / 400 - + (31 * ((long) (month + (12 * ((14 - month) / 12) - 2)))) / 12) - 719529; + - ((long) (year - ((14 - month) / 12))) / 100 + ((long) (year - ((14 - month) / 12))) / 400 + + (31 * ((long) (month + (12 * ((14 - month) / 12) - 2)))) / 12) - 719529; // // // Calculate the number of days from 1970 to the given year @@ -338,8 +337,8 @@ public static long toEpoch(int year, int month, int day, int hour, int minute, i } private static Order handleCommonDatatype(Literal leftLit, Literal rightLit, boolean strict, - CoreDatatype.XSD leftCoreDatatype, CoreDatatype.XSD rightCoreDatatype, - CoreDatatype.XSD commonDatatype) { + CoreDatatype.XSD leftCoreDatatype, CoreDatatype.XSD rightCoreDatatype, + CoreDatatype.XSD commonDatatype) { if (commonDatatype == CoreDatatype.XSD.DOUBLE) { return Order.from(Double.compare(leftLit.doubleValue(), rightLit.doubleValue())); } else if (commonDatatype == CoreDatatype.XSD.FLOAT) { @@ -371,7 +370,7 @@ private static Order handleCommonDatatype(Literal leftLit, Literal rightLit, boo XMLGregorianCalendar left = leftLit.calendarValue(); XMLGregorianCalendar right = rightLit.calendarValue(); - int compare = compareXMLGregorianCalendar(leftCoreDatatype, rightCoreDatatype, left, right); + int compare = compareXMLGregorianCalendar(leftCoreDatatype, rightCoreDatatype, left, right, leftLit, rightLit); // Note: XMLGregorianCalendar.compare() returns compatible values (-1, 0, 1) but INDETERMINATE // needs special treatment @@ -403,41 +402,48 @@ private static Order handleCommonDatatype(Literal leftLit, Literal rightLit, boo } private static int compareXMLGregorianCalendar(CoreDatatype.XSD leftCoreDatatype, - CoreDatatype.XSD rightCoreDatatype, XMLGregorianCalendar left, XMLGregorianCalendar right) { + CoreDatatype.XSD rightCoreDatatype, XMLGregorianCalendar left, XMLGregorianCalendar right, Literal leftLit, Literal rightLit) { if (leftCoreDatatype == rightCoreDatatype && left.getTimezone() == right.getTimezone()) { int leftYear = left.getYear(); int rightYear = right.getYear(); if (leftYear > 1971 && rightYear > 1971 && leftYear < 2038 && rightYear < 2038) { int compare = Long.compare( - toEpoch(leftYear, left.getMonth(), left.getDay(), left.getHour(), left.getMinute(), - left.getSecond()), - toEpoch(rightYear, right.getMonth(), right.getDay(), right.getHour(), right.getMinute(), - right.getSecond()) + toEpoch(leftYear, left.getMonth(), left.getDay(), left.getHour(), left.getMinute(), + left.getSecond()), + toEpoch(rightYear, right.getMonth(), right.getDay(), right.getHour(), right.getMinute(), + right.getSecond()) ); if (compare != 0) { // since the values are different we can assume that we don't need to account for a higher precision return compare; } else { // since the values are equal we need to account for a higher precision - return left.compare(right); + if (leftLit.getLabel().equals(rightLit.getLabel())) { + return 0; + } else { + return left.compare(right); + } } } else { // since the values are equal we need to account for a higher precision - return left.compare(right); - } + if (leftLit.getLabel().equals(rightLit.getLabel())) { + return 0; + } else { + return left.compare(right); + } } } else { return left.compare(right); } } private static Order otherCases(Literal leftLit, Literal rightLit, CoreDatatype leftCoreDatatype, - CoreDatatype rightCoreDatatype, boolean leftLangLit, boolean rightLangLit) { + CoreDatatype rightCoreDatatype, boolean leftLangLit, boolean rightLangLit) { boolean literalsEqual = leftLit.equals(rightLit); if (!literalsEqual) { if (!leftLangLit && !rightLangLit && isSupportedDatatype(leftCoreDatatype) - && isSupportedDatatype(rightCoreDatatype)) { + && isSupportedDatatype(rightCoreDatatype)) { // left and right arguments have incompatible but supported datatypes // we need to check that the lexical-to-value mapping for both datatypes succeeds @@ -482,7 +488,7 @@ && isSupportedDatatype(rightCoreDatatype)) { } private static CoreDatatype.XSD getCommonDatatype(boolean strict, CoreDatatype.XSD leftCoreDatatype, - CoreDatatype.XSD rightCoreDatatype) { + CoreDatatype.XSD rightCoreDatatype) { if (leftCoreDatatype == null || rightCoreDatatype == null) { return null; } @@ -507,7 +513,7 @@ private static CoreDatatype.XSD getCommonDatatype(boolean strict, CoreDatatype.X } private static CoreDatatype.XSD getCommonNumericDatatype(CoreDatatype.XSD leftCoreDatatype, - CoreDatatype.XSD rightCoreDatatype) { + CoreDatatype.XSD rightCoreDatatype) { if (leftCoreDatatype == CoreDatatype.XSD.DOUBLE || rightCoreDatatype == CoreDatatype.XSD.DOUBLE) { return CoreDatatype.XSD.DOUBLE; } @@ -525,7 +531,7 @@ private static CoreDatatype.XSD getCommonNumericDatatype(CoreDatatype.XSD leftCo * optionally a language tag. * * @see RDF Literal - * Documentation + * Documentation */ public static boolean isPlainLiteral(Value v) { if (v.isLiteral()) { @@ -599,7 +605,7 @@ public static boolean isStringLiteral(Value v) { * @param arg2 the second argument * @return true iff the two supplied arguments are argument compatible, false otherwise * @see SPARQL Argument Compatibility - * Rules + * Rules */ public static boolean compatibleArguments(Literal arg1, Literal arg2) { // 1. The arguments are literals typed as CoreDatatype.XSD:string @@ -608,9 +614,9 @@ public static boolean compatibleArguments(Literal arg1, Literal arg2) { // argument is a literal typed as CoreDatatype.XSD:string return (isSimpleLiteral(arg1) && isSimpleLiteral(arg2)) - || (Literals.isLanguageLiteral(arg1) && Literals.isLanguageLiteral(arg2) - && arg1.getLanguage().equals(arg2.getLanguage())) - || (Literals.isLanguageLiteral(arg1) && isSimpleLiteral(arg2)); + || (Literals.isLanguageLiteral(arg1) && Literals.isLanguageLiteral(arg2) + && arg1.getLanguage().equals(arg2.getLanguage())) + || (Literals.isLanguageLiteral(arg1) && isSimpleLiteral(arg2)); } /** @@ -625,8 +631,8 @@ public static boolean isStringLiteral(Literal l) { private static boolean isSupportedDatatype(CoreDatatype datatype) { return datatype != null && datatype.isXSDDatatype() - && (datatype == CoreDatatype.XSD.STRING || ((CoreDatatype.XSD) datatype).isNumericDatatype() - || ((CoreDatatype.XSD) datatype).isCalendarDatatype()); + && (datatype == CoreDatatype.XSD.STRING || ((CoreDatatype.XSD) datatype).isNumericDatatype() + || ((CoreDatatype.XSD) datatype).isCalendarDatatype()); } public enum Result { @@ -712,35 +718,35 @@ public Result toResult(CompareOp operator) { if (this == notEqual) { switch (operator) { - case EQ: - return Result._false; - case NE: - return Result._true; + case EQ: + return Result._false; + case NE: + return Result._true; + case LT: + case LE: + case GE: + case GT: + return Result.incompatibleValueExpression; + default: + return Result.illegalArgument; + } + } + + switch (operator) { case LT: + return Result.fromBoolean(value < 0); case LE: + return Result.fromBoolean(value <= 0); + case EQ: + return Result.fromBoolean(value == 0); + case NE: + return Result.fromBoolean(value != 0); case GE: + return Result.fromBoolean(value >= 0); case GT: - return Result.incompatibleValueExpression; + return Result.fromBoolean(value > 0); default: return Result.illegalArgument; - } - } - - switch (operator) { - case LT: - return Result.fromBoolean(value < 0); - case LE: - return Result.fromBoolean(value <= 0); - case EQ: - return Result.fromBoolean(value == 0); - case NE: - return Result.fromBoolean(value != 0); - case GE: - return Result.fromBoolean(value >= 0); - case GT: - return Result.fromBoolean(value > 0); - default: - return Result.illegalArgument; } } } diff --git a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java index f142b72b1e5..469c709e098 100644 --- a/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java +++ b/core/queryalgebra/evaluation/src/main/java/org/eclipse/rdf4j/query/algebra/evaluation/util/ValueComparator.java @@ -45,6 +45,10 @@ public int compare(Value o1, Value o2) { return 1; } + if(o1.getClass() == o2.getClass()){ + return compareSameTypes(o1, o2, o1.getValueType()); + } + Value.Type o1Type = o1.getValueType(); Value.Type o2Type = o2.getValueType(); diff --git a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java index 53b1999234e..3713281367e 100644 --- a/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java +++ b/core/queryalgebra/evaluation/src/test/java/org/eclipse/rdf4j/query/algebra/evaluation/util/OrderComparatorTest.java @@ -14,6 +14,7 @@ import java.time.Instant; import java.util.Arrays; +import java.util.Comparator; import java.util.Date; import java.util.Iterator; import java.util.List; @@ -109,7 +110,7 @@ public void setQueryEvaluationMode(QueryEvaluationMode queryEvaluationMode) { } } - class ComparatorStub extends ValueComparator { + class ComparatorStub implements Comparator { Iterator iter; diff --git a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java index 9b5dd0e0a2a..25163ccd867 100644 --- a/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java +++ b/core/sail/memory/src/test/java/org/eclipse/rdf4j/sail/memory/benchmark/SortBenchmark.java @@ -43,10 +43,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; -import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; /** * @author HÃ¥vard Ottestad @@ -84,12 +81,14 @@ public static void main(String[] args) throws RunnerException, IOException, Inte // // new Runner(opt).run(); + long temp = 0; SortBenchmark sortBenchmark = new SortBenchmark(); sortBenchmark.setup(); - for (int i = 0; i < 1000; i++) { + for (int i = 0; i < 2; i++) { System.out.println("i = " + i); - sortBenchmark.sortDirectlySingleThreaded(); + temp += sortBenchmark.compareAllDirectlySingleThreaded(); } + System.out.println("temp = " + temp); } @Setup(Level.Trial) @@ -175,4 +174,22 @@ public Value sortDirectlySingleThreaded() { } + @Benchmark + public long compareAllDirectlySingleThreaded() { + + ValueComparator valueComparator = new ValueComparator(); + long compare = 0; + + + for (Value value1 : valuesList) { + for (Value value2 : valuesList) { + compare += valueComparator.compare(value1, value2); + + } + } + + return compare; + + } + }