Example #1
0
        public SqlSectionExpr Postprocess()
        {
            switch (sectionName)
            {
            case "SELECT":
            case "FROM":
                var lst = new Expr[args.Count];
                for (int i = 0; i < args.Count; i++)
                {
                    var  expr = args[i];
                    var  seq  = expr as SequenceExpr;
                    Expr item;
                    if (seq != null && seq.args.Count > 1)
                    {
                        item = AliasExpr.AsAlias(seq.args) ?? expr;
                    }
                    else
                    {
                        item = expr;
                    }
                    lst[i] = item;
                }
                var res = new SqlSectionExpr(sectionName, lst);
                return(res);

            default:
                return(this);
            }
        }
Example #2
0
        static IList <Expr> RestructAsSqlSelect(IList <Expr> lst)
        {
            var seq = lst[0] as SequenceExpr;

            if (seq == null)
            {
                return(lst);
            }
            var ref0 = (seq.args.Count > 0) ? seq.args[0] as ReferenceExpr : null;

            if (ref0 == null || string.Compare(ref0.name, "SELECT", StringComparison.InvariantCultureIgnoreCase) != 0)
            {
                return(lst);
            }
            string sectionName        = null;
            string sectionPartialName = string.Empty;
            var    res          = new List <Expr>(lst.Count);
            var    sectionItems = new List <Expr>(lst.Count);

            foreach (var item in lst)
            {
                var se = item as SequenceExpr;
                if (se == null)
                {
                    se = new SequenceExpr(item);
                }
                var argItems = new List <Expr>();
                foreach (var exprArg in se.args)
                {
                    var      expr = exprArg;
                    var      r    = expr as ReferenceExpr;
                    CallExpr ce   = null;
                    if (r == null)
                    {
                        ce = expr as CallExpr;
                        if (ce != null && ce.funcName.Length > 0)
                        {
                            r = new ReferenceExpr(ce.funcName);
                        }
                    }
                    if (r != null)
                    {
                        var s = r.name.ToUpperInvariant();
                        switch (s)
                        {
                        case "SELECT":
                        case "FROM":
                        case "WHERE":
                        case "BY":
                        case "USING":
                            if (argItems.Count > 0)
                            {
                                moveArgsToSection(sectionName, sectionItems, argItems);
                            }
                            if (sectionName != null)
                            {
                                var after = new SqlSectionExpr(sectionName, sectionItems.ToArray()).Postprocess();
                                if (after == null)
                                {
                                    return(null);
                                }
                                res.Add(after);
                            }
                            else if (sectionItems.Count > 0)
                            {
                                res.AddRange(sectionItems);
                            }
                            sectionItems.Clear();
                            if (s == "BY")
                            {
                                sectionName        = sectionPartialName + ' ' + s;
                                sectionPartialName = string.Empty;
                            }
                            else
                            {
                                System.Diagnostics.Trace.Assert(sectionPartialName.Length == 0, "Unknown SQL clause");
                                sectionName = s;
                            }
                            break;

                        case "JOIN":
                        {
                            System.Diagnostics.Trace.Assert(argItems.Count > 0, "No expressions before JOIN");
                            var ae = AliasExpr.AsAlias(argItems);
                            if (ae != null)
                            {
                                argItems.Clear();
                                argItems.Add(ae);
                            }
                            if (sectionPartialName.Length > 0)
                            {
                                argItems.Add(new ReferenceExpr(sectionPartialName));
                            }
                            argItems.Add(new ReferenceExpr(s));
                            if (ae == null)
                            {
                                var tmp = new SequenceExpr(argItems.ToArray());
                                argItems.Clear();
                                argItems.Add(tmp);
                            }
                            sectionPartialName = string.Empty;
                        }
                        break;

                        case "ON":
                        {
                            int i      = argItems.Count - 1;
                            var subseq = new List <Expr>();
                            while (i >= 0)
                            {
                                var exp = argItems[i];
                                var re  = exp as ReferenceExpr;
                                if (re != null && re.name == "JOIN")
                                {
                                    break;
                                }
                                argItems.RemoveAt(i);
                                i--;
                                subseq.Insert(0, exp);
                            }
                            if (subseq.Count > 0)
                            {
                                argItems.Add((Expr)AliasExpr.AsAlias(subseq) ?? new SequenceExpr(subseq));
                            }
                            argItems.Add(new ReferenceExpr(s));
                        }
                        break;

                        case "ORDER":
                        case "GROUP":
                        case "INNER":
                        case "OUTER":
                        case "LEFT":
                        case "RIGHT":
                        case "CROSS":
                        case "FULL":
                            if (sectionPartialName.Length == 0)
                            {
                                sectionPartialName = s;
                            }
                            else
                            {
                                sectionPartialName += ' ' + s;
                            }
                            break;

                        default:
                            if (ce == null)
                            {
                                argItems.Add(r);
                            }
                            r = null;
                            break;
                        }
                        if (ce == null)
                        {
                            continue;
                        }
                        if (r != null)
                        {
                            expr = new CallExpr(string.Empty, ce.args);
                            ce   = null;
                        }
                    }
                    if (ce != null && ce.funcName == string.Empty)
                    {
                        // no need to modify possible aliases in nested queries
                        var items = RestructAsSqlSelect(ce.args);
                        if (items != ce.args)
                        {
                            argItems.Add(CallExpr.Eval(new SequenceExpr(items)));
                        }
                    }
                    else
                    {
                        argItems.Add(expr);
                    }
                }
                moveArgsToSection(sectionName, sectionItems, argItems);
            }
            if (sectionName != null)
            {
                var after = new SqlSectionExpr(sectionName, sectionItems.ToArray()).Postprocess();
                if (after == null)
                {
                    return(null);
                }
                res.Add(after);
            }
            else if (sectionItems.Count > 0)
            {
                res.AddRange(sectionItems);
            }
            return(res.ToArray());
        }
