예제 #1
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();
        }
예제 #2
0
 protected virtual void WriteTableName(QueryItem item)
 {
     TryFillName(item);
     WriteIdentifier(item.Type);
 }
예제 #3
0
 protected virtual IExpression GetWhereClause(QueryItem query, bool skipIdWhereClause = false)
 {
     return(query.Where);
 }
예제 #4
0
 public PropertyReference(string name, QueryItem table)
 {
     Name  = name;
     Table = table;
 }
        public void Visit(QueryItem query)
        {
            var refId = Guid.NewGuid().ToArasId();

            _writer.WriteStartElement("Item");
            _writer.WriteAttributeString("type", "qry_QueryDefinition");
            _writer.WriteAttributeString("action", "qry_ExecuteQueryDefinition");

            _writer.WriteStartElement("Relationships");

            _writer.WriteStartElement("Item");
            _writer.WriteAttributeString("type", "qry_QueryItem");
            _writer.WriteElementString("alias", query.Alias);
            _writer.WriteStartElement("item_type");
            _writer.WriteAttributeString("keyed_name", query.Type);
            _writer.WriteEndElement();
            _writer.WriteElementString("ref_id", refId);

            if (!query.Select.All(s => s.Expression is PropertyReference))
            {
                throw new NotSupportedException();
            }

            if (!query.OrderBy.All(s => s.Expression is PropertyReference))
            {
                throw new NotSupportedException();
            }

            _writer.WriteStartElement("Relationships");

            foreach (var select in query.Select)
            {
                _writer.WriteStartElement("Item");
                _writer.WriteAttributeString("type", "qry_QueryItemSelectProperty");
                _writer.WriteElementString("property_name", ((PropertyReference)select.Expression).Name);
                _writer.WriteEndElement(); // Item
            }

            var idx = 10;

            foreach (var orderBy in query.OrderBy)
            {
                _writer.WriteStartElement("Item");
                _writer.WriteAttributeString("type", "qry_QueryItemSortProperty");
                _writer.WriteElementString("property_name", ((PropertyReference)orderBy.Expression).Name);
                _writer.WriteElementString("sort_order_direction", orderBy.Ascending ? "asc" : "desc");
                _writer.WriteElementString("sort_order", _context.Format(idx));
                _writer.WriteEndElement(); // Item
                idx += 10;
            }

            _writer.WriteEndElement(); // Relationships

            var where = query.Where;
            if (query.Version is CurrentVersion)
            {
                where = new AndOperator()
                {
                    Left  = where,
                    Right = new EqualsOperator()
                    {
                        Left  = new PropertyReference("is_current", query),
                        Right = new BooleanLiteral(true)
                    }.Normalize()
                }.Normalize();
            }

            if (where != null)
            {
                using (var strWriter = new StringWriter())
                    using (_conditionWriter = XmlWriter.Create(strWriter, new XmlWriterSettings()
                    {
                        OmitXmlDeclaration = true
                    }))
                    {
                        _conditionWriter.WriteStartElement("condition");
                        query.Where.Visit(this);
                        _conditionWriter.WriteEndElement();

                        _conditionWriter.Flush();
                        strWriter.Flush();

                        _writer.WriteStartElement("filter_xml");
                        _writer.WriteCData(strWriter.ToString());
                        _writer.WriteEndElement();
                    }
                _conditionWriter = null;
            }

            if (query.Offset.HasValue || query.Fetch.HasValue)
            {
                using (var strWriter = new StringWriter())
                    using (_conditionWriter = XmlWriter.Create(strWriter, new XmlWriterSettings()
                    {
                        OmitXmlDeclaration = true
                    }))
                    {
                        _conditionWriter.WriteStartElement("configuration");
                        _conditionWriter.WriteStartElement("option");
                        if (query.Offset.HasValue)
                        {
                            _conditionWriter.WriteElementString("offset", _context.Format(query.Offset));
                        }
                        if (query.Fetch.HasValue)
                        {
                            _conditionWriter.WriteElementString("fetch", _context.Format(query.Fetch));
                        }
                        _conditionWriter.WriteEndElement();
                        _conditionWriter.WriteEndElement();

                        _conditionWriter.Flush();
                        strWriter.Flush();

                        _writer.WriteStartElement("offset_fetch_xml");
                        _writer.WriteCData(strWriter.ToString());
                        _writer.WriteEndElement();
                    }
                _conditionWriter = null;
            }

            _writer.WriteEndElement(); // Item

            foreach (var param in _parameters)
            {
                _writer.WriteStartElement("Item");
                _writer.WriteAttributeString("type", "qry_QueryParameter");
                _writer.WriteElementString("name", param.Name);
                _writer.WriteEndElement(); // Item
            }

            _writer.WriteStartElement("Item");
            _writer.WriteAttributeString("type", "qry_QueryReference");
            _writer.WriteElementString("child_ref_id", refId);
            _writer.WriteEndElement(); // Item

            _writer.WriteEndElement(); // Relationships
            _writer.WriteEndElement(); // Item
        }
