Exemple #1
0
        protected AnnotatedQuery(ICypherFluentQuery query, AnnotatedQuery previous) : base(query)
        {
            if (VbCompareReplacerType == null)
            {
                var neo4jClientAssembly = typeof(ICypherFluentQuery).GetTypeInfo().Assembly;
                VbCompareReplacerType = neo4jClientAssembly.GetType("Neo4jClient.Cypher.VbCompareReplacer");
            }

            if (previous == null)
            {
                QueryContext = CypherUtilities.GetQueryContext(query);

                CamelCaseProperties = (bool)query.GetType().GetField("CamelCaseProperties",
                                                                     BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public).GetValue(query);
                FunctionVisitor = new FunctionExpressionVisitor(QueryContext);
            }
            else
            {
                QueryContext = previous.QueryContext;
                QueryContext.CurrentQueryWriter   = QueryWriterGetter(query);
                QueryContext.CurrentBuildStrategy = QueryContext.BuildStrategyGetter(query);

                CamelCaseProperties = previous.CamelCaseProperties;
                var funcsVisitor = previous.FunctionVisitor;
                funcsVisitor.QueryContext = QueryContext;
                FunctionVisitor           = funcsVisitor;
            }

            var context = QueryContext?.AnnotationsContext ?? previous?.AnnotationsContext;

            if (context != null)
            {
                AnnotationsContext = context;
            }
        }
Exemple #2
0
        internal static ICypherFluentQuery <TResult> SharedProjectionQuery <TResult>
            (this ICypherFluentQuery query, LambdaExpression expression, string clause,
            bool isOutputQuery,
            bool applyResultMode = true, bool applyResultFormat = true)
        {
            var queryContext = CypherUtilities.GetQueryContext(query);

            queryContext.CurrentBuildStrategy = queryContext.CurrentBuildStrategy ?? PropertiesBuildStrategy.WithParams;
            var funcVisitor = new FunctionExpressionVisitor(queryContext);
            var result      = ExpressionUtilities.BuildProjectionQueryExpression
                                  (expression, queryContext, funcVisitor, isOutputQuery, out var mode, out var format);

            return(Mutate <TResult>(query, w =>
            {
                if (applyResultMode)
                {
                    w.ResultMode = mode;
                }

                if (applyResultFormat)
                {
                    w.ResultFormat = format;
                }

                w.AppendClause(clause + " " + result);
            }));
        }
