4using System.Threading.Tasks;
56 private readonly KeyValuePair<ScriptNode, bool>[] orderBy;
59 private readonly
int? limit;
60 private readonly
int? offset;
61 private readonly
bool distinct;
62 private readonly
bool reduced;
63 private Dictionary<UriNode, ISemanticCube> namedGraphs;
64 private UriNode[] namedGraphNames;
90 KeyValuePair<ScriptNode, bool>[] OrderBy,
int? Limit,
int? Offset,
95 this.distinct = Distinct;
96 this.reduced = Reduced;
99 this.construct = Construct;
101 this.columns = Columns;
104 this.columnNames = ColumnNames;
109 this.namedGraphs = NamedGraphs;
111 this.namedGraphNames =
new UriNode[NamedGraphs?.Count ?? 0];
112 NamedGraphs?.Keys.CopyTo(this.namedGraphNames, 0);
117 this.groupBy = GroupBy;
120 this.groupByNames = GroupByNames;
123 this.having = Having;
126 this.orderBy = OrderBy;
128 if (!(this.orderBy is
null))
130 foreach (KeyValuePair<ScriptNode, bool> P
in this.orderBy)
131 P.Key.SetParent(
this);
175 IEnumerable<Possibility> ExistingMatches)
180 if (this.from is
null)
183 From = v.ValueObject;
187 DataSet.
Add(await this.GetDataSource(From,
Variables,
false));
194 DataSet.
Add(await this.GetDataSource(From,
Variables,
false));
198 IEnumerable<ISparqlResultRecord> Possibilities;
200 if (this.where is
null)
201 Possibilities = ExistingMatches;
203 Possibilities = await this.where.Search(DataSet,
Variables, ExistingMatches,
this);
205 if (!(this.groupBy is
null) && !(Possibilities is
null))
207 Dictionary<string, bool> VectorProperties =
null;
209 if (!(this.columns is
null))
219 if (VectorProperties is
null)
220 VectorProperties =
new Dictionary<string, bool>();
222 VectorProperties[Ref.VariableName] =
true;
233 SortedDictionary<ISparqlResultRecord, KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>>> Groups =
234 new SortedDictionary<ISparqlResultRecord, KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>>>(GroupComparer);
241 if (LastRecord is
null || GroupComparer.Compare(LastRecord, P) != 0)
252 Groups[P] =
new KeyValuePair<ISparqlResultRecord, ChunkedList<ISparqlResultRecord>>(P, LastList);
260 if (!(VectorProperties is
null))
262 foreach (
string VectorProperty
in VectorProperties.Keys)
268 LastRecord[VectorProperty] = Vector;
274 Vector.Add(P[VectorProperty]);
281 Possibilities = Groups.Keys;
283 if (!(this.having is
null))
292 if (RecordVariables is
null)
295 RecordVariables.Object =
Record;
297 object Value = await EvaluateValue(RecordVariables, this.having);
298 if (Value is
bool b && b)
307 Possibilities = Filtered;
311 switch (this.queryType)
314 if (!(Possibilities is
null))
316 using (IEnumerator<ISparqlResultRecord> e = Possibilities.GetEnumerator())
325 Dictionary<string, int> ColumnVariables =
new Dictionary<string, int>();
332 if (this.columns is
null)
338 int Columns = this.columns.Length;
340 c = this.columnNames?.Length ?? 0;
342 for (i = 0; i < Columns; i++)
344 if (i < c && !(this.columnNames[i] is
null))
347 Name = Ref2.VariableName;
351 ColumnVariables[Name] = i;
352 ColumnNames.
Add(Name);
361 Name = Ref.VariableName;
363 ColumnVariables[Name] = i;
364 ColumnNames.
Add(Name);
368 if (ColumnScript is
null)
371 ColumnScript.
Add(
new KeyValuePair<ScriptNode, int>(Ref, i));
376 if (ColumnScript is
null)
379 ColumnScript.
Add(
new KeyValuePair<ScriptNode, int>(this.columns[i], i));
383 Name =
" c" + i.ToString();
384 ColumnNames.
Add(Name);
390 List<ISparqlResultRecord> Records =
new List<ISparqlResultRecord>();
391 bool MakeUnique = this.distinct || this.reduced;
392 Dictionary<string, bool> Distinct = MakeUnique ?
new Dictionary<string, bool>() :
null;
393 StringBuilder sb = MakeUnique ?
new StringBuilder() :
null;
396 if (!(Possibilities is
null))
400 Dictionary<string, ISparqlResultItem>
Record =
new Dictionary<string, ISparqlResultItem>();
406 if (ColumnVariables.TryGetValue(Name, out i))
410 i = ColumnNames.
Count;
411 ColumnNames.
Add(Name);
412 ColumnVariables[Name] = i;
418 if (!(ColumnScript is
null))
420 if (RecordVariables is
null)
423 RecordVariables.Object = P;
425 foreach (KeyValuePair<ScriptNode, int> P2
in ColumnScript)
427 Name = ColumnNames[P2.Value];
428 ISemanticElement Literal = await this.EvaluateSemanticElement(RecordVariables, P2.Key);
430 if (!(Literal is
null))
451 sb.Append(Value.
Name);
453 sb.Append(Value.
Value?.ToString());
456 string Key = sb.ToString();
458 if (Distinct.ContainsKey(Key))
461 Distinct[Key] =
true;
468 if (!(this.orderBy is
null))
471 if (this.offset.HasValue ||
this.limit.HasValue)
473 int Offset = this.offset ?? 0;
474 int MaxCount = this.limit ??
int.MaxValue;
475 int Count = Records.Count;
477 while (Offset > 0 && Count > 0)
484 while (Count > MaxCount)
486 Records.RemoveAt(MaxCount);
495 Dictionary<string, string> BlankNodeDictionary =
null;
497 IEnumerable<ISparqlResultRecord> Items = Possibilities;
499 RecordVariables =
null;
501 if (!(Items is
null))
503 if (!(this.orderBy is
null))
505 List<ISparqlResultRecord> Ordered =
new List<ISparqlResultRecord>();
514 int Offset = this.offset ?? 0;
515 int MaxCount = this.limit ??
int.MaxValue;
528 BlankNodeDictionary?.Clear();
530 if (RecordVariables is
null)
533 RecordVariables.Object = P;
542 if (BlankNodeDictionary is
null)
543 BlankNodeDictionary =
new Dictionary<string, string>();
545 if (!BlankNodeDictionary.TryGetValue(BnS.NodeId, out
string NewLabel))
547 NewLabel =
"n" + Guid.NewGuid().ToString();
548 BlankNodeDictionary[BnS.NodeId] = NewLabel;
555 if (Predicate is
null)
559 if (BlankNodeDictionary is
null)
560 BlankNodeDictionary =
new Dictionary<string, string>();
562 if (!BlankNodeDictionary.TryGetValue(BnP.NodeId, out
string NewLabel))
564 NewLabel =
"n" + Guid.NewGuid().ToString();
565 BlankNodeDictionary[BnP.NodeId] = NewLabel;
576 if (BlankNodeDictionary is
null)
577 BlankNodeDictionary =
new Dictionary<string, string>();
579 if (!BlankNodeDictionary.TryGetValue(BnO.NodeId, out
string NewLabel))
581 NewLabel =
"n" + Guid.NewGuid().ToString();
582 BlankNodeDictionary[BnO.NodeId] = NewLabel;
605 else if (From is Uri Uri)
606 return await this.LoadGraph(Uri,
Variables, NullIfNotFound);
607 else if (From is
string s)
608 return await this.LoadGraph(
new Uri(s, UriKind.RelativeOrAbsolute),
Variables, NullIfNotFound);
620 internal static async Task<object> EvaluateValue(
Variables RecordVariables,
ScriptNode Node)
624 return (await Node.
EvaluateAsync(RecordVariables)).AssociatedObjectValue;
649 internal static async Task<object> EvaluateValue(
Variables RecordVariables,
654 return (await Node.
EvaluateAsync(RecordVariables, Cube, Query, P)).AssociatedObjectValue;
682 return this.EvaluateSemanticElement(RecordVariables, ScriptElement.Node);
684 return Task.FromResult(
Element);
687 internal async Task<ISemanticElement> EvaluateSemanticElement(
Variables RecordVariables,
ScriptNode Node)
689 object Value = await EvaluateValue(RecordVariables, Node);
707 if (!this.columns.ForAllChildNodes(Callback, State, Order))
710 if (!(this.where is
null) && !this.where.ForAllChildNodes(Callback, State, Order))
713 if (!(this.construct is
null) && !this.construct.ForAllChildNodes(Callback, State, Order))
717 if (!this.columns.ForAll(Callback,
this, State, Order ==
SearchMethod.TreeOrder))
720 if (!(this.where is
null) && !this.where.ForAll(Callback, State, Order))
723 if (!(this.construct is
null) && !this.construct.ForAll(Callback, State, Order))
728 if (!this.columns.ForAllChildNodes(Callback, State, Order))
731 if (!(this.where is
null) && !this.where.ForAllChildNodes(Callback, State, Order))
734 if (!(this.construct is
null) && !this.construct.ForAllChildNodes(Callback, State, Order))
745 !
AreEqual(this.columns, O.columns) ||
746 ((
this.where is
null) ^ (O.where is
null)) ||
747 ((
this.construct is
null) ^ (O.construct is
null)) ||
748 this.distinct != O.distinct ||
749 this.reduced != O.reduced ||
755 if (!(this.where is
null) && !this.where.Equals(O.where))
758 if (!(this.construct is
null) && !this.construct.Equals(O.construct))
767 int Result = base.GetHashCode();
770 Result ^= Result << 5 ^ this.distinct.GetHashCode();
771 Result ^= Result << 5 ^ this.reduced.GetHashCode();
773 if (!(this.where is
null))
774 Result ^= Result << 5 ^ this.where.GetHashCode();
776 if (!(this.construct is
null))
777 Result ^= Result << 5 ^ this.construct.GetHashCode();
782 private async Task<ISemanticCube> LoadGraph(Uri Uri,
Variables Variables,
bool NullIfNotFound)
797 return await Source.
LoadGraph(Uri,
this, NullIfNotFound, await Caller.GetOrigin());
802 return await Source.
LoadGraph(Uri,
this, NullIfNotFound, await Caller2.GetOrigin());
825 if (Source is
null && !NullIfNotFound)
826 throw new InvalidOperationException(
"Unable to get access to graph source: " + Uri.ToString());
836 internal UriNode GetGraphName(
object Name)
840 else if (Name is Uri Uri)
841 return new UriNode(Uri, Uri.ToString());
842 else if (Name is
string s &&
System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out Uri))
873 if (this.namedGraphs is
null)
874 this.namedGraphs =
new Dictionary<UriNode, ISemanticCube>();
876 lock (this.namedGraphs)
878 if (!(this.namedGraphs is
null) &&
879 this.namedGraphs.TryGetValue(Uri, out Cube) &&
886 Cube = await this.GetDataSource(Uri,
Variables,
true);
890 lock (this.namedGraphs)
892 this.namedGraphs[Uri] = Cube;
906 lock (this.namedGraphs)
908 foreach (KeyValuePair<UriNode, ISemanticCube> P
in this.namedGraphs)
912 if (NotLoaded is
null)
915 NotLoaded.
Add(P.Key);
920 if (NotLoaded is
null)
921 return Task.CompletedTask;
933 return this.LoadUnloadedNamedGraphs(
Variables, Convert(Names));
943 return this.LoadUnloadedNamedGraphs(
Variables, Convert(Names));
955 foreach (
UriNode Name
in Names)
958 await Task.WhenAll(Tasks.
ToArray());
971 private static UriNode[] Convert(
string[] Names)
973 int i, c = Names.Length;
976 for (i = 0; i < c; i++)
978 if (!Uri.TryCreate(Names[i], UriKind.RelativeOrAbsolute, out Uri Name))
979 throw new ArgumentException(
"Not a valid URI.", nameof(Names));
981 Nodes[i] =
new UriNode(Name, Names[i]);
997 private static UriNode[] Convert(Uri[] Names)
999 int i, c = Names.Length;
1002 for (i = 0; i < c; i++)
1015 if (this.namedGraphs is
null)
1016 this.namedGraphs =
new Dictionary<UriNode, ISemanticCube>();
1018 lock (this.namedGraphs)
1020 foreach (
UriNode Name
in Names)
1022 if (!this.namedGraphs.ContainsKey(Name))
1023 this.namedGraphs[Name] =
null;
1026 this.namedGraphNames =
new UriNode[this.namedGraphs.Count];
1027 this.namedGraphs.Keys.CopyTo(this.namedGraphNames, 0);
static async Task< InMemorySemanticCube > Create(ISemanticModel Model)
Creates an in-memory semantic cube from a semantic model.
In-memory semantic model.
Contains a vector of semantic elements.
Set of semantic elements.
static ISemanticElement Encapsulate(object Value)
Encapsulates an object as a semantic element.
Implements a semantic triple.
void Add(ISemanticCube Source)
Adds a source to the data set.
Contains a record from the results of a SPARQL query.
Contains an item in a record from the results of a SPARQL query.
Contains the results of a SPARQL query. https://www.w3.org/TR/2023/WD-sparql12-results-xml-20230516/ ...
Static interface for database persistence. In order to work, a database provider has to be assigned t...
This filter selects objects that have a named field equal to a given value.
A chunked list is a linked list of chunks of objects of type T .
int Count
Number of elements in collection.
void Add(T Item)
Adds an item to the collection.
T[] ToArray()
Returns an array containing all elements of the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
Base class for all types of elements.
Exception used to break a loop.
IElement LoopValue
Value to include in the loop's result.
Exception used to continue a loop.
IElement LoopValue
Value to include in the loop's result.
Script runtime exception.
IElement ReturnValue
Return value.
Script runtime exception.
Class managing a script expression.
Base class for all nodes in a parsed script tree.
bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, bool DepthFirst)
Calls the callback method for all child nodes.
int Length
Length of expression covered by node.
override string ToString()
static bool AreEqual(ScriptNode S1, ScriptNode S2)
Compares if two script nodes are equal.
int Start
Start position in script expression.
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed or created.
virtual Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection. This method should be ...
Represents a variable reference.
Comparer for grouping a SPARQL result set.
Comparer for ordering a SPARQL result set.
Represents a pattern in a SPARQL query.
Represents a possible solution during SPARQL evaluation.
Semantic element based on script.
Contains a reference to a graph in the graph store.
async Task< IGraphSource > GetGraphSource()
Gets a Graph Source object corresponding to the graph referenced by the object.
override int GetHashCode()
async Task< IElement > EvaluateAsync(Variables Variables, IEnumerable< Possibility > ExistingMatches)
Evaluates the node asynchronously, using the variables provided in the Variables collection.
static async Task< IGraphSource > GetSourceHandler(Uri Uri, bool NullIfNotFound)
Gets a graph source handler, given the Graph URI
void RegisterNamedGraph(params UriNode[] Names)
Registers implicitly defined named graphs, that may be used by GRAPH patterns, even if they are not n...
override bool ForAllChildNodes(ScriptNodeEventHandler Callback, object State, SearchMethod Order)
Calls the callback method for all child nodes.
override bool Equals(object obj)
override Task< IElement > EvaluateAsync(Variables Variables)
Evaluates the node asynchronously, using the variables provided in the Variables collection.
void RegisterNamedGraph(params string[] Names)
Registers implicitly defined named graphs, that may be used by GRAPH patterns, even if they are not n...
void RegisterNamedGraph(params Uri[] Names)
Registers implicitly defined named graphs, that may be used by GRAPH patterns, even if they are not n...
SparqlQuery(QueryType QueryType, bool Distinct, bool Reduced, ScriptNode[] Columns, ScriptNode[] ColumnNames, ScriptNode[] From, Dictionary< UriNode, ISemanticCube > NamedGraphs, ISparqlPattern Where, ScriptNode[] GroupBy, ScriptNode[] GroupByNames, ScriptNode Having, KeyValuePair< ScriptNode, bool >[] OrderBy, int? Limit, int? Offset, SparqlRegularPattern Construct, int Start, int Length, Expression Expression)
Executes a SPARQL query.
override IElement Evaluate(Variables Variables)
Evaluates the node, using the variables provided in the Variables collection.
UriNode[] NamedGraphNames
Names of named graphs, may be null.
override bool IsAsynchronous
If the node (or its decendants) include asynchronous evaluation. Asynchronous nodes should be evaluat...
Executes a SELECT statement against the object database.
Contains information about a variable.
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Tokens available in request.
static readonly RequestOrigin Empty
Empty request origin.
Interface for semantic cubes.
Interface for semantic nodes.
Interface for semantic models.
Interface for semantic triples.
ISemanticElement Object
Object element
ISemanticElement Predicate
Predicate element
ISemanticElement Subject
Subject element
Interface for items in a record from the results of a SPARQL query.
string Name
Name of item in record.
ISemanticElement Value
Value of item in record.
Interface for result records of a SPARQL query.
Basic interface for all types of elements.
object AssociatedObjectValue
Associated object value.
Interface for script nodes with asynchronous evaluation
Interface for filter nodes.
Task< IElement > EvaluateAsync(Variables Variables, ISemanticCube Cube, SparqlQuery Query, Possibility Possibility)
Evaluates the node, using the variables provided in the Variables collection.
Interface for graph sources.
Task< ISemanticCube > LoadGraph(Uri Source, ScriptNode Node, bool NullIfNotFound, RequestOrigin Caller)
Loads the graph
Interface for SPARQL patterns.
void SetParent(ScriptNode Parent)
Sets the parent node. Can only be used when expression is being parsed or created.
Interface for requestors that can act as an origin for distributed requests.
delegate bool ScriptNodeEventHandler(ScriptNode Node, out ScriptNode NewNode, object State)
Delegate for ScriptNode callback methods.
SearchMethod
Method to traverse the expression structure
QueryType
SPARQL query type.