Skip to content

Commit

Permalink
alternative orderBy
Browse files Browse the repository at this point in the history
  • Loading branch information
jitsedesmet committed Oct 24, 2023
1 parent e0dd496 commit bf457c9
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 81 deletions.
53 changes: 14 additions & 39 deletions packages/expression-evaluator/lib/evaluators/ExpressionEvaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,10 @@ export class ExpressionEvaluator implements IExpressionEvaluator {
// ==================================================================================================================
// ==================================================================================================================
// ==================================================================================================================
// TODO: make this order function a seperate class(it will be an actor)/ term comparator bus
// Determine the relative numerical order of the two given terms.
// In accordance with https://www.w3.org/TR/sparql11-query/#modOrderBy
public orderTypes(termA: RDF.Term | undefined, termB: RDF.Term | undefined, strict = false): -1 | 0 | 1 {
public orderTypes(termA: RDF.Term | undefined, termB: RDF.Term | undefined): -1 | 0 | 1 {
// Check if terms are the same by reference
if (termA === termB) {
return 0;
Expand All @@ -123,49 +124,20 @@ export class ExpressionEvaluator implements IExpressionEvaluator {
return 0;
}

// Handle quoted triples
if (termA.termType === 'Quad' && termB.termType === 'Quad') {
const orderSubject = this.orderTypes(
termA.subject, termB.subject, strict,
);
if (orderSubject !== 0) {
return orderSubject;
}
const orderPredicate = this.orderTypes(
termA.predicate, termB.predicate, strict,
);
if (orderPredicate !== 0) {
return orderPredicate;
}
const orderObject = this.orderTypes(
termA.object, termB.object, strict,
);
if (orderObject !== 0) {
return orderObject;
}
return this.orderTypes(
termA.graph, termB.graph, strict,
);
}

// Handle literals
if (termA.termType === 'Literal') {
return this.orderLiteralTypes(termA, <RDF.Literal>termB);
if (termA.termType === 'Literal' || termA.termType === 'Quad') {
return this.orderUsingSparqlFunctions(termA, <RDF.Literal | RDF.BaseQuad> termB);
}

// Handle all other types
if (strict) {
throw new Err.InvalidCompareArgumentTypes(termA, termB);
}
return this.comparePrimitives(termA.value, termB.value);
}

private orderLiteralTypes(litA: RDF.Literal, litB: RDF.Literal): -1 | 0 | 1 {
private orderUsingSparqlFunctions(litA: RDF.Literal | RDF.BaseQuad, litB: RDF.Literal | RDF.BaseQuad): -1 | 0 | 1 {
const isGreater = regularFunctions[C.RegularOperator.GT];
const isEqual = regularFunctions[C.RegularOperator.EQUAL];

const myLitA = this.transformer.transformLiteral(litA);
const myLitB = this.transformer.transformLiteral(litB);
const myLitA: E.Term = this.transformer.transformRDFTermUnsafe(litA);
const myLitB: E.Term = this.transformer.transformRDFTermUnsafe(litB);

try {
if ((<E.BooleanLiteral> isEqual.applyOnTerms([ myLitA, myLitB ], this)).typedValue) {
Expand All @@ -176,10 +148,13 @@ export class ExpressionEvaluator implements IExpressionEvaluator {
}
return -1;
} catch {
// Fallback to string-based comparison
const compareType = this.comparePrimitives(myLitA.dataType, myLitB.dataType);
if (compareType !== 0) {
return compareType;
if (litA.termType === 'Literal') {
// Fallback to string-based comparison
const compareType = this.comparePrimitives((<E.Literal<any>> myLitA).dataType,
(<E.Literal<any>> myLitB).dataType);
if (compareType !== 0) {
return compareType;
}
}
return this.comparePrimitives(myLitA.str(), myLitB.str());
}
Expand Down
48 changes: 11 additions & 37 deletions packages/expression-evaluator/lib/expressions/Term.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type * as RDF from '@rdfjs/types';
import { DataFactory } from 'rdf-data-factory';
import { TermTransformer } from '../transformers/TermTransformer';
import * as C from '../util/Consts';
import { TypeAlias, TypeURL } from '../util/Consts';

Expand Down Expand Up @@ -69,49 +68,20 @@ export class BlankNode extends Term {
// Quads -----------------------------------------------------------------
export class Quad extends Term {
public termType: TermType = 'quad';
private readonly transformer: TermTransformer;
private readonly valueTerm: RDF.BaseQuad;

public constructor(input: RDF.BaseQuad, superTypeProvider: ISuperTypeProvider) {
public constructor(public readonly subject: Term, public readonly predicate: Term, public readonly object: Term,
public readonly graph: Term) {
super();
this.transformer = new TermTransformer(superTypeProvider);
this.valueTerm = input;
}

public toRDF(): RDF.BaseQuad {
return this.valueTerm;
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
return DF.quad(this.subject.toRDF(), this.predicate.toRDF(), this.object.toRDF(), this.graph.toRDF());
}

public get subject(): Term {
return this.transformer.transformRDFTermUnsafe(this.RDFsubject);
}

public get predicate(): Term {
return this.transformer.transformRDFTermUnsafe(this.RDFpredicate);
}

public get object(): Term {
return this.transformer.transformRDFTermUnsafe(this.RDFobject);
}

public get graph(): Term {
return this.transformer.transformRDFTermUnsafe(this.RDFgraph);
}

public get RDFsubject(): RDF.Term {
return this.toRDF().subject;
}

public get RDFpredicate(): RDF.Term {
return this.toRDF().predicate;
}

public get RDFobject(): RDF.Term {
return this.toRDF().object;
}

public get RDFgraph(): RDF.Term {
return this.toRDF().graph;
public str(): string {
return `Quad: [${this.subject.str()}, ${this.predicate.str()}, ${this.object.str()}, ${this.graph.str()}]`;
}
}

Expand All @@ -125,6 +95,10 @@ export class DefaultGraph extends Term {
public toRDF(): RDF.DefaultGraph {
return DF.defaultGraph();
}

public str(): string {
return 'DefaultGraph';
}
}

// Literals-- -----------------------------------------------------------------
Expand Down
29 changes: 25 additions & 4 deletions packages/expression-evaluator/lib/functions/RegularFunctions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,29 @@ class LesserThan extends RegularFunction {
.booleanTest(() => (left, right) => left < right)
.set(
[ 'quad', 'quad' ],
exprEval => ([ left, right ]) => bool(exprEval.orderTypes(left.toRDF(), right.toRDF(), true) === -1),
exprEval => ([ left, right ]: [E.Quad, E.Quad]) => {
const orderSubject = this.applyOnTerms(
[ left.subject, right.subject ], exprEval,
);
if (orderSubject.coerceEBV()) {
return orderSubject;
}
const orderPredicate = this.applyOnTerms(
[ left.predicate, right.predicate ], exprEval,
);
if (orderPredicate.coerceEBV()) {
return orderPredicate;
}
const orderObject = this.applyOnTerms(
[ left.object, right.object ], exprEval,
);
if (orderObject.coerceEBV()) {
return orderObject;
}
return this.applyOnTerms(
[ left.graph, right.graph ], exprEval,
);
},
false,
)
.dateTimeTest(exprEval => (left, right) =>
Expand Down Expand Up @@ -1104,9 +1126,8 @@ class Triple extends RegularFunction {

protected overloads = declare(C.RegularOperator.TRIPLE)
.onTerm3(
exprEval => (...args) => new E.Quad(
DF.quad(args[0].toRDF(), args[1].toRDF(), args[2].toRDF()),
exprEval.superTypeProvider,
_ => (...args) => new E.Quad(
args[0], args[1], args[2], new E.DefaultGraph(),
),
)
.collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,12 @@ export class TermTransformer implements ITermTransformer {
case 'BlankNode':
return new E.BlankNode(term.term.value);
case 'Quad':
return new E.Quad(term.term, this.superTypeProvider);
return new E.Quad(
this.transformRDFTermUnsafe(term.term.subject),
this.transformRDFTermUnsafe(term.term.predicate),
this.transformRDFTermUnsafe(term.term.object),
this.transformRDFTermUnsafe(term.term.graph),
);
case 'DefaultGraph':
return new E.DefaultGraph();
default:
Expand Down

0 comments on commit bf457c9

Please sign in to comment.