Пример #1
0
        ///
        /// Baut die Dinge zusammen, die speziell für eine History-Table erforderlich sind
        ///
        private void PrepareHistoryTable(IBLInterface iifa)
        {
            if (!(iifa is DerivedBLInterface))
            {
                throw new InvalidInterfaceTypeException("An dieser Stelle dürfen nur DerivedBLInterfaces ankommen!");
            }

            // Dadurch bekommen wir Zugriff aufs Default-Interface!
            var ifa      = (DerivedBLInterface)iifa;
            var identity = ifa.Attributes.Single(a => a.IsIdentity);
            var pk       = (BaseBLAttribute)ifa.Attributes.Single(a => a.IsPartOfUniqueKey && a is BaseBLAttribute);

            this.Attributes.Add(ConvertAttribute(identity));
            this.Attributes.Add(CreateVersionKNZAttribute(pk));
            this.Attributes.Add(CreateNonVersionedRefAttribute(pk, ifa));

            // Restliche Standardattribute
            var dataAttributes = ifa.Attributes
                                 .Where(a => !(a.IsTechnicalAttribute ||
                                               a.IsIdentity ||
                                               (a.IsPartOfUniqueKey && a is BaseBLAttribute)
                                               ));

            foreach (var attr in dataAttributes)
            {
                this.Attributes.Add(ConvertAttribute(attr));
            }
        }
Пример #2
0
        private void PrepareHistorizedFactTable(IBLInterface iifa)
        {
            if (!(iifa is DefaultBLInterface))
            {
                throw new InvalidInterfaceTypeException("An dieser Stelle dürfen nur DefaultBLInterfaces ankommen!");
            }
            if (!iifa.IsHistorized)
            {
                throw new InvalidInterfaceTypeException("An dieser Stelle dürfen nur historisierte Interfaces ankommen!");
            }
            if (iifa.InterfaceType != CoreInterfaceType.FACT_TABLE)
            {
                throw new InvalidInterfaceTypeException("An dieser Stelle dürfen nur FactTable Interfaces ankommen!");
            }

            var ifa = (DefaultBLInterface)iifa;

            // Restliche Standardattribute
            var dataAttributes = ifa.Attributes
                                 .Where(a => !(a.IsTechnicalAttribute));

            foreach (var attr in dataAttributes)
            {
                this.Attributes.Add(ConvertAttribute(attr));
            }
        }
Пример #3
0
        ///
        /// Generiert die IL -> BL View für eine DimTable
        ///
        internal string GenerateDimTableView(IBLInterface ifa)
        {
            if (ifa is DerivedBLInterface)
            {
                throw new InvalidInterfaceTypeException("LOGICAL_ERROR: Die Methode GenerateDimView in CreateBLGenerator.cs ist nur "
                                                        + "für nicht historisierte DimTables vorgesehen");
            }

            string code = "\n";

            // Kopf von create view generieren
            code += GenerateDefaultDimTableViewTop(ifa);
            // T_Modifikation berechnen
            code += GenerateTModificationNoHistory(ifa);

            // Join für nicht historisierte DimTables generieren ...
            code += $"from {ifa.GetILInterface().FullName} as il \n";
            code += $"left outer join {ifa.FullName} as bl\n".Indent("    ");
            foreach (var attr in ifa.UniqueKeyAttributes)
            {
                if (attr == ifa.UniqueKeyAttributes.First())
                {
                    // TODO: il.{attr.Name} sollte eigentlich attr.GetILAttribute().Name sein, geht aber bei Mandant_KNZ nicht!
                    code += $"  on il.{attr.Name} = bl.{attr.Name}\n".Indent("    ");
                }
                else
                {
                    code += $" and il.{attr.Name} = bl.{attr.Name}\n".Indent("    ");
                }
            }
            code += ";\ngo\n\n";
            return(code);
        }
