private static bool ProcessIdentifierAliasesFunctor(TreeIteratorContext ctx, ParseTreeNode node) { if (0 != StringComparer.Ordinal.Compare(node.Term.Name, "Id")) { return(true); } ctx.Buffer.Clear(); foreach (var part in node.ChildNodes) { ctx.Buffer.Add(part.Token.ValueString); } // first, try to find the alias of maximum length, // then keep trimming tail until buffer is empty or we find some alias while (ctx.Buffer.Count > 0) { string[] mapped; if (ctx.TargetEntity.TryGetIdentifierAlias(ctx.Buffer, out mapped)) { // replace content of this identifier with pre-cached parts node.ChildNodes.Clear(); foreach (var part in mapped) { node.ChildNodes.Add(GetCachedIdentifierAliasPart(part, ctx.CachedParts)); } break; } ctx.Buffer.RemoveAt(ctx.Buffer.Count - 1); } return(false); }
private static TreeIteratorContext GetTreeIteratorContext(ParsedRequest parsedRequest, DataContainerDescriptor containerDescriptor) { var result = new TreeIteratorContext(); result.ContainerDescriptor = containerDescriptor; result.ParsedRequest = parsedRequest; return(result); }
public void ProcessIdentifierAliases(ParseTreeNode root, DocumentTypeDescriptor targetEntity) { var ctx = new TreeIteratorContext { Buffer = new List <string>(5), TargetEntity = targetEntity, CachedParts = m_identifierAliasParts }; IterateTree(root, 0, ctx); }
private static void IterateTree(ParseTreeNode root, int level, TreeIteratorContext ctx) { if (!ctx.Functor(ctx, root)) { // no need to go deeper into the tree return; } foreach (var child in root.ChildNodes) { IterateTree(child, level + 1, ctx); } }
private void ParseOrderClause(TreeIteratorContext ctx) { if (ctx.ParsedRequest.BaseDataset.OrderClause != null) { // preprocess identifiers m_preprocessor.ProcessIdentifierAliases(ctx.ParsedRequest.BaseDataset.OrderClause, ctx.ParsedRequest.TargetEntity); // iterator callback will place column IDs and ASC/DESC flag into "order" list ctx.Functor = OrderFieldExtractor; // extract all field names IterateTree(ctx.ParsedRequest.BaseDataset.OrderClause, 0, ctx); } }
private static bool OrderFieldExtractor(TreeIteratorContext ctx, ParseTreeNode node) { if (0 == StringComparer.Ordinal.Compare(node.Term.Name, "orderMember")) { var idsimple = node.RequireChild("Id", 0).RequireChild("id_simple", 0); var fieldName = idsimple.Token.ValueString; var field = ctx.ContainerDescriptor.TryGetField(ctx.ParsedRequest.TargetEntity.DocumentType, fieldName); if (field == null) { throw new CompilationException("Unknown field: " + fieldName, node); } var descOpt = node.TryGetChild(null, 1, 0); var descending = descOpt != null; if (descending) { if (0 == StringComparer.Ordinal.Compare(descOpt.Term.Name, "ASC")) { descending = false; } else if (0 != StringComparer.Ordinal.Compare(descOpt.Term.Name, "DESC")) { throw new CompilationException("Invalid sort order option: " + descOpt.Token.Text, descOpt); } } if (ctx.ParsedRequest.BaseDataset.OrderClauseFields.Count > 0) { throw new CompilationException("Cannot sort by more than one field at this time", node); } if (0 <= ctx.ParsedRequest.BaseDataset.OrderClauseFields.FindIndex(x => x.Item1 == field.FieldId)) { throw new CompilationException("Duplicate order field: " + field.Name, node); } ctx.ParsedRequest.BaseDataset.OrderClauseFields.Add(new Tuple <int, bool>(field.FieldId, descending)); // no need to traverse deeper into the Id non-terminal return(false); } return(true); }
private void ParseWhereClause(ParseTreeNode whereClause, TreeIteratorContext ctx) { if (whereClause != null) { ctx.ParsedRequest.BaseDataset.WhereClauseRoot = whereClause.ChildNodes.Count == 0 ? null : whereClause.RequireChild(null, 1); if (ctx.ParsedRequest.BaseDataset.WhereClauseRoot != null) { // preprocess identifiers m_preprocessor.ProcessIdentifierAliases(whereClause, ctx.ParsedRequest.TargetEntity); // iterator callback will place column IDs into "where" list ctx.Argument = 2; // extract all field names IterateTree(ctx.ParsedRequest.BaseDataset.WhereClauseRoot, 0, ctx); } } }
private static bool FieldExtractor(TreeIteratorContext ctx, ParseTreeNode node) { if (0 != StringComparer.Ordinal.Compare(node.Term.Name, "Id")) { // keep going deeper return(true); } var field = TryGetFieldByIdentifierNode(node, ctx.ContainerDescriptor, ctx.ParsedRequest.TargetEntity.DocumentType); if (field != null) { switch (ctx.Argument) { case 1: if (!ctx.ParsedRequest.Select.SelectFields.Contains(field)) { ctx.ParsedRequest.Select.SelectFields.Add(field); } break; case 2: if (!ctx.ParsedRequest.BaseDataset.WhereClauseFields.Contains(field)) { ctx.ParsedRequest.BaseDataset.WhereClauseFields.Add(field); } break; default: throw new Exception("Internal error, invalid argument for iterator: " + ctx.Argument); } } // no need to traverse deeper into the Id non-terminal return(false); }
private static bool OrderFieldExtractor(TreeIteratorContext ctx, ParseTreeNode node) { if (0 == StringComparer.Ordinal.Compare(node.Term.Name, "orderMember")) { var idsimple = node.RequireChild("Id", 0).RequireChild("id_simple", 0); var fieldName = idsimple.Token.ValueString; var field = ctx.ContainerDescriptor.TryGetField(ctx.ParsedRequest.TargetEntity.DocumentType, fieldName); if (field == null) { throw new CompilationException("Unknown field: " + fieldName, node); } var descOpt = node.TryGetChild(null, 1, 0); var descending = descOpt != null; if (descending) { if (0 == StringComparer.Ordinal.Compare(descOpt.Term.Name, "ASC")) { descending = false; } else if (0 != StringComparer.Ordinal.Compare(descOpt.Term.Name, "DESC")) { throw new CompilationException("Invalid sort order option: " + descOpt.Token.Text, descOpt); } } if (ctx.ParsedRequest.BaseDataset.OrderClauseFields.Count > 0) { throw new CompilationException("Cannot sort by more than one field at this time", node); } if (0 <= ctx.ParsedRequest.BaseDataset.OrderClauseFields.FindIndex(x => x.Item1 == field.FieldId)) { throw new CompilationException("Duplicate order field: " + field.Name, node); } ctx.ParsedRequest.BaseDataset.OrderClauseFields.Add(new Tuple<int, bool>(field.FieldId, descending)); // no need to traverse deeper into the Id non-terminal return false; } return true; }
private static TreeIteratorContext GetTreeIteratorContext(ParsedRequest parsedRequest, DataContainerDescriptor containerDescriptor) { var result = new TreeIteratorContext(); result.ContainerDescriptor = containerDescriptor; result.ParsedRequest = parsedRequest; return result; }
private static bool FieldExtractor(TreeIteratorContext ctx, ParseTreeNode node) { if (0 != StringComparer.Ordinal.Compare(node.Term.Name, "Id")) { // keep going deeper return true; } var field = TryGetFieldByIdentifierNode(node, ctx.ContainerDescriptor, ctx.ParsedRequest.TargetEntity.DocumentType); if (field != null) { switch (ctx.Argument) { case 1: if (!ctx.ParsedRequest.Select.SelectFields.Contains(field)) { ctx.ParsedRequest.Select.SelectFields.Add(field); } break; case 2: if (!ctx.ParsedRequest.BaseDataset.WhereClauseFields.Contains(field)) { ctx.ParsedRequest.BaseDataset.WhereClauseFields.Add(field); } break; default: throw new Exception("Internal error, invalid argument for iterator: " + ctx.Argument); } } // no need to traverse deeper into the Id non-terminal return false; }