예제 #1
0
파일: OPs.cs 프로젝트: WVitek/DotGlue
        public static object GetConstant(this Generator.Ctx ctx, string valueName)
        {
            int i   = ctx.IndexOf(valueName);
            var val = (i < 0) ? null : ctx[i];

            if (val == null)
            {
                return(null);
            }
            var expr = val as Expr;

            if (expr != null)
            {
                val = Generator.Generate(expr, ctx);
            }
            if (OPs.KindOf(val) == ValueKind.Const)
            {
                return(val);
            }
            else if (expr != null)
            {
                return(ctx.Error(string.Format("Constant expected as value of '{0}' // {1}", valueName, expr)));
            }
            else
            {
                return(ctx.Error(string.Format("Constant expected as value of '{0}'", valueName)));
            }
        }
예제 #2
0
        public static object UseSqlAsFuncsFrom(CallExpr ce, Generator.Ctx ctx)
        {
            var arg0 = Generator.Generate(ce.args[0], ctx);

            if (OPs.KindOf(arg0) != ValueKind.Const)
            {
                ctx.Error("Constant value expected");
            }

            var arg1 = (ce.args.Count < 2) ? null : Generator.Generate(ce.args[1], ctx);

            var        sqlFileName = Convert.ToString(arg0);
            DbFuncType forKinds;

            if (arg1 == null)
            {
                forKinds = DbFuncType.TimeSlice | DbFuncType.TimeInterval;
            }
            else
            {
                var lst = arg1 as IList ?? new object[] { arg1 };
                forKinds = DbFuncType.None;
                foreach (var v in lst)
                {
                    forKinds |= (DbFuncType)Enum.Parse(typeof(DbFuncType), Convert.ToString(v));
                }
            }

            var dbConnName = (ce.args.Count < 3) ? DefaultDbConnName : OPs.TryAsName(ce.args[2], ctx);

            if (string.IsNullOrEmpty(dbConnName))
            {
                ctx.Error($"Connection name must be nonempty: {ce.args[2]}");
            }

            var fullFileName = Path.IsPathRooted(sqlFileName)
                ? sqlFileName
                : Path.Combine(AppDomain.CurrentDomain.BaseDirectory, Convert.ToString(sqlFileName));

            var           cacheKey = $"FuncDefs:{fullFileName}:{forKinds.ToString()}";
            Func <object> ldfsFunc = () =>
            {
                var sqlCtx = new W.Expressions.Sql.Preprocessing.PreprocessingContext()
                {
                    sqlFileName                 = fullFileName,
                    cacheSubdomain              = "DB",
                    dbConnValueName             = dbConnName,
                    forKinds                    = forKinds,
                    ctx                         = ctx,
                    cachingExpiration           = TimeSpan.FromMinutes(5),
                    defaultLocationForValueInfo = (ce.args.Count < 4) ? null : OPs.TryAsString(ce.args[3], ctx)
                };
                return(sqlCtx.LoadingFuncs());
            };
            var lfds = (IEnumerable <FuncDef>)FuncDefs_Core._Cached(cacheKey, ldfsFunc, DateTimeOffset.MaxValue, TimeSpan.FromMinutes(5));

            return(lfds);
        }
예제 #3
0
파일: OPs.cs 프로젝트: WVitek/DotGlue
        public static object GetConstant(this Generator.Ctx ctx, Expr expr)
        {
            var val = Generator.Generate(expr, ctx);

            if (OPs.KindOf(val) == ValueKind.Const)
            {
                return(val);
            }
            else
            {
                return(ctx.Error("Constant expected as value of " + expr.ToString()));
            }
        }
