/// <summary> /// Perform a JSON-syntax query /// </summary> /// <param name="queryString">The Json string representing the query object, which contains the query path, and traverse action objects.</param> /// <param name="queryPath">When provided, overrides the query path in the query object.</param> /// <returns>A json string representing query results.</returns> /// <exception cref="FanoutSearchQueryException">Throws if the query string is invalid.</exception> /// <exception cref="FanoutSearchQueryTimeoutException">Throws if the query timed out, and the server is set to not respond with partial result.</exception>" /// <exception cref="Trinity.Network.Messaging.MessageTooLongException">Throws if the query response is too big, and the server is set to not respond with partial result.</exception> public string JsonQuery(string queryString, string queryPath = "") { FanoutSearchDescriptor fanoutSearch_desc = _JsonQuery_impl(queryString, queryPath); using (StringWriter sw = new StringWriter(new StringBuilder(128, s_max_fanoutmsg_size))) { _SerializePaths(fanoutSearch_desc, sw); return(sw.ToString()); } }
/// <summary> /// Perform a Lambda-syntax query /// </summary> /// <param name="lambda">The query string, in LIKQ syntax.</param> /// <param name="getEdgeType">Get edge types, and interleave nodes and edge type arrays in the query result.</param> /// <returns>A json string representing query results.</returns> /// <exception cref="FanoutSearchQueryException">Throws if the query string is invalid.</exception> /// <exception cref="FanoutSearchQueryTimeoutException">Throws if the query timed out, and the server is set to not respond with partial result.</exception>" /// <exception cref="Trinity.Network.Messaging.MessageTooLongException">Throws if the query response is too big, and the server is set to not respond with partial result.</exception> public string LambdaQuery(string lambda) { FanoutSearchDescriptor fanoutSearch_desc = _LambdaQuery_impl(lambda); using (StringWriter sw = new StringWriter(new StringBuilder(128, s_max_fanoutmsg_size))) { _SerializePaths(fanoutSearch_desc, sw); return(sw.ToString()); } }
private static FanoutSearchDescriptor ConstructFanoutSearchOrigin(FSDescCallchainElement origin) { /*********************************************** * Syntax: * * 1. StartFrom(long cellid, IEnumerable<string> select = null) * 2. StartFrom(IEnumerable<long> cellid, IEnumerable<string> select = null) * 3. StartFrom(string queryObject, IEnumerable<string> select = null) ***********************************************/ ThrowIf(origin.Method != s_LIKQ_StartFrom, "Expecting " + s_LIKQ_StartFrom, origin.SyntaxNode); FanoutSearchDescriptor fs_desc = new FanoutSearchDescriptor(""); fs_desc.m_origin_query = null; ThrowIf(origin.Arguments.Count < 1 || origin.Arguments.Count > 2, "Expecting 1 or 2 arguments", origin.SyntaxNode); ExpressionSyntax origin_cell_query = origin.Arguments[0].Expression; ExpressionSyntax selection = origin.Arguments.Count < 2 ? null : origin.Arguments[1].Expression; switch (origin_cell_query.Kind()) { case SyntaxKind.ObjectCreationExpression: case SyntaxKind.ImplicitArrayCreationExpression: case SyntaxKind.ArrayCreationExpression: fs_desc.m_origin = ConstructCollection <long>(origin_cell_query).ToList(); break; case SyntaxKind.NumericLiteralExpression: case SyntaxKind.UnaryMinusExpression: case SyntaxKind.UnaryPlusExpression: { long cell_id = 0; var parse_result = long.TryParse(origin_cell_query.ToString(), out cell_id); ThrowIf(!parse_result, "Expecting a cell id", origin_cell_query); fs_desc.m_origin = new List <long> { cell_id }; break; } case SyntaxKind.StringLiteralExpression: fs_desc.m_origin_query = (origin_cell_query as LiteralExpressionSyntax).Token.ValueText; break; default: throw new LambdaDSLSyntaxErrorException("Invalid starting node argument", origin_cell_query); } if (selection != null) { fs_desc.m_selectFields.Add(ConstructCollection <string>(selection).ToList()); } return(fs_desc); }
// queryResultPaths represents a serialized json array, so we just concatenate it with // a wrapper private static void _WriteResults(HttpListenerResponse response, FanoutSearchDescriptor queryResultPaths) { using (var sw = new StreamWriter(response.OutputStream)) { sw.WriteLine(@"{ ""Results"":"); _SerializePaths(queryResultPaths, sw); sw.WriteLine(@" }"); } }
private static void ProcessJsonEdgeTypeDescriptor(FanoutSearchDescriptor fs_desc, string edge_desc) { if (edge_desc == "*" || edge_desc == "") { fs_desc.m_edgeTypes.Add(new EdgeTypeDescriptor(fs_desc)); } else { fs_desc.m_edgeTypes.Add(new EdgeTypeDescriptor(fs_desc, edge_desc.Split(','))); } }
private FanoutSearchDescriptor Take_impl(int startIndex, int count) { Debug.Assert(startIndex >= 0); Debug.Assert(count >= 0); FanoutSearchDescriptor that = this.MemberwiseClone() as FanoutSearchDescriptor; that.m_takeCount = count; that.m_skipCount = startIndex; that.m_results = null; return(that); }
private static void _SerializePaths(FanoutSearchDescriptor search, TextWriter writer) { long len = 0; try { var paths = search.ToList().AsParallel().Select(p => { StringBuilder builder = new StringBuilder(); p.Serialize(builder); var newlen = Interlocked.Add(ref len, builder.Length); if (newlen > s_max_rsp_size) { throw new MessageTooLongException(); } return(builder.ToString()); }); bool first = true; writer.Write('['); foreach (var path in paths) { if (first) { first = false; } else { writer.Write(','); } writer.Write(path); } writer.Write(']'); } catch (AggregateException ex) when(ex.InnerExceptions.Any(_ => _ is MessageTooLongException || _ is OutOfMemoryException)) { throw new MessageTooLongException(); } catch (OutOfMemoryException) { throw new MessageTooLongException(); } }
internal static void ProcessJsonTraverseAction(FanoutSearchDescriptor fs_desc, JObject queryObject, int i, int len, string element_str) { List <long> cell_ids = null; bool is_cell_id = TryParseLongList(element_str, out cell_ids); bool is_origin = (i == 0); bool is_last = (i == len - 1 || i == len - 2); List <string> selectedFields = new List <string>(); if (is_cell_id) { if (is_origin) { fs_desc.m_origin = cell_ids; } else { if (is_last) /* The last node, action set to return */ { fs_desc.AddTraverseStep(ExpressionBuilder.GenerateTraverseActionFromCellIds(Action.Return, cell_ids), null); } else /* Intermediate node, action set to continue */ { fs_desc.AddTraverseStep(ExpressionBuilder.GenerateTraverseActionFromCellIds(Action.Continue, cell_ids), null); } } } else { dynamic action_object = queryObject[element_str]; ProcessJsonSelectField(selectedFields, action_object); if (is_origin) { ProcessJsonOriginNodeObject(fs_desc, action_object); } else /* not origin */ { ProcessJsonNonOriginNodeObject(fs_desc, is_last, action_object); } } fs_desc.m_selectFields.Add(selectedFields); }
private static FanoutSearchDescriptor ConstructFanoutSearchBody(FanoutSearchDescriptor current, FSDescCallchainElement visitNode, FSDescCallchainElement followEdge, Action defaultTraverseAction) { List <string> follow_edge_set = ConstructFollowEdgeSet(followEdge); EdgeTypeDescriptor ets = current.FollowEdge(follow_edge_set.ToArray()); if (visitNode == null) { return(ets.VisitNode(defaultTraverseAction)); } else if (visitNode.Arguments.Count == 1) { return(ets.VisitNode(ConstructVisitNodeAction(visitNode.Arguments[0].Expression))); } else /*if (visitNode.Arguments.Count > 1)*/ { return(ets.VisitNode( ConstructVisitNodeAction(visitNode.Arguments[0].Expression), ConstructCollection <string>(visitNode.Arguments[1].Expression) /*select*/)); } }
private string PathsToJsonArray(FanoutSearchDescriptor search, bool getEdgeType) { StringBuilder sb = new StringBuilder(); bool first = true; sb.Append('['); foreach (var path in search) { if (first) { first = false; } else { sb.Append(','); } OutputPath(path, sb, getEdgeType); } sb.Append(']'); return(sb.ToString()); }
internal static void ProcessJsonQueryObject(FanoutSearchDescriptor fs_desc, string queryPath, JObject queryObject) { string[] path_elements = queryPath.Split(s_url_path_separator, StringSplitOptions.RemoveEmptyEntries); for (int i = 0, len = path_elements.Length; i != len; ++i) { var element_str = path_elements[i]; if (0 == (i % 2)) /* Node */ { ProcessJsonTraverseAction(fs_desc, queryObject, i, len, element_str); } else /* Edge */ { ProcessJsonEdgeTypeDescriptor(fs_desc, element_str); } } if (0 == path_elements.Length % 2) /* There's no final node desc. Add a return command. */ { fs_desc.AddTraverseStep(_ => Action.Return, null); } }
private static FanoutSearchDescriptor _JsonQuery_impl(string queryString, string queryPath) { JObject queryObject = null; try { queryObject = JsonConvert.DeserializeObject <JObject>(queryString); } catch { } if (queryObject == null) { throw new FanoutSearchQueryException("The input is not a valid Json object."); } if (QueryPathInvalid(queryPath)) { JToken queryPath_token = null; if (!queryObject.TryGetValue(JsonDSL.Path, out queryPath_token)) { throw new FanoutSearchQueryException("Query path not found"); } queryPath = queryPath_token.ToString(); if (QueryPathInvalid(queryPath)) { throw new FanoutSearchQueryException("Invalid query path"); } } Log.WriteLine(LogLevel.Debug, "{0}", $"Json query: {queryString} \r\n QueryPath = {queryPath}"); try { FanoutSearchDescriptor fanoutSearch_desc = new FanoutSearchDescriptor(queryPath, queryObject); return(fanoutSearch_desc); } catch (Exception ex) { throw new FanoutSearchQueryException("Error parsing the json query object", ex); } }
internal static void ProcessJsonOriginNodeObject(FanoutSearchDescriptor fs_desc, dynamic action_object) { if (action_object == null) { throw new FanoutSearchQueryException("The starting node descriptor cannot be null"); } JArray id_array = action_object[JsonDSL.Id]; string type_str = action_object[JsonDSL.Type]; JObject match_obj = action_object[JsonDSL.Match]; if (id_array != null) { fs_desc.m_origin = id_array.Select(_ => (long)_).ToList(); } else { /* construct origin query object */ JObject query_object = new JObject(); /* if match_obj not found, use the action object itself (remove query operators). */ if (match_obj == null) { match_obj = new JObject(action_object); match_obj.Remove(JsonDSL.Id); match_obj.Remove(JsonDSL.Type); match_obj.Remove(JsonDSL.Match); if (match_obj.Properties().Count() == 0) { throw new FanoutSearchQueryException("No match conditions for starting node"); } } query_object[JsonDSL.Match] = match_obj; query_object[JsonDSL.Type] = type_str; fs_desc.m_origin_query = query_object.ToString(); } }
private static void ProcessJsonNonOriginNodeObject(FanoutSearchDescriptor fs_desc, bool is_last, dynamic action_object) { Expression <Func <ICellAccessor, Action> > traverse_action = null; Action default_action = is_last ? Action.Return : Action.Continue; traverse_action = ExpressionBuilder.GenerateTraverseActionFromQueryObject(action_object, default_action); if (traverse_action != null) { fs_desc.AddTraverseStep(traverse_action, null); } else { /* either user didn't specify node desc, or node desc doesn't imply traverse action */ if (is_last) { fs_desc.AddTraverseStep(_ => Action.Return, null); } else { fs_desc.AddTraverseStep(_ => Action.Continue, null); } } }
internal EdgeTypeDescriptor(FanoutSearchDescriptor search, params string[] edge_types) { this.edge_types = edge_types; this.fanout_search = search; }