Exemple #3
0
        public void FinalPropertiesResolution(Dictionary <string, dynamic> expected, LambdaExpression expression,
                                              Type expectedExceptionType, string expectedExceptionMessage,
                                              string testContextName, TestContext testContext)
        {
            Func <JObject> action = () => CypherUtilities.GetFinalProperties
                                        (expression, testContext.QueryContext, out var hasFuncs);

            if (expectedExceptionType != null)
            {
                var exception = Assert.Throws(expectedExceptionType, () => action.Invoke());

                if (expectedExceptionMessage != null)
                {
                    Assert.Equal(expectedExceptionMessage, exception.Message);
                }
            }
            else
            {
                var finalPropsObj = action.Invoke();
                TestUtilities.TestFinalPropertiesForEquality(testContext.Serializer, expected, finalPropsObj);
            }
        }
        /// <summary>
        ///     Don't call this method directly unless you wan't to force this process
        /// </summary>
        public virtual void ProcessUnhandledSimpleVars(Expression currentNode, bool considerInits = false)
        {
            if (UnhandledNodes.Count == 0)
            {
                return;
            }

            Expression initExpression = null;

            //filter the nodes for only the onces of interest to us
            Func <Expression, bool> filter = n =>
            {
                switch (n.NodeType)
                {
                case ExpressionType.MemberAccess:
                case ExpressionType.TypeAs:
                case ExpressionType.Convert:
                case ExpressionType.ConvertChecked:
                case ExpressionType.Unbox:
                case ExpressionType.Call when n is MethodCallExpression callExpr &&
                    (
                        callExpr.Method.Name.StartsWith("_As") &&
                        (callExpr.Method.DeclaringType == Defaults.CypherFuncsType ||
                         callExpr.Method.DeclaringType ==
                         Defaults.CypherExtensionFuncsType) ||                            //._As and ._AsList()
                        callExpr.Method.Name == "Get" &&
                        callExpr.Method.DeclaringType ==
                        Defaults.VarsType ||                            //CypherVariables.Get()
                        callExpr.Method.IsEquivalentTo(
                            Defaults
                            .CypherObjectIndexerInfo)                                   //CypherVariables.Get("")[""]
                                                                                        //|| (callExpr.Method.Name == "_" && callExpr.Method.DeclaringType == Defaults.ObjectExtensionsType) //._()
                    ):
                {
                    return(true);
                }

                case ExpressionType.MemberInit:
                case ExpressionType.New:
                case ExpressionType.ListInit when n.Type.IsDictionaryType():
                {
                    if (considerInits && initExpression == null)
                    {
                        //we only need one type init
                        initExpression = n;
                        return(true);
                    }

                    return(false);
                }
                }

                return(false);
            };

            //repeatFilter:

            var _unhandledNodes = UnhandledNodes
                                  .AsEnumerable()
                                  .Reverse()
                                  .TakeWhile(filter)
                                  .ToList();

            if (_unhandledNodes.Count == 0)
            {
                return;
            }

            var hasMemberAccess = _unhandledNodes.Any(n => n.NodeType == ExpressionType.MemberAccess);

            JObject initJObject = null;
            JToken  initJValue  = null;

            var initExprIdx = -1;

            string builtValue = null;

            if (considerInits && initExpression != null)
            {
                //remove it from the list
                initExprIdx = _unhandledNodes.IndexOf(initExpression);
                if (initExprIdx >= 0)
                {
                    _unhandledNodes.Remove(initExpression);
                }

                if (!hasMemberAccess)
                {
                    try
                    {
                        var executedValue = initExpression.ExecuteExpression <object>();
                        if (executedValue is JToken token)
                        {
                            initJValue = token;
                        }
                    }
                    catch
                    {
                    }
                }
            }

            if (initJValue == null)
            {
                var removeVariable = false;

                if (!Utils.Utilities.HasVars(_unhandledNodes))
                {
                    if (!hasMemberAccess) //!_unhandledNodes.Any(n => n.NodeType == ExpressionType.MemberAccess))
                    {
                        return;           //we need at least one memberaccess for this to work
                    }
                    //it doesn't have a vars get call, so add one
                    var randomVar = "_fev_" + Utils.Utilities.GetRandomVariableFor("fevr");

                    //create a CypherVariables.Get call for this variable
                    var varsGetCallExpr = ExpressionUtilities.GetVarsGetExpressionFor(randomVar, currentNode.Type);

                    _unhandledNodes.Insert(0, varsGetCallExpr); //this is just going to be the header

                    removeVariable = true;
                }

                builtValue =
                    ExpressionUtilities.BuildSimpleVarsCall(_unhandledNodes, QueryContext, Context.UseResolvedJsonName);

                if (string.IsNullOrWhiteSpace(builtValue))
                {
                    //error
                    throw new InvalidOperationException(
                              string.Format(Messages.InvalidVariableExpressionError,
                                            _unhandledNodes.Last(), builtValue ?? ""));
                }

                if (removeVariable)
                {
                    var dotIdx = builtValue.IndexOf(".");
                    dotIdx = dotIdx > 0 ? dotIdx : builtValue.Length;
                    if (dotIdx > 0)
                    {
                        builtValue = builtValue.Remove(0, dotIdx);
                    }

                    //remove the dummy vars get node added earlier
                    _unhandledNodes.RemoveAt(0);
                }

                if (considerInits && initExpression != null && initJObject == null && initJValue == null)
                {
                    //build the init independently
                    //but first check if we have a cached value already
                    if (!QueryContext.FuncsCachedJTokens.TryGetValue(initExpression, out var existingJToken) ||
                        !(existingJToken is JObject existingJObject))
                    {
                        initJObject = CypherUtilities.GetFinalProperties
                                          (Expression.Lambda(initExpression), QueryContext, out var hasFuncsInProps);

                        if (existingJToken == null)
                        {
                            //cache this for later use in same query
                            QueryContext.FuncsCachedJTokens[initExpression] = initJObject;
                        }
                    }
                    else
                    {
                        initJObject = existingJObject;
                    }
                }

                if (initJObject != null && initJObject.Count > 0)
                {
                    try
                    {
                        initJValue = initJObject.SelectToken($"$.{builtValue.Trim().TrimStart('.')}");
                    }
                    catch (Exception e)
                    {
                    }
                }
            }

            if (considerInits && initJValue == null)
            {
                //we didn't get what we came here for
                return;
            }

            if (considerInits && initExprIdx >= 0)
            {
                //replace it
                _unhandledNodes.Insert(initExprIdx, initExpression);
            }

            if (initJValue != null)
            {
                WriteArgument(Expression.Constant(initJValue, initJValue.GetType()), _unhandledNodes.LastOrDefault());
            }
            else
            {
                Builder.Append(builtValue, _unhandledNodes.LastOrDefault());
            }

            foreach (var node in _unhandledNodes)
            {
                Handled(node);
            }
        }