Example #3
0
        public Expr CreateQueryExpr(Expr andCondition = null, AliasExpr groupBy = null, Expr[] orderBy = null,
                                    Func <AliasExpr, AliasExpr> resultModifier = null, params string[] resultsNames)
        {
            var sections = new List <Expr>(args.Count);

            // select
            Expr[] toSelect;
            var    gba = (groupBy == null) ? null : groupBy.alias;
            // "group by" preprocessing
            Expr newGroupBySection;
            Dictionary <string, bool> presentInGroupBy = null;
            {
                var currGroupBy = this[SqlSectionExpr.Kind.GroupBy];
                if (currGroupBy != null)
                {
                    newGroupBySection = currGroupBy;
                    presentInGroupBy  = GetPresenseDict(currGroupBy.args);
                }
                else if (groupBy != null)
                {
                    newGroupBySection = new SqlSectionExpr(SqlSectionExpr.Kind.GroupBy, groupBy.expr);
                    presentInGroupBy  = GetPresenseDict(new Expr[] { groupBy });
                }
                else
                {
                    newGroupBySection = null;
                }
            }
            // "select"
            bool resultsModified = false;

            if (resultsNames.Length == 0)
            {
                if (resultModifier != null)
                {
                    toSelect = new Expr[results.Length];
                    for (int i = toSelect.Length - 1; i >= 0; i--)
                    {
                        var r = results[i];
                        var s = IsGroupedBy(presentInGroupBy, r) ? r : resultModifier(r);
                        if (r != s)
                        {
                            resultsModified = true;
                        }
                        toSelect[i] = s;
                    }
                }
                else
                {
                    toSelect = results;
                }
            }
            else
            {
                resultModifier  = resultModifier ?? AsIs;
                toSelect        = new Expr[resultsNames.Length];
                resultsModified = true;
                for (int i = toSelect.Length - 1; i >= 0; i--)
                {
                    var r = results[resNdx[resultsNames[i]]];
                    toSelect[i] = IsGroupedBy(presentInGroupBy, r) ? r : resultModifier(r);
                }
            }
            if (resultsModified)
            {
                sections.Add(new SqlSectionExpr(SqlSectionExpr.Kind.Select, toSelect));
            }
            else
            {
                sections.Add(this[SqlSectionExpr.Kind.Select]);
            }
            // from
            sections.Add(this[SqlSectionExpr.Kind.From]);
            // where
            if (andCondition != null)
            {
                sections.Add(new SqlSectionExpr(SqlSectionExpr.Kind.Where, (condition == null) ? andCondition : new BinaryExpr(ExprType.LogicalAnd, condition, andCondition)));
            }
            else if (condition != null)
            {
                sections.Add(this[SqlSectionExpr.Kind.Where]);
            }
            // group by
            if (newGroupBySection != null)
            {
                sections.Add(newGroupBySection);
            }
            // order by
            var thisOrderBy = this[SqlSectionExpr.Kind.OrderBy];

            if (orderBy != null && orderBy.Length > 0)
            {
                if (thisOrderBy != null)
                {
                    var fromQuery = thisOrderBy.args.Where(e =>
                    {
                        var s = e.ToString();
                        return(presentInGroupBy == null || presentInGroupBy.ContainsKey(s));
                    }).ToArray();
                    var presentInOrderBy = GetPresenseDict(fromQuery);

                    orderBy = fromQuery.Concat(orderBy.Where(e =>
                    {
                        var s = e.ToString();
                        return(!presentInOrderBy.ContainsKey(s));
                    })).ToArray();
                }
                sections.Add(new SqlSectionExpr(SqlSectionExpr.Kind.OrderBy, orderBy));
            }
            else if (thisOrderBy != null)
            {
                sections.Add(this[SqlSectionExpr.Kind.OrderBy]);
            }
            //for (int i = 3; i < sql.Length; i++)
            //	if (sql[i] != null)
            //		sections.Add(sql[i]);
            return(new SequenceExpr(sections)); // todo
        }
