2using System.Collections.Generic;
4using System.Threading.Tasks;
55 private readonly KeyValuePair<ScriptNode, bool>[] orderBy;
58 private readonly
int? limit;
59 private readonly
int? offset;
60 private readonly
bool distinct;
61 private readonly
bool reduced;
62 private Dictionary<UriNode, ISemanticCube> namedGraphs;
63 private UriNode[] namedGraphNames;
89 KeyValuePair<ScriptNode, bool>[] OrderBy,
int? Limit,
int? Offset,
94 this.distinct = Distinct;
95 this.reduced = Reduced;
98 this.construct = Construct;
100 this.columns = Columns;
103 this.columnNames = ColumnNames;
108 this.namedGraphs = NamedGraphs;
110 this.namedGraphNames =
new UriNode[NamedGraphs?.Count ?? 0];
111 NamedGraphs?.Keys.CopyTo(this.namedGraphNames, 0);
116 this.groupBy = GroupBy;
119 this.groupByNames = GroupByNames;
122 this.having = Having;
125 this.orderBy = OrderBy;
127 if (!(this.orderBy is
null))
129 foreach (KeyValuePair<ScriptNode, bool> P
in this.orderBy)
130 P.Key.SetParent(
this);
174 IEnumerable<Possibility> ExistingMatches)
179 if (this.from is
null)
182 From = v.ValueObject;
186 DataSet.
Add(await this.GetDataSource(From,
Variables,
false));
193 DataSet.
Add(await this.GetDataSource(From,
Variables,
false));
197 IEnumerable<ISparqlResultRecord> Possibilities;
199 if (this.where is
null)
200 Possibilities = ExistingMatches;
202 Possibilities = await this.where.Search(DataSet,
Variables, ExistingMatches,
this);
204 if (!(this.groupBy is
null) && !(Possibilities is
null))
206 Dictionary<string, bool> VectorProperties =
null;
208 if (!(this.columns is
null))
218 if (VectorProperties is
null)
219 VectorProperties =
new Dictionary<string, bool>();
221 VectorProperties[Ref.VariableName] =
true;
232 SortedDictionary<ISparqlResultRecord, KeyValuePair<ISparqlResultRecord, LinkedList<ISparqlResultRecord>>> Groups =
233 new SortedDictionary<ISparqlResultRecord, KeyValuePair<ISparqlResultRecord, LinkedList<ISparqlResultRecord>>>(GroupComparer);
234 LinkedList<ISparqlResultRecord> LastList =
null;
240 if (LastRecord is
null || GroupComparer.Compare(LastRecord, P) != 0)
242 if (Groups.TryGetValue(P, out KeyValuePair<
ISparqlResultRecord, LinkedList<ISparqlResultRecord>> P2))
250 LastList =
new LinkedList<ISparqlResultRecord>();
251 Groups[P] =
new KeyValuePair<ISparqlResultRecord, LinkedList<ISparqlResultRecord>>(P, LastList);
259 if (!(VectorProperties is
null))
261 foreach (
string VectorProperty
in VectorProperties.Keys)
267 LastRecord[VectorProperty] = Vector;
273 Vector.Add(P[VectorProperty]);
280 Possibilities = Groups.Keys;
282 if (!(this.having is
null))
284 LinkedList<ISparqlResultRecord> Filtered =
new LinkedList<ISparqlResultRecord>();
291 if (RecordVariables is
null)
294 RecordVariables.Object =
Record;
296 object Value = await EvaluateValue(RecordVariables, this.having);
297 if (Value is
bool b && b)
306 Possibilities = Filtered;
310 switch (this.queryType)
313 if (!(Possibilities is
null))
319 Dictionary<string, int> ColumnVariables =
new Dictionary<string, int>();
320 LinkedList<KeyValuePair<ScriptNode, int>> ColumnScript =
null;
321 List<string> ColumnNames =
new List<string>();
326 if (this.columns is
null)
332 int Columns = this.columns.Length;
334 c = this.columnNames?.Length ?? 0;
336 for (i = 0; i < Columns; i++)
338 if (i < c && !(this.columnNames[i] is
null))
341 Name = Ref2.VariableName;
343 Name = (await this.columnNames[i].EvaluateAsync(
Variables)).AssociatedObjectValue?.
ToString();
345 ColumnVariables[Name] = i;
346 ColumnNames.Add(Name);
355 Name = Ref.VariableName;
357 ColumnVariables[Name] = i;
358 ColumnNames.Add(Name);
362 if (ColumnScript is
null)
363 ColumnScript =
new LinkedList<KeyValuePair<ScriptNode, int>>();
365 ColumnScript.AddLast(
new KeyValuePair<ScriptNode, int>(Ref, i));
370 if (ColumnScript is
null)
371 ColumnScript =
new LinkedList<KeyValuePair<ScriptNode, int>>();
373 ColumnScript.AddLast(
new KeyValuePair<ScriptNode, int>(this.columns[i], i));
377 Name =
" c" + i.ToString();
378 ColumnNames.Add(Name);
384 List<ISparqlResultRecord> Records =
new List<ISparqlResultRecord>();
385 bool MakeUnique = this.distinct || this.reduced;
386 Dictionary<string, bool> Distinct = MakeUnique ?
new Dictionary<string, bool>() :
null;
387 StringBuilder sb = MakeUnique ?
new StringBuilder() :
null;
390 if (!(Possibilities is
null))
394 Dictionary<string, ISparqlResultItem>
Record =
new Dictionary<string, ISparqlResultItem>();
400 if (ColumnVariables.TryGetValue(Name, out i))
404 i = ColumnNames.Count;
405 ColumnNames.Add(Name);
406 ColumnVariables[Name] = i;
412 if (!(ColumnScript is
null))
414 if (RecordVariables is
null)
417 RecordVariables.Object = P;
419 foreach (KeyValuePair<ScriptNode, int> P2
in ColumnScript)
421 Name = ColumnNames[P2.Value];
422 ISemanticElement Literal = await this.EvaluateSemanticElement(RecordVariables, P2.Key);
424 if (!(Literal is
null))
445 sb.Append(Value.
Name);
447 sb.Append(Value.
Value?.ToString());
450 string Key = sb.ToString();
452 if (Distinct.ContainsKey(Key))
455 Distinct[Key] =
true;
462 if (!(this.orderBy is
null))
465 if (this.offset.HasValue ||
this.limit.HasValue)
467 int Offset = this.offset ?? 0;
468 int MaxCount = this.limit ??
int.MaxValue;
469 int Count = Records.Count;
471 while (Offset > 0 && Count > 0)
478 while (Count > MaxCount)
480 Records.RemoveAt(MaxCount);
489 Dictionary<string, string> BlankNodeDictionary =
null;
490 LinkedList<SemanticTriple> Construction =
new LinkedList<SemanticTriple>();
491 IEnumerable<ISparqlResultRecord> Items = Possibilities;
493 RecordVariables =
null;
495 if (!(Items is
null))
497 if (!(this.orderBy is
null))
499 List<ISparqlResultRecord> Ordered =
new List<ISparqlResultRecord>();
508 int Offset = this.offset ?? 0;
509 int MaxCount = this.limit ??
int.MaxValue;
522 BlankNodeDictionary?.Clear();
524 if (RecordVariables is
null)
527 RecordVariables.Object = P;
536 if (BlankNodeDictionary is
null)
537 BlankNodeDictionary =
new Dictionary<string, string>();
539 if (!BlankNodeDictionary.TryGetValue(BnS.NodeId, out
string NewLabel))
541 NewLabel =
"n" + Guid.NewGuid().ToString();
542 BlankNodeDictionary[BnS.NodeId] = NewLabel;
549 if (Predicate is
null)
553 if (BlankNodeDictionary is
null)
554 BlankNodeDictionary =
new Dictionary<string, string>();
556 if (!BlankNodeDictionary.TryGetValue(BnP.NodeId, out
string NewLabel))
558 NewLabel =
"n" + Guid.NewGuid().ToString();
559 BlankNodeDictionary[BnP.NodeId] = NewLabel;
570 if (BlankNodeDictionary is
null)
571 BlankNodeDictionary =
new Dictionary<string, string>();
573 if (!BlankNodeDictionary.TryGetValue(BnO.NodeId, out
string NewLabel))
575 NewLabel =
"n" + Guid.NewGuid().ToString();
576 BlankNodeDictionary[BnO.NodeId] = NewLabel;
582 Construction.AddLast(
new SemanticTriple(Subject, Predicate, Object));
599 else if (From is Uri Uri)
600 return await this.LoadGraph(Uri,
Variables, NullIfNotFound);
601 else if (From is
string s)
602 return await this.LoadGraph(
new Uri(s, UriKind.RelativeOrAbsolute),
Variables, NullIfNotFound);
614 internal static async Task<object> EvaluateValue(
Variables RecordVariables,
ScriptNode Node)
618 return (await Node.
EvaluateAsync(RecordVariables)).AssociatedObjectValue;
630 internal static async Task<object> EvaluateValue(
Variables RecordVariables,
635 return (await Node.
EvaluateAsync(RecordVariables, Cube, Query, P)).AssociatedObjectValue;
650 return this.EvaluateSemanticElement(RecordVariables, ScriptElement.Node);
652 return Task.FromResult(
Element);
655 internal async Task<ISemanticElement> EvaluateSemanticElement(
Variables RecordVariables,
ScriptNode Node)
657 object Value = await EvaluateValue(RecordVariables, Node);
675 if (!this.columns.ForAllChildNodes(Callback, State, Order))
678 if (!(this.where is
null) && !this.where.ForAllChildNodes(Callback, State, Order))
681 if (!(this.construct is
null) && !this.construct.ForAllChildNodes(Callback, State, Order))
685 if (!this.columns.ForAll(Callback,
this, State, Order ==
SearchMethod.TreeOrder))
688 if (!(this.where is
null) && !this.where.ForAll(Callback, State, Order))
691 if (!(this.construct is
null) && !this.construct.ForAll(Callback, State, Order))
696 if (!this.columns.ForAllChildNodes(Callback, State, Order))
699 if (!(this.where is
null) && !this.where.ForAllChildNodes(Callback, State, Order))
702 if (!(this.construct is
null) && !this.construct.ForAllChildNodes(Callback, State, Order))
713 !
AreEqual(this.columns, O.columns) ||
714 ((
this.where is
null) ^ (O.where is
null)) ||
715 ((
this.construct is
null) ^ (O.construct is
null)) ||
716 this.distinct != O.distinct ||
717 this.reduced != O.reduced ||
723 if (!(this.where is
null) && !this.where.Equals(O.where))
726 if (!(this.construct is
null) && !this.construct.Equals(O.construct))
735 int Result = base.GetHashCode();
738 Result ^= Result << 5 ^ this.distinct.GetHashCode();
739 Result ^= Result << 5 ^ this.reduced.GetHashCode();
741 if (!(this.where is
null))
742 Result ^= Result << 5 ^ this.where.GetHashCode();
744 if (!(this.construct is
null))
745 Result ^= Result << 5 ^ this.construct.GetHashCode();
750 private async Task<ISemanticCube> LoadGraph(Uri Uri,
Variables Variables,
bool NullIfNotFound)
765 return await Source.
LoadGraph(Uri,
this, NullIfNotFound, await Caller.GetOrigin());
770 return await Source.
LoadGraph(Uri,
this, NullIfNotFound, await Caller2.GetOrigin());
773 return await Source.
LoadGraph(Uri,
this, NullIfNotFound,
new RequestOrigin(
string.Empty,
null,
null,
null));
793 if (Source is
null && !NullIfNotFound)
794 throw new InvalidOperationException(
"Unable to get access to graph source: " + Uri.ToString());
809 else if (Name is Uri Uri)
811 else if (Name is
string s && System.Uri.TryCreate(s, UriKind.RelativeOrAbsolute, out Uri))
825 if (!(this.namedGraphs is
null) &&
832 Cube = await this.GetDataSource(Uri,
Variables,
true);
836 if (this.namedGraphs is
null)
837 this.namedGraphs =
new Dictionary<UriNode, ISemanticCube>();
839 this.namedGraphs[Uri] = Cube;
851 int i, c = Names.Length;
854 for (i = 0; i < c; i++)
856 if (!Uri.TryCreate(Names[i], UriKind.RelativeOrAbsolute, out Uri Name))
857 throw new ArgumentException(
"Not a valid URI.", nameof(Names));
859 Nodes[i] =
new UriNode(Name, Names[i]);
872 int i, c = Names.Length;
875 for (i = 0; i < c; i++)
888 if (this.namedGraphs is
null)
889 this.namedGraphs =
new Dictionary<UriNode, ISemanticCube>();
891 foreach (
UriNode Name
in Names)
893 if (!this.namedGraphs.ContainsKey(Name))
894 this.namedGraphs[Name] =
null;
897 this.namedGraphNames =
new UriNode[this.namedGraphs.Count];
898 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.
Static class that dynamically manages types and interfaces available in the runtime environment.
Base class for all types of elements.
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.
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.
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.
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.