private void DoGenerateCascadeDeletions(DatabaseInfo db, List <ChangeSetDeleteItem> res) { var table = db.FindTable(TargetTable); if (table == null) { return; } foreach (var fk in table.GetReferences()) { if (res.Any(x => x.TargetTable == fk.OwnerTable.FullName)) { // prevent cycling continue; } if (fk.OwnerTable == fk.RefTable) { // skip foreign keys referencing the same table continue; } var newItem = new ChangeSetDeleteItem { LinkedInfo = LinkedInfo, TargetTable = fk.OwnerTable.FullName, }; newItem.Conditions.AddRange(GetPrefixedConditions(Conditions, fk.ConstraintName)); res.Add(newItem); newItem.DoGenerateCascadeDeletions(db, res); } }
public void GetCommands(DmlfBatch res, DatabaseInfo db, IDialectDataAdapter dda, ICdlValueConvertor converter) { var cmd = new DmlfInsert(); cmd.InsertTarget = TargetTable; var table = db.FindTable(TargetTable); if (table == null) return; var autoinc = table.FindAutoIncrementColumn(); bool isAutoInc = autoinc != null && Values.Any(x => x.Column == autoinc.Name); GetValues(cmd.Columns, Values, table, dda, converter); if (isAutoInc) { res.AllowIdentityInsert(table.FullName, true); } res.Commands.Add(cmd); if (isAutoInc) { res.AllowIdentityInsert(table.FullName, false); } }
public bool IsUpdatingPk(DatabaseInfo db) { var table = db.FindTable(TargetTable); if (table == null) return false; if (table.PrimaryKey == null) return false; return Values.Any(x => table.PrimaryKey.Columns.Any(y => System.String.Compare(x.Column, y.RefColumnName, System.StringComparison.OrdinalIgnoreCase) == 0)); }
public void GetCommands(DmlfBatch res, DatabaseInfo db, IDialectDataAdapter dda, ICdlValueConvertor converter) { var cmd = new DmlfInsert(); cmd.InsertTarget = TargetTable; var table = db.FindTable(TargetTable); if (table == null) { return; } var autoinc = table.FindAutoIncrementColumn(); bool isAutoInc = autoinc != null && Values.Any(x => x.Column == autoinc.Name); GetValues(cmd.Columns, Values, table, dda, converter); if (isAutoInc) { res.AllowIdentityInsert(table.FullName, true); } res.Commands.Add(cmd); if (isAutoInc) { res.AllowIdentityInsert(table.FullName, false); } }
private void GenerateCascadeUpdates(DatabaseInfo db, List<ChangeSetUpdateItem> res) { if (!IsUpdatingPk(db)) return; var table = db.FindTable(TargetTable); if (table == null) return; foreach (var fk in table.GetReferences()) { var newItem = new ChangeSetUpdateItem { LinkedInfo = LinkedInfo, TargetTable = fk.OwnerTable.FullName, }; newItem.Conditions.AddRange(GetPrefixedConditions(Conditions, fk.ConstraintName)); res.Add(newItem); for (int i = 0; i < fk.Columns.Count; i++) { string pkcol = fk.RefColumns[i].RefColumnName; var val = Values.FirstOrDefault(x => x.Column == pkcol); if (val == null) continue; newItem.Values.Add(new ChangeSetValue { Column = fk.Columns[i].RefColumnName, Value = val.Value, }); } } }
public void GetDeleteCommands(DmlfBatch res, DatabaseInfo db, ChangeSetModel model) { var table = db.FindTable(TargetTable); if (table == null) { return; } if (IsDuplicatingIdentity(db, model)) { var del = new DmlfDelete(); del.DeleteTarget = new DmlfSource { TableOrView = table.FullName, Alias = "basetbl", }; del.SingleFrom = new DmlfFromItem { Source = del.DeleteTarget }; GetConditions(del, this, Conditions, db); res.Commands.Add(del); } }
public bool IsDuplicatingIdentity(DatabaseInfo db, ChangeSetModel model) { if (!UpdateReferences && !model.UpdateReferences) return false; if (!IsUpdatingPk(db)) return false; var table = db.FindTable(TargetTable); if (table == null) return false; var autoinc = table.FindAutoIncrementColumn(); return autoinc != null && Values.Any(x => x.Column == autoinc.Name); }
private DmlfSource DoAddOrFindRelation(DmlfSource baseSource, NameWithSchema baseTable, StructuredIdentifier relationJoined, StructuredIdentifier relationToJoin, DatabaseInfo db, DmlfJoinType joinType) { if (relationToJoin.IsEmpty) return baseSource; string relName = relationToJoin.First; string alias = String.Format("_REF{0}_{1}", relationJoined.NameItems.Select(x => "_" + x).CreateDelimitedText(""), relName); var source = FindSourceByAlias(alias); if (source == null) { var baseTableInfo = db.FindTable(baseTable); var fk = baseTableInfo.ForeignKeys.FirstOrDefault(x => System.String.Compare(x.ConstraintName, relName, StringComparison.OrdinalIgnoreCase) == 0); if (fk == null) { var column = baseTableInfo.FindColumn(relName); if (column != null) fk = column.GetForeignKeys().FirstOrDefault(x => x.Columns.Count == 1); } if (fk == null) return null; source = new DmlfSource { TableOrView = fk.RefTableFullName, Alias = alias, }; var relation = new DmlfRelation { Reference = source, JoinType = joinType, }; for (int i = 0; i < fk.Columns.Count; i++) { relation.Conditions.Add(new DmlfEqualCondition { LeftExpr = new DmlfColumnRefExpression { Column = new DmlfColumnRef { ColumnName = fk.Columns[0].RefColumnName, Source = baseSource, } }, RightExpr = new DmlfColumnRefExpression { Column = new DmlfColumnRef { ColumnName = fk.RefColumns[0].RefColumnName, Source = source, } }, }); Relations.Add(relation); } } if (relationToJoin.IsEmpty) return source; return DoAddOrFindRelation(source, source.TableOrView, relationJoined/relationToJoin.First, relationToJoin.WithoutFirst, db, joinType); }
/// <summary> /// Generates the cascade deletions. /// </summary> /// <param name="db">The db.</param> /// <returns></returns> public List <ChangeSetDeleteItem> GenerateCascadeDeletions(DatabaseInfo db) { var res = new List <ChangeSetDeleteItem>(); DoGenerateCascadeDeletions(db, res); var dct = new Dictionary <NameWithSchema, DeleteWrapper>(); var queue = new List <DeleteWrapper>(); foreach (var item in res) { DeleteWrapper wrap; if (!dct.ContainsKey(item.TargetTable)) { wrap = new DeleteWrapper(); dct[item.TargetTable] = wrap; wrap.Table = db.FindTable(item.TargetTable); wrap.Refs = wrap.Table.GetReferences().Select(x => x.OwnerTable.FullName).ToList(); wrap.Refs.RemoveAll(x => x == wrap.Table.FullName); queue.Add(wrap); } else { wrap = dct[item.TargetTable]; } wrap.Items.Add(item); } queue.Reverse(); var resWrappers = new List <DeleteWrapper>(); while (queue.Any()) { DeleteWrapper selected = null; foreach (var wrap in queue) { if (wrap.Refs.All(x => resWrappers.Any(y => y.Table.FullName == x))) { selected = wrap; break; } } if (selected == null) { // omit partial ordering, if order is not possible selected = queue.First(); } queue.Remove(selected); resWrappers.Add(selected); } return(resWrappers.SelectMany(x => x.Items).ToList()); }
/// <summary> /// Generates the cascade deletions. /// </summary> /// <param name="db">The db.</param> /// <returns></returns> public List<ChangeSetDeleteItem> GenerateCascadeDeletions(DatabaseInfo db) { var res = new List<ChangeSetDeleteItem>(); DoGenerateCascadeDeletions(db, res); var dct = new Dictionary<NameWithSchema, DeleteWrapper>(); var queue = new List<DeleteWrapper>(); foreach (var item in res) { DeleteWrapper wrap; if (!dct.ContainsKey(item.TargetTable)) { wrap = new DeleteWrapper(); dct[item.TargetTable] = wrap; wrap.Table = db.FindTable(item.TargetTable); wrap.Refs = wrap.Table.GetReferences().Select(x => x.OwnerTable.FullName).ToList(); wrap.Refs.RemoveAll(x => x == wrap.Table.FullName); queue.Add(wrap); } else { wrap = dct[item.TargetTable]; } wrap.Items.Add(item); } queue.Reverse(); var resWrappers = new List<DeleteWrapper>(); while (queue.Any()) { DeleteWrapper selected = null; foreach (var wrap in queue) { if (wrap.Refs.All(x => resWrappers.Any(y => y.Table.FullName == x))) { selected = wrap; break; } } if (selected == null) { // omit partial ordering, if order is not possible selected = queue.First(); } queue.Remove(selected); resWrappers.Add(selected); } return resWrappers.SelectMany(x => x.Items).ToList(); }
public void GetInsertCommands(DmlfBatch res, DatabaseInfo db, ChangeSetModel model, IDialectDataAdapter dda, ICdlValueConvertor converter) { var table = db.FindTable(TargetTable); if (table == null) { return; } if (IsDuplicatingIdentity(db, model)) { res.AllowIdentityInsert(table.FullName, true); var insert = new DmlfInsertSelect { TargetTable = table.FullName, }; insert.Select = new DmlfSelect(); insert.Select.SingleFrom = new DmlfFromItem { Source = new DmlfSource { TableOrView = table.FullName, Alias = "basetbl", } }; GetConditions(insert.Select, this, Conditions, db); foreach (var col in table.Columns) { var valcol = Values.FirstOrDefault(x => x.Column == col.Name); insert.TargetColumns.Add(col.Name); if (valcol == null) { insert.Select.Columns.Add(DmlfResultField.BuildFromColumn(col.Name, insert.Select.SingleFrom.Source)); } else { insert.Select.Columns.Add(new DmlfResultField { Expr = new DmlfLiteralExpression { Value = valcol.Value, } }); } } res.Commands.Add(insert); res.AllowIdentityInsert(table.FullName, false); } }
public ColumnInfo FindSourceColumn(DatabaseInfo db) { if (Source == null || Source.TableOrView == null) { return(null); } var table = db.FindTable(Source.TableOrView); if (table == null) { return(null); } return(table.FindColumn(ColumnName)); }
public bool IsUpdatingPk(DatabaseInfo db) { var table = db.FindTable(TargetTable); if (table == null) { return(false); } if (table.PrimaryKey == null) { return(false); } return(Values.Any(x => table.PrimaryKey.Columns.Any(y => System.String.Compare(x.Column, y.RefColumnName, System.StringComparison.OrdinalIgnoreCase) == 0))); }
public bool IsDuplicatingIdentity(DatabaseInfo db, ChangeSetModel model) { if (!UpdateReferences && !model.UpdateReferences) { return(false); } if (!IsUpdatingPk(db)) { return(false); } var table = db.FindTable(TargetTable); if (table == null) { return(false); } var autoinc = table.FindAutoIncrementColumn(); return(autoinc != null && Values.Any(x => x.Column == autoinc.Name)); }
private void DoGenerateCascadeDeletions(DatabaseInfo db, List<ChangeSetDeleteItem> res) { var table = db.FindTable(TargetTable); if (table == null) return; foreach (var fk in table.GetReferences()) { if (res.Any(x => x.TargetTable == fk.OwnerTable.FullName)) { // prevent cycling continue; } var newItem = new ChangeSetDeleteItem { LinkedInfo = LinkedInfo, TargetTable = fk.OwnerTable.FullName, }; newItem.Conditions.AddRange(GetPrefixedConditions(Conditions, fk.ConstraintName)); res.Add(newItem); newItem.DoGenerateCascadeDeletions(db, res); } }
private void GenerateCascadeUpdates(DatabaseInfo db, List <ChangeSetUpdateItem> res) { if (!IsUpdatingPk(db)) { return; } var table = db.FindTable(TargetTable); if (table == null) { return; } foreach (var fk in table.GetReferences()) { var newItem = new ChangeSetUpdateItem { LinkedInfo = LinkedInfo, TargetTable = fk.OwnerTable.FullName, }; newItem.Conditions.AddRange(GetPrefixedConditions(Conditions, fk.ConstraintName)); res.Add(newItem); for (int i = 0; i < fk.Columns.Count; i++) { string pkcol = fk.RefColumns[i].RefColumnName; var val = Values.FirstOrDefault(x => x.Column == pkcol); if (val == null) { continue; } newItem.Values.Add(new ChangeSetValue { Column = fk.Columns[i].RefColumnName, Value = val.Value, }); } } }
private void FillWorkingSets() { if (_options.TableOptions.AllTables) { _tables.AddRange(_database.Tables); } else { _tables.AddRange(_options.TableOptions.TableFilter.Select(x => _database.FindTable(x)).Where(x => x != null)); } if (_options.ViewOptions.AllObjects) { _views.AddRange(_database.Views); } else { _views.AddRange(_options.ViewOptions.ObjectFilter.Select(x => _database.FindView(x)).Where(x => x != null)); } if (_options.StoredProcedureOptions.AllObjects) { _storedProcedures.AddRange(_database.StoredProcedures); } else { _storedProcedures.AddRange(_options.StoredProcedureOptions.ObjectFilter.Select(x => _database.FindStoredProcedure(x)).Where(x => x != null)); } if (_options.FunctionOptions.AllObjects) { _functions.AddRange(_database.Functions); } else { _functions.AddRange(_options.FunctionOptions.ObjectFilter.Select(x => _database.FindFunction(x)).Where(x => x != null)); } }
public void GetCommands(DmlfBatch res, DatabaseInfo db, ChangeSetModel model, IDialectDataAdapter dda, ICdlValueConvertor converter) { var table = db.FindTable(TargetTable); if (table == null) { return; } if ((UpdateReferences || model.UpdateReferences) && IsUpdatingPk(db)) { var refs = GenerateCascadeUpdates(db); foreach (var item in refs) { item.GetCommands(res, db, model, dda, converter); } } if (!IsDuplicatingIdentity(db, model)) { var cmd = new DmlfUpdate(); cmd.UpdateTarget = new DmlfSource { TableOrView = TargetTable, LinkedInfo = LinkedInfo, Alias = "basetbl", }; cmd.From.Add(new DmlfFromItem { Source = cmd.UpdateTarget, }); if (GetConditions(cmd, this, Conditions, db)) { GetValues(cmd.Columns, Values, table, dda, converter); res.Commands.Add(cmd); } } }
//public void SaveToXml(XmlElement xml) //{ // foreach (var elem in Inserts) // { // elem.SaveToXml(xml.AddChild("Insert")); // } // foreach (var elem in Updates) // { // elem.SaveToXml(xml.AddChild("Update")); // } // foreach (var elem in Deletes) // { // elem.SaveToXml(xml.AddChild("Delete")); // } //} //private void DumpTarget(ISqlDumper dmp, ChangeSetItem item) //{ // string linkedInfoStr = item.LinkedInfo != null ? item.LinkedInfo.ToString() : ""; // dmp.Put("%s%f", linkedInfoStr, item.TargetTable); //} //private void DumpWhere(ISqlDumper dmp, ChangeSetItem item, List<ChangeSetCondition> conditions, DatabaseInfo db) //{ // dmp.Put("^ where "); // bool wasCond = false; // foreach(var cond in conditions) // { // if (wasCond) dmp.Put(" ^and "); // wasCond = true; // DumpCondition(dmp, item, cond, db); // } //} public DmlfBatch GetCommands(DatabaseInfo db, IDatabaseFactory factory) { var disableFks = new HashSet<Tuple<NameWithSchema, string>>(); var dda = factory.CreateDataAdapter(); var converter = new CdlValueConvertor(new DataFormatSettings()); foreach (var upd in Updates) { if (upd.DisableReferencedForeignKeys || upd.UpdateReferences || DisableReferencedForeignKeys || UpdateReferences) { var table = db.FindTable(upd.TargetTable); if (table == null) continue; foreach (var fk in table.GetReferences()) { disableFks.Add(Tuple.Create(fk.OwnerTable.FullName, fk.ConstraintName)); } } } var res = new DmlfBatch(); foreach (var fk in disableFks) res.DisableConstraint(fk.Item1, fk.Item2, true); foreach (var ins in Inserts) { ins.GetCommands(res, db, dda, converter); } foreach (var upd in Updates) { upd.GetInsertCommands(res, db, this, dda, converter); } foreach (var upd in Updates) { upd.GetCommands(res, db, this, dda, converter); } foreach (var upd in Updates) { upd.GetDeleteCommands(res, db, this); } foreach (var del in Deletes) { del.GetCommands(res, db, this); } foreach (var fk in disableFks) res.DisableConstraint(fk.Item1, fk.Item2, false); res.Commands.ForEach(x => { var cmd = x as DmlfCommandBase; if (cmd != null) cmd.SimplifyFromAliases(); }); return res; }
private DmlfSource DoAddOrFindRelation(DmlfSource baseSource, NameWithSchema baseTable, StructuredIdentifier relationJoined, StructuredIdentifier relationToJoin, DatabaseInfo db, DmlfJoinType joinType) { if (relationToJoin.IsEmpty) { return(baseSource); } string relName = relationToJoin.First; string alias = String.Format("_REF{0}_{1}", relationJoined.NameItems.Select(x => "_" + x).CreateDelimitedText(""), relName); var source = FindSourceByAlias(alias); if (source == null) { var baseTableInfo = db.FindTable(baseTable); var fk = baseTableInfo.ForeignKeys.FirstOrDefault(x => System.String.Compare(x.ConstraintName, relName, StringComparison.OrdinalIgnoreCase) == 0); if (fk == null) { var column = baseTableInfo.FindColumn(relName); if (column != null) { fk = column.GetForeignKeys().FirstOrDefault(x => x.Columns.Count == 1); } } if (fk == null) { return(null); } source = new DmlfSource { TableOrView = fk.RefTableFullName, Alias = alias, }; var relation = new DmlfRelation { Reference = source, JoinType = joinType, }; for (int i = 0; i < fk.Columns.Count; i++) { relation.Conditions.Add(new DmlfEqualCondition { LeftExpr = new DmlfColumnRefExpression { Column = new DmlfColumnRef { ColumnName = fk.Columns[0].RefColumnName, Source = baseSource, } }, RightExpr = new DmlfColumnRefExpression { Column = new DmlfColumnRef { ColumnName = fk.RefColumns[0].RefColumnName, Source = source, } }, }); Relations.Add(relation); } } if (relationToJoin.IsEmpty) { return(source); } return(DoAddOrFindRelation(source, source.TableOrView, relationJoined / relationToJoin.First, relationToJoin.WithoutFirst, db, joinType)); }
public void GetDeleteCommands(DmlfBatch res, DatabaseInfo db, ChangeSetModel model) { var table = db.FindTable(TargetTable); if (table == null) return; if (IsDuplicatingIdentity(db, model)) { var del = new DmlfDelete(); del.DeleteTarget = new DmlfSource { TableOrView = table.FullName, Alias = "basetbl", }; del.SingleFrom = new DmlfFromItem { Source = del.DeleteTarget }; GetConditions(del, this, Conditions, db); res.Commands.Add(del); } }
public void GetCommands(DmlfBatch res, DatabaseInfo db, ChangeSetModel model, IDialectDataAdapter dda, ICdlValueConvertor converter) { var table = db.FindTable(TargetTable); if (table == null) return; if ((UpdateReferences || model.UpdateReferences) && IsUpdatingPk(db)) { var refs = GenerateCascadeUpdates(db); foreach (var item in refs) { item.GetCommands(res, db, model, dda, converter); } } if (!IsDuplicatingIdentity(db, model)) { var cmd = new DmlfUpdate(); cmd.UpdateTarget = new DmlfSource { TableOrView = TargetTable, LinkedInfo = LinkedInfo, Alias = "basetbl", }; cmd.From.Add(new DmlfFromItem { Source = cmd.UpdateTarget, }); if (GetConditions(cmd, this, Conditions, db)) { GetValues(cmd.Columns, Values, table, dda, converter); res.Commands.Add(cmd); } } }
public void GetInsertCommands(DmlfBatch res, DatabaseInfo db, ChangeSetModel model, IDialectDataAdapter dda, ICdlValueConvertor converter) { var table = db.FindTable(TargetTable); if (table == null) return; if (IsDuplicatingIdentity(db, model)) { res.AllowIdentityInsert(table.FullName, true); var insert = new DmlfInsertSelect { TargetTable = table.FullName, }; insert.Select = new DmlfSelect(); insert.Select.SingleFrom = new DmlfFromItem { Source = new DmlfSource { TableOrView = table.FullName, Alias = "basetbl", } }; GetConditions(insert.Select, this, Conditions, db); foreach (var col in table.Columns) { var valcol = Values.FirstOrDefault(x => x.Column == col.Name); insert.TargetColumns.Add(col.Name); if (valcol == null) { insert.Select.Columns.Add(DmlfResultField.BuildFromColumn(col.Name, insert.Select.SingleFrom.Source)); } else { insert.Select.Columns.Add(new DmlfResultField { Expr = new DmlfLiteralExpression { Value = valcol.Value, } }); } } res.Commands.Add(insert); res.AllowIdentityInsert(table.FullName, false); } }
public void ChangeTableSchema(TableInfo obj, string newschema) { var oldObj = _database.FindTable(obj); if (oldObj != null) { oldObj.FullName = new NameWithSchema(newschema, oldObj.FullName.Name); } }
//public void SaveToXml(XmlElement xml) //{ // foreach (var elem in Inserts) // { // elem.SaveToXml(xml.AddChild("Insert")); // } // foreach (var elem in Updates) // { // elem.SaveToXml(xml.AddChild("Update")); // } // foreach (var elem in Deletes) // { // elem.SaveToXml(xml.AddChild("Delete")); // } //} //private void DumpTarget(ISqlDumper dmp, ChangeSetItem item) //{ // string linkedInfoStr = item.LinkedInfo != null ? item.LinkedInfo.ToString() : ""; // dmp.Put("%s%f", linkedInfoStr, item.TargetTable); //} //private void DumpWhere(ISqlDumper dmp, ChangeSetItem item, List<ChangeSetCondition> conditions, DatabaseInfo db) //{ // dmp.Put("^ where "); // bool wasCond = false; // foreach(var cond in conditions) // { // if (wasCond) dmp.Put(" ^and "); // wasCond = true; // DumpCondition(dmp, item, cond, db); // } //} public DmlfBatch GetCommands(DatabaseInfo db, IDatabaseFactory factory) { var disableFks = new HashSet <Tuple <NameWithSchema, string> >(); var dda = factory.CreateDataAdapter(); var converter = new CdlValueConvertor(new DataFormatSettings()); foreach (var upd in Updates) { if (upd.DisableReferencedForeignKeys || upd.UpdateReferences || DisableReferencedForeignKeys || UpdateReferences) { var table = db.FindTable(upd.TargetTable); if (table == null) { continue; } foreach (var fk in table.GetReferences()) { disableFks.Add(Tuple.Create(fk.OwnerTable.FullName, fk.ConstraintName)); } } } var res = new DmlfBatch(); foreach (var fk in disableFks) { res.DisableConstraint(fk.Item1, fk.Item2, true); } foreach (var ins in Inserts) { ins.GetCommands(res, db, dda, converter); } foreach (var upd in Updates) { upd.GetInsertCommands(res, db, this, dda, converter); } foreach (var upd in Updates) { upd.GetCommands(res, db, this, dda, converter); } foreach (var upd in Updates) { upd.GetDeleteCommands(res, db, this); } foreach (var del in Deletes) { del.GetCommands(res, db, this); } foreach (var fk in disableFks) { res.DisableConstraint(fk.Item1, fk.Item2, false); } res.Commands.ForEach(x => { var cmd = x as DmlfCommandBase; if (cmd != null) { cmd.SimplifyFromAliases(); } }); return(res); }