Пример #1
0
        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);
        }
Пример #2
0
        private static TreeIteratorContext GetTreeIteratorContext(ParsedRequest parsedRequest, DataContainerDescriptor containerDescriptor)
        {
            var result = new TreeIteratorContext();

            result.ContainerDescriptor = containerDescriptor;
            result.ParsedRequest       = parsedRequest;
            return(result);
        }
Пример #3
0
        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);
        }
Пример #4
0
        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);
            }
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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);
        }
Пример #7
0
        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);
                }
            }
        }
Пример #8
0
        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);
        }
Пример #9
0
        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);
            }
        }
Пример #10
0
        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;
        }
Пример #11
0
        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);
            }
        }
Пример #12
0
 private static TreeIteratorContext GetTreeIteratorContext(ParsedRequest parsedRequest, DataContainerDescriptor containerDescriptor)
 {
     var result = new TreeIteratorContext();
     result.ContainerDescriptor = containerDescriptor;
     result.ParsedRequest = parsedRequest;
     return result;
 }
Пример #13
0
        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;
        }
Пример #14
0
        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);
                }
            }
        }