Exemple #1
0
        static void SqlFuncsToTextImpl(Generator.Ctx ctx, TextWriter wr, Func <ValueInfo, bool> filter)
        {
            foreach (var f in ctx.GetFunc(null, 0))
            {
                if (f.xtraAttrs == null || !f.xtraAttrs.TryGetValue(nameof(QueryTemplate), out var objQT))
                {
                    // no QueryTemplate = is not SQL-originated function
                    continue;
                }
                if (!f.resultsInfo.Any(filter))
                {
                    // no any output parameter from specified location/origin/source
                    continue;
                }

                Attr.TblAttrsFriendlyText(f.xtraAttrs, wr);
                var colAttrs  = (IList <Dictionary <Attr.Col, object> >)f.xtraAttrs[nameof(Attr.Tbl._columns_attrs)];
                var queryTmpl = (QueryTemplate)objQT;
                var sql       = queryTmpl.SrcSqlExpr;
                foreach (SqlSectionExpr sec in sql.args)
                {
                    var  args        = sec.args;
                    var  attrs       = (sec.kind == SqlSectionExpr.Kind.Select) ? colAttrs : null;
                    bool fromNewLine = args.Count > 1 || attrs != null;
                    wr.Write(sec.sectionName);
                    if (fromNewLine)
                    {
                        wr.WriteLine();
                    }
                    for (int i = 0; i < args.Count; i++)
                    {
                        if (i > 0)
                        {
                            wr.WriteLine(',');
                        }
                        if (attrs != null)
                        {
                            Attr.FriendlyText(attrs[i], wr);
                        }
                        wr.Write(fromNewLine ? '\t' : ' ');
                        wr.Write(args[i]);
                    }
                    wr.WriteLine();
                }
                //wr.WriteLine(sql);
                wr.WriteLine(';');
                wr.WriteLine();
                wr.WriteLine();
            }
        }
Exemple #2
0
        public static object FindDependencies(CallExpr ce, Generator.Ctx ctx)
        {
            var arg0 = Generator.Generate(ce.args[0], ctx);

            if (OPs.KindOf(arg0) != ValueKind.Const || arg0 == null)
            {
                throw new SolverException("FindDependencies: list of source params must be constant and not null");
            }
            var arg1 = (ce.args.Count > 1) ? Generator.Generate(ce.args[1], ctx) : null;

            if (OPs.KindOf(arg1) != ValueKind.Const)
            {
                throw new SolverException("FindDependencies: optional list of dependent params must be constant");
            }
            var arg2 = (ce.args.Count > 2) ? Generator.Generate(ce.args[2], ctx) : null;

            if (OPs.KindOf(arg2) != ValueKind.Const)
            {
                throw new SolverException("FindDependencies: optional list of unusable params must be constant");
            }
            var srcPrms   = ((IList)arg0).Cast <object>().Select(o => o.ToString()).ToArray();
            var depPrms   = (arg1 == null) ? null : ((IList)arg1).Cast <object>().Select(o => o.ToString()).ToArray();
            var unusables = (arg2 == null)
                ? new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase)
                : ((IList)arg2).Cast <object>().Select(o => o.ToString()).ToDictionary(s => s, StringComparer.OrdinalIgnoreCase);
            var aliasOf      = GetAliases(ctx);
            var funcs        = Dependecies.GetFuncInfos(ctx.GetFunc(null, 0), aliasOf, fi => !fi.inputs.Any(inp => unusables.ContainsKey(inp)));
            var dependencies = Dependecies.Find(funcs, aliasOf, int.MaxValue, srcPrms, depPrms);
            var resDict      = new Dictionary <string, bool>(StringComparer.OrdinalIgnoreCase);
            var resParams    = (depPrms == null)
                ? dependencies.Keys.Except(srcPrms, StringComparer.OrdinalIgnoreCase)
                : depPrms.Where(s => dependencies.ContainsKey(s));
            var res = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase);

            foreach (var prmName in resParams)
            {
                var deps = dependencies[prmName];
                var srcs = srcPrms.Where(s => deps.ContainsKey(s)).ToArray();
                if (srcs.Length > 0)
                {
                    res.Add(prmName, srcs);
                }
            }
            return(res);
        }
