-
Notifications
You must be signed in to change notification settings - Fork 0
Queryable and Filterable typings #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
35 commits
Select commit
Hold shift + click to select a range
8d364bd
first draft of the Queryable spec
jacoscaz 04daba8
adds undefined as a possible return type of BindingsFactory.merge()
jacoscaz d017b32
drops strong metadata typization
jacoscaz ea71d63
adds all the interfaces and types from the WebIDL version of the Filt…
jacoscaz 14e403e
adds limit, offset and available orders based on #8
jacoscaz 3400d5e
drops use of generics in Queryable(Algebra)Context as per #7
jacoscaz e84c9a9
uses generics to allow implementors to specify supported return types…
jacoscaz 3857a75
renames value methods in intermediate result objects to execute() and…
jacoscaz 8b076ac
adds support for custom properties in QueryOperationCost
jacoscaz 79a5f80
aliases Algebra to any
jacoscaz 331a63c
makes Bindings extend Iterable
jacoscaz d24f360
moves mutation methods from Bindings to BindingsFactory
jacoscaz 93ed430
renames FilterableResult#quads() to #execute() to align with Queryabl…
jacoscaz c7a7e46
drops BaseQueryableResult
jacoscaz aeff5ba
FilterableResultMetadataCount becomes FilterableResultMetadataCount
jacoscaz bc10881
count becomes cardinality
jacoscaz e32c527
count becomes cardinality
jacoscaz 910f6ec
QueryableContext becomes QueryableStringContext
jacoscaz 75e2e51
offset becomes start, limit becomes length in FilterableSource
jacoscaz da34b6c
adds support for custom properties in FilterableResultMetadata
jacoscaz ee78abb
makes BindingsFactory#merge() return undefined on merge conflicts
jacoscaz 8e7f57c
merges QueryableResultMetadata and FilterableResultMetadata, Queryabl…
jacoscaz c24fb47
adds dedicated interface for execute() options
jacoscaz b1f2625
moves QueryResultBindings#variables into a dedicated interface extend…
jacoscaz 63c2d9e
Replace the "Queryable" prefix with "Query"
jacoscaz bba92c5
Replace the "Queryable" prefix with "Query"
jacoscaz 8b7abcb
renames QueryResult* to Query*
jacoscaz fc1d32a
drops isSupported()
jacoscaz 022adec
adds comments mentioning possible rejections in case of unsupported q…
jacoscaz 5e86528
renames type to resultType, refactors metadata to use specific methods
jacoscaz 1f6ca66
refactors high-level *Queryable interfaces into a single interface us…
jacoscaz a5fc74d
renames QueryResultExecuteOptions to QueryExecuteOptions
jacoscaz b12a29c
drops one layer of indirection when retrieving metadata
jacoscaz 035741f
fixes type resolution when dealing with metadata
jacoscaz e42a0fe
execute()'s options do not need to include the selected ordering's cost
jacoscaz File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,390 @@ | ||
|
||
import RDF from '@rdfjs/types'; | ||
import { Algebra } from 'sparqlalgebrajs'; | ||
import { EventEmitter } from 'events'; // TODO: refer to underlying interface, not to the class | ||
|
||
/****************************************************************************** | ||
COMMON INTERFACES AND TYPES | ||
*****************************************************************************/ | ||
|
||
/* | ||
* Helper union type | ||
*/ | ||
type TermName = 'subject' | 'predicate' | 'object' | 'graph'; | ||
|
||
/* | ||
* Custom typings for the RDF/JS Stream interface as the current | ||
* typings restrict the generic param Q to extensions of "BaseQuad", | ||
* meaning it cannot be used for Bindings. | ||
*/ | ||
export interface Stream<Q> extends EventEmitter { | ||
read(): Q | null; | ||
} | ||
|
||
|
||
/****************************************************************************** | ||
FILTERABLE SOURCE | ||
*****************************************************************************/ | ||
|
||
|
||
/** | ||
* QueryResultMetadataOptions is an abstract interface that represents a generic | ||
* expression over a stream of quads. | ||
*/ | ||
interface Expression { | ||
/** | ||
* Value that identifies the concrete interface of the expression, since the | ||
* Expression itself is not directly instantiated. Possible values include | ||
* "operator" and "term". | ||
*/ | ||
expressionType: string; | ||
}; | ||
|
||
/** | ||
* An OperatorExpression is represents an expression that applies a given | ||
* operator on given sub-expressions. | ||
* | ||
* The WebIDL definition of the Filterable spec contains a list of supported | ||
* operators: https://rdf.js.org/query-spec/#expression-operators | ||
*/ | ||
interface OperatorExpression extends Expression { | ||
|
||
/** | ||
* Contains the constant "operator". | ||
*/ | ||
expressionType: 'operator'; | ||
|
||
/** | ||
* Value that identifies an operator. Possible values can be found in the | ||
* list of operators. | ||
*/ | ||
operator: string; | ||
|
||
/** | ||
* Array of Expression's on to which the given operator applies. The length | ||
* of this array depends on the operator. | ||
*/ | ||
args: Expression[]; | ||
}; | ||
|
||
/** | ||
* A TermExpression is an expression that contains a Term. | ||
*/ | ||
interface TermExpression { | ||
|
||
/** | ||
* The constant "term". | ||
*/ | ||
expressionType: 'term'; | ||
|
||
/** | ||
* a Term. | ||
*/ | ||
term: RDF.Term; | ||
} | ||
|
||
/** | ||
* ExpressionFactory enables expressions to be created in an idiomatic manner. | ||
*/ | ||
interface ExpressionFactory { | ||
|
||
/** | ||
* Creates a new OperatorExpression instance for the given operator and array of arguments. | ||
*/ | ||
operatorExpression(operator: string, args: Expression[]): OperatorExpression; | ||
|
||
/** | ||
* Creates a new TermExpression instance for the given term. | ||
*/ | ||
termExpression(term: RDF.Term): TermExpression; | ||
}; | ||
|
||
|
||
/** | ||
* QueryResultMetadataCount is part of the QueryResultMetadata interface to | ||
* represent metadata about the number of quads in the result stream. | ||
*/ | ||
interface FilterableResultMetadataCount { | ||
/** | ||
* indicates the type of counting that was done, and MUST either be | ||
* "estimate" or "exact". | ||
*/ | ||
type: 'estimate' | 'exact'; | ||
|
||
/** | ||
* Indicates an estimate of the number of quads in the stream if | ||
* type = "estimate", or the exact number of quads in the stream if | ||
* type = "exact". | ||
*/ | ||
value: number; | ||
}; | ||
|
||
/** | ||
* TBD | ||
*/ | ||
interface FilterableCost { | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
/** | ||
* An estimation of how many iterations over items are executed. | ||
* This is used to determine the CPU cost. | ||
*/ | ||
iterations: number; | ||
/** | ||
* An estimation of how many items are stored in memory. | ||
* This is used to determine the memory cost. | ||
*/ | ||
persistedItems: number; | ||
/** | ||
* An estimation of how many items block the stream. | ||
* This is used to determine the time the stream is not progressing anymore. | ||
*/ | ||
blockingItems: number; | ||
/** | ||
* An estimation of the time to request items from sources. | ||
* This estimation can be based on the `cardinality`, `pageSize`, and `requestTime` metadata entries. | ||
* This is used to determine the I/O cost. | ||
*/ | ||
requestTime: number; | ||
} | ||
|
||
/** | ||
* TBD | ||
*/ | ||
interface FilterableOrder { | ||
cost: FilterableCost; | ||
terms: { term: TermName, direction: 'asc' | 'desc' }[]; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
/** | ||
* A QueryResultMetadata is an object that contains metadata about a certain | ||
* query result, such as invoking FilterableSource.matchExpression. | ||
*/ | ||
interface FilterableResultMetadata { | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
/** | ||
* An optional field that contains metadata about the number of quads in the | ||
* result stream. | ||
*/ | ||
count?: FilterableResultMetadataCount; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
/** | ||
* An optional field that contains the available options for quad sorting | ||
* based on the provided pattern, expression and options. | ||
*/ | ||
availableOrders?: FilterableOrder[]; | ||
}; | ||
|
||
/** | ||
* A QueryResultMetadataOptions is an object that gives suggestions on what | ||
* type of metadata is desired, such as when invoking FilterResult.metadata. | ||
*/ | ||
interface FilterableResultMetadataOptions { | ||
|
||
/** | ||
* optional field that MAY either contain "estimate" or "exact". If defined, | ||
* this type MUST correspond to the type in QueryResultMetadataCount. | ||
*/ | ||
count?: 'estimate' | 'exact'; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
}; | ||
|
||
|
||
|
||
/** | ||
* A FilterResult is an object that represents the result of a filter | ||
* expression of FilterableSource for a given quad pattern and expression. | ||
* It MAY create results lazily after one of its methods is invoked. | ||
*/ | ||
interface FilterableResult { | ||
|
||
/** | ||
* Returns a Stream containing all the quads that matched the given quad | ||
* pattern and expression. | ||
*/ | ||
quads(opts?: { order?: FilterableOrder }): Stream<RDF.Quad>; | ||
|
||
/** | ||
* Asynchronously returns a QueryResultMetadata, that contains the metadata | ||
* of the current result. | ||
*/ | ||
metadata(opts?: FilterableResultMetadataOptions): Promise<FilterableResultMetadata>; | ||
|
||
/** | ||
* Asynchronously returns a boolean indicating if the requested expression is | ||
* supported by the FilterableSource. If it returns true, quads() and | ||
* metadata() MAY produce a valid result. If it returns false, quads() MUST | ||
* return a stream emitting an error, and metadata() MUST reject. | ||
*/ | ||
isSupported(): Promise<boolean>; | ||
}; | ||
|
||
/* | ||
* A FilterableSource is an object that produces a FilterableSourceResult that | ||
* can emit quads. The emitted quads can be directly contained in this | ||
* FilterableSourceo bject, or they can be generated on the fly. | ||
* | ||
* FilterableSource is not necessarily an extension of the RDF/JS Source | ||
* interface, but implementers MAY decide to implement both at the same time. | ||
* | ||
* matchExpression() Returns a FilterableSourceResult that contains a quad | ||
* stream that processes all quads matching the quad pattern and the expression. | ||
* | ||
* When a Term parameter is defined, and is a NamedNode, Literal or BlankNode, | ||
* it must match each produced quad, according to the Quad.equals semantics. | ||
* When a Term parameter is a Variable, or it is undefined, it acts as a | ||
* wildcard, and can match with any Term. | ||
* | ||
* NOTES: | ||
* - When matching with graph set to undefined or null it MUST match all the | ||
* graphs (sometimes called the union graph). To match only the default graph | ||
* set graph to a DefaultGraph. | ||
* - When an Expression parameter is defined, the complete quad stream is | ||
* filtered according to this expression. When it is undefined, no filter is | ||
* applied. | ||
* | ||
* If parameters of type Variable with an equal variable name are in place, | ||
* then the corresponding quad components in the resulting quad stream MUST be | ||
* equal. | ||
* Expression's MAY contain Variable Term's. If their variable names are equal | ||
* to Variable's in the given quad pattern, then the Expression MUST be | ||
* instantiated for each variable's binding in the resulting quad stream when | ||
* applying the Expression filter. | ||
*/ | ||
interface FilterableSource { | ||
matchExpression( | ||
subject?: RDF.Term, | ||
predicate?: RDF.Term, | ||
obj?: RDF.Term, | ||
graph?: RDF.Term, | ||
expression?: Expression, | ||
opts?: { | ||
limit?: number; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
offset?: number; | ||
}, | ||
): FilterableResult; | ||
}; | ||
|
||
|
||
/****************************************************************************** | ||
QUERYABLE SOURCE | ||
*****************************************************************************/ | ||
|
||
/* | ||
* Map-like representation of Bindings as using plain objects could lead | ||
* to collisions between variable names and object properties. | ||
* | ||
* Long-term goal: maintain compatibility with the native Map class. | ||
*/ | ||
jacoscaz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
interface Bindings { | ||
type: 'bindings'; | ||
get(variable: RDF.Variable): RDF.Term; | ||
keys(): RDF.Variable[]; | ||
entries(): [RDF.Variable, RDF.Term][]; | ||
size: number; | ||
} | ||
|
||
/* | ||
* Bindings objects are created using a dedicated factory, keeping in line | ||
* with DataFactory.quad(). This also helps with facilitating support for | ||
* immutability. Basic helper methods must also be provided for the most | ||
* common manipulations of bindings objects. | ||
*/ | ||
interface BindingsFactory { | ||
jacoscaz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
bindings(entries: [RDF.Variable, RDF.Term][]): Bindings; | ||
// NOTE: returns undefined in case of conflicting bindings, i.e. bindings | ||
// having the same variables. | ||
merge(bindings: Bindings[]): Bindings|undefined; | ||
} | ||
|
||
/* | ||
* Base interfaces to represent query results. These interfaces are generic | ||
* with respect to the types of query metadata objects. These can be extended | ||
* by implementors. | ||
*/ | ||
|
||
interface QueryableResultMetadata<OrderItemsType> { | ||
cardinality?: number; | ||
order?: OrderItemsType[]; | ||
[key: string]: any; | ||
} | ||
|
||
interface BaseQueryableResult<MetadataOrderType> { | ||
type: 'bindings' | 'quads' | 'boolean'; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
metadata(opts: { [key: string]: any }): Promise<QueryableResultMetadata<MetadataOrderType>>; | ||
} | ||
|
||
interface QueryableResultBindings extends BaseQueryableResult<RDF.Variable> { | ||
type: 'bindings'; | ||
stream(): Stream<Bindings>; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
variables: RDF.Variable[]; | ||
} | ||
|
||
interface QueryableResultQuads extends BaseQueryableResult<TermName> { | ||
type: 'quads'; | ||
stream(): Stream<RDF.Quad>; | ||
} | ||
|
||
interface QueryableResultBoolean extends BaseQueryableResult<any> { | ||
type: 'boolean'; | ||
value(): Promise<boolean>; | ||
} | ||
|
||
type QueryableResult = QueryableResultBindings | QueryableResultQuads | QueryableResultBoolean;/* | ||
* Context objects provide a way to pass additional bits information to | ||
* implementors, such as but not limited to: | ||
* - data sources | ||
* - base IRI for IRI resolution | ||
* - timestamp for expression evaluation | ||
* - query language | ||
* - ... | ||
*/ | ||
|
||
// SourceType can be anything the query engine defines | ||
// TODO: we may consider defining some standards, like 'string', RDF.Source, ... | ||
interface QueryableContext<SourceType> { | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
sources: [SourceType, ...SourceType[]]; | ||
jacoscaz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
queryTimestamp?: Date; // Required for certain SPARQL operations such as NOW(). | ||
[key: string]: any; | ||
} | ||
|
||
interface QueryableStringContext<SourceType> extends QueryableContext<SourceType> { | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
queryFormat?: QueryableFormat; // defaults to { language: 'SPARQL', version: '1.1', extensions: [] } | ||
baseIRI?: string; // Required for parsing SPARQL queries | ||
}; | ||
|
||
interface QueryableAlgebraContext<SourceType> extends QueryableContext<SourceType> {}; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
interface QueryableFormat { | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
language: string; // Like 'SPARQL' | ||
version: string; // Like '1.1' | ||
extensions: string[]; // TODO: leave the syntax of these extensions open for now? | ||
} | ||
|
||
/* | ||
* Generic query interfaces. These allow engines to return any type of result | ||
* object for any type of query, supporting the kind of flexibility required | ||
* by engines such as Comunica. | ||
*/ | ||
|
||
interface Queryable<SourceType> { | ||
query(query: string, context?: QueryableStringContext<SourceType>): Promise<QueryableResult>; | ||
} | ||
|
||
interface QueryableAlgebra<SourceType> { | ||
query(query: Algebra.Operation, context?: QueryableAlgebraContext<SourceType>): Promise<QueryableResult>; | ||
} | ||
|
||
/* | ||
* SPARQL-constrainted query interfaces. These interfaces guarantee that result | ||
* objects are of the expected type as defined by the SPARQL spec. | ||
*/ | ||
|
||
interface QueryableSparql<SourceType> { | ||
boolean?(query: string, context?: QueryableContext<SourceType>): Promise<QueryableResultBoolean>; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
bindings?(query: string, context?: QueryableContext<SourceType>): Promise<QueryableResultBindings>; | ||
quads?(query: string, context?: QueryableContext<SourceType>): Promise<QueryableResultQuads>; | ||
} | ||
|
||
interface QueryableAlgebraSparql<SourceType> { | ||
boolean?(query: Algebra.Ask, context?: QueryableAlgebraContext<SourceType>): Promise<QueryableResultBoolean>; | ||
jacoscaz marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
bindings?(query: Algebra.Project, context?: QueryableAlgebraContext<SourceType>): Promise<QueryableResultBindings>; | ||
quads?(query: Algebra.Construct, context?: QueryableAlgebraContext<SourceType>): Promise<QueryableResultQuads>; | ||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.