예제 #4
0
파일: Impl.cs 프로젝트: WVitek/DotGlue
        static Dictionary <TAttr, object> ParseAttrs <TAttr>(Generator.Ctx ctx, IEnumerable <string> comments,
                                                             params TAttr[] firstLineDefaultKeys
                                                             )
            where TAttr : struct
        {
            bool firstLine = true;
            var  lstDescr  = new List <string>();
            Dictionary <TAttr, object> attrs = null;
            int iDefaultKey = (firstLineDefaultKeys.Length > 0) ? 0 : -1;

            foreach (var txt in comments)
            {
                bool isKeyValueComment;
                {
                    int iEqualSign = txt.IndexOf('=');
                    if (iEqualSign > 0)
                    {
                        isKeyValueComment = !Enumerable.Range(0, iEqualSign - 1).Any(i => char.IsWhiteSpace(txt[i]));
                    }
                    else
                    {
                        isKeyValueComment = false;
                    }
                }
                if ((firstLineDefaultKeys.Length == 0 || !firstLine) && !isKeyValueComment)
                {
                    if (txt.Trim().Length == 0)
                    {
                        lstDescr.Clear();
                    }
                    else
                    {
                        lstDescr.Add(txt);
                    }
                    continue; // do not parse simple comment lines
                }
                foreach (Expr attr in Parser.ParseSequence(txt, comparison: StringComparison.InvariantCulture))
                {
                    string attrName;
                    Expr   attrValue;
                    if (attr.nodeType == ExprType.Equal)
                    {   // named attribute
                        var be = (BinaryExpr)attr;
                        if (be.left.nodeType == ExprType.Reference)
                        {
                            attrName = Convert.ToString(be.left);
                        }
                        else
                        {
                            var name = Generator.Generate(be.left, ctx);
                            if (OPs.KindOf(name) != ValueKind.Const)
                            {
                                ctx.Error("ParseAttrs: attribute name must be constant\t" + be.left.ToString());
                            }
                            attrName = Convert.ToString(name);
                        }
                        attrValue = be.right;
                    }
                    else if (firstLine && iDefaultKey >= 0)
                    {   // unnamed attributes possible in first line
                        attrs = attrs ?? new Dictionary <TAttr, object>();
                        attrs.Add(firstLineDefaultKeys[iDefaultKey], attr);
                        if (++iDefaultKey >= firstLineDefaultKeys.Length)
                        {
                            iDefaultKey = -1;
                        }
                        continue;
                    }
                    else
                    {
                        break;  // it is simple comment to the end of line?
                    }
                    if (attrValue.nodeType != ExprType.Constant)
                    {
                        attrValue = new CallExpr(FuncDefs_Core._block, attrValue);
                    }
                    var value = Generator.Generate(attrValue, ctx);
                    if (OPs.KindOf(value) != ValueKind.Const)
                    {
                        ctx.Error(string.Format("ParseAttrs: attribute value must be constant\t{0}={1}", attrName, attrValue));
                    }
                    if (attrName != null)
                    {
                        if (!Enum.TryParse <TAttr>(attrName, out var attrKey))
                        {
                            throw new Generator.Exception($"Unrecognized attribute name, {attrName}={attrValue} // enum {typeof(TAttr)}");
                        }
                        attrs = attrs ?? new Dictionary <TAttr, object>();
                        Attr.Add(attrs, attrKey, value, false);
                    }
                }
                firstLine = false;
            }
            if (lstDescr.Count > 0)
            {
                attrs = attrs ?? new Dictionary <TAttr, object>();
                if (!Enum.TryParse <TAttr>(nameof(Attr.Tbl.Description), out var attrDescription))
                {
                    throw new Generator.Exception($"ParseAttrs: enum '{typeof(TAttr)}' does not contains value named '{nameof(Attr.Tbl.Description)}'");
                }
                attrs.Add(attrDescription, lstDescr);
            }
            return(attrs);
        }
