public void PipeVariableRewriter_test() { string query = "match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + "WITH * WITH *, p WITH p, collect(r) WITH *, collect(r)"; PipeVariableRewriter obj = new PipeVariableRewriter(); string res = obj.Tokenize(query).Rebuild(); List <Match> m = Regex.Matches(res, "_[a-fA-F0-9]{32}").ToList(); Assert.Equal("match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + $"WITH p,r WITH p,r,p WITH p,collect(r) AS {m[0]} WITH p,{m[0]},collect(r) AS {m[2]}", res); res = obj.Tokenize(res).Rebuild(); List <Match> m1 = Regex.Matches(res, "_[a-fA-F0-9]{32}").ToList(); Assert.Equal("match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + $"WITH p,r WITH p,r,p WITH p,collect(r) AS {m[0]} WITH p,{m[0]},collect(r) AS {m1[2]}", res); query = "match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + "WITH p, collect(r) AS q WITH *"; res = obj.Tokenize(query).Rebuild(); Assert.Equal("match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + $"WITH p,collect(r) AS q WITH p,q", res); query = "MATCH (_8f4a36df17da497d93d2ffde4677e0d4:`N4pper.Ogm.Entities.IOgmEntity`{Name:'a083e3e08ca5407eab11687974520036'}) " + "WITH _8f4a36df17da497d93d2ffde4677e0d4 WITH * WITH count(*)"; res = obj.Tokenize(query).Rebuild(); Assert.StartsWith("MATCH (_8f4a36df17da497d93d2ffde4677e0d4:`N4pper.Ogm.Entities.IOgmEntity`{Name:'a083e3e08ca5407eab11687974520036'}) " + "WITH _8f4a36df17da497d93d2ffde4677e0d4 WITH _8f4a36df17da497d93d2ffde4677e0d4 WITH count(*) AS _", res); }
public void PipeVariableRewriter_test2() { string query = "with val as d match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + "WITH * WITH *, p WITH p, collect(r) WITH *, collect(r)"; PipeVariableRewriter obj = new PipeVariableRewriter(); string res = obj.Tokenize(query).Rebuild(); List <Match> m = Regex.Matches(res, "_[a-fA-F0-9]{32}").ToList(); Assert.Equal("WITH val as d match (p:Parent {Name:\"Luca\", Age:2}-[r:Of {Id:1}]->(:Son {Name:\"Carlo\"}) " + $"WITH d,p,r WITH d,p,r,p WITH p,collect(r) AS {m[0]} WITH p,{m[0]},collect(r) AS {m[2]}", res); }
internal static object Execute <TResult>(IStatementRunner runner, Statement statement, Func <IRecord, Type, object> mapper, Expression expression) { bool IsEnumerable = typeof(TResult).IsEnumerable(); Type typeResult; QueryTranslator tranaslator = new QueryTranslator(); expression = Evaluator.PartialEval(expression); string statementText = Regex.Replace(statement.Text, "RETURN", "WITH", RegexOptions.IgnoreCase); PipeVariableRewriter rewriter = new PipeVariableRewriter(); statementText = rewriter.Tokenize(statementText).Rebuild(); (string firstVar, IEnumerable <string> otherVars) = GetFirstCypherVariableName(statementText); string queryText = tranaslator.Translate(expression, out MethodCallExpression terminal, out int?countFromBegin, out typeResult, firstVar, otherVars); queryText = Regex.Replace($"{statementText} {queryText}", "RETURN", "WITH", RegexOptions.IgnoreCase); queryText = rewriter.Tokenize(queryText).Rebuild(); queryText = Regex.Replace(queryText, "WITH(.+?)$", "RETURN$1", RegexOptions.IgnoreCase | RegexOptions.RightToLeft); IStatementResult result = runner.Run(queryText, statement.Parameters); IQueryable <IRecord> records = result.ToList().AsQueryable(); if (terminal != null) { IRecord r = records.FirstOrDefault(); if (terminal.Method.Name.StartsWith("First")) { if (r == null) { if (terminal.Method.Name.EndsWith("Default")) { return(typeResult.GetDefault()); } else { throw new ArgumentOutOfRangeException(nameof(records), "The collection is empty"); } } return(mapper(r, typeResult)); } else { return(Convert.ChangeType(r.Values[r.Keys[0]], terminal.Type));//can only be an aggregate numeric value } } else { System.Collections.IList lst = (System.Collections.IList) typeof(List <>).MakeGenericType(typeResult).GetInstanceOf(null); foreach (object item in records.Select(p => mapper(p, typeResult))) { lst.Add(item); } IQueryable lstQ = lst.AsQueryable(); if (countFromBegin == null) { return(lstQ); } else { ExpressionInitialModifier treeCopier = new ExpressionInitialModifier(lstQ, countFromBegin.Value); Expression newExpressionTree = treeCopier.Visit(expression); // This step creates an IQueryable that executes by replacing Queryable methods with Enumerable methods. if (IsEnumerable) { return(lstQ.Provider.CreateQuery(newExpressionTree)); } else { return(lstQ.Provider.Execute(newExpressionTree)); } } } }