Пример #4
0
        ///
        /// Generieren einer Views für eine historisierte DimTable (_VERSION_VW)
        ///
        internal string GenerateHistorizedDimTableView(IBLInterface ifa)
        {
            string code = $"-- View für historisierte DimTable {ifa.Name}\n";

            code += "-- !!! DAS KONZEPT HIER IST NOCH EIN EINZIGER BUG !!!\n";
            code += GenerateDefaultDimTableViewTop(ifa);
            // TODO: ...
            code += GenerateTModificationWithHistory(ifa);
            // TODO: ...

            // Join für historisierte DimTables generieren ...
            code += $"from {ifa.GetILInterface().FullName} as il \n";
            code += $"left outer join {ifa.FullName} as bl\n".Indent("    ");
            foreach (var attr in ifa.UniqueKeyAttributes.Where(a => a != ifa.HistoryAttribute))
            {
                if (attr == ifa.UniqueKeyAttributes.First())
                {
                    // TODO: il.{attr.Name} sollte eigentlich attr.GetILAttribute().Name sein, geht aber bei Mandant_KNZ nicht!
                    code += $"  on il.{attr.Name} = bl.{attr.Name}\n".Indent("    ");
                }
                else
                {
                    code += $" and il.{attr.Name} = bl.{attr.Name}\n".Indent("    ");
                }
            }
            // ACHTUNG: so kann ich das nicht stehen lassen, das multipliziert evtl. Sätze!!!
            code += $" and (bl.{ifa.HistoryAttribute.Name} is null or bl.{ifa.HistoryAttribute.Name} > dbo.GetCurrentTimeForHistory())".Indent("    ");
            // /Achtung
            code += ";\ngo\n\n";
            code += "go\n\n";
            return(code);
        }
Пример #5
0
        ///
        /// Generiert den SQL-Code für die Berechnung von T_Modifikation in
        /// Views zu nicht historisierten DimTables
        ///
        private string GenerateTModificationNoHistory(IBLInterface ifa)
        {
            string code = "";

            var pk = ifa.PrimaryKeyAttributes?.First();

            if (pk == null)
            {
                throw new InvalidParameterException($"{ifa.FullName} has no PrimaryKey-Attributes");
            }

            code += $"case\n".Indent("    ");
            code += $"when bl.{pk.Name} is null then 'I'\n".Indent("        ");

            var historyCheckAttrs = ifa.UpdateCheckAttributes;

            foreach (var attr in historyCheckAttrs)
            {
                if (historyCheckAttrs.First() == attr)
                {
                    code += $"when bl.{attr.Name} <> il.{attr.GetILAttribute().Name}\n".Indent("        ");
                }
                else
                {
                    code += $"  or bl.{attr.Name} <> il.{attr.GetILAttribute().Name}\n".Indent("        ");
                }
            }
            code += "then 'U'\nelse 'X'\n".Indent("        ");
            code += "end as T_Modifikation\n".Indent("    ");

            return(code);
        }
Пример #6
0
        ///
        /// Generiert den Standard-Kopf für DimTableViews in der BL
        ///
        private string GenerateDefaultDimTableViewTop(IBLInterface ifa)
        {
            string code = $"go\ncreate view {ifa.ViewName} as\n";

            code += $"select\n";
            foreach (var attr in ifa.Attributes)
            {
                if (!attr.IsTechnicalAttribute)
                {
                    var il = attr.GetILAttribute();
                    if (il != null)
                    {
                        code += $"il.{il.Name} as {attr.Name},\n".Indent("    ");
                    }
                    else if (attr.IsPrimaryKey)
                    {
                        code += $"bl.{attr.Name},\n".Indent("    ");
                    }
                }
            }

            if (ifa.IsMandant)
            {
                code += "il.Mandant_KNZ,\n".Indent("    ");
            }
            return(code);
        }
        ///
        /// Generiert ein neues T_Gueltig_Bis-Attribut
        ///
        public static IBLAttribute GetNewTGueltigBisAttribute(IBLInterface parentInterface, IBLInterface timeInterface)
        {
            if (timeInterface == null)
            {
                throw new MissingFinestTimeAttributeException("Wenn Sie history=\"true\" verwenden müssen Sie ein finest_time_attribute angeben");
            }

            // 1. Das Primärschlüssel-Attribut (z. B. KNZ) aus dem FinestTimeInterface ermitteln.
            var timeAttribute = timeInterface.UniqueKeyAttributes.Where(a => a.Name != "Mandant_KNZ").First();

            // 2. Custom-Attribut bauen.
            return(new CustomBLAttribute()
            {
                ShortName = null,
                Name = "T_Gueltig_Bis_Dat",
                FullName = $"{parentInterface.Name}.T_Gueltig_Bis_Dat",
                DataType = timeAttribute.DataType,
                Length = timeAttribute.Length,
                Decimals = timeAttribute.Decimals,
                IsPartOfUniqueKey = true,
                ParentInterface = parentInterface,
                IsTechnicalAttribute = true,
                SortId = 106
            });
        }