예제 #5
0
파일: Impl.cs 프로젝트: WVitek/DotGlue
        public static IEnumerable <T> ParseSqlFuncs <T>(string sqlFileName, SqlFuncDefAction <T> func, Generator.Ctx ctx)
        {
            var seps = new char[] { '\t', ' ' };

            using (var rdr = new System.IO.StreamReader(sqlFileName))
            {
                var uniqFuncName = new Dictionary <string, bool>();
                var queryText    = new System.Text.StringBuilder();
                Dictionary <Attr.Tbl, object> extraAttrs = null;
                var innerAttrs      = new List <Dictionary <Attr.Col, object> >();
                var comments        = new List <string>();
                int lineNumber      = 0;
                int lineNumberFirst = -1;
                while (true)
                {
                    var line = rdr.ReadLine();
                    lineNumber++;
                    if (line == null || line.StartsWith(";"))
                    {   // "end of query" line
                        if (queryText.Length > 0)
                        {
                            string funcPrefix = null;
                            int    actuality  = -1; // negative to use defaultActualityDays value;

                            if (extraAttrs != null)
                            {
                                // Scan function attributes
                                foreach (var attr in extraAttrs)
                                {
                                    switch (attr.Key)
                                    {
                                    case Attr.Tbl.FuncPrefix:
                                        funcPrefix = attr.Value.ToString();
                                        break;

                                    case Attr.Tbl.ActualityDays:
                                        actuality = Convert.ToInt32(attr.Value);
                                        break;

                                    case Attr.Tbl._columns_attrs:
                                        throw new Generator.Exception($"Attribute name '{attr.Key}' is reserved for inner purposes");
                                    }
                                }
                            }
                            else
                            {
                                extraAttrs = new Dictionary <Attr.Tbl, object>();
                            }

                            bool arrayResults = false;
                            if (funcPrefix == null)
                            {
                                funcPrefix = "QueryAtLn" + lineNumberFirst.ToString();
                                extraAttrs[Attr.Tbl.FuncPrefix] = funcPrefix;
                            }
                            else if (funcPrefix.EndsWith("[]"))
                            {
                                arrayResults = true;
                                funcPrefix   = funcPrefix.Substring(0, funcPrefix.Length - 2);
                                extraAttrs[Attr.Tbl.ArrayResults] = true;
                            }
                            //if (actuality < 0)
                            //{
                            //    actuality = Attr.defaultActualityDays;
                            //    extraAttrs[Attr.Tbl.ActualityDays] = actuality;
                            //}

                            if (innerAttrs != null)
                            {
                                extraAttrs[Attr.Tbl._columns_attrs] = innerAttrs.ToArray();
                            }

                            try { uniqFuncName.Add(funcPrefix, true); }
                            catch (ArgumentException) { ctx.Error("ParseSqlFuncs: function prefix is not unique\t" + funcPrefix); }
                            yield return(func(funcPrefix, actuality, queryText.ToString(), arrayResults, extraAttrs));
                        }
                        // must clear all query-related data after converting query into func
                        lineNumberFirst = -1;
                        extraAttrs      = null;
                        innerAttrs.Clear();
                        queryText.Clear();
                        comments.Clear();
                        if (line == null)
                        {
                            break;
                        }
                        continue;
                    }

                    if (line.Length == 0)
                    {
                        continue;
                    }

                    if (line.StartsWith("--"))
                    {   // comment line
                        if (line.StartsWith("----"))
                        {
                            // skip commented comments :)
                            continue;
                        }
                        if (line.Length == 2)
                        {
                            // empty comment line clear previous block of comments
                            comments.Clear();
                        }
                        else
                        {
                            // akkumulate comments
                            comments.Add(line.Substring(2));
                        }
                        continue;
                    }

                    // remember first line of query
                    if (queryText.Length == 0)
                    {
                        if (lineNumberFirst < 0)
                        {
                            lineNumberFirst = lineNumber;
                        }
                    }

                    // query line
                    if (queryText.Length == 0)
                    {
                        // first line of query, parse header comments into function attributes
                        extraAttrs = ParseAttrs(ctx, comments, Attr.Tbl.FuncPrefix, Attr.Tbl.ActualityDays);
                    }
                    else
                    {
                        // not first line of query, parse inner comments into inner attributes
                        innerAttrs.Add(ParseAttrs <Attr.Col>(ctx, comments));
                    }

                    comments.Clear();

                    // akkumulate lines of query
                    line.Trim();
                    if (line.Length > 0)
                    {
                        queryText.AppendLine(line);
                    }
                }
            }
        }