importing messaging-2008 branch to trunk [continued]
[mono.git] / mcs / class / System.Data / System.Data / Constraint.cs
index d6a983a1072771564b4faf59273089ea9b847f04..6ca051632d062471ca710c14788a03b7c2794926 100644 (file)
@@ -5,7 +5,7 @@
 //     Franklin Wise <gracenote@earthlink.net>
 //     Daniel Morgan
 //      Tim Coleman (tim@timcoleman.com)
-//   
+//
 //
 // (C) Ximian, Inc. 2002
 // Copyright (C) Tim Coleman, 2002
 // distribute, sublicense, and/or sell copies of the Software, and to
 // permit persons to whom the Software is furnished to do so, subject to
 // the following conditions:
-// 
+//
 // The above copyright notice and this permission notice shall be
 // included in all copies or substantial portions of the Software.
-// 
+//
 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
@@ -39,19 +39,28 @@ using System.Collections;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
 using System.Runtime.Serialization;
+using System.Data.Common;
 
 namespace System.Data {
        [Serializable]
        internal delegate void DelegateConstraintNameChange (object sender, string newName);
 
-       [DefaultProperty ("ConstraintName")]    
+       [DefaultProperty ("ConstraintName")]
+#if !NET_2_0
        [Serializable]
+#endif
        [TypeConverterAttribute (typeof (ConstraintConverter))]
-       public abstract class Constraint 
-       {
-               internal event DelegateConstraintNameChange BeforeConstraintNameChange;
+       public abstract class Constraint {
+               static readonly object beforeConstraintNameChange = new object ();
+
+               EventHandlerList events = new EventHandlerList ();
 
-               //if constraintName is not set then a name is 
+               internal event DelegateConstraintNameChange BeforeConstraintNameChange {
+                       add { events.AddHandler (beforeConstraintNameChange, value); }
+                       remove { events.RemoveHandler (beforeConstraintNameChange, value); }
+               }
+
+               //if constraintName is not set then a name is
                //created when it is added to
                //the ConstraintCollection
                //it can not be set to null, empty or duplicate
@@ -66,10 +75,10 @@ namespace System.Data {
 
                DataSet dataSet;
 
-               protected Constraint () 
+               protected Constraint ()
                {
                        dataSet = null;
-                       _properties = new PropertyCollection();
+                       _properties = new PropertyCollection ();
                }
 
                [CLSCompliant (false)]
@@ -78,68 +87,91 @@ namespace System.Data {
                }
 
                [DataCategory ("Data")]
+#if !NET_2_0
                [DataSysDescription ("Indicates the name of this constraint.")]
+#endif
                [DefaultValue ("")]
                public virtual string ConstraintName {
-                       get{ return _constraintName == null ? "" : _constraintName; } 
-                       set{
+                       get { return _constraintName == null ? "" : _constraintName; }
+                       set {
                                //This should only throw an exception when it
                                //is a member of a ConstraintCollection which
                                //means we should let the ConstraintCollection
                                //handle exceptions when this value changes
-                               _onConstraintNameChange(value);
+                               _onConstraintNameChange (value);
                                _constraintName = value;
                        }
                }
 
                [Browsable (false)]
                [DataCategory ("Data")]
+#if !NET_2_0
                [DataSysDescription ("The collection that holds custom user information.")]
+#endif
                public PropertyCollection ExtendedProperties {
                        get { return _properties; }
                }
 
+#if !NET_2_0
                [DataSysDescription ("Indicates the table of this constraint.")]
+#endif
                public abstract DataTable Table {
                        get;
                }
 
                internal ConstraintCollection ConstraintCollection {
-                       get{ return _constraintCollection; }
-                       set{ _constraintCollection = value; }
+                       get { return _constraintCollection; }
+                       set { _constraintCollection = value; }
                }
-               
+
                private void _onConstraintNameChange (string newName)
                {
-                       if (null != BeforeConstraintNameChange)
-                       {
-                               BeforeConstraintNameChange (this, newName);
-                       }
+                       DelegateConstraintNameChange eh = events [beforeConstraintNameChange] as DelegateConstraintNameChange;
+                       if (eh != null)
+                               eh (this, newName);
                }
 
                //call once before adding a constraint to a collection
                //will throw an exception to prevent the add if a rule is broken
-               internal virtual void AddToConstraintCollectionSetup (ConstraintCollection collection)
+               internal abstract void AddToConstraintCollectionSetup (ConstraintCollection collection);
+
+               internal abstract bool IsConstraintViolated ();
+
+               internal static void ThrowConstraintException ()
                {
+                       throw new ConstraintException("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");
+               }
+
+               bool initInProgress = false;
+               internal virtual bool InitInProgress {
+                       get { return initInProgress; }
+                       set { initInProgress = value; }
                }
-                                       
-               internal virtual void AssertConstraint ()
+
+               internal virtual void FinishInit (DataTable table)
                {
                }
-               
-               internal virtual void AssertConstraint (DataRow row)
+
+               internal void AssertConstraint ()
                {
+                       // The order is important.. IsConstraintViolated fills the RowErrors if it detects
+                       // a violation
+                       if (!IsConstraintViolated ())
+                               return;
+                       if (Table._duringDataLoad || (Table.DataSet != null && !Table.DataSet.EnforceConstraints))
+                               return;
+                       ThrowConstraintException ();
                }
 
+               internal abstract void AssertConstraint (DataRow row);
+
                internal virtual void RollbackAssert (DataRow row)
                {
                }
 
                //call once before removing a constraint to a collection
                //can throw an exception to prevent the removal
-               internal virtual void RemoveFromConstraintCollectionCleanup (ConstraintCollection collection)
-               {
-               }
+               internal abstract void RemoveFromConstraintCollectionCleanup (ConstraintCollection collection);
 
                [MonoTODO]
                protected void CheckStateForProperty ()
@@ -152,68 +184,35 @@ namespace System.Data {
                        this.dataSet = dataSet;
                }
 
-               internal Index Index
+               internal void SetExtendedProperties (PropertyCollection properties)
                {
-                       get {
-                               return _index;
-                       }
-                       set {
-                               _index = value;
-                       }
+                       _properties = properties;
                }
 
-               internal void UpdateIndex (DataRow row)
-               {
-                       if (row.RowState == DataRowState.Detached || row.RowState == DataRowState.Unchanged)
-                               Index.Insert (new Node (row), DataRowVersion.Default);
-                       else if ((row.RowState == DataRowState.Modified) || (row.RowState == DataRowState.Added)) {
-                               // first we check if the values of the key changed.
-                               bool keyChanged = false;
-                               for (int i = 0; i < Index.Columns.Length; i++) {
-                                       if (row[Index.Columns[i], DataRowVersion.Default] != row[Index.Columns[i], DataRowVersion.Current]) {
-                                               keyChanged = true;
-                                       }
-                               }
-                               // if key changed we first try to insert a new node 
-                               // and,if succeded, we delete the row's old node.
-                               if (keyChanged) 
-                               {
-                                       // insert new node for the row
-                                       // note : may throw if not succeded
-                                       Index.Insert (new Node (row), DataRowVersion.Default);
-
-                                       // delete the row's node
-                                       Index.Delete(row);                                      
+               internal Index Index {
+                       get { return _index; }
+                       set {
+                               if (_index != null) {
+                                       _index.RemoveRef();
+                                       Table.DropIndex(_index);
                                }
-                       }
-               }
 
-               internal void RollbackIndex (DataRow row)
-               {
-                       Node n = Index.Find(row, DataRowVersion.Default);
-                       if ( n == null)
-                               throw new ConstraintException("Row was not found in constraint index");
-
-                       // first remove the node inserted as a result of last AssertConstraint on the row 
-                       Index.Delete(n);
-                       
-                       // if the row is not detached we should add back to the index 
-                       // node corresponding to row value before AssertConstraint was called
-                       if(row.RowState != DataRowState.Detached){
-                               // since index before we updated index was ok, insert should always suceed
-                               // maybe we still need to try/catch here
-                               Index.Insert(new Node(row), DataRowVersion.Current);
+                               _index = value;
+
+                               if (_index != null)
+                                       _index.AddRef();
                        }
                }
 
+               internal abstract bool IsColumnContained (DataColumn column);
+               internal abstract bool CanRemoveFromCollection (ConstraintCollection col, bool shouldThrow);
 
                /// <summary>
-               /// Gets the ConstraintName, if there is one, as a string. 
+               /// Gets the ConstraintName, if there is one, as a string.
                /// </summary>
-               public override string ToString () 
+               public override string ToString ()
                {
                        return _constraintName == null ? "" : _constraintName;
                }
-
        }
 }