internal static DataRow?GetParentRow(DataKey parentKey, DataKey childKey, DataRow childRow, DataRowVersion version) { if (!childRow.HasVersion((version == DataRowVersion.Original) ? DataRowVersion.Original : DataRowVersion.Current)) { if (childRow._tempRecord == -1) { return(null); } } object[] values = childRow.GetKeyValues(childKey, version); if (IsKeyNull(values)) { return(null); } Index index = parentKey.GetSortIndex((version == DataRowVersion.Original) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); Range range = index.FindRecords(values); if (range.IsNull) { return(null); } if (range.Count > 1) { throw ExceptionBuilder.MultipleParents(); } return(parentKey.Table._recordManager[index.GetRecord(range.Min)]); }
internal void CascadeRollback(DataRow row) { Index sortIndex = this.childKey.GetSortIndex((row.RowState == DataRowState.Deleted) ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] keyValues = row.GetKeyValues(this.parentKey, (row.RowState == DataRowState.Modified) ? DataRowVersion.Current : DataRowVersion.Default); if (!this.IsKeyNull(keyValues)) { Range range = sortIndex.FindRecords(keyValues); if (this.acceptRejectRule == System.Data.AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = sortIndex.GetRows(range); for (int i = 0; i < rows.Length; i++) { if (!rows[i].inCascade) { rows[i].RejectChanges(); } } } } else if (((((row.RowState != DataRowState.Deleted) && row.Table.DataSet.EnforceConstraints) && !range.IsNull) && ((range.Count != 1) || (sortIndex.GetRow(range.Min) != row))) && row.HasKeyChanged(this.parentKey)) { throw ExceptionBuilder.FailedCascadeUpdate(this.ConstraintName); } } }
internal override bool IsConstraintViolated() { Index childIndex = childKey.GetSortIndex(); object[] uniqueChildKeys = childIndex.GetUniqueKeyValues(); bool errors = false; Index parentIndex = parentKey.GetSortIndex(); for (int i = 0; i < uniqueChildKeys.Length; i++) { object[] childValues = (object[])uniqueChildKeys[i]; if (!IsKeyNull(childValues)) { if (!parentIndex.IsKeyInIndex(childValues)) { DataRow[] rows = childIndex.GetRows(childIndex.FindRecords(childValues)); string error = Res.GetString(Res.DataConstraint_ForeignKeyViolation, ConstraintName, ExceptionBuilder.KeysToString(childValues)); for (int j = 0; j < rows.Length; j++) { rows[j].RowError = error; } errors = true; } } } return(errors); }
internal void CascadeCommit(DataRow row) { if (row.RowState == DataRowState.Detached) { return; } if (acceptRejectRule == AcceptRejectRule.Cascade) { Index childIndex = childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.Deleted : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(parentKey, row.RowState == DataRowState.Deleted ? DataRowVersion.Original : DataRowVersion.Default); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (!range.IsNull) { for (int j = range.Min; j <= range.Max; j++) { DataRow childRow = childIndex.GetRow(j); if (childRow.inCascade) { continue; } childRow.AcceptChanges(); } } } }
internal override void CheckConstraint(DataRow row, DataRowAction action) { if (Table.EnforceConstraints && (action == DataRowAction.Add || action == DataRowAction.Change || (action == DataRowAction.Rollback && row.tempRecord != -1))) { if (row.HaveValuesChanged(Columns)) { Index index = Key.GetSortIndex(); object[] values = row.GetColumnValues(Columns); if (index.IsKeyInIndex(values)) { #if DEBUG if (CompModSwitches.Data_Constraints.TraceVerbose) { Debug.WriteLine("UniqueConstraint violation..."); string valuesText = ""; for (int i = 0; i < values.Length; i++) { valuesText = Convert.ToString(values[i]) + (i < values.Length - 1 ? ", " : ""); } Debug.WriteLine(" constraint: " + this.GetDebugString()); Debug.WriteLine(" key values: " + valuesText); Range range = index.FindRecords(values); int record = index.GetRecord(range.Min); Debug.WriteLine(" conflicting record: " + record.ToString()); } #endif throw ExceptionBuilder.ConstraintViolation(Columns, values); } } } }
internal override bool IsConstraintViolated() { bool result = false; Index index = ConstraintIndex; if (index.HasDuplicates) { object[] uniqueKeys = index.GetUniqueKeyValues(); for (int i = 0; i < uniqueKeys.Length; i++) { Range r = index.FindRecords((object[])uniqueKeys[i]); if (1 < r.Count) { DataRow[] rows = index.GetRows(r); string error = ExceptionBuilder.UniqueConstraintViolationText(_key.ColumnsReference, (object[])uniqueKeys[i]); for (int j = 0; j < rows.Length; j++) { rows[j].RowError = error; foreach (DataColumn dataColumn in _key.ColumnsReference) { rows[j].SetColumnError(dataColumn, error); } } result = true; } } } return(result); }
internal override bool IsConstraintViolated() { bool flag = false; Index constraintIndex = this.ConstraintIndex; if (constraintIndex.HasDuplicates) { object[] uniqueKeyValues = constraintIndex.GetUniqueKeyValues(); for (int i = 0; i < uniqueKeyValues.Length; i++) { Range range = constraintIndex.FindRecords((object[])uniqueKeyValues[i]); if (1 < range.Count) { DataRow[] rows = constraintIndex.GetRows(range); string error = ExceptionBuilder.UniqueConstraintViolationText(this.key.ColumnsReference, (object[])uniqueKeyValues[i]); for (int j = 0; j < rows.Length; j++) { rows[j].RowError = error; foreach (DataColumn column in this.key.ColumnsReference) { rows[j].SetColumnError(column, error); } } flag = true; } } } return(flag); }
internal void CascadeRollback(DataRow row) { Debug.Assert(row.Table.DataSet != null); Index childIndex = _childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(_parentKey, row.RowState == DataRowState.Modified ? DataRowVersion.Current : DataRowVersion.Default); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (_acceptRejectRule == AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { if (rows[j]._inCascade) { continue; } rows[j].RejectChanges(); } } } else { // AcceptRejectRule.None if (row.RowState != DataRowState.Deleted && row.Table.DataSet.EnforceConstraints) { if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) { return; } if (row.HasKeyChanged(_parentKey)) {// if key is not changed, this will not cause child to be stranded throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } } } }
internal void CascadeRollback(DataRow row) { Index childIndex = childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.OriginalRows : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(parentKey, row.RowState == DataRowState.Modified ? DataRowVersion.Current : DataRowVersion.Default); // Bug : This is definitely not a proper fix. (Ref. MDAC Bug 73592) if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (acceptRejectRule == AcceptRejectRule.Cascade) { if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { if (rows[j].inCascade) { continue; } rows[j].RejectChanges(); } } } else { // AcceptRejectRule.None if (row.RowState != DataRowState.Deleted && row.Table.DataSet.EnforceConstraints) { if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) { return; } throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } } }
internal void CascadeCommit(DataRow row) { if ((row.RowState != DataRowState.Detached) && (this.acceptRejectRule == System.Data.AcceptRejectRule.Cascade)) { Index sortIndex = this.childKey.GetSortIndex((row.RowState == DataRowState.Deleted) ? DataViewRowState.Deleted : DataViewRowState.CurrentRows); object[] keyValues = row.GetKeyValues(this.parentKey, (row.RowState == DataRowState.Deleted) ? DataRowVersion.Original : DataRowVersion.Default); if (!this.IsKeyNull(keyValues)) { Range range = sortIndex.FindRecords(keyValues); if (!range.IsNull) { foreach (DataRow row2 in sortIndex.GetRows(range)) { if ((DataRowState.Detached != row2.RowState) && !row2.inCascade) { row2.AcceptChanges(); } } } } } }
internal override bool IsConstraintViolated() { Index index = key.GetSortIndex(); object[] uniqueKeys = index.GetUniqueKeyValues(); bool errors = false; for (int i = 0; i < uniqueKeys.Length; i++) { Range r = index.FindRecords((object[])uniqueKeys[i]); DataRow[] rows = index.GetRows(r); if (rows.Length > 1) { string error = ExceptionBuilder.UniqueConstraintViolationText(key.Columns, (object[])uniqueKeys[i]); for (int j = 0; j < rows.Length; j++) { rows[j].RowError = error; errors = true; } } } return(errors); }
internal override bool IsConstraintViolated() { Index sortIndex = this.childKey.GetSortIndex(); object[] uniqueKeyValues = sortIndex.GetUniqueKeyValues(); bool flag = false; Index index2 = this.parentKey.GetSortIndex(); for (int i = 0; i < uniqueKeyValues.Length; i++) { object[] values = (object[])uniqueKeyValues[i]; if (!this.IsKeyNull(values) && !index2.IsKeyInIndex(values)) { DataRow[] rows = sortIndex.GetRows(sortIndex.FindRecords(values)); string str = Res.GetString("DataConstraint_ForeignKeyViolation", new object[] { this.ConstraintName, ExceptionBuilder.KeysToString(values) }); for (int j = 0; j < rows.Length; j++) { rows[j].RowError = str; } flag = true; } } return(flag); }
internal void CascadeCommit(DataRow row) { if (row.RowState == DataRowState.Detached) { return; } if (_acceptRejectRule == AcceptRejectRule.Cascade) { Index childIndex = _childKey.GetSortIndex(row.RowState == DataRowState.Deleted ? DataViewRowState.Deleted : DataViewRowState.CurrentRows); object[] key = row.GetKeyValues(_parentKey, row.RowState == DataRowState.Deleted ? DataRowVersion.Original : DataRowVersion.Default); if (IsKeyNull(key)) { return; } Range range = childIndex.FindRecords(key); if (!range.IsNull) { // Self-referencing table has suspendIndexEvents, in the multi-table scenario the child table hasn't // this allows the self-ref table to maintain the index while in the child-table doesn't DataRow[] rows = childIndex.GetRows(range); foreach (DataRow childRow in rows) { if (DataRowState.Detached != childRow.RowState) { if (childRow._inCascade) { continue; } childRow.AcceptChanges(); } } } } }
internal void CascadeUpdate(DataRow row) { if (-1 == row.newRecord) { return; } object[] currentKey = row.GetKeyValues(parentKey, DataRowVersion.Current); if (!Table.DataSet.fInReadXml && IsKeyNull(currentKey)) { return; } Index childIndex = childKey.GetSortIndex(); switch (UpdateRule) { case Rule.None: { if (row.Table.DataSet.EnforceConstraints) { // if we're not cascading deletes, we should throw if we're going to strand a child row under enforceConstraints. Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { throw ExceptionBuilder.FailedCascadeUpdate(ConstraintName); } } break; } case Rule.Cascade: { Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { object[] proposedKey = row.GetKeyValues(parentKey, DataRowVersion.Proposed); DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } case Rule.SetNull: { object[] proposedKey = new object[childKey.Columns.Length]; for (int i = 0; i < childKey.Columns.Length; i++) { proposedKey[i] = DBNull.Value; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } case Rule.SetDefault: { object[] proposedKey = new object[childKey.Columns.Length]; for (int i = 0; i < childKey.Columns.Length; i++) { proposedKey[i] = childKey.Columns[i].DefaultValue; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; rows[j].SetKeyValues(childKey, proposedKey); } } break; } default: { Debug.Assert(false, "Unknown Rule value"); break; } } }
internal void CascadeDelete(DataRow row) { if (-1 != row.newRecord) { object[] keyValues = row.GetKeyValues(this.parentKey, DataRowVersion.Current); if (!this.IsKeyNull(keyValues)) { Index sortIndex = this.childKey.GetSortIndex(); switch (this.DeleteRule) { case Rule.None: if (row.Table.DataSet.EnforceConstraints) { Range range4 = sortIndex.FindRecords(keyValues); if (range4.IsNull) { return; } if ((range4.Count != 1) || (sortIndex.GetRow(range4.Min) != row)) { throw ExceptionBuilder.FailedCascadeDelete(this.ConstraintName); } } return; case Rule.Cascade: { object[] key = row.GetKeyValues(this.parentKey, DataRowVersion.Default); Range range3 = sortIndex.FindRecords(key); if (!range3.IsNull) { foreach (DataRow row2 in sortIndex.GetRows(range3)) { if (!row2.inCascade) { row2.Table.DeleteRow(row2); } } } return; } case Rule.SetNull: { object[] objArray3 = new object[this.childKey.ColumnsReference.Length]; for (int i = 0; i < this.childKey.ColumnsReference.Length; i++) { objArray3[i] = DBNull.Value; } Range range2 = sortIndex.FindRecords(keyValues); if (!range2.IsNull) { DataRow[] rows = sortIndex.GetRows(range2); for (int j = 0; j < rows.Length; j++) { if (row != rows[j]) { rows[j].SetKeyValues(this.childKey, objArray3); } } } return; } case Rule.SetDefault: { object[] objArray2 = new object[this.childKey.ColumnsReference.Length]; for (int k = 0; k < this.childKey.ColumnsReference.Length; k++) { objArray2[k] = this.childKey.ColumnsReference[k].DefaultValue; } Range range = sortIndex.FindRecords(keyValues); if (!range.IsNull) { DataRow[] rowArray = sortIndex.GetRows(range); for (int m = 0; m < rowArray.Length; m++) { if (row != rowArray[m]) { rowArray[m].SetKeyValues(this.childKey, objArray2); } } } return; } } } } }
internal void CascadeUpdate(DataRow row) { if (-1 != row.newRecord) { object[] keyValues = row.GetKeyValues(this.parentKey, DataRowVersion.Current); if (this.Table.DataSet.fInReadXml || !this.IsKeyNull(keyValues)) { Index sortIndex = this.childKey.GetSortIndex(); switch (this.UpdateRule) { case Rule.None: if (row.Table.DataSet.EnforceConstraints && !sortIndex.FindRecords(keyValues).IsNull) { throw ExceptionBuilder.FailedCascadeUpdate(this.ConstraintName); } return; case Rule.Cascade: { Range range3 = sortIndex.FindRecords(keyValues); if (!range3.IsNull) { object[] objArray4 = row.GetKeyValues(this.parentKey, DataRowVersion.Proposed); DataRow[] rows = sortIndex.GetRows(range3); for (int i = 0; i < rows.Length; i++) { rows[i].SetKeyValues(this.childKey, objArray4); } } return; } case Rule.SetNull: { object[] objArray3 = new object[this.childKey.ColumnsReference.Length]; for (int j = 0; j < this.childKey.ColumnsReference.Length; j++) { objArray3[j] = DBNull.Value; } Range range2 = sortIndex.FindRecords(keyValues); if (!range2.IsNull) { DataRow[] rowArray2 = sortIndex.GetRows(range2); for (int k = 0; k < rowArray2.Length; k++) { rowArray2[k].SetKeyValues(this.childKey, objArray3); } } return; } case Rule.SetDefault: { object[] objArray2 = new object[this.childKey.ColumnsReference.Length]; for (int m = 0; m < this.childKey.ColumnsReference.Length; m++) { objArray2[m] = this.childKey.ColumnsReference[m].DefaultValue; } Range range = sortIndex.FindRecords(keyValues); if (!range.IsNull) { DataRow[] rowArray = sortIndex.GetRows(range); for (int n = 0; n < rowArray.Length; n++) { rowArray[n].SetKeyValues(this.childKey, objArray2); } } return; } } } } }
internal void CascadeDelete(DataRow row) { if (-1 == row._newRecord) { return; } object[] currentKey = row.GetKeyValues(_parentKey, DataRowVersion.Current); if (IsKeyNull(currentKey)) { return; } Index childIndex = _childKey.GetSortIndex(); switch (DeleteRule) { case Rule.None: { if (row.Table.DataSet.EnforceConstraints) { // if we're not cascading deletes, we should throw if we're going to strand a child row under enforceConstraints. Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { if (range.Count == 1 && childIndex.GetRow(range.Min) == row) { return; } throw ExceptionBuilder.FailedCascadeDelete(ConstraintName); } } break; } case Rule.Cascade: { object[] key = row.GetKeyValues(_parentKey, DataRowVersion.Default); Range range = childIndex.FindRecords(key); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { DataRow r = rows[j]; if (r._inCascade) { continue; } r.Table.DeleteRow(r); } } break; } case Rule.SetNull: { object[] proposedKey = new object[_childKey.ColumnsReference.Length]; for (int i = 0; i < _childKey.ColumnsReference.Length; i++) { proposedKey[i] = DBNull.Value; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; if (row != rows[j]) { rows[j].SetKeyValues(_childKey, proposedKey); } } } break; } case Rule.SetDefault: { object[] proposedKey = new object[_childKey.ColumnsReference.Length]; for (int i = 0; i < _childKey.ColumnsReference.Length; i++) { proposedKey[i] = _childKey.ColumnsReference[i].DefaultValue; } Range range = childIndex.FindRecords(currentKey); if (!range.IsNull) { DataRow[] rows = childIndex.GetRows(range); for (int j = 0; j < rows.Length; j++) { // if (rows[j].inCascade) // continue; if (row != rows[j]) { rows[j].SetKeyValues(_childKey, proposedKey); } } } break; } default: { Debug.Fail("Unknown Rule value"); break; } } }