public void DoChangeValueTypeProperty_To_Nullable(ObjectClass objClass, ValueTypeProperty prop, string prefix) { var savedProp = savedSchema.FindPersistenceObject<ValueTypeProperty>(prop.ExportGuid); if (!PreMigration(PropertyMigrationEventType.ChangeToNullable, savedProp, prop)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); db.AlterColumn(tblName, colName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), prop.IsNullable(), null); PostMigration(PropertyMigrationEventType.ChangeToNullable, savedProp, prop); }
public void DoNewValueTypePropertyList(ObjectClass objClass, ValueTypeProperty prop) { if (!PreMigration(PropertyMigrationEventType.Add, null, prop)) return; Log.InfoFormat("New ValueType Property List: {0}", prop.Name); CheckValueTypePropertyHasWarnings(prop); var tblName = db.GetTableName(prop.Module.SchemaName, prop.GetCollectionEntryTable()); string fkName = Construct.ForeignKeyColumnName(prop); string valPropName = prop.Name; string valPropIndexName = prop.Name + "Index"; string assocName = prop.GetAssociationName(); bool hasPersistentOrder = prop.HasPersistentOrder; db.CreateTable(tblName, true); db.CreateColumn(tblName, fkName, System.Data.DbType.Int32, 0, 0, false); db.CreateColumn(tblName, valPropName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), false, SchemaManager.GetDefaultConstraint(prop)); if (hasPersistentOrder) { db.CreateColumn(tblName, valPropIndexName, System.Data.DbType.Int32, 0, 0, false); } db.CreateFKConstraint(tblName, objClass.GetTableRef(db), fkName, assocName, true); db.CreateIndex(tblName, Construct.IndexName(tblName.Name, fkName), false, false, fkName); PostMigration(PropertyMigrationEventType.Add, null, prop); }
private void CheckExtraColumns(ObjectClass objClass) { if (objClass.GetTableMapping() == TableMapping.TPH && objClass.BaseObjectClass != null) return; // Check only base TPH classes Log.Debug("Extra Columns: "); List<string> columns = new List<string>(); List<ObjectClass> classes = new List<ObjectClass>(new[] { objClass }); if (objClass.GetTableMapping() == TableMapping.TPH) objClass.CollectChildClasses(classes, true); foreach (var cls in classes) { GetExistingColumnNames(cls, cls.Properties, String.Empty, columns); GetRelationColumnNames(cls, columns); } foreach (string propName in db.GetTableColumnNames(objClass.GetTableRef(db))) { if (propName == "ID" || propName == TableMapper.DiscriminatorColumnName) continue; if (!columns.Contains(propName)) { Log.WarnFormat("Column '[{0}].[{1}].[{2}]' found in database but no Property was defined", objClass.Module.IfNotNull(o => o.SchemaName), objClass.TableName, propName); } } }
private void CheckTableSecurityRules(ObjectClass objClass) { if (objClass.NeedsRightsTable()) { var tblName = objClass.GetTableRef(db); var tblRightsName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesTableName(objClass)); var rightsViewUnmaterializedName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(objClass)); var refreshRightsOnProcedureName = db.GetProcedureName(objClass.Module.SchemaName, Construct.SecurityRulesRefreshRightsOnProcedureName(objClass)); if (!db.CheckTableExists(tblRightsName)) { Log.WarnFormat("Security Rules Table '{0}' is missing", tblRightsName); if (repair) { Case.DoNewObjectClassACL(objClass); } } else { if (!db.CheckViewExists(rightsViewUnmaterializedName)) { Log.WarnFormat("Security Rules unmaterialized View '{0}' is missing", rightsViewUnmaterializedName); if (repair) { Case.DoCreateRightsViewUnmaterialized(objClass); } } if (!db.CheckProcedureExists(refreshRightsOnProcedureName)) { Log.WarnFormat("Security Rules Refresh Procedure '{0}' is missing", refreshRightsOnProcedureName); if (repair) { db.CreateRefreshRightsOnProcedure(refreshRightsOnProcedureName, rightsViewUnmaterializedName, tblName, tblRightsName); } } } } }
public void DoRenameObjectClassTable(ObjectClass objClass) { var savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); if (!PreMigration(ClassMigrationEventType.RenameTable, savedObjClass, objClass)) return; var tbl = objClass.GetTableRef(db); var saveTbl = savedObjClass.GetTableRef(db); Log.InfoFormat("Renaming table from '{0}' to '{1}'", saveTbl, tbl); var mapping = objClass.GetTableMapping(); if (mapping == TableMapping.TPT || (mapping == TableMapping.TPH && objClass.BaseObjectClass == null)) { db.RenameTable(saveTbl, tbl); } else if (mapping == TableMapping.TPH && objClass.BaseObjectClass != null) { foreach (var prop in objClass.Properties.OfType<ValueTypeProperty>().Where(p => !p.IsList)) { DoRenameValueTypePropertyName(objClass, prop, string.Empty); } // FK names will be changed in DoChangeRelationName case } if (mapping == TableMapping.TPH) { db.RenameDiscriminatorValue(tbl, Construct.DiscriminatorValue(savedObjClass), Construct.DiscriminatorValue(objClass)); } PostMigration(ClassMigrationEventType.RenameTable, savedObjClass, objClass); }
public void DoChangeDefaultValue(ObjectClass objClass, ValueTypeProperty prop, string prefix) { var savedProp = savedSchema.FindPersistenceObject<Property>(prop.ExportGuid); if (!PreMigration(PropertyMigrationEventType.ChangeDefaultValueDefinition, savedProp, prop)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); // Use current nullable definition. // Another case is responsible to change that. var currentIsNullable = db.GetIsColumnNullable(tblName, colName); db.AlterColumn(tblName, colName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), currentIsNullable, SchemaManager.GetDefaultConstraint(prop)); PostMigration(PropertyMigrationEventType.ChangeDefaultValueDefinition, savedProp, prop); }
public void DoDeleteValueTypeProperty(ObjectClass objClass, ValueTypeProperty savedProp, string prefix) { if (!PreMigration(PropertyMigrationEventType.Delete, savedProp, null)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(savedProp, prefix); var checkConstraintName = Construct.CheckConstraintName(tblName.Name, colName); Log.InfoFormat("Drop Column: {0}.{1}", tblName, colName); if (db.CheckCheckConstraintExists(tblName, checkConstraintName)) db.DropCheckConstraint(tblName, checkConstraintName); if (db.CheckColumnExists(tblName, colName)) db.DropColumn(tblName, colName); PostMigration(PropertyMigrationEventType.Delete, savedProp, null); }
public void DoRemoveObjectClassInheritance(ObjectClass objClass) { var savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); if (!PreMigration(ClassMigrationEventType.ChangeBase, savedObjClass, objClass)) return; string assocName = Construct.InheritanceAssociationName(savedObjClass.BaseObjectClass, savedObjClass); var tblName = objClass.GetTableRef(db); Log.InfoFormat("Remove ObjectClass Inheritance: {0} -> {1}: {2}", savedObjClass.Name, savedObjClass.BaseObjectClass.Name, assocName); if (db.CheckFKConstraintExists(tblName, assocName)) db.DropFKConstraint(tblName, assocName); PostMigration(ClassMigrationEventType.ChangeBase, savedObjClass, objClass); }
public void DoDeleteObjectClass(ObjectClass savedObjClass) { if (!PreMigration(ClassMigrationEventType.Delete, savedObjClass, null)) return; if (savedObjClass.NeedsRightsTable()) { DoDeleteObjectClassSecurityRules(savedObjClass); } foreach (var lstPop in savedObjClass.Properties.OfType<ValueTypeProperty>().Where(p => p.IsList)) { DoDeleteValueTypePropertyList(savedObjClass, lstPop, string.Empty); } foreach (var lstPop in savedObjClass.Properties.OfType<CompoundObjectProperty>().Where(p => p.IsList)) { DoDeleteCompoundObjectPropertyList(savedObjClass, lstPop, string.Empty); } var mapping = savedObjClass.GetTableMapping(); if (mapping == TableMapping.TPT) { var tbl = savedObjClass.GetTableRef(db); Log.InfoFormat("Drop Table: {0}", tbl); if (db.CheckTableExists(tbl)) db.DropTable(tbl); } else if (mapping == TableMapping.TPH) { // TODO: Do delete all columns } else { throw new NotSupportedException(string.Format("Mapping {0} is not supported", mapping)); } PostMigration(ClassMigrationEventType.Delete, savedObjClass, null); }
public void DoDeleteObjectClassSecurityRules(ObjectClass objClass) { var tblName = objClass.GetTableRef(db); var tblRightsName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesTableName(objClass)); var rightsViewUnmaterializedName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(objClass)); var refreshRightsOnProcedureName = Construct.SecurityRulesRefreshRightsOnProcedureName(objClass); var updateRightsTriggerName = new TriggerRef(tblName, Construct.SecurityRulesUpdateRightsTriggerName(objClass)); Log.InfoFormat("Delete ObjectClass Security Rules: {0}", objClass.Name); if (db.CheckTriggerExists(updateRightsTriggerName)) db.DropTrigger(updateRightsTriggerName); if (db.CheckProcedureExists(db.GetProcedureName(objClass.Module.SchemaName, refreshRightsOnProcedureName))) db.DropProcedure(db.GetProcedureName(objClass.Module.SchemaName, refreshRightsOnProcedureName)); if (db.CheckViewExists(rightsViewUnmaterializedName)) db.DropView(rightsViewUnmaterializedName); if (db.CheckTableExists(tblRightsName)) db.DropTable(tblRightsName); }
public void DoDeleteCompoundObjectProperty(ObjectClass objClass, CompoundObjectProperty savedCProp, string prefix) { if (!PreMigration(PropertyMigrationEventType.Delete, savedCProp, null)) return; Log.InfoFormat("deleting CompoundObject Property: '{0}'", savedCProp.Name); var tblName = objClass.GetTableRef(db); string baseColName = Construct.ColumnName(savedCProp, prefix); foreach (var valProp in savedCProp.CompoundObjectDefinition.Properties.OfType<ValueTypeProperty>()) { var colName = Construct.ColumnName(valProp, baseColName); Log.InfoFormat(" deleting ValueType Property: '{0}' ('{1}')", valProp.Name, colName); db.DropColumn(tblName, colName); } // TODO: Add nested CompoundObjectProperty PostMigration(PropertyMigrationEventType.Delete, savedCProp, null); }
public void DoCreateRightsViewUnmaterialized(ObjectClass objClass) { var tblName = objClass.GetTableRef(db); var tblRightsName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesTableName(objClass)); var rightsViewUnmaterializedName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(objClass)); if (objClass.AccessControlList.Count == 0) { Log.ErrorFormat("Unable to create RightsViewUnmaterialized: ObjectClass '{0}' has an empty AccessControlList", objClass.Name); db.CreateEmptyRightsViewUnmaterialized(rightsViewUnmaterializedName); return; } List<ACL> viewAcls = new List<ACL>(); foreach (var ac in objClass.AccessControlList.OfType<RoleMembership>()) { if (ac.Relations.Count == 0) { Log.ErrorFormat("Unable to create RightsViewUnmaterialized: RoleMembership '{0}' has no relations", ac.Description); db.CreateEmptyRightsViewUnmaterialized(rightsViewUnmaterializedName); return; } var viewAcl = new ACL(); viewAcls.Add(viewAcl); viewAcl.Right = (Zetbox.API.AccessRights)ac.Rights; try { viewAcl.Relations.AddRange(SchemaManager.CreateJoinList(db, objClass, ac.Relations)); } catch (SchemaManager.JoinListException ex) { Log.ErrorFormat(ex.Message); db.CreateEmptyRightsViewUnmaterialized(rightsViewUnmaterializedName); return; } } db.CreateRightsViewUnmaterialized(rightsViewUnmaterializedName, tblName, tblRightsName, viewAcls); }
public void DoCreateOrReplaceUpdateRightsTrigger(ObjectClass objClass) { var tblName = objClass.GetTableRef(db); var updateRightsTriggerName = new TriggerRef(tblName, Construct.SecurityRulesUpdateRightsTriggerName(objClass)); if (db.CheckTriggerExists(updateRightsTriggerName)) db.DropTrigger(updateRightsTriggerName); var tblList = new List<RightsTrigger>(); tblList.Add(new RightsTrigger() { TblName = objClass.GetTableRef(db), TblNameRights = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesTableName(objClass)), ViewUnmaterializedName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(objClass)) }); // Get all ObjectClasses that depends on current object class var list = schema.GetQuery<ObjectClass>() .Where(o => o.AccessControlList.OfType<RoleMembership>() .Where(rm => rm.Relations .Where(r => r.A.Type == objClass || r.B.Type == objClass).Count() > 0).Count() > 0) .Distinct().ToList().Where(o => o.NeedsRightsTable() && o != objClass); var identity = (ObjectClass)NamedObjects.Base.Classes.Zetbox.App.Base.Identity.Find(objClass.Context); foreach (var dep in list) { Log.DebugFormat(" Additional update Table: {0}", dep.TableName); foreach (var ac in dep.AccessControlList.OfType<RoleMembership>()) { var rel = ac.Relations.FirstOrDefault(r => r.A.Type == objClass || r.B.Type == objClass); if (rel != null) { var rt = new RightsTrigger() { TblName = dep.GetTableRef(db), TblNameRights = db.GetTableName(dep.Module.SchemaName, Construct.SecurityRulesTableName(dep)), ViewUnmaterializedName = db.GetTableName(dep.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(dep)), }; try { rt.ObjectRelations.AddRange(SchemaManager.CreateJoinList(db, dep, ac.Relations.TakeWhileInclusive(r => r != rel))); rt.IdentityRelations.AddRange(SchemaManager.CreateJoinList(db, identity, ac.Relations.Reverse().TakeWhile(r => r != rel))); } catch (Zetbox.Server.SchemaManagement.SchemaManager.JoinListException ex) { Log.Warn("Unable to create UpdateRightsTrigger on " + objClass, ex); return; } tblList.Add(rt); } } } // do not check fk_ChangedBy since it always changes, even when only recalculations were done. // ACLs MUST never use ChangedBy information var fkCols = objClass.GetRelationEndsWithLocalStorage() .Where(r => !(r.Type.ImplementsIChangedBy() && r.Navigator != null && r.Navigator.Name == "ChangedBy")) .Select(r => Construct.ForeignKeyColumnName(r.GetParent().GetOtherEnd(r))) .ToList(); db.CreateUpdateRightsTrigger(updateRightsTriggerName, tblName, tblList, fkCols); }
public void DoNewValueTypePropertyNotNullable(ObjectClass objClass, ValueTypeProperty prop, string prefix) { if (!PreMigration(PropertyMigrationEventType.Add, null, prop)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); var dbType = prop.GetDbType(); var size = prop.GetSize(); var scale = prop.GetScale(); var def = SchemaManager.GetDefaultConstraint(prop); var isSimplyCheckable = objClass.GetTableMapping() == TableMapping.TPT || objClass.BaseObjectClass == null; bool updateDone = false; // classes that do have this property var classes = objClass.AndChildren(c => c.SubClasses).Select(cls => Construct.DiscriminatorValue(cls)).ToList(); Log.InfoFormat("New not nullable ValueType Property: [{0}.{1}] (col:{2})", prop.ObjectClass.Name, prop.Name, colName); CheckValueTypePropertyHasWarnings(prop); if (db.CheckTableContainsData(tblName, isSimplyCheckable ? null : classes)) { db.CreateColumn(tblName, colName, dbType, size, scale, true, isSimplyCheckable ? def : null); updateDone = WriteDefaultValue(tblName, colName, def, isSimplyCheckable ? null : classes); } else { db.CreateColumn(tblName, colName, dbType, size, scale, !isSimplyCheckable, isSimplyCheckable ? def : null); updateDone = true; } if (updateDone && isSimplyCheckable) { db.AlterColumn(tblName, colName, dbType, size, scale, false, def); } else if (updateDone && !isSimplyCheckable) { CreateTPHNotNullCheckConstraint(tblName, colName, objClass); } else if (!updateDone && isSimplyCheckable) { Log.ErrorFormat("unable to set ValueType Property '{0}' to NOT NULL when table '{1}' contains data: No supported default constraint found", colName, tblName); } else if (!updateDone && !isSimplyCheckable) { Log.ErrorFormat("unable to create CHECK constraint on ValueType Property '{0}' when table '{1}' contains data: No supported default constraint found", colName, tblName); } PostMigration(PropertyMigrationEventType.Add, null, prop); }
public void DoMoveValueTypeProperty(ObjectClass objClass, ValueTypeProperty prop, string prefix) { var savedProp = savedSchema.FindPersistenceObject<ValueTypeProperty>(prop.ExportGuid); if (!PreMigration(PropertyMigrationEventType.Move, savedProp, prop)) return; // Reflected changed hierarchie var currentOriginObjClass = schema.FindPersistenceObject<ObjectClass>(savedProp.ObjectClass.ExportGuid); var movedUp = IsParentOf(objClass, currentOriginObjClass); var movedDown = IsParentOf(currentOriginObjClass, objClass); var tblName = objClass.GetTableRef(db); var srcTblName = ((ObjectClass)savedProp.ObjectClass).GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); var srcColName = Construct.ColumnName(savedProp, prefix); // TODO: What if prefix has changed var dbType = prop.GetDbType(); var size = prop.GetSize(); var scale = prop.GetScale(); var def = SchemaManager.GetDefaultConstraint(prop); if (movedUp) { Log.InfoFormat("Moving property '{0}' from '{1}' up to '{2}'", prop.Name, savedProp.ObjectClass.Name, objClass.Name); db.CreateColumn(tblName, colName, dbType, size, scale, true, def); db.CopyColumnData(srcTblName, srcColName, tblName, colName); if (!prop.IsNullable()) { if (db.CheckColumnContainsNulls(tblName, colName)) { Log.ErrorFormat("column '{0}.{1}' contains NULL values, cannot set NOT NULLABLE", tblName, colName); } else { db.AlterColumn(tblName, colName, dbType, size, scale, prop.IsNullable(), def); } } if (db.CheckColumnExists(srcTblName, srcColName)) db.DropColumn(srcTblName, srcColName); } else if (movedDown) { Log.InfoFormat("Moving property '{0}' from '{1}' down to '{2}' (dataloss possible)", prop.Name, savedProp.ObjectClass.Name, objClass.Name); db.CreateColumn(tblName, colName, dbType, size, scale, true, def); db.CopyColumnData(srcTblName, srcColName, tblName, colName); if (!prop.IsNullable()) { db.AlterColumn(tblName, colName, dbType, size, scale, prop.IsNullable(), def); } if (db.CheckColumnExists(srcTblName, srcColName)) db.DropColumn(srcTblName, srcColName); } else { Log.ErrorFormat("Moving property '{2}' from '{0}' to '{1}' is not supported. ObjectClasses are not in the same hierarchy. Will only create destination column.", savedProp.ObjectClass.Name, prop.ObjectClass.Name, prop.Name); db.CreateColumn(tblName, colName, dbType, size, scale, true, def); } PostMigration(PropertyMigrationEventType.Move, savedProp, prop); }
public void DoNewValueTypePropertyNullable(ObjectClass objClass, ValueTypeProperty prop, string prefix) { if (!PreMigration(PropertyMigrationEventType.Add, null, prop)) return; string colName = Construct.ColumnName(prop, prefix); Log.InfoFormat("New nullable ValueType Property: '{0}' ('{1}')", prop.Name, colName); CheckValueTypePropertyHasWarnings(prop); CreateValueTypePropertyNullable(objClass.GetTableRef(db), prop, colName, true); PostMigration(PropertyMigrationEventType.Add, null, prop); }
public void DoNewCompoundObjectProperty(ObjectClass objClass, CompoundObjectProperty cprop, string prefix) { if (!PreMigration(PropertyMigrationEventType.Add, null, cprop)) return; var tblName = objClass.GetTableRef(db); CreateCompoundObjectProperty(tblName, cprop, prefix, true); PostMigration(PropertyMigrationEventType.Add, null, cprop); }
public void DoRenameObjectClassACL(ObjectClass objClass) { ObjectClass savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); var tblName = objClass.GetTableRef(db); var savedTblName = savedObjClass.GetTableRef(db); var tblRightsName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesTableName(objClass)); var savedTblRightsName = db.GetTableName(savedObjClass.Module.SchemaName, Construct.SecurityRulesTableName(savedObjClass)); var rightsViewUnmaterializedName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(objClass)); var savedRightsViewUnmaterializedName = db.GetTableName(savedObjClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(savedObjClass)); var refreshRightsOnProcedureName = db.GetProcedureName(objClass.Module.SchemaName, Construct.SecurityRulesRefreshRightsOnProcedureName(objClass)); var savedRefreshRightsOnProcedureName = db.GetProcedureName(savedObjClass.Module.SchemaName, Construct.SecurityRulesRefreshRightsOnProcedureName(savedObjClass)); var savedUpdateRightsTriggerName = new TriggerRef(savedTblName, Construct.SecurityRulesUpdateRightsTriggerName(savedObjClass)); Log.InfoFormat("Renaming ObjectClass Security Rules: {0}", objClass.Name); if (db.CheckTriggerExists(savedUpdateRightsTriggerName)) db.DropTrigger(savedUpdateRightsTriggerName); if (db.CheckProcedureExists(savedRefreshRightsOnProcedureName)) db.DropProcedure(savedRefreshRightsOnProcedureName); if (db.CheckViewExists(savedRightsViewUnmaterializedName)) db.DropView(savedRightsViewUnmaterializedName); db.RenameTable(savedTblRightsName, tblRightsName); db.RenameIndex(tblRightsName, Construct.SecurityRulesIndexName(savedObjClass), Construct.SecurityRulesIndexName(objClass)); db.RenameFKConstraint(tblRightsName, Construct.SecurityRulesFKName(savedObjClass), objClass.GetTableRef(db), "ID", Construct.SecurityRulesFKName(objClass), true); DoCreateOrReplaceUpdateRightsTrigger(objClass); DoCreateRightsViewUnmaterialized(objClass); db.CreateRefreshRightsOnProcedure(refreshRightsOnProcedureName, rightsViewUnmaterializedName, tblName, tblRightsName); }
public void DoNewCompoundObjectPropertyList(ObjectClass objClass, CompoundObjectProperty cprop) { if (!PreMigration(PropertyMigrationEventType.Add, null, cprop)) return; Log.InfoFormat("New CompoundObject Property List: {0}", cprop.Name); var tblName = db.GetTableName(cprop.Module.SchemaName, cprop.GetCollectionEntryTable()); string fkName = Construct.ForeignKeyColumnName(cprop); // TODO: Support nested CompoundObject string valPropIndexName = cprop.Name + "Index"; string assocName = cprop.GetAssociationName(); bool hasPersistentOrder = cprop.HasPersistentOrder; db.CreateTable(tblName, true); db.CreateColumn(tblName, fkName, System.Data.DbType.Int32, 0, 0, false); foreach (ValueTypeProperty p in cprop.CompoundObjectDefinition.Properties) { CheckValueTypePropertyHasWarnings(p); db.CreateColumn(tblName, Construct.ColumnName(p, cprop.Name), p.GetDbType(), p.GetSize(), p.GetScale(), true, null); } if (hasPersistentOrder) { db.CreateColumn(tblName, valPropIndexName, System.Data.DbType.Int32, 0, 0, false); } db.CreateFKConstraint(tblName, objClass.GetTableRef(db), fkName, assocName, true); db.CreateIndex(tblName, Construct.IndexName(tblName.Name, fkName), false, false, fkName); PostMigration(PropertyMigrationEventType.Add, null, cprop); }
public void DoRenameValueTypePropertyName(ObjectClass objClass, ValueTypeProperty prop, string prefix) { var savedProp = savedSchema.FindPersistenceObject<ValueTypeProperty>(prop.ExportGuid); if (!PreMigration(PropertyMigrationEventType.Rename, savedProp, prop)) return; var tblName = objClass.GetTableRef(db); var srcName = Construct.ColumnName(savedProp, prefix); var dstName = Construct.ColumnName(prop, prefix); if (srcName == dstName) return; Log.InfoFormat("Renaming property on '{0}' from '{1}' up to '{2}'", tblName, srcName, dstName); // TODO: What if prefix has changed db.RenameColumn(tblName, srcName, dstName); PostMigration(PropertyMigrationEventType.Rename, savedProp, prop); }
public void DoNewObjectClass(ObjectClass objClass) { if (!PreMigration(ClassMigrationEventType.Add, null, objClass)) return; TableMapping mapping = objClass.GetTableMapping(); if (mapping == TableMapping.TPT || (mapping == TableMapping.TPH && objClass.BaseObjectClass == null)) { var tblName = objClass.GetTableRef(db); Log.InfoFormat("New Table: {0}", tblName); if (!db.CheckTableExists(tblName)) { db.CreateTable(tblName, objClass.BaseObjectClass == null); if (mapping == TableMapping.TPH) { db.CreateColumn(tblName, TableMapper.DiscriminatorColumnName, System.Data.DbType.String, TableMapper.DiscriminatorColumnSize, 0, false); } } else { Log.ErrorFormat("Table {0} already exists", tblName); } } else { Log.DebugFormat("Skipping table for TPH child {0}", objClass.Name); } PostMigration(ClassMigrationEventType.Add, null, objClass); }
private void CheckColumns(ObjectClass objClass, ICollection<Property> properties, string prefix) { Log.Debug(" Columns: "); var tblName = objClass.GetTableRef(db); var mapping = objClass.GetTableMapping(); if (mapping == TableMapping.TPH && objClass.BaseObjectClass == null) { CheckColumn(tblName, TableMapper.DiscriminatorColumnName, System.Data.DbType.String, TableMapper.DiscriminatorColumnSize, 0, false, null); } foreach (ValueTypeProperty prop in properties.OfType<ValueTypeProperty>() .Where(p => !p.IsList) .OrderBy(p => p.Module.Namespace).ThenBy(p => p.Name)) { var colName = Construct.ColumnName(prop, prefix); Log.DebugFormat(" {0}", colName); var realIsNullable = prop.IsNullable(); if (realIsNullable == false) realIsNullable = mapping == TableMapping.TPH && objClass.BaseObjectClass != null; CheckColumn(tblName, colName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), realIsNullable, SchemaManager.GetDefaultConstraint(prop)); } foreach (CompoundObjectProperty sprop in properties.OfType<CompoundObjectProperty>().Where(p => !p.IsList)) { CheckColumns(objClass, sprop.CompoundObjectDefinition.Properties, Construct.ColumnName(sprop, prefix)); } }
public void DoNewObjectClassACL(ObjectClass objClass) { Log.InfoFormat("New ObjectClass Security Rules: {0}", objClass.Name); var tblRightsName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesTableName(objClass)); db.CreateTable(tblRightsName, false, false); db.CreateColumn(tblRightsName, "Identity", System.Data.DbType.Int32, 0, 0, false); db.CreateColumn(tblRightsName, "Right", System.Data.DbType.Int32, 0, 0, false); db.CreateIndex(tblRightsName, Construct.SecurityRulesIndexName(objClass), true, true, "ID", "Identity"); db.CreateFKConstraint(tblRightsName, objClass.GetTableRef(db), "ID", Construct.SecurityRulesFKName(objClass), true); var tblName = objClass.GetTableRef(db); var rightsViewUnmaterializedName = db.GetTableName(objClass.Module.SchemaName, Construct.SecurityRulesRightsViewUnmaterializedName(objClass)); var refreshRightsOnProcedureName = db.GetProcedureName(objClass.Module.SchemaName, Construct.SecurityRulesRefreshRightsOnProcedureName(objClass)); DoCreateOrReplaceUpdateRightsTrigger(objClass); DoCreateRightsViewUnmaterialized(objClass); db.CreateRefreshRightsOnProcedure(refreshRightsOnProcedureName, rightsViewUnmaterializedName, tblName, tblRightsName); db.ExecRefreshRightsOnProcedure(refreshRightsOnProcedureName); }
private void CheckIndexConstraints(ObjectClass objClass) { foreach (var uc in objClass.Constraints.OfType<IndexConstraint>()) { var isFulltextConstraint = uc is FullTextIndexConstraint; if (isFulltextConstraint) continue; var tblName = objClass.GetTableRef(db); var columns = Construct.GetUCColNames(uc); var idxName = Construct.IndexName(tblName.Name, columns); if (!db.CheckIndexExists(tblName, idxName)) { Log.WarnFormat("Index Constraint '{0}' is missing", idxName); if (repair) { Case.DoNewIndexConstraint(uc); } } } }
public void DoNewObjectClassInheritance(ObjectClass objClass) { var savedObjClass = savedSchema.FindPersistenceObject<ObjectClass>(objClass.ExportGuid); if (!PreMigration(ClassMigrationEventType.ChangeBase, savedObjClass, objClass)) return; var newBaseClass = objClass.BaseObjectClass; var assocName = Construct.InheritanceAssociationName(newBaseClass, objClass); var tblName = objClass.GetTableRef(db); Log.InfoFormat("New ObjectClass Inheritance: {0} -> {1}: {2}", objClass.Name, newBaseClass.Name, assocName); var movedUp = IsParentOf(newBaseClass, savedObjClass); if (!movedUp && db.CheckTableContainsData(tblName)) { Log.ErrorFormat("Table '{0}' contains data. Unable to add inheritance when the new basetable does not contain instances of the child class.", tblName); return; } db.CreateFKConstraint(tblName, newBaseClass.GetTableRef(db), "ID", assocName, false); PostMigration(ClassMigrationEventType.ChangeBase, savedObjClass, objClass); }
private void CheckValueTypeCollections(ObjectClass objClass) { Log.Debug("ValueType Collections: "); foreach (ValueTypeProperty prop in objClass.Properties.OfType<ValueTypeProperty>() .Where(p => p.IsList) .OrderBy(p => p.Module.Namespace).ThenBy(p => p.Name)) { var tblName = db.GetTableName(prop.Module.SchemaName, prop.GetCollectionEntryTable()); var fkName = Construct.ForeignKeyColumnName(prop); var valPropName = prop.Name; var valPropIndexName = prop.Name + "Index"; var assocName = prop.GetAssociationName(); var refTblName = objClass.GetTableRef(db); bool hasPersistentOrder = prop.HasPersistentOrder; if (db.CheckTableExists(tblName)) { Log.DebugFormat("{0}", prop.Name); CheckColumn(tblName, fkName, System.Data.DbType.Int32, 0, 0, false, null); CheckColumn(tblName, valPropName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), false, SchemaManager.GetDefaultConstraint(prop)); if (hasPersistentOrder) { CheckColumn(tblName, valPropIndexName, System.Data.DbType.Int32, 0, 0, true, null); } if (!hasPersistentOrder && db.CheckColumnExists(tblName, valPropIndexName)) { Log.WarnFormat("Index Column '{0}' exists but property is not indexed", valPropIndexName); } if (!db.CheckFKConstraintExists(tblName, assocName)) { Log.WarnFormat("FK Constraint is missing", prop.Name); if (repair) { db.CreateFKConstraint(tblName, refTblName, fkName, assocName, true); } } } else { Log.WarnFormat("Table '{0}' for Property '{1}' is missing", tblName, prop.Name); if (repair) { Case.DoNewValueTypePropertyList(objClass, prop); } } } }
public void DoChangeValueTypeProperty_To_NotNullable(ObjectClass objClass, ValueTypeProperty prop, string prefix) { var savedProp = savedSchema.FindPersistenceObject<ValueTypeProperty>(prop.ExportGuid); if (!PreMigration(PropertyMigrationEventType.ChangeToNotNullable, savedProp, prop)) return; var tblName = objClass.GetTableRef(db); var colName = Construct.ColumnName(prop, prefix); var def = SchemaManager.GetDefaultConstraint(prop); if (def == null && db.CheckColumnContainsNulls(tblName, colName)) { Log.ErrorFormat("column '{0}.{1}' contains NULL values and has no default contraint, cannot set NOT NULLABLE", tblName, colName); } else { if (def != null) { var isSimplyCheckable = objClass.GetTableMapping() == TableMapping.TPT || objClass.BaseObjectClass == null; var classes = objClass.AndChildren(c => c.SubClasses).Select(cls => Construct.DiscriminatorValue(cls)).ToList(); WriteDefaultValue(tblName, colName, def, isSimplyCheckable ? null : classes); } db.AlterColumn(tblName, colName, prop.GetDbType(), prop.GetSize(), prop.GetScale(), prop.IsNullable(), null /* don't change contraints */); } PostMigration(PropertyMigrationEventType.ChangeToNotNullable, savedProp, prop); }