Пример #8
0
        ///
        /// Generiert ein Update-Statement, das dann die historisierungsrelevanten
        /// Attribute des Interfaces aktualisiert, wenn der letzte Historiensatz
        /// in der gleichen Zeiteinheit angelegt wurde, für die die aktuell
        /// zu ladenden Daten geliefert wurden.
        ///
        private void GenerateInTimeUpdateForDimTableWithHistory(IBLInterface ifa, StringBuilder sb)
        {
            var idAttribute = ifa.Attributes.Where(a => a.IsIdentity).First();

            sb.Append("update t\n");
            sb.Append("set\n");
            foreach (var attr in ifa.UpdateCheckAttributes)
            {
                sb.Append($"t.{attr.Name} = v.{attr.Name}".Indent("    "));
                if (attr != ifa.UpdateCheckAttributes.Last())
                {
                    sb.Append(",");
                }
                sb.Append("\n");
            }
            sb.Append($"from {ifa.FullName} t\n");
            sb.Append($"inner join {ifa.FullViewName} v\n");
            sb.Append($"on t.{idAttribute.Name} = v.{idAttribute.Name} \nand v.T_Modifikation = 'U'\n".Indent("    "));
            sb.Append("where exists (\n");

            sb.Append($"select t1.{idAttribute.Name}\nfrom {ifa.FullName} as t1\n".Indent("    "));
            sb.Append("where ".Indent("    "));
            foreach (var uk in ifa.UniqueKeyAttributes.Where(a => ifa.HistoryAttribute != a))
            {
                sb.Append($"t1.{uk.Name} = t.{uk.Name} and\n          ");
            }
            sb.Append($"t1.{ifa.HistoryAttribute.Name} = dbo.GetCurrentTimeForHistory()\n");

            sb.Append(")\n");
        }
        // TODO:für TableExistsModified brauch ich noch Testfälle
        public bool TableExistsModified(IBLInterface ifa)
        {
            if (!TableWithNameExists(ifa.Name))
            {
                return(false);
            }

            bool unmodified = true;

            foreach (var attr in ifa.Attributes)
            {
                if (!ColumnExists(ifa.Name, attr.Name))
                {
                    unmodified &= false;
                }
                if (!ColumnHasCorrectType(attr))
                {
                    unmodified &= false;
                }
                if (!ConstraintExists(ifa.Name, $"{ifa.Name}_UK", ifa.UniqueKeyAttributes.Select(a => a.Name).ToList()))
                {
                    unmodified &= false;
                }
            }

            unmodified &= !HasRemovedColums(ifa);

            return(!unmodified);
        }
Пример #10
0
 private string GenerateRelations(IBLInterface ifa)
 {
     string code = "# Beziehungen \n";
     foreach(var r in ifa.Attributes.Where(a => a is RefBLAttribute).Select(a => (RefBLAttribute)a)) {
         code += $"{ifa.ShortName}:{r.Name} -- {r.ReferencedAttribute.ParentInterface.ShortName}:{r.ReferencedAttribute.Name}\n";
     }
     return code;
 }
Пример #11
0
        internal string GenerateFactTableDelete(IBLInterface ifa)
        {
            string code = $"-- Löschen der neu zu ladenden Inhalte von {ifa.FullName}\n";

            code += $"delete from {ifa.FullName} \n";
            code += GenerateFactRelevantTimeSelector(ifa);
            code += "\n";
            return(code);
        }