예제 #6
0
        public void Visit(QueryItem query)
        {
            var newQuery = new QueryItem(query.Context)
            {
                Alias  = query.Alias,
                Fetch  = query.Fetch,
                Offset = query.Offset,
                Type   = query.Type,
            };

            _clones[query] = newQuery;

            if (query.Version is CurrentVersion)
            {
                newQuery.Version = new CurrentVersion();
            }
            else if (query.Version is LatestMatch latest)
            {
                newQuery.Version = new LatestMatch()
                {
                    AsOf = latest.AsOf
                }
            }
            ;
            else if (query.Version is VersionCriteria crit)
            {
                newQuery.Version = new VersionCriteria()
                {
                    Condition = CloneAndReturn(crit.Condition)
                }
            }
            ;
            else if (query.Version is LastVersionOfId last)
            {
                newQuery.Version = new LastVersionOfId()
                {
                    Id = last.Id
                }
            }
            ;

            foreach (var attr in query.Attributes)
            {
                newQuery.Attributes.Add(attr);
            }

            if (query.TypeProvider != null)
            {
                newQuery.TypeProvider = Clone(query.TypeProvider) as PropertyReference;
            }

            foreach (var join in query.Joins
                     .Select(Clone)
                     .Where(j => j != null && !(j.Condition is IgnoreNode)))
            {
                newQuery.Joins.Add(join);
            }

            foreach (var orderBy in query.OrderBy
                     .Select(Clone)
                     .Where(o => o != null && !(o.Expression is IgnoreNode)))
            {
                newQuery.OrderBy.Add(orderBy);
            }

            foreach (var select in query.Select
                     .Select(Clone)
                     .Where(s => s != null && !(s.Expression is IgnoreNode)))
            {
                newQuery.Select.Add(select);
            }

            if (query.Where != null)
            {
                newQuery.Where = CloneAndReturn(query.Where);
            }
            _query = newQuery;
        }
예제 #7
0
        internal IExpression Parse(QueryItem table, IPropertyDefinition prop, string value, Condition condition = Condition.Undefined)
        {
            var propRef = new PropertyReference(prop.NameProp().Value
                                                ?? prop.KeyedName().Value
                                                ?? prop.IdProp().KeyedName().Value, table);
            var meta = prop.Metadata();

            if (meta.DataType().Value == "item")
            {
                propRef = new PropertyReference("keyed_name", propRef.GetOrAddTable(table.Context));
            }

            var expressions = new List <IExpression>();
            var values      = default(IEnumerable <string>);

            switch (condition)
            {
            case Condition.Undefined:
            case Condition.Equal:
            case Condition.NotEqual:
            case Condition.Like:
            case Condition.NotLike:
                values = SplitOr(value);
                break;

            default:
                values = new[] { value };
                break;
            }

            foreach (var val in values)
            {
                if ((val == "*" || (val == "%" && String.IsPercentWildcard)) && condition == Condition.Undefined)
                {
                    expressions.Add(new LikeOperator()
                    {
                        Left  = propRef,
                        Right = AmlLikeParser.Instance.Parse("%")
                    }.Normalize());
                }
                else if (condition == Condition.IsNotNull)
                {
                    return(new IsOperator()
                    {
                        Left = propRef,
                        Right = IsOperand.NotNull
                    }.Normalize());
                }
                else if (condition == Condition.IsNull)
                {
                    return(new IsOperator()
                    {
                        Left = propRef,
                        Right = IsOperand.Null
                    }.Normalize());
                }
                else
                {
                    switch (meta.DataType().AsString("").ToLowerInvariant())
                    {
                    case "boolean":
                        expressions.Add(Boolean.Parse(propRef, val, condition));
                        break;

                    case "date":
                        expressions.Add(Date.Parse(propRef, val, condition));
                        break;

                    case "decimal":
                    case "float":
                    case "integer":
                        expressions.Add(Number.Parse(propRef, val, condition));
                        break;

                    default:
                        expressions.Add(String.Parse(propRef, val, condition));
                        break;
                    }
                }
            }

            var addNotOperator = expressions.Count > 0 && expressions.All(e => e is NotOperator);

            if (addNotOperator)
            {
                expressions = expressions.Cast <NotOperator>().Select(n => n.Arg).ToList();
            }

            var result = default(IExpression);

            if (expressions.Count > 0 && expressions.All(e => e is EqualsOperator eq && eq.Right is IOperand))
            {
                var list = new ListExpression();
                foreach (var op in expressions.Cast <EqualsOperator>().Select(e => (IOperand)e.Right))
                {
                    list.Values.Add(op);
                }
                result = new InOperator()
                {
                    Left  = propRef,
                    Right = list
                }.Normalize();
            }
예제 #8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="AllProperties"/> class.
 /// </summary>
 /// <param name="table">The table.</param>
 public AllProperties(QueryItem table)
 {
     Table = table;
 }
예제 #9
0
 protected override void VisitTopRecords(QueryItem query)
 {
     // Do nothing
 }
예제 #10
0
 public AmlToModelWriter(IServerContext context)
 {
     Query    = new QueryItem(context);
     _context = context;
 }