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))); } }
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); }
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())); } }
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); }
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); } } } }