Exemple #3
0
        static IEnumerable <FuncDef> DefineProjectionFuncsImpl(CallExpr ce, Generator.Ctx ctx, bool acceptVector)
        {
            var inpParams      = ((IList)OPs.GetConstant(ctx, ce.args[0])).Cast <object>().Select(Convert.ToString).ToArray();
            var inpParamsParts = inpParams.Select(s => s.Split('_')).ToArray();
            var inpParamsMasks = inpParamsParts.Where(parts => parts.Any(string.IsNullOrEmpty)).ToArray();
            var outParams      = ((IList)OPs.GetConstant(ctx, ce.args[1])).Cast <object>().Select(Convert.ToString).ToArray();
            var outParamsMasks = outParams.Select(s => Convert.ToString(s).Split('_')).ToArray();

            var newFuncName = "@projfunc:" + ce.args[ce.args.Count - 1].ToString().Replace('(', '_').Replace(')', '_').Replace('"', '_').Replace('\'', '_');

            #region Collect suitable parameters from all functions outputs
            var suitableParams = new Dictionary <string, string[]>(StringComparer.OrdinalIgnoreCase);

            foreach (var f in ctx.GetFunc(null, 0))
            {
                foreach (var prm in f.resultsInfo)
                {
                    var prmParts = prm.Parts();
                    for (int i = 0; i < inpParamsMasks.Length; i++)
                    {
                        var maskParts = inpParamsMasks[i];
                        var details   = GetDetailsIfMatched(prmParts, maskParts);
                        if (details == null)
                        {
                            continue;
                        }
                        if (!suitableParams.TryGetValue(details, out var suitables))
                        {
                            suitables = new string[inpParamsMasks.Length];
                            suitableParams.Add(details, suitables);
                        }
                        suitables[i] = details;
                    }
                }
            }
            #endregion

            #region Return FuncDef for each suitable params set
            foreach (var suitable in suitableParams.Where(prms => prms.Value.All(s => s != null)))
            {
                var details = suitable.Key;
                var inps    = new string[inpParamsParts.Length];
                for (int i = 0; i < inpParamsParts.Length; i++)
                {
                    var ip = inpParamsParts[i];
                    if (ip.Any(string.IsNullOrEmpty))
                    {   // one or more parts masked
                        inps[i] = ParamFromMaskAndDetails(details, ip);
                    }
                    else
                    {
                        inps[i] = inpParams[i];
                    }
                }

                var outs = new string[outParams.Length];
                for (int i = 0; i < outParamsMasks.Length; i++)
                {
                    outs[i] = ParamFromMaskAndDetails(details, outParamsMasks[i]);
                }

                yield return(FuncDefs_Core.macroFuncImpl(
                                 context: ctx,
                                 nameForNewFunc: new ConstExpr(newFuncName + details),
                                 inpsDescriptors: new ArrayExpr(inps.Select(ReferenceExpr.Create).Cast <Expr>().ToList()),
                                 outsDescriptors: new ArrayExpr(outs.Select(ReferenceExpr.Create).Cast <Expr>().ToList()),
                                 funcBody: ce.args[ce.args.Count - 1],
                                 inputParameterToSubstitute: (ce.args.Count > 3) ? ce.args[2] : null,
                                 funcAcceptVector: acceptVector
                                 ));
            }
            #endregion
        }
