*** empty log message ***
authorEran Domb <eran@mono-cvs.ximian.com>
Wed, 22 Oct 2003 05:55:54 +0000 (05:55 -0000)
committerEran Domb <eran@mono-cvs.ximian.com>
Wed, 22 Oct 2003 05:55:54 +0000 (05:55 -0000)
svn path=/trunk/mcs/; revision=19293

mcs/class/System.Data/System.Data/DataRelationCollection.cs
mcs/class/System.Data/System.Data/DataRow.cs
mcs/class/System.Data/System.Data/DataRowCollection.cs
mcs/class/System.Data/System.Data/DataSet.cs
mcs/class/System.Data/System.Data/DataTable.cs
mcs/class/System.Data/System.Data/UniqueConstraint.cs

index 83f2ef03d1db507e6a6fa249d24db44dc4cce769..4f343c08c08a904e806ecddc71c7ecc656530150 100644 (file)
@@ -76,43 +76,53 @@ namespace System.Data {
                                base.AddCore (relation);
                                if (relation.ChildTable.DataSet != this.dataSet || relation.ParentTable.DataSet != this.dataSet)
                                        throw new DataException ();
-                               List.Add (relation);
+                               //List.Add (relation);
                                relation.SetDataSet (dataSet);
                                relation.ParentTable.ChildRelations.Add (relation);
                                relation.ChildTable.ParentRelations.Add (relation);
                                ForeignKeyConstraint foreignKeyConstraint = null;
-                               if (relation.createConstraints) {
+                               if (relation.createConstraints) \r
+                               {
                                        foreignKeyConstraint = new ForeignKeyConstraint (relation.ParentColumns, relation.ChildColumns);
                                        relation.ChildTable.Constraints.Add (foreignKeyConstraint);
-                               }
-                               UniqueConstraint uniqueConstraint = null;
-                               foreach (object o in List) {
-                                       if (o is UniqueConstraint) {
-                                               UniqueConstraint uc = (UniqueConstraint) o;
-                                               if (uc.Columns.Length == relation.ParentColumns.Length) {
-                                                       bool allColumnsEqual = true;
-                                                       for (int columnCnt = 0; columnCnt < uc.Columns.Length; ++columnCnt) {
-                                                               if (uc.Columns[columnCnt] != relation.ParentColumns[columnCnt]) {
-                                                                       allColumnsEqual = false;
+                               
+                                       UniqueConstraint uniqueConstraint = null;
+                                       ConstraintCollection parentConstrains = relation.ParentTable.Constraints;
+                                       // find if the unique constraint already exists in the parent table.
+                                       foreach (Constraint o in parentConstrains) \r
+                                       {
+                                               if (o is UniqueConstraint) \r
+                                               {
+                                                       UniqueConstraint uc = (UniqueConstraint) o;
+                                                       if (uc.Columns.Length == relation.ParentColumns.Length) \r
+                                                       {
+                                                               bool allColumnsEqual = true;
+                                                               for (int columnCnt = 0; columnCnt < uc.Columns.Length; ++columnCnt) \r
+                                                               {
+                                                                       if (uc.Columns[columnCnt] != relation.ParentColumns[columnCnt]) \r
+                                                                       {
+                                                                               allColumnsEqual = false;
+                                                                               break;
+                                                                       }
+                                                               }
+                                                               if (allColumnsEqual) \r
+                                                               {
+                                                                       uniqueConstraint = uc;
                                                                        break;
                                                                }
                                                        }
-                                                       if (allColumnsEqual) {
-                                                               uniqueConstraint = uc;
-                                                               break;
-                                                       }
                                                }
                                        }
+                                       // if we did not find the unique constraint in the parent table.
+                                       // we generate new uniqueconastraint and add it to the parent table.
+                                       if (uniqueConstraint == null)
+                                       {
+                                               uniqueConstraint = new UniqueConstraint(relation.ParentColumns, false);
+                                               relation.ParentTable.Constraints.Add(uniqueConstraint);
+                                       }
+                                       relation.SetParentKeyConstraint (uniqueConstraint);
+                                       relation.SetChildKeyConstraint (foreignKeyConstraint);
                                }
-                               // if we did not find the unique constraint in the parent table.
-                               // we generate new uniqueconastraint and add it to the parent table.
-                               if (uniqueConstraint == null)
-                               {
-                                       uniqueConstraint = new UniqueConstraint(relation.ParentColumns, false);
-                                       relation.ParentTable.Constraints.Add(uniqueConstraint);
-                               }
-                               relation.SetParentKeyConstraint (uniqueConstraint);
-                               relation.SetChildKeyConstraint (foreignKeyConstraint);
                        }
 
                        public override void AddRange (DataRelation[] relations)
@@ -122,16 +132,17 @@ namespace System.Data {
 
                        public override void Clear ()
                        {
-                               base.Clear ();
+                               for (int i = 0; i < Count; i++)
+                                       RemoveCore(this[i]);
+
+                               base.Clear();
                        }
 
                        protected override void RemoveCore (DataRelation relation)
                        {
-                               base.RemoveCore (relation);
                                relation.SetDataSet (null);
                                relation.ParentTable.ChildRelations.Remove (relation);
                                relation.ChildTable.ParentRelations.Remove (relation);
-                               ForeignKeyConstraint foreignKeyConstraint = null;
                                relation.SetParentKeyConstraint (null);
                                relation.SetChildKeyConstraint (null);
                        }
@@ -467,7 +478,7 @@ namespace System.Data {
 
                public void RemoveAt (int index)
                {
-                       List.RemoveAt (index);
+                       Remove(this[index]);
                }
 
                [MonoTODO]
index 6b361e2916f84216f1e47305554578a96ee05696..c599a3d48d4031fdad3e33fa8bcac48790cdd356 100644 (file)
@@ -51,14 +51,13 @@ namespace System.Data {
                        _table = builder.Table;
 
                        original = null; 
-                       current = new object[_table.Columns.Count];
-                       // initialize to DBNull.Value
-                       for (int c = 0; c < _table.Columns.Count; c++) {
-                               current[c] = DBNull.Value;
-                       }
+                       
                        proposed = new object[_table.Columns.Count];
-                       Array.Copy (current, proposed, _table.Columns.Count);
-
+                       for (int c = 0; c < _table.Columns.Count; c++) 
+                       {
+                               proposed[c] = DBNull.Value;
+                       }
+                       
                        columnErrors = new string[_table.Columns.Count];
                        rowError = String.Empty;
 
@@ -86,7 +85,15 @@ namespace System.Data {
                public bool HasErrors {
                        [MonoTODO]
                        get {
-                               throw new NotImplementedException ();
+                               if (RowError != string.Empty)
+                                       return true;
+
+                               for (int i= 0; i < columnErrors.Length; i++){
+                                       if (columnErrors[i] != null && columnErrors[i] != string.Empty)
+                                               return true;
+                               }
+
+                               return false;
                        }
                }
 
@@ -107,7 +114,9 @@ namespace System.Data {
                /// Gets or sets the data stored in specified DataColumn
                /// </summary>
                public object this[DataColumn column] {
-                       get { return this[column, DataRowVersion.Default]; } 
+
+                       get {
+                               return this[column, DataRowVersion.Default];} 
                        set {
                                int columnIndex = _table.Columns.IndexOf (column);
                                if (columnIndex == -1)
@@ -129,6 +138,7 @@ namespace System.Data {
                                DataColumn column = _table.Columns[columnIndex];
                                _table.ChangingDataColumn (this, column, value);
                                
+                               
                                bool orginalEditing = editing;
                                if (!orginalEditing) BeginEdit ();
                                object v = SetColumnValue (value, columnIndex);
@@ -457,6 +467,7 @@ namespace System.Data {
                [MonoTODO]
                public void Delete () 
                {
+                       _table.DeletingDataRow(this, DataRowAction.Delete);
                        switch (rowState) {
                        case DataRowState.Added:
                                Table.Rows.Remove (this);
@@ -464,10 +475,104 @@ namespace System.Data {
                        case DataRowState.Deleted:
                                throw new DeletedRowInaccessibleException ();
                        default:
-                               //TODO: Events, Constraints
+                               // check what to do with child rows
+                               CheckChildRows(DataRowAction.Delete);
                                rowState = DataRowState.Deleted;
                                break;
                        }
+                       _table.DeletedDataRow(this, DataRowAction.Delete);
+               }
+
+               // check the child rows of this row before deleting the row.
+               private void CheckChildRows(DataRowAction action)
+               {
+                       
+                       // in this method we find the row that this row is in a reltion with them.
+                       // in shortly we find all child rows of this row.
+                       // then we function according to the DeleteRule of the foriegnkey.
+
+
+                       // 1. find if this row is attached to dataset.
+                       // 2. find if EnforceConstraints is true.
+                       // 3. find if there are any constraint on the table that the row is in.
+                       if (_table.DataSet != null && _table.DataSet.EnforceConstraints && _table.Constraints.Count > 0)
+                       {
+                               // loop on all relations of the dataset.
+                               DataRelationCollection relCollection = _table.DataSet.Relations;
+                               for (int i = 0; i < relCollection.Count; i++)
+                               {
+                                       DataRelation rel = relCollection[i];
+                                       // we want only relations that their parent table is the table this row is in.
+                                       // that is because we interesting only in relations that the row is a parent of
+                                       // other rows.
+                                       if (rel.ParentTable == _table)
+                                       {
+                                               Rule rule;
+                                               if (action == DataRowAction.Delete)
+                                                       rule = rel.ChildKeyConstraint.DeleteRule;
+                                               else
+                                                       rule = rel.ChildKeyConstraint.UpdateRule;
+                                               
+                                               DataRow[] childRows = GetChildRows(rel);
+                                               switch (rule)
+                                               {
+                                                       case Rule.Cascade:  // delete or change all relted rows.
+                                                               if (childRows != null)
+                                                               {
+                                                                       for (int j = 0; j < childRows.Length; j++)
+                                                                       {
+                                                                               // if action is delete we delte all child rows
+                                                                               if (action == DataRowAction.Delete)
+                                                                                       childRows[j].Delete();
+                                                                               // if action is change we change the values in the child row
+                                                                               else if (action == DataRowAction.Change)
+                                                                               {
+                                                                                       // change only the values in the key columns
+                                                                                       // set the childcolumn value to the new parent row value
+                                                                                       for (int k = 0; k < rel.ChildColumns.Length; k++)
+                                                                                               childRows[j][rel.ChildColumns[k]] = this[rel.ParentColumns[k], DataRowVersion.Proposed];
+                                                                               }
+                                                                       }
+                                                               }
+                                                               break;
+                                                       case Rule.None: // throw an exception if there are any child rows.
+                                                               if (childRows != null)
+                                                               {
+                                                                       string changeStr = "Cannot change this row because constraints are enforced on relation " + rel.RelationName +", and changing this row will strand child rows.";
+                                                                       string delStr = "Cannot delete this row because constraints are enforced on relation " + rel.RelationName +", and deleting this row will strand child rows.";
+                                                                       string message = action == DataRowAction.Delete ? delStr : changeStr;
+                                                                       throw new InvalidConstraintException(message);
+                                                               }
+                                                               break;
+                                                       case Rule.SetDefault: // set the values in the child rows to the defult value of the columns.
+                                                               if (childRows != null)
+                                                               {
+                                                                       for (int j = 0; j < childRows.Length; j++)
+                                                                       {
+                                                                               DataRow child = childRows[j];
+                                                                               //set only the key columns to default
+                                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)
+                                                                                       child[rel.ChildColumns[k]] = rel.ChildColumns[k].DefaultValue;
+                                                                       }
+                                                               }
+                                                               break;
+                                                       case Rule.SetNull: // set the values in the child row to null.
+                                                               if (childRows != null)
+                                                               {
+                                                                       for (int j = 0; j < childRows.Length; j++)
+                                                                       {
+                                                                               DataRow child = childRows[j];
+                                                                               // set only the key columns to DBNull
+                                                                               for (int k = 0; k < rel.ChildColumns.Length; k++)
+                                                                                       child.SetNull(rel.ChildColumns[k]);
+                                                                       }
+                                                               }
+                                                               break;
+                                               }
+                                                       
+                                       }
+                               }
+                       }
                }
 
                /// <summary>
@@ -481,14 +586,18 @@ namespace System.Data {
                                return;
                        if (HasVersion (DataRowVersion.Proposed))
                        {
+                               _table.ChangingDataRow(this, DataRowAction.Change);
                                if (rowState == DataRowState.Unchanged)
                                        rowState = DataRowState.Modified;
                                
                                //Calling next method validates UniqueConstraints
                                //and ForeignKeys.
                                _table.Rows.ValidateDataRowInternal(this);
+                               // check all child rows.
+                               CheckChildRows(DataRowAction.Change);
                                current = proposed;
                                proposed = null;
+                               _table.ChangedDataRow(this, DataRowAction.Change);
                        }
                }
 
@@ -559,7 +668,10 @@ namespace System.Data {
                        if (columnIndex < 0 || columnIndex >= columnErrors.Length)
                                throw new IndexOutOfRangeException ();
 
-                       return columnErrors[columnIndex];
+                       string retVal = columnErrors[columnIndex];
+                       if (retVal == null)
+                               retVal = string.Empty;
+                       return retVal;
                }
 
                /// <summary>
@@ -579,11 +691,11 @@ namespace System.Data {
 
                        for (int i = 0; i < columnErrors.Length; i += 1)
                        {
-                               if (columnErrors[i] != String.Empty)
+                               if (columnErrors[i] != null && columnErrors[i] != String.Empty)
                                        dataColumns.Add (_table.Columns[i]);
                        }
 
-                       return (DataColumn[])(dataColumns.ToArray ());
+                       return (DataColumn[])(dataColumns.ToArray (typeof(DataColumn)));
                }
 
                /// <summary>
@@ -682,12 +794,22 @@ namespace System.Data {
                        switch (version)
                        {
                                case DataRowVersion.Default:
+                                       if (rowState == DataRowState.Deleted)
+                                               return false;
+                                       if (rowState == DataRowState.Detached)
+                                               return proposed != null;
                                        return true;
                                case DataRowVersion.Proposed:
+                                       if (rowState == DataRowState.Deleted)
+                                               return false;
                                        return (proposed != null);
                                case DataRowVersion.Current:
+                                       if (rowState == DataRowState.Deleted || rowState == DataRowState.Detached)
+                                               return false;
                                        return (current != null);
                                case DataRowVersion.Original:
+                                       if (rowState == DataRowState.Detached)
+                                               return false;
                                        return (original != null);
                        }
                        return false;
@@ -825,6 +947,7 @@ namespace System.Data {
                //Copy all values of this DataaRow to the row parameter.
                internal void CopyValuesToRow(DataRow row)
                {
+                                               
                        if (row == null)
                                throw new ArgumentNullException("row");
                        if (row == this)
@@ -833,9 +956,10 @@ namespace System.Data {
                        DataColumnCollection columns = Table.Columns;
                        
                        for(int i = 0; i < columns.Count; i++){
+
                                string columnName = columns[i].ColumnName;
                                int index = row.Table.Columns.IndexOf(columnName);
-                               //if a column withe the same name exists in bote rows copy the values
+                               //if a column with the same name exists in both rows copy the values
                                if(index != -1) {
                                        if (HasVersion(DataRowVersion.Original))
                                        {
@@ -855,6 +979,10 @@ namespace System.Data {
                                                        row.proposed = new object[row.Table.Columns.Count];
                                                row.proposed[index] = row.SetColumnValue(proposed[i], index);
                                        }
+                                       
+                                       //Saving the current value as the column value
+                                       row[index] = row.current[index];
+                                       
                                }
                        }
 
@@ -872,21 +1000,26 @@ namespace System.Data {
 
                        if (args.Action == System.ComponentModel.CollectionChangeAction.Add)
                        {
-                               object[] tmp = new object[current.Length + 1];
-                               Array.Copy (current, tmp, current.Length);
-                               tmp[tmp.Length - 1] = DBNull.Value;
-                               current = tmp;
-
+                               object[] tmp;
+                               if (current != null)
+                               {
+                                       tmp = new object[current.Length + 1];
+                                       Array.Copy (current, tmp, current.Length);
+                                       tmp[tmp.Length - 1] = DBNull.Value;
+                                       current = tmp;
+                               }
                                if (proposed != null)
                                {
                                        tmp = new object[proposed.Length + 1];
                                        Array.Copy (proposed, tmp, proposed.Length);
+                                       tmp[tmp.Length - 1] = DBNull.Value;
                                        proposed = tmp;
                                }
                                if(original != null)
                                {
                                        tmp = new object[original.Length + 1];
                                        Array.Copy (original, tmp, original.Length);
+                                       tmp[tmp.Length - 1] = DBNull.Value;
                                        original = tmp;
                                }
 
index 5b25b50b3fc926539bce8c81f0ed5787aebc3f66..fe475a77b763bdad660e4f530a6264a90e6853b1 100644 (file)
@@ -133,18 +133,22 @@ namespace System.Data
                        
                        foreach (DataRow row in this) {
                                
-                               object primValue = row [primColumnName];
-                               if (key == null) {
-                                       if (primValue == null)
-                                               return row;
-                                       else 
-                                               continue;
-                               }
+                               if (row.RowState != DataRowState.Deleted)
+                               {
+                                       object primValue = row [primColumnName];
+                                       if (key == null) \r
+                                       {
+                                               if (primValue == null)
+                                                       return row;
+                                               else 
+                                                       continue;
+                                       }
                                       
-                               newKey = Convert.ChangeType (key, Type.GetTypeCode(primValue.GetType ()));
+                                       newKey = Convert.ChangeType (key, Type.GetTypeCode(primValue.GetType ()));
 
-                               if (primValue.Equals (newKey))
-                                       return row;
+                                       if (primValue.Equals (newKey))
+                                               return row;
+                               }
                        }
                                                
                        // FIXME: is the correct value null?
@@ -170,28 +174,34 @@ namespace System.Data
                        
                        foreach (DataRow row in this) {
                                
-                               bool eq = true;
-                               for (int i = 0; i < keys.Length; i++) {
+                               if (row.RowState != DataRowState.Deleted)
+                               {
+                                       bool eq = true;
+                                       for (int i = 0; i < keys.Length; i++) \r
+                                       {
                                        
-                                       object primValue = row [primColumnNames [i]];
-                                       object keyValue = keys [i];
-                                       if (keyValue == null) {
-                                               if (primValue == null)
-                                                       return row;
-                                               else 
-                                                       continue;
-                                       }
+                                               object primValue = row [primColumnNames [i]];
+                                               object keyValue = keys [i];
+                                               if (keyValue == null) \r
+                                               {
+                                                       if (primValue == null)
+                                                               return row;
+                                                       else 
+                                                               continue;
+                                               }
                                                                       
-                                       newKey = Convert.ChangeType (keyValue, Type.GetTypeCode(primValue.GetType ()));
+                                               newKey = Convert.ChangeType (keyValue, Type.GetTypeCode(primValue.GetType ()));
 
-                                       if (!primValue.Equals (newKey)) {
-                                               eq = false;
-                                               break;
-                                       }                                               
-                               }
+                                               if (!primValue.Equals (newKey)) \r
+                                               {
+                                                       eq = false;
+                                                       break;
+                                               }                                               
+                                       }
 
-                               if (eq)
-                                       return row;
+                                       if (eq)
+                                               return row;
+                               }
                        }
                                                
                        // FIXME: is the correct value null?
@@ -217,13 +227,12 @@ namespace System.Data
                /// </summary>
                public void Remove (DataRow row) 
                {
-                       // FIXME: This is the way the MS.NET handles this kind of situation. Could be better, but what can you do.
-                       if (row == null || list.IndexOf (row) == -1)
+                       if (row == null)
                                throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
-
-                       list.Remove (row);
-                       row.DetachRow ();
-                       table.DeletedDataRow (row, DataRowAction.Delete);
+                       int index = list.IndexOf(row);
+                       if (index < 0)
+                               throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
+                       RemoveAt(index);
                }
 
                /// <summary>
@@ -235,7 +244,10 @@ namespace System.Data
                                throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
 
                        DataRow row = (DataRow)list [index];
-                       list.RemoveAt (index);                  
+                       if (row.RowState != DataRowState.Deleted && row.RowState != DataRowState.Added)
+                               row.Delete();
+                       list.RemoveAt (index);
+                       row.DetachRow();
                        table.DeletedDataRow (row, DataRowAction.Delete);
                }
 
index 08ec40c328b7df8a7d85ecf41213b21e0c5e425c..d4362a9652dc7e6efadbd9fbda78d0e95a98b804 100644 (file)
@@ -119,7 +119,12 @@ namespace System.Data {
                public bool HasErrors {
                        [MonoTODO]
                        get {
-                               throw new NotImplementedException ();
+                               for (int i = 0; i < Tables.Count; i++)
+                               {
+                                       if (Tables[i].HasErrors)
+                                               return true;
+                               }
+                               return false;
                        }
                }
 
@@ -282,7 +287,11 @@ namespace System.Data {
 
                        foreach (DataTable Table in Tables) {
                                Copy.Tables.Add (Table.Clone ());
-                       }       
+                       }
+
+                       //Copy Relationships between tables after existance of tables
+                       //and setting properties correctly
+                       CopyRelations(Copy);
                        
                        return Copy;
                }
@@ -298,6 +307,10 @@ namespace System.Data {
                                Copy.Tables.Add (Table.Copy ());
                        }
 
+                       //Copy Relationships between tables after existance of tables
+                       //and setting properties correctly
+                       CopyRelations(Copy);
+
                        return Copy;
                }
 
@@ -314,11 +327,55 @@ namespace System.Data {
                        //Copy.HasErrors
                        //Copy.Locale = Locale;
                        Copy.Namespace = Namespace;
-                       Copy.Prefix = Prefix;
-                       //Copy.Relations = Relations;
+                       Copy.Prefix = Prefix;                   
                        //Copy.Site = Site;
 
                }
+               
+               
+               private void CopyRelations (DataSet Copy)
+               {
+
+                       //Creation of the relation contains some of the properties, and the constructor\r
+                       //demands these values. instead changing the DataRelation constructor and behaviour the\r
+                       //parameters are pre-configured and sent to the most general constructor
+
+                       foreach (DataRelation MyRelation in this.Relations)\r
+                       {\r
+                               string pTable = MyRelation.ParentTable.TableName;\r
+                               string cTable = MyRelation.ChildTable.TableName;\r
+                               DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length]; \r
+                               DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];\r
+                               int i = 0;\r
+                               foreach(DataColumn DC in MyRelation.ParentColumns)\r
+                               {\r
+                                       P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];\r
+                                       i++;\r
+                               }\r
+\r
+                               i = 0;\r
+\r
+                               foreach(DataColumn DC in MyRelation.ChildColumns)\r
+                               {\r
+                                       C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];\r
+                                       i++;\r
+                               }\r
+                               \r
+\r
+                               DataRelation cRel = new DataRelation(MyRelation.RelationName,P_DC,C_DC);\r
+                               //cRel.ChildColumns = MyRelation.ChildColumns;\r
+                               //cRel.ChildTable = MyRelation.ChildTable;\r
+                               //cRel.ExtendedProperties = cRel.ExtendedProperties; \r
+                               //cRel.Nested = MyRelation.Nested;\r
+                               //cRel.ParentColumns = MyRelation.ParentColumns;\r
+                               //cRel.ParentTable = MyRelation.ParentTable;\r
+                                                               \r
+                               Copy.Relations.Add(cRel);\r
+                       }
+               }
+
+               
+
 
                public DataSet GetChanges()
                {
@@ -433,7 +490,22 @@ namespace System.Data {
 
                public virtual void Reset()
                {
-                       throw new NotImplementedException ();
+                       IEnumerator constraintEnumerator;
+                       // first we remove all ForeignKeyConstraints (if we will not do that
+                       // we will get an exception when clearing the tables).
+                       for (int i = 0; i < Tables.Count; i++)
+                       {
+                               ConstraintCollection cc = Tables[i].Constraints;
+                               for (int j = 0; j < cc.Count; j++)
+                               {
+                                       if (cc[j] is ForeignKeyConstraint)
+                                               cc.Remove(cc[j]);
+                               }
+                       }
+
+                       Clear();
+                       Relations.Clear();
+                       Tables.Clear();
                }
 
                public void WriteXml(Stream stream)
index 85e83829e11281eb0c7cd038f1f610b89df2b299..3721d9285ec02b22a00608008baed0ec52f1b22f 100644 (file)
@@ -75,8 +75,7 @@ namespace System.Data {
                        _primaryKey = null;
                        _site = null;
                        _rows = new DataRowCollection (this);
-                       _locale = CultureInfo.CurrentCulture;
-
+                       
                        //LAMESPEC: spec says 25 impl does 50
                        _minimumCapacity = 50;
                        
@@ -142,12 +141,24 @@ namespace System.Data {
                        OnRowDeleted (e);
                }
 
+               internal void DeletingDataRow (DataRow dr, DataRowAction action) 
+               {
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
+                       OnRowDeleting(e);
+               }
+
                internal void ChangedDataRow (DataRow dr, DataRowAction action) 
                {
                        DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
                        OnRowChanged (e);
                }
 
+               internal void ChangingDataRow (DataRow dr, DataRowAction action) 
+               {
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
+                       OnRowChanging (e);
+               }
+
                /// <summary>
                /// Gets the collection of child relations for this DataTable.
                /// </summary>
@@ -234,7 +245,15 @@ namespace System.Data {
                [Browsable (false)]
                [DataSysDescription ("Returns whether the table has errors.")]
                public bool HasErrors {
-                       get { return _hasErrors; }
+                       get { 
+                               // we can not use the _hasError flag because we do not know when to turn it off!
+                               for (int i = 0; i < _rows.Count; i++)
+                               {
+                                       if (_rows[i].HasErrors)
+                                               return true;
+                               }
+                               return false;
+                       }
                }
 
                /// <summary>
@@ -243,8 +262,21 @@ namespace System.Data {
                /// </summary>
                [DataSysDescription ("Indicates a locale under which to compare strings within the table.")]
                public CultureInfo Locale {
-                       get { return _locale; }
-                       set { _locale = value; }
+                       get { 
+                               // if the locale is null, we check for the DataSet locale
+                               // and if the DataSet is null we return the current culture.
+                               // this way if DataSet locale is changed, only if there is no locale for 
+                               // the DataTable it influece the Locale get;
+                               if (_locale != null)
+                                       return _locale;
+                               if (DataSet != null)
+                                       return DataSet.Locale;
+                               return CultureInfo.CurrentCulture;
+                       }
+                       set { 
+                               if (_locale == null || !_locale.Equals(value))
+                                       _locale = value; 
+                       }
                }
 
                /// <summary>
@@ -396,9 +428,19 @@ namespace System.Data {
                {
                        //FIXME: Do we need to validate anything here or
                        //try to catch any errors to deal with them?
-
-                       foreach(DataRow myRow in _rows) {
+                       
+                       // we do not use foreach because if one of the rows is in Delete state
+                       // it will be romeved from Rows and we get an exception.
+                       DataRow myRow;
+                       for (int i = 0; i < Rows.Count; )
+                       {
+                               myRow = Rows[i];
                                myRow.AcceptChanges();
+
+                               // if the row state is Detached it meens that it was removed from row list (Rows)
+                               // so we should not increase 'i'.
+                               if (myRow.RowState != DataRowState.Detached)
+                                       i++;
                        }
                }
 
@@ -427,9 +469,33 @@ namespace System.Data {
                        // TODO: thow an exception if any rows that 
                        //       have enforced child relations 
                        //       that would result in child rows being orphaned
+                       // now we check if any ForeignKeyConstraint is referncing 'table'.
+                       if (DataSet != null)
+                       {
+                               IEnumerator tableEnumerator = DataSet.Tables.GetEnumerator();
+                       
+                               // loop on all tables in dataset
+                               while (tableEnumerator.MoveNext())
+                               {
+                                       IEnumerator constraintEnumerator = ((DataTable) tableEnumerator.Current).Constraints.GetEnumerator();
+                                       // loop on all constrains in the current table
+                                       while (constraintEnumerator.MoveNext())
+                                       {
+                                               Object o = constraintEnumerator.Current;
+                                               // we only check ForeignKeyConstraint
+                                               if (o is ForeignKeyConstraint)
+                                               {
+                                                       ForeignKeyConstraint fc = (ForeignKeyConstraint) o;
+                                                       if(fc.RelatedTable == this && fc.Table.Rows.Count > 0)
+                                                               throw new InvalidConstraintException("Cannot clear table " + fc.RelatedTable + " because ForeignKeyConstraint " + fc.ConstraintName + " enforces constraints and there are child rows in " + fc.Table);
+                                               }
+                                       }
+                               }
+                       }
+                       
                        // TODO: throw a NotSupportedException if the DataTable is part
                        //       of a DataSet that is binded to an XmlDataDocument
-
+                       
                        _rows.Clear ();
                }
 
@@ -487,13 +553,12 @@ namespace System.Data {
                        DataTable Copy = new DataTable ();
                        CopyProperties (Copy);
 
+                       // we can not simply copy the row values (NewRow [C.ColumnName] = Row [C.ColumnName])
+                       // because if the row state is deleted we get an exception.
                        foreach (DataRow Row in Rows) {
                                DataRow NewRow = Copy.NewRow ();
-                               NewRow.RowError = Row.RowError;
-                               foreach (DataColumn C in Copy.Columns) {
-                                       NewRow [C.ColumnName] = Row [C.ColumnName];
-                               }
                                Copy.Rows.Add (NewRow);
+                               Row.CopyValuesToRow(NewRow);
                        }
                                        
                        return Copy;
@@ -517,7 +582,6 @@ namespace System.Data {
                        Copy.Namespace = Namespace;
                        // Copy.ParentRelations
                        Copy.Prefix = Prefix;
-                       //Copy.PrimaryKey = PrimaryKey;
                        Copy.Site = Site;
                        Copy.TableName = TableName;
 
@@ -526,6 +590,16 @@ namespace System.Data {
                                Copy.Columns.Add (CopyColumn (Column));                         
                        }
 
+                       // add primary key to the copy
+                       if (PrimaryKey.Length > 0)
+                       {
+                               DataColumn[] pColumns = new DataColumn[PrimaryKey.Length];
+                               for (int i = 0; i < pColumns.Length; i++)
+                                       pColumns[i] = Copy.Columns[PrimaryKey[i].ColumnName];
+
+                               Copy.PrimaryKey = pColumns;
+                       }
+
                }
                /// <summary>
                /// Ends the initialization of a DataTable that is used 
@@ -555,8 +629,7 @@ namespace System.Data {
                [MonoTODO]
                public DataTable GetChanges() 
                {
-                       //TODO:
-                       return this;
+                       return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
                }
 
                /// <summary>
@@ -567,8 +640,21 @@ namespace System.Data {
                [MonoTODO]      
                public DataTable GetChanges(DataRowState rowStates) 
                {
-                       //TODO:
-                       return this;
+                       DataTable copyTable = null;
+
+                       IEnumerator rowEnumerator = Rows.GetEnumerator();
+                       while (rowEnumerator.MoveNext()) {
+                               DataRow row = (DataRow)rowEnumerator.Current;
+                               if (row.IsRowChanged(rowStates)) {
+                                       if (copyTable == null)
+                                               copyTable = Clone();
+                                       DataRow newRow = copyTable.NewRow();
+                                       copyTable.Rows.Add(newRow);
+                                       row.CopyValuesToRow(newRow);
+                               }
+                       }
+                        
+                       return copyTable;
                }
 
                /// <summary>
@@ -577,7 +663,14 @@ namespace System.Data {
                [MonoTODO]
                public DataRow[] GetErrors () 
                {
-                       throw new NotImplementedException ();
+                       ArrayList errors = new ArrayList();
+                       for (int i = 0; i < _rows.Count; i++)
+                       {
+                               if (_rows[i].HasErrors)
+                                       errors.Add(_rows[i]);
+                       }
+                       
+                       return (DataRow[]) errors.ToArray(typeof(DataRow));
                }
        
                /// <summary>
@@ -617,6 +710,10 @@ namespace System.Data {
                [MonoTODO]
                public void ImportRow (DataRow row) 
                {
+                       DataRow newRow = NewRow();
+                       Rows.Add(newRow);
+                       row.CopyValuesToRow(newRow);
+                       
                }
 
                /// <summary>
@@ -640,8 +737,32 @@ namespace System.Data {
                                if (fAcceptChanges)
                                        row.AcceptChanges ();
                        }
-                       else
-                               throw new NotImplementedException ();
+                       else {
+                               bool hasPrimaryValues = true;
+                               // initiate an array that has the values of the primary keys.\r
+                               object[] keyValues = new object[PrimaryKey.Length];\r
+                               for (int i = 0; i < keyValues.Length && hasPrimaryValues; i++)\r
+                               {\r
+                                       if(PrimaryKey[i].Ordinal < values.Length)\r
+                                               keyValues[i] = values[PrimaryKey[i].Ordinal];\r
+                                       else\r
+                                               hasPrimaryValues = false;\r
+                               }\r
+                               \r
+                               if (hasPrimaryValues){\r
+                                       // find the row in the table.\r
+                                       row = Rows.Find(keyValues);
+                               }
+                               
+                               if (row == null)
+                                       row = Rows.Add (values);
+                               else
+                                       row.ItemArray = values;
+                               
+                               if (fAcceptChanges)
+                                       row.AcceptChanges ();
+                       }
+                               
                        return row;
                }
 
@@ -679,8 +800,6 @@ namespace System.Data {
                [MonoTODO]
                public void RejectChanges () 
                {       
-                       //foreach(DataRow myRow in _rows)
-                       //{
                        for (int i = _rows.Count - 1; i >= 0; i--) {
                                DataRow row = _rows [i];
                                if (row.RowState != DataRowState.Unchanged)
@@ -694,6 +813,20 @@ namespace System.Data {
                [MonoTODO]
                public virtual void Reset () 
                {
+                       Clear();
+                       while (ParentRelations.Count > 0)
+                       {
+                               if (dataSet.Relations.Contains(ParentRelations[ParentRelations.Count - 1].RelationName))
+                                       dataSet.Relations.Remove(ParentRelations[ParentRelations.Count - 1]);
+                       }
+
+                       while (ChildRelations.Count > 0)
+                       {
+                               if (dataSet.Relations.Contains(ChildRelations[ChildRelations.Count - 1].RelationName))
+                                       dataSet.Relations.Remove(ChildRelations[ChildRelations.Count - 1]);
+                       }
+                       Constraints.Clear();
+                       Columns.Clear();
                }
 
                /// <summary>
@@ -717,7 +850,6 @@ namespace System.Data {
 
                        ArrayList List = new ArrayList ();
                        foreach (DataRow Row in Rows) {
-                               
                                if (Expression.Test (Row))
                                        List.Add (Row);
                        }
@@ -782,7 +914,10 @@ namespace System.Data {
                {
                        //LAMESPEC: spec says concat the two. impl puts a 
                        //plus sign infront of DisplayExpression
-                       return TableName + " + " + DisplayExpression;
+                       string retVal = TableName;
+                       if(DisplayExpression != null && DisplayExpression != "")
+                               retVal += " + " + DisplayExpression;
+                       return retVal;
                }
 
                
index 76c68ac2aa1188e15de352453a9dd4e9d81b46e6..9298d3635743adf4e534f6c2a26193c03a8ed044 100644 (file)
@@ -186,10 +186,9 @@ namespace System.Data {
                internal void UpdatePrimaryKey ()
                {
                        _isPrimaryKey = __isPrimaryKey;
-                       if (_isPrimaryKey) {
-                               foreach (DataColumn Col in _dataColumns)
-                                       Col.SetUnique();
-                       }
+                       foreach (DataColumn Col in _dataColumns)
+                               Col.SetUnique();
+                       
                }
 
                internal static void SetAsPrimaryKey(ConstraintCollection collection, UniqueConstraint newPrimaryKey)
@@ -362,7 +361,6 @@ namespace System.Data {
                        DataTable tbl = _dataTable;
 
                        //TODO: Investigate other ways of speeding up the validation work below.
-                       //FIXME: This only works when only one DataColumn has been specified.
 
                        //validate no duplicates exists.
                        //Only validate when there are at least 2 rows
@@ -372,31 +370,23 @@ namespace System.Data {
                                //original.
                                DataRow[] rows = new DataRow [tbl.Rows.Count];
                                tbl.Rows.CopyTo (rows, 0);
-                               ArrayList clonedDataList = new ArrayList (rows);
-
-                               ArrayList newDataList = new ArrayList();
-
-                               //copy to array list only the column we are interested in.
-                               foreach (DataRow row in clonedDataList) {
-                                       
-                                       object colvalue = row[this._dataColumns[0]];
-                                       if (colvalue == DBNull.Value)
-                                               newDataList.Add (null);
-                                       else
-                                               newDataList.Add (colvalue);
-                               }
                                
-                               //sort ArrayList and check adjacent values for duplicates.
-                               newDataList.Sort ();
-
-                               for (int i = 0 ; i < newDataList.Count - 1 ; i++) 
-                                       
-                                       if (newDataList [i] == null) {
-                                               if (newDataList [i+1] == null)
-                                                       throw new InvalidConstraintException (String.Format ("Column '{0}' contains non-unique values", this._dataColumns[0]));
-                                       }
-                                       else if (newDataList[i].Equals (newDataList[i+1])) 
-                                               throw new InvalidConstraintException (String.Format ("Column '{0}' contains non-unique values", this._dataColumns[0]));
+                               Array.Sort(rows, new RowsComparer(this));
+                               for (int i = 0 ; i < rows.Length - 1 ; i++) 
+                               {\r
+                                       bool match = true;\r
+                                       // check if the values in the constraints columns are equal\r
+                                       for (int j = 0; j < _dataColumns.Length; j++)\r
+                                       {\r
+                                               if (!rows[i][_dataColumns[j]].Equals(rows[i + 1][_dataColumns[j]]))\r
+                                               {\r
+                                                       match = false;\r
+                                                       break;\r
+                                               }       \r
+                                       }\r
+                                       if (match)\r
+                                               throw new InvalidConstraintException (String.Format ("Column '{0}' contains non-unique values", this._dataColumns[0]));                                 
+                               }
                        }
 
 
@@ -421,34 +411,40 @@ namespace System.Data {
 
                        DataTable tbl = _dataTable;
                        bool isValid;
+                       object[] rowVals = new object[_dataColumns.Length];
+                       for (int i = 0; i < _dataColumns.Length; i++)
+                       {
+                               if(row.HasVersion(DataRowVersion.Proposed))
+                                       rowVals[i] = row[_dataColumns[i], DataRowVersion.Proposed];
+                               else
+                                       rowVals[i] = row[_dataColumns[i], DataRowVersion.Current];
+                       }
+                       
                        foreach(DataRow compareRow in tbl.Rows)
                        {
-                               isValid = false;
-                               //skip if it is the same row to be validated
-                               if(!row.Equals(compareRow))
+                               if (compareRow.RowState != DataRowState.Deleted)
                                {
-                                       //FIXME: should we compare to compareRow[DataRowVersion.Current]?
-                                       //FIXME: We need to compare to all columns the constraint is set to.
-                                       object rowVal;
-                                       for (int i = 0; i < _dataColumns.Length; i++)
+                                       isValid = false;
+                                       //skip if it is the same row to be validated
+                                       if(!row.Equals(compareRow))
                                        {
-                                               if(row.HasVersion(DataRowVersion.Proposed))
-                                                       rowVal = row[_dataColumns[i], DataRowVersion.Proposed];
-                                               else
-                                                       rowVal = row[_dataColumns[i], DataRowVersion.Current];
-                                               
-                                               // if the values in the row are not equal to the values of
-                                               // the original row from the table we can move to the next row.
-                                               if(!rowVal.Equals( compareRow[_dataColumns[i]]))
+                                               //FIXME: should we compare to compareRow[DataRowVersion.Current]?
+                                               //FIXME: We need to compare to all columns the constraint is set to.
+                                               for (int i = 0; i < _dataColumns.Length; i++)
                                                {
-                                                       isValid = true;
-                                                       break;
+                                                       // if the values in the row are not equal to the values of
+                                                       // the original row from the table we can move to the next row.
+                                                       if(!rowVals[i].Equals( compareRow[_dataColumns[i]]))
+                                                       {
+                                                               isValid = true;
+                                                               break;
+                                                       }
                                                }
-                                       }
                                
-                                       if (!isValid)
-                                               throw new ConstraintException(GetErrorMessage(compareRow));
+                                               if (!isValid)
+                                                       throw new ConstraintException(GetErrorMessage(compareRow));
 
+                                       }
                                }
 
                        }
@@ -469,7 +465,43 @@ namespace System.Data {
                        string colStr = sb.ToString();
                        return "Column '" + colStr + "' is constrained to be unique.  Value '" + valStr + "' is already present.";
                }
+               
+               // generates a hash key for a given row based on the constraints columns.
+               internal int CalcHashValue(DataRow row)
+               {
+                       object o;
+                       int retVal = 0;
+                       for (int i = 0; i < _dataColumns.Length; i++)
+                       {
+                               o = row[_dataColumns[i]];
+                               if (o != null)
+                                       retVal += o.GetHashCode();
+                       }
+                       return retVal;
+               }
 
                #endregion // Methods
+
+               private class RowsComparer : IComparer
+               {
+                       private UniqueConstraint _uc;
+                       
+                       public RowsComparer(UniqueConstraint uc)
+                       {
+                               _uc = uc;
+                       }
+
+                       public int Compare(object o1, object o2)
+                       {
+                               DataRow row1 = (DataRow) o1;
+                               DataRow row2 = (DataRow) o2;
+                               int val1 = _uc.CalcHashValue(row1);
+                               int val2 = _uc.CalcHashValue(row2);
+                               
+                               return val1 - val2;
+                       }
+               }
        }
+
+       
 }