Пример #12
0
        ///
        /// Schließt den bisher aktuellen Dimensionssatz ab
        /// (Läuft i. d. R. wenn entweder noch kein abgeschlossener Satz
        ///  zum Unique-Key dieses Dimensionsobjekts existiert, oder der aktuellste
        ///  abgeschlossene Satz zu einem Zeitpunkt != GetCurrentTimeForHistory
        ///  abgeschlossen wurde. Dieser Zusammenhang wird ausschließlich durch
        ///  vorheriges Ausführen von GenerateInTimeUpdateForDimTableWithHistory sichergestellt.)
        ///
        private void GeneratePastTimeUpdateForDimTableWithHistory(IBLInterface ifa, StringBuilder sb)
        {
            var idAttribute = ifa.Attributes.Where(a => a.IsIdentity).First();

            sb.Append($"-- Update historized table: {ifa.FullName}\n");
            sb.Append("update t \nset t.T_Gueltig_Bis_Dat = dbo.GetCurrentTimeForHistory()\n");
            sb.Append($"from {ifa.FullName} t\n");
            sb.Append($"inner join {ifa.FullViewName} v\n");
            sb.Append($"on t.{idAttribute.Name} = v.{idAttribute.Name} \nand v.T_Modifikation = 'U'\n\n".Indent("    "));
        }
Пример #13
0
        private string GenerateAttribute(IBLAttribute attr, IBLInterface ifa)
        {
            string code = $"{attr.Name} {attr.GetSqlDataTypeDefinition()}";

            if (ifa.Attributes.Last() != attr)
            {
                code += ", ";
            }
            return(code);
        }
Пример #14
0
 private string GenerateDimTableUpdate(IBLInterface ifa)
 {
     if (ifa.IsHistorized && ifa is DerivedBLInterface)
     {
         return(GenerateUpdatesForDimTableWithHistory(ifa));
     }
     else
     {
         return(GenerateDimTableUpdateNoHist(ifa));
     }
 }
Пример #15
0
        private string GenerateUpdatesForDimTableWithHistory(IBLInterface ifa)
        {
            StringBuilder sb = new StringBuilder();

            sb.Append("-- Aktualisierung innerhalb des aktuellen Zeitraums\n");
            GenerateInTimeUpdateForDimTableWithHistory(ifa, sb);
            sb.Append("\n");
            sb.Append("-- Aktualisierung außerhalb des aktuellen Zeitruams = Abschließen eines Dimensionssatzes\n");
            GeneratePastTimeUpdateForDimTableWithHistory(ifa, sb);
            sb.Append("\n");
            return(sb.ToString());
        }
Пример #16
0
        internal string GenerateBLTable(IBLInterface ifa)
        {
            // Create Table
            string code = $"create table {ifa.FullName} (\n";

            foreach (var attr in ifa.Attributes)
            {
                code += GenerateAttribute(attr, ifa).Indent("    ");
                code += "\n";
            }
            code += ");\n\n";
            return(code);
        }
        // TODO: Hier die vergleichende Analyse des BL-Inhalts lt. Datenbankschema (information_schema) und
        //       des gewünschten Zustands lt. CEUSDL (BLModel) durchführen...
        #region complex operations

        public bool InterfaceRenamed(IBLInterface ifa)
        {
            if (TableWithNameExists(ifa.Name, ifa.ParentModel.Config.BLDatabase))
            {
                return(false);
            }
            if (!TableWithNameExists(ifa.FormerName, ifa.ParentModel.Config.BLDatabase))
            {
                return(false);
            }

            return(true);
        }
Пример #18
0
        private DerivedBLInterface GetDerivedForDefault(IBLInterface ifa)
        {
            if (!(ifa is DefaultBLInterface))
            {
                throw new InvalidInterfaceTypeException("GetDerivedForDefault erwartet ein DefaultInterface!");
            }

            return(this.model.Interfaces
                   .Where(i => i is DerivedBLInterface)
                   .Select(i => (DerivedBLInterface)i)
                   .Where(i => i.DefaultInterface == ifa)
                   .FirstOrDefault());
        }
        // TODO: Hier die vergleichende Analyse des BL-Inhalts lt. Datenbankschema (information_schema) und
        //       des gewünschten Zustands lt. CEUSDL (BLModel) durchführen...
        #region complex operations

        public bool InterfaceRenamed(IBLInterface ifa)
        {
            if (TableWithNameExists(ifa.Name))
            {
                return(false);
            }
            if (!TableWithNameExists(ifa.FormerName))
            {
                return(false);
            }

            return(true);
        }