Exemple #4
0
        static void SqlFuncsToDDL_Impl(Generator.Ctx ctx, TextWriter wr, TextWriter drops, string locationCode)
        {
            var dictTypes    = new Dictionary <string, ValInf>(StringComparer.OrdinalIgnoreCase);
            var tablesToDrop = new List <string>();

            foreach (var f in ctx.GetFunc(null, 0))
            {
                if (f.xtraAttrs == null || !f.xtraAttrs.TryGetValue(nameof(QueryTemplate), out var objQT))
                {
                    // no QueryTemplate = is not SQL-originated function
                    continue;
                }

                var queryTmpl = (QueryTemplate)objQT;
                var sql       = queryTmpl.SrcSqlExpr;
                var secFrom   = sql[SqlSectionExpr.Kind.From];

                if (secFrom.args.Count > 1)
                {
                    // can't generate DDL for join
                    continue;
                }

                if (f.resultsInfo.All(vi => vi.location != locationCode))
                {
                    // no any output parameter from specified location/origin/source
                    continue;
                }

                Attr.TblAttrsFriendlyText(f.xtraAttrs, wr);

                var colAttrs = (IList <Dictionary <Attr.Col, object> >)f.xtraAttrs[nameof(Attr.Tbl._columns_attrs)];

                var secSelect = sql[SqlSectionExpr.Kind.Select];
                var tableName = secFrom.args[0].ToString();

                tablesToDrop.Add(tableName);

                var extraDDL   = new StringBuilder();
                var initValues = new Dictionary <string, object>();
                int nInitRows  = 0;

                wr.WriteLine($"CREATE TABLE {tableName} (");

                var columns = secSelect.args;
                // columns
                for (int i = 0; i < columns.Count; i++)
                {
                    AliasExpr ae; // column is presented as pair of field name and globally unique alias of value
                    {
                        var colExpr = columns[i];
                        ae = colExpr as AliasExpr;

                        // Skip improper fields
                        if (ae == null)
                        {
                            if (colExpr is ReferenceExpr re)
                            {
                                ae = new AliasExpr(re, re);
                            }
                            else
                            {
                                wr.WriteLine($"--???\t{colExpr}");
                                continue;
                            }
                        }
                        switch (ae.left.nodeType)
                        {
                        case ExprType.Reference: break;

                        case ExprType.Constant:
                            wr.WriteLine($"--\t{ae.left}\t{ae.right}");
                            continue;

                        default:
                            wr.WriteLine($"--???\t{ae.left}\t{ae.right}");
                            continue;
                        }
                    }

                    var attrs = colAttrs[i] ?? Attr.Empty;

                    var fieldName  = ae.left.ToString();//.ToUpperInvariant();
                    var fieldAlias = ValueInfo.WithoutParts(ae.right.ToString(), ValueInfo.Part.Location);

                    var descr = attrs.Get(Attr.Col.Description);

                    string type, trail;
                    {
                        bool isPK    = attrs.GetBool(Attr.Col.PK, false);
                        bool notNull = isPK || attrs.GetBool(Attr.Col.NotNull, false);

                        var curr = new ValInf()
                        {
                            sqlType = attrs.GetString(Attr.Col.Type)
                        };

                        var initVals = attrs.Get(Attr.Col.InitValues);
                        if (initVals != null)
                        {
                            initValues.Add(fieldName, initVals);
                            if (initVals is IList lst)
                            {
                                nInitRows = Math.Max(lst.Count, nInitRows);
                            }
                            else if (nInitRows == 0)
                            {
                                nInitRows = 1;
                            }
                        }

                        ValInf valInfByLookupAttr = null;
                        if (attrs.TryGet(Attr.Col.Lookup, out var objLookup))
                        {
                            var masked = ValueInfo.OverrideByMask(fieldAlias, objLookup.ToString());

                            if (!dictTypes.TryGetValue(masked, out valInfByLookupAttr))
                            {
                                var parts = ValueInfo.FourParts(masked);
                                parts[3]           = null; // remove 'units' part
                                masked             = ValueInfo.FromParts(parts);
                                valInfByLookupAttr = dictTypes[masked];
                            }
                        }

                        // Descriptor 'type' in form '_QUANTITY__UNIT'
                        // remove substance and location parts
                        string sDescrType = ValueInfo.WithoutParts(fieldAlias, ValueInfo.Part.Substance, ValueInfo.Part.Location);

                        ValInf valInfExact = null, valInfByType = null;

                        if (valInfByLookupAttr != null ||
                            dictTypes.TryGetValue(fieldAlias, out valInfExact) ||
                            dictTypes.TryGetValue(sDescrType, out valInfByType))
                        {
                            var vi = valInfByLookupAttr ?? valInfExact ?? valInfByType;

                            if (vi.pkTable != null)
                            {
                                if (isPK)
                                {
                                    if (valInfExact != null)
                                    {
                                        wr.WriteLine($"--WARNING! Value named '{fieldAlias}' is already used as PK in table '{vi.pkTable}'");
                                    }
                                }
                                else
                                {   // create foreign key constraint
                                    var hash = $"{tableName}:{fieldAlias}".GetHashCode().ToString("X").Substring(0, 4);
                                    var sPK  = vi.pkTable.Split('_')[0];
                                    if (sPK.StartsWith(tableName))
                                    {
                                        sPK = sPK.Substring(tableName.Length);
                                    }
                                    var fk = string.Format("fk_{0}_{1}",
                                                           (tableName + '_' + sPK).DeLowerVowel(22),
                                                           hash
                                                           );

                                    #region XRef comment (cross reference information)
                                    {
                                        f.xtraAttrs.TryGetValue(nameof(Attr.Tbl.Substance), out var substance);
                                        f.xtraAttrs.TryGetValue(nameof(Attr.Tbl.Description), out var tableDescr);
                                        var tDesc = Attr.OneLineText(tableDescr);
                                        var fDesc = Attr.OneLineText(descr);
                                        extraDDL.AppendLine($"--XRef\t{vi.pkTable}\t{substance}\t{tDesc}\t{tableName}\t{fieldName}\t{fDesc}");
                                    }
                                    #endregion

                                    extraDDL.AppendLine($"ALTER TABLE {tableName} ADD CONSTRAINT {fk} FOREIGN KEY ({fieldName}) REFERENCES {vi.pkTable};");
                                }
                            }

                            if (curr.sqlType == null)
                            {
                                curr = new ValInf()
                                {
                                    firstValue = vi.firstValue, pkField = vi.pkField, pkTable = vi.pkTable, sqlType = vi.sqlType
                                }
                            }
                            ;
                            else
                            {
                                if (curr.sqlType != vi.sqlType && valInfExact != null)
                                {
                                    wr.WriteLine($"--WARNING! Type mismatch for value named '{fieldAlias}', first declaration has type '{vi.sqlType}'");
                                }
                                curr.firstValue = vi.firstValue;
                                curr.pkTable    = vi.pkTable;
                                curr.pkField    = vi.pkField;
                            }
                        }

                        if (valInfByLookupAttr == null && valInfExact == null)
                        {
                            bool noTypeFound = curr.sqlType == null;
                            if (noTypeFound)
                            {
                                var info = ValueInfo.Create(fieldAlias, true);
                                curr.sqlType = info?.quantity.DefaultDimensionUnit.Name ?? fieldAlias;
                                wr.WriteLine($"--WARNING! No SQL-type inferenced for value named '{fieldAlias}' of type '{sDescrType}'");
                            }
                            if (curr.sqlType != null)
                            {
                                if (isPK)
                                {
                                    curr.pkTable = tableName;
                                    curr.pkField = fieldName;
                                    if (initVals is IList lst)
                                    {
                                        curr.firstValue = lst[0];
                                    }
                                    else
                                    {
                                        curr.firstValue = initVals;
                                    }
                                }
                                if (noTypeFound == false)
                                {
                                    if (isPK)
                                    {
                                        dictTypes.Add(fieldAlias, curr);
                                    }
                                    if (!dictTypes.ContainsKey(sDescrType))
                                    {
                                        dictTypes.Add(sDescrType, new ValInf()
                                        {
                                            sqlType = curr.sqlType
                                        });
                                    }
                                }
                            }
                        }

                        object defVal = attrs.Get(Attr.Col.Default);

                        if (isPK)
                        {
                            trail = " NOT NULL PRIMARY KEY";
                        }
                        else if (notNull)
                        {
                            var def = attrs.Get(Attr.Col.Default) ?? curr.firstValue;
                            if (def != null)
                            {
                                trail = $" DEFAULT {new ConstExpr(def)} NOT NULL";
                            }
                            else
                            {
                                trail = " NOT NULL";
                            }
                        }
                        else
                        {
                            trail = null;
                        }

                        type = curr.sqlType;
                    }

                    var typeArgs = attrs.GetString(Attr.Col.TypeArgs);
                    if (!string.IsNullOrEmpty(typeArgs))
                    {
                        typeArgs = '(' + typeArgs + ')';
                    }

                    wr.WriteLine($"\t{fieldName} {type}{typeArgs}{trail},\t--{fieldAlias}\t{Attr.OneLineText(descr)}");
                }

                wr.WriteLine(')');
                wr.WriteLine(';');
                wr.WriteLine();

                if (extraDDL.Length > 0)
                {
                    wr.WriteLine(extraDDL);
                    wr.WriteLine();
                    extraDDL.Clear();
                }

                if (nInitRows > 0)
                {
                    var fields = string.Join(", ", initValues.Keys);
                    for (int i = 0; i < nInitRows; i++)
                    {
                        var vals = initValues.Values.Select(v =>
                        {
                            if (v is IList lst)
                            {
                                return((i < lst.Count) ? lst[i] : null);
                            }
                            else
                            {
                                return(v);
                            }
                        })
                                   .Select(v => new ConstExpr(v))
                                   .Select(v => ((v.value is string) ? "N" : null) + v.ToString());
                        var values = string.Join(", ", vals);
                        wr.WriteLine($"INSERT INTO {tableName} ({fields}) VALUES ({values});");
                    }
                    wr.WriteLine();

                    #region How to add MS SQL descriptions example
                    //declare @CurrentUser sysname;
                    //select @CurrentUser = user_name();
                    //execute sp_addextendedproperty 'MS_Description', 'Табле комент', 'user', @CurrentUser, 'table', 'PipeSysType_CL';
                    //execute sp_addextendedproperty 'MS_Description', 'This is the column comment', 'user', @CurrentUser, 'table', 'TABLE_1', 'column', 'ID'            }
                    #endregion
                }
            }
            if (drops != null)
            {
                tablesToDrop.Reverse();
                foreach (var tableName in tablesToDrop)
                {
                    drops.WriteLine($"DROP TABLE {tableName};");
                }
            }
        }