Пример #1
0
        internal void SetMinMaxFromSql(string value)
        {
            var tokens = new SqlTokenizer(value).ToArray();

            var minText = default(SqlToken);
            var maxText = default(SqlToken);

            if (tokens.Length == 3)
            {
                if (!string.Equals(tokens[1].Text, "and", StringComparison.OrdinalIgnoreCase))
                {
                    throw new InvalidOperationException();
                }
                minText = tokens[0];
                maxText = tokens[2];
            }
            else
            {
                var andToken = tokens.Single(t => string.Equals(t.Text, "and", StringComparison.OrdinalIgnoreCase));
                minText = new SqlToken()
                {
                    Text = "'" + value.Substring(0, andToken.StartOffset).Trim().Replace("'", "''") + "'",
                    Type = SqlType.String
                };
                maxText = new SqlToken()
                {
                    Text = "'" + value.Substring(andToken.StartOffset + 3).Trim().Replace("'", "''") + "'",
                    Type = SqlType.String
                };
            }

            if (!Expressions.TryGetExpression(minText, out var min) ||
                !Expressions.TryGetExpression(maxText, out var max))
            {
                throw new InvalidOperationException();
            }

            Min = min;
            Max = max;
        }
Пример #2
0
        public static IExpression Parse(string whereClause, QueryItem table, IServerContext context = null)
        {
            context = context ?? ElementFactory.Utc.LocalizationContext;
            var tokens      = new SqlTokenizer(whereClause).Where(t => t.Type != SqlType.Comment).ToArray();
            var expressions = GetExpressions(tokens, table).ToArray();

            var output = new List <IExpression>();
            var ops    = new List <IExpression>();
            var last   = default(IExpression);

            foreach (var expression in expressions)
            {
                var expr = expression;
                if (expr is ILiteral || expr is PropertyReference)
                {
                    output.Push(expr);
                }
                else
                {
                    if (expr is NotOperator && last is IsOperator)
                    {
                        expr = new NotIsOperator();
                    }
                    else if (expr is AndOperator)
                    {
                        for (var i = ops.Count - 1; i >= 0; i--)
                        {
                            if (ops[i] is AndOperator)
                            {
                                break;
                            }
                            else if (ops[i] is BetweenOperator)
                            {
                                expr = new AndBetweenOperator();
                                break;
                            }
                        }
                    }
                    var precedence = GetPrecedence(expr);

                    if (expr is EndParen)
                    {
                        while (ops.Count > 0 && !IsOpenParen(ops.Peek()))
                        {
                            output.Push(HandleOperator(ops.Pop(), output, context));
                        }
                        var parenExpr = ops.Pop();
                        if (!IsOpenParen(last))
                        {
                            var args = new List <IExpression>();
                            FlattenArgs(args, output.Pop());
                            if (ops.Count > 0 &&
                                ops.Peek() is InOperator &&
                                parenExpr is ListExpression listExpr)
                            {
                                foreach (var arg in args.Cast <IOperand>())
                                {
                                    listExpr.Values.Add(arg);
                                }
                            }
                            else if (parenExpr is SqlFunction funcExpr)
                            {
                                foreach (var arg in args)
                                {
                                    funcExpr.Add(arg);
                                }
                                parenExpr = funcExpr.Normalize();
                            }
                            else if (args.Count == 1)
                            {
                                parenExpr = args[0];
                            }
                            else
                            {
                                throw new NotSupportedException();
                            }
                        }
                        output.Push(parenExpr);
                    }
                    else if (expr is ListExpression && last is PropertyReference prop)
                    {
                        output.Pop();
                        ops.Push(new SqlFunction(prop.Name));
                    }
                    else if (ops.Count < 1 || precedence > GetPrecedence(ops.Peek()))
                    {
                        ops.Push(expr);
                    }
                    else
                    {
                        while (ops.Count > 0 && precedence <= GetPrecedence(ops.Peek()) && !IsOpenParen(ops.Peek()))
                        {
                            output.Push(HandleOperator(ops.Pop(), output, context));
                        }
                        ops.Push(expr);
                    }
                }
                last = expr;
            }

            while (ops.Count > 0)
            {
                output.Push(HandleOperator(ops.Pop(), output, context));
            }

            if (output.Count == 1)
            {
                return(output.Pop());
            }

            throw new NotSupportedException();
        }