Example #4
0
        public SqlExpr(IList <Expr> sections, Options opts)
            : base(sections)
        {
            foreach (SqlSectionExpr s in sections)
            {
                sql[(int)s.kind] = s;
            }
            SqlSectionExpr section;

            // FROM: scan sources
            section = this[SqlSectionExpr.Kind.From];
            if (section == null)
            {
                if (!opts.HasFlag(Options.EmptyFromPossible))
                {
                    throw new Generator.Exception($"new SqlExpr(...): nonempty FROM section expected");
                }
                section = new SqlSectionExpr(SqlSectionExpr.Kind.From);
            }
            IDictionary <string, int> srcAlias2Ndx;

            {
                var items = section.args;
                var srcs  = new List <AliasExpr>(items.Count);
                srcAlias2Ndx = new Dictionary <string, int>(items.Count, StringComparer.OrdinalIgnoreCase);
                int i = 0;
                foreach (var item in items)
                {
                    var ae = item as AliasExpr;
                    if (ae != null)
                    {
                        srcAlias2Ndx[ae.alias] = i++;
                        srcs.Add(ae);
                        continue;
                    }
                    var sq = item as SequenceExpr;
                    if (sq != null)
                    {
                        foreach (var it in sq.args)
                        {
                            var tmp = it as AliasExpr;
                            if (tmp != null)
                            {
                                srcAlias2Ndx[tmp.alias] = i++;
                                srcs.Add(tmp);
                            }
                        }
                    }
                    else
                    {
                        var tmp = new AliasExpr(item, item);
                        srcAlias2Ndx[tmp.alias] = i++;
                        srcs.Add(tmp);
                    }
                }
                //System.Diagnostics.Trace.Assert(i <= 32, "No more than 32 sources in FROM supported");
                sources = srcs.ToArray();
            }
            // SELECT: scan results
            section = this[SqlSectionExpr.Kind.Select];
            {
                var items = section.args;
                int n     = items.Count;
                //System.Diagnostics.Trace.Assert(n <= 64, "No more than 64 result columns in SELECT supported");
                results   = new AliasExpr[n];
                resFields = new Expr[n];
                resNdx    = new Dictionary <string, int>(n, StringComparer.OrdinalIgnoreCase);
                //resultUsesSrcs = new uint[n];
                for (int i = 0; i < n; i++)
                {
                    var aliasExpr = items[i] as AliasExpr;
                    if (aliasExpr != null)
                    {   // item in form "expression alias"
                        Expr resField = null;
                        foreach (var srcAlias in aliasExpr.expr.Traverse <BinaryExpr>(e =>
                        {
                            var be = e as BinaryExpr;
                            if (be != null && be.nodeType == ExprType.Fluent)
                            {
                                return(be);
                            }
                            else
                            {
                                return(null);
                            }
                        }))
                        {
                            if (srcAlias == null)
                            {
                                continue;
                            }
                            int j;
                            if (srcAlias2Ndx.TryGetValue(srcAlias.left.ToString(), out j)) // source alias may be to the left of point
                            {
                                //resultUsesSrcs[i] |= (uint)(1 << j);
                                resField = srcAlias;
                            }
                        }
                        //System.Diagnostics.Trace.Assert(resField != null, "No field reference found");
                        resFields[i] = resField ?? aliasExpr.expr;
                        results[i]   = aliasExpr;
                        resNdx.Add(aliasExpr.alias, i);
                        continue;
                    }
                    var binExpr = items[i] as BinaryExpr;
                    if (binExpr != null)
                    {
                        if (binExpr.nodeType == ExprType.Fluent)
                        {   // item in form "tablename.fieldname"
                            resFields[i] = binExpr;
                            results[i]   = new AliasExpr(binExpr, binExpr.right);
                            resNdx.Add(binExpr.right.ToString(), i);
                            continue;
                        }
                    }
                    else
                    {
                        var tmp = items[i] as ReferenceExpr;
                        if (tmp != null)
                        {   // item in form "fieldname"
                            resFields[i] = tmp;
                            results[i]   = new AliasExpr(tmp, tmp);
                            resNdx.Add(tmp.ToString(), i);
                            continue;
                        }
                    }
                    throw new ArgumentException("SELECTed expression must be a simple field reference or have alias", items[i].ToString());
                }
            }
            // WHERE: scan conditions
            section = this[SqlSectionExpr.Kind.Where];
            if (section != null)
            {
                var items = section.args;
                System.Diagnostics.Trace.Assert(items.Count == 1, "Only one condition expression in WHERE supported");
                condition = items[0];
            }
        }