Пример #20
0
        private string GenerateInterface(IBLInterface ifa)
        {
            string code = $"{ifa.ShortName}[label=<\n";
            code += "<table border=\"0\" cellborder=\"1\" cellspacing=\"0\">\n";
            code += $"<tr><td><b>{ifa.Name}:{ifa.InterfaceType}</b></td></tr>\n";

            foreach(var attr in ifa.Attributes) {
                code += $"<tr><td port=\"{attr.Name}\">{attr.Name}:{attr.GetSqlDataTypeDefinition()}</td></tr>\n";
            }

            code += "</table>>];\n\n";
            return code;
        }
 ///
 /// Generiert ein neues T_Bemerkung-Attribut
 ///
 public static IBLAttribute GetNewTBemerkungAttribute(IBLInterface parentInterface)
 {
     return(new CustomBLAttribute()
     {
         ShortName = null,
         Name = "T_Bemerkung",
         FullName = $"{parentInterface.Name}.T_Bemerkung",
         DataType = CoreDataType.VARCHAR,
         Length = 100,
         ParentInterface = parentInterface,
         IsTechnicalAttribute = true,
         SortId = 101
     });
 }
 ///
 /// Generiert ein neues T_Ladelauf_NR-Attribut
 ///
 public static IBLAttribute GetNewTLadelaufNRAttribute(IBLInterface parentInterface)
 {
     return(new CustomBLAttribute()
     {
         ShortName = null,
         Name = "T_Ladelauf_NR",
         FullName = $"{parentInterface.Name}.T_Ladelauf_NR",
         DataType = CoreDataType.INT,
         IsNotNull = true,
         ParentInterface = parentInterface,
         IsTechnicalAttribute = true,
         SortId = 107
     });
 }
 ///
 /// Generiert ein neues T_Aend_Dat-Attribut
 ///
 public static IBLAttribute GetNewTAendDatAttribute(IBLInterface parentInterface)
 {
     return(new CustomBLAttribute()
     {
         ShortName = null,
         Name = "T_Aend_Dat",
         FullName = $"{parentInterface.Name}.T_Aend_Dat",
         DataType = CoreDataType.DATETIME,
         IsNotNull = true,
         ParentInterface = parentInterface,
         IsTechnicalAttribute = true,
         SortId = 105
     });
 }
 ///
 /// Generiert ein neues ID-Attribut
 ///
 public static IBLAttribute GetNewIDAttribute(IBLInterface parentInterface)
 {
     return(new CustomBLAttribute()
     {
         ShortName = "ID",
         Name = $"{parentInterface.ShortName}_ID",
         FullName = $"{parentInterface.Name}.{parentInterface.ShortName}_ID",
         DataType = CoreDataType.INT,
         IsPrimaryKey = true,
         IsIdentity = true,
         ParentInterface = parentInterface,
         IsTechnicalAttribute = false,
         SortId = 1
     });
 }
 ///
 /// Generiert ein neues T_Modifikation-Attribut
 ///
 public static IBLAttribute GetNewTModifikationAttribute(IBLInterface parentInterface)
 {
     return(new CustomBLAttribute()
     {
         ShortName = null,
         Name = "T_Modifikation",
         FullName = $"{parentInterface.Name}.T_Modifikation",
         DataType = CoreDataType.VARCHAR,
         Length = 10,
         IsNotNull = true,
         ParentInterface = parentInterface,
         IsTechnicalAttribute = true,
         SortId = 100
     });
 }
