Skip to content

Commit

Permalink
More logic about strict-equality compatibility moved to DBTermType.
Browse files Browse the repository at this point in the history
  • Loading branch information
bcogrel committed Nov 2, 2019
1 parent 02f17b5 commit 4dc694f
Show file tree
Hide file tree
Showing 18 changed files with 268 additions and 142 deletions.
Expand Up @@ -11,6 +11,7 @@
import javax.annotation.Nullable;
import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Stream;

public class DefaultSimpleDBCastFunctionSymbol extends AbstractDBTypeConversionFunctionSymbolImpl {

Expand Down Expand Up @@ -100,7 +101,9 @@ public String getNativeDBString(ImmutableList<? extends ImmutableTerm> terms,
protected IncrementalEvaluation evaluateStrictEqWithNonNullConstant(ImmutableList<? extends ImmutableTerm> terms,
NonNullConstant otherTerm, TermFactory termFactory,
VariableNullability variableNullability) {
if ((inputType != null) && inputType.areLexicalTermsUnique()) {
if ((inputType != null)
&& (otherTerm.getType() instanceof DBTermType)
&& areCompatibleForStrictEq(inputType, (DBTermType) otherTerm.getType())) {
ImmutableExpression newEquality = termFactory.getStrictEquality(
terms.get(0),
termFactory.getDBConstant(otherTerm.getValue(), inputType));
Expand All @@ -110,4 +113,14 @@ protected IncrementalEvaluation evaluateStrictEqWithNonNullConstant(ImmutableLis
else
return IncrementalEvaluation.declareSameExpression();
}

private boolean areCompatibleForStrictEq(DBTermType type1, DBTermType type2) {
return Stream.of(type1.areEqualitiesStrict(type2), type2.areEqualitiesStrict(type1))
.filter(Optional::isPresent)
.map(Optional::get)
.reduce((b1, b2) -> b1 && b2)
.orElse(false);
}


}
Expand Up @@ -154,15 +154,15 @@ private ImmutableTerm liftIfElseNull(ImmutableList<ImmutableTerm> terms, int ind
@Override
public IncrementalEvaluation evaluateStrictEq(ImmutableList<? extends ImmutableTerm> terms, ImmutableTerm otherTerm,
TermFactory termFactory, VariableNullability variableNullability) {
boolean differentTypeDetected = inferType(terms)
boolean incompatibleTypesDetected = inferType(terms)
.flatMap(TermTypeInference::getTermType)
.map(t1 -> otherTerm.inferType()
.flatMap(TermTypeInference::getTermType)
.map(t2 -> !areEquivalentForStrictEq(t1,t2))
.map(t2 -> areIncompatibleForStrictEq(t1,t2))
.orElse(false))
.orElse(false);

if (differentTypeDetected)
if (incompatibleTypesDetected)
return IncrementalEvaluation.declareIsFalse();

if ((otherTerm instanceof ImmutableFunctionalTerm))
Expand All @@ -176,19 +176,13 @@ else if (otherTerm instanceof NonNullConstant) {
return IncrementalEvaluation.declareSameExpression();
}

private boolean areEquivalentForStrictEq(TermType type1, TermType type2) {
/**
* Different types are only tolerated for DB term types
*/
private boolean areIncompatibleForStrictEq(TermType type1, TermType type2) {
if (type1.equals(type2))
return true;
if (!((type1 instanceof DBTermType) && (type2 instanceof DBTermType)))
return false;

DBTermType dbType1 = (DBTermType) type1;
DBTermType dbType2 = (DBTermType) type2;
DBTermType.Category category1 = dbType1.getCategory();

return (category1 == dbType2.getCategory())
&& category1.isTreatingSameCategoryTypesAsEquivalentInStrictEq();

return !((type1 instanceof DBTermType) && (type2 instanceof DBTermType));
}

/**
Expand Down
Expand Up @@ -52,10 +52,9 @@ public int hashCode() {
* This method directly refers to the notion of strict-equality.
* Is under 2VL and treats the NULLs of strict-equalities as false.
*
* For DBConstants, different types belonging to the same category may be considered as
* equivalent by strict-equalities and may therefore not prevent this test from passing.
* For DBConstants, term types are NOT CONSIDERED for this test. Only the lexical string matters.
*
* This tolerance comes from the fact that DBs like PostgreSQL offer almost-identical datatypes
* This tolerance initially comes from the fact that DBs like PostgreSQL offer almost-identical datatypes
* such as SERIAL and INT4 over which one would like to join and over which foreign keys may hold.
* For the sake of simplicity, Ontop treats these types as equivalent in strict-equality,
* which enables FK-based optimization to be applied. Observes that the tiny technical difference between
Expand All @@ -72,22 +71,12 @@ public int hashCode() {
public boolean equals(Object other) {
if (other instanceof DBConstant) {
DBConstant otherConstant = (DBConstant) other;
return otherConstant.getValue().equals(value)
&& isOtherTypeEquivalentForStrictEquality(otherConstant.getType());
return otherConstant.getValue().equals(value);
}
else
return false;
}

private boolean isOtherTypeEquivalentForStrictEquality(DBTermType otherConstantType) {
if (termType.equals(otherConstantType))
return true;

DBTermType.Category otherCategory = otherConstantType.getCategory();
return (otherCategory == termType.getCategory())
&& otherCategory.isTreatingSameCategoryTypesAsEquivalentInStrictEq();
}

@Override
public IncrementalEvaluation evaluateStrictEq(ImmutableTerm otherTerm, VariableNullability variableNullability) {
if (otherTerm instanceof Constant) {
Expand Down
Expand Up @@ -21,41 +21,37 @@ public interface DBTermType extends TermType {
boolean isNeedingIRISafeEncoding();

/**
* Returns true if the mapping VALUE -> LEXICAL TERM is unique.
* Returns true if the non-strict equality between two terms of this type
* is equivalent to a strict equality
*/
boolean areEqualitiesStrict();

/**
* Returns true if the non-strict equality between terms of these two types
* are equivalent to a strict equality
*/
Optional<Boolean> areEqualitiesStrict(DBTermType otherType);

/**
* Returns true if the non-strict equality between two attributes of the same database
* of this type is equivalent to a strict equality.
*
* Not the case for instance for floating numbers, timestamp with timezone, etc.
* Useful for floating numbers.
*
* Useful for decomposing constant IRIs
* Note that we are NOT considering here equalities with constants coming from source part
* of the mapping assertion.
*
*/
boolean areLexicalTermsUnique();
boolean areEqualitiesBetweenTwoDBAttributesStrict();

/**
* Returns true if the non-strict equality between two terms of this type
* is equivalent to a strict equality
*/
boolean areEqualitiesStrict();

enum Category {
STRING(true),
INTEGER(true),
DECIMAL(false),
FLOAT_DOUBLE(false),
BOOLEAN(false),
DATETIME(false),
OTHER(false);

private final boolean treatSameCategoryTypesAsEquivalentInStrictEq;

Category(boolean treatSameCategoryTypesAsEquivalentInStrictEq) {
this.treatSameCategoryTypesAsEquivalentInStrictEq = treatSameCategoryTypesAsEquivalentInStrictEq;
}

/**
* For instance, STRICT_EQ("ab"^^TEXT, "ab"^^VARCHAR) evaluates as true
*/
public boolean isTreatingSameCategoryTypesAsEquivalentInStrictEq() {
return treatSameCategoryTypesAsEquivalentInStrictEq;
}
STRING,
INTEGER,
DECIMAL,
FLOAT_DOUBLE,
BOOLEAN,
DATETIME,
OTHER
}
}
Expand Up @@ -10,9 +10,8 @@ public class BooleanDBTermType extends DBTermTypeImpl implements DBTermType {

private final RDFDatatype xsdBooleanDatatype;

public BooleanDBTermType(String booleanStr, TermTypeAncestry ancestry, RDFDatatype xsdBooleanDatatype,
boolean areLexicalTermsUnique) {
super(booleanStr, ancestry, false, false);
public BooleanDBTermType(String booleanStr, TermTypeAncestry ancestry, RDFDatatype xsdBooleanDatatype) {
super(booleanStr, ancestry, false);
this.xsdBooleanDatatype = xsdBooleanDatatype;
}

Expand All @@ -32,10 +31,21 @@ public boolean isNeedingIRISafeEncoding() {
}

/**
* TODO: look at it seriously
* Constants often can have different values (true, false, 0, 1).
* TODO: double-check
*/
@Override
public boolean areEqualitiesStrict() {
return false;
}

@Override
public Optional<Boolean> areEqualitiesStrict(DBTermType otherType) {
return Optional.of(false);
}

@Override
public boolean areEqualitiesBetweenTwoDBAttributesStrict() {
return true;
}
}
Expand Up @@ -6,12 +6,10 @@
public abstract class DBTermTypeImpl extends TermTypeImpl implements DBTermType {

private final String name;
private final boolean areLexicalTermsUnique;

protected DBTermTypeImpl(String name, TermTypeAncestry parentAncestry, boolean isAbstract, boolean areLexicalTermsUnique) {
protected DBTermTypeImpl(String name, TermTypeAncestry parentAncestry, boolean isAbstract) {
super(name, parentAncestry, isAbstract);
this.name = name;
this.areLexicalTermsUnique = areLexicalTermsUnique;
}

@Override
Expand All @@ -26,9 +24,4 @@ public String getName() {
public String getCastName() {
return name;
}

@Override
public boolean areLexicalTermsUnique() {
return areLexicalTermsUnique;
}
}
@@ -1,5 +1,6 @@
package it.unibz.inf.ontop.model.type.impl;

import it.unibz.inf.ontop.model.type.DBTermType;
import it.unibz.inf.ontop.model.type.RDFDatatype;
import it.unibz.inf.ontop.model.type.TermTypeAncestry;

Expand All @@ -8,9 +9,8 @@
public class DatetimeDBTermType extends DBTermTypeImpl {
private final RDFDatatype rdfDatatype;

protected DatetimeDBTermType(String name, TermTypeAncestry parentAncestry, RDFDatatype rdfDatatype,
boolean areLexicalTermsUnique) {
super(name, parentAncestry, false, areLexicalTermsUnique);
protected DatetimeDBTermType(String name, TermTypeAncestry parentAncestry, RDFDatatype rdfDatatype) {
super(name, parentAncestry, false);
this.rdfDatatype = rdfDatatype;
}

Expand All @@ -32,8 +32,24 @@ public boolean isNeedingIRISafeEncoding() {
return true;
}

/**
* TODO: check if TZ are allowed are not
*/
@Override
public boolean areEqualitiesStrict() {
return false;
}

@Override
public Optional<Boolean> areEqualitiesStrict(DBTermType otherType) {
return Optional.of(false);
}

/**
* TODO: check if TZ are allowed are not
*/
@Override
public boolean areEqualitiesBetweenTwoDBAttributesStrict() {
return false;
}
}
Expand Up @@ -14,7 +14,7 @@ public class MockupDBTypeFactory implements DBTypeFactory {
@AssistedInject
private MockupDBTypeFactory(@Assisted TermType rootTermType, @Assisted TypeFactory typeFactory) {
rootDBType = new NonStringNonNumberNonBooleanNonDatetimeDBTermType("AbstractDBType",
rootTermType.getAncestry(), true, false, false);
rootTermType.getAncestry(), true);
rootAncestry = rootDBType.getAncestry();
}

Expand Down Expand Up @@ -70,12 +70,12 @@ public DBTermType getAbstractRootDBType() {

@Override
public DBTermType getDBTermType(String typeName) {
return new NonStringNonNumberNonBooleanNonDatetimeDBTermType(typeName, rootAncestry, false, false, true);
return new NonStringNonNumberNonBooleanNonDatetimeDBTermType(typeName, rootAncestry, false);
}

@Override
public DBTermType getDBTermType(String typeName, int columnSize) {
return new NonStringNonNumberNonBooleanNonDatetimeDBTermType(typeName, rootAncestry, false, false, true);
return new NonStringNonNumberNonBooleanNonDatetimeDBTermType(typeName, rootAncestry, false);
}

@Override
Expand Down

0 comments on commit 4dc694f

Please sign in to comment.