예제 #1
0
        public override void OnBeforeFromClauseVisited(Expression expression)
        {
            base.OnBeforeFromClauseVisited(expression);

            // TODO: Move into OnBeforeSelectClauseVisited.
            if (expression is ConstantExpression)
            {
                ConstantExpression constantExpression = expression as ConstantExpression;

                IQueryable queryable = constantExpression.Value as IQueryable;

                if (queryable != null && typeof(Resource).IsAssignableFrom(queryable.ElementType))
                {
                    SparqlVariable s = VariableGenerator.GlobalSubject;

                    SetSubjectVariable(s);

                    VariableGenerator.SetSubjectVariable(expression, s);
                }
                else
                {
                    throw new NotSupportedException(constantExpression.Value.GetType().ToString());
                }
            }
            else
            {
                // TODO: Create unit test for QuerySourceReferenceExpression, SubQueryExpression
                throw new NotImplementedException(expression.GetType().ToString());
            }
        }
예제 #2
0
        private SparqlVariable BuildMemberAccess(MemberExpression memberExpression, IGraphPatternBuilder patternBuilder)
        {
            MemberInfo member = memberExpression.Member;

            // If we do access a member of a system type, like string.Length we actually select the
            // the declaring member and invoke a SPARQL built in call to get the value.
            if (member.IsBuiltInCall())
            {
                MemberExpression parentMember = memberExpression.Expression as MemberExpression;

                return(BuildMemberAccess(parentMember, patternBuilder));
            }
            else if (memberExpression.Expression is MemberExpression)
            {
                MemberExpression parentMember = memberExpression.Expression as MemberExpression;

                // Note: When we build an optional property path, we consider the relation to the
                // parent properties of the accessed property to be non-optional.
                IGraphPatternBuilder builder = member.IsUriType() ? patternBuilder : PatternBuilder;

                // We might encounter property paths (i.e. contact.Organization.Name). Therefore,
                // implement the parent expression of the current member recursively..
                SparqlVariable po = BuildMemberAccess(parentMember, builder);

                // If we are building a node on a property path (parentExpression != null), we associate
                // the object variable with the parent expression so that it becomes the subject of the parent.
                VariableGenerator.SetSubjectVariable(memberExpression, po);
            }

            if (member.IsUriType())
            {
                // When we access the .Uri member of a resource we do not need a property mapping and return the subject as the bound variable.

                // We create a triple pattern describing the resource in the local scope just in case it has not been described yet.
                // Todo: Improve. Check if triples actually need to be asserted.
                SparqlVariable s = VariableGenerator.TryGetSubjectVariable(memberExpression) ?? SubjectVariable;
                SparqlVariable p = VariableGenerator.CreatePredicateVariable();
                SparqlVariable o = VariableGenerator.CreateObjectVariable(memberExpression);

                patternBuilder.Where(t => t.Subject(s).Predicate(p).Object(o));

                VariableGenerator.SetSubjectVariable(memberExpression, s);

                return(s);
            }
            else if (memberExpression.Expression is QuerySourceReferenceExpression)
            {
                QuerySourceReferenceExpression querySource = memberExpression.Expression as QuerySourceReferenceExpression;

                if (VariableGenerator.TryGetSubjectVariable(memberExpression) == VariableGenerator.GlobalSubject)
                {
                    // In case the accessed member is the global query subject (i.e. from x select x.Y)..
                    SparqlVariable s = VariableGenerator.TryGetSubjectVariable(querySource);
                    SparqlVariable o = VariableGenerator.GlobalSubject;

                    if (s == null)
                    {
                        s = VariableGenerator.CreateSubjectVariable(querySource);

                        BuildMemberAccess(memberExpression, patternBuilder, member, s, o);
                    }

                    return(o);
                }
                else
                {
                    // Otherwise we are accessing a member of the globale query subject (i.e. from x where x.Y select x)
                    SparqlVariable s = VariableGenerator.TryGetSubjectVariable(querySource) ?? VariableGenerator.GlobalSubject;
                    SparqlVariable o = VariableGenerator.TryGetObjectVariable(memberExpression) ?? VariableGenerator.CreateObjectVariable(memberExpression);

                    BuildMemberAccess(memberExpression, patternBuilder, member, s, o);

                    return(o);
                }
            }
            else
            {
                SparqlVariable s = VariableGenerator.TryGetSubjectVariable(memberExpression) ?? VariableGenerator.CreateSubjectVariable(memberExpression);
                SparqlVariable o = VariableGenerator.TryGetObjectVariable(memberExpression) ?? VariableGenerator.CreateObjectVariable(memberExpression);

                BuildMemberAccess(memberExpression, patternBuilder, member, s, o);

                return(o);
            }
        }
예제 #3
0
        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);
            }
        }