public override void OnSelectClauseVisited(Expression selector) { if (QueryModel.HasResultOperator <SkipResultOperator>() || QueryModel.HasResultOperator <TakeResultOperator>() || QueryModel.HasResultOperator <FirstResultOperator>() || QueryModel.HasResultOperator <LastResultOperator>()) { // Finally, if we have a SKIP or TAKE operator on the root query, set the current // query generator as a child. ISparqlQueryGenerator subGenerator = QueryGeneratorTree.GetQueryGenerator(selector); Child(subGenerator); } }
public override void OnBeforeSelectClauseVisited(Expression selector) { base.OnBeforeSelectClauseVisited(selector); Type selectedType = TryGetSelectedType(selector); if (selectedType == null || !typeof(Resource).IsAssignableFrom(selectedType)) { throw new NotSupportedException(selectedType.ToString()); } // 1. We always create an outer query which selects all triples that describe our resources. SparqlVariable s_ = VariableGenerator.GlobalSubject; SparqlVariable p_ = VariableGenerator.GlobalPredicate; SparqlVariable o_ = VariableGenerator.GlobalObject; VariableGenerator.SetSubjectVariable(selector, s_); VariableGenerator.SetPredicateVariable(selector, p_); VariableGenerator.SetObjectVariable(selector, o_); SetSubjectVariable(s_); SetObjectVariable(o_); SelectVariable(s_); SelectVariable(p_); SelectVariable(o_); WhereResource(s_, p_, o_); // If we are describing resources using a SKIP or TAKE operator, we need to make sure that // these operations are on a per-resource basis and all triples for the described resources // are contained in the result. if (QueryModel.HasResultOperator <SkipResultOperator>() || QueryModel.HasResultOperator <TakeResultOperator>() || QueryModel.HasResultOperator <FirstResultOperator>() || QueryModel.HasResultOperator <LastResultOperator>()) { // ..which are described in an inner query on which the LIMIT and OFFSET operators are set. // This results in a SELECT query that acts like a DESCRIBE but ist faster on most triple // stores as the triples can be returend via bindings and must not be parsed. ISparqlQueryGenerator subGenerator = QueryGeneratorTree.CreateSubQueryGenerator(this, selector); subGenerator.SetSubjectVariable(s_, true); subGenerator.SetObjectVariable(o_); GenerateTypeConstraintOnSubject(subGenerator, selector); QueryGeneratorTree.CurrentGenerator = subGenerator; // NOTE: We set the subGenerator as a child *AFTER* the select clause and body clauses // have been processed (see <c>OnSelectClauseVisited</c>). This is because the dotNetRDF // query generator does not correctly handle result operators when it is already set as a child. } else if (!QueryModel.HasTypeConstraintOnExpression(selector)) { // NOTE: This should not be done here. Simply because the HasTypeConstraintOnExpression // requires us to look ahead at the body clauses which is already done in more detail // by the expression visitor. We need a way to generate the type constraint after the query // has been visited and no type constraint was generated. GenerateTypeConstraintOnSubject(this, selector); } if (selector is MemberExpression) { MemberExpression memberExpression = selector as MemberExpression; BuildMemberAccess(memberExpression); } }