Пример #26
0
        private string GenerateDimTableUpdateNoHist(IBLInterface ifa)
        {
            var idAttribute = ifa.Attributes.Where(a => a.IsIdentity).First();

            StringBuilder sb = new StringBuilder();

            sb.Append($"-- Update for non historized table: {ifa.FullName}\n");
            sb.Append($"update {ifa.FullName} t\ninner join {ifa.FullViewName} v\n");
            sb.Append($"on t.{idAttribute.Name} = v.{idAttribute.Name}\n    and v.T_Modifikation = 'U'\nset ");
            foreach (var attr in ifa.UpdateCheckAttributes)
            {
                sb.Append($"t.{attr.Name} = v.{attr.Name},\n".Indent("    "));
            }
            sb.Append("t.T_Modifikation = 'U',\nt.T_Aend_Dat = now(),\nt.T_Benutzer = CURRENT_USER();\n\n".Indent("    "));
            return(sb.ToString());
        }
 ///
 /// Generiert ein neues Mandant-Attribut
 ///
 public static IBLAttribute GetNewMandantAttribute(IBLInterface parentInterface)
 {
     return(new CustomBLAttribute()
     {
         ShortName = null,
         Name = "Mandant_KNZ",
         FullName = $"{parentInterface?.Name}.Mandant_KNZ",
         DataType = CoreDataType.VARCHAR,
         Length = 10,
         IsNotNull = true,
         IsPartOfUniqueKey = true,
         ParentInterface = parentInterface,
         IsTechnicalAttribute = false,
         SortId = 0
     });
 }
 // Prüft, ob in der Datenbank noch Spalten vorhanden sind, die im ceusdl-Code
 // schon entfernt wurden.
 private bool HasRemovedColums(IBLInterface ifa)
 {
     if (TableWithNameExists(ifa.Name))
     {
         var dbCols  = GetColumnNamesFromDb(ifa.Name);
         var cdlCols = ifa.Attributes.Select(a => a.Name).ToList <string>();
         foreach (var dbcol in dbCols)
         {
             if (!cdlCols.Contains(dbcol))
             {
                 return(true);
             }
         }
     }
     return(false);
 }
        private string GenerateUnbekannt(IBLInterface ifa)
        {
            string code = $"";

            code += $"insert into {ifa.FullName} ";
            string attributeList = "";
            string valuesList    = "";

            foreach (var attr in ifa.Attributes)
            {
                attributeList += attr.Name;
                if (attr.IsIdentity)
                {
                    valuesList += "-1";
                }
                else if (attr.IsPartOfUniqueKey || attr is RefBLAttribute)    // KNZ und ggf. Mandant_KNZ
                {
                    valuesList += "'-1'";
                }
                else if (attr.DataType == CoreDataType.VARCHAR)    // Alle anderen textuellen Felder
                {
                    valuesList += $"'{"UNBEKANNT".Shorten(attr.Length)}'";
                }
                else if (attr.DataType == CoreDataType.DATE || attr.DataType == CoreDataType.DATETIME)    // Datumsfelder auf aktuelles Datum
                {
                    valuesList += "NOW()";
                }
                else if (attr.Name == "T_Ladelauf_NR")    // Ladelauf 0
                {
                    valuesList += "0";
                }
                else     // Ansonsten versuchen wir es mal mit NULL ;-) evtl geht das aber nicht immer?
                {
                    valuesList += "NULL";
                }
                if (attr != ifa.Attributes.Last())
                {
                    attributeList += ",\n";
                    valuesList    += ",\n";
                }
            }
            code += $"(\n{attributeList.Indent(1)}\n) values (\n{valuesList.Indent(1)}\n);\n";
            code += $"\n";
            return(code);
        }
Пример #30
0
        ///
        /// Wichtig: nur in BT zur Abbildung der History-Beziehung nutzen!
        ///
        internal RefBTAttribute(BaseBLAttribute blAttribute, IBLInterface blIfa, BTInterface ifa)
        {
            this.blAttribute         = blAttribute;
            this.refBLAttribute      = null;
            this.otherBlAttribute    = blAttribute;
            this.ParentInterface     = ifa;
            this.IsIdentity          = otherBlAttribute.IsIdentity;
            this.IsPartOfUniqueKey   = otherBlAttribute.IsPartOfUniqueKey;
            this.HasToUseVerionTable = false; // TODO: Das ist noch nicht sicher !

            var blModel = blAttribute.ParentInterface.ParentModel;

            this.ReferencedBLInterface = blIfa;
            this.ReferencedBLAttribute = blIfa.Attributes.Single(a => a.IsPartOfUniqueKey && (a is BaseBLAttribute));

            this.IdAttribute  = new IdSubAttribute(this);
            this.KnzAttribute = new KnzSubAttribute(this);
        }