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; } }
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); })); }
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); } }