/// /// 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)); } }
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)); } }
/// /// 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); }
/// /// 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); }
/// /// 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); }
/// /// 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 }); }
/// /// 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); }
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; }
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); }
/// /// 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(" ")); }
private string GenerateAttribute(IBLAttribute attr, IBLInterface ifa) { string code = $"{attr.Name} {attr.GetSqlDataTypeDefinition()}"; if (ifa.Attributes.Last() != attr) { code += ", "; } return(code); }
private string GenerateDimTableUpdate(IBLInterface ifa) { if (ifa.IsHistorized && ifa is DerivedBLInterface) { return(GenerateUpdatesForDimTableWithHistory(ifa)); } else { return(GenerateDimTableUpdateNoHist(ifa)); } }
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()); }
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); }
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); }
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 }); }
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); }
/// /// 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); }