merging the Mainsoft branch to the trunk
authorKonstantin Triger <kostat@mono-cvs.ximian.com>
Sun, 15 May 2005 23:15:37 +0000 (23:15 -0000)
committerKonstantin Triger <kostat@mono-cvs.ximian.com>
Sun, 15 May 2005 23:15:37 +0000 (23:15 -0000)
svn path=/trunk/mcs/; revision=44547

87 files changed:
mcs/class/System.Data/ChangeLog
mcs/class/System.Data/Mono.Data.SqlExpressions/Aggregation.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/ArithmeticExpressions.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/BooleanExpressions.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/ChangeLog
mcs/class/System.Data/Mono.Data.SqlExpressions/ColumnReference.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/Comparison.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/Expressions.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/Functions.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/In.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/Like.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/Literal.cs
mcs/class/System.Data/Mono.Data.SqlExpressions/Numeric.cs
mcs/class/System.Data/System.Data.Common/CatalogLocation.cs
mcs/class/System.Data/System.Data.Common/ChangeLog
mcs/class/System.Data/System.Data.Common/DataContainer.cs
mcs/class/System.Data/System.Data.Common/DbCommand.cs
mcs/class/System.Data/System.Data.Common/DbCommandBuilder.cs
mcs/class/System.Data/System.Data.Common/DbCommandSet.cs
mcs/class/System.Data/System.Data.Common/DbConnection.cs
mcs/class/System.Data/System.Data.Common/DbConvert.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbDataAdapter.cs
mcs/class/System.Data/System.Data.Common/DbDataPermissionAttribute.cs
mcs/class/System.Data/System.Data.Common/DbDataReader.cs
mcs/class/System.Data/System.Data.Common/DbDataRecord.cs
mcs/class/System.Data/System.Data.Common/DbDataSourceEnumerator.cs
mcs/class/System.Data/System.Data.Common/DbEnumerator.cs
mcs/class/System.Data/System.Data.Common/DbMetaDataCache.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbParameter.cs
mcs/class/System.Data/System.Data.Common/DbParameterCollection.cs
mcs/class/System.Data/System.Data.Common/DbProviderFactory.cs
mcs/class/System.Data/System.Data.Common/DbProviderSupportedClasses.cs
mcs/class/System.Data/System.Data.Common/DbTable.cs
mcs/class/System.Data/System.Data.Common/DbTransaction.cs
mcs/class/System.Data/System.Data.Common/DbTypes.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/ExceptionHelper.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/Index.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/Key.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/RecordCache.cs
mcs/class/System.Data/System.Data.Common/SchemaLocation.cs
mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBCommand.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBConnection.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBParameter.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDataReader.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractTransaction.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase.jvm/DbPortResolver.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase.jvm/ReaderCache.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.ProviderBase/DbStringManager.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.dll.sources
mcs/class/System.Data/System.Data/AcceptRejectRule.cs
mcs/class/System.Data/System.Data/ChangeLog
mcs/class/System.Data/System.Data/ConflictOptions.cs
mcs/class/System.Data/System.Data/Constraint.cs
mcs/class/System.Data/System.Data/ConstraintCollection.cs
mcs/class/System.Data/System.Data/DataColumn.cs
mcs/class/System.Data/System.Data/DataColumnCollection.cs
mcs/class/System.Data/System.Data/DataColumnPropertyDescriptor.cs
mcs/class/System.Data/System.Data/DataRelation.cs
mcs/class/System.Data/System.Data/DataRelationCollection.cs
mcs/class/System.Data/System.Data/DataRelationPropertyDescriptor.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data/DataRow.cs
mcs/class/System.Data/System.Data/DataRowCollection.cs
mcs/class/System.Data/System.Data/DataRowView.cs
mcs/class/System.Data/System.Data/DataSet.cs
mcs/class/System.Data/System.Data/DataTable.cs
mcs/class/System.Data/System.Data/DataTableCollection.cs
mcs/class/System.Data/System.Data/DataView.cs
mcs/class/System.Data/System.Data/DataViewManager.cs
mcs/class/System.Data/System.Data/DataViewRowState.cs
mcs/class/System.Data/System.Data/ExpressionElement.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data/FillOptions.cs
mcs/class/System.Data/System.Data/ForeignKeyConstraint.cs
mcs/class/System.Data/System.Data/IDataReader2.cs
mcs/class/System.Data/System.Data/IDataRecord2.cs
mcs/class/System.Data/System.Data/ISafeDataRecord.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data/Index.cs
mcs/class/System.Data/System.Data/IsolationLevel.cs
mcs/class/System.Data/System.Data/Locale.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data/MergeManager.cs
mcs/class/System.Data/System.Data/RelatedDataView.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data/Res.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data/UniqueConstraint.cs
mcs/class/System.Data/System.Data/UpdateOptions.cs
mcs/class/System.Data/System.Data/XmlConstants.cs
mcs/class/System.Data/System.Data/XmlDataInferenceLoader.cs
mcs/class/System.Data/System.Data/XmlDataReader.cs
mcs/class/System.Data/System.Data/XmlDiffLoader.cs

index 591f498bc281006ae143d91e688cbf4d9b6eb201..f87f80143d22497ef786e58c7bcd217e2e4e5d19 100644 (file)
 
        * System.Data_test.dll.sources: Added DataTableLoadRowTest.cs.
 
+2005-01-05  Konstantin Triger <kostat@mainsoft.com>
+
+       * DbCommandOptionalFeatures.cs, DbConnectionString.cs, DbConnectionOptions.cs: revert to r43344
+
+2005-01-05  Konstantin Triger <kostat@mainsoft.com>
+       
+       * DbDataAdapter.cs: Rostore the Dispose logic
+
+2005-04-28  Konstantin Triger <kostat@mainsoft.com>  Sureshkumar T  <tsureshkumar@novell.com>
+
+       * DataView.cs: Nullify an index when Closed
+
+2005-04-27  Konstantin Triger <kostat@mainsoft.com>
+
+       * DataRow.cs: Removed unneeded check of RowState
+
+2005-04-27  Konstantin Triger <kostat@mainsoft.com>
+
+       * ConstraintCollection: throw DuplicateException only if names match exactly with Table's locale
+
 2005-04-08  Raja R Harinath  <rharinath@novell.com>
 
        * Makefile (EXTRA_DISTFILES): Add app_test_2.0.config.
index 63deec717f01a055afcd28e1ee6da8c3876857a1..ab6d0028d91b1e64ea044a6b3c50aaeb422aae5d 100644 (file)
@@ -97,10 +97,15 @@ namespace Mono.Data.SqlExpressions {
                        }
                        
                        if (result == null)
-                               result = 0;
+                               result = DBNull.Value;
                                
                        return result;
                }
+
+               override public bool DependsOn(DataColumn other)
+               {
+                       return column.DependsOn(other);
+               }
                
                private void Aggregate (IConvertible val)
                {
index cce4350037c834861058cf3b25f97f73cd6fb1ee..ca3452b7b64f549af7225add8c618a03dfb77d85 100644 (file)
@@ -50,7 +50,11 @@ namespace Mono.Data.SqlExpressions {
                override public object Eval (DataRow row)
                {
                        object obj1 = expr1.Eval (row);
+                       if (obj1 == DBNull.Value)
+                               return obj1;
                        object obj2 = expr2.Eval (row);
+                       if (obj2 == DBNull.Value)
+                               return obj2;
                
                        if (op == Operation.ADD && (obj1 is string || obj2 is string))
                                return (obj1 != null ? obj1.ToString () : String.Empty) + (obj2 != null ? obj2.ToString () : String.Empty);
index 6548e41da8c5789c39f171be72f00890650e1dc7..04f05c0b31334abb07cda6e0d538c09c7f2fa60d 100644 (file)
@@ -40,7 +40,10 @@ namespace Mono.Data.SqlExpressions {
        
                override public object Eval (DataRow row)
                {
-                       return !((bool)expr.Eval (row));
+                       object o = expr.Eval (row);
+                       if (o == DBNull.Value)
+                               return o;
+                       return !((bool)o);
                }
 
                override public bool EvalBoolean (DataRow row)
index c2effbe8714b440a5bbda5b803ad7ab1db368883..25234b12b86657478237277786a9305afe2bbcc0 100644 (file)
@@ -1,3 +1,7 @@
+2005-05-02 Konstantin Triger <kostat@mainsoft.com>
+
+        * IExpression interface: Added DependsOn(DataColumn) method, which checks whether the Expression contains a specific column
+
 2005-04-26 Gonzalo Paniagua Javier <gonzalo@ximian.com>
 
        * Tokenizer.cs: make it not rely in exceptions being thrown to know that
index ff365875773c1d2ee90f6a4ee2179adf9d049157..488793285ee4fa434dd2f6ca79905842a6d98cac 100644 (file)
@@ -100,7 +100,7 @@ namespace Mono.Data.SqlExpressions {
                        switch (refTable) {
                        case ReferencedTable.Self:
                        default:
-                               DataRow[] rows = new DataRow [row.Table.Rows.Count];
+                               DataRow[] rows = row.Table.NewRowArray(row.Table.Rows.Count);
                                row.Table.Rows.CopyTo (rows, 0);
                                return rows;
                                
@@ -153,5 +153,10 @@ namespace Mono.Data.SqlExpressions {
                        }
                        return Unify (val);
                }
+
+               override public bool DependsOn(DataColumn other)
+               {
+                       return refTable == ReferencedTable.Self && columnName == other.ColumnName;
+               }
        }
 }
index 7c3b69547dce993402615381073ceb1ffa62efc5..e2ddfc6400259bacf07b1f507a5eb6722a1fdc67 100644 (file)
@@ -54,15 +54,16 @@ namespace Mono.Data.SqlExpressions {
                                        return (op == Operation.NE);
                        }
 
-                       switch(Compare (o1, o2, row.Table.CaseSensitive)) {
-                       case -1:
+                       int result = Compare (o1, o2, row.Table.CaseSensitive);
+                       if (result < 0) {
                                return (op == Operation.NE || op == Operation.LE || op == Operation.LT);
-                       case 0:
-                       default:
-                               return (op == Operation.EQ || op == Operation.LE || op == Operation.GE);
-                       case 1:
+                       }
+                       if (result > 0) {
                                return (op == Operation.NE || op == Operation.GE || op == Operation.GT);
                        }
+                       // result == 0
+                       return (op == Operation.EQ || op == Operation.LE || op == Operation.GE);
+                       
                }
                        
                internal static int Compare (IComparable o1, IComparable o2, bool caseSensitive)
index 8487204826b272f0b6e47434698a28c9705693fd..5ef521505e50135c456d75c7475981a0c7c3aef9 100644 (file)
@@ -37,12 +37,14 @@ using System.Data;
 namespace Mono.Data.SqlExpressions {
        internal interface IExpression {
                object Eval (DataRow row);
+               bool DependsOn(DataColumn other);
 
                bool EvalBoolean (DataRow row);
        }
 
        internal abstract class BaseExpression : IExpression {
                public abstract object Eval (DataRow row);
+               public abstract bool DependsOn(DataColumn other);
 
                public virtual bool EvalBoolean (DataRow row)
                {
@@ -58,6 +60,10 @@ namespace Mono.Data.SqlExpressions {
                {
                        expr = e;
                }
+
+               override public bool DependsOn(DataColumn other) {
+                       return expr.DependsOn(other);
+               }
        }
        
        internal abstract class BinaryExpression : BaseExpression {
@@ -68,6 +74,10 @@ namespace Mono.Data.SqlExpressions {
                        expr1 = e1;
                        expr2 = e2;
                }
+               override public bool DependsOn(DataColumn other)
+               {
+                       return expr1.DependsOn(other) || expr2.DependsOn(other);
+               }
        }
        
        internal enum Operation {
index 92c826902f19e5b4f211371ff9d2ac0e2dda5f57..27cd1e9fead2bf6ac6378ea98a041782dc00becc 100644 (file)
@@ -45,7 +45,10 @@ namespace Mono.Data.SqlExpressions {
                
                override public object Eval (DataRow row)
                {
-                       bool val = (bool)expr.Eval (row);
+                       object o = expr.Eval (row);
+                       if (o == DBNull.Value)
+                               return o;
+                       bool val = (bool)o;
                        return (val ? trueExpr.Eval (row) : falseExpr.Eval (row));
                }
        }
@@ -79,7 +82,7 @@ namespace Mono.Data.SqlExpressions {
                {
                        object val = expr.Eval (row);
                        
-                       if (val.GetType () == targetType)
+                       if (val == DBNull.Value || val.GetType () == targetType)
                                return val;
 
                        //--> String is always allowed                  
index 754901dd9988d7c3e17c677b059bccbae398e571..3d20472b515d79ad2ef99d2a6d47ce592b768c35 100644 (file)
@@ -45,7 +45,10 @@ namespace Mono.Data.SqlExpressions {
        
                override public object Eval (DataRow row)
                {
-                       IComparable val = (IComparable)expr.Eval (row);
+                       object o = expr.Eval (row);
+                       if (o == DBNull.Value)
+                               return o;
+                       IComparable val = o as IComparable;
                        if (val == null)
                                return false;
 
index 7cf79aeca6d979666f4e03ab1b8ec43a9997e2b6..80f986be033611aedee1a8c8e1d8a69cb3424b5c 100644 (file)
@@ -60,7 +60,10 @@ namespace Mono.Data.SqlExpressions {
 
                override public object Eval (DataRow row)
                {
-                       string str = (string)expr.Eval (row);
+                       object o = expr.Eval (row);
+                       if (o == DBNull.Value)
+                               return o;
+                       string str = (string)o;
                        string pattern = this.pattern;
                        if (!row.Table.CaseSensitive) {
                                str = str.ToLower();
index 1ab79e9b163b89de08be269260284020a7186ea6..0936bbbcb87c75cd32273e2b94f0ac4756068fea 100644 (file)
@@ -46,5 +46,10 @@ namespace Mono.Data.SqlExpressions {
                {
                        return val;
                }
+
+               override public bool DependsOn(DataColumn other)
+               {
+                       return false;
+               }
        }
 }
index 0f8fd67469a1d05e5d550f56509b997ddc104f44..b0b0808002d8c4a8745ed6d06f99bc32e5b0a115 100644 (file)
@@ -61,43 +61,51 @@ namespace Mono.Data.SqlExpressions {
                }
                
                //(note: o1 and o2 must both be of type Int32/Int64/Decimal/Double)
-               internal static void ToSameType (ref IConvertible o1, ref IConvertible o2)
+               internal static TypeCode ToSameType (ref IConvertible o1, ref IConvertible o2)
                {
                        TypeCode tc1 = o1.GetTypeCode();
                        TypeCode tc2 = o2.GetTypeCode();
                        
                        if (tc1 == tc2)
-                               return;
+                               return tc1;
+
+                       if (tc1 == TypeCode.DBNull || tc2 == TypeCode.DBNull)
+                               return TypeCode.DBNull;
+
 
                        // is it ok to make such assumptions about the order of an enum?
                        if (tc1 < tc2)
-                               o1 = (IConvertible) Convert.ChangeType (o1, tc2);
+                       {
+                               o1 = (IConvertible)Convert.ChangeType (o1, tc2);
+                               return tc2;
+                       }
                        else
-                               o2 = (IConvertible) Convert.ChangeType (o2, tc1);
+                       {
+                               o2 = (IConvertible)Convert.ChangeType (o2, tc1);
+                               return tc1;
+                       }
                }
                
                internal static IConvertible Add (IConvertible o1, IConvertible o2)
                {
-                       ToSameType (ref o1, ref o2);
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
-                               return (int)o1 + (int)o2;
+                               return (long)((int)o1 + (int)o2);
                        case TypeCode.Int64:
                                return (long)o1 + (long)o2;
                        case TypeCode.Double:
                                return (double)o1 + (double)o2;
                        case TypeCode.Decimal:
                                return (decimal)o1 + (decimal)o2;
+                       default:
+                               return DBNull.Value;
                        }
                }
                
                internal static IConvertible Subtract (IConvertible o1, IConvertible o2)
                {
-                       ToSameType (ref o1, ref o2);
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
                                return (int)o1 - (int)o2;
                        case TypeCode.Int64:
                                return (long)o1 - (long)o2;
@@ -105,15 +113,15 @@ namespace Mono.Data.SqlExpressions {
                                return (double)o1 - (double)o2;
                        case TypeCode.Decimal:
                                return (decimal)o1 - (decimal)o2;
+                       default:
+                               return DBNull.Value;
                        }
                }
                
                internal static IConvertible Multiply (IConvertible o1, IConvertible o2)
                {
-                       ToSameType (ref o1, ref o2);
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
                                return (int)o1 * (int)o2;
                        case TypeCode.Int64:
                                return (long)o1 * (long)o2;
@@ -121,15 +129,15 @@ namespace Mono.Data.SqlExpressions {
                                return (double)o1 * (double)o2;
                        case TypeCode.Decimal:
                                return (decimal)o1 * (decimal)o2;
+                       default:
+                               return DBNull.Value;
                        }
                }
                
                internal static IConvertible Divide (IConvertible o1, IConvertible o2)
                {
-                       ToSameType (ref o1, ref o2);
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
                                return (int)o1 / (int)o2;
                        case TypeCode.Int64:
                                return (long)o1 / (long)o2;
@@ -137,15 +145,15 @@ namespace Mono.Data.SqlExpressions {
                                return (double)o1 / (double)o2;
                        case TypeCode.Decimal:
                                return (decimal)o1 / (decimal)o2;
+                       default:
+                               return DBNull.Value;
                        }
                }
                
                internal static IConvertible Modulo (IConvertible o1, IConvertible o2)
                {
-                       ToSameType (ref o1, ref o2);
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
                                return (int)o1 % (int)o2;
                        case TypeCode.Int64:
                                return (long)o1 % (long)o2;
@@ -153,6 +161,8 @@ namespace Mono.Data.SqlExpressions {
                                return (double)o1 % (double)o2;
                        case TypeCode.Decimal:
                                return (decimal)o1 % (decimal)o2;
+                       default:
+                               return DBNull.Value;
                        }
                }
                
@@ -160,7 +170,6 @@ namespace Mono.Data.SqlExpressions {
                {
                        switch (o.GetTypeCode()) {
                        case TypeCode.Int32:
-                       default:
                                return -((int)o);
                        case TypeCode.Int64:
                                return -((long)o);
@@ -168,14 +177,15 @@ namespace Mono.Data.SqlExpressions {
                                return -((double)o);
                        case TypeCode.Decimal:
                                return -((decimal)o);
+                       default:
+                               return DBNull.Value;
                        }
                }
                
                internal static IConvertible Min (IConvertible o1, IConvertible o2)
                {
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
                                return System.Math.Min ((int)o1, (int)o2);
                        case TypeCode.Int64:
                                return System.Math.Min ((long)o1, (long)o2);
@@ -183,14 +193,15 @@ namespace Mono.Data.SqlExpressions {
                                return System.Math.Min ((double)o1, (double)o2);
                        case TypeCode.Decimal:
                                return System.Math.Min ((decimal)o1, (decimal)o2);
+                       default:
+                               return DBNull.Value;
                        }
                }
 
                internal static IConvertible Max (IConvertible o1, IConvertible o2)
                {
-                       switch (o1.GetTypeCode()) {
+                       switch (ToSameType (ref o1, ref o2)) {
                        case TypeCode.Int32:
-                       default:
                                return System.Math.Max ((int)o1, (int)o2);
                        case TypeCode.Int64:
                                return System.Math.Max ((long)o1, (long)o2);
@@ -198,6 +209,8 @@ namespace Mono.Data.SqlExpressions {
                                return System.Math.Max ((double)o1, (double)o2);
                        case TypeCode.Decimal:
                                return System.Math.Max ((decimal)o1, (decimal)o2);
+                       default:
+                               return DBNull.Value;
                        }
                }
        }
index 8a0613f2549c59fdf1136a905791515cb0681041..3d3b0adb43f104e15a06d9b21343d9d7552ac760 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data.Common {
        public enum CatalogLocation 
index b145a8ff96221b0dcaf083415bab82a4e575cf1a..c89271f1bb289945b870ee0193292b260bb334da 100755 (executable)
@@ -1,3 +1,30 @@
+2005-05-16 Konstantin Triger <kostat@mainsoft.com>
+
+       * Index.cs: validation that the updated row belongs to the index
+
+2005-05-02 Konstantin Triger <kostat@mainsoft.com>
+
+       * DataContainer.cs: 
+               Added CharDataContainer, SByteDataContainer, UInt16DataContainer, UInt32DataContainer, UInt64DataContainer, DateTimeDataContainer, DecimalDataContainer
+               SetItemFromDataRecord: Changed to work with ISafeDataRecord or through GetValue to enable conversion
+               return DBNull.Value when the stored value is null
+       
+       * DbDataAdapter.cs:
+               Ensure correct order for LoadDataRow
+               Fixing schema creation
+               Use NewRowArray API
+       
+       * DbEnumerator.cs:
+               LoadSchema: Retrieve needed fields only
+       
+       * RecordCache.cs:
+               Added Rows-to-Records mapping
+               Added ReadIDataRecord method for correct handling of default/auto increment values
+       
+       * Added Index.cs: Index implementation
+       * Added Key.cs: Index descriptor implementation
+
+
 2005-04-27  Sureshkumar T  <tsureshkumar@novell.com>
 
        * DbDataReader.cs: Added static method to construct the schema
 
 2003-10-22  Eran Domb  <erand@miansoft.com>
 
-       * DbDataAdapter.cs (Fill): add only the mapped column to the dataTable (not all columns of dataReader).\r
-            Also closing the dataReader if an exception is thrown.\r
-       (Fill): the same as above.\r
-       (SetupSchema): in now return string (the table name). \r
-       (GetFillParameters): fix a bug.\r
-       (BuildSchema) \96 it now return Hashtable. Add columns to the table only if there is a mapping. Build an Hashtable that maps the columns from the table to the column from the reader.\r
+       * DbDataAdapter.cs (Fill): add only the mapped column to the dataTable (not all columns of dataReader).
+            Also closing the dataReader if an exception is thrown.
+       (Fill): the same as above.
+       (SetupSchema): in now return string (the table name). 
+       (GetFillParameters): fix a bug.
+       (BuildSchema) \96 it now return Hashtable. Add columns to the table only if there is a mapping. Build an Hashtable that maps the columns from the table to the column from the reader.
        (Update): first open the connection if needed. Catch an exception of the ExecuteQuery.
        
 
index 42c74108b0cb38216523d2f4b7803705e3c112c2..1b190ff15d346a1d8c3eb9b5fcf259f977729914 100644 (file)
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-using System;
-using System.Collections;
-
-namespace System.Data.Common
-{
-       internal abstract class AbstractDataContainer
-       {
-               #region Fields
-
-               BitArray _nullValues;
-               System.Type _type;
-               DataColumn _column;
-
-               #endregion //Fields
-
-               #region Properties
-
-               internal abstract object this[int index] {
-                       get;
-                       set;
-               }
-
-               internal virtual int Capacity {
-                       get { 
-                               return (_nullValues != null) ? _nullValues.Count : 0; 
-                       }
-                       set { 
-                               if (_nullValues == null) {
-                                       _nullValues = new BitArray(value);
-                               }
-                               else {
-                                       _nullValues.Length = value;
-                               }
-                       }
-               }
-
-               internal Type Type {
-                       get {
-                               return _type;
-                       }
-               }
-
-               protected DataColumn Column {
-                       get {
-                               return _column;
-                       }
-               }
-
-               #endregion //Properties
-
-               #region Methods
-
-               internal static AbstractDataContainer CreateInstance(Type type, DataColumn column)
-               {
-                       AbstractDataContainer container;
-                       switch (Type.GetTypeCode(type)) {
-                               case TypeCode.Int16 :
-                                       container = new Int16DataContainer();
-                                       break;
-                               case TypeCode.Int32 : 
-                                       container = new Int32DataContainer();
-                                       break;
-                               case TypeCode.Int64 :
-                                       container = new Int64DataContainer();
-                                       break;
-                               case TypeCode.String :
-                                       container = new StringDataContainer();
-                                       break;
-                               case TypeCode.Boolean:
-                                       container = new BitDataContainer();
-                                       break;
-                               case TypeCode.Byte :
-                                       container = new ByteDataContainer();
-                                       break;
-                               //case TypeCode.Char :
-                               case TypeCode.DateTime :
-                                       container = new DateTimeDataContainer();
-                                       break;
-                               //case TypeCode.Decimal :
-                               case TypeCode.Double :
-                                       container = new DoubleDataContainer();
-                                       break;
-                               //case TypeCode.SByte :
-                               case TypeCode.Single :
-                                       container = new SingleDataContainer();
-                                       break;
-                               //case TypeCode.UInt16 :
-                               //case TypeCode.UInt32 :
-                               //case TypeCode.UInt64 :
-                               default :
-                                       container = new ObjectDataContainer();
-                                       break;
-                       }
-                       container._type = type;
-                       container._column = column;
-                       return container;
-               }
-
-               internal bool IsNull(int index)
-               {
-                       return (_nullValues != null) ? _nullValues[index] : true;
-               }
-
-               internal void SetNullBit(int index,bool isNull)
-               {
-                       _nullValues[index] = isNull;
-               }
-
-               protected void SetNull(int index,bool isNull,bool isDbNull)
-               {
-                       SetNullBit(index,isDbNull);
-                       // this method must be called after setting the value into value array
-                       // otherwise the dafault value will be overriden
-                       if ( isNull ) {
-                               // set the value to default
-                               CopyValue(Column.Table.DefaultValuesRowIndex,index);
-                       }
-               }
-
-               internal void FillValues(int fromIndex)
-               {
-                       for(int i=0; i < Capacity; i++) {
-                               CopyValue(fromIndex,i);
-                               _nullValues[i] = _nullValues[fromIndex];
-                       }
-               }
-
-               internal virtual void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-               {
-                       _nullValues[toIndex] = fromContainer._nullValues[fromIndex];
-               }
-
-               internal virtual void CopyValue(int fromIndex, int toIndex)
-               {
-                       _nullValues[toIndex] = _nullValues[fromIndex];
-               }
-
-               internal virtual void SetItemFromDataRecord(int index, IDataRecord record, int field)
-               {
-                       bool isDbNull = record.IsDBNull(field);
-                       SetNull(index,false,isDbNull);
-               }
-
-               protected  bool CheckAndSetNull( int index, IDataRecord record, int field)
-               {
-                        bool isDbNull = record.IsDBNull(field);
-                        SetNull(index,false,isDbNull);
-                        return isDbNull;               
-               }
-
-               protected int CompareNulls(int index1, int index2)
-               {
-                       bool null1 = IsNull(index1);
-                       bool null2 = IsNull(index2);
-
-                       if ( null1 ^ null2 ) {
-                               return null1 ? -1 : 1;
-                       }
-                       else {
-                               return 0;
-                       }
-               }
-
-               internal abstract int CompareValues(int index1, int index2);
-
-               internal abstract long GetInt64(int index);
-
-               #endregion //Methods
-
-               sealed class Int16DataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       short[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       if (IsNull(index)) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,0);
-                                       }
-                                       else if( value is short ) {
-                                               SetValue(index,(short)value);
-                                       }
-                                       else {
-                                               try {
-                                                       SetValue(index,Convert.ToInt16(value));
-                                               } catch (Exception ex) {
-                                                       throw new ArgumentException (ex.Message, ex);
-                                               }
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new short[value];
-                                       }
-                                       else {
-                                               short[] tmp = new short[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, short value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                       SetValue(index,record.GetInt16(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((Int16DataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               short s1 = _values[index1];
-                               short s2 = _values[index2];
-
-                               if ( s1 == 0 && s2 == 0 ) {
-                                       int cn = CompareNulls(index1, index2);
-                                       return cn;
-                               }
-
-                               bool b1 = IsNull(index1);
-                               bool b2 = IsNull(index2);
-                               
-                               if ( s1 == 0 && b1 ) {
-                                       return -1;
-                               }
-
-                               if ( s2 == 0 && b2 ) {
-                                       return 1;
-                               }
-
-                               if ( s1 <= s2 ) {
-                                       return ( s1 != s2 ) ? -1 : 0;
-                               }
-                               return 1;
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return (long) _values[index];
-                       }
-
-                       #endregion //Methods
-               }
-
-               sealed class Int32DataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       int[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       if (IsNull(index)) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,0);
-                                       }
-                                       else if( value is int ) {
-                                               SetValue(index,(int)value);
-                                       }
-                                       else {
-                                               SetValue(index,Convert.ToInt32(value));
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new int[value];
-                                       }
-                                       else {
-                                               int[] tmp = new int[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, int value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetInt32(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((Int32DataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               int i1 = _values[index1];
-                               int i2 = _values[index2];
-
-                               if ( i1 == 0 && i2 == 0 ) {
-                                       int cn = CompareNulls(index1, index2);
-                                       return cn;
-                               }
-
-                               bool b1 = IsNull(index1);
-                               bool b2 = IsNull(index2);
-                               
-                               if ( i1 == 0 && b1 ) {
-                                       return -1;
-                               }
-
-                               if ( i2 == 0 && b2 ) {
-                                       return 1;
-                               }
-
-                               if ( i1 <= i2 ) {
-                                       return ( i1 != i2 ) ? -1 : 0;
-                               }
-                               return 1;
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return (long) _values[index];
-                       }
-
-                       #endregion //Methods
-               }
-
-               sealed class Int64DataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       long[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       if (IsNull(index)) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,0);
-                                       }
-                                       else if( value is long ) {
-                                               SetValue(index,(long)value);
-                                       }
-                                       else {
-                                               SetValue(index,Convert.ToInt64(value));
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new long[value];
-                                       }
-                                       else {
-                                               long[] tmp = new long[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, long value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetInt64(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((Int64DataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               long l1 = _values[index1];
-                               long l2 = _values[index2];
-
-                               if ( l1 == 0 || l2 == 0 ) {
-                                       int cn = CompareNulls(index1, index2);
-                                       if (cn != 0) {
-                                               return cn;
-                                       }
-                               }
-
-                               if ( l1 <= l2 ) {
-                                       return ( l1 != l2 ) ? -1 : 0;
-                               }
-                               return 1;
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return _values[index];
-                       }
-
-                       #endregion //Methods
-               }
-
-               sealed class SingleDataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       float[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       if (IsNull(index)) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,0);
-                                       }
-                                       else if( value is float ) {
-                                               SetValue(index,(float)value);
-                                       }
-                                       else {
-                                               SetValue(index,Convert.ToSingle(value));
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new float[value];
-                                       }
-                                       else {
-                                               float[] tmp = new float[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, float value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetFloat(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((SingleDataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               float f1 = _values[index1];
-                               float f2 = _values[index2];
-
-                               if ( f1 == 0 || f2 == 0 ) {
-                                       int cn = CompareNulls(index1, index2);
-                                       if (cn != 0) {
-                                               return cn;
-                                       }
-                               }
-
-                               if ( f1 <= f2 ) {
-                                       return ( f1 != f2 ) ? -1 : 0;
-                               }
-                               return 1;
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return Convert.ToInt64(_values[index]);
-                       }
-
-                       #endregion //Methods
-               }
-
-               sealed class DoubleDataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       double[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       if (IsNull(index)) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,0);
-                                       }
-                                       else if( value is double ) {
-                                               SetValue(index,(double)value);
-                                       }
-                                       else {
-                                               SetValue(index,Convert.ToDouble(value));
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new double[value];
-                                       }
-                                       else {
-                                               double[] tmp = new double[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, double value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetDouble(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((DoubleDataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               double d1 = _values[index1];
-                               double d2 = _values[index2];
-
-                               if ( d1 == 0 || d2 == 0 ) {
-                                       int cn = CompareNulls(index1, index2);
-                                       if (cn != 0) {
-                                               return cn;
-                                       }
-                               }
-
-                               if ( d1 <= d2 ) {
-                                       return ( d1 != d2 ) ? -1 : 0;
-                               }
-                               return 1;
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return Convert.ToInt64(_values[index]);
-                       }
-
-                       #endregion //Methods
-               }
-
-               sealed class ByteDataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       byte[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       if (IsNull(index)) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,0);
-                                       }
-                                       else if( value is byte ) {
-                                               SetValue(index,(byte)value);
-                                       }
-                                       else {
-                                               SetValue(index,Convert.ToByte(value));
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new byte[value];
-                                       }
-                                       else {
-                                               byte[] tmp = new byte[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, byte value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetByte(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((ByteDataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               byte b1 = _values[index1];
-                               byte b2 = _values[index2];
-
-                               if ( b1 == 0 || b2 == 0 ) {
-                                       int cn = CompareNulls(index1, index2);
-                                       if (cn != 0) {
-                                               return cn;
-                                       }
-                               }
-
-                               if ( b1 <= b2 ) {
-                                       return ( b1 != b2 ) ? -1 : 0;
-                               }
-                               return 1;
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return (long) _values[index];
-                       }
-
-                       #endregion //Methods
-               }
-
-               sealed class BitDataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       bool[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       bool isNull = IsNull(index);
-                                       if (isNull) {
-                                               return DBNull.Value;
-                                       }
-                                       else {
-                                               return _values[index];
-                                       }
-                               }
-                               set {
-                                       bool isDbNull = (value ==  DBNull.Value);
-                                       if (value == null || isDbNull) {
-                                               SetValue(index,false);
-                                       }
-                                       else if( value is bool ) {
-                                               SetValue(index,(bool)value);
-                                       }
-                                       else {
-                                               SetValue(index,Convert.ToBoolean(value));
-                                       }
-                                       SetNull(index,value == null,isDbNull);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new bool[value];
-                                       }
-                                       else {
-                                               bool[] tmp = new bool[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       private void SetValue(int index, bool value)
-                       {
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetBoolean(field));
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((BitDataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               bool b1 = _values[index1];
-                               bool b2 = _values[index2];
-
-                               if ( b1 ^ b2 ) {
-                                       return b1 ? 1 : -1;
-                               }
-                               
-                               if ( b1 ) {
-                                       return 0;
-                               }
-
-                               return CompareNulls(index1, index2);    
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return Convert.ToInt64(_values[index]);
-                       }
-
-                       #endregion //Methods
-               }
-
-               class ObjectDataContainer : AbstractDataContainer
-               {
-                       #region Fields
-               
-                       object[] _values;
-
-                       #endregion //Fields
-
-                       #region Properties
-
-                       internal override object this[int index] {
-                               get {
-                                       return _values[index];
-                               }
-                               set {
-                                       SetValue(index,value);
-                                       SetNull(index,value == null,value == DBNull.Value);
-                               }
-                       }
-
-                       internal override int Capacity {
-                               set {
-                                       base.Capacity = value;
-                                       if (_values == null) {
-                                               _values = new object[value];
-                                       }
-                                       else {
-                                               object[] tmp = new object[value];
-                                               Array.Copy(_values,0,tmp,0,_values.Length);
-                                               _values = tmp;
-                                       }
-                               }
-                       }
-
-                       #endregion //Properties
-
-                       #region Methods
-                       
-                       protected virtual void SetValue(int index, object value)
-                       {
-                               if(value == null) {
-                                       value = Column.DefaultValue;
-                               }
-                               _values[index] = value;
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller metho
-                               SetValue(index,record.GetValue(field));
-                               base.SetItemFromDataRecord(index,record,field);
-                       }
-
-                       internal override void CopyValue(int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromIndex, toIndex);
-                               _values[toIndex] = _values[fromIndex];
-                       }
-
-                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)
-                       {
-                               base.CopyValue(fromContainer, fromIndex, toIndex);
-                               _values[toIndex] = ((ObjectDataContainer)fromContainer)._values[fromIndex];
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               object obj1 = _values[index1];
-                               object obj2 = _values[index2];
-                               if(obj1 == obj2) {
-                                       return 0;
-                               }
-                               else if (obj1 is IComparable) {
-                                       try {
-                                               return ((IComparable)obj1).CompareTo(obj2);
-                                       }
-                                       catch {
-                                               //just suppress
-                                       }
-
-                                       if (obj2 is IComparable) {
-                                               obj2 = Convert.ChangeType(obj2, Type.GetTypeCode(obj1.GetType()));
-                                               return ((IComparable)obj1).CompareTo(obj2);
-                                       }
-                               }
-
-                               return String.Compare(obj1.ToString(), obj2.ToString());
-                       }
-
-                       internal override long GetInt64(int index)
-                       {
-                               return Convert.ToInt64(_values[index]);
-                       }
-
-                       #endregion //Methods
-        
-               }
-
-               sealed class StringDataContainer : ObjectDataContainer
-               {
-                       #region Methods
-
-                       private void SetValue(int index, string value)
-                       {
-                               if (value != null && Column.MaxLength >= 0 && Column.MaxLength < value.Length ) {
-                                       throw new ArgumentException("Cannot set column '" + Column.ColumnName + "' to '" + value + "'. The value violates the MaxLength limit of this column.");
-                               }
-                               base.SetValue(index,value);
-                       }
-                       
-                       protected override void SetValue(int index, object value)
-                       {
-                               if ( value != null && value != DBNull.Value ) {
-                                       if ( value is string ) {
-                                               SetValue(index, (string) value);
-                                       }
-                                       else {
-                                               SetValue(index, Convert.ToString(value));
-                                       }
-                                       return;
-                               }
-
-                               base.SetValue(index, value);
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull ( index, record,field))
-                                        SetValue(index,record.GetString(field));
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               bool isNull1 = IsNull(index1);
-                               bool isNull2 = IsNull(index2);
-
-                               if (isNull1) {
-                                       return isNull2 ? 0 : -1;
-                               }
-                               else {
-                                       if (isNull2) {
-                                               return 1;
-                                       }
-                               }
-                               return String.Compare((string)this[index1], (string)this[index2], !Column.Table.CaseSensitive);
-                       }
-
-                       #endregion //Methods 
-               }
-
-               sealed class DateTimeDataContainer : ObjectDataContainer
-               {
-                       #region Methods
-                       
-                       protected override void SetValue(int index, object value)
-                       {
-                               if ( value != null && value != DBNull.Value && !(value is DateTime)) {
-                                       value = Convert.ToDateTime(value);
-                               }
-
-                               base.SetValue(index,value);
-                       }
-
-                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)
-                       {
-                               // if exception thrown, it should be caught 
-                               // in the  caller method
-                               if (!CheckAndSetNull(index,record,field))
-                                       base.SetValue(index,record.GetDateTime(field));
-                       }
-
-                       internal override int CompareValues(int index1, int index2)
-                       {
-                               bool isNull1 = IsNull(index1);
-                               bool isNull2 = IsNull(index2);
-
-                               if (isNull1) {
-                                       return isNull2 ? 0 : -1;
-                               }
-                               else {
-                                       if (isNull2) {
-                                               return 1;
-                                       }
-                               }
-                               return DateTime.Compare((DateTime)this[index1], (DateTime)this[index2]);
-                       }
-
-                       #endregion //Methods 
-               }
-       }
-}
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+using System;\r
+using System.Collections;\r
+\r
+namespace System.Data.Common\r
+{\r
+       internal abstract class AbstractDataContainer\r
+       {\r
+               #region Fields\r
+\r
+               BitArray _nullValues;\r
+               System.Type _type;\r
+               DataColumn _column;\r
+\r
+               #endregion //Fields\r
+\r
+               #region Properties\r
+\r
+               internal abstract object this[int index] {\r
+                       get;\r
+                       set;\r
+               }\r
+\r
+               internal virtual int Capacity {\r
+                       get { \r
+                               return (_nullValues != null) ? _nullValues.Count : 0; \r
+                       }\r
+                       set { \r
+                               if (_nullValues == null) {\r
+                                       _nullValues = new BitArray(value);\r
+                               }\r
+                               else {\r
+                                       _nullValues.Length = value;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal Type Type {\r
+                       get {\r
+                               return _type;\r
+                       }\r
+               }\r
+\r
+               protected DataColumn Column {\r
+                       get {\r
+                               return _column;\r
+                       }\r
+               }\r
+\r
+               #endregion //Properties\r
+\r
+               #region Methods\r
+\r
+               internal static AbstractDataContainer CreateInstance(Type type, DataColumn column)\r
+               {\r
+                       AbstractDataContainer container;\r
+                       switch (Type.GetTypeCode(type)) {\r
+                               case TypeCode.Int16 :\r
+                                       container = new Int16DataContainer();\r
+                                       break;\r
+                               case TypeCode.Int32 : \r
+                                       container = new Int32DataContainer();\r
+                                       break;\r
+                               case TypeCode.Int64 :\r
+                                       container = new Int64DataContainer();\r
+                                       break;\r
+                               case TypeCode.String :\r
+                                       container = new StringDataContainer();\r
+                                       break;\r
+                               case TypeCode.Boolean:\r
+                                       container = new BitDataContainer();\r
+                                       break;\r
+                               case TypeCode.Byte :\r
+                                       container = new ByteDataContainer();\r
+                                       break;\r
+                               case TypeCode.Char :\r
+                                       container = new CharDataContainer();\r
+                                       break;\r
+                               case TypeCode.Double :\r
+                                       container = new DoubleDataContainer();\r
+                                       break;\r
+                               case TypeCode.SByte :\r
+                                       container = new SByteDataContainer();\r
+                                       break;\r
+                               case TypeCode.Single :\r
+                                       container = new SingleDataContainer();\r
+                                       break;\r
+                               case TypeCode.UInt16 :\r
+                                       container = new UInt16DataContainer();\r
+                                       break;\r
+                               case TypeCode.UInt32 :\r
+                                       container = new UInt32DataContainer();\r
+                                       break;\r
+                               case TypeCode.UInt64 :\r
+                                       container = new UInt64DataContainer();\r
+                                       break;\r
+                               case TypeCode.DateTime :\r
+                                       container = new DateTimeDataContainer();\r
+                                       break;\r
+                               case TypeCode.Decimal :\r
+                                       container = new DecimalDataContainer();\r
+                                       break;\r
+                               default :\r
+                                       container = new ObjectDataContainer();\r
+                                       break;\r
+                       }\r
+                       container._type = type;\r
+                       container._column = column;\r
+                       return container;\r
+               }\r
+\r
+               internal bool IsNull(int index)\r
+               {\r
+                       return (_nullValues != null) ? _nullValues[index] : true;\r
+               }\r
+\r
+               internal void SetNullBit(int index,bool isNull)\r
+               {\r
+                       _nullValues[index] = isNull;\r
+               }\r
+\r
+               protected void SetNull(int index,bool isNull,bool isDbNull)\r
+               {\r
+                       SetNullBit(index,isDbNull);\r
+                       // this method must be called after setting the value into value array\r
+                       // otherwise the dafault value will be overriden\r
+                       if ( isNull ) {\r
+                               // set the value to default\r
+                               CopyValue(Column.Table.DefaultValuesRowIndex,index);\r
+                       }\r
+               }\r
+\r
+               internal void FillValues(int fromIndex)\r
+               {\r
+                       for(int i=0; i < Capacity; i++) {\r
+                               CopyValue(fromIndex,i);\r
+                               _nullValues[i] = _nullValues[fromIndex];\r
+                       }\r
+               }\r
+\r
+               internal virtual void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+               {\r
+                       _nullValues[toIndex] = fromContainer._nullValues[fromIndex];\r
+               }\r
+\r
+               internal virtual void CopyValue(int fromIndex, int toIndex)\r
+               {\r
+                       _nullValues[toIndex] = _nullValues[fromIndex];\r
+               }\r
+\r
+               internal virtual void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+               {\r
+                       bool isDbNull = record.IsDBNull(field);\r
+                       SetNull(index,false,isDbNull);\r
+               }\r
+\r
+               protected int CompareNulls(int index1, int index2)\r
+               {\r
+                       bool null1 = IsNull(index1);\r
+                       bool null2 = IsNull(index2);\r
+\r
+                       if ( null1 ^ null2 ) {\r
+                               return null1 ? -1 : 1;\r
+                       }\r
+                       else {\r
+                               return 0;\r
+                       }\r
+               }\r
+\r
+               internal abstract int CompareValues(int index1, int index2);\r
+\r
+               internal abstract long GetInt64(int index);\r
+\r
+               #endregion //Methods\r
+\r
+               sealed class Int16DataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       short[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is short ) {\r
+                                               SetValue(index,(short)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToInt16(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new short[value];\r
+                                       }\r
+                                       else {\r
+                                               short[] tmp = new short[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, short value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetInt16Safe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((Int16DataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               short s1 = _values[index1];\r
+                               short s2 = _values[index2];\r
+\r
+                               if ( s1 == 0 || s2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0)\r
+                                               return cn;\r
+                               }\r
+\r
+                               return s1 - s2;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return (long) _values[index];\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class Int32DataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       int[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is int ) {\r
+                                               SetValue(index,(int)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToInt32(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new int[value];\r
+                                       }\r
+                                       else {\r
+                                               int[] tmp = new int[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, int value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetInt32Safe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((Int32DataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               int i1 = _values[index1];\r
+                               int i2 = _values[index2];\r
+                               \r
+                               if (i1 == 0 || i2 == 0) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0)\r
+                                               return cn;\r
+                               }\r
+\r
+                               if ( i1 <= i2 ) {\r
+                                       return ( i1 == i2 ) ? 0 : -1;\r
+                               }\r
+                               return 1;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return (long) _values[index];\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class Int64DataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       long[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is long ) {\r
+                                               SetValue(index,(long)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToInt64(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new long[value];\r
+                                       }\r
+                                       else {\r
+                                               long[] tmp = new long[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, long value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetInt64Safe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((Int64DataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               long l1 = _values[index1];\r
+                               long l2 = _values[index2];\r
+\r
+                               if ( l1 == 0 || l2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) {\r
+                                               return cn;\r
+                                       }\r
+                               }\r
+\r
+                               if ( l1 <= l2 ) {\r
+                                       return ( l1 != l2 ) ? -1 : 0;\r
+                               }\r
+                               return 1;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return _values[index];\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class SingleDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       float[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is float ) {\r
+                                               SetValue(index,(float)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToSingle(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new float[value];\r
+                                       }\r
+                                       else {\r
+                                               float[] tmp = new float[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, float value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetFloatSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((SingleDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               float f1 = _values[index1];\r
+                               float f2 = _values[index2];\r
+\r
+                               if ( f1 == 0 || f2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) {\r
+                                               return cn;\r
+                                       }\r
+                               }\r
+\r
+                               if ( f1 <= f2 ) {\r
+                                       return ( f1 != f2 ) ? -1 : 0;\r
+                               }\r
+                               return 1;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class DoubleDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       double[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is double ) {\r
+                                               SetValue(index,(double)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToDouble(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new double[value];\r
+                                       }\r
+                                       else {\r
+                                               double[] tmp = new double[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, double value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetDoubleSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((DoubleDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               double d1 = _values[index1];\r
+                               double d2 = _values[index2];\r
+\r
+                               if ( d1 == 0 || d2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) {\r
+                                               return cn;\r
+                                       }\r
+                               }\r
+\r
+                               if ( d1 <= d2 ) {\r
+                                       return ( d1 != d2 ) ? -1 : 0;\r
+                               }\r
+                               return 1;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class ByteDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       byte[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is byte ) {\r
+                                               SetValue(index,(byte)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToByte(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new byte[value];\r
+                                       }\r
+                                       else {\r
+                                               byte[] tmp = new byte[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, byte value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetByteSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((ByteDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               byte b1 = _values[index1];\r
+                               byte b2 = _values[index2];\r
+\r
+                               if ( b1 == 0 || b2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) {\r
+                                               return cn;\r
+                                       }\r
+                               }\r
+\r
+                               return b1 - b2;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return (long) _values[index];\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class BitDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       bool[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       bool isNull = IsNull(index);\r
+                                       if (isNull) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,false);\r
+                                       }\r
+                                       else if( value is bool ) {\r
+                                               SetValue(index,(bool)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToBoolean(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new bool[value];\r
+                                       }\r
+                                       else {\r
+                                               bool[] tmp = new bool[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, bool value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetBooleanSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((BitDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               bool b1 = _values[index1];\r
+                               bool b2 = _values[index2];\r
+\r
+                               if ( b1 ^ b2 ) {\r
+                                       return b1 ? 1 : -1;\r
+                               }\r
+                               \r
+                               if ( b1 ) {\r
+                                       return 0;\r
+                               }\r
+\r
+                               return CompareNulls(index1, index2);    \r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               abstract class AbstractObjectDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       object[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) \r
+                                               return DBNull.Value;\r
+\r
+                                       return _values[index];\r
+                               }\r
+                               set {\r
+                                       SetValue(index,value);\r
+                                       SetNull(index,value == null,value == DBNull.Value);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new object[value];\r
+                                       }\r
+                                       else {\r
+                                               object[] tmp = new object[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       protected virtual void SetValue(int index, object value)\r
+                       {\r
+                               if(value == null) {\r
+                                       value = Column.DefaultValue;\r
+                               }\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((AbstractObjectDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               object obj1 = _values[index1];\r
+                               object obj2 = _values[index2];\r
+                               if(obj1 == obj2) \r
+                               {\r
+                                       return 0;\r
+                               }\r
+                               else\r
+                               {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) \r
+                                               return cn;\r
+\r
+                                       if (obj1 is IComparable) \r
+                                       {\r
+                                               try \r
+                                               {\r
+                                                       return ((IComparable)obj1).CompareTo(obj2);\r
+                                               }\r
+                                               catch \r
+                                               {\r
+                                                       //just suppress\r
+                                               }\r
+\r
+                                               if (obj2 is IComparable) \r
+                                               {\r
+                                                       obj2 = Convert.ChangeType(obj2, Type.GetTypeCode(obj1.GetType()));\r
+                                                       return ((IComparable)obj1).CompareTo(obj2);\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               return String.Compare(obj1.ToString(), obj2.ToString());\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+        \r
+               }\r
+\r
+               sealed class ObjectDataContainer : AbstractObjectDataContainer\r
+               {\r
+                       #region Methods\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught \r
+                               // in the  caller method\r
+                               SetValue(index,record.GetValue(field));\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       protected override void SetValue(int index, object value)\r
+                       {\r
+                               if(value != null && value != DBNull.Value && !Type.IsAssignableFrom(value.GetType()))\r
+                                       value = Convert.ChangeType(value, Type);\r
+\r
+                               base.SetValue(index, value);\r
+                       }\r
+                       #endregion //Methods\r
+        \r
+               }\r
+\r
+               sealed class DateTimeDataContainer : AbstractObjectDataContainer\r
+               {\r
+                       #region Methods\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught \r
+                               // in the  caller method\r
+                               base.SetValue(index,record.GetDateTime(field));\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       protected override void SetValue(int index, object value)\r
+                       {\r
+                               if (value != null && value != DBNull.Value)\r
+                                       value = Convert.ToDateTime(value);\r
+                               base.SetValue(index, value);\r
+                       }\r
+                       #endregion //Methods\r
+        \r
+               }\r
+\r
+               sealed class DecimalDataContainer : AbstractObjectDataContainer\r
+               {\r
+                       #region Methods\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetDecimalSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       protected override void SetValue(int index, object value)\r
+                       {\r
+                               if (value != null && value != DBNull.Value)\r
+                                       value = Convert.ToDecimal(value);\r
+                               base.SetValue(index, value);\r
+                       }\r
+                       #endregion //Methods\r
+        \r
+               }\r
+\r
+               sealed class StringDataContainer : AbstractObjectDataContainer\r
+               {\r
+                       #region Methods\r
+\r
+                       private void SetValue(int index, string value)\r
+                       {\r
+                               if (value != null && Column.MaxLength >= 0 && Column.MaxLength < value.Length ) {\r
+                                       throw new ArgumentException("Cannot set column '" + Column.ColumnName + "' to '" + value + "'. The value violates the MaxLength limit of this column.");\r
+                               }\r
+                               base.SetValue(index,value);\r
+                       }\r
+                       \r
+                       protected override void SetValue(int index, object value)\r
+                       {\r
+                               if ( value != null && value != DBNull.Value ) {\r
+                                       if ( value is string ) {\r
+                                               SetValue(index, (string) value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index, Convert.ToString(value));\r
+                                       }\r
+                                       return;\r
+                               }\r
+\r
+                               base.SetValue(index, value);\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught \r
+                               // in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetStringSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               bool isNull1 = IsNull(index1);\r
+                               bool isNull2 = IsNull(index2);\r
+\r
+                               if (isNull1) {\r
+                                       return isNull2 ? 0 : -1;\r
+                               }\r
+                               else {\r
+                                       if (isNull2) {\r
+                                               return 1;\r
+                                       }\r
+                               }\r
+                               return String.Compare((string)this[index1], (string)this[index2], !Column.Table.CaseSensitive);\r
+                       }\r
+\r
+                       #endregion //Methods \r
+               }\r
+\r
+               sealed class CharDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       char[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,'\0');\r
+                                       }\r
+                                       else if( value is char ) {\r
+                                               SetValue(index,(char)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToChar(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new char[value];\r
+                                       }\r
+                                       else {\r
+                                               char[] tmp = new char[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, char value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,((ISafeDataRecord)record).GetCharSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((CharDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               char c1 = _values[index1];\r
+                               char c2 = _values[index2];\r
+\r
+                               if ( c1 == '\0' || c2 == '\0' ) \r
+                               {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) \r
+                                               return cn;\r
+                               }\r
+\r
+                               return c1 - c2;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class UInt16DataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       ushort[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is ushort ) {\r
+                                               SetValue(index,(ushort)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToUInt16(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new ushort[value];\r
+                                       }\r
+                                       else {\r
+                                               ushort[] tmp = new ushort[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, ushort value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,(ushort)((ISafeDataRecord)record).GetInt16Safe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((UInt16DataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               ushort s1 = _values[index1];\r
+                               ushort s2 = _values[index2];\r
+\r
+                               if ( s1 == 0 || s2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0)\r
+                                               return cn;\r
+                               }\r
+\r
+                               return s1 - s2;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class UInt32DataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       uint[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is uint ) {\r
+                                               SetValue(index,(uint)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToUInt32(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new uint[value];\r
+                                       }\r
+                                       else {\r
+                                               uint[] tmp = new uint[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, uint value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,(uint)((ISafeDataRecord)record).GetInt32Safe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((UInt32DataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               uint i1 = _values[index1];\r
+                               uint i2 = _values[index2];\r
+\r
+                               if ( i1 == 0 || i2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0)\r
+                                               return cn;\r
+                               }\r
+\r
+                               if ( i1 <= i2 ) {\r
+                                       return ( i1 != i2 ) ? -1 : 0;\r
+                               }\r
+                               return 1;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+               sealed class UInt64DataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       ulong[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is ulong ) {\r
+                                               SetValue(index,(ulong)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToUInt64(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new ulong[value];\r
+                                       }\r
+                                       else {\r
+                                               ulong[] tmp = new ulong[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, ulong value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,(ulong)((ISafeDataRecord)record).GetInt64Safe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((UInt64DataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               ulong l1 = _values[index1];\r
+                               ulong l2 = _values[index2];\r
+\r
+                               if ( l1 == 0 || l2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) {\r
+                                               return cn;\r
+                                       }\r
+                               }\r
+\r
+                               if ( l1 <= l2 ) {\r
+                                       return ( l1 != l2 ) ? -1 : 0;\r
+                               }\r
+                               return 1;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToInt64(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+\r
+               sealed class SByteDataContainer : AbstractDataContainer\r
+               {\r
+                       #region Fields\r
+               \r
+                       sbyte[] _values;\r
+\r
+                       #endregion //Fields\r
+\r
+                       #region Properties\r
+\r
+                       internal override object this[int index] {\r
+                               get {\r
+                                       if (IsNull(index)) {\r
+                                               return DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               return _values[index];\r
+                                       }\r
+                               }\r
+                               set {\r
+                                       bool isDbNull = (value ==  DBNull.Value);\r
+                                       if (value == null || isDbNull) {\r
+                                               SetValue(index,0);\r
+                                       }\r
+                                       else if( value is sbyte ) {\r
+                                               SetValue(index,(sbyte)value);\r
+                                       }\r
+                                       else {\r
+                                               SetValue(index,Convert.ToSByte(value));\r
+                                       }\r
+                                       SetNull(index,value == null,isDbNull);\r
+                               }\r
+                       }\r
+\r
+                       internal override int Capacity {\r
+                               set {\r
+                                       base.Capacity = value;\r
+                                       if (_values == null) {\r
+                                               _values = new sbyte[value];\r
+                                       }\r
+                                       else {\r
+                                               sbyte[] tmp = new sbyte[value];\r
+                                               Array.Copy(_values,0,tmp,0,_values.Length);\r
+                                               _values = tmp;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       #endregion //Properties\r
+\r
+                       #region Methods\r
+                       \r
+                       private void SetValue(int index, sbyte value)\r
+                       {\r
+                               _values[index] = value;\r
+                       }\r
+\r
+                       internal override void SetItemFromDataRecord(int index, IDataRecord record, int field)\r
+                       {\r
+                               // if exception thrown, it should be caught in the  caller method\r
+                               if (record is ISafeDataRecord) {\r
+                                       SetValue(index,(sbyte)((ISafeDataRecord)record).GetByteSafe(field));\r
+                               }\r
+                               else {\r
+                                       this[index] = record.GetValue(field);\r
+                               }\r
+                               base.SetItemFromDataRecord(index,record,field);\r
+                       }\r
+\r
+                       internal override void CopyValue(int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromIndex, toIndex);\r
+                               _values[toIndex] = _values[fromIndex];\r
+                       }\r
+\r
+                       internal override void CopyValue(AbstractDataContainer fromContainer, int fromIndex, int toIndex)\r
+                       {\r
+                               base.CopyValue(fromContainer, fromIndex, toIndex);\r
+                               _values[toIndex] = ((SByteDataContainer)fromContainer)._values[fromIndex];\r
+                       }\r
+\r
+                       internal override int CompareValues(int index1, int index2)\r
+                       {\r
+                               sbyte b1 = _values[index1];\r
+                               sbyte b2 = _values[index2];\r
+\r
+                               if ( b1 == 0 || b2 == 0 ) {\r
+                                       int cn = CompareNulls(index1, index2);\r
+                                       if (cn != 0) {\r
+                                               return cn;\r
+                                       }\r
+                               }\r
+\r
+                               return b1 - b2;\r
+                       }\r
+\r
+                       internal override long GetInt64(int index)\r
+                       {\r
+                               return Convert.ToSByte(_values[index]);\r
+                       }\r
+\r
+                       #endregion //Methods\r
+               }\r
+\r
+       }\r
+}\r
index cee239e54a6296411e995af96a5070b6142413b6..8c96e0677f630532fe3df880ff906bb7fc429e49 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.ComponentModel;
 using System.Data;
index 7c747e7e37b5456944e10784990e986ae0c79d3b..57bae5fc1b53ba35dba1211b624c38dd36290974 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.ComponentModel;
 using System.Data;
index d0e494463a6502e2598197ba8cbf9fcb10a2c237..9f55fba24f2c647b071a4cf5574234d3875ec338 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.ComponentModel;
 using System.Data;
index 3142583ebb3cda1b736b71860190835a00eab0e3..3f7f7cda1d596a7b2fb81343a21266445c8825f5 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.ComponentModel;
 using System.Data;
+#if !TARGET_JVM
 using System.EnterpriseServices;
+#endif
 
 namespace System.Data.Common {
        public abstract class DbConnection : Component, IDbConnection, IDisposable
        {
-
-                #region Fields
-                bool disposed = false;
-                #endregion //Fields
-                
                #region Constructors
 
                protected DbConnection ()
@@ -67,16 +64,14 @@ namespace System.Data.Common {
 
                protected abstract DbTransaction BeginDbTransaction (IsolationLevel isolationLevel);
 
-               [MonoTODO]
                public DbTransaction BeginTransaction ()
                {
-                       throw new NotImplementedException ();
+                       return BeginDbTransaction(IsolationLevel.ReadCommitted);
                }
 
-               [MonoTODO]
                public DbTransaction BeginTransaction (IsolationLevel isolationLevel)
                {
-                       throw new NotImplementedException ();
+                       return BeginDbTransaction(isolationLevel);
                }
 
                public abstract void ChangeDatabase (string databaseName);
@@ -87,36 +82,21 @@ namespace System.Data.Common {
                        return CreateDbCommand ();
                }
 
-                protected override void Dispose (bool disposing)
-               {
-                        if (!disposed) { 
-                                try {
-                                        if (disposing) {
-                                                // unmanaged cleanup
-                                        }
-
-                                        disposed = true;
-                                } finally {
-                                        base.Dispose (disposing);
-                                }
-                                
-                       }
-               }
-
-
                protected abstract DbCommand CreateDbCommand ();
 
-                [MonoTODO]
-                public virtual void EnlistTransaction (ITransaction transaction)
-                {
+#if NET_2_0
+        [MonoTODO]
+        public virtual void EnlistTransaction (ITransaction transaction)
+        {
                        throw new NotImplementedException ();                        
-                }
+        }
 
                [MonoTODO]
                public virtual void EnlistDistributedTransaction (ITransaction transaction)
                {
                        throw new NotImplementedException ();
                }
+#endif
 
                [MonoTODO]
                public virtual DataTable GetSchema ()
diff --git a/mcs/class/System.Data/System.Data.Common/DbConvert.cs b/mcs/class/System.Data/System.Data.Common/DbConvert.cs
new file mode 100644 (file)
index 0000000..d88969e
--- /dev/null
@@ -0,0 +1,330 @@
+//\r
+// System.Data.Common.DbConvert\r
+//\r
+// Author:\r
+//   Boris Kirzner (borisk@mainsoft.com)\r
+//\r
+\r
+using System;\r
+\r
+using java.io;\r
+using java.sql;\r
+\r
+namespace System.Data.Common\r
+{\r
+       internal class DbConvert\r
+       {\r
+               #region Fields\r
+\r
+               const long JAVA_MIN_MILLIS_UTC = -62135769600000L; // java.sql.Timestamp.valueOf("0001-01-01 00:00:00.000000000").getTime() at Greenwich time zone.\r
+               static readonly long TIMEZONE_RAW_OFFSET;\r
+               // .NET milliseconds value of DateTime(1582,1,1,0,0,0,0).Ticks/TimeSpan.TicksPerMillisecond                     \r
+               const long CLR_MILLIS_1582 = 49891507200000L;\r
+               const long MILLIS_PER_TWO_DAYS = 2 * TimeSpan.TicksPerDay / TimeSpan.TicksPerMillisecond; // 172800000L;\r
+               internal static readonly java.util.TimeZone DEFAULT_TIME_ZONE;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               static DbConvert()\r
+               {\r
+                       DEFAULT_TIME_ZONE = java.util.SimpleTimeZone.getDefault();                      \r
+                       TIMEZONE_RAW_OFFSET = (long)DEFAULT_TIME_ZONE.getRawOffset();                                           \r
+               }\r
+\r
+               // The diff between .Net and Java goes as the following:\r
+               //  * at 1582: java has 10 days less than .net\r
+               //  * below 1500 (exept 1200,800,400) : each 100'th year java adds 1 day over .net. \r
+               // Current implementation compatible with .net in 1-99 and since 1582. In 100-1582 we're not compatible with .Ner nor with Java\r
+\r
+               internal static long JavaMillisToClrMillis(long javaMillis)\r
+               {\r
+                       return JavaMillisToClrMillisUTC(javaMillis) + TIMEZONE_RAW_OFFSET;\r
+               }\r
+\r
+               internal static long JavaMillisToClrMillisUTC(long javaMillis) {\r
+                       long clrMillis = javaMillis - JAVA_MIN_MILLIS_UTC;\r
+                       if (clrMillis > CLR_MILLIS_1582) {\r
+                               clrMillis -= MILLIS_PER_TWO_DAYS;\r
+                       }\r
+                       return clrMillis;\r
+               }\r
+\r
+               internal static long ClrMillisToJavaMillis(long clrMillis)\r
+               {\r
+                       return ClrMillisToJavaMillisUTC(clrMillis) - TIMEZONE_RAW_OFFSET;\r
+               }\r
+\r
+               internal static long ClrMillisToJavaMillisUTC(long clrMillis) {\r
+                       long javaMillis = clrMillis + JAVA_MIN_MILLIS_UTC;\r
+                       if (clrMillis > CLR_MILLIS_1582) {\r
+                               javaMillis += MILLIS_PER_TWO_DAYS;\r
+                       }\r
+                       return javaMillis;\r
+               }\r
+\r
+               internal static java.sql.Time ClrTicksToJavaTime(long ticks) {\r
+                       return new Time((ticks / TimeSpan.TicksPerMillisecond)\r
+                               - DEFAULT_TIME_ZONE.getRawOffset());\r
+               }\r
+\r
+               internal static java.sql.Date ClrTicksToJavaDate(long ticks) {\r
+                       java.sql.Date d = new java.sql.Date(0);\r
+                       ClrTicksToJavaDate(d, ticks);\r
+                       return d;\r
+               }\r
+\r
+               internal static java.sql.Timestamp ClrTicksToJavaTimestamp(long ticks)\r
+               {\r
+                       java.sql.Timestamp ts = new java.sql.Timestamp(0);\r
+                       ClrTicksToJavaDate(ts, ticks);\r
+\r
+//                     int nanos = (int)(ticks % TimeSpan.TicksPerMillisecond) * 100;\r
+//                     ts.setNanos(javaTimestamp.getNanos() + nanos);\r
+\r
+                       return ts;\r
+               }\r
+\r
+               internal static void ClrTicksToJavaDate(java.util.Date d, long ticks) {\r
+                       long millis = ClrMillisToJavaMillis(ticks / TimeSpan.TicksPerMillisecond);\r
+\r
+                       d.setTime(millis);\r
+                       if (DEFAULT_TIME_ZONE.inDaylightTime(d)) {\r
+                               millis -= DEFAULT_TIME_ZONE.getDSTSavings();\r
+                               d.setTime(millis);\r
+                       }\r
+               }\r
+               \r
+               internal static long JavaTimestampToClrTicks(java.sql.Timestamp ts)\r
+               {\r
+                       long ticks = JavaDateToClrTicks(ts);\r
+                       // Extra ticks, for dbs that can save them. \r
+                       // We do not use it, since .net does not saves ticks for fractial milliseconds\r
+                       // long ticksLessThanMilliseconds = (ts.getNanos()*100) % TimeSpan.TicksPerMillisecond;\r
+                       // ticks += ticksLessThanMilliseconds;\r
+                       \r
+                       return ticks;\r
+               }\r
+\r
+               internal static long JavaDateToClrTicks(java.util.Date d) {\r
+                       long millis = JavaMillisToClrMillis(d.getTime());\r
+                       if (DEFAULT_TIME_ZONE.inDaylightTime(d)) {\r
+                               millis += DEFAULT_TIME_ZONE.getDSTSavings();\r
+                       }\r
+                       return millis * TimeSpan.TicksPerMillisecond;\r
+               }\r
+\r
+               internal static long JavaTimeToClrTicks(java.sql.Time t) {\r
+                       return (t.getTime() + DEFAULT_TIME_ZONE.getRawOffset())\r
+                               * TimeSpan.TicksPerMillisecond;\r
+               }\r
+\r
+               internal protected static Type JavaSqlTypeToClrType(int sqlTypeValue)\r
+               {\r
+                       DbTypes.JavaSqlTypes sqlType = (DbTypes.JavaSqlTypes)sqlTypeValue;\r
+\r
+                       switch (sqlType) {\r
+                               case DbTypes.JavaSqlTypes.ARRAY : return typeof (java.sql.Array);\r
+                               case DbTypes.JavaSqlTypes.BIGINT : return DbTypes.TypeOfInt64;\r
+                               case DbTypes.JavaSqlTypes.BINARY : return DbTypes.TypeOfByteArray;\r
+                               case DbTypes.JavaSqlTypes.BIT : return DbTypes.TypeOfBoolean;\r
+                               case DbTypes.JavaSqlTypes.BLOB : return DbTypes.TypeOfByteArray;\r
+                               case DbTypes.JavaSqlTypes.BOOLEAN : return DbTypes.TypeOfBoolean;\r
+                               case DbTypes.JavaSqlTypes.CHAR : return DbTypes.TypeOfString;\r
+                               case DbTypes.JavaSqlTypes.CLOB : return DbTypes.TypeOfString;\r
+//                             case DbTypes.JavaSqlTypes.DATALINK :\r
+                               case DbTypes.JavaSqlTypes.DATE : return DbTypes.TypeOfDateTime;\r
+                               case DbTypes.JavaSqlTypes.DECIMAL : return DbTypes.TypeOfDecimal;\r
+//                             case DbTypes.JavaSqlTypes.DISTINCT :\r
+                               case DbTypes.JavaSqlTypes.DOUBLE : return DbTypes.TypeOfDouble;\r
+                               case DbTypes.JavaSqlTypes.FLOAT : return DbTypes.TypeOfDouble;\r
+                               case DbTypes.JavaSqlTypes.INTEGER : return DbTypes.TypeOfInt32;\r
+//                             case DbTypes.JavaSqlTypes.JAVA_OBJECT :\r
+                               case DbTypes.JavaSqlTypes.LONGVARBINARY : return DbTypes.TypeOfByteArray;\r
+                               case DbTypes.JavaSqlTypes.LONGVARCHAR : return DbTypes.TypeOfString;\r
+                               case DbTypes.JavaSqlTypes.NULL : return null;\r
+                               case DbTypes.JavaSqlTypes.NUMERIC : return DbTypes.TypeOfDecimal;\r
+//                             case DbTypes.JavaSqlTypes.OTHER :\r
+                               case DbTypes.JavaSqlTypes.REAL : return DbTypes.TypeOfSingle;\r
+                               case DbTypes.JavaSqlTypes.REF : return typeof (java.sql.Ref);\r
+                               case DbTypes.JavaSqlTypes.SMALLINT : return DbTypes.TypeOfInt16;\r
+                               case DbTypes.JavaSqlTypes.STRUCT : return typeof (java.sql.Struct);\r
+                               case DbTypes.JavaSqlTypes.TIME : return DbTypes.TypeOfTimespan;\r
+                               case DbTypes.JavaSqlTypes.TIMESTAMP : return DbTypes.TypeOfDateTime;\r
+                               case DbTypes.JavaSqlTypes.TINYINT : return DbTypes.TypeOfByte;\r
+                               case DbTypes.JavaSqlTypes.VARBINARY : return DbTypes.TypeOfByteArray;\r
+                               case DbTypes.JavaSqlTypes.VARCHAR : return DbTypes.TypeOfString;\r
+                               default : return DbTypes.TypeOfObject;\r
+                       }\r
+\r
+               }\r
+\r
+\r
+               internal protected static object JavaResultSetToClrWrapper(CallableStatement results,int columnIndex,DbTypes.JavaSqlTypes javaSqlType,int maxLength ,ResultSetMetaData resultsMetaData)\r
+               {\r
+                       object returnValue = null;      \r
+                       sbyte[] sbyteArray;\r
+                       long milliseconds;\r
+                       long ticks;\r
+                       string s;\r
+                       columnIndex++; //jdbc style\r
+                       switch (javaSqlType) {\r
+                               case DbTypes.JavaSqlTypes.ARRAY :\r
+                                       returnValue = results.getArray(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.BIGINT :\r
+                                       returnValue = results.getLong(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.BINARY :\r
+                               case DbTypes.JavaSqlTypes.VARBINARY :\r
+                               case DbTypes.JavaSqlTypes.LONGVARBINARY :\r
+                                       // FIXME : comsider using maxLength\r
+                                       sbyteArray = results.getBytes(columnIndex);\r
+                                       if (sbyteArray != null) {\r
+                                               returnValue = vmw.common.TypeUtils.ToByteArray(sbyteArray);\r
+                                       }\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.BIT :\r
+                                       returnValue = results.getBoolean(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.BLOB :\r
+                                       // FIXME : comsider using maxLength\r
+                                       java.sql.Blob blob = results.getBlob(columnIndex);\r
+                                       if (blob != null) {\r
+                                               InputStream input = blob.getBinaryStream();                                     \r
+                                               if (input == null) {\r
+                                                       returnValue = new byte[0];\r
+                                               }\r
+                                               else {\r
+                                                       long length = blob.length();\r
+                                                       byte[] byteValue = new byte[length];\r
+                                                       sbyte[] sbyteValue = vmw.common.TypeUtils.ToSByteArray(byteValue);\r
+                                                       input.read(sbyteValue);\r
+                                                       returnValue = byteValue;\r
+                                               }\r
+                                       }\r
+                                       break;  \r
+                               case DbTypes.JavaSqlTypes.CHAR :                                                \r
+                                       if (resultsMetaData != null && "uniqueidentifier".Equals(resultsMetaData.getColumnTypeName(columnIndex))) {\r
+                                               returnValue = new Guid(results.getString(columnIndex));\r
+                                       }\r
+                                       else {\r
+                                               // Oracle Jdbc driver returns extra trailing 0 chars for NCHAR columns, so we threat this at parameter.Size level\r
+                                               s = results.getString(columnIndex);\r
+                                               if ((s != null) && (maxLength < s.Length)) {\r
+                                                       s = s.Substring(0,maxLength);\r
+                                               }\r
+                                               returnValue = s;\r
+                                       }\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.CLOB :\r
+                                       // FIXME : comsider using maxLength\r
+                                       java.sql.Clob clob = results.getClob(columnIndex);\r
+                                       if (clob != null) {\r
+                                               java.io.Reader reader = clob.getCharacterStream();                                      \r
+                                               if (reader == null) {\r
+                                                       returnValue = String.Empty;\r
+                                               }\r
+                                               else {\r
+                                                       long length = clob.length();\r
+                                                       char[] charValue = new char[length];\r
+                                                       reader.read(charValue);\r
+                                                       returnValue = new string(charValue);\r
+                                               }\r
+                                       }\r
+                                       break;          \r
+                               case DbTypes.JavaSqlTypes.TIME :\r
+                                       Time t = results.getTime(columnIndex);\r
+                                       if (t != null) {\r
+                                               returnValue = new TimeSpan(JavaTimeToClrTicks(t));\r
+                                       }\r
+                                       break;  \r
+                               case DbTypes.JavaSqlTypes.DATE :\r
+                                       Date d = results.getDate(columnIndex);\r
+                                       if (d != null) {\r
+                                               returnValue = new DateTime(JavaDateToClrTicks(d));\r
+                                       }\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.TIMESTAMP :                           \r
+                                       Timestamp ts = results.getTimestamp(columnIndex);\r
+                                       if (ts != null) {\r
+                                               returnValue = new DateTime(JavaTimestampToClrTicks(ts));\r
+                                       }\r
+                                       break;          \r
+                               case DbTypes.JavaSqlTypes.DECIMAL :\r
+                               case DbTypes.JavaSqlTypes.NUMERIC :\r
+                                       // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal \r
+                                       // therefore we rely on scale\r
+                                       if (resultsMetaData != null &&  resultsMetaData.getScale(columnIndex) == -127) {\r
+                                               // Oracle db type FLOAT\r
+                                               returnValue = results.getDouble(columnIndex);\r
+                                       }\r
+                                       else {\r
+                                               java.math.BigDecimal bigDecimal = results.getBigDecimal(columnIndex);\r
+                                               if (bigDecimal != null) {\r
+                                                       returnValue = vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bigDecimal);\r
+                                               }\r
+                                       }\r
+                                       break;          \r
+                               case DbTypes.JavaSqlTypes.DISTINCT :\r
+                                       returnValue = results.getObject(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.DOUBLE :\r
+                                       returnValue = results.getDouble(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.FLOAT :\r
+                                       //float f = results.getFloat(columnIndex);\r
+                                       returnValue = results.getDouble(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.INTEGER :\r
+                                       returnValue = results.getInt(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.JAVA_OBJECT :\r
+                                       returnValue = results.getObject(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.LONGVARCHAR :\r
+                                       returnValue = results.getString(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.NULL :\r
+                                       returnValue = DBNull.Value;\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.OTHER :\r
+                                       returnValue = results.getObject(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.REAL :\r
+                                       returnValue = results.getFloat(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.REF :\r
+                                       returnValue = results.getRef(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.SMALLINT :\r
+                                       returnValue = results.getShort(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.STRUCT :\r
+                                       returnValue = results.getObject(columnIndex);\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.TINYINT :\r
+                                       returnValue = Convert.ToByte(results.getByte(columnIndex));\r
+                                       break;\r
+                               case DbTypes.JavaSqlTypes.VARCHAR :\r
+                                       s = results.getString(columnIndex);\r
+                                       if ((s != null) && (maxLength < s.Length)) {\r
+                                               s = s.Substring(0,maxLength);\r
+                                       }\r
+                                       returnValue = s;\r
+                                       break;\r
+                               default :\r
+                                       returnValue = results.getObject(columnIndex);\r
+                                       break;\r
+                       }\r
+                               \r
+                       if (results.wasNull() || results == null) {\r
+                               return DBNull.Value;\r
+                       }                \r
+                       return  returnValue;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+}\r
index 563aad68a0bcc92c2edb604b10e86d141dbe5936..a895a21cc8183bdc54710273329d2ae0a296aebb 100644 (file)
@@ -169,7 +169,7 @@ namespace System.Data.Common {
                                        da.SelectCommand = null;
                                }
                                if (da.InsertCommand != null) {
-                                       da.InsertCommand.Dispose();
+                                        da.InsertCommand.Dispose();
                                        da.InsertCommand = null;
                                }
                                if (da.UpdateCommand != null) {
@@ -337,57 +337,51 @@ namespace System.Data.Common {
                        if (dataReader.FieldCount == 0)
                                return false;
 
+                       int counterStart = counter;
+
                        int[] mapping = BuildSchema (dataReader, dataTable, SchemaType.Mapped);
-                        try {
-                                FillTable (dataTable, dataReader, startRecord, maxRecords, mapping,
-                                           AcceptChangesDuringFill, ref counter);
-                        } catch (Exception e) {
-                                object[] readerArray = new object[dataReader.FieldCount];
-                                object[] tableArray = new object[dataReader.FieldCount];
-                                // we get the values from the datareader
-                                dataReader.GetValues (readerArray);
-                                // copy from datareader columns to table columns according to given mapping
-                                int count = 0;
-                                for (int i = 0; i < dataTable.Columns.Count; i++) {
-                                        if (mapping [i] >= 0)
-                                                tableArray[count++] = readerArray[mapping[i]];
-                                }
-                                FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
-                                OnFillError (args);
-                                if(!args.Continue) {
-                                        return false;
-                                }
-                        }
-                       return true;
-               }
 
-                /// <summary>
-                ///     Fills the given datatable using values from reader. if a column 
-                ///     does not have a mapped reader column (-1 in mapping), that will 
-                ///     be filled with default value. 
-                /// </summary>
-               internal static void FillTable (DataTable dataTable, 
-                                               IDataReader dataReader, 
-                                               int startRecord, 
-                                               int maxRecords, 
-                                               int [] mapping,
-                                               bool acceptChanges,
-                                               ref int counter) 
-                {
-                        if (dataReader.FieldCount == 0)
-                               return ;
+                       int[] sortedMapping = new int[mapping.Length];
+                       int length = sortedMapping.Length;
+                       for(int i=0; i < sortedMapping.Length; i++) {
+                               if (mapping[i] >= 0)
+                                       sortedMapping[mapping[i]] = i;
+                               else
+                                       sortedMapping[--length] = i;
+                       }
 
-                        for (int i = 0; i < startRecord; i++)
-                                dataReader.Read ();
+                               for (int i = 0; i < startRecord; i++) {
+                                       dataReader.Read ();
+                               }
+
+                       while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
+                               try {
+                                       dataTable.BeginLoadData ();
+                                       dataTable.LoadDataRow (dataReader, sortedMapping, length, AcceptChangesDuringFill);
+                                       dataTable.EndLoadData ();
+                                       counter++;
+                               } 
+                               catch (Exception e) {
+                                       object[] readerArray = new object[dataReader.FieldCount];
+                                       object[] tableArray = new object[mapping.Length];
+                                       // we get the values from the datareader
+                                       dataReader.GetValues (readerArray);
+                                       // copy from datareader columns to table columns according to given mapping
+                                       for (int i = 0; i < mapping.Length; i++) {
+                                               if (mapping[i] >= 0) {
+                                                       tableArray[i] = readerArray[mapping[i]];
+                                               }
+                                       }
+                                       FillErrorEventArgs args = CreateFillErrorEvent (dataTable, tableArray, e);
+                                       OnFillError (args);
+                                       if(!args.Continue) {
+                                               return false;
+                                       }
+                               }
+                       }
+                       return true;
+               }
 
-                        int counterStart = counter;
-                        while (dataReader.Read () && (maxRecords == 0 || (counter - counterStart) < maxRecords)) {
-                                dataTable.BeginLoadData ();
-                                dataTable.LoadDataRow (dataReader, mapping, acceptChanges);
-                                dataTable.EndLoadData ();
-                                counter++;
-                        }
-                }
 #if NET_2_0
                 /// <summary>
                 ///     Fills the given datatable using values from reader. if a value 
@@ -549,29 +543,33 @@ namespace System.Data.Common {
                [MonoTODO ("Test")]
                private int[] BuildSchema (IDataReader reader, DataTable table, SchemaType schemaType)
                {
-                        return BuildSchema (reader, table, schemaType, MissingSchemaAction,
-                                            MissingMappingAction, TableMappings);
-               }
+                         return BuildSchema (reader, table, schemaType, MissingSchemaAction,
+                                             MissingMappingAction, TableMappings);
+                }
 
                 /// <summary>
                 ///     Creates or Modifies the schema of the given DataTable based on the schema of
                 ///     the reader and the arguments passed.
                 /// </summary>
-                internal static int[] BuildSchema (IDataReader reader, 
-                                                   DataTable table, 
+                internal static int[] BuildSchema (IDataReader reader,
+                                                   DataTable table,
                                                    SchemaType schemaType,
                                                    MissingSchemaAction missingSchAction,
                                                    MissingMappingAction missingMapAction,
                                                    DataTableMappingCollection dtMapping
                                                    )
-               {
+               {
                        int readerIndex = 0;
-                       int[] mapping = new int[reader.FieldCount + table.Columns.Count]; // mapping the reader indexes to the datatable indexes
-                        for (int i =0 ; i < mapping.Length; i++) 
-                                mapping [i] = -1; // no mapping
-
+                       // FIXME : this fails if query has fewer columns than a table
+                       int[] mapping = new int[table.Columns.Count]; // mapping the reader indexes to the datatable indexes
+                       
+                       for(int i=0; i < mapping.Length; i++) {
+                               mapping[i] = -1;
+                       }
+                       
                        ArrayList primaryKey = new ArrayList ();
                        ArrayList sourceColumns = new ArrayList ();
+                       bool createPrimaryKey = true;
 
                        foreach (DataRow schemaRow in reader.GetSchemaTable ().Rows) {
                                // generate a unique column name in the source table.
@@ -599,10 +597,11 @@ namespace System.Data.Common {
                                        DataColumnMapping columnMapping = DataColumnMappingCollection.GetColumnMappingBySchemaAction(tableMapping.ColumnMappings, realSourceColumnName, missingMapAction);
                                        if (columnMapping != null)
                                        {
+                                               Type columnType = (Type)schemaRow["DataType"];
                                                DataColumn col =
                                                        columnMapping.GetDataColumnBySchemaAction(
                                                        table ,
-                                                       (Type)schemaRow["DataType"],
+                                                       columnType,
                                                        missingSchAction);
 
                                                if (col != null)
@@ -611,27 +610,73 @@ namespace System.Data.Common {
                                                        if (table.Columns.IndexOf(col) == -1)
                                                        {
                                                                if (missingSchAction == MissingSchemaAction.Add 
-                                                                    || missingSchAction == MissingSchemaAction.AddWithKey)
+                                                                       || missingSchAction == MissingSchemaAction.AddWithKey)
                                                                        table.Columns.Add(col);
+
+                                                               int[] tmp = new int[mapping.Length + 1];
+                                                               Array.Copy(mapping,0,tmp,0,col.Ordinal);
+                                                               Array.Copy(mapping,col.Ordinal,tmp,col.Ordinal + 1,mapping.Length - col.Ordinal);
+                                                               mapping = tmp;
+                                                       }                               
+                                                       bool isAutoIncrement = (bool)schemaRow["IsAutoIncrement"];
+                                                       bool allowDBNull = (bool)schemaRow["AllowDBNull"];
+                                                       bool isReadOnly =(bool)schemaRow["IsReadOnly"];
+                                                       bool isKey = (bool)schemaRow["IsKey"];                                                  
+                                                       bool isUnique = (bool)schemaRow["IsUnique"];
+
+                            if (missingSchAction == MissingSchemaAction.AddWithKey) {
+                                                               // fill woth key info                                                           
+                                                               if (isAutoIncrement && DataColumn.CanAutoIncrement(columnType)) {
+                                                                       col.AutoIncrement = true;
+                                                                       if (!allowDBNull)
+                                                                               col.AllowDBNull = false;
+                                                               }
+
+                                                               if (columnType == DbTypes.TypeOfString) {
+                                                                       col.MaxLength = (int)schemaRow["ColumnSize"];
+                                                               }
+
+                                                               if (isReadOnly)
+                                                                       col.ReadOnly = true;
+                                                       }
+                                                                                                                                                                       
+                                                       if (!allowDBNull && (!isReadOnly || isKey))
+                                                               col.AllowDBNull = false;
+                                                       if (isUnique && !isKey && !columnType.IsArray) {
+                                                               col.Unique = true;
+                                                               if (!allowDBNull)
+                                                                       col.AllowDBNull = false;
                                                        }
 
-                                                        if (missingSchAction == MissingSchemaAction.AddWithKey) {
-                                                                if (!schemaRow["IsKey"].Equals (DBNull.Value))
-                                                                        if ((bool) (schemaRow ["IsKey"]))
-                                                                                primaryKey.Add (col);
-                                                                
-                                                                col.AutoIncrement = (bool) schemaRow ["IsAutoIncrement"];
-                                                        }
+                                                       if (isKey) {
+                                primaryKey.Add (col);
+                                                               if (allowDBNull)
+                                                                       createPrimaryKey = false;
+                            }
                                                        
                                                        // add the ordinal of the column as a key and the index of the column in the datareader as a value.
-                                                       mapping[col.Ordinal] = readerIndex;
+                                                       mapping[col.Ordinal] = readerIndex++;
+                                               }
+                                       }
+                               }
+                       }
+                       if (primaryKey.Count > 0) {
+                               DataColumn[] colKey = (DataColumn[])(primaryKey.ToArray(typeof (DataColumn)));
+                               if (createPrimaryKey)
+                                       table.PrimaryKey = colKey;
+                               else {
+                                       UniqueConstraint uConstraint = new UniqueConstraint(colKey);
+                                       for (int i = 0; i < table.Constraints.Count; i++) {
+                                               if (table.Constraints[i].Equals(uConstraint)) {
+                                                       uConstraint = null;
+                                                       break;
                                                }
                                        }
+
+                                       if (uConstraint != null)
+                                               table.Constraints.Add(uConstraint);
                                }
-                               readerIndex++;
                        }
-                       if (primaryKey.Count > 0)
-                               table.PrimaryKey = (DataColumn[])(primaryKey.ToArray(typeof (DataColumn)));
 
                        return mapping;
                         
@@ -701,7 +746,7 @@ namespace System.Data.Common {
                                }
                        }
 
-                       DataRow[] copy = new DataRow [dataRows.Length];
+                       DataRow[] copy = table.NewRowArray(dataRows.Length);
                        Array.Copy(dataRows, 0, copy, 0, dataRows.Length);
                        return Update(copy, tableMapping);
                }
@@ -752,7 +797,7 @@ namespace System.Data.Common {
 
                private int Update (DataTable dataTable, DataTableMapping tableMapping)
                {
-                       DataRow[] rows = new DataRow [dataTable.Rows.Count];
+                       DataRow[] rows = dataTable.NewRowArray(dataTable.Rows.Count);
                        dataTable.Rows.CopyTo (rows, 0);
                        return Update (rows, tableMapping);
                }
@@ -761,12 +806,10 @@ namespace System.Data.Common {
                protected virtual int Update (DataRow[] dataRows, DataTableMapping tableMapping) 
                {
                        int updateCount = 0;
-
                        foreach (DataRow row in dataRows) {
                                StatementType statementType = StatementType.Update;
                                IDbCommand command = null;
                                string commandName = String.Empty;
-                               bool useCommandBuilder = false;
 
                                switch (row.RowState) {
                                case DataRowState.Added:
@@ -785,161 +828,184 @@ namespace System.Data.Common {
                                        commandName = "Update";
                                        break;
                                case DataRowState.Unchanged:
-                                       continue;
                                case DataRowState.Detached:
-                                       throw new NotImplementedException ();
+                                       continue;
                                }
 
-                               if (command == null)
-                                       useCommandBuilder = true;
-
-                               RowUpdatingEventArgs updatingArgs = CreateRowUpdatingEvent (row, command, statementType, tableMapping);
-                               OnRowUpdating (updatingArgs);
-
-                               if (updatingArgs.Status == UpdateStatus.ErrorsOccurred)
-                                       throw (updatingArgs.Errors);
-
-                               if (command == null && updatingArgs.Command != null)
-                                       command = updatingArgs.Command;
-                               else if (command == null)
-                                       throw new InvalidOperationException (String.Format ("Update requires a valid {0}Command when passed a DataRow collection with modified rows.", commandName));
-
-                               if (!useCommandBuilder) {
-                                       DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
-
-                                       foreach (IDataParameter parameter in command.Parameters) {
-                                               string dsColumnName = parameter.SourceColumn;
-                                               if (columnMappings.Contains(parameter.SourceColumn))
-                                                       dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
-                                                if (dsColumnName == null || dsColumnName.Length <= 0)
-                                                        continue;
-                                               DataRowVersion rowVersion = DataRowVersion.Default;
-
-                                               // Parameter version is ignored for non-update commands
-                                               if (statementType == StatementType.Update) 
-                                                       rowVersion = parameter.SourceVersion;
-                                               if (statementType == StatementType.Delete) 
-                                                       rowVersion = DataRowVersion.Original;
-                                                
-                                                parameter.Value = row [dsColumnName, rowVersion];
+                               RowUpdatingEventArgs argsUpdating = CreateRowUpdatingEvent (row, command, statementType, tableMapping);
+                               row.RowError = null;
+                               try {
+                                       if (command != null) {
+                                               DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
+                                               foreach (IDataParameter parameter in command.Parameters) {
+                                                       if ((parameter.Direction & ParameterDirection.Input) != 0) {
+                                                               string dsColumnName = parameter.SourceColumn;
+                                                               if (columnMappings.Contains(parameter.SourceColumn))
+                                                                       dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
+                                                               if (dsColumnName == null || dsColumnName.Length <= 0)
+                                                                               continue;
+                                                               DataRowVersion rowVersion = DataRowVersion.Default;
+
+                                                               // Parameter version is ignored for non-update commands
+                                                               if (statementType == StatementType.Update) 
+                                                                       rowVersion = parameter.SourceVersion;
+                                                               if (statementType == StatementType.Delete) 
+                                                                       rowVersion = DataRowVersion.Original;
+
+                                                               parameter.Value = row [dsColumnName, rowVersion];
+                                                       }
+                                               }
                                        }
                                }
-                               
-                               CommandBehavior commandBehavior = CommandBehavior.Default;
-                               if (command.Connection.State == ConnectionState.Closed) 
-                               {
-                                       command.Connection.Open ();
-                                       commandBehavior |= CommandBehavior.CloseConnection;
+                               catch (Exception e) {
+                                       argsUpdating.Errors = e;
+                                       argsUpdating.Status = UpdateStatus.ErrorsOccurred;
                                }
-                               
+
+                               OnRowUpdating(argsUpdating);
+
+                               switch(argsUpdating.Status) {
+                                       case UpdateStatus.Continue :
+                                               //continue in update operation
+                                               break;
+                                       case UpdateStatus.ErrorsOccurred :
+                                               if (argsUpdating.Errors == null) {
+                                                       argsUpdating.Errors = new DataException("RowUpdatedEvent: Errors occurred; no additional is information available.");
+                                               }
+                                               row.RowError += argsUpdating.Errors.Message;
+                                               if (!ContinueUpdateOnError) {
+                                                       throw argsUpdating.Errors;
+                                               }
+                                               continue;
+                                       case UpdateStatus.SkipAllRemainingRows :
+                                               return updateCount;
+                                       case UpdateStatus.SkipCurrentRow :
+                                               updateCount++;
+                                               continue;
+                                       default :
+                                               throw new ArgumentException(String.Format("Invalid UpdateStatus: {0}",argsUpdating.Status));
+                               }
+
+                               command = argsUpdating.Command;                                 
                                IDataReader reader = null;
-                               try
-                               {
+                               try {                                                           
+                                       if (command == null) {
+                                               throw new InvalidOperationException("ADP_UpdateRequiresCommand" + command);
+                                       }                               
+                               
+                                       CommandBehavior commandBehavior = CommandBehavior.Default;
+                                               if (command.Connection.State == ConnectionState.Closed) {
+                                               command.Connection.Open ();
+                                               commandBehavior |= CommandBehavior.CloseConnection;
+                                       }
+                               
                                        // use ExecuteReader because we want to use the commandbehavior parameter.
                                        // so the connection will be closed if needed.
                                        reader = command.ExecuteReader (commandBehavior);
 
-                                        // update the current row, if the update command returns any resultset
-                                        // ignore other than the first record.
-                                        DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
-
-                                        if (command.UpdatedRowSource == UpdateRowSource.Both ||
-                                            command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) {
-                                                if (reader.Read ()){
-                                                        DataTable retSchema = reader.GetSchemaTable ();
-                                                        foreach (DataRow dr in retSchema.Rows) {
-                                                                string columnName = dr ["ColumnName"].ToString ();
-                                                                string dstColumnName = columnName;
-                                                                if (columnMappings != null &&
-                                                                    columnMappings.Contains(columnName))
-                                                                        dstColumnName = columnMappings [dstColumnName].DataSetColumn;
-                                                                DataColumn dstColumn = row.Table.Columns [dstColumnName];
-                                                                if (dstColumn == null
-                                                                    || (dstColumn.Expression != null
-                                                                    && dstColumn.Expression.Length > 0))
-                                                                        continue;
-                                                                // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/
-                                                                // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx
-                                                                // disable readonly for non-expression columns.
-                                                                bool readOnlyState = dstColumn.ReadOnly;
-                                                                dstColumn.ReadOnly = false;
-                                                                try {
-                                                                        row [dstColumnName] = reader [columnName];
-                                                                } finally {
-                                                                        dstColumn.ReadOnly = readOnlyState;
-                                                                }
-                                                        
-                                                        }
-                                                }
-                                        }
-
-                                        reader.Close ();
-
-                                        int tmp = reader.RecordsAffected; // records affected is valid only after closing reader
+                    // update the current row, if the update command returns any resultset
+                    // ignore other than the first record.
+                    DataColumnMappingCollection columnMappings = tableMapping.ColumnMappings;
+
+                    if (command.UpdatedRowSource == UpdateRowSource.Both ||
+                        command.UpdatedRowSource == UpdateRowSource.FirstReturnedRecord) {
+                            if (reader.Read ()){
+                                    DataTable retSchema = reader.GetSchemaTable ();
+                                    foreach (DataRow dr in retSchema.Rows) {
+                                        string columnName = dr ["ColumnName"].ToString ();
+                                        string dstColumnName = columnName;
+                                        if (columnMappings != null &&
+                                            columnMappings.Contains(columnName))
+                                                dstColumnName = columnMappings [dstColumnName].DataSetColumn;
+                                        DataColumn dstColumn = row.Table.Columns [dstColumnName];
+                                        if (dstColumn == null
+                                            || (dstColumn.Expression != null
+                                            && dstColumn.Expression.Length > 0))
+                                                continue;
+                                        // info from : http://www.error-bank.com/microsoft.public.dotnet.framework.windowsforms.databinding/
+                                        // _35_hcsyiv0dha.2328@tk2msftngp10.phx.gbl_Thread.aspx
+                                        // disable readonly for non-expression columns.
+                                        bool readOnlyState = dstColumn.ReadOnly;
+                                        dstColumn.ReadOnly = false;
+                                        try {
+                                                row [dstColumnName] = reader [columnName];
+                                        } finally {
+                                                dstColumn.ReadOnly = readOnlyState;
+                                        }                                    
+                                    }
+                            }
+                    }
+                    reader.Close ();
+
+                    int tmp = reader.RecordsAffected; // records affected is valid only after closing reader
                                        // if the execute does not effect any rows we throw an exception.
                                        if (tmp == 0)
                                                throw new DBConcurrencyException("Concurrency violation: the " + 
                                                                                  commandName +"Command affected 0 records.");
                                        updateCount += tmp;
                                         
-                                        if (command.UpdatedRowSource == UpdateRowSource.Both ||
-                                            command.UpdatedRowSource == UpdateRowSource.OutputParameters) {
-                                                // Update output parameters to row values
-                                                foreach (IDataParameter parameter in command.Parameters) {
-                                                        if (parameter.Direction != ParameterDirection.InputOutput
-                                                            && parameter.Direction != ParameterDirection.Output
-                                                            && parameter.Direction != ParameterDirection.ReturnValue)
-                                                                continue;
-
-                                                        string dsColumnName = parameter.SourceColumn;
-                                                        if (columnMappings != null &&
-                                                            columnMappings.Contains(parameter.SourceColumn))
-                                                                dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
-                                                        DataColumn dstColumn = row.Table.Columns [dsColumnName];
-                                                        if (dstColumn == null
-                                                            || (dstColumn.Expression != null 
-                                                            && dstColumn.Expression.Length > 0))
-                                                                continue;
-                                                        bool readOnlyState = dstColumn.ReadOnly;
-                                                        dstColumn.ReadOnly  = false;
-                                                        try {
-                                                                row [dsColumnName] = parameter.Value;
-                                                        } finally {
-                                                                dstColumn.ReadOnly = readOnlyState;
-                                                        }
-                                                        
-                                                }
-                                        }
-                                        
-
-                                        RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent(row, command, statementType, tableMapping);
-                                        OnRowUpdated(updatedArgs);
-                                        switch(updatedArgs.Status) {
-                                        case UpdateStatus.Continue:
-                                                break;
-                                        case UpdateStatus.ErrorsOccurred:
-                                                throw(updatedArgs.Errors);
-                                        case UpdateStatus.SkipCurrentRow:
-                                                continue;
-                                        case UpdateStatus.SkipAllRemainingRows:
-                                                return updateCount;
-                                        }
+                    if (command.UpdatedRowSource == UpdateRowSource.Both ||
+                        command.UpdatedRowSource == UpdateRowSource.OutputParameters) {
+                            // Update output parameters to row values
+                            foreach (IDataParameter parameter in command.Parameters) {
+                                    if (parameter.Direction != ParameterDirection.InputOutput
+                                        && parameter.Direction != ParameterDirection.Output
+                                        && parameter.Direction != ParameterDirection.ReturnValue)
+                                            continue;
+
+                                    string dsColumnName = parameter.SourceColumn;
+                                    if (columnMappings != null &&
+                                        columnMappings.Contains(parameter.SourceColumn))
+                                            dsColumnName = columnMappings [parameter.SourceColumn].DataSetColumn;
+                                    DataColumn dstColumn = row.Table.Columns [dsColumnName];
+                                    if (dstColumn == null
+                                        || (dstColumn.Expression != null 
+                                        && dstColumn.Expression.Length > 0))
+                                            continue;
+                                    bool readOnlyState = dstColumn.ReadOnly;
+                                    dstColumn.ReadOnly  = false;
+                                    try {
+                                            row [dsColumnName] = parameter.Value;
+                                    } finally {
+                                            dstColumn.ReadOnly = readOnlyState;
+                                    }
+                                    
+                            }
+                    }
+                    
+                    RowUpdatedEventArgs updatedArgs = CreateRowUpdatedEvent(row, command, statementType, tableMapping);
+                    OnRowUpdated(updatedArgs);
+                    switch(updatedArgs.Status) {
+                    case UpdateStatus.Continue:
+                            break;
+                    case UpdateStatus.ErrorsOccurred:
+                            if (updatedArgs.Errors == null) {
+                                                               updatedArgs.Errors = new DataException("RowUpdatedEvent: Errors occurred; no additional is information available.");
+                                                       }
+                                                       row.RowError += updatedArgs.Errors.Message;
+                                                       if (!ContinueUpdateOnError) {
+                                                               throw updatedArgs.Errors;
+                                                       }
+                                                       break;
+                    case UpdateStatus.SkipCurrentRow:
+                            continue;
+                    case UpdateStatus.SkipAllRemainingRows:
+                            return updateCount;
+                    }
                                        row.AcceptChanges ();
                                }
-                               catch (Exception e)
-                               {
-                                       if (ContinueUpdateOnError)
-                                               row.RowError = e.Message;// do somthing with the error
-                                       else
+                               catch(Exception e) {
+                                       row.RowError = e.Message;
+                                       if (!ContinueUpdateOnError) {
                                                throw e;
+                                       }
                                }
-                               finally
-                               {
-                                       if (reader != null && !reader.IsClosed)
+                               finally {
+                                       if (reader != null) {
                                                reader.Close ();
-                               }
-                       }
-                       
+                                       }
+                               }       
+                       }               
                        return updateCount;
                }
 
index 5c43eb69c61a299eb2ba0409dfcd7486636a81ac..f29c3d17eafe2176ce2c91b70888958ff8ea7f00 100644 (file)
@@ -32,6 +32,7 @@
 
 using System.ComponentModel;
 using System.Security.Permissions;
+using System.Globalization;
 
 namespace System.Data.Common {
 
index 6dd3f1733cb5871b36e2557e25aa1f4f89e1f753..68a137ba041b46b166b96995763beb0c7b279f49 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.Collections;
 using System.Data;
@@ -55,7 +55,9 @@ namespace System.Data.Common {
                public abstract object this [int index] { get; }
                public abstract object this [string name] { get; }
                public abstract int RecordsAffected { get; }
+#if NET_2_0
                public abstract int VisibleFieldCount { get; }
+#endif
 
                #endregion // Properties
 
@@ -69,18 +71,22 @@ namespace System.Data.Common {
                public abstract char GetChar (int i);
                public abstract long GetChars (int i, long dataIndex, char[] buffer, int bufferIndex, int length);
 
+#if NET_2_0
                [MonoTODO]
                public DbDataReader GetData (int i)
                {
                        throw new NotImplementedException ();
                }
+#endif
 
                public abstract string GetDataTypeName (int i);
                public abstract DateTime GetDateTime (int i);
                public abstract decimal GetDecimal (int i);
                public abstract double GetDouble (int i);
                public abstract IEnumerator GetEnumerator ();
+#if NET_2_0
                public abstract Type GetFieldProviderSpecificType (int i);
+#endif
                public abstract Type GetFieldType (int i);
                public abstract float GetFloat (int i);
                public abstract Guid GetGuid (int i);
@@ -89,8 +95,12 @@ namespace System.Data.Common {
                public abstract long GetInt64 (int i);
                public abstract string GetName (int i);
                public abstract int GetOrdinal (string name);
+
+#if NET_2_0
                public abstract object GetProviderSpecificValue (int i);
                public abstract int GetProviderSpecificValues (object[] values);
+#endif
+
                public abstract DataTable GetSchemaTable ();
                public abstract string GetString (int i);
                public abstract object GetValue (int i);
@@ -145,4 +155,4 @@ namespace System.Data.Common {
        }
 }
 
-#endif // NET_2_0
+#endif
index 69a2013f64d69937f29fd4e327334ff983c2f3ef..6d664fb963d833da8fd67bf98215dc5f201e168c 100644 (file)
@@ -307,7 +307,6 @@ namespace System.Data.Common {
                                new DataColumnPropertyDescriptor[FieldCount];
 
                        DataColumnPropertyDescriptor descriptor;
-                       DataColumn dataColumn;
                        for(int col = 0; col < FieldCount; col++) {
                                descriptor = new DataColumnPropertyDescriptor(
                                        GetName(col), col, null);
index 5ed80c7ce009e21b8c7570a5e91077cc0bbc2fcd..7bb7afccd05298118cbe3073355653174260bb61 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data.Common {
        public abstract class DbDataSourceEnumerator
@@ -52,4 +52,4 @@ namespace System.Data.Common {
        }
 }
 
-#endif // NET_2_0
+#endif
index 50718c50ad2afbd80a819512204f81ff3692c8fd..1c02bbb232269485a4e2ae49feb5bcb91b659d94 100644 (file)
@@ -61,7 +61,7 @@ namespace System.Data.Common {
                        this.closeReader = closeReader;
                        this.lookup = new FieldNameLookup ();
                        this.fieldCount = reader.FieldCount;
-                       LoadSchema (reader.GetSchemaTable ());
+                       LoadSchema ();
                }
 
                #endregion // Constructors
@@ -80,36 +80,21 @@ namespace System.Data.Common {
 
                #region Methods
 
-               private void LoadSchema (DataTable schemaTable)
+               private void LoadSchema ()
                {
                        schema = new SchemaInfo [fieldCount];
-                       int index = 0;
-                       foreach (DataRow row in schemaTable.Rows) {
+
+                       for(int i=0; i < fieldCount; i++) {
                                SchemaInfo columnSchema = new SchemaInfo ();
+                               
+                               lookup.Add (reader.GetName(i));
+
+                               columnSchema.ColumnName = reader.GetName(i);
+                               columnSchema.ColumnOrdinal = i; 
+                               columnSchema.DataTypeName = reader.GetDataTypeName (i);
+                               columnSchema.FieldType = reader.GetFieldType (i);
 
-                               lookup.Add ((string) row["ColumnName"]);
-
-                               columnSchema.AllowDBNull = (bool) row ["AllowDBNull"];
-                               columnSchema.ColumnName = row ["ColumnName"].ToString ();
-                               columnSchema.ColumnOrdinal = (int) row ["ColumnOrdinal"];
-                               columnSchema.ColumnSize = (int) row ["ColumnSize"];
-                               columnSchema.DataTypeName = reader.GetDataTypeName (index);
-                               columnSchema.FieldType = reader.GetFieldType (index);
-                               columnSchema.IsReadOnly = (bool) row ["IsReadOnly"];
-                               columnSchema.TableName = row ["BaseTableName"].ToString ();
-
-                               if (row ["NumericPrecision"] != DBNull.Value)
-                                       columnSchema.NumericPrecision = Convert.ToByte (row ["NumericPrecision"]);
-                               else
-                                       columnSchema.NumericPrecision = Convert.ToByte (0);
-
-                               if (row ["NumericScale"] != DBNull.Value)
-                                       columnSchema.NumericScale = Convert.ToByte (row ["NumericScale"]);
-                               else
-                                       columnSchema.NumericScale = Convert.ToByte (0);
-
-                               schema [index] = columnSchema;
-                               index += 1;
+                               schema [i] = columnSchema;
                        }
                }
 
diff --git a/mcs/class/System.Data/System.Data.Common/DbMetaDataCache.cs b/mcs/class/System.Data/System.Data.Common/DbMetaDataCache.cs
new file mode 100644 (file)
index 0000000..ee279b1
--- /dev/null
@@ -0,0 +1,60 @@
+/*\r
+  * Copyright (c) 2002-2004 Mainsoft Corporation.\r
+  *\r
+  * Permission is hereby granted, free of charge, to any person obtaining a\r
+  * copy of this software and associated documentation files (the "Software"),\r
+  * to deal in the Software without restriction, including without limitation\r
+  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+  * and/or sell copies of the Software, and to permit persons to whom the\r
+  * Software is furnished to do so, subject to the following conditions:\r
+  *\r
+  * The above copyright notice and this permission notice shall be included in\r
+  * all copies or substantial portions of the Software.\r
+  *\r
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+  * DEALINGS IN THE SOFTWARE.\r
+  */\r
+\r
+using System;\r
+using System.Collections;\r
+\r
+using java.sql;\r
+\r
+namespace System.Data.Common\r
+{\r
+       #region AbstractDbMetaDataCache\r
+\r
+       internal abstract class AbstractDbMetaDataCache\r
+       {\r
+               Hashtable _cache;\r
+               const int MINUTES_TIMEOUT = 10;\r
+               private long _timestamp;\r
+\r
+               protected AbstractDbMetaDataCache()\r
+               {\r
+                       _cache = Hashtable.Synchronized(new Hashtable());\r
+               }\r
+\r
+               protected Hashtable Cache \r
+               {\r
+                       get\r
+                       {\r
+                               long now = DateTime.Now.Ticks;\r
+                               if (now - _timestamp > MINUTES_TIMEOUT * TimeSpan.TicksPerMinute)\r
+                               {\r
+                                       _timestamp = now;\r
+                                       _cache.Clear();\r
+                               }\r
+\r
+                               return _cache;\r
+                       }\r
+               }\r
+       }\r
+\r
+       #endregion\r
+}\r
index b4e465728bef7635484c01da05bc179a947b1b8c..3546eb54e8012b37763cb27caa95f7482ef5a0e8 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data.Common {
        public abstract class DbParameter : MarshalByRefObject, IDbDataParameter, IDataParameter
@@ -48,25 +48,28 @@ namespace System.Data.Common {
 
                public abstract DbType DbType { get; set; }
                public abstract ParameterDirection Direction { get; set; }
-               public abstract bool IsNullable { get; set; }
-               public abstract int Offset { get; set; }
                public abstract string ParameterName { get; set; }
                public abstract byte Precision { get; set; }
                public abstract byte Scale { get; set; }
                public abstract int Size { get; set; }
+               public abstract object Value { get; set; }
+               public abstract bool IsNullable { get; set; }
+               public abstract int Offset { get; set; }
                public abstract string SourceColumn { get; set; }
                public abstract DataRowVersion SourceVersion { get; set; }
-               public abstract object Value { get; set; }
 
                #endregion // Properties
 
                #region Methods
 
                public abstract void CopyTo (DbParameter destination);
+
+#if NET_2_0
                public abstract void ResetDbType ();
+#endif
 
                #endregion // Methods
        }
 }
 
-#endif // NET_2_0
+#endif
index 1b5be67f9d25c4927c5e58b42614dda20433ac0b..11fd1f8476533739360d56b0466964daa2361a8f 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.Collections;
 using System.Runtime.InteropServices;
@@ -104,4 +104,4 @@ namespace System.Data.Common {
        }
 }
 
-#endif // NET_2_0
+#endif
index 9a5b71efdc3c7bc5e24a743a9323a4cc09459255..be5f493bd94346961438ca4df3225115e918431b 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.Collections;
 using System.Security;
@@ -118,4 +118,4 @@ namespace System.Data.Common {
        }
 }
 
-#endif // NET_2_0
+#endif
index a368bf3f224a432c772c1e61cd33fd75525a8a6e..846ffed87bcc17d02d2f3777b857816702713825 100644 (file)
@@ -31,7 +31,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data.Common {
        public enum DbProviderSupportedClasses 
index 63e7900b4aa0ae6cba2c89cb881f7cfbae6fc4d4..69666b15787c0c88c20c6b3e4db978e117066d43 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 using System.ComponentModel;
 
@@ -241,4 +241,4 @@ namespace System.Data.Common {
        }
 }
 
-#endif // NET_2_0
+#endif
index c1b7f04dbd6c7eb05eb3d255a4fa3cf9e5c352ab..0c9d3dc1f46d720f9fc5103d208c05b0e4ced8d1 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data.Common {
        public abstract class DbTransaction : MarshalByRefObject, IDbTransaction, IDisposable
@@ -70,4 +70,4 @@ namespace System.Data.Common {
        }
 }
 
-#endif // NET_2_0
+#endif
diff --git a/mcs/class/System.Data/System.Data.Common/DbTypes.cs b/mcs/class/System.Data/System.Data.Common/DbTypes.cs
new file mode 100644 (file)
index 0000000..4deed2f
--- /dev/null
@@ -0,0 +1,76 @@
+using System;\r
+\r
+namespace System.Data.Common\r
+{\r
+       public class DbTypes\r
+       {\r
+#if TARGET_JVM\r
+               #region java.sql.Types constants\r
+\r
+               internal enum JavaSqlTypes {\r
+                       ARRAY = 2003 ,\r
+                       BIGINT = -5, \r
+                       BINARY = -2 ,\r
+                       BIT = -7 ,\r
+                       BLOB = 2004, \r
+                       BOOLEAN = 16, \r
+                       CHAR = 1, \r
+                       CLOB = 2005, \r
+                       DATALINK = 70, \r
+                       DATE = 91, \r
+                       DECIMAL = 3, \r
+                       DISTINCT = 2001, \r
+                       DOUBLE = 8, \r
+                       FLOAT = 6, \r
+                       INTEGER = 4, \r
+                       JAVA_OBJECT = 2000, \r
+                       LONGVARBINARY = -4,\r
+                       LONGVARCHAR = -1, \r
+                       NULL = 0, \r
+                       NUMERIC = 2 ,\r
+                       OTHER = 1111 ,\r
+                       REAL = 7 ,\r
+                       REF = 2006 ,\r
+                       SMALLINT = 5,\r
+                       STRUCT = 2002, \r
+                       TIME = 92, \r
+                       TIMESTAMP = 93, \r
+                       TINYINT = -6, \r
+                       VARBINARY = -3, \r
+                       VARCHAR = 12,\r
+//                     NOTSET = int.MinValue\r
+               }\r
+\r
+\r
+               #endregion // java.sql.Types constants\r
+#endif\r
+\r
+               #region .Net types constants\r
+\r
+               internal static readonly Type TypeOfBoolean = typeof(Boolean);\r
+               internal static readonly Type TypeOfSByte = typeof(SByte);\r
+               internal static readonly Type TypeOfChar = typeof(Char);\r
+               internal static readonly Type TypeOfInt16 = typeof(Int16);\r
+               internal static readonly Type TypeOfInt32 = typeof(Int32);\r
+               internal static readonly Type TypeOfInt64 = typeof(Int64);\r
+               internal static readonly Type TypeOfByte = typeof(Byte);\r
+               internal static readonly Type TypeOfUInt16 = typeof(UInt16);\r
+               internal static readonly Type TypeOfUInt32 = typeof(UInt32);\r
+               internal static readonly Type TypeOfUInt64 = typeof(UInt64);\r
+               internal static readonly Type TypeOfDouble = typeof(Double);\r
+               internal static readonly Type TypeOfSingle = typeof(Single);\r
+               internal static readonly Type TypeOfDecimal = typeof(Decimal);\r
+               internal static readonly Type TypeOfString = typeof(String);\r
+               internal static readonly Type TypeOfDateTime = typeof(DateTime);                \r
+               internal static readonly Type TypeOfObject = typeof(object);\r
+               internal static readonly Type TypeOfGuid = typeof(Guid);\r
+               internal static readonly Type TypeOfType = typeof(Type);\r
+\r
+               // additional types\r
+               internal static readonly Type TypeOfByteArray = typeof(Byte[]);\r
+               internal static readonly Type TypeOfFloat = typeof (float);\r
+               internal static readonly Type TypeOfTimespan = typeof (TimeSpan);\r
+\r
+               #endregion // .Net types constants\r
+       }\r
+}\r
diff --git a/mcs/class/System.Data/System.Data.Common/ExceptionHelper.cs b/mcs/class/System.Data/System.Data.Common/ExceptionHelper.cs
new file mode 100644 (file)
index 0000000..0eb66ea
--- /dev/null
@@ -0,0 +1,224 @@
+//\r
+// System.Data.Common.ExceptionHelper\r
+//\r
+// Author:\r
+//   Boris Kirzner (borisk@mainsoft.com)\r
+//\r
+\r
+using System;\r
+\r
+using java.util;\r
+\r
+namespace System.Data.Common\r
+{\r
+       internal sealed class ExceptionHelper\r
+       {\r
+               sealed class ResourceManager\r
+               {\r
+                       private static readonly ResourceBundle _resourceBundle = ResourceBundle.getBundle("SystemData");\r
+                       \r
+                       internal ResourceManager()\r
+                       {                               \r
+                       }\r
+                       \r
+                       internal string GetString(string key)\r
+                       {\r
+                               return _resourceBundle.getString(key);\r
+                       }\r
+               }\r
+\r
+               static ResourceManager _resourceManager = new ResourceManager();\r
+               \r
+               internal static ArgumentException InvalidSizeValue(int value)\r
+               {\r
+                       string[] args = new string[] {value.ToString()};\r
+                       return new ArgumentException(GetExceptionMessage("ADP_InvalidSizeValue",args));\r
+               }\r
+\r
+               internal static ArgumentOutOfRangeException InvalidDataRowVersion(DataRowVersion value)\r
+               {\r
+                       return InvalidEnumerationValue(typeof(DataRowVersion), (int) value);\r
+               }\r
+                \r
+               internal static ArgumentOutOfRangeException InvalidEnumerationValue(Type type, int value)\r
+               {\r
+                       object[] args = new object[] { type.Name, value.ToString() } ;\r
+                       return new ArgumentOutOfRangeException(GetExceptionMessage("ADP_InvalidEnumerationValue",args));\r
+               }\r
\r
+               internal static ArgumentException InvalidOffsetValue(int value)\r
+               {\r
+                       string[] args = new string[] {value.ToString()};\r
+                       return new ArgumentException(GetExceptionMessage("ADP_InvalidOffsetValue",args));\r
+               }\r
+\r
+               internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterDirection value)\r
+               {\r
+                       return InvalidEnumerationValue(typeof(ParameterDirection), (int) value);\r
+               }\r
+\r
+               internal static InvalidOperationException NoStoredProcedureExists(string procedureName) {\r
+                       object[] args = new object[1] { procedureName } ;\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_NoStoredProcedureExists", args));\r
+               }\r
+\r
+               internal static ArgumentNullException ArgumentNull(string parameter)\r
+               {\r
+                       return new ArgumentNullException(parameter);\r
+               }\r
+\r
+               internal static InvalidOperationException TransactionRequired()\r
+               {\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_TransactionRequired_Execute"));\r
+               }\r
+\r
+               internal static ArgumentOutOfRangeException InvalidOleDbType(int value)\r
+               {\r
+                       string[] args = new string[] {value.ToString()};\r
+                       return new ArgumentOutOfRangeException(GetExceptionMessage("OleDb_InvalidOleDbType",args));\r
+               }\r
\r
+               internal static ArgumentException InvalidDbType(int value)\r
+               {\r
+                       string[] args = new string[] {value.ToString()};\r
+                       return new ArgumentException(GetExceptionMessage("ADP_UnknownDataType",args));\r
+               }\r
+\r
+               internal static InvalidOperationException DeriveParametersNotSupported(Type type,CommandType commandType)\r
+               {\r
+                       string[] args = new string[] {type.ToString(),commandType.ToString()};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_DeriveParametersNotSupported",args));\r
+               }\r
+\r
+               internal static InvalidOperationException ReaderClosed(string mehodName)\r
+               {\r
+                       string[] args = new string[] {mehodName};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_DataReaderClosed",args));\r
+               }\r
+\r
+               internal static ArgumentOutOfRangeException InvalidSqlDbType(int value)\r
+               {\r
+                       string[] args = new string[] {value.ToString()};\r
+                       return new ArgumentOutOfRangeException(GetExceptionMessage("SQL_InvalidSqlDbType",args));\r
+               }\r
+\r
+               internal static ArgumentException UnknownDataType(string type1, string type2)\r
+               {\r
+                       string[] args = new string[] {type1, type2};\r
+                       return new ArgumentException(GetExceptionMessage("ADP_UnknownDataType",args));\r
+               }\r
+\r
+               internal static InvalidOperationException TransactionNotInitialized()\r
+               {\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_TransactionRequired_Execute"));\r
+               }\r
+\r
+               internal static InvalidOperationException ParametersNotInitialized(int parameterPosition,string parameterName,string parameterType)\r
+               {\r
+                       object[] args = new object[] {parameterPosition,parameterName,parameterType};\r
+                       return new InvalidOperationException(GetExceptionMessage("OleDb_UninitializedParameters",args));\r
+               }\r
+\r
+               internal static InvalidOperationException WrongParameterSize(string provider)\r
+               {\r
+                       string[] args = new string[] {provider};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_PrepareParameterSize",args));\r
+               }\r
+\r
+               internal static InvalidOperationException ConnectionNotOpened(string operationName, string connectionState)\r
+               {\r
+                       object[] args = new object[] {operationName,connectionState};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_OpenConnectionRequired_PropertySet",args));\r
+               }\r
+\r
+               internal static InvalidOperationException ConnectionNotInitialized(string methodName)\r
+               {\r
+                       object[] args = new object[] {methodName};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_ConnectionRequired_ExecuteReader",args));\r
+               }\r
+\r
+               internal static InvalidOperationException OpenConnectionRequired(string methodName, object connectionState)\r
+               {\r
+                       object[] args = new object[] {methodName, connectionState};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_OpenConnectionRequired_Fill",args));\r
+               }\r
+\r
+               internal static InvalidOperationException OpenedReaderExists()\r
+               {\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_OpenReaderExists"));\r
+               }\r
+\r
+               internal static InvalidOperationException ConnectionAlreadyOpen(object connectionState)\r
+               {\r
+                       object[] args = new object[] {connectionState};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_ConnectionAlreadyOpen",args));\r
+               }\r
+\r
+               internal static InvalidOperationException ConnectionStringNotInitialized()\r
+               {\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_NoConnectionString"));\r
+               }\r
+\r
+               internal static InvalidOperationException ConnectionIsBusy(object commandType,object connectionState)\r
+               {\r
+                       object[] args = new object[] {commandType.ToString(), connectionState.ToString()};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_CommandIsActive",args));\r
+               }\r
+\r
+               internal static InvalidOperationException NotAllowedWhileConnectionOpen(string propertyName, object connectionState)\r
+               {\r
+                       object[] args = new object[] {propertyName,connectionState};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_OpenConnectionPropertySet",args));\r
+               }\r
+\r
+               internal static ArgumentException OleDbNoProviderSpecified()\r
+               {\r
+                       return new ArgumentException(GetExceptionMessage("OleDb_NoProviderSpecified"));\r
+               }\r
+\r
+               internal static ArgumentException InvalidValueForKey(string key)\r
+               {\r
+                       string[] args = new string[] { key };\r
+                       return new ArgumentException(String.Format("Invalid value for key {0}",args));\r
+               }\r
+\r
+               internal static InvalidOperationException ParameterSizeNotInitialized(int parameterIndex, string parameterName,string parameterType,int parameterSize)\r
+               {\r
+                       object[] args = new object[] { parameterIndex.ToString(),parameterName,parameterType,parameterSize.ToString()};\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_UninitializedParameterSize",args));\r
+               }\r
+\r
+               internal static ArgumentException InvalidUpdateStatus(UpdateStatus status)\r
+               {\r
+                       object[] args = new object[] { status };\r
+                       return new ArgumentException(GetExceptionMessage("ADP_InvalidUpdateStatus",args));\r
+               }\r
+\r
+               internal static InvalidOperationException UpdateRequiresCommand(string command)\r
+               {\r
+                       return new InvalidOperationException(GetExceptionMessage("ADP_UpdateRequiresCommand" + command));\r
+               }\r
+\r
+               internal static DataException RowUpdatedError()\r
+               {\r
+                       return new DataException(GetExceptionMessage("ADP_RowUpdatedErrors"));\r
+               }\r
+\r
+               internal static string GetExceptionMessage(string key,object[] args)\r
+               {\r
+                       string exceptionMessage = _resourceManager.GetString(key);\r
+\r
+                       if ((args == null) || (args.Length == 0)) {\r
+                               return exceptionMessage;\r
+                       }\r
+                       else {\r
+                               return String.Format(exceptionMessage,args);\r
+                       }\r
+               }\r
+\r
+               internal static string GetExceptionMessage(string key)\r
+               {\r
+                       return GetExceptionMessage(key,null);\r
+               }\r
+       }\r
+}\r
diff --git a/mcs/class/System.Data/System.Data.Common/Index.cs b/mcs/class/System.Data/System.Data.Common/Index.cs
new file mode 100644 (file)
index 0000000..868d702
--- /dev/null
@@ -0,0 +1,653 @@
+//\r
+// System.Data.Common.Key.cs\r
+//\r
+// Author:\r
+//   Boris Kirzner  <borisk@mainsoft.com>\r
+//   Konstantin Triger (kostat@mainsoft.com)\r
+//\r
+\r
+/*\r
+  * Copyright (c) 2002-2004 Mainsoft Corporation.\r
+  *\r
+  * Permission is hereby granted, free of charge, to any person obtaining a\r
+  * copy of this software and associated documentation files (the "Software"),\r
+  * to deal in the Software without restriction, including without limitation\r
+  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+  * and/or sell copies of the Software, and to permit persons to whom the\r
+  * Software is furnished to do so, subject to the following conditions:\r
+  *\r
+  * The above copyright notice and this permission notice shall be included in\r
+  * all copies or substantial portions of the Software.\r
+  *\r
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+  * DEALINGS IN THE SOFTWARE.\r
+  */\r
+\r
+using System;\r
+using System.Collections;\r
+\r
+using System.Text;\r
+\r
+namespace System.Data.Common\r
+{\r
+       enum IndexDuplicatesState { Unknown, True, False }; \r
+       /// <summary>\r
+       /// Summary description for Index.\r
+       /// </summary>\r
+       internal class Index\r
+       {\r
+               #region Fields\r
+\r
+               int[] _array;\r
+               int _size;\r
+               Key _key;\r
+               int _refCount = 0;\r
+               IndexDuplicatesState _hasDuplicates;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               internal Index(Key key)\r
+               {\r
+                       _key = key;\r
+                       Reset();\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Properties\r
+\r
+               internal Key Key \r
+               {\r
+                       get {\r
+                               return _key;\r
+                       }\r
+               }\r
+\r
+               internal int Size\r
+               {\r
+                       get {\r
+                               EnsureArray();\r
+                               return _size;\r
+                       }\r
+               }\r
+\r
+               internal int RefCount\r
+               {\r
+                       get {\r
+                               return _refCount;\r
+                       }\r
+               }\r
+\r
+               internal int IndexToRecord(int index){\r
+                       return index < 0 ? index : Array[index];\r
+               }\r
+\r
+               private int[] Array\r
+               {\r
+                       get {\r
+                               EnsureArray();\r
+                               return _array;\r
+                       }\r
+               }\r
+\r
+               internal bool HasDuplicates\r
+               {\r
+                       get {\r
+                               if (_array == null || _hasDuplicates == IndexDuplicatesState.Unknown) {\r
+                                       EnsureArray();\r
+                                       if (_hasDuplicates == IndexDuplicatesState.Unknown) {\r
+                                               // check for duplicates\r
+                                               _hasDuplicates = IndexDuplicatesState.False;\r
+                                               for(int i = 0; i < Size - 1; i++) {\r
+                                                       if (Key.CompareRecords(Array[i],Array[i+1]) == 0) {\r
+                                                               _hasDuplicates = IndexDuplicatesState.True;\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }\r
+                               return (_hasDuplicates == IndexDuplicatesState.True);\r
+                       }\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+\r
+               internal int[] Duplicates {\r
+                       get {\r
+                               if (!HasDuplicates)\r
+                                       return null;\r
+\r
+                               ArrayList dups = new ArrayList();\r
+\r
+                               bool inRange = false;\r
+                               for(int i = 0; i < Size - 1; i++) {\r
+                                       if (Key.CompareRecords(Array[i],Array[i+1]) == 0){\r
+                                               if (!inRange) {\r
+                                                       dups.Add(Array[i]);\r
+                                                       inRange = true;\r
+                                               }\r
+\r
+                                               dups.Add(Array[i+1]);\r
+                                       }\r
+                                       else\r
+                                               inRange = false;\r
+                               }\r
+\r
+                               return (int[])dups.ToArray(typeof(int));\r
+                       }\r
+               }\r
+\r
+               private void EnsureArray()\r
+               {\r
+                       if (_array == null) {\r
+                               RebuildIndex();\r
+                       }\r
+               }\r
+\r
+               internal int[] GetAll()\r
+               {\r
+                       return Array;\r
+               }\r
+\r
+               internal void Reset()\r
+               {\r
+                       _array = null;\r
+               }\r
+\r
+               private void RebuildIndex()\r
+               {\r
+                       // consider better capacity approximation\r
+                       _array = new int[Key.Table.RecordCache.CurrentCapacity];\r
+                       _size = 0;\r
+                       foreach(DataRow row in Key.Table.Rows) {\r
+                               int record = Key.GetRecord(row);\r
+                               if (record != -1) {\r
+                                       _array[_size++] = record;\r
+                               }\r
+                       }\r
+                       _hasDuplicates = IndexDuplicatesState.False;\r
+                       // Note : MergeSort may update hasDuplicates to True\r
+                       Sort();\r
+               }\r
+\r
+               private void Sort()\r
+               {\r
+                       //QuickSort(Array,0,Size-1);\r
+                       MergeSort(Array,Size);\r
+               }\r
+               \r
+               /*\r
+                * Returns record number of the record equal to the key values supplied \r
+                * in the meaning of index key, or -1 if no equal record found.\r
+                */\r
+               internal int Find(object[] keys)\r
+               {\r
+                       int index = FindIndex(keys);\r
+                       return IndexToRecord(index);\r
+               }\r
+\r
+               /*\r
+                * Returns record index (location) of the record equal to the key values supplied \r
+                * in the meaning of index key, or -1 if no equal record found.\r
+                */\r
+               internal int FindIndex(object[] keys)\r
+               {\r
+                       if (keys == null || keys.Length != Key.Columns.Length) {\r
+                               throw new ArgumentException("Expecting " + Key.Columns.Length + " value(s) for the key being indexed, " +\r
+                                       "but received " + ((keys == null) ? 0 : keys.Length) + " value(s).");\r
+                       }\r
+\r
+                       int tmp = Key.Table.RecordCache.NewRecord();\r
+                       try {\r
+                               // init key values for temporal record\r
+                               for(int i = 0; i < Key.Columns.Length; i++) {\r
+                                       Key.Columns[i].DataContainer[tmp] = keys[i];\r
+                               }\r
+                               return FindIndex(tmp);\r
+                       }\r
+//                     catch(FormatException) {\r
+//                             return -1;\r
+//                     }\r
+//                     catch(InvalidCastException) {\r
+//                             return -1;\r
+//                     }\r
+                       finally {\r
+                               Key.Table.RecordCache.DisposeRecord(tmp);\r
+                       }\r
+               }\r
+\r
+               /*\r
+                * Returns record number of the record equal to the record supplied \r
+                * in the meaning of index key, or -1 if no equal record found.\r
+                */\r
+               internal int Find(int record)\r
+               {\r
+                       int index = FindIndex(record);\r
+                       return IndexToRecord(index);\r
+               }\r
+\r
+               /*\r
+                * Returns array of record numbers of the records equal equal to the key values supplied \r
+                * in the meaning of index key, or -1 if no equal record found.\r
+                */\r
+               internal int[] FindAll(object[] keys)\r
+               {\r
+                       int[] indexes = FindAllIndexes(keys);\r
+                       IndexesToRecords(indexes);\r
+                       return indexes;\r
+               }\r
+\r
+               /*\r
+                * Returns array of indexes of the records inside the index equal equal to the key values supplied \r
+                * in the meaning of index key, or -1 if no equal record found.\r
+                */\r
+               internal int[] FindAllIndexes(object[] keys)\r
+               {\r
+                       if (keys == null || keys.Length != Key.Columns.Length) {\r
+                               throw new ArgumentException("Expecting " + Key.Columns.Length + " value(s) for the key being indexed," +\r
+                                       "but received " + ((keys == null) ? 0 : keys.Length) + " value(s).");\r
+                       }\r
+\r
+                       int tmp = Key.Table.RecordCache.NewRecord();\r
+                       try {\r
+                               // init key values for temporal record\r
+                               for(int i = 0; i < Key.Columns.Length; i++) {\r
+                                       Key.Columns[i].DataContainer[tmp] = keys[i];\r
+                               }\r
+                               return FindAllIndexes(tmp);\r
+                       }\r
+                       catch(FormatException) {\r
+                               return new int[0];\r
+                       }\r
+                       catch(InvalidCastException) {\r
+                               return new int[0];\r
+                       }\r
+                       finally {\r
+                               Key.Table.RecordCache.DisposeRecord(tmp);\r
+                       }\r
+               }\r
+\r
+               /*\r
+                * Returns array of record numbers of the records equal to the record supplied \r
+                * in the meaning of index key, or empty list if no equal records found.\r
+                */\r
+               internal int[] FindAll(int record)\r
+               {\r
+                       int[] indexes = FindAllIndexes(record);\r
+            IndexesToRecords(indexes);\r
+                       return indexes;\r
+               }\r
+\r
+               /*\r
+                * Returns array of indexes of the records inside the index that equal to the record supplied \r
+                * in the meaning of index key, or empty list if no equal records found.\r
+                */\r
+               internal int[] FindAllIndexes(int record)\r
+               {\r
+                       int index = FindIndex(record);\r
+\r
+                       if (index == -1) {\r
+                               return new int[0];\r
+                       }\r
+\r
+                       int startIndex = index++;\r
+                       int endIndex = index;\r
+                       \r
+                       for(;startIndex >= 0 && Key.CompareRecords(Array[startIndex],record) == 0;startIndex--);\r
+                       for(;endIndex < Size && Key.CompareRecords(Array[endIndex],record) == 0;endIndex++);\r
+                       \r
+                       int length = endIndex - startIndex - 1;\r
+                       int[] indexes = new int[length];\r
+                       \r
+                       for(int i = 0; i < length; i++) {\r
+                               indexes[i] = ++startIndex;\r
+                       }\r
+                       \r
+                       return indexes;\r
+               }\r
+\r
+               /*\r
+                * Returns index inside the array where record number of the record equal to the record supplied \r
+                * in the meaning of index key is sored, or -1 if no equal record found.\r
+                */\r
+               private int FindIndex(int record)\r
+               {\r
+                       if (Size == 0) {\r
+                               return -1;\r
+                       }\r
+                       return BinarySearch(Array,0,Size - 1,record);\r
+               }\r
+\r
+               /*\r
+                * Finds exact location of the record specified\r
+                */ \r
+               private int FindIndexExact(int record)\r
+               {\r
+                       int index = System.Array.BinarySearch(Array,record);\r
+                       return (index > 0) ? index : -1;\r
+               }\r
+\r
+               /*\r
+                * Returns array of records from the indexes (locations) inside the index\r
+                */\r
+               private void IndexesToRecords(int[] indexes)\r
+               {\r
+                       for(int i = 0; i < indexes.Length; i++) {\r
+                               indexes[i] = Array[indexes[i]];\r
+                       }\r
+               }\r
+\r
+               internal void Delete(DataRow row)\r
+               {\r
+                       int oldRecord = Key.GetRecord(row);\r
+\r
+                       Delete(oldRecord);\r
+               }\r
+\r
+               internal void Delete(int oldRecord)\r
+               {\r
+                       int index = FindIndex(oldRecord);\r
+                       if (index != -1) {\r
+                               if ((_hasDuplicates == IndexDuplicatesState.True)) {\r
+                                       int c1 = 1;\r
+                                       int c2 = 1;\r
+\r
+                                       if (index > 0) {\r
+                                               c1 = Key.CompareRecords(Array[index - 1],oldRecord);\r
+                                       }\r
+                                       if (index < Size - 1) {\r
+                                               c2 = Key.CompareRecords(Array[index + 1],oldRecord);\r
+                                       }\r
+\r
+                                       if (c1 == 0 ^ c2 == 0) {\r
+                                               _hasDuplicates = IndexDuplicatesState.Unknown;\r
+                                       }\r
+                               }\r
+                               Remove(index);\r
+                       }\r
+               }\r
+\r
+               private void Remove(int index)\r
+               {\r
+                       if (Size > 1) {\r
+                               System.Array.Copy(Array,index+1,Array,index,Size - index);\r
+                       }\r
+                       _size--;\r
+               }\r
+\r
+               internal void Update(DataRow row,int newRecord)\r
+               {\r
+                       int oldRecord = Key.GetRecord(row);\r
+\r
+                       if (oldRecord == -1 || Size == 0) {\r
+                               Add(row,newRecord);\r
+                               return;\r
+                       }\r
+\r
+                       int oldIdx = FindIndex(oldRecord);\r
+\r
+                       if( oldIdx == -1 || Key.Table.RecordCache[Array[oldIdx]] != row ) {\r
+                               Add(row,newRecord);\r
+                               return;\r
+                       }\r
+                               \r
+                       int newIdx = -1;\r
+                       int compare = Key.CompareRecords(Array[oldIdx],newRecord);\r
+                       int start,end;\r
+\r
+                       int c1 = 1;\r
+                       int c2 = 1;\r
+\r
+                       if (compare == 0) {\r
+                               if (Array[oldIdx] == newRecord) {\r
+                                       // we deal with the same record that didn't change\r
+                                       // in the context of current index.\r
+                                       // so , do nothing.\r
+                                       return;\r
+                               }\r
+                       }\r
+                       else {\r
+                               if ((_hasDuplicates == IndexDuplicatesState.True)) {\r
+                                       if (oldIdx > 0) {\r
+                                               c1 = Key.CompareRecords(Array[oldIdx - 1],newRecord);\r
+                                       }\r
+                                       if (oldIdx < Size - 1) {\r
+                                               c2 = Key.CompareRecords(Array[oldIdx + 1],newRecord);\r
+                                       }\r
+\r
+                                       if ((c1 == 0 ^ c2 == 0) && compare != 0) {\r
+                                               _hasDuplicates = IndexDuplicatesState.Unknown;\r
+                                       }\r
+                               }\r
+                       }\r
+                       \r
+                       if ((oldIdx == 0 && compare > 0) || (oldIdx == (Size - 1) && compare < 0) || (compare == 0)) {\r
+                               // no need to switch cells\r
+                               newIdx = oldIdx;\r
+                       }\r
+                       else {\r
+                               if (compare < 0) {\r
+                                       // search after the old place\r
+                                       start = oldIdx + 1;\r
+                                       end = Size - 1;\r
+                               }\r
+                               else {\r
+                                       // search before the old palce\r
+                                       start = 0;\r
+                                       end = oldIdx - 1;\r
+                               }\r
+\r
+                               newIdx = LazyBinarySearch(Array,start,end,newRecord);                                   \r
+\r
+                               if (oldIdx < newIdx) {\r
+                                       System.Array.Copy(Array,oldIdx + 1,Array,oldIdx,newIdx - oldIdx);\r
+                               }\r
+                               else if (oldIdx > newIdx){\r
+                                       System.Array.Copy(Array,newIdx,Array,newIdx + 1,oldIdx - newIdx);\r
+                               }\r
+                       }                       \r
+                       Array[newIdx] = newRecord;\r
+\r
+                       if (compare != 0) {\r
+                               if (!(_hasDuplicates == IndexDuplicatesState.True)) {\r
+                                       if (newIdx > 0) {\r
+                                               c1 = Key.CompareRecords(Array[newIdx - 1],newRecord);\r
+                                       }\r
+                                       if (newIdx < Size - 1) {\r
+                                               c2 = Key.CompareRecords(Array[newIdx + 1],newRecord);\r
+                                       }\r
+\r
+                                       if (c1 == 0 || c2 == 0) {\r
+                                               _hasDuplicates = IndexDuplicatesState.True;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void Add(DataRow row,int newRecord)\r
+               {\r
+                       int newIdx;\r
+                       if (Size == 0) {\r
+                               newIdx = 0;\r
+                       }\r
+                       else {\r
+                               newIdx = LazyBinarySearch(Array,0,Size - 1,newRecord);\r
+                               // if newl value is greater - insert afer old value\r
+                               // else - insert before old value\r
+                               if (Key.CompareRecords(Array[newIdx],newRecord) < 0) {\r
+                                       newIdx++;\r
+                               }\r
+                       }\r
+                                       \r
+                       Insert(newIdx,newRecord);\r
+\r
+                       int c1 = 1;\r
+                       int c2 = 1;\r
+                       if (!(_hasDuplicates == IndexDuplicatesState.True)) {\r
+                               if (newIdx > 0) {\r
+                                       c1 = Key.CompareRecords(Array[newIdx - 1],newRecord);\r
+                               }\r
+                               if (newIdx < Size - 1) {\r
+                                       c2 = Key.CompareRecords(Array[newIdx + 1],newRecord);\r
+                               }\r
+\r
+                               if (c1 == 0 || c2 == 0) {\r
+                                       _hasDuplicates = IndexDuplicatesState.True;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void Insert(int index,int r)\r
+               {\r
+                       if (Array.Length == Size) {\r
+                               int[] tmp = (Size == 0) ? new int[16] : new int[Size << 1];\r
+                               System.Array.Copy(Array,0,tmp,0,index);\r
+                               tmp[index] = r;\r
+                               System.Array.Copy(Array,index,tmp,index + 1,Size - index);\r
+                               _array = tmp;\r
+                       }\r
+                       else {\r
+                               System.Array.Copy(Array,index,Array,index + 1,Size - index);\r
+                               Array[index] = r;\r
+                       }\r
+                       _size++;\r
+               }\r
+\r
+               private void MergeSort(int[] to, int length)\r
+        {\r
+            int[] from = new int[length];\r
+            System.Array.Copy(to, 0, from, 0, from.Length);\r
+\r
+            MergeSort(from, to, 0, from.Length);\r
+        }\r
+\r
+        private void MergeSort(int[] from, int[] to,int p, int r)\r
+        {\r
+            int q = (p + r) >> 1;\r
+               if (q == p) {\r
+                return;\r
+            }        \r
+\r
+            MergeSort(to, from, p, q);\r
+            MergeSort(to, from, q, r);\r
+\r
+            // merge\r
+            for (int middle = q, current = p;;) {\r
+                               int res = Key.CompareRecords(from[p],from[q]);\r
+                if (res > 0) {\r
+                    to[current++] = from[q++];\r
+\r
+                    if (q == r) {\r
+                        while( p < middle) {\r
+                                to[current++] = from[p++];\r
+                                               }\r
+                        break;\r
+                    }\r
+                }\r
+                else {\r
+\r
+                                       if (res == 0) {\r
+                                               _hasDuplicates = IndexDuplicatesState.True;\r
+                                       }\r
+\r
+                    to[current++] = from[p++];\r
+\r
+                    if (p == middle) {\r
+                        while( q < r) {\r
+                                to[current++] = from[q++];\r
+                                               }\r
+                        break;\r
+                    }\r
+                }\r
+            }\r
+               }\r
+\r
+               private void QuickSort(int[] a,int p,int r)\r
+               {\r
+                       if (p < r) {\r
+                               int q = Partition(a,p,r);\r
+                               QuickSort(a,p,q);\r
+                               QuickSort(a,q+1,r);\r
+                       }\r
+               }\r
+\r
+               private int Partition(int[] a,int p,int r)\r
+               {\r
+                       int x = a[p];\r
+                       int i = p - 1;\r
+                       int j = r + 1;\r
+\r
+                       while(true) {\r
+                               // decrement upper limit while values are greater then border value\r
+                               do {\r
+                                       j--;\r
+                               }\r
+                               while(Key.CompareRecords(a[j],x) > 0);  //while(a[j] > x);\r
+\r
+                               do {\r
+                                       i++;\r
+                               }\r
+                               while(Key.CompareRecords(a[i],x) < 0);  //while(a[i] < x);\r
+                               \r
+                               if (i<j) {\r
+                                       int tmp = a[j];\r
+                                       a[j] = a[i];\r
+                                       a[i] = tmp;\r
+                               }\r
+                               else {\r
+                                       return j;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private int BinarySearch(int[] a, int p, int r,int b)\r
+               {\r
+                       int i = LazyBinarySearch(a,p,r,b);\r
+\r
+                       return (Key.CompareRecords(a[i],b) == 0) ? i : -1;\r
+               }\r
+\r
+               // Lazy binary search only returns the cell number the search finished in,\r
+               // but does not checks that the correct value was actually found\r
+               private int LazyBinarySearch(int[] a, int p, int r,int b)\r
+               {\r
+                       if ( p == r ) {\r
+                               return p;\r
+                       }\r
+\r
+                       int q = (p+r) >> 1;\r
+\r
+                       int compare = Key.CompareRecords(a[q],b);\r
+                       if (compare < 0) { // if (a[q] < b) {\r
+                               return LazyBinarySearch(a,q+1,r,b);\r
+                       }\r
+                       else if (compare > 0) { // a[q] > b\r
+                               return LazyBinarySearch(a,p,q,b);\r
+                       }       \r
+                       else { // a[q] == b\r
+                               return q;\r
+                       }\r
+               }\r
+\r
+               internal void AddRef()\r
+               {\r
+                       _refCount++;\r
+               }\r
+\r
+               internal void RemoveRef()\r
+               {\r
+                       _refCount--;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+}\r
diff --git a/mcs/class/System.Data/System.Data.Common/Key.cs b/mcs/class/System.Data/System.Data.Common/Key.cs
new file mode 100644 (file)
index 0000000..8433277
--- /dev/null
@@ -0,0 +1,226 @@
+//\r
+// System.Data.Common.Key.cs\r
+//\r
+// Author:\r
+//   Boris Kirzner  <borisk@mainsoft.com>\r
+//   Konstantin Triger (kostat@mainsoft.com)\r
+//\r
+\r
+/*\r
+  * Copyright (c) 2002-2004 Mainsoft Corporation.\r
+  *\r
+  * Permission is hereby granted, free of charge, to any person obtaining a\r
+  * copy of this software and associated documentation files (the "Software"),\r
+  * to deal in the Software without restriction, including without limitation\r
+  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+  * and/or sell copies of the Software, and to permit persons to whom the\r
+  * Software is furnished to do so, subject to the following conditions:\r
+  *\r
+  * The above copyright notice and this permission notice shall be included in\r
+  * all copies or substantial portions of the Software.\r
+  *\r
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+  * DEALINGS IN THE SOFTWARE.\r
+  */\r
+\r
+using System;\r
+using Mono.Data.SqlExpressions;\r
+using System.ComponentModel;\r
+\r
+namespace System.Data.Common\r
+{\r
+       internal class Key\r
+       {\r
+               #region Fields\r
+\r
+               DataTable _table;\r
+               DataColumn[] _columns;\r
+               ListSortDirection[] _sortDirection;\r
+               DataViewRowState _rowStateFilter;\r
+               IExpression _filter;\r
+               //Currently IExpression.Eval does not receive DataRowVersion\r
+               //      and always uses the _current version\r
+               //so need a temp row for Eval calls\r
+               DataRow _tmpRow;\r
+\r
+               #endregion //Fields\r
+\r
+               #region Constructors\r
+\r
+               internal Key(DataTable table,DataColumn[] columns,ListSortDirection[] sort, DataViewRowState rowState, IExpression filter)\r
+               {\r
+                       _table = table;\r
+                       _filter = filter;\r
+                       if (_filter != null)\r
+                               _tmpRow = _table.NewNotInitializedRow();\r
+                       _columns = columns;\r
+                       if (sort != null && sort.Length == columns.Length) {\r
+                               _sortDirection = sort;\r
+                       }\r
+                       else {\r
+                               _sortDirection = new ListSortDirection[columns.Length];\r
+                               for(int i=0; i < _sortDirection.Length; i++) {\r
+                                       _sortDirection[i] = ListSortDirection.Ascending;\r
+                               }\r
+                       }\r
+\r
+                       if (rowState != DataViewRowState.None) {\r
+                               _rowStateFilter = rowState;\r
+                       }\r
+                       else {\r
+                               // FIXME : what is the correct value ?\r
+                               _rowStateFilter = DataViewRowState.CurrentRows;\r
+                       }\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Properties\r
+\r
+               internal DataColumn[] Columns\r
+               {\r
+                       get {\r
+                               return _columns;\r
+                       }\r
+               }\r
+\r
+               internal DataTable Table\r
+               {\r
+                       get {\r
+                               return _table;\r
+                       }\r
+               }\r
+\r
+               ListSortDirection[] Sort \r
+               {\r
+                       get {\r
+                               return _sortDirection;\r
+                       }\r
+               }\r
+\r
+               internal DataViewRowState RowStateFilter\r
+               {\r
+                       get {\r
+                               return _rowStateFilter;\r
+                       }\r
+\r
+                       set {\r
+                               _rowStateFilter = value;\r
+                       }\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+\r
+               internal int CompareRecords(int first, int second)\r
+               {\r
+                       if (first == second) {\r
+                               return 0;\r
+                       }\r
+\r
+                       for(int i = 0; i < Columns.Length; i++) {\r
+\r
+                               int res = Columns[i].CompareValues(first,second);\r
+\r
+                               if (res == 0) {\r
+                                       continue;\r
+                               }\r
+\r
+                               return (Sort[i] == ListSortDirection.Ascending) ? res : -res;\r
+                       }\r
+                       return 0;\r
+               }\r
+\r
+               internal int GetRecord(DataRow row)\r
+               {\r
+                       int index = Key.GetRecord(row,_rowStateFilter);\r
+                       if (_filter == null)\r
+                               return index;\r
+\r
+                       if (index < 0)\r
+                               return index;\r
+\r
+                       _tmpRow._current = index;\r
+                       return _filter.EvalBoolean(_tmpRow) ? index : -1;\r
+               }\r
+\r
+               internal static int GetRecord(DataRow row, DataViewRowState rowStateFilter)\r
+               {\r
+\r
+                       if (row.Original == row.Current) {\r
+                                if ((rowStateFilter & DataViewRowState.Unchanged) != DataViewRowState.None) {\r
+                                        return row.Current;\r
+                                }\r
+                       }\r
+                       else if (row.Original == -1) {\r
+                                 if ((rowStateFilter & DataViewRowState.Added) != DataViewRowState.None) {\r
+                                       return row.Current;\r
+                                 }\r
+                       }\r
+                       else if (row.Current == -1) {\r
+                                    if ((rowStateFilter & DataViewRowState.Deleted) != DataViewRowState.None) {\r
+                                               return row.Original;\r
+                                        }\r
+                       }\r
+                       else if ((rowStateFilter & DataViewRowState.ModifiedCurrent) != DataViewRowState.None) {\r
+                               return row.Current;\r
+                       }\r
+                       else if ((rowStateFilter & DataViewRowState.ModifiedOriginal) != DataViewRowState.None) {\r
+                               return row.Original;\r
+                       }\r
+\r
+            return -1;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Checks for key equality to parameters set given\r
+               /// </summary>\r
+               /// <param name="columns">Columns the key consits of. If this parameter is null, it does not affects equality check</param>\r
+               /// <param name="sort">Sort order of columns. If this parameter is null, it does not affects equality check</param>\r
+               /// <param name="rowState">DataViewRowState to check for.If this parameter is null, it does not affects equality check</param>\r
+               /// <param name="unique">Indicates whenever the index managed by this key allows non-uniqie keys to appear.</param>\r
+               /// <param name="strict">Indicates whenever unique parameter should affect the equality check.</param>\r
+               /// <returns></returns>\r
+               internal bool Equals(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter) \r
+               {\r
+                       if (rowState != DataViewRowState.None && RowStateFilter != rowState) {\r
+                               return false;\r
+                       }\r
+\r
+                       if (_filter != filter)\r
+                               return false;\r
+\r
+                       if (Columns.Length != columns.Length) {\r
+                               return false;\r
+                       }\r
+\r
+                       if (sort != null && Sort.Length != sort.Length) {\r
+                               return false;\r
+                       }\r
+\r
+                       if (sort != null) {\r
+                               for(int i=0; i < columns.Length; i++) {\r
+                                       if (Sort[i] != sort[i] || Columns[i] != columns[i]) {\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                       }\r
+                       else {\r
+                               for(int i=0; i < columns.Length; i++) {\r
+                                       if (Columns[i] != columns[i]) {\r
+                                               return false;\r
+                                       }\r
+                               }\r
+                       }\r
+                       return true;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+}\r
index 92bf0d239bcabe2c93acf1d5b4a08cb5b236fc24..7338240e1e03f66c6e417d4b7d85bbecf497ea2b 100644 (file)
@@ -36,6 +36,7 @@ namespace System.Data.Common
                int _nextFreeIndex = 0;
                int _currentCapacity = 0;
                DataTable _table;
+               DataRow[] _rowsToRecords;
 
                #endregion // Fields
 
@@ -44,6 +45,7 @@ namespace System.Data.Common
                internal RecordCache(DataTable table)
                {
                        _table = table;
+                       _rowsToRecords = table.NewRowArray(16);
                }
 
                #endregion //Constructors
@@ -57,6 +59,19 @@ namespace System.Data.Common
                        }
                }
 
+               internal DataRow this[int index]
+               {
+                       get {
+                               return _rowsToRecords[index];
+                       }
+
+                       set {
+                               if (index >= 0) {
+                                       _rowsToRecords[index] = value;
+                               }
+                       }
+               }
+
                #endregion // Properties
 
                #region Methods
@@ -76,6 +91,10 @@ namespace System.Data.Common
                                        foreach(DataColumn col in cols) {
                                                col.DataContainer.Capacity = _currentCapacity;
                                        }
+
+                                       DataRow[] old = _rowsToRecords;
+                                       _rowsToRecords = _table.NewRowArray(_currentCapacity);
+                                       Array.Copy(old,0,_rowsToRecords,0,old.Length);
                                }
                                return _nextFreeIndex++;
                        }
@@ -86,9 +105,8 @@ namespace System.Data.Common
                        if ( index < 0 ) {
                                throw new ArgumentException();
                        }
-                        if (! _records.Contains (index)) {
-                                _records.Push(index);
-                        }
+                       _records.Push(index);
+                       this[index] = null;
                }
 
                internal int CopyRecord(DataTable fromTable,int fromRecordIndex,int toRecordIndex)
@@ -98,30 +116,49 @@ namespace System.Data.Common
                                recordIndex = NewRecord();
                        }
 
-                       foreach(DataColumn fromColumn in fromTable.Columns) {
-                               DataColumn column = _table.Columns[fromColumn.ColumnName];
-                               if (column != null) {
-                                       column.DataContainer.CopyValue(fromColumn.DataContainer,fromRecordIndex,recordIndex);
+                       try
+                       {
+                               foreach(DataColumn fromColumn in fromTable.Columns) 
+                               {
+                                       DataColumn column = _table.Columns[fromColumn.ColumnName];
+                                       if (column != null) 
+                                       {
+                                               column.DataContainer.CopyValue(fromColumn.DataContainer,fromRecordIndex,recordIndex);
+                                       }
                                }
+
+                               return recordIndex;
                        }
+                       catch
+                       {
+                               if (toRecordIndex == -1)
+                                       DisposeRecord(recordIndex);
 
-                       return recordIndex;
+                               throw;
+                       }
                }
 
-                /// <summary>
-                ///     Compares two records in the given data table. The numbers are the offset
-                ///     into the container tables.
-                /// </summary>
-                internal static bool CompareRecords (DataTable table, int x, int y)
-                {
-                        foreach (DataColumn dc in table.Columns) {
-                                if (dc.DataContainer.CompareValues (x, y) != 0)
-                                        return false;
-                        }
-                        return true;
-                }
-                
-               #endregion // Methods
+               internal void ReadIDataRecord(int recordIndex, IDataRecord record, int[] mapping, int length)
+               {
+                       if ( mapping.Length > _table.Columns.Count)
+                               throw new ArgumentException ();
+
+                       int i=0;
+                       for(; i < length; i++) {
+                               DataColumn column = _table.Columns[mapping[i]];
+                               column.DataContainer.SetItemFromDataRecord(recordIndex, record,i);
+                       }
 
+                       for (; i < mapping.Length; i++)
+                       {
+                               DataColumn column = _table.Columns[mapping[i]];
+                               if ( column.AutoIncrement ) 
+                                       column.DataContainer[recordIndex] = column.AutoIncrementValue ();
+                               else
+                                       column.DataContainer[recordIndex] = column.DefaultValue;
+                       }
+               }
+
+               #endregion // Methods
        }
 }
index b270c61899caa014abf55c9bdc28fb47e3fbc6e4..da645ca64fc0561f159bf1154ca0c5ba17a578d9 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data.Common {
        public enum SchemaLocation 
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBCommand.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBCommand.cs
new file mode 100644 (file)
index 0000000..5174651
--- /dev/null
@@ -0,0 +1,751 @@
+//namespace System.Data.Common\r
+//{\r
+//\r
+//     using java.sql;\r
+//     using java.util;\r
+//\r
+//     using System;\r
+//     using System.Collections;\r
+//     using System.Data;\r
+//     using System.Data.ProviderBase;\r
+//\r
+//     /**\r
+//      * @author erand\r
+//      */\r
+//     public abstract class AbstractDBCommand : DbCommandBase\r
+//     {\r
+//             protected String _cmdText, _javaCmdText;\r
+//             protected AbstractDBConnection _connection;\r
+//             protected IDbTransaction _transaction;\r
+//             protected int _cmdTimeout = 30;\r
+//             protected CommandType _cmdType = CommandType.Text;\r
+//             protected UpdateRowSource _updateRowSource = UpdateRowSource.Both;\r
+//             protected Statement _statement;\r
+//             protected IDataParameterCollection _paramCollection;\r
+//             protected IDataReader _reader;\r
+//             private bool _isCommandTextChanged;\r
+//             private CommandBehavior _behvior = CommandBehavior.Default;\r
+//\r
+//             private static readonly int _oracleRefCursor;\r
+//             protected const int oracleTypeRefCursor = 1111; // Types.OTHER\r
+//        \r
+//        \r
+//             static AbstractDBCommand()\r
+//             {\r
+//                     try {\r
+//                             java.lang.Class OracleTypesClass = java.lang.Class.forName("oracle.jdbc.OracleTypes");\r
+//                             _oracleRefCursor = OracleTypesClass.getField("CURSOR").getInt(null);\r
+//                     }\r
+//                     catch(java.lang.ClassNotFoundException e) {\r
+//                             // oracle driver is not in classpath - just continue\r
+//                     }\r
+//             }\r
+//\r
+//             public AbstractDBCommand(\r
+//                     String cmdText,\r
+//                     AbstractDBConnection connection,\r
+//                     IDbTransaction transaction)\r
+//             {\r
+//                     _connection = connection;\r
+//                     _cmdText = cmdText;\r
+//                     _transaction = transaction;\r
+//                     _isCommandTextChanged = true;\r
+//             }\r
+//    \r
+//             public java.sql.Statement Statement\r
+//             {\r
+//                     get\r
+//                     {\r
+//                             return _statement;\r
+//                     }\r
+//                     set\r
+//                     {\r
+//                             _statement = value;\r
+//                     }\r
+//             }\r
+//\r
+//             public virtual String JavaCommandText\r
+//             {\r
+//                     get\r
+//                     {\r
+//                             return _javaCmdText;\r
+//                     }\r
+//                     set\r
+//                     {\r
+//                             _javaCmdText = value;\r
+//                     }\r
+//             }\r
+//\r
+//             protected bool getCommandTextChanged()\r
+//             {\r
+//                     return _isCommandTextChanged;\r
+//             }\r
+//    \r
+//             internal void setCommandTextChanged(bool value)\r
+//             {\r
+//                     _isCommandTextChanged = value;\r
+//             }\r
+//    \r
+//             public Statement getStatement()\r
+//             {\r
+//                     return _statement;\r
+//             }\r
+//             /**\r
+//              * @see System.Data.IDbCommand#Cancel()\r
+//              */\r
+//             public override void Cancel()\r
+//             {\r
+//                     try\r
+//                     {\r
+//                             if (_statement != null)\r
+//                                     _statement.cancel();\r
+//                     }\r
+//                     catch (SQLException exp)\r
+//                     {\r
+//                             Console.WriteLine(exp);\r
+//                     }\r
+//             }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#ExecuteScalar()\r
+////            */\r
+////           public virtual Object ExecuteScalar()\r
+////           {\r
+////                   Object result = null;\r
+////                   IDataReader reader = ((IDbCommand)this).ExecuteReader();\r
+////\r
+////                   if (reader != null && reader.Read())\r
+////                   {\r
+////                           result = ((IDataRecord) reader).GetValue(0);\r
+////                   }\r
+////                   reader.Close();\r
+////\r
+////                   return result;\r
+////           }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#CommandTimeout\r
+////            */\r
+////           public virtual int CommandTimeout\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return _cmdTimeout;\r
+////                   }\r
+////                   set\r
+////                   {\r
+////                           _cmdTimeout = value;\r
+////                   }\r
+////           }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#CommandType\r
+////            */\r
+////           public virtual CommandType CommandType\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return _cmdType;\r
+////                   }\r
+////                   set\r
+////                   {\r
+////                           _cmdType = value;\r
+////                   }\r
+////           }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#Connection\r
+////            */\r
+////           public virtual IDbConnection Connection\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return (IDbConnection)_connection;\r
+////                   }\r
+////                   set\r
+////                   {\r
+////                           _connection = (AbstractDBConnection) value;\r
+////                   }\r
+////           }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#Transaction\r
+////            */\r
+////           public virtual IDbTransaction Transaction\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return _transaction;\r
+////                   }\r
+////                   set\r
+////                   {\r
+////                           _transaction = value;\r
+////                   }\r
+////           }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#UpdatedRowSource\r
+////            */\r
+////           public virtual UpdateRowSource UpdatedRowSource\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return _updateRowSource;\r
+////                   }\r
+////                   set\r
+////                   {\r
+////                           _updateRowSource = value;\r
+////                   }\r
+////           }\r
+//\r
+////           /**\r
+////            * @see System.Data.IDbCommand#CommandText\r
+////            */\r
+////           public virtual String CommandText\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return _cmdText;\r
+////                   }\r
+////                   set\r
+////                   {\r
+////                           if (_cmdText == null || String.Compare(_cmdText, value,  true) != 0)\r
+////                           {\r
+////                                   _cmdText = value;\r
+////                                   _isCommandTextChanged = true;\r
+////                           }\r
+////                   }\r
+////           }\r
+//\r
+//             protected virtual void setInputForStatement(\r
+//                     PreparedStatement stm,\r
+//                     int javaType,\r
+//                     int place,\r
+//                     Object value)\r
+//                     //throws SQLException\r
+//             {\r
+//                     // by the type of the the parameter we know wich method of\r
+//                     // the statement to use\r
+//\r
+//                     if (value is DBNull)\r
+//                             stm.setNull(place, javaType);\r
+//\r
+//                     else if (javaType == Types.BINARY)\r
+//                             stm.setBytes(place, vmw.common.TypeUtils.ToSByteArray((byte[]) value));\r
+//\r
+//                     else if (javaType == Types.BLOB)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.CLOB)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.DISTINCT)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.ARRAY)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.JAVA_OBJECT)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.REF)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.STRUCT)\r
+//                             stm.setObject(place, value);\r
+//\r
+//                     else if (javaType == Types.VARBINARY)\r
+//                             stm.setBytes(place, vmw.common.TypeUtils.ToSByteArray((byte[]) value));\r
+//\r
+//                     else if (javaType == Types.BIGINT)\r
+//                             stm.setLong(place, ((java.lang.Long) value).longValue());\r
+//\r
+//                     else if (javaType == Types.BIT)\r
+//                             stm.setBoolean(place, ((java.lang.Boolean) value).booleanValue());\r
+//\r
+//                     else if (javaType == Types.CHAR)\r
+//                             stm.setString(place, ((java.lang.Character) value).toString());\r
+//\r
+//                     else if (javaType == Types.DATE)\r
+//                     {\r
+//                             DateTime tmp = (DateTime) value;\r
+//                             Calendar c = vmw.common.DateTimeUtils.DateTimeToCalendar(tmp);\r
+//                             stm.setDate(\r
+//                                     place, new java.sql.Date(c.getTime().getTime()));\r
+//                     }\r
+//                     else if (javaType == Types.DECIMAL || javaType == Types.NUMERIC)\r
+//                             stm.setBigDecimal(place, vmw.common.PrimitiveTypeUtils.DecimalToBigDecimal((Decimal) value));\r
+//\r
+//                     else if (javaType == Types.DOUBLE)\r
+//                             stm.setDouble(place, ((java.lang.Double) value).doubleValue());\r
+//\r
+//                     else if (javaType == Types.FLOAT)\r
+//                             stm.setFloat(place, ((java.lang.Float) value).floatValue());\r
+//\r
+//                     else if (javaType == Types.INTEGER)\r
+//                             stm.setInt(place, ((java.lang.Integer) value).intValue());\r
+//\r
+//                     else if (javaType == Types.LONGVARCHAR)\r
+//                             stm.setString(place, (String) value);\r
+//\r
+//                     else if (javaType == Types.LONGVARBINARY)\r
+//                             stm.setBytes(place, vmw.common.TypeUtils.ToSByteArray((byte[]) value));\r
+//\r
+//                     else if (javaType == Types.REAL)\r
+//                             stm.setFloat(place, ((java.lang.Float) value).floatValue());\r
+//\r
+//                     else if (javaType == Types.SMALLINT)\r
+//                             stm.setShort(place, ((java.lang.Short) value).shortValue());\r
+//\r
+//                     else if (javaType == Types.TIME)\r
+//                     {\r
+//                             Calendar c = vmw.common.DateTimeUtils.DateTimeToCalendar(value);\r
+//                             stm.setTime(\r
+//                                     place,\r
+//                                     new java.sql.Time(c.getTime().getTime()));\r
+//                     }\r
+//                     else if (javaType == Types.TIMESTAMP)\r
+//                     {\r
+//                             DateTime tmp = (DateTime) value;\r
+//                             Calendar c = vmw.common.DateTimeUtils.DateTimeToCalendar(value);\r
+//                             stm.setTimestamp(\r
+//                                     place,\r
+//                                     new java.sql.Timestamp(c.getTime().getTime()));\r
+//                     }\r
+//\r
+//                     else if (javaType == Types.TINYINT)\r
+//                             stm.setByte(place, ((java.lang.Byte) value).byteValue());\r
+//\r
+//                     else if (javaType == Types.VARCHAR)\r
+//                             stm.setString(place, (String) value);\r
+//\r
+//                     else\r
+//                             stm.setObject(place, value, javaType);\r
+//\r
+//             }\r
+//\r
+//             // create the _javaCmdText from the _cmdText (the .NET text)\r
+//             protected String createCommandForStoreProcedure(String text)\r
+//             {\r
+//                     IDbDataParameter param;\r
+//                     bool isFirst = true;\r
+//                     IList paramCollection = (IList) ((IDbCommand)this).Parameters;\r
+//        \r
+//                     //in .Net the name of sore procedure can be wraped by '[' and ']'\r
+//                     // so we remove them.\r
+//                     int indx1 = text.IndexOf('[');\r
+//                     if (indx1 != -1)\r
+//                     {\r
+//                             int indx2 = text.IndexOf(']', indx1);\r
+//                             if (indx2 != -1)\r
+//                                     text = text.Substring(indx1 + 1, indx2 - (indx1 + 1));\r
+//                     }\r
+//\r
+//                     java.lang.StringBuffer sb = new java.lang.StringBuffer(text);\r
+//                     sb.insert(0, "{call ");\r
+//\r
+//                     for (int i = 0; i < paramCollection.Count; i++)\r
+//                     {\r
+//                             param = (IDbDataParameter) paramCollection[i];\r
+//\r
+//                             if (param.Direction == ParameterDirection.ReturnValue)\r
+//                                     sb = sb.insert(1, "? =");\r
+//                             else if (isFirst)\r
+//                             {\r
+//                                     sb = sb.append("(?");\r
+//                                     isFirst = false;\r
+//                             }\r
+//                             else\r
+//                                     sb = sb.append(",?");\r
+//                     }\r
+//\r
+//                     String retVal = sb.toString();\r
+//\r
+//                     if (retVal.IndexOf("(") != -1)\r
+//                             retVal = retVal + ")";\r
+//\r
+//                     retVal += "}";\r
+//\r
+//                     _javaCmdText = retVal;\r
+//\r
+//                     return retVal;\r
+//\r
+//             }\r
+//\r
+//             // prepare the input and output parameters for the jdbc prepared statement\r
+//             // from the SqlParameters of this instance\r
+//             internal virtual void prepareStatementForStoreProcedure()// throws SQLException\r
+//             {\r
+//                     CallableStatement stm = (CallableStatement) _statement;\r
+//                     AbstractDBParameter param;\r
+//                     IList paramCollection = (IList) ((IDbCommand)this).Parameters;\r
+//                     ParameterDirection direction;\r
+//                     //int place;\r
+//\r
+//                     // NOTE - we add 1 to the index because in .NET it is zero base\r
+//                     // and in jdbc it is one base\r
+//                     for (int i = 0; i < paramCollection.Count; i++)\r
+//                     {\r
+//                             param = (AbstractDBParameter) paramCollection[i];\r
+//                             direction = param.Direction;\r
+//\r
+//                             if (direction == ParameterDirection.Input)\r
+//                                     setInput(stm, i + 1, param);\r
+//                             else if (direction == ParameterDirection.Output)\r
+//                             {\r
+//                                     setOutput(stm, i + 1, param);\r
+//                                     param.setParameterPlace(i + 1);\r
+//                             }\r
+//                             else if (direction == ParameterDirection.InputOutput)\r
+//                             {\r
+//                                     setInput(stm, i + 1, param);\r
+//                                     setOutput(stm, i + 1, param);\r
+//                                     param.setParameterPlace(i + 1);\r
+//                             }\r
+//                             else if (direction == ParameterDirection.ReturnValue)\r
+//                             {\r
+//                                     setOutput(stm, 1, param);\r
+//                                     param.setParameterPlace(1);\r
+//                             }\r
+//                     }\r
+//\r
+//             }\r
+//\r
+//             // set input parameter for the statement\r
+//             protected void setInput(\r
+//                     PreparedStatement stm,\r
+//                     int place,\r
+//                     AbstractDbParameter param)\r
+//                     //throws SQLException\r
+//             {\r
+//                     int javaType = param.JdbcType;\r
+//                     Object value = param.Value;\r
+//\r
+//                     value = getJavaWrapperFromCSharp(value);\r
+//\r
+//                     setInputForStatement(stm, javaType, place, value);\r
+//             }\r
+//        \r
+//             public static Object getJavaWrapperFromCSharp(Object obj)\r
+//             {\r
+//                     if (obj is bool)\r
+//                             return new java.lang.Boolean((bool)obj);\r
+//                     else if (obj is byte)\r
+//                             return new java.lang.Byte((sbyte)obj);\r
+//                     else if (obj is char)\r
+//                             return new java.lang.Character((char) obj);\r
+//                     else if (obj is short)\r
+//                             return new java.lang.Short((short)obj);\r
+//                     else if (obj is int)\r
+//                             return new java.lang.Integer((int)obj);\r
+//                     else if (obj is long)\r
+//                             return new java.lang.Long((long)obj);\r
+//                     else if (obj is float)\r
+//                             return new java.lang.Float((float)obj);\r
+//                     else if (obj is double)\r
+//                             return new java.lang.Double((double)obj);\r
+//\r
+//                     return obj;\r
+//\r
+//             }\r
+//\r
+//             // set an output parameter to the statement.\r
+//             protected void setOutput(\r
+//                     CallableStatement stm,\r
+//                     int place,\r
+//                     AbstractDbParameter param)\r
+//                     //throws SQLException\r
+//             {\r
+//                     int javaType = param.JdbcType;\r
+//\r
+//                     // the scale has a meening only in DECIMAL parameters\r
+//                     if (javaType == Types.DECIMAL || javaType == Types.NUMERIC)\r
+//                     {\r
+//                             if(param.DbType == DbType.Currency)\r
+//                                     stm.registerOutParameter(place, javaType, 4);\r
+//                             else\r
+//                                     stm.registerOutParameter(place, javaType, param.Scale);\r
+//                     }\r
+//                     else if (javaType == oracleTypeRefCursor) {\r
+//                             stm.registerOutParameter(place, _oracleRefCursor);\r
+//                     }\r
+//                     else {\r
+//                             stm.registerOutParameter(place, javaType);\r
+//                     }\r
+//\r
+//             }\r
+//\r
+//             // get the the output parameter for a specific statement at a specific place\r
+//             // returns the value of the output parameter\r
+//             protected Object getOutputValue(\r
+//                     AbstractDbParameter param,\r
+//                     CallableStatement stm)\r
+//                     //throws SQLException\r
+//             {\r
+//                     Object retVal = null;\r
+//\r
+//                     int place = param.getParameterPlace();\r
+//\r
+//                     // by the type of the parameter we know wich method to use\r
+//                     // on the statement\r
+//                     int type = param.JdbcType;\r
+//\r
+//                     if (type == Types.ARRAY)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.BIGINT)\r
+//                             retVal = stm.getLong(place);\r
+//                     else if (type == Types.BINARY)\r
+//                             retVal = stm.getBytes(place);\r
+//                     else if (type == Types.BIT)\r
+//                             retVal = stm.getBoolean(place);\r
+//                     else if (type == Types.BLOB)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.CHAR)\r
+//                             retVal = stm.getString(place);\r
+//                     else if (type == Types.CLOB)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.DATE)\r
+//                     {\r
+//                             java.sql.Date date = stm.getDate(place);\r
+//                             if(date != null)\r
+//                             {\r
+//                                     // convertirn sql.Date to DateTime\r
+//                                     Calendar c = Calendar.getInstance();\r
+//                                     c.setTime(date);\r
+//\r
+//                                     retVal = vmw.common.DateTimeUtils.CalendarToDateTime(c);\r
+//                             }\r
+//                             \r
+//                     }\r
+//                     else if (type == Types.DECIMAL)\r
+//                     {\r
+//                             java.math.BigDecimal bd = stm.getBigDecimal(place);\r
+//                             if(bd != null)\r
+//                                     retVal = vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bd);\r
+//                     }\r
+//                     else if (type == Types.DISTINCT)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.DOUBLE)\r
+//                             retVal = stm.getDouble(place);\r
+//                     else if (type == Types.FLOAT)\r
+//                             retVal = stm.getFloat(place);\r
+//                     else if (type == Types.INTEGER)\r
+//                             retVal = stm.getInt(place);\r
+//                     else if (type == Types.JAVA_OBJECT)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.LONGVARBINARY)\r
+//                             retVal = stm.getBytes(place);\r
+//                     else if (type == Types.LONGVARCHAR)\r
+//                             retVal = stm.getString(place);\r
+//                     else if (type == Types.NULL)\r
+//                             retVal = DBNull.Value;\r
+//                     else if (type == Types.NUMERIC)\r
+//                             retVal = stm.getBigDecimal(place);\r
+//                     else if (type == Types.OTHER)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.REAL)\r
+//                             retVal = stm.getFloat(place);\r
+//                     else if (type == Types.REF)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.SMALLINT)\r
+//                             retVal = stm.getShort(place);\r
+//                     else if (type == Types.STRUCT)\r
+//                             retVal = stm.getObject(place);\r
+//                     else if (type == Types.TIME)\r
+//                     {\r
+//                             Time t = stm.getTime(place);\r
+//                             if(t != null)\r
+//                             {\r
+//                                     java.util.Date d = new java.util.Date(t.getTime());\r
+//                                     // convertirn sql.Date to DateTime\r
+//                                     Calendar c = Calendar.getInstance();\r
+//                                     c.setTime(d);\r
+//\r
+//                                     retVal = vmw.common.DateTimeUtils.CalendarToDateTime(c);\r
+//                             }\r
+//                             \r
+//                     }\r
+//                     else if (type == Types.TIMESTAMP)\r
+//                     {\r
+//                             Timestamp ts = stm.getTimestamp(place);\r
+//                             if(ts != null)\r
+//                             {\r
+//                                     java.util.Calendar cal = java.util.Calendar.getInstance();\r
+//                                     cal.setTime(new java.util.Date(ts.getTime() + ts.getNanos()/1000000));\r
+//                                     retVal = (DateTime)vmw.common.DateTimeUtils.CalendarToDateTime(cal);\r
+//                             }\r
+//                     }\r
+//                     else if (type == Types.TINYINT)\r
+//                             retVal = stm.getByte(place);\r
+//                     else if (type == Types.VARBINARY)\r
+//                             retVal = stm.getBytes(place);\r
+//                     else if (type == Types.VARCHAR)\r
+//                             retVal = stm.getString(place);\r
+//        \r
+//                     if(stm.wasNull())\r
+//                             retVal = DBNull.Value;\r
+//            \r
+//                     return retVal;\r
+//             }\r
+//\r
+//    \r
+////           IDbDataParameter IDbCommand.CreateParameter()\r
+////           {\r
+////                   return null;\r
+////           }\r
+//    \r
+////           IDataReader IDbCommand.ExecuteReader(CommandBehavior behavior)\r
+////           {\r
+////                   return null;\r
+////           }\r
+////\r
+////           IDataReader IDbCommand.ExecuteReader()\r
+////           {\r
+////                   return null;\r
+////           }\r
+////\r
+////           int IDbCommand.ExecuteNonQuery()\r
+////           {\r
+////                   return -1;\r
+////           }\r
+////\r
+////           void IDbCommand.Prepare()\r
+////           {\r
+////           }\r
+//\r
+//        \r
+////           public IDataParameterCollection Parameters\r
+////           {\r
+////                   get\r
+////                   {\r
+////                           return _paramCollection;\r
+////                   }\r
+////           }\r
+//\r
+//             ~AbstractDBCommand()\r
+//             {\r
+//                     Dispose();\r
+//             }\r
+//\r
+//             public new void Dispose()
+//             {
+//                     if (_paramCollection != null)
+//                             _paramCollection.Clear();
+//
+//                     _connection = null;
+//                     _transaction = null;
+//
+//                     if (_statement != null)
+//                     {
+//                             _statement.close();
+//                             _statement = null;
+//                     }
+//                     base.Dispose();
+//             }\r
+//\r
+//             protected void CheckTrasactionContext()\r
+//             {\r
+//                     if (_connection.Transaction != null && \r
+//                             (Transaction == null || Transaction != _connection.Transaction)) {\r
+//                             throw new InvalidOperationException("Execute requires the command to have a transaction object" + \r
+//                                                     " when the connection assigned to the command is in a pending local transaction." +\r
+//                                                     " The Transaction property of the command has not been initialized.");\r
+//                     }\r
+//             }\r
+//\r
+//             protected String buildJavaCommand(String command)\r
+//             {\r
+//                     IDataParameterCollection parameters = Parameters;\r
+//                     \r
+//                     if (parameters != null && parameters.Count > 0) {\r
+//                             string tokens = command;\r
+//                             System.Text.StringBuilder sb = new System.Text.StringBuilder(tokens.Length);\r
+//\r
+//                             int currParameter = 0;\r
+//                             int currStart = 0;\r
+//                             int curr = 0;\r
+//                             char curSeparator = (char)0;\r
+//                             bool foundSeparator = false;\r
+//\r
+//                             for(;curr<tokens.Length;curr++) {\r
+//                                     switch(tokens[curr]) {\r
+//                                             case '"':\r
+//                                             case '\'':\r
+//                                                     if (foundSeparator) {\r
+//                                                             if (curSeparator == tokens[curr]) {\r
+//                                                                     foundSeparator = false;\r
+//                                                             }\r
+//                                                     }\r
+//                                                     else {\r
+//                                                             // start inner string\r
+//                                                             foundSeparator = true;\r
+//                                                             curSeparator = tokens[curr];\r
+//                                                     }\r
+//                                                     break;\r
+//                                             case '?':\r
+//                                                     if (!foundSeparator) {\r
+//                                                             if (curr > currStart) { \r
+//                                                                     // copy collected \r
+//                                                                     sb.Append(tokens,currStart,curr - currStart);\r
+//                                                             }\r
+//                                                             // append parameter value\r
+//                                                             AbstractDBParameter param = (AbstractDBParameter)parameters[currParameter++];\r
+//                                                             sb.Append(param.formatParameter());\r
+//                                                             currStart = curr+1;\r
+//                                                     }\r
+//                                                     break;\r
+//                                     }\r
+//                             }\r
+//\r
+//                             if (curr > currStart) { // end of the stirng\r
+//                                     sb.Append(tokens,currStart,curr - currStart);\r
+//                             }\r
+//\r
+//                             command = sb.ToString();\r
+//                     }\r
+//                     return command;\r
+//             }\r
+//\r
+//             internal void fillParameters()
+//             {
+//                     if(CommandType == CommandType.StoredProcedure)
+//                     {
+//                             AbstractDBParameter param;
+//                             CallableStatement stm = (CallableStatement)_statement;
+//                             // get the output parameters from the statement
+//                             // and put their values into the SqlParameter
+//                             for (int i = 0; i < _paramCollection.Count; i++)
+//                             {
+//                                     param = (AbstractDBParameter)_paramCollection[i];
+//
+//                                     if (param.IsOracleRefCursor)
+//                                             continue;
+//
+//                                     ParameterDirection direction = param.Direction;
+//                                     if (direction == ParameterDirection.InputOutput
+//                                             || direction == ParameterDirection.Output
+//                                             || direction == ParameterDirection.ReturnValue)
+//                                             param.Value = getOutputValue(param, stm);
+//                             }
+//                     }
+//             }\r
+//\r
+//             protected void setCommandBehabior(CommandBehavior cmdBehavior)\r
+//             {\r
+//                     _behvior = cmdBehavior;\r
+//             }\r
+//\r
+//             internal CommandBehavior getCommandBehavior()\r
+//             {\r
+//                     return _behvior;\r
+//             }\r
+//\r
+//             protected static String GetProcedureName(string cmdText)\r
+//             {\r
+//                     if(cmdText[0] == '[' && cmdText[cmdText.Length - 1] == ']')\r
+//                             return cmdText.Substring(1, cmdText.Length - 2);\r
+//                     return cmdText;\r
+//             }\r
+//        \r
+//     }\r
+//}
\ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBConnection.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBConnection.cs
new file mode 100644 (file)
index 0000000..4c70f56
--- /dev/null
@@ -0,0 +1,1158 @@
+//\r
+// System.Data.Common.AbstractDBConnection\r
+//\r
+// Author:\r
+//   Boris Kirzner (borisk@mainsoft.com)\r
+//\r
+\r
+using System.Data;\r
+using System.Data.ProviderBase;\r
+using System.Data.Configuration;\r
+using System.Configuration;\r
+using System.Collections;\r
+using System.Collections.Specialized;\r
+using System.Text;\r
+using System.Text.RegularExpressions;\r
+\r
+using java.sql;\r
+using javax.sql;\r
+using javax.naming;\r
+// can not use java.util here - it manes ArrayList an ambiguous reference\r
+\r
+namespace System.Data.Common\r
+{\r
+       public abstract class AbstractDBConnection : DbConnection\r
+       {\r
+               #region ObjectNamesHelper\r
+\r
+               private sealed class ObjectNamesHelper\r
+               {\r
+                       //static readonly Regex NameOrder = new Regex(@"^\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       static readonly Regex NameOrder = new Regex(@"^((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+\r
+                       //static readonly Regex SchemaNameOrder = new Regex(@"^\s*((\[(?<SCHEMA>(\s*[^\[\]\s])+)\s*\])|(?<SCHEMA>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       static readonly Regex SchemaNameOrder = new Regex(@"^((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       //static readonly Regex CatalogSchemaNameOrder = new Regex(@"^\s*((\[\s*(?<CATALOG>(\s*[^\[\]\s])+)\s*\])|(?<CATALOG>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<SCHEMA>(\s*[^\[\]\s])+)\s*\])|(?<SCHEMA>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       //static readonly Regex CatalogSchemaNameOrder = new Regex(@"^\s*((\[\s*(?<CATALOG>(\s*[^\]\s])+)\s*\])|(?<CATALOG>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<SCHEMA>(\s*[^\]\s])+)\s*\])|(?<SCHEMA>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<NAME>(\s*[^\]\s])+)\s*\])|(?<NAME>([^\.\s])+(\s*([^\.\s])+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       static readonly Regex CatalogSchemaNameOrder = new Regex(@"^((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+\r
+                       //static readonly Regex CatalogNameOrder = new Regex(@"^\s*((\[(?<CATALOG>(\s*[^\[\]\s])+)\s*\])|(?<CATALOG>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       //static readonly Regex CatalogNameOrder = new Regex(@"^\s*((\[(?<CATALOG>(\s*[^\]\s])+)\s*\])|(?<CATALOG>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<NAME>(\s*[^\]\s])+)\s*\])|(?<NAME>([^\.\s])+(\s*([^\.\s])+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       static readonly Regex CatalogNameOrder = new Regex(@"^((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       //static readonly Regex SchemaCatalogNameOrder = new Regex(@"^\s*((\[\s*(?<SCHEMA>(\s*[^\[\]\s])+)\s*\])|(?<SCHEMA>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<CATALOG>(\s*[^\[\]\s])+)\s*\])|(?<CATALOG>(\w|!|\#|\$)*(\s*(\w|!|\#|\$)+)*))\s*\.\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       //static readonly Regex SchemaCatalogNameOrder = new Regex(@"^\s*((\[\s*(?<SCHEMA>(\s*[^\]\s])+)\s*\])|(?<SCHEMA>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<CATALOG>(\s*[^\]\s])+)\s*\])|(?<CATALOG>([^\.\s])*(\s*([^\.\s])+)*))\s*\.\s*((\[(?<NAME>(\s*[^\]\s])+)\s*\])|(?<NAME>([^\.\s])+(\s*([^\.\s])+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+                       static readonly Regex SchemaCatalogNameOrder = new Regex(@"^((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);\r
+\r
+                       internal static ObjectNameResolver[] GetSyntaxPatterns(AbstractDBConnection connection)\r
+                       {\r
+                               ArrayList collection = new ArrayList();\r
+                               collection.Add(new ObjectNameResolver(NameOrder));\r
+\r
+                               ObjectNameResolversCollection basic = (ObjectNameResolversCollection)ConfigurationSettings.GetConfig("system.data/objectnameresolution");\r
+                               \r
+                               DatabaseMetaData metaData = connection.JdbcConnection.getMetaData();\r
+                               string productName = metaData.getDatabaseProductName();\r
+\r
+                               foreach(ObjectNameResolver nameResolver in basic) {\r
+                                       if (productName.IndexOf(nameResolver.DbName) != -1) {\r
+                                               collection.Add(nameResolver);\r
+                                       }\r
+                               }\r
+\r
+                               //defaults\r
+                               if (metaData.isCatalogAtStart()) {\r
+                                       collection.Add(new ObjectNameResolver(SchemaNameOrder));\r
+                                       collection.Add(new ObjectNameResolver(CatalogNameOrder));\r
+                                       collection.Add(new ObjectNameResolver(CatalogSchemaNameOrder));\r
+                                       collection.Add(new ObjectNameResolver(SchemaCatalogNameOrder));\r
+                               }\r
+                               else {\r
+                                       collection.Add(new ObjectNameResolver(CatalogNameOrder));\r
+                                       collection.Add(new ObjectNameResolver(SchemaNameOrder));\r
+                                       collection.Add(new ObjectNameResolver(SchemaCatalogNameOrder));\r
+                                       collection.Add(new ObjectNameResolver(CatalogSchemaNameOrder));\r
+                               }\r
+\r
+                               return (ObjectNameResolver[])collection.ToArray(typeof(ObjectNameResolver));                            \r
+                       }\r
+               }\r
+\r
+               #endregion // ObjectNamesHelper\r
+\r
+               #region ConnectionStringHelper\r
+\r
+               internal sealed class ConnectionStringHelper\r
+               {\r
+                       internal static string FindValue(NameValueCollection collection, string[] keys)\r
+                       {\r
+                               if (collection == null || keys == null || keys.Length == 0) {\r
+                                       return String.Empty;\r
+                               }\r
+\r
+                               for(int i=0; i < keys.Length; i++) {\r
+                                       string value = FindValue(collection,keys[i]);\r
+                                       if (!String.Empty.Equals(value)) {\r
+                                               return value;\r
+                                       }\r
+                               }\r
+                               return String.Empty;\r
+                       }\r
+\r
+                       internal static string FindValue(NameValueCollection collection, string key)\r
+                       {\r
+                               if (collection == null) {\r
+                                       return String.Empty;\r
+                               }\r
+\r
+                               string value = collection[key];\r
+                               return (value != null) ? value : String.Empty;\r
+                       }\r
+\r
+                       internal static void UpdateValue(NameValueCollection collection,string[] keys,string value)\r
+                       {\r
+                               for(int i=0; i < keys.Length; i++) {\r
+                                       if (collection[keys[i]] != null) {\r
+                                               collection[keys[i]] = value;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       internal static void AddValue(NameValueCollection collection,string[] keys,string value)\r
+                       {\r
+                               for(int i=0; i < keys.Length; i++) {\r
+                                       collection[keys[i]] = value;\r
+                               }\r
+                       }\r
+\r
+                       /**\r
+                       * Parses connection string and builds NameValueCollection \r
+                       * for all keys.\r
+                       */ \r
+                       internal static NameValueCollection BuildUserParameters (string connectionString)\r
+                       {\r
+                               NameValueCollection userParameters = new NameValueCollection();\r
+\r
+                               if (connectionString == null || connectionString.Length == 0) {\r
+                                       return userParameters;\r
+                               }\r
+                               connectionString += ";";\r
+\r
+                               bool inQuote = false;\r
+                               bool inDQuote = false;\r
+                               bool inName = true;\r
+\r
+                               string name = String.Empty;\r
+                               string value = String.Empty;\r
+                               StringBuilder sb = new StringBuilder ();\r
+\r
+                               for (int i = 0; i < connectionString.Length; i += 1) {\r
+                                       char c = connectionString [i];\r
+                                       char peek;\r
+                                       if (i == connectionString.Length - 1)\r
+                                               peek = '\0';\r
+                                       else\r
+                                               peek = connectionString [i + 1];\r
+\r
+                                       switch (c) {\r
+                                               case '\'':\r
+                                                       if (inDQuote)\r
+                                                               sb.Append (c);\r
+                                                       else if (peek.Equals(c)) {\r
+                                                               sb.Append(c);\r
+                                                               i += 1;\r
+                                                       }\r
+                                                       else\r
+                                                               inQuote = !inQuote;\r
+                                                       break;\r
+                                               case '"':\r
+                                                       if (inQuote)\r
+                                                               sb.Append(c);\r
+                                                       else if (peek.Equals(c)) {\r
+                                                               sb.Append(c);\r
+                                                               i += 1;\r
+                                                       }\r
+                                                       else\r
+                                                               inDQuote = !inDQuote;\r
+                                                       break;\r
+                                               case ';':\r
+                                                       if (inDQuote || inQuote)\r
+                                                               sb.Append(c);\r
+                                                       else {\r
+                                                               if (name != String.Empty && name != null) {\r
+                                                                       value = sb.ToString();\r
+                                                                       userParameters [name.Trim()] = value.Trim();\r
+                                                               }\r
+                                                               inName = true;\r
+                                                               name = String.Empty;\r
+                                                               value = String.Empty;\r
+                                                               sb = new StringBuilder();\r
+                                                       }\r
+                                                       break;\r
+                                               case '=':\r
+                                                       if (inDQuote || inQuote || !inName)\r
+                                                               sb.Append (c);\r
+                                                       else if (peek.Equals(c)) {\r
+                                                               sb.Append (c);\r
+                                                               i += 1;\r
+                                                       }\r
+                                                       else {\r
+                                                               name = sb.ToString();\r
+                                                               sb = new StringBuilder();\r
+                                                               inName = false;\r
+                                                       }\r
+                                                       break;\r
+                                               case ' ':\r
+                                                       if (inQuote || inDQuote)\r
+                                                               sb.Append(c);\r
+                                                       else if (sb.Length > 0 && !peek.Equals(';'))\r
+                                                               sb.Append(c);\r
+                                                       break;\r
+                                               default:\r
+                                                       sb.Append(c);\r
+                                                       break;\r
+                                       }\r
+                               }\r
+                               return userParameters;\r
+                       }\r
+               }\r
+\r
+               #endregion // ConnectionStringHelper\r
+\r
+               #region DataSourceCache\r
+\r
+               private sealed class DataSourceCache : AbstractDbMetaDataCache\r
+               {\r
+                       internal DataSource GetDataSource(string dataSourceName,string namingProviderUrl,string namingFactoryInitial)\r
+                       {\r
+                               Hashtable cache = Cache;\r
+\r
+                               DataSource ds = cache[dataSourceName] as DataSource;\r
+\r
+                               if (ds != null) {\r
+                                       return ds;\r
+                               }\r
+\r
+                               Context ctx = null;\r
+                               \r
+                               java.util.Properties properties = new java.util.Properties();\r
+\r
+                               if ((namingProviderUrl != null) && (namingProviderUrl.Length > 0)) {\r
+                                       properties.put("java.naming.provider.url",namingProviderUrl);\r
+                               }\r
+                               \r
+                               if ((namingFactoryInitial != null) && (namingFactoryInitial.Length > 0)) {\r
+                                       properties.put("java.naming.factory.initial",namingFactoryInitial);\r
+                               }\r
+\r
+                               ctx = new InitialContext(properties);\r
\r
+                               try {\r
+                                       ds = (DataSource)ctx.lookup(dataSourceName);\r
+                               }\r
+                               catch(javax.naming.NameNotFoundException e) {\r
+                                       // possible that is a Tomcat bug,\r
+                                       // so try to lookup for jndi datasource with "java:comp/env/" appended\r
+                                       ds = (DataSource)ctx.lookup("java:comp/env/" + dataSourceName);\r
+                               }\r
+\r
+                               cache[dataSourceName] = ds;\r
+                               return ds;\r
+                       }\r
+               }\r
+\r
+               #endregion // DatasourceCache\r
+\r
+               #region Declarations\r
+\r
+               protected internal enum JDBC_MODE { NONE, DATA_SOURCE_MODE, JDBC_DRIVER_MODE, PROVIDER_MODE }\r
+               protected internal enum PROVIDER_TYPE { NONE, SQLOLEDB, MSDAORA, IBMDADB2 }\r
+\r
+               #endregion // Declarations\r
+               \r
+               #region Fields\r
+\r
+               private static DataSourceCache _dataSourceCache = new DataSourceCache();\r
+               private const int DEFAULT_TIMEOUT = 15;\r
+\r
+               private Connection _jdbcConnnection;\r
+               private ConnectionState _internalState;\r
+               private object _internalStateSync = new object();\r
+\r
+               private NameValueCollection _userParameters;\r
+\r
+               protected string _connectionString = String.Empty;\r
+               protected string _jdbcUrl;              \r
+\r
+               private ArrayList _referencedObjects = new ArrayList(); \r
+               private ObjectNameResolver[] _syntaxPatterns;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               public AbstractDBConnection(string connectionString)\r
+               {\r
+                       _connectionString = connectionString;\r
+                       InitializeSkippedUserParameters();\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Properties\r
+\r
+               public override String ConnectionString\r
+               {\r
+                       get { return _connectionString; }\r
+                       set {\r
+                               if (IsOpened) {\r
+                                       throw ExceptionHelper.NotAllowedWhileConnectionOpen("ConnectionString",_internalState);\r
+                               }                                       \r
+                               _connectionString = value;\r
+                               _userParameters = null;\r
+                               _jdbcUrl = null;\r
+                       }\r
+               }\r
+\r
+               public override int ConnectionTimeout\r
+               {\r
+                       get {\r
+                               string timeoutStr = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_TIMEOUT"));\r
+                               if (!String.Empty.Equals(timeoutStr)) {\r
+                                       try {\r
+                                               return Convert.ToInt32(timeoutStr);\r
+                                       }\r
+                                       catch(FormatException e) {\r
+                                               throw ExceptionHelper.InvalidValueForKey("connect timeout");\r
+                                       }\r
+                                       catch (OverflowException e) {\r
+                                               throw ExceptionHelper.InvalidValueForKey("connect timeout");\r
+                                       }\r
+                               }\r
+                               return DEFAULT_TIMEOUT;\r
+                       }\r
+               }\r
+\r
+               public override String Database\r
+               {\r
+                       get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATABASE")); }\r
+               }\r
+\r
+               public override ConnectionState State\r
+               {\r
+                       get {\r
+                               try {\r
+                                       if ((JdbcConnection == null) || JdbcConnection.isClosed()) {\r
+                                               // jdbc connection not initialized or closed\r
+                                               if (_internalState == ConnectionState.Closed ) {\r
+                                                       return ConnectionState.Closed;\r
+                                               }\r
+                                       }\r
+                                       else {\r
+                                               // jdbc connection is opened\r
+                                               if ((_internalState & ConnectionState.Open) != 0) {\r
+                                                       return ConnectionState.Open;\r
+                                               }\r
+                                       }\r
+                                       return ConnectionState.Broken;                                                                          \r
+                               }       \r
+                               catch (SQLException) {\r
+                                       return ConnectionState.Broken;\r
+                               }                               \r
+                       }\r
+               }\r
+\r
+               internal bool IsExecuting\r
+               {\r
+                       get { \r
+                               return ((_internalState & ConnectionState.Executing) != 0);\r
+                       }\r
+\r
+                       set {\r
+                               lock(_internalStateSync) {\r
+                                       // to switch to executing, the connection must be in opened\r
+                                       if (value) {\r
+                                               if (_internalState != ConnectionState.Open) {\r
+                                                       if (IsFetching) {\r
+                                                               throw ExceptionHelper.OpenedReaderExists();\r
+                                                       }\r
+                                                       throw ExceptionHelper.OpenConnectionRequired("",_internalState);\r
+                                               }\r
+                                               _internalState |= ConnectionState.Executing;\r
+                                       }\r
+                                       else { \r
+                                               if (!IsExecuting) {\r
+                                                       throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Executing.ToString() + " while in state " + _internalState.ToString());\r
+                                               }\r
+                                               _internalState &= ~ConnectionState.Executing;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal bool IsFetching\r
+               {\r
+                       get {\r
+                               return ((_internalState & ConnectionState.Fetching) != 0);\r
+                       }\r
+\r
+                       set {\r
+                               lock(_internalStateSync) {\r
+                                       if (value) {\r
+                                               // to switch to fetching connection must be in opened, executing\r
+                                               if (((_internalState & ConnectionState.Open) == 0) || ((_internalState & ConnectionState.Executing) == 0)) {\r
+                                                       throw ExceptionHelper.OpenConnectionRequired("",_internalState);\r
+                                               }\r
+                                               _internalState |= ConnectionState.Fetching;\r
+                                       }\r
+                                       else {\r
+                                               if (!IsFetching) {\r
+                                                       throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Fetching.ToString() + " while in state " + _internalState.ToString());\r
+                                               }\r
+                                               _internalState &= ~ConnectionState.Fetching;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal bool IsOpened\r
+               {\r
+                       get {\r
+                               return ((_internalState & ConnectionState.Open) != 0);\r
+                       }\r
+\r
+                       set {\r
+                               lock(_internalStateSync) {                      \r
+                                       if (value) {\r
+                                               // only connecting connection can be opened\r
+                                               if ((_internalState != ConnectionState.Connecting)) {\r
+                                                       throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);\r
+                                               }\r
+                                               _internalState |= ConnectionState.Open;\r
+                                       }\r
+                                       else {\r
+                                               if (!IsOpened) {\r
+                                                       throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Open.ToString() + " while in state " + _internalState.ToString());\r
+                                               }\r
+                                               _internalState &= ~ConnectionState.Open;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal bool IsConnecting\r
+               {\r
+                       get {\r
+                               return ((_internalState & ConnectionState.Connecting) != 0);\r
+                       }\r
+\r
+                       set {\r
+                               lock(_internalStateSync) {                      \r
+                                       if (value) {\r
+                                               // to switch to connecting conection must be in closed or in opened\r
+                                               if ((_internalState != ConnectionState.Closed) && (_internalState != ConnectionState.Open)) {\r
+                                                       throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);\r
+                                               }\r
+                                               _internalState |= ConnectionState.Connecting;\r
+                                       }\r
+                                       else {\r
+                                               if (!IsConnecting) {\r
+                                                       throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Connecting.ToString() + " while in state " + _internalState.ToString());\r
+                                               }\r
+                                               _internalState &= ~ConnectionState.Connecting;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               protected virtual PROVIDER_TYPE ProviderType\r
+               {\r
+                       get {\r
+                               if (JdbcMode != JDBC_MODE.PROVIDER_MODE) {\r
+                                       return PROVIDER_TYPE.NONE;\r
+                               }\r
+                               \r
+                               string providerStr = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_PROVIDER"));\r
+                               if (providerStr.StartsWith("SQLOLEDB")) {\r
+                                       return PROVIDER_TYPE.SQLOLEDB;\r
+                               }\r
+                               else if (providerStr.StartsWith("MSDAORA")) {\r
+                                       return PROVIDER_TYPE.MSDAORA;\r
+                               }\r
+                               else if (providerStr.StartsWith("IBMDADB2")) {\r
+                                       return PROVIDER_TYPE.IBMDADB2;\r
+                               }\r
+                               return PROVIDER_TYPE.NONE;\r
+                       }\r
+               }\r
+\r
+               protected internal virtual JDBC_MODE JdbcMode\r
+               {\r
+                       get { \r
+                               string[] conJndiNameStr = StringManager.GetStringArray("CON_JNDI_NAME");\r
+                               if ( !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,conJndiNameStr))) {\r
+                                       return JDBC_MODE.DATA_SOURCE_MODE;\r
+                               }\r
+\r
+                               string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");\r
+                               string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");\r
+                               bool jdbcDriverSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr));\r
+                               bool jdbcUrlSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr));\r
+\r
+                               if (jdbcDriverSpecified && jdbcUrlSpecified) {\r
+                                       return JDBC_MODE.JDBC_DRIVER_MODE;\r
+                               }\r
+\r
+                               string[] providerStr = StringManager.GetStringArray("CON_PROVIDER");\r
+                               if (!String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,providerStr))) {\r
+                                       return JDBC_MODE.PROVIDER_MODE;\r
+                               }\r
+                               \r
+                               return JDBC_MODE.NONE;\r
+                       }\r
+               }\r
+\r
+               protected virtual string JdbcDriverName\r
+               {\r
+                       get { return String.Empty; }\r
+               }\r
+\r
+               protected abstract DbStringManager StringManager\r
+               {\r
+                       get;\r
+               }\r
+\r
+               protected virtual string ServerName\r
+               {\r
+                       get { return DataSource; }\r
+               }\r
+\r
+               protected virtual string CatalogName\r
+               {\r
+                       get { return Database; }\r
+               }\r
+\r
+               protected virtual string Port\r
+               {\r
+                       get {\r
+                               string port = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_PORT"));\r
+                               switch (ProviderType) {\r
+                                       case PROVIDER_TYPE.SQLOLEDB : \r
+                                               if (String.Empty.Equals(port)) {\r
+                                                       // if needed - resolve MSSQL port\r
+                                                       // FIXME : decide about behaviour in the case all the timeout spent on port resolution\r
+                                                       //long start = DateTime.Now.Ticks;\r
+                                                       port = DbPortResolver.getMSSqlPort(DataSource,InstanceName,ConnectionTimeout).ToString();\r
+                                                       //long end = DateTime.Now.Ticks;                                                                                                        \r
+                                                       //if( (end - start) < ConnectionTimeout*1000000) {                                                              \r
+                                                               //timeout -= (int)(end - start)/1000000;\r
+                                                       //}\r
+                                               }\r
+                                               // todo : what should we do if all the timeout spent on port resolution ?\r
+                                               if ("-1".Equals(port)) {\r
+                                                       port = StringManager.GetString("SQL_CON_PORT", "1433"); //default port of MSSql Server 3167.\r
+                                               }\r
+                                               ConnectionStringHelper.AddValue(UserParameters,StringManager.GetStringArray("CON_PORT"),port);\r
+                                               break;\r
+                               }\r
+                               return port;\r
+                       }\r
+               }\r
+\r
+               public override string DataSource\r
+               {\r
+                       get {\r
+                               string dataSource = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATA_SOURCE"));\r
+\r
+                               if (ProviderType == PROVIDER_TYPE.SQLOLEDB) {\r
+                                       int instanceIdx;\r
+                                       if ((instanceIdx = dataSource.IndexOf("\\")) != -1) {\r
+                                               // throw out named instance name\r
+                                               dataSource = dataSource.Substring(0,instanceIdx);\r
+                                       }\r
+\r
+                                       if (dataSource != null && dataSource.StartsWith("(") && dataSource.EndsWith(")")) {                                             \r
+                                               dataSource = dataSource.Substring(1,dataSource.Length - 2);\r
+                                       }\r
+\r
+                                       if(String.Empty.Equals(dataSource) || (String.Compare("local",dataSource,true) == 0)) {\r
+                                               dataSource = "localhost";\r
+                                       }\r
+                               }\r
+                               return dataSource;\r
+                       }\r
+               }\r
+\r
+               protected virtual string InstanceName\r
+               {\r
+                       get {\r
+                               string dataSource = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATA_SOURCE"));\r
+                               string instanceName = String.Empty;\r
+                               if (ProviderType == PROVIDER_TYPE.SQLOLEDB) {\r
+                                       int instanceIdx;\r
+                                       if ((instanceIdx = dataSource.IndexOf("\\")) == -1) {\r
+                                               // no named instance specified - use a default name\r
+                                               instanceName = StringManager.GetString("SQL_DEFAULT_INSTANCE_NAME");\r
+                                       }\r
+                                       else {\r
+                                               // get named instance name\r
+                                               instanceName = dataSource.Substring(instanceIdx + 1);\r
+                                       }\r
+                               }\r
+                               return instanceName;\r
+                       }\r
+               }\r
+\r
+               protected virtual string User\r
+               {\r
+                       get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_USER_ID")); }\r
+               }\r
+\r
+               protected virtual string Password\r
+               {\r
+                       get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_PASSWORD")); }\r
+               }\r
+\r
+               protected NameValueCollection UserParameters\r
+               {\r
+                       get {\r
+                               if (_userParameters == null) {\r
+                                       _userParameters = ConnectionStringHelper.BuildUserParameters(ConnectionString);\r
+                               }\r
+                               return _userParameters;\r
+                       }\r
+               }\r
+\r
+               internal String JdbcUrl \r
+               {\r
+                       get { \r
+                               if ( UserParameters == null) {\r
+                                       return String.Empty;\r
+                               }\r
+\r
+                               if (_jdbcUrl == null) {\r
+                                       _jdbcUrl = BuildJdbcUrl();\r
+                               }\r
+                               return _jdbcUrl;\r
+                       }\r
+               }\r
+\r
+               internal ConnectionState InternalState\r
+               {\r
+                       get     { return _internalState; }\r
+               }\r
+\r
+\r
+               protected internal Connection JdbcConnection\r
+               {\r
+                       get { return _jdbcConnnection; }\r
+                       set { _jdbcConnnection = value; }\r
+               }\r
+\r
+               protected virtual string[] ResourceIgnoredKeys\r
+               {\r
+                       get { return new string[0]; }\r
+               }\r
+\r
+               protected virtual Hashtable SkippedUserParameters\r
+               {\r
+                       get { return new Hashtable(new CaseInsensitiveHashCodeProvider(),new CaseInsensitiveComparer()); }\r
+               }\r
+\r
+               internal ObjectNameResolver[] SyntaxPatterns\r
+               {\r
+                       get {\r
+                               if (_syntaxPatterns == null) {\r
+                                       _syntaxPatterns = ObjectNamesHelper.GetSyntaxPatterns(this);\r
+                               }\r
+                               return _syntaxPatterns;\r
+                       }\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+                       // since WS also does not permits dynamically change of login timeout and tomcat does no implements - do not do it at all\r
+                       //ds.setLoginTimeout(ConnectionTimeout);\r
+\r
+               internal abstract void OnSqlWarning(SQLWarning warning);\r
+\r
+               internal abstract void OnStateChanged(ConnectionState orig, ConnectionState current);\r
+\r
+               protected abstract SystemException CreateException(SQLException e);\r
+\r
+               public override void Close()\r
+               {\r
+                       try {\r
+                               ClearReferences();\r
+                               if (JdbcConnection != null && !JdbcConnection.isClosed()) {\r
+                                       JdbcConnection.close();\r
+                               }\r
+                       }\r
+                       catch (SQLException e) {\r
+                               // suppress exception\r
+                               JdbcConnection = null;\r
+#if DEBUG\r
+                               Console.WriteLine("Exception catched at Conection.Close() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);\r
+#endif\r
+                       }\r
+                       catch (Exception e) {\r
+                               // suppress exception\r
+                               JdbcConnection = null;\r
+#if DEBUG\r
+                               Console.WriteLine("Exception catched at Conection.Close() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);\r
+#endif\r
+                       }\r
+                       finally {\r
+                               lock(_internalStateSync) {\r
+                                       _internalState = ConnectionState.Closed;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               protected internal virtual void CopyTo(AbstractDBConnection target)\r
+               {\r
+                       target._connectionString = _connectionString;\r
+               }\r
+\r
+               internal protected virtual void OnSqlException(SQLException exp)\r
+               {\r
+                       throw CreateException(exp);\r
+               }\r
+\r
+               internal void AddReference(object referencedObject)\r
+               {       lock(_referencedObjects.SyncRoot) {\r
+                               _referencedObjects.Add(new WeakReference(referencedObject));\r
+                       }\r
+               }\r
+\r
+               internal void RemoveReference(object referencedObject)\r
+               {\r
+                       lock(_referencedObjects.SyncRoot) {\r
+                               for(int i = 0; i < _referencedObjects.Count; i++) {\r
+                                       WeakReference wr = (WeakReference) _referencedObjects[i];\r
+                                       if (wr.IsAlive && (wr.Target == referencedObject)) {\r
+                                               _referencedObjects.RemoveAt(i);\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void ClearReferences()\r
+               {\r
+                       ArrayList oldList = _referencedObjects;\r
+                       _referencedObjects = new ArrayList();\r
+\r
+                       for(int i = 0; i < oldList.Count; i++) {\r
+                               WeakReference wr = (WeakReference) oldList[i];\r
+                               if (wr.IsAlive) {\r
+                                       ClearReference(wr.Target);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void ClearReference(object referencedObject)\r
+               {\r
+                       try {\r
+                               if (referencedObject is AbstractDbCommand) {\r
+                                       ((AbstractDbCommand)referencedObject).CloseInternal();\r
+                               }\r
+                               else if (referencedObject is AbstractDataReader) {\r
+                                       ((AbstractDataReader)referencedObject).CloseInternal();\r
+                               }\r
+                       }\r
+                       catch (SQLException) {\r
+                               // suppress exception since it's possible that command or reader are in inconsistent state\r
+                       }\r
+               }\r
+\r
+               public override void Open()\r
+               {\r
+                       if (_connectionString == null || _connectionString.Length == 0) {\r
+                               throw ExceptionHelper.ConnectionStringNotInitialized();\r
+                       }\r
+\r
+                       IsConnecting = true;\r
+                       try {                   \r
+                               if (JdbcConnection != null && !JdbcConnection.isClosed()) {\r
+                                       throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);\r
+                               }\r
+       \r
+                               switch(JdbcMode) {\r
+                                       case JDBC_MODE.DATA_SOURCE_MODE :\r
+                                               JdbcConnection = GetConnectionFromDataSource();\r
+                                               break;\r
+\r
+                                       case JDBC_MODE.JDBC_DRIVER_MODE:\r
+                                               JdbcConnection = GetConnectionFromJdbcDriver();\r
+                                               break;\r
+\r
+                                       case JDBC_MODE.PROVIDER_MODE :                                  \r
+                                               JdbcConnection = GetConnectionFromProvider();\r
+                                               break;\r
+                               }\r
+                               IsOpened = true;\r
+\r
+                               OnStateChanged(ConnectionState.Closed, ConnectionState.Open);\r
+                       }\r
+                       catch (SQLWarning warning) {\r
+                               OnSqlWarning(warning);\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               OnSqlException(exp);\r
+                       }\r
+                       finally {\r
+                               IsConnecting = false;\r
+                       }\r
+               }\r
+\r
+               public override void ChangeDatabase(String database)\r
+               {\r
+                       IsConnecting = true;\r
+                       try {\r
+                               ClearReferences();\r
+                               Connection con = JdbcConnection;                                \r
+                               con.setCatalog(database);\r
+                               ConnectionStringHelper.UpdateValue(UserParameters,StringManager.GetStringArray("CON_DATABASE"),database);\r
+                       }\r
+                       catch (SQLWarning warning) {\r
+                               OnSqlWarning(warning);\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               throw CreateException(exp);\r
+                       }\r
+                       finally {\r
+                               IsConnecting = false;\r
+                       }\r
+               }\r
+\r
+               public override string ServerVersion {\r
+                       get {\r
+                               // only if the driver support this methods\r
+                               try {\r
+                                       if (JdbcConnection == null)\r
+                                               return String.Empty;\r
+\r
+                                       DatabaseMetaData metaData = JdbcConnection.getMetaData();\r
+                                       return metaData.getDatabaseProductVersion();\r
+                               }\r
+                               catch (SQLException exp) {\r
+                                       throw CreateException(exp);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal string JdbcProvider {\r
+                       get {\r
+                               // only if the driver support this methods\r
+                               try {\r
+                                       if (JdbcConnection == null)\r
+                                               return String.Empty;\r
+\r
+                                       DatabaseMetaData metaData = JdbcConnection.getMetaData();\r
+                                       return metaData.getDriverName() + " " + metaData.getDriverVersion();\r
+                               }\r
+                               catch (SQLException exp) {\r
+                                       return String.Empty; //suppress\r
+                               }\r
+                       }\r
+               }\r
+\r
+               protected override void Dispose(bool disposing)\r
+               {\r
+                       if (disposing) {\r
+                               try {\r
+                                       if (JdbcConnection != null && !JdbcConnection.isClosed()) {\r
+                                               JdbcConnection.close();\r
+                                       }                       \r
+                                       JdbcConnection = null;\r
+                               }\r
+                               catch (java.sql.SQLException exp) {\r
+                                       throw CreateException(exp);\r
+                               }\r
+                       }\r
+                       base.Dispose(disposing);\r
+               }\r
+\r
+               protected internal virtual void ValidateConnectionString(string connectionString)\r
+               {\r
+                       JDBC_MODE currentJdbcMode = JdbcMode;\r
+                       \r
+                       if (currentJdbcMode == JDBC_MODE.NONE) {\r
+                               string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");\r
+                               string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");\r
+                               bool jdbcDriverSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr));\r
+                               bool jdbcUrlSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr));\r
+\r
+                               if (jdbcDriverSpecified ^ jdbcUrlSpecified) {\r
+                                       throw new ArgumentException("Invalid format of connection string. If you want to use third-party JDBC driver, the format is: \"JdbcDriverClassName=<jdbc driver class name>;JdbcURL=<jdbc url>\"");\r
+                               }                               \r
+                       }\r
+               }\r
+\r
+               protected virtual string BuildJdbcUrl()\r
+               {\r
+                       switch (JdbcMode) {\r
+                               case JDBC_MODE.JDBC_DRIVER_MODE :\r
+                                       return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("JDBC_URL"));\r
+                               default :\r
+                                       return String.Empty;\r
+                       }\r
+               }\r
+\r
+               protected java.util.Properties BuildProperties()\r
+               {\r
+                       java.util.Properties properties = new java.util.Properties();\r
+\r
+                       string user = User;\r
+                       if (user != null && user.Length > 0)\r
+                               properties.put("user", user);\r
+                       string password = Password;\r
+                       if (user != null && user.Length > 0)\r
+                               properties.put("password", password);\r
+\r
+                       string[] userKeys = UserParameters.AllKeys;\r
+\r
+                       for(int i=0; i < userKeys.Length; i++) {\r
+                               string userKey = userKeys[i];\r
+                               string userParameter = UserParameters[userKey];\r
+                               if (!SkipUserParameter(userKey)) {\r
+                                       properties.put(userKey,userParameter);\r
+                               }\r
+                       }\r
+                       return properties;\r
+               }\r
+\r
+               protected virtual bool SkipUserParameter(string parameterName)\r
+               {\r
+                       if (SkippedUserParameters.Count == 0) {\r
+                               // skipped parameters not initialized - skip all\r
+                               return true;\r
+                       }\r
+\r
+                       return SkippedUserParameters.Contains(parameterName);\r
+               }\r
+\r
+               protected virtual void InitializeSkippedUserParameters()\r
+               {\r
+                       if (SkippedUserParameters.Count > 0) {\r
+                               return;\r
+                       }\r
+\r
+                       for(int i=0; i < ResourceIgnoredKeys.Length; i++) {\r
+                               string[] userKeys = StringManager.GetStringArray(ResourceIgnoredKeys[i]);\r
+                               for(int j=0; j < userKeys.Length; j++) {\r
+                                       SkippedUserParameters.Add(userKeys[j],userKeys[j]);\r
+                               }\r
+                       }\r
+               }\r
\r
+               internal void ValidateBeginTransaction()\r
+               {\r
+                       if (State != ConnectionState.Open) {\r
+                               throw new InvalidOperationException(Res.GetString("ADP_OpenConnectionRequired_BeginTransaction", new object[] {"BeginTransaction", State}));\r
+                       }\r
+\r
+                       if (!JdbcConnection.getAutoCommit()) {\r
+                               throw new System.InvalidOperationException("Parallel transactions are not supported.");\r
+                       }\r
+               }\r
+\r
+               internal virtual Connection GetConnectionFromProvider()\r
+               {\r
+                       ActivateJdbcDriver(JdbcDriverName);\r
+                       DriverManager.setLoginTimeout(ConnectionTimeout);\r
+                       java.util.Properties properties = BuildProperties();\r
+                       return DriverManager.getConnection (JdbcUrl, properties);\r
+               }\r
+\r
+               internal Connection GetConnectionFromDataSource()\r
+               {\r
+                       string dataSourceJndi = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_NAME"));\r
+                       string namingProviderUrl = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_PROVIDER"));\r
+                       string namingFactoryInitial = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_FACTORY"));\r
+                       DataSource ds = _dataSourceCache.GetDataSource(dataSourceJndi,namingProviderUrl,namingFactoryInitial);\r
+                       try {\r
+                               ds.setLoginTimeout(ConnectionTimeout);\r
+                       }\r
+                       catch (java.lang.Exception) {\r
+                               // WebSphere does not allows dynamicall change of login timeout\r
+                               // setLoginTimeout is not supported yet\r
+                               // in Tomcat data source.\r
+                               // In this case we work wthout timeout.\r
+                       }\r
+                       return ds.getConnection();\r
+               }\r
+\r
+               internal virtual Connection GetConnectionFromJdbcDriver()\r
+               {\r
+                       string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");\r
+                       string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");\r
+               \r
+                       string jdbcDriverName = ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr);\r
+                       string jdbcUrl = ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr);\r
+\r
+                       ActivateJdbcDriver(jdbcDriverName);\r
+                       DriverManager.setLoginTimeout(ConnectionTimeout);\r
+\r
+                       java.util.Properties properties = BuildProperties();\r
+\r
+                       return DriverManager.getConnection(jdbcUrl,properties);\r
+               }\r
+\r
+               internal ArrayList GetProcedureColumns(String procedureString, AbstractDbCommand command)\r
+               {\r
+                       ArrayList col = new ArrayList();\r
+                       try {\r
+                               ObjectNameResolver[] nameResolvers = SyntaxPatterns;\r
+                               ResultSet res = null;\r
+                               string catalog = null;\r
+                               string schema = null;\r
+                               string spname = null;\r
+                                               \r
+                               DatabaseMetaData metadata = JdbcConnection.getMetaData();       \r
+                               bool storesUpperCaseIdentifiers = false;\r
+                               bool storesLowerCaseIdentifiers = false;\r
+                               try {\r
+                                       storesUpperCaseIdentifiers = metadata.storesUpperCaseIdentifiers();\r
+                                       storesLowerCaseIdentifiers = metadata.storesLowerCaseIdentifiers();\r
+                               }\r
+                               catch (SQLException e) {\r
+                                       // suppress\r
+                               }\r
+\r
+                               for(int i=0; i < nameResolvers.Length; i++) {\r
+                                       ObjectNameResolver nameResolver = nameResolvers[i];\r
+                                       Match match = nameResolver.Match(procedureString);\r
+\r
+                                       if (match.Success) {\r
+                                               spname = ObjectNameResolver.GetName(match);                             \r
+                                               schema = ObjectNameResolver.GetSchema(match);                                           \r
+                                               catalog = ObjectNameResolver.GetCatalog(match);                                         \r
+\r
+                                               // make all identifiers uppercase or lowercase according to database metadata\r
+                                               if (storesUpperCaseIdentifiers) {\r
+                                                       spname = (spname.Length > 0) ? spname.ToUpper() : null;\r
+                                                       schema = (schema.Length > 0) ? schema.ToUpper() : null;\r
+                                                       catalog = (catalog.Length > 0) ? catalog.ToUpper() : null;\r
+                                               }\r
+                                               else if (storesLowerCaseIdentifiers) {\r
+                                                       spname = (spname.Length > 0) ? spname.ToLower() : null;\r
+                                                       schema = (schema.Length > 0) ? schema.ToLower() : null;\r
+                                                       catalog = (catalog.Length > 0) ? catalog.ToLower() : null;\r
+                                               }\r
+                                               else {\r
+                                                       spname = (spname.Length > 0) ? spname : null;\r
+                                                       schema = (schema.Length > 0) ? schema : null;\r
+                                                       catalog = (catalog.Length > 0) ? catalog : null;\r
+                                               }\r
+\r
+                                               // catalog from db is always in correct caps\r
+                                               if (catalog == null) {\r
+                                                       catalog = JdbcConnection.getCatalog();\r
+                                               }\r
+\r
+                                               try {\r
+                                                       // always get the first procedure that db returns\r
+                                                       res = metadata.getProcedures(catalog, schema, spname);                                                                                          \r
+                                                       if (res.next()) {\r
+                                                               catalog = res.getString(1);\r
+                                                               schema = res.getString(2);\r
+                                                               spname = res.getString(3);\r
+                                                               break;\r
+                                                       }\r
+\r
+                                                       spname = null;\r
+                                               }\r
+                                               catch { // suppress exception\r
+                                                       return null;\r
+                                               }\r
+                                               finally {\r
+                                                       if (res != null) {\r
+                                                               res.close();\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                               }       \r
+               \r
+                               if (spname == null || spname.Length == 0) {\r
+                                       return null;\r
+                               }\r
+                               \r
+                               try {\r
+                                       // get procedure columns based o  procedure metadata\r
+                                       res = metadata.getProcedureColumns(catalog, schema, spname, null);                              \r
+                                       while (res.next()) {\r
+                                               // since there is still a possibility that some of the parameters to getProcedureColumn were nulls, \r
+                                               // we need to filter the results with strict matching\r
+                                               if ((res.getString(1) != catalog ) || (res.getString(2) != schema) || (res.getString(3) != spname)) {\r
+                                                       continue;\r
+                                               }\r
+\r
+                                               AbstractDbParameter parameter = (AbstractDbParameter)command.CreateParameter();\r
+                                               \r
+                                               parameter.SetParameterName(res);\r
+                                               parameter.SetParameterDbType(res);\r
+                                               parameter.SetSpecialFeatures(res);\r
+\r
+                                               //get parameter direction\r
+                                               short direction = res.getShort("COLUMN_TYPE");\r
+                                               if(direction == 1) //DatabaseMetaData.procedureColumnIn\r
+                                                       parameter.Direction = ParameterDirection.Input;\r
+                                               else if(direction == 2) //DatabaseMetaData.procedureColumnInOut\r
+                                                       parameter.Direction = ParameterDirection.InputOutput;\r
+                                               else if(direction == 4) //DatabaseMetaData.procedureColumnOut\r
+                                                       parameter.Direction = ParameterDirection.Output;\r
+                                               else if(direction == 5) //DatabaseMetaData.procedureColumnReturn\r
+                                                       parameter.Direction = ParameterDirection.ReturnValue;\r
+                                       \r
+                                               //get parameter precision and scale\r
+                                               parameter.SetParameterPrecisionAndScale(res);\r
+\r
+                                               parameter.SetParameterSize(res);\r
+                                               parameter.SetParameterIsNullable(res);\r
+\r
+                                               col.Add(parameter);\r
+                                       }\r
+                               }\r
+                               finally {\r
+                                       if (res != null) {\r
+                                               res.close();\r
+                                       }\r
+                               }                               \r
+                       }\r
+                       catch(Exception e) {\r
+                               //supress\r
+#if DEBUG\r
+                               Console.WriteLine("Exception catched at AbstractDBConnection.GetProcedureColumns() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);\r
+#endif\r
+                       }\r
+                       return col;\r
+               }\r
+\r
+               protected static void ActivateJdbcDriver(string driver)\r
+               {\r
+                       if(driver != null) {\r
+                               try {\r
+                                       java.lang.Class.forName(driver).newInstance();\r
+                               }\r
+                               catch (java.lang.ClassNotFoundException e) {\r
+                                       throw new TypeLoadException(e.Message);\r
+                               }\r
+                               catch (java.lang.InstantiationException e) {\r
+                                       throw new MemberAccessException(e.Message);\r
+                               }\r
+                catch (java.lang.IllegalAccessException e) {\r
+                                       throw new MissingMethodException(e.Message);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               protected String BuildMsSqlUrl()\r
+               {\r
+                       return StringManager.GetString("SQL_JDBC_URL") //"jdbc:microsoft:sqlserver://"\r
+                               + ServerName + ":" + Port + ";DatabaseName=" + CatalogName;\r
+               }\r
+\r
+               #endregion // Methods   \r
+       }\r
+}
\ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBParameter.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDBParameter.cs
new file mode 100644 (file)
index 0000000..493c6a5
--- /dev/null
@@ -0,0 +1,259 @@
+//namespace System.Data.Common\r
+//{\r
+//\r
+//    //using clr.System;\r
+//    //using clr.compiler.BitConstants;\r
+//\r
+//    using System.Data;\r
+//     using System.Data.ProviderBase;\r
+//     using System.Text;\r
+//\r
+//    /**\r
+//     * @author erand\r
+//     */\r
+//    public abstract class AbstractDBParameter : DbParameterBase, System.ICloneable\r
+//    {\r
+//        /* Properties from IDataParameter */\r
+////        protected ParameterDirection _direction = ParameterDirection.Input;\r
+////        protected bool _isNullable = false;\r
+////        protected String _name = null;\r
+////        protected String _sourceColumn = null;\r
+//        protected DataRowVersion _version = DataRowVersion.Current;\r
+////        protected Object _value = null;\r
+//\r
+//        /* Properties from IDbDataParameter */\r
+////        protected byte _precision;\r
+////        protected byte _scale;\r
+////        protected int _size = -1;\r
+//\r
+//        private int _place;\r
+//             private int _jdbcType;\r
+//    \r
+////        /**\r
+////         * @see System.Data.IDbDataParameter#Precision\r
+////         */\r
+////        public virtual byte Precision\r
+////        {\r
+////            get\r
+////            {\r
+////                return _precision;\r
+////            }\r
+////            set\r
+////            {\r
+////                _precision = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+////        /**\r
+////         * @see System.Data.IDbDataParameter#Scale\r
+////         */\r
+////        public virtual byte Scale\r
+////        {\r
+////            get\r
+////            {\r
+////                return _scale;\r
+////            }\r
+////            set\r
+////            {\r
+////                _scale = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+//\r
+////        /**\r
+////         * @see System.Data.IDbDataParameter#Size\r
+////         */\r
+////        public virtual int Size\r
+////        {\r
+////            get\r
+////            {\r
+////                return _size;\r
+////            }\r
+////            set\r
+////            {\r
+////                _size = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+////        /**\r
+////         * @see System.Data.IDataParameter#Direction\r
+////         */\r
+////        public virtual ParameterDirection Direction\r
+////        {\r
+////            get\r
+////            {\r
+////                return _direction;\r
+////            }\r
+////            set\r
+////            {\r
+////                _direction = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+////        /**\r
+////         * @see System.Data.IDataParameter#IsNullable\r
+////         */\r
+////        public virtual bool IsNullable\r
+////        {\r
+////            get\r
+////            {\r
+////                return _isNullable;\r
+////            }\r
+////            set\r
+////            {\r
+////                _isNullable = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+////        /**\r
+////         * @see System.Data.IDataParameter#ParameterName\r
+////         */\r
+////        public virtual String ParameterName\r
+////        {\r
+////            get\r
+////            {\r
+////                /**@todo What's the value of the Empty string ?*/\r
+////                /*Where to define our Empty String ?*/\r
+////                if (_name == null)\r
+////                    return String.Empty;\r
+////                else\r
+////                    return _name;\r
+////            }\r
+////            set\r
+////            {\r
+////                if ((value != null) && value.Equals(_name))\r
+////                    return;\r
+////                //if ((value != null) && (value.length() > Constants.MAXIMAL_PARAMETER_LENGTH))\r
+////                /**@todo Implement Exception::-->*/\r
+////                //    throw InvalidParameterLength(value);\r
+////\r
+////                _name = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+////        /**\r
+////         * @see System.Data.IDataParameter#SourceColumn\r
+////         */\r
+////        public virtual String SourceColumn\r
+////        {\r
+////            get\r
+////            {\r
+////                if (_sourceColumn != null)\r
+////                    return _sourceColumn;\r
+////                else\r
+////                    return String.Empty;\r
+////            }\r
+////            set\r
+////            {\r
+////                _sourceColumn = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+//\r
+////        /**\r
+////         * @see System.Data.IDataParameter#SourceVersion\r
+////         */\r
+////        public virtual DataRowVersion SourceVersion\r
+////        {\r
+////            get\r
+////            {\r
+////                return _version;\r
+////            }\r
+////            set\r
+////            {\r
+////                _version = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+////        /**\r
+////         * @see System.Data.IDataParameter#Value\r
+////         */\r
+////        public virtual Object Value\r
+////        {\r
+////            get\r
+////            {\r
+////                return _value;\r
+////            }\r
+////            set\r
+////            {\r
+////                _value = value;\r
+////            }\r
+////        }\r
+//\r
+//        \r
+//\r
+//        public virtual void setParameterPlace(int place)\r
+//        {\r
+//            _place = place;\r
+//        }\r
+//\r
+//        public virtual int getParameterPlace()\r
+//        {\r
+//            return _place;\r
+//        }\r
+//\r
+//        abstract internal int getJDBCType(DbType dbType);\r
+//\r
+//             internal int JdbcType\r
+//             {\r
+//                     get {\r
+//                             return _jdbcType;\r
+//                     }\r
+//\r
+//                     set {\r
+//                             _jdbcType = value;\r
+//                     }\r
+//             }\r
+//\r
+//        public abstract DbType DbType\r
+//        {\r
+//            get;\r
+//            set;\r
+//        }\r
+//\r
+//        public abstract Object Clone();\r
+//\r
+//             internal virtual bool IsOracleRefCursor\r
+//             {\r
+//                     get\r
+//                     {\r
+//                             return false;\r
+//                     }\r
+//             }\r
+//        \r
+//        internal virtual String formatParameter()\r
+//        {\r
+//                     if (Value == null || Value == DBNull.Value)\r
+//                             return "NULL";\r
+//                 \r
+//                     switch(DbType) {\r
+//                             case DbType.Byte:\r
+//                             case DbType.Currency:\r
+//                             case DbType.Decimal:\r
+//                             case DbType.Double:\r
+//                             case DbType.Int16:\r
+//                             case DbType.Int32:\r
+//                             case DbType.Int64:\r
+//                             case DbType.SByte:\r
+//                             case DbType.Single:\r
+//                             case DbType.UInt16:\r
+//                             case DbType.UInt32:\r
+//                             case DbType.UInt64:\r
+//                                     return Value.ToString();\r
+//                             case DbType.Boolean:\r
+//                                     return (bool)Value ? "0x1" : "0x0";\r
+//                             case DbType.Binary:\r
+//                             default:\r
+//                                     return String.Concat("\'", Value.ToString().Replace("\'", "\'\'"),"\'");\r
+//                     }\r
+//        }\r
+//    }\r
+//}
\ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDataReader.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractDataReader.cs
new file mode 100644 (file)
index 0000000..b6bdbc5
--- /dev/null
@@ -0,0 +1,1179 @@
+//\r
+// System.Data.Common.AbstractDataReader\r
+//\r
+// Author:\r
+//   Boris Kirzner (borisk@mainsoft.com)\r
+//   Konstantin Triger (kostat@mainsoft.com)\r
+//\r
+\r
+using System;\r
+using System.Data;\r
+using System.Collections;\r
+using System.Data.ProviderBase;\r
+\r
+using java.io;\r
+using java.sql;\r
+\r
+namespace System.Data.Common\r
+{\r
+       public abstract class AbstractDataReader : DbDataReaderBase, ISafeDataRecord {\r
+               #region Fields\r
+\r
+               private ResultSetMetaData _resultsMetaData;\r
+               protected AbstractDbCommand _command;\r
+               private DataTable _schemaTable;\r
+               private ReaderState _readerState = ReaderState.Uninitialized;\r
+\r
+               private IReaderCacheContainer[] _readerCache;\r
+               private int _currentCacheFilledPosition; \r
+               private Stack _resultSetStack = new Stack();\r
+\r
+               [Flags]\r
+               private enum ReaderState { Uninitialized = 0, Empty = 1, HasRows = 2, FirstRed = 4, Eof = 8, Fetching = 16 };\r
+\r
+               internal enum SCHEMA_TABLE { ColumnName,\r
+                       ColumnOrdinal,\r
+                       ColumnSize,\r
+                       NumericPrecision,\r
+                       NumericScale,\r
+                       IsUnique,\r
+                       IsKey,\r
+                       BaseServerName,\r
+                       BaseCatalogName,\r
+                       BaseColumnName,\r
+                       BaseSchemaName,\r
+                       BaseTableName,\r
+                       DataType,\r
+                       AllowDBNull,\r
+                       ProviderType,\r
+                       IsAliased,\r
+                       IsExpression,\r
+                       IsIdentity,\r
+                       IsAutoIncrement,\r
+                       IsRowVersion,\r
+                       IsHidden,\r
+                       IsLong,\r
+                       IsReadOnly};\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               protected AbstractDataReader() : base (CommandBehavior.Default) {\r
+               }\r
+               \r
+               public AbstractDataReader(AbstractDbCommand command): base(command.Behavior) {\r
+                       _command = command;\r
+                       if (_command.Connection != null) {\r
+                               ((AbstractDBConnection)_command.Connection).AddReference(this);\r
+                       }\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Properties\r
+\r
+               public override bool HasRows {\r
+                       get {\r
+                               if (IsClosed) {\r
+                                       throw new InvalidOperationException("Invalid attempt to HasRows when reader is closed.");\r
+                               }\r
+\r
+                               try {\r
+                                       if(null == Results)\r
+                                               return false;\r
+                               }\r
+                               catch(SystemException) {\r
+                                       //suppress\r
+                                       return false;\r
+                               }\r
+\r
+                               return (_readerState & ReaderState.HasRows) != 0;\r
+                       }\r
+               }\r
+\r
+               public override int RecordsAffected\r
+               {\r
+                       // MSDN : The RecordsAffected property is not set \r
+                       // until all rows are read and you close the reader.\r
+                       get { \r
+                               return _command.RecordsAffected; \r
+                       }\r
+               }\r
+\r
+               public override int FieldCount\r
+               {\r
+                       get {\r
+                               if (ResultsMetaData == null)\r
+                                       return 0;\r
+\r
+                               try {\r
+                                       return ResultsMetaData.getColumnCount();\r
+                               }\r
+                               catch (SQLException exp) {\r
+                                       throw CreateException(exp);\r
+                               }\r
+\r
+                       }\r
+               }\r
+\r
+               protected internal CommandBehavior Behavior\r
+               {\r
+                       get {\r
+                               return _command.Behavior;\r
+                       }\r
+               }\r
+\r
+               public override Object this[String columnName]\r
+               {\r
+                       get {\r
+                               try {\r
+                                       int columnIndex = Results.findColumn(columnName) - 1;\r
+                                       return this[columnIndex];\r
+                               }\r
+                               catch (SQLException exp) {\r
+                                       throw new IndexOutOfRangeException(exp.Message, exp);\r
+                               }                               \r
+                       }\r
+               }\r
+\r
+               public override Object this[int columnIndex]\r
+               {\r
+                       get { return GetValue(columnIndex); }\r
+               }\r
+\r
+               protected ResultSet Results\r
+               {\r
+                       get {\r
+                               if (_readerState == ReaderState.Uninitialized) {\r
+\r
+                                       if (_resultSetStack.Count == 0) {\r
+                                               ResultSet resultSet =  _command.CurrentResultSet;\r
+                                               if (resultSet == null)\r
+                                                       return null;\r
+\r
+                                               _resultSetStack.Push(resultSet);\r
+                                       }\r
+\r
+                                       _readerState = ReaderState.Fetching;\r
+                                       for (;;) {\r
+                                               try {\r
+                                                       Configuration.BooleanSetting prefetchSchema = Configuration.Switches.PrefetchSchema;\r
+\r
+                                                       if (prefetchSchema == Configuration.BooleanSetting.NotSet) {\r
+                                                               AbstractDBConnection conn = (AbstractDBConnection)((ICloneable)_command.Connection);\r
+                                                               string driverName = conn.JdbcConnection.getMetaData().getDriverName();\r
+                                                               if (driverName.IndexOf("DB2") >= 0)\r
+                                                                       prefetchSchema = Configuration.BooleanSetting.True;\r
+                                                       }\r
+\r
+                                                       if (prefetchSchema == Configuration.BooleanSetting.True)\r
+                                                               GetSchemaTable();\r
+\r
+                                                       ResultSet resultSet = (ResultSet)_resultSetStack.Peek();\r
+                                                       if (resultSet.next()) {\r
+                                                               _readerState = (ReaderState.HasRows | ReaderState.FirstRed);\r
+                                                               ResultSetMetaData rsMetaData = ResultsMetaData;\r
+                                                               DbTypes.JavaSqlTypes javaSqlType = (DbTypes.JavaSqlTypes)rsMetaData.getColumnType(1);\r
+                                                               if (javaSqlType == DbTypes.JavaSqlTypes.OTHER) {\r
+                                                                       object value = GetValue(0);\r
+                                                                       if (value != null && value is ResultSet) {\r
+                                                                               _resultsMetaData = null;\r
+                                                                               _readerCache = null;\r
+                                                                               SchemaTable = null;\r
+                                                                               _readerState = ReaderState.Fetching;\r
+                                                                               _resultSetStack.Push(value);\r
+                                                                               continue;\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                                       else\r
+                                                               _readerState = ReaderState.Empty;\r
+\r
+                                                       break;\r
+                                               }\r
+                                               catch(SQLException e) {\r
+                                                       throw CreateException(e);\r
+                                               }\r
+                                       }\r
+                               }\r
+\r
+                               return (_resultSetStack.Count > 0) ? (ResultSet)_resultSetStack.Peek() : null;\r
+                       }\r
+               }\r
+\r
+               protected ResultSetMetaData ResultsMetaData\r
+               {\r
+                       get {\r
+                               ResultSet results = Results;\r
+                               if (results == null) {\r
+                                       return null;\r
+                               }\r
+                               if(_resultsMetaData == null) {\r
+                                       _resultsMetaData = results.getMetaData();\r
+                               }\r
+                               return _resultsMetaData;\r
+                       }                       \r
+               }\r
+\r
+               protected DataTable SchemaTable\r
+               {\r
+                       get {\r
+                               if (_schemaTable == null) {\r
+                                       _schemaTable = ConstructSchemaTable();\r
+                               }\r
+                               return _schemaTable;\r
+                       }\r
+\r
+                       set {_schemaTable = value; }\r
+               }\r
+\r
+               internal protected IReaderCacheContainer[] ReaderCache\r
+               {\r
+                       get {\r
+                               if (_readerCache == null) {\r
+                                       _readerCache = CreateReaderCache();\r
+                                       _currentCacheFilledPosition = -1;\r
+                               }\r
+                               return _readerCache;\r
+                       }\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+\r
+               protected abstract int GetProviderType(int jdbcType);\r
+\r
+               protected abstract SystemException CreateException(string message, SQLException e);\r
+\r
+               protected abstract SystemException CreateException(IOException e);\r
+\r
+               protected SystemException CreateException(SQLException e)\r
+               {\r
+                       return CreateException(e.Message,e);    \r
+               }\r
+\r
+               private bool CloseCurrentResultSet() {\r
+                       if (_resultSetStack.Count > 0) {\r
+                               try{\r
+                                       _resultsMetaData = null;\r
+                                       _readerCache = null;\r
+                                       _readerState = ReaderState.Uninitialized;\r
+                                       ResultSet rs = (ResultSet)_resultSetStack.Pop();\r
+                                       rs.close();\r
+                                       return true;\r
+                               }\r
+                               catch (SQLException exp) {\r
+                                       throw CreateException(exp);\r
+                               }\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               // FIXME : add Close(bool readAllRecords) and pass this bool to skip looping over NextResult(), override AbstractDbCommand.ExecuteScalar\r
+               public override void Close()\r
+               {\r
+                       if (IsClosed)\r
+                               return;\r
+\r
+                       try {\r
+                               CloseCurrentResultSet();\r
+                               _command.OnReaderClosed(this);\r
+                       }\r
+                       finally {\r
+                               CloseInternal();\r
+                       }\r
+               }\r
+\r
+               internal void CloseInternal()\r
+               {\r
+                       _resultsMetaData = null;\r
+                       _readerCache = null;\r
+                       _isClosed = true;\r
+               }\r
+\r
+               public override bool NextResult()\r
+               {\r
+                       CloseCurrentResultSet();\r
+\r
+                       if ((_command.Behavior & CommandBehavior.SingleResult) != 0) {\r
+                               while (CloseCurrentResultSet());\r
+                               while (_command.NextResultSet());\r
+                               return false;\r
+                       }\r
+\r
+                       try {\r
+                               while (_resultSetStack.Count > 0) {\r
+                                       ResultSet rs = (ResultSet)_resultSetStack.Peek();\r
+\r
+                                       if(!rs.next()) {\r
+                                               CloseCurrentResultSet();\r
+                                               continue;\r
+                                       }\r
+\r
+                                       // must be a ResultSet\r
+                                       object childRs = rs.getObject(1);\r
+                                       if (childRs != null) {\r
+                                               SchemaTable = null;\r
+                                               _resultSetStack.Push(childRs);\r
+                                               return true;\r
+                                       }\r
+                               }\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               throw CreateException(exp);\r
+                       }\r
+                               \r
+                       if (_command.NextResultSet()) {\r
+                               SchemaTable = null;     \r
+                               return true;\r
+                       }\r
+                       return false;\r
+               }\r
+\r
+               public override bool Read()\r
+               {\r
+                       if(null == Results ||\r
+                               (_readerState & (ReaderState.HasRows | ReaderState.Eof)) != ReaderState.HasRows)\r
+                               return false;\r
+\r
+                       bool firstRead = false;\r
+\r
+                       try {\r
+                               if ((_readerState & ReaderState.FirstRed) != 0) {\r
+                                       firstRead = true;\r
+                                       _readerState &= ~ReaderState.FirstRed;\r
+                                       return true;\r
+                               }\r
+                               else {\r
+                                       bool next = Results.next();\r
+\r
+                                       if (!next)\r
+                                               _readerState |= ReaderState.Eof;\r
+\r
+                                       return next;\r
+                               }\r
+                       }                       \r
+                       catch (SQLException exp) {\r
+                               // suppress exception as .Net does\r
+                               return false;\r
+                       }\r
+                       finally {\r
+                               // in case of first read we could sampled the first value\r
+                               // to see whether there is a resultset, so _currentCacheFilledPosition\r
+                               // might be already inited\r
+                               if (!firstRead)\r
+                                       _currentCacheFilledPosition = -1;\r
+                       }\r
+               }\r
+\r
+               public override bool GetBoolean(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((BooleanReaderCacheContainer)ReaderCache[columnIndex]).GetBoolean();\r
+               }\r
+\r
+               public bool GetBooleanSafe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is BooleanReaderCacheContainer) {\r
+                               return GetBoolean(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToBoolean(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override byte GetByte(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((ByteReaderCacheContainer)ReaderCache[columnIndex]).GetByte();\r
+               }\r
+\r
+               public byte GetByteSafe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is ByteReaderCacheContainer) {\r
+                               return GetByte(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToByte(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override long GetBytes(\r
+                       int columnIndex,\r
+                       long dataIndex,\r
+                       byte[] buffer,\r
+                       int bufferIndex,\r
+                       int length)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       byte[] byteArr = ((BytesReaderCacheContainer)ReaderCache[columnIndex]).GetBytes();\r
+                       long actualLength = ((dataIndex + length) >= byteArr.Length) ? (byteArr.Length - dataIndex) : length;\r
+                       Array.Copy(byteArr,dataIndex,buffer,bufferIndex,actualLength);\r
+                       return actualLength;\r
+               }\r
+\r
+               public virtual byte[] GetBytes(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((BytesReaderCacheContainer)ReaderCache[columnIndex]).GetBytes();\r
+               }\r
+\r
+               public override char GetChar(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       string s = ((StringReaderCacheContainer)ReaderCache[columnIndex]).GetString();\r
+                       if(s == null) {\r
+                               return '\0';\r
+                       }\r
+                       return s[0];\r
+               }\r
+\r
+               public char GetCharSafe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is StringReaderCacheContainer) {\r
+                               return GetChar(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToChar(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override long GetChars(\r
+                       int columnIndex,\r
+                       long dataIndex,\r
+                       char[] buffer,\r
+                       int bufferIndex,\r
+                       int length)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       char[] charArr = ((CharsReaderCacheContainer)ReaderCache[columnIndex]).GetChars();\r
+                       long actualLength = ((dataIndex + length) >= charArr.Length) ? (charArr.Length - dataIndex) : length;\r
+                       Array.Copy(charArr,dataIndex,buffer,bufferIndex,actualLength);\r
+                       return actualLength;\r
+               }\r
+\r
+               public override string GetDataTypeName(int columnIndex)\r
+               {\r
+                       try {\r
+                               if (ResultsMetaData == null) {\r
+                                       return String.Empty;\r
+                               }\r
+                               return ResultsMetaData.getColumnTypeName(columnIndex + 1);\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               throw CreateException(exp);\r
+                       }\r
+               }\r
+\r
+               public override DateTime GetDateTime(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((DateTimeReaderCacheContainer)ReaderCache[columnIndex]).GetDateTime();\r
+               }\r
+\r
+               public virtual TimeSpan GetTimeSpan(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((TimeSpanReaderCacheContainer)ReaderCache[columnIndex]).GetTimeSpan();\r
+               }\r
+\r
+               public override Guid GetGuid(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((GuidReaderCacheContainer)ReaderCache[columnIndex]).GetGuid();\r
+               }\r
+\r
+               public override decimal GetDecimal(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((DecimalReaderCacheContainer)ReaderCache[columnIndex]).GetDecimal();\r
+               }\r
+\r
+               public decimal GetDecimalSafe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is DecimalReaderCacheContainer) {\r
+                               return GetDecimal(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToDecimal(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override double GetDouble(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((DoubleReaderCacheContainer)ReaderCache[columnIndex]).GetDouble();\r
+               }\r
+\r
+               public double GetDoubleSafe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is DoubleReaderCacheContainer) {\r
+                               return GetDouble(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToDouble(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override float GetFloat(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((FloatReaderCacheContainer)ReaderCache[columnIndex]).GetFloat();\r
+               }\r
+\r
+               public float GetFloatSafe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is FloatReaderCacheContainer) {\r
+                               return GetFloat(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToSingle(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override short GetInt16(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((Int16ReaderCacheContainer)ReaderCache[columnIndex]).GetInt16();\r
+               }\r
+\r
+               public short GetInt16Safe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is Int16ReaderCacheContainer) {\r
+                               return GetInt16(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToInt16(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override int GetInt32(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((Int32ReaderCacheContainer)ReaderCache[columnIndex]).GetInt32();\r
+               }\r
+\r
+               public int GetInt32Safe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is Int32ReaderCacheContainer) {\r
+                               return GetInt32(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToInt32(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override long GetInt64(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((Int64ReaderCacheContainer)ReaderCache[columnIndex]).GetInt64();\r
+               }\r
+\r
+               public long GetInt64Safe(int columnIndex)\r
+               {\r
+                       if (ReaderCache[columnIndex] is Int64ReaderCacheContainer) {\r
+                               return GetInt64(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToInt64(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override string GetName(int columnIndex)\r
+               {\r
+                       try {\r
+                               if (ResultsMetaData == null) {\r
+                                       return String.Empty;\r
+                               }\r
+                               return ResultsMetaData.getColumnName(columnIndex + 1);\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               throw new IndexOutOfRangeException(exp.Message, exp);\r
+                       }\r
+               }\r
+\r
+               public override int GetOrdinal(String columnName)\r
+               {\r
+                       try {\r
+                               int retVal = Results.findColumn(columnName);\r
+                               if(retVal != -1) {\r
+                                       retVal -= 1;\r
+                               }\r
+                               return  retVal;\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               throw new IndexOutOfRangeException(exp.Message, exp);\r
+                       }\r
+               }\r
+\r
+               public override string GetString(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ((StringReaderCacheContainer)ReaderCache[columnIndex]).GetString();\r
+               }\r
+\r
+               public string GetStringSafe(int columnIndex) {\r
+                       if (ReaderCache[columnIndex] is StringReaderCacheContainer) {\r
+                               return GetString(columnIndex);\r
+                       }\r
+                       else {\r
+                               return Convert.ToString(GetValue(columnIndex));\r
+                       }\r
+               }\r
+\r
+               public override object GetValue(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       if (ReaderCache[columnIndex].IsNull()) {\r
+                               return DBNull.Value;\r
+                       }\r
+                       return ReaderCache[columnIndex].GetValue();\r
+               }\r
+\r
+               public override int GetValues(Object[] values)\r
+               {       \r
+                       int columnCount = FieldCount;\r
+                       int i = 0;\r
+                       for (; i < values.Length && i < columnCount; i++) {\r
+                               values[i] = GetValue(i);\r
+                       }\r
+                       return i;\r
+               }\r
+\r
+               private void FillReaderCache(int columnIndex)\r
+               {\r
+                       try {\r
+                               IReaderCacheContainer[] readerCache = ReaderCache;\r
+                               if ((Behavior & CommandBehavior.SequentialAccess) == 0) {                                       \r
+                                       while (_currentCacheFilledPosition < columnIndex) {\r
+                                               _currentCacheFilledPosition++;\r
+                                               readerCache[_currentCacheFilledPosition].Fetch(Results,_currentCacheFilledPosition);\r
+                                       }                                       \r
+                               }\r
+                               else {\r
+                                       readerCache[columnIndex].Fetch(Results,columnIndex);\r
+                               }\r
+                       }\r
+                       catch(SQLException e) {\r
+                               _currentCacheFilledPosition = -1;\r
+                               throw CreateException(e);\r
+                       }\r
+                       catch (IOException e) {\r
+                               _currentCacheFilledPosition = -1;\r
+                               throw CreateException(e);\r
+                       }\r
+               }\r
+\r
+               private IReaderCacheContainer[] CreateReaderCache()\r
+               {\r
+                       try {\r
+                               IReaderCacheContainer[] readerCache = new IReaderCacheContainer[FieldCount];\r
+                               for(int i=0; i < readerCache.Length; i++) {\r
+                                       DbTypes.JavaSqlTypes javaSqlType = (DbTypes.JavaSqlTypes) ResultsMetaData.getColumnType(i + 1);\r
+                                       switch (javaSqlType) {\r
+                                               case DbTypes.JavaSqlTypes.ARRAY :\r
+                                                       readerCache[i] = new ArrayReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.BIGINT :\r
+                                                       readerCache[i] = new Int64ReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.BINARY :\r
+                                               case DbTypes.JavaSqlTypes.VARBINARY :\r
+                                               case DbTypes.JavaSqlTypes.LONGVARBINARY :\r
+                                                       readerCache[i] = new BytesReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.BIT :\r
+                                                       readerCache[i] = new BooleanReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.BLOB :\r
+                                                       readerCache[i] = new BlobReaderCacheContainer();\r
+                                                       break;  \r
+                                               case DbTypes.JavaSqlTypes.CHAR :                                                \r
+                                                       if ("uniqueidentifier".Equals(ResultsMetaData.getColumnTypeName(i + 1))) {\r
+                                                               readerCache[i] = new GuidReaderCacheContainer();\r
+                                                       }\r
+                                                       else {\r
+                                                               readerCache[i] = new StringReaderCacheContainer();\r
+                                                       }\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.CLOB :\r
+                                                       readerCache[i] = new ClobReaderCacheContainer();\r
+                                                       break;          \r
+                                               case DbTypes.JavaSqlTypes.TIME :\r
+                                                       readerCache[i] = new TimeSpanReaderCacheContainer();\r
+                                                       break;  \r
+                                               case DbTypes.JavaSqlTypes.DATE :\r
+                                                       AbstractDBConnection conn = (AbstractDBConnection)((ICloneable)_command.Connection);\r
+                                                       string driverName = conn.JdbcConnection.getMetaData().getDriverName();\r
+\r
+                                                       if (driverName.StartsWith("PostgreSQL")) {\r
+                                                               readerCache[i] = new DateTimeReaderCacheContainer();\r
+                                                               break;\r
+                                                       }\r
+                                                       else\r
+                                                               goto case DbTypes.JavaSqlTypes.TIMESTAMP;\r
+                                               case DbTypes.JavaSqlTypes.TIMESTAMP :                           \r
+                                                       readerCache[i] = new TimestampReaderCacheContainer();\r
+                                                       break;          \r
+                                               case DbTypes.JavaSqlTypes.DECIMAL :\r
+                                               case DbTypes.JavaSqlTypes.NUMERIC :\r
+                                                       // jdbc driver for oracle identitfies both FLOAT and NUMBEr columns as \r
+                                                       // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal \r
+                                                       // therefore we relay on scale\r
+                                                       int scale = ResultsMetaData.getScale(i + 1);\r
+                                                       if (scale == -127) {\r
+                                                               // Oracle db type FLOAT\r
+                                                               readerCache[i] = new DoubleReaderCacheContainer();\r
+                                                       }\r
+                                                       else {\r
+                                                               readerCache[i] = new DecimalReaderCacheContainer();\r
+                                                       }\r
+                                                       break;          \r
+                                               case DbTypes.JavaSqlTypes.DOUBLE :\r
+                                               case DbTypes.JavaSqlTypes.FLOAT :\r
+                                                       readerCache[i] = new DoubleReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.INTEGER :\r
+                                                       readerCache[i] = new Int32ReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.LONGVARCHAR :\r
+                                               case DbTypes.JavaSqlTypes.VARCHAR :\r
+                                                       readerCache[i] = new StringReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.NULL :\r
+                                                       readerCache[i] = new NullReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.REAL :\r
+                                                       readerCache[i] = new FloatReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.REF :\r
+                                                       readerCache[i] = new RefReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.SMALLINT :\r
+                                                       readerCache[i] = new Int16ReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.TINYINT :\r
+                                                       readerCache[i] = new ByteReaderCacheContainer();\r
+                                                       break;\r
+                                               case DbTypes.JavaSqlTypes.DISTINCT :\r
+                                               case DbTypes.JavaSqlTypes.JAVA_OBJECT :\r
+                                               case DbTypes.JavaSqlTypes.OTHER :\r
+                                               case DbTypes.JavaSqlTypes.STRUCT :\r
+                                               default :\r
+                                                       readerCache[i] = new ObjectReaderCacheContainer();\r
+                                                       break;\r
+                                       }\r
+                                       //                              ((ReaderCacheContainerBase)readerCache[i])._jdbcType = (int) javaSqlType;\r
+                               }\r
+\r
+                               return readerCache;\r
+                       }\r
+                       catch(SQLException e) {\r
+                               throw CreateException(e);\r
+                       }\r
+               }\r
+\r
+               public override bool IsDBNull(int columnIndex)\r
+               {\r
+                       FillReaderCache(columnIndex);\r
+                       return ReaderCache[columnIndex].IsNull();\r
+               }\r
+\r
+               public override Type GetFieldType(int i)\r
+               {\r
+                       try {\r
+                               int javaSqlType = ResultsMetaData.getColumnType(i + 1);\r
+                               return DbConvert.JavaSqlTypeToClrType(javaSqlType);\r
+                       }\r
+                       catch (SQLException exp) {\r
+                               throw new IndexOutOfRangeException(exp.Message, exp);\r
+                       }\r
+               }\r
+\r
+               public IDataReader GetData(int i)\r
+               {\r
+                       throw new NotSupportedException();\r
+               }\r
+\r
+               public override DataTable GetSchemaTable()\r
+               {\r
+                       if (SchemaTable.Rows != null && SchemaTable.Rows.Count > 0) {\r
+                               return SchemaTable;\r
+                       }\r
+            \r
+                       ResultSetMetaData metaData;                     \r
+                       if (Behavior == CommandBehavior.SchemaOnly) {\r
+                               try {\r
+                                       metaData = ((PreparedStatement)_command.JdbcStatement).getMetaData();\r
+                               }\r
+                               catch(SQLException e) {\r
+                                       throw CreateException("CommandBehaviour.SchemaOnly is not supported by the JDBC driver.",e);\r
+                               }\r
+                       }\r
+                       else {\r
+                               metaData = ResultsMetaData;\r
+                       }\r
+\r
+                       if (metaData == null) {\r
+                               return SchemaTable;\r
+                       }\r
+\r
+                       DatabaseMetaData dbMetaData = null;\r
+                       AbstractDBConnection clonedConnection = null;\r
+                       if ((_command.Behavior & CommandBehavior.KeyInfo) != 0) {\r
+                               clonedConnection = (AbstractDBConnection)((ICloneable)_command.Connection).Clone();\r
+\r
+                               try {\r
+                                       clonedConnection.Open();\r
+                                       dbMetaData = clonedConnection.JdbcConnection.getMetaData();\r
+                               }\r
+                               catch {\r
+                                       //suppress\r
+                                       if (clonedConnection != null) {\r
+                                               clonedConnection.Close();\r
+                                       }\r
+                               }                       \r
+                       }\r
+                       \r
+                       try {\r
+                               int tmp;                                \r
+                               for(int i = 1; i <= metaData.getColumnCount(); i++) {\r
+                                       DataRow row = SchemaTable.NewRow ();\r
+                                       string columnName = metaData.getColumnLabel(i);\r
+                                       string baseColumnName = metaData.getColumnName(i);\r
+       \r
+                                       row [(int)SCHEMA_TABLE.ColumnName] = columnName; // maybe we should use metaData.getColumnLabel(i);\r
+                                       row [(int)SCHEMA_TABLE.ColumnSize] = metaData.getColumnDisplaySize(i);\r
+                                       row [(int)SCHEMA_TABLE.ColumnOrdinal]           = i - 1;\r
+                                       try {\r
+                                               // FIXME : workaround for Oracle JDBC driver bug\r
+                                               // getPrecision on BLOB, CLOB, NCLOB throws NumberFormatException\r
+                                               tmp = metaData.getPrecision(i);\r
+                                       }\r
+                                       catch(java.lang.NumberFormatException e) {\r
+                                               // supress exception\r
+                                               tmp = 255;\r
+                                       }\r
+                                       row [(int)SCHEMA_TABLE.NumericPrecision] = Convert.ToInt16(tmp > 255 ? 255 : tmp);\r
+                                       tmp = metaData.getScale(i);\r
+                                       row [(int)SCHEMA_TABLE.NumericScale] = Convert.ToInt16(tmp > 255 ? 255 : tmp);\r
+\r
+                                       row [(int)SCHEMA_TABLE.BaseServerName] = DBNull.Value;\r
+                               \r
+                                       string catalog = null;\r
+                                       try {\r
+                                               catalog = metaData.getCatalogName(i);\r
+                                       }\r
+                                       catch (Exception e) {\r
+                                               // supress exception\r
+                                       }\r
+                                       if (catalog != null && catalog.Length == 0)\r
+                                               catalog =  ((AbstractDBConnection)_command.Connection).JdbcConnection.getCatalog();\r
+                                       row [(int)SCHEMA_TABLE.BaseCatalogName] = catalog;\r
+                                       row [(int)SCHEMA_TABLE.BaseColumnName] = baseColumnName;\r
+\r
+                                       string schemaName;\r
+                                       string tableName;\r
+\r
+                                       try {\r
+                                               tableName = metaData.getTableName(i);\r
+                                       }\r
+                                       catch {\r
+                                               tableName = null;\r
+                                       }\r
+\r
+                                       try {\r
+                                               schemaName = metaData.getSchemaName(i);\r
+                                       }\r
+                                       catch {\r
+                                               schemaName = null;\r
+                                       }\r
+\r
+                                       if (tableName != null && tableName.Length == 0)\r
+                                               tableName = null;\r
+                                       if (schemaName != null && schemaName.Length == 0)\r
+                                               schemaName = null;\r
+\r
+                                       row [(int)SCHEMA_TABLE.BaseSchemaName] = schemaName;\r
+                                       row [(int)SCHEMA_TABLE.BaseTableName] = tableName;\r
+\r
+\r
+                                       row [(int)SCHEMA_TABLE.AllowDBNull] = Convert.ToBoolean(metaData.isNullable(i));\r
+                               \r
+                                       InitKeyInfo(row, dbMetaData, catalog, schemaName, tableName);\r
+                               \r
+                                       row [(int)SCHEMA_TABLE.IsAliased] = columnName != baseColumnName;\r
+                                       row [(int)SCHEMA_TABLE.IsExpression] = false;\r
+\r
+                                       row [(int)SCHEMA_TABLE.IsAutoIncrement] = metaData.isAutoIncrement(i);\r
+\r
+                                       row [(int)SCHEMA_TABLE.IsHidden] = false;\r
+                                       row [(int)SCHEMA_TABLE.IsReadOnly] = metaData.isReadOnly(i);\r
+\r
+                                       int columnType = metaData.getColumnType(i);\r
+                                       string columnTypeName = metaData.getColumnTypeName(i);\r
+                                       if(columnType == Types.ARRAY) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Array);\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.BIGINT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt64;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.BINARY) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.BIT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfBoolean;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.BLOB) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.CHAR) {\r
+                                               // FIXME : specific for Microsoft SQl Server driver\r
+                                               if (columnTypeName.Equals("uniqueidentifier")) {\r
+                                                       row [(int)SCHEMA_TABLE.ProviderType] = DbType.Guid;\r
+                                                       row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfGuid;\r
+                                                       row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                               }\r
+                                               else {\r
+                                                       row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                                       row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;\r
+                                                       row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                               }\r
+                                       }\r
+                                       else if(columnType == Types.CLOB) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString; // instead og .java.sql.Clob\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.DATE) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDateTime;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.DECIMAL) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDecimal;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                               //                else if(columnType == Types.DISTINCT)\r
+                                               //                {\r
+                                               //                    row ["ProviderType = (int)GetProviderType(columnType);\r
+                                               //                    row ["DataType = typeof (?);\r
+                                               //                    row ["IsLong = false;\r
+                                               //                }\r
+                                       else if(columnType == Types.DOUBLE) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble; // was typeof(float)\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.FLOAT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.REAL) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfFloat;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.INTEGER) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt32;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.JAVA_OBJECT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.LONGVARBINARY) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.LONGVARCHAR) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.NUMERIC) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDecimal;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.REF) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Ref);\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.SMALLINT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt16;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.STRUCT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Struct);\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.TIME) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfTimespan;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.TIMESTAMP) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDateTime;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.TINYINT) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByte;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else if(columnType == Types.VARBINARY) {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       else if(columnType == Types.VARCHAR) {\r
+                                               // FIXME : specific for Microsoft SQl Server driver\r
+                                               if (columnTypeName.Equals("sql_variant")) {\r
+                                                       row [(int)SCHEMA_TABLE.ProviderType] = DbType.Object;\r
+                                                       row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;\r
+                                                       row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                               }\r
+                                               else {\r
+                                                       row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);\r
+                                                       row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;// (char[]);\r
+                                                       row [(int)SCHEMA_TABLE.IsLong] = false;//true;\r
+                                               }\r
+                                       }\r
+                                       else if(columnType == -8 && columnTypeName.Equals("ROWID")) {\r
+                                               // FIXME : specific for Oracle JDBC driver : OracleTypes.ROWID\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = DbType.String;\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = false;\r
+                                       }\r
+                                       else {\r
+                                               row [(int)SCHEMA_TABLE.ProviderType] = DbType.Object;\r
+                                               row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;\r
+                                               row [(int)SCHEMA_TABLE.IsLong] = true;\r
+                                       }\r
+                                       SchemaTable.Rows.Add (row);\r
+                               }\r
+                       }\r
+                       catch (SQLException e) {                                \r
+                               throw CreateException(e);\r
+                       }\r
+                       finally {\r
+                               if (clonedConnection != null) {\r
+                                       clonedConnection.Close();\r
+                               }\r
+                       }                       \r
+                       return SchemaTable;\r
+               }\r
+\r
+               private void InitKeyInfo(DataRow row, DatabaseMetaData dbMetaData, String catalog, String schema, String table) {\r
+                       string column = (string)row [(int)SCHEMA_TABLE.BaseColumnName];\r
+\r
+                       row [(int)SCHEMA_TABLE.IsUnique] = false;\r
+                       row [(int)SCHEMA_TABLE.IsKey] = false;\r
+                       row [(int)SCHEMA_TABLE.IsIdentity] = false;\r
+                       row [(int)SCHEMA_TABLE.IsRowVersion] = false;\r
+\r
+                       if ((_command.Behavior & CommandBehavior.KeyInfo) == 0)\r
+                               return;\r
+\r
+                       if(table == null || column == null || dbMetaData == null)\r
+                               return;\r
+\r
+                       ResultSet indexInfoRes = dbMetaData.getIndexInfo(catalog,schema,table,true,false);\r
+                       try {\r
+                               while(indexInfoRes.next()) {\r
+                                       if(indexInfoRes.getString("COLUMN_NAME") == column)\r
+                                               row [(int)SCHEMA_TABLE.IsUnique] = true;\r
+                               }\r
+                       }\r
+                       finally {\r
+                               indexInfoRes.close();\r
+                       }\r
+\r
+                       ResultSet versionCol = dbMetaData.getVersionColumns(catalog, schema, table);\r
+                       try {\r
+                               while(versionCol.next()) {\r
+                                       if(versionCol.getString("COLUMN_NAME") == column) {\r
+                                               if (DatabaseMetaData__Finals.versionColumnPseudo == versionCol.getShort("PSEUDO_COLUMN")) {\r
+                                                       row [(int)SCHEMA_TABLE.IsIdentity] = true;\r
+                                                       row [(int)SCHEMA_TABLE.IsRowVersion] = true;\r
+                                               }\r
+                                       }\r
+                               }\r
+                       }\r
+                       finally {\r
+                               versionCol.close();\r
+                       }\r
+\r
+                       ResultSet bestRowId = dbMetaData.getBestRowIdentifier(catalog, schema, table, DatabaseMetaData__Finals.bestRowTemporary, false);\r
+                       try {\r
+                               while(bestRowId.next()) {\r
+                                       if(bestRowId.getString("COLUMN_NAME") == column)\r
+                                               row [(int)SCHEMA_TABLE.IsKey] = true;\r
+                               }\r
+                       }\r
+                       finally {\r
+                               bestRowId.close();\r
+                       }\r
+               }\r
+\r
+               protected static DataTable ConstructSchemaTable ()\r
+               {\r
+                       Type booleanType = DbTypes.TypeOfBoolean;\r
+                       Type stringType = DbTypes.TypeOfString;\r
+                       Type intType = DbTypes.TypeOfInt32;\r
+                       Type typeType = DbTypes.TypeOfType;\r
+                       Type shortType = DbTypes.TypeOfInt16;\r
+\r
+                       DataTable schemaTable = new DataTable ("SchemaTable");\r
+                       schemaTable.Columns.Add ("ColumnName", stringType);\r
+                       schemaTable.Columns.Add ("ColumnOrdinal", intType);\r
+                       schemaTable.Columns.Add ("ColumnSize", intType);\r
+                       schemaTable.Columns.Add ("NumericPrecision", shortType);\r
+                       schemaTable.Columns.Add ("NumericScale", shortType);\r
+                       schemaTable.Columns.Add ("IsUnique", booleanType);\r
+                       schemaTable.Columns.Add ("IsKey", booleanType);\r
+                       schemaTable.Columns.Add ("BaseServerName", stringType);\r
+                       schemaTable.Columns.Add ("BaseCatalogName", stringType);\r
+                       schemaTable.Columns.Add ("BaseColumnName", stringType);\r
+                       schemaTable.Columns.Add ("BaseSchemaName", stringType);\r
+                       schemaTable.Columns.Add ("BaseTableName", stringType);\r
+                       schemaTable.Columns.Add ("DataType", typeType);\r
+                       schemaTable.Columns.Add ("AllowDBNull", booleanType);\r
+                       schemaTable.Columns.Add ("ProviderType", intType);\r
+                       schemaTable.Columns.Add ("IsAliased", booleanType);\r
+                       schemaTable.Columns.Add ("IsExpression", booleanType);\r
+                       schemaTable.Columns.Add ("IsIdentity", booleanType);\r
+                       schemaTable.Columns.Add ("IsAutoIncrement", booleanType);\r
+                       schemaTable.Columns.Add ("IsRowVersion", booleanType);\r
+                       schemaTable.Columns.Add ("IsHidden", booleanType);\r
+                       schemaTable.Columns.Add ("IsLong", booleanType);\r
+                       schemaTable.Columns.Add ("IsReadOnly", booleanType);\r
+                       return schemaTable;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+}
\ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractTransaction.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/AbstractTransaction.cs
new file mode 100644 (file)
index 0000000..586976b
--- /dev/null
@@ -0,0 +1,152 @@
+/*\r
+  * Copyright (c) 2002-2004 Mainsoft Corporation.\r
+  *\r
+  * Permission is hereby granted, free of charge, to any person obtaining a\r
+  * copy of this software and associated documentation files (the "Software"),\r
+  * to deal in the Software without restriction, including without limitation\r
+  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+  * and/or sell copies of the Software, and to permit persons to whom the\r
+  * Software is furnished to do so, subject to the following conditions:\r
+  *\r
+  * The above copyright notice and this permission notice shall be included in\r
+  * all copies or substantial portions of the Software.\r
+  *\r
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+  * DEALINGS IN THE SOFTWARE.\r
+  */\r
+\r
+namespace System.Data.Common\r
+{\r
+\r
+    using java.sql;\r
+\r
+    using System.Data;\r
+    /**\r
+     * @author erand\r
+     */\r
+    public abstract class AbstractTransaction : DbTransaction\r
+    {\r
+\r
+        protected String _transactionName;\r
+        protected AbstractDBConnection _connection;\r
+\r
+        protected IsolationLevel _isolationLevel;\r
+\r
+        public AbstractTransaction(\r
+            IsolationLevel isolationLevel,\r
+            AbstractDBConnection connection,\r
+            String transactionName)\r
+        {\r
+                       connection.ValidateBeginTransaction();\r
+            _transactionName = transactionName;\r
+            _connection = connection;\r
+            _isolationLevel = isolationLevel;\r
+            try\r
+            {\r
+                _connection.JdbcConnection.setAutoCommit(false);\r
+                _connection.JdbcConnection.setTransactionIsolation(\r
+                convertIsolationLevel(isolationLevel));\r
+            }\r
+            catch (SQLException exp)\r
+            {\r
+                throw new System.InvalidOperationException(exp.Message);\r
+            }\r
+        }\r
+\r
+        \r
+        /**\r
+         * @see System.Data.IDbTransaction#Connection\r
+         */\r
+        protected override DbConnection DbConnection\r
+        {\r
+            get\r
+            {\r
+                return _connection;\r
+            }\r
+        }\r
+\r
+        /**\r
+         * @see System.Data.IDbTransaction#IsolationLevel\r
+         */\r
+        public override IsolationLevel IsolationLevel\r
+        {\r
+            get\r
+            {\r
+                return _isolationLevel;\r
+            }\r
+        }\r
+\r
+        /**\r
+         * @see System.Data.IDbTransaction#Commit()\r
+         */\r
+        public override void Commit()\r
+        {\r
+                       if (_connection == null)\r
+                               return;\r
+\r
+            try\r
+            {\r
+                _connection.JdbcConnection.commit();\r
+                               _connection.JdbcConnection.setAutoCommit(true);\r
+                               _connection = null;\r
+            }\r
+            catch (SQLException exp)\r
+            {\r
+                throw new SystemException(exp.Message);\r
+            }\r
+        }\r
+\r
+        /**\r
+         * @see System.Data.IDbTransaction#Rollback()\r
+         */\r
+        public override void Rollback()\r
+        {\r
+                       if (_connection == null)\r
+                               return;\r
+\r
+            try\r
+            {\r
+                _connection.JdbcConnection.rollback();\r
+                               _connection = null;\r
+            }\r
+            catch (SQLException exp)\r
+            {\r
+                throw new SystemException(exp.Message);\r
+            }\r
+        }\r
+\r
+        public override void Dispose()\r
+        {\r
+            Rollback();\r
+        }\r
+\r
+               internal AbstractTransaction ActiveTransaction {\r
+                       get {\r
+                               // recoursively return parent transaction when nesting will\r
+                               // be implemented\r
+                               return _connection != null ? this : null;\r
+                       }\r
+               }\r
+\r
+        private int convertIsolationLevel(IsolationLevel isolationLevel)\r
+        {\r
+            if (isolationLevel == IsolationLevel.Unspecified)\r
+                return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_NONE;\r
+            if (isolationLevel == IsolationLevel.ReadCommitted)\r
+                return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_READ_COMMITTED;\r
+            if (isolationLevel == IsolationLevel.ReadUncommitted)\r
+                return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_READ_UNCOMMITTED;\r
+            if (isolationLevel == IsolationLevel.RepeatableRead)\r
+                return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_REPEATABLE_READ;\r
+            if (isolationLevel == IsolationLevel.Serializable)\r
+                return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_SERIALIZABLE;\r
+\r
+            throw new NotSupportedException("The Isolation level '" + isolationLevel + "' is not supported");\r
+        }\r
+    }\r
+}
\ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/DbPortResolver.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/DbPortResolver.cs
new file mode 100644 (file)
index 0000000..d152319
--- /dev/null
@@ -0,0 +1,107 @@
+/*\r
+  * Copyright (c) 2002-2004 Mainsoft Corporation.\r
+  *\r
+  * Permission is hereby granted, free of charge, to any person obtaining a\r
+  * copy of this software and associated documentation files (the "Software"),\r
+  * to deal in the Software without restriction, including without limitation\r
+  * the rights to use, copy, modify, merge, publish, distribute, sublicense,\r
+  * and/or sell copies of the Software, and to permit persons to whom the\r
+  * Software is furnished to do so, subject to the following conditions:\r
+  *\r
+  * The above copyright notice and this permission notice shall be included in\r
+  * all copies or substantial portions of the Software.\r
+  *\r
+  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r
+  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r
+  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r
+  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r
+  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\r
+  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\r
+  * DEALINGS IN THE SOFTWARE.\r
+  */\r
+\r
+using System;\r
+\r
+using java.net;\r
+\r
+namespace System.Data.Common\r
+{\r
+       public class DbPortResolver\r
+       {\r
+               public static int getMSSqlPort(String sqlName, String instanceName,int timeout)\r
+               {\r
+                       int port = -1;\r
+                       try\r
+                       {\r
+                               DatagramSocket socket = new DatagramSocket();\r
+\r
+                               // send request\r
+                               sbyte[] buf = new sbyte[] {2};\r
+                               InetAddress address = InetAddress.getByName(sqlName);\r
+                               DatagramPacket packet = new DatagramPacket(buf, buf.Length, address, 1434);\r
+                               socket.send(packet);\r
+                               sbyte[] recbuf = new sbyte[1024];\r
+                               packet = new DatagramPacket(recbuf, recbuf.Length, packet.getAddress(), packet.getPort());\r
+\r
+                               // try to receive from socket while increasing timeouts in geometric progression\r
+                               int iterationTimeout = 1;\r
+                               int totalTimeout = 0;\r
+                               while (totalTimeout < timeout*1000)\r
+                               {\r
+                                       socket.setSoTimeout(iterationTimeout);\r
+                                       try\r
+                                       {\r
+                                               socket.receive(packet);\r
+                                               break;\r
+                                       }\r
+                                       catch (SocketTimeoutException e)\r
+                                       {\r
+                                               totalTimeout += iterationTimeout;\r
+                                               iterationTimeout *= 2;\r
+                                       }\r
+                               }\r
+                               sbyte[] rcvdSbytes = packet.getData();\r
+                               char[] rcvdChars = new char[rcvdSbytes.Length];\r
+                               for(int i=0; i < rcvdSbytes.Length; i++)\r
+                               {\r
+                                       rcvdChars[i] = (char)rcvdSbytes[i];\r
+                               }\r
+                               String received = new String(rcvdChars);\r
+\r
+                               java.util.StringTokenizer st = new java.util.StringTokenizer(received, ";");\r
+                               String prev = "";\r
+                               bool instanceReached = false;\r
+                               while (st.hasMoreTokens())\r
+                               {\r
+                                       if (!instanceReached)\r
+                                       {\r
+                                               if (prev.Trim().Equals("InstanceName"))\r
+                                               {\r
+                                                       if (String.Compare(instanceName,st.nextToken().Trim(),true) == 0)\r
+                                                       {\r
+                                                               instanceReached = true;\r
+                                                       }\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if (prev.Trim().Equals("tcp"))\r
+                                               {\r
+                                                       port = java.lang.Integer.parseInt(st.nextToken().Trim());\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       prev = st.nextToken();\r
+                               }\r
+                               socket.close();\r
+                               return port;\r
+\r
+                       }\r
+                       catch (java.lang.Exception e)\r
+                       {\r
+                               return port;\r
+                       }\r
+               }\r
+           \r
+       }\r
+}\r
diff --git a/mcs/class/System.Data/System.Data.ProviderBase.jvm/ReaderCache.cs b/mcs/class/System.Data/System.Data.ProviderBase.jvm/ReaderCache.cs
new file mode 100644 (file)
index 0000000..13a7b96
--- /dev/null
@@ -0,0 +1,659 @@
+using System;\r
+using java.sql;\r
+\r
+namespace System.Data.Common\r
+{\r
+       public interface IReaderCacheContainer\r
+       {\r
+               void Fetch(ResultSet rs, int columnIndex);\r
+               bool IsNull();\r
+               object GetValue();\r
+       }\r
+\r
+       internal abstract class ReaderCacheContainerBase : IReaderCacheContainer\r
+       {\r
+               #region Fields\r
+\r
+               bool _isNull;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected abstract void FetchInternal(ResultSet rs, int columnIndex);\r
+\r
+               public abstract object GetValue();              \r
+\r
+               public void Fetch(ResultSet rs, int columnIndex)\r
+               {\r
+                       FetchInternal(rs, columnIndex + 1);\r
+                       _isNull = rs.wasNull();\r
+               }\r
+\r
+               public bool IsNull()\r
+               {\r
+                       return _isNull;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class ArrayReaderCacheContainer : ReaderCacheContainerBase // Types.ARRAY\r
+       {\r
+               #region Fields\r
+\r
+               java.sql.Array _a;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _a = rs.getArray(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _a;\r
+               }\r
+\r
+               internal java.sql.Array GetArray()\r
+               {\r
+                       return _a;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class Int64ReaderCacheContainer : ReaderCacheContainerBase // Types.BIGINT\r
+       {\r
+               #region Fields\r
+               \r
+               long _l;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _l = rs.getLong(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _l;\r
+               }\r
+\r
+               internal long GetInt64()\r
+               {\r
+                       return _l;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal class BytesReaderCacheContainer : ReaderCacheContainerBase // Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY\r
+       {\r
+               #region Fields\r
+\r
+               protected byte[] _b;\r
+               \r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       sbyte[] sbyteArray = rs.getBytes(columnIndex);\r
+                       if (sbyteArray != null) {\r
+                               _b = (byte[])vmw.common.TypeUtils.ToByteArray(sbyteArray);\r
+                       }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               internal byte[] GetBytes()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class BooleanReaderCacheContainer : ReaderCacheContainerBase // Types.BIT\r
+       {\r
+               #region Fields\r
+               \r
+               bool _b;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _b = rs.getBoolean(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               internal bool GetBoolean()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class BlobReaderCacheContainer : BytesReaderCacheContainer // Types.BLOB\r
+       {\r
+               #region Fields\r
+\r
+               static readonly byte[] _emptyByteArr = new byte[0];\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       java.sql.Blob blob = rs.getBlob(columnIndex);\r
+                       if (blob != null) {\r
+                               long length = blob.length();                                                            \r
+                               if (length == 0) {\r
+                                       _b = _emptyByteArr;\r
+                               }\r
+                               else {  \r
+                                       java.io.InputStream input = blob.getBinaryStream();     \r
+                                       byte[] byteValue = new byte[length];\r
+                                       sbyte[] sbyteValue = vmw.common.TypeUtils.ToSByteArray(byteValue);\r
+                                       input.read(sbyteValue);\r
+                                       _b = byteValue;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+       \r
+\r
+       internal abstract class CharsReaderCacheContainer : ReaderCacheContainerBase // \r
+       {\r
+               #region Fields\r
+               \r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               internal abstract char[] GetChars();\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class GuidReaderCacheContainer : ReaderCacheContainerBase // Types.CHAR\r
+       {\r
+               #region Fields\r
+               \r
+               Guid _g;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _g = new Guid(rs.getString(columnIndex));\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _g;\r
+               }\r
+\r
+               internal Guid GetGuid()\r
+               {\r
+                       return _g;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class ClobReaderCacheContainer : StringReaderCacheContainer // Types.CLOB\r
+       {\r
+               #region Fields\r
+               \r
+               char[] _c;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               // FIXME : conside adding stream wrapper interface\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       java.sql.Clob clob = rs.getClob(columnIndex);                   \r
+                       if (clob != null) {\r
+                               long length = clob.length();                                                            \r
+                               if (length == 0) {\r
+                                       _s = String.Empty;\r
+                                       _c = String.Empty.ToCharArray();\r
+                               }\r
+                               else {  \r
+                                       java.io.Reader reader = clob.getCharacterStream();      \r
+                                       char[] charValue = new char[length];\r
+                                       reader.read(charValue);\r
+                                       _c = charValue;\r
+                                       \r
+                               }\r
+                       }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       if (_s == null && _c != null) {\r
+                               _s = (_c.Length != 0) ? new String(_c) : String.Empty;\r
+                       }\r
+                       return _s;\r
+               }\r
+\r
+               internal override char[] GetChars()\r
+               {\r
+                       return _c;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+       \r
+\r
+       internal sealed class TimeSpanReaderCacheContainer : ReaderCacheContainerBase // Types.TIME\r
+       {\r
+               #region Fields\r
+               \r
+               TimeSpan _t;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       Time t = rs.getTime(columnIndex);\r
+                       if (t != null) {                                \r
+                               _t = new TimeSpan(DbConvert.JavaTimeToClrTicks(t));\r
+                       }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _t;\r
+               }\r
+\r
+               internal TimeSpan GetTimeSpan()\r
+               {\r
+                       return _t;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal class DateTimeReaderCacheContainer : ReaderCacheContainerBase // Types.TIMESTAMP\r
+       {\r
+               #region Fields\r
+               \r
+               protected DateTime _d;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       Date d = rs.getDate(columnIndex);\r
+                       if (d != null) {\r
+                               _d = new DateTime(DbConvert.JavaDateToClrTicks(d));\r
+                       }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _d;\r
+               }\r
+\r
+               internal DateTime GetDateTime()\r
+               {\r
+                       return _d;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+       internal sealed class TimestampReaderCacheContainer : DateTimeReaderCacheContainer // Types.DATE\r
+       {\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex) {\r
+                       Timestamp ts = rs.getTimestamp(columnIndex);\r
+                       if (ts != null) {\r
+                               _d = new DateTime(DbConvert.JavaTimestampToClrTicks(ts));\r
+                       }\r
+               }\r
+       }\r
+\r
+\r
+       internal sealed class DecimalReaderCacheContainer : ReaderCacheContainerBase // Types.DECIMAL, Types.NUMERIC\r
+       {\r
+               #region Fields\r
+               \r
+               decimal _d;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       java.math.BigDecimal bigDecimal = rs.getBigDecimal(columnIndex);\r
+                       if (bigDecimal != null) {\r
+                               _d = (decimal)vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bigDecimal);\r
+                       }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _d;\r
+               }\r
+\r
+               internal decimal GetDecimal()\r
+               {\r
+                       return _d;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class DoubleReaderCacheContainer : ReaderCacheContainerBase // Types.DOUBLE, Types.Float, Types.NUMERIC for Oracle with scale = -127\r
+       {\r
+               #region Fields\r
+               \r
+               double _d;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _d = rs.getDouble(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _d;\r
+               }\r
+\r
+               internal double GetDouble()\r
+               {\r
+                       return _d;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class Int32ReaderCacheContainer : ReaderCacheContainerBase // Types.INTEGER\r
+       {\r
+               #region Fields\r
+               \r
+               int _i;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _i = rs.getInt(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _i;\r
+               }\r
+\r
+               internal int GetInt32()\r
+               {\r
+                       return _i;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal class StringReaderCacheContainer : CharsReaderCacheContainer // Types.LONGVARCHAR, Types.VARCHAR, Types.CHAR\r
+       {\r
+               #region Fields\r
+               \r
+               protected string _s;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _s = rs.getString(columnIndex);\r
+                       // Oracle Jdbc driver returns extra trailing 0 chars for NCHAR columns\r
+//                     if ((_s != null) && (_jdbcType == 1)) { \r
+//                             Console.WriteLine(_jdbcType);\r
+//                             int zeroIndex = ((string)_s).IndexOf((char)0);\r
+//                             if (zeroIndex > 0) {\r
+//                                     Console.WriteLine("zero-padded");\r
+//                                     _s = ((string)_s).Substring(0,zeroIndex);\r
+//                             }\r
+//                             else {\r
+//                                     // Oracle sometimes pads with blanks (32)\r
+//                                     int blankIndex = ((string)_s).IndexOf((char)32);\r
+//                                     if (blankIndex > 0) {\r
+//                                             Console.WriteLine("blank-padded");\r
+//                                             _s = ((string)_s).Substring(0,blankIndex);\r
+//                                     }\r
+//                             }\r
+//                     }\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _s;\r
+               }\r
+\r
+               internal string GetString()\r
+               {\r
+                       return _s;\r
+               }\r
+\r
+               internal override char[] GetChars()\r
+               {\r
+                       return _s.ToCharArray();\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class NullReaderCacheContainer : ReaderCacheContainerBase // Types.NULL\r
+       {\r
+               #region Fields\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return DBNull.Value;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class FloatReaderCacheContainer : ReaderCacheContainerBase // Types.REAL\r
+       {\r
+               #region Fields\r
+               \r
+               float _f;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _f = rs.getFloat(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _f;\r
+               }\r
+\r
+               internal float GetFloat()\r
+               {\r
+                       return _f;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class RefReaderCacheContainer : ReaderCacheContainerBase // Types.REF\r
+       {\r
+               #region Fields\r
+               \r
+               java.sql.Ref _r;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _r = rs.getRef(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _r;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class Int16ReaderCacheContainer : ReaderCacheContainerBase // Types.SMALLINT\r
+       {\r
+               #region Fields\r
+               \r
+               short _s;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _s = rs.getShort(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _s;\r
+               }\r
+\r
+               internal short GetInt16()\r
+               {\r
+                       return _s;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class ByteReaderCacheContainer : ReaderCacheContainerBase // Types.TINYINT\r
+       {\r
+               #region Fields\r
+               \r
+               byte _b;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       _b = (byte)rs.getByte(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               internal byte GetByte()\r
+               {\r
+                       return _b;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+\r
+       internal sealed class ObjectReaderCacheContainer : ReaderCacheContainerBase // Types.Distinct, Types.JAVA_OBJECT, Types.OTHER, Types.STRUCT\r
+       {\r
+               #region Fields\r
+               \r
+               object o;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Methods\r
+\r
+               protected override  void FetchInternal(ResultSet rs, int columnIndex)\r
+               {\r
+                       o = rs.getObject(columnIndex);\r
+               }\r
+\r
+               public override object GetValue()\r
+               {\r
+                       return o;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+\r
+}\r
diff --git a/mcs/class/System.Data/System.Data.ProviderBase/DbStringManager.cs b/mcs/class/System.Data/System.Data.ProviderBase/DbStringManager.cs
new file mode 100644 (file)
index 0000000..efc2cce
--- /dev/null
@@ -0,0 +1,56 @@
+using java.util;\r
+\r
+namespace System.Data.Common\r
+{\r
+       public class DbStringManager\r
+       {\r
+               public DbStringManager(string bundleName)\r
+               {\r
+                       _bundleName = bundleName;\r
+                       _resourceBundle = ResourceBundle.getBundle(_bundleName);\r
+               }\r
+\r
+        private readonly string _bundleName;\r
+\r
+        private readonly ResourceBundle _resourceBundle;\r
+\r
+        public string GetString(string key)\r
+        {\r
+            try {\r
+                return _resourceBundle.getString(key);\r
+            }\r
+            catch (MissingResourceException) {\r
+                return null;\r
+            }\r
+        }\r
+       \r
+        public string GetString(string key, string defaultValue)\r
+        {\r
+            try {\r
+                return _resourceBundle.getString(key);\r
+            }\r
+            catch (MissingResourceException) {\r
+                return defaultValue;\r
+            }\r
+        }\r
+       \r
+       \r
+        public string[] GetStringArray(String key)\r
+        {\r
+            try {\r
+                string tmp = _resourceBundle.getString(key);\r
+                java.util.StringTokenizer st = new java.util.StringTokenizer(tmp, ",");\r
+                       \r
+                String[] strArr = new String[st.countTokens()];\r
+                       \r
+                for (int i = 0; i < strArr.Length; i++) {\r
+                    strArr[i] = st.nextToken();\r
+                }                              \r
+                return strArr;                 \r
+            }\r
+            catch (MissingResourceException) {\r
+                return null;\r
+            }\r
+        }\r
+    }\r
+}\r
index d33ea4809c49e9a96ca89a0511f7fa63dda517b5..7fc6a139d0f6bf8295cbb62617191483dd0236c6 100755 (executable)
@@ -21,9 +21,11 @@ System.Data/DataColumnChangeEventHandler.cs
 System.Data/DataColumnCollection.cs
 System.Data/DataColumnPropertyDescriptor.cs
 System.Data/DataException.cs
+System.Data/RelatedDataView.cs
 System.Data/RelationshipConverter.cs
 System.Data/DataRelation.cs
 System.Data/DataRelationCollection.cs
+System.Data/DataRelationPropertyDescriptor.cs
 System.Data/DataRow.cs
 System.Data/DataRowAction.cs
 System.Data/DataRowBuilder.cs
@@ -79,11 +81,11 @@ System.Data/IDbDataParameter.cs
 System.Data/IDbExecutionContext.cs
 System.Data/IDbTransaction.cs
 System.Data/IGetTypedData.cs
-System.Data/Index.cs
 System.Data/InRowChangingEventException.cs
 System.Data/InternalDataCollectionBase.cs
 System.Data/InvalidConstraintException.cs
 System.Data/InvalidExpressionException.cs
+System.Data/ISafeDataRecord.cs
 System.Data/ISetTypedData.cs
 System.Data/IsolationLevel.cs
 System.Data/ITableMapping.cs
@@ -168,9 +170,12 @@ System.Data.Common/DbProviderFactory.cs
 System.Data.Common/DbProviderSupportedClasses.cs
 System.Data.Common/DbTable.cs
 System.Data.Common/DbTransaction.cs
+System.Data.Common/DbTypes.cs
 System.Data.Common/FieldNameLookup.cs
 System.Data.Common/GroupByBehavior.cs
 System.Data.Common/IdentifierCase.cs
+System.Data.Common/Index.cs
+System.Data.Common/Key.cs
 System.Data.Common/PermissionHelper.cs
 System.Data.Common/RecordCache.cs
 System.Data.Common/RowUpdatedEventArgs.cs
index afa2b436f52ccae774d525481b4ecf511403698e..c33ad28a586d8e0ebbd548bcbd19af8f361c132c 100644 (file)
@@ -40,9 +40,9 @@ namespace System.Data
        /// </summary>
        [Serializable]
        public enum AcceptRejectRule
-       {
-               Cascade = 1,
-               None = 0
+       {               
+               None = 0,
+               Cascade = 1
        }
 
 }
index f1de05208c28cfe93c3901da5192c2ab732fdd61..10178e5bd2c7ec02b9b51505b213a3e087998128 100644 (file)
        * DataRowAction.cs: Added few more enums for .net 2.0. Sorted
        alphabetically.
 
+2005-05-16 Konstantin Triger <kostat@mainsoft.com>
+
+       * UniqueConstraint.cs : IsNull check is relevant for rows having default row version.
+       * DataTable.cs : The row should be validated when imported
+       * DataRowCollection.cs : if the row does not contain Proposed neither Current version, it's irrelevant for validation
+
+2005-04-26 Boris Kirzner <borisk@mainsoft.com>
+
+       * UniqueConstraint.cs :
+               - Add indication whenever the constraint belongs to collection. 
+               - Calculation of IsPrimaryKey simplified.
+               - If constraint is based on single column, the column becomes unique.
+               - Use boolean IsConstraintViolated() instead of AssertConstraint().
+               - Use Index.Duplicates to proper exception message formatting.
+               - AssertConstraint(DataRow) changed to suite new indexes interface.
+               - Added CanRemoveFromCollection method.
+               - Contains() method renamed to IsColumnContained().
+       * RelatedDataView.cs : added new class.
+       * MergeManager.cs :
+               - Reset indexes after merge.
+               - Add new tables when row array is merged into dataset.
+               - Clean proposed record in MergeRow.
+               - Inherit nesting on creating new relations in target data set.
+               - Avoid double loop on constraints collection.
+       * Locale.cs : added new class.
+       * ISafeDataRecord.cs : added new interface.
+       * Index.cs : commented out. Index implementation moved to System.Data.Common.
+       * ForeignKeyConstraint.cs : 
+               - No more use of childColumnsExtended since new indexes allow duplicate records.
+               - Constraints can not be created on expression columns.
+               - Removed unnecessary delegation.
+               - Use boolean IsConstraintViolated() instead of AssertConstraint(). 
+               - Use proper exception message formatting.
+               - Contains() method renamed to IsColumnContained().
+       * DataViewRowState.cs : use enum members to simplify notation.
+       * MergeManager.cs : implemented RelationCollectionChanged().
+       * DataView.cs :  new implementation.
+       * DataTableCollection.cs : 
+               - Added boundary check in indexer.
+               - More accurate handling in AddRange().
+               - Raise event in Remove().
+       * DataTable.cs :
+               - Hold primary key as constraint.
+               - Added accurate handling of DefaultView.
+               - Hold DataRowBuilder per table.
+               - Proper exception messages if enforce Constraints is violated.
+               - If there is no rows, Compute() returns DBNull.
+               - Use DataRow properties instead of private members.
+               - CopyProperties() fixed.
+               - Raise proper events in EndInit().
+               - Proper order of violation checks in EndLoadData().
+               - Create array of rows using NewRowArray().
+               - ImportRow handles rows according to their versions.
+               - LoadDataRow make use of records (instead of raw object array).
+               - Added and implemented LoadDataRow() that gets IDataRecord as a parameter (used in Fill)
+               - Select() uses indexes filtering and sorting ability (instead of "loop-throw-sort" approach).
+               - Removed redundant RowSorter and Sortable column classes.
+               - ParseSortString() fixed to threat bracketed column names.
+               - Table holds collection of property descriptors.
+       * DataSet.cs :
+               - Reset table case sensitive indexes on CaseSensitive change.
+               - EnforceConstraints update logic moved to internal method (used by DataTable).
+               - InAddChangedRow first add row and than copy values for proper handling of default values.
+       * DataRowView.cs :
+               - Changed private member names to suite name convention.
+               - CancelEdit() fixed.
+               - CreateChildView() delegates to DataView.
+               - IsNew fixed.
+               - Proper exception messages in indexers.
+               - RowVersion uses DataView.
+               - GetProperties() delegates to corresponding table if needed.
+       * DataRowCollection.cs :
+               - Common Add() logic moved to AddInternal() (used also by DataTable).
+               - Removed redundant check from Contains().
+               - Dalegate Find() calls when possible.
+               - Remove() fixed.
+               - RomoveAt() delegates to Remove().
+               - Optimized constraints check in row validation.
+       * DataRelationPropertyDescriptor.cs : added new class.
+       * DataRelationCollection.cs :
+               - Indexers fixed.
+               - Fixed order of actions in AddCore().
+               - RemoveCore() also delegates to base.
+               - Add relation to dataset also in AddCore().
+               - Remove relation from dataset also in RemoveCore().
+               - InTransition hold a data relation so we can properly identify the "in transition" state.
+               - Added threat of parent and child table s property descriptors in Add().
+               - Common Add() logic moved to AddCore().
+               - Clear() fixed.
+               - Remove() threats "in transition" state properly.
+               - Remove methods delegate to single implementation.
+       * DataColumnPropertyDescriptior.cs :
+               - Added new constructor.
+               - Commented out redundant method.
+       * DataColumnCollection.cs :
+               - Boundary check in indexer.
+               - RegisterName and UnregisterName become internal (used also by DataColumn).
+               - Fixed AddRange().
+               - Fixed CanRemove().
+               - Rethrow correct exception in Clear();
+               - Change in collection resets parent table property descriptors.
+               - Added PostEndEdit() helper method (used by DataTable).
+       * DataColumn.cs :
+               - Private member names changed to suite name convention.
+               - Created method for CanAutoIncrement() logic.
+               - Proper handling of column name update.
+               - Proper exception messages on expression update.
+               - Proper namespace handling (delegates to table when needed).
+               - Removed redundant check in Unique update.
+               - Implemented internal Clone().
+               - GetParentRalation() and GetChildRelation() become private.
+       * Constraint.cs :
+               - Added abstract methods (implemented in UniqueConstraint and ForeignKeyConstraint).
+               - Simplified index update.
+       * ConstraintCollection.cs :
+               - Use Locale instead of CaseSensitive in column names comparison.
+               - Removed #ifdef
+               - Rethrow correct exception type in Add().
+               - Proper update of table primary key in Add().
+               - Delegate CanRemove() to constraint.
+               - Remove table primary key in Clear();
+               - Delegate "can remove" check to constraint in Remove().
+               - Removed unnecessary methods and properties.
+       * DataRow.cs :
+               - RowSate becomes calculated property.
+               - Use properties instead of private members where possible.
+               - Fixed indexer.
+               - Fixed order of actions in ItemArray update.
+               - Fixed DetachRow().
+               - Added ImportRecord() method.
+               - Removed redundant SetValuesFromDataRecord().
+               - Fixed IndexFromVersion().
+               - Added VersionFromIndex() method. Returns row version the passed record index corresponds to.
+               - Fixed AcceptChanges().
+               - Fixed creating proposed version in BeginEdit();
+               - Added record disposal in Delete().
+               - Fixed CheckChildRows().
+               - EndEdit() fixed. Checks for readonly. Uses straight flow instead of "try and fix if fail" approach.
+               - GetChildRows() and GetPrarentRows() rewrited. Use records and indexes for rows lookup.
+               - GetColumnError() delegates to another implementation.
+               - HasVersion() fixed.
+               - RejectCahnges checks on child rows before passing through.
+               - SetParentRow() fixed. Create relation collection if needed. Use typed data container value copy.
+               - CopyErrors() logic moved to separate method (used also by DataTable).
+       * ExpressionElement.cs : added new class.
+       * Res.cs : added new class.
+
 2005-04-20  Jordi Mas i Hernandez <jordi@ximian.com>
 
        * DataViewManager.cs: implements TypedList.GetListName used in SWF
index 93cfbce35c8c1f5101c521e6750899164dec225b..2b09cacd4b8742d3dbd205acfb7ea3172ae5abe9 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+
 
 namespace System.Data {
        public enum ConflictOptions 
@@ -52,4 +52,4 @@ namespace System.Data {
        }
 }
 
-#endif // NET_2_0
+
index d6a983a1072771564b4faf59273089ea9b847f04..0cb69c7fada68a8f1efd9cc5e1fde3cabbc0145a 100644 (file)
@@ -39,6 +39,7 @@ using System.Collections;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
 using System.Runtime.Serialization;
+using System.Data.Common;
 
 namespace System.Data {
        [Serializable]
@@ -119,27 +120,28 @@ namespace System.Data {
 
                //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 virtual void AssertConstraint ()
-               {
-               }
+               protected abstract bool IsConstraintViolated ();
                
-               internal virtual void AssertConstraint (DataRow row)
-               {
+               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.");
                }
 
+               internal void AssertConstraint() {
+                       if (IsConstraintViolated())
+                               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 ()
@@ -158,54 +160,21 @@ namespace System.Data {
                                return _index;
                        }
                        set {
+                               if (_index != null) {
+                                       _index.RemoveRef();
+                                       Table.DropIndex(_index);
+                               }
+
                                _index = value;
-                       }
-               }
 
-               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 (_index != null) {
+                                       _index.AddRef();
                                }
-                               // 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 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);
                        }
                }
 
+               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. 
index 68ea2302a2034079c5b93d4e26caf04796d9b404..8450de856177c6cdbb18d11ced3c60348e8b3393 100644 (file)
@@ -53,7 +53,6 @@ namespace System.Data {
                //private bool beginInit = false;
                
                public event CollectionChangeEventHandler CollectionChanged;
-               internal event DelegateValidateRemoveConstraint ValidateRemoveConstraint;
                private DataTable table;
                
                // Call this to set the "table" property of the UniqueConstraint class
@@ -108,7 +107,7 @@ namespace System.Data {
                private bool _isDuplicateConstraintName(string constraintName, Constraint excludeFromComparison) 
                {
                        foreach (Constraint cst in List) {
-                               if (String.Compare (constraintName, cst.ConstraintName, !Table.CaseSensitive) == 0  && cst != excludeFromComparison) 
+                               if (String.Compare (constraintName, cst.ConstraintName, false, Table.Locale) == 0  && cst != excludeFromComparison) 
                                        return true;
                        }
 
@@ -162,37 +161,32 @@ namespace System.Data {
                                throw new ArgumentException("Constraint already belongs to another collection.");
                        
                        //check for duplicate name
-#if !NET_1_1
                        if (_isDuplicateConstraintName(constraint.ConstraintName,null)  )
                                throw new DuplicateNameException("Constraint name already exists.");
-#endif
        
                        // Check whether Constraint is UniqueConstraint and initailized with the special
-                        // constructor - UniqueConstraint( string, string[], bool );
-                        // If yes, It must be added via AddRange() only
-                        // Environment.StackTrace can help us 
+            // constructor - UniqueConstraint( string, string[], bool );
+            // If yes, It must be added via AddRange() only
+            // Environment.StackTrace can help us 
                        // FIXME: Is a different mechanism to do this?
-                        if (constraint is UniqueConstraint){
-                                if ((constraint as UniqueConstraint).DataColsNotValidated == true){
-                                        if ( Environment.StackTrace.IndexOf( "AddRange" ) == -1 ){
-                                                throw new ArgumentException(" Some DataColumns are invalid - They may not belong to the table associated with this Constraint Collection" );
-                                        }
-                                }
-                        }
+            if (constraint is UniqueConstraint){
+                if ((constraint as UniqueConstraint).DataColsNotValidated == true){
+                    if ( Environment.StackTrace.IndexOf( "AddRange" ) == -1 ){
+                        throw new ArgumentException(" Some DataColumns are invalid - They may not belong to the table associated with this Constraint Collection" );
+                    }
+                }
+            }
 
-                         if (constraint is ForeignKeyConstraint){
-                                if ((constraint as ForeignKeyConstraint).DataColsNotValidated == true){
-                                        if ( Environment.StackTrace.IndexOf( "AddRange" ) == -1 ){
-                                                throw new ArgumentException(" Some DataColumns are invalid - They may not belong to the table associated with this Constraint Collection" );
-                                        }
-                                }
-                        }
-                       try {
-                               //Allow constraint to run validation rules and setup 
-                               constraint.AddToConstraintCollectionSetup(this); //may throw if it can't setup
-                       } catch (ConstraintException ex) {
-                               throw new ArgumentException (ex.Message, ex);
-                       }
+                       if (constraint is ForeignKeyConstraint){
+                if ((constraint as ForeignKeyConstraint).DataColsNotValidated == true){
+                    if ( Environment.StackTrace.IndexOf( "AddRange" ) == -1 ){
+                        throw new ArgumentException(" Some DataColumns are invalid - They may not belong to the table associated with this Constraint Collection" );
+                    }
+                }
+            }
+
+                       //Allow constraint to run validation rules and setup 
+                       constraint.AddToConstraintCollectionSetup(this); //may throw if it can't setup                  
 
                        //Run Constraint to check existing data in table
                        // this is redundant, since AddToConstraintCollectionSetup 
@@ -213,14 +207,13 @@ namespace System.Data {
                        constraint.ConstraintCollection = this;
                        List.Add(constraint);
 
-                       if (constraint is UniqueConstraint) 
-                               ((UniqueConstraint)constraint).UpdatePrimaryKey();
+                       if (constraint is UniqueConstraint && ((UniqueConstraint)constraint).IsPrimaryKey) { 
+                               table.PrimaryKey = ((UniqueConstraint)constraint).Columns;
+                       }
 
                        OnCollectionChanged( new CollectionChangeEventArgs( CollectionChangeAction.Add, this) );
                }
 
-       
-
                public virtual Constraint Add(string name, DataColumn column, bool primaryKey) 
                {
 
@@ -261,78 +254,61 @@ namespace System.Data {
                public void AddRange(Constraint[] constraints) {
 
                        //When AddRange() occurs after BeginInit,
-                        //it does not add any elements to the collection until EndInit is called.
+            //it does not add any elements to the collection until EndInit is called.
                        if (this.table.fInitInProgress) {
                                // Keep reference so that they can be added when EndInit() is called.
-                                _mostRecentConstraints = constraints;
-                                return;
-                        }
-
-                        if ( (constraints == null) || (constraints.Length == 0))
-                                return;
-
-                        // Check whether the constraint is UniqueConstraint
-                        // And whether it was initialized with the special ctor
-                        // i.e UniqueConstraint( string, string[], bool );
-                        for (int i = 0; i < constraints.Length; i++){
-                                if (constraints[i] is UniqueConstraint){
-                                        if (( constraints[i] as UniqueConstraint).DataColsNotValidated == true){
-                                                PostAddRange _postAddRange= new PostAddRange ((constraints[i] as UniqueConstraint).PostAddRange);
-                                                // UniqueConstraint.PostAddRange() validates whether all named
-                                                // columns exist in the table associated with this instance of
-                                                // ConstraintCollection.
-                                                _postAddRange (this.table);
-                                                                                                    
-                                        }
-                                }
+                    _mostRecentConstraints = constraints;
+                    return;
+            }
+
+                       if ( (constraints == null) || (constraints.Length == 0))
+                                       return;
+
+            // Check whether the constraint is UniqueConstraint
+            // And whether it was initialized with the special ctor
+            // i.e UniqueConstraint( string, string[], bool );
+            for (int i = 0; i < constraints.Length; i++){
+                if (constraints[i] is UniqueConstraint){
+                    if (( constraints[i] as UniqueConstraint).DataColsNotValidated == true){
+                            PostAddRange _postAddRange= new PostAddRange ((constraints[i] as UniqueConstraint).PostAddRange);
+                            // UniqueConstraint.PostAddRange() validates whether all named
+                            // columns exist in the table associated with this instance of
+                            // ConstraintCollection.
+                            _postAddRange (this.table);                                                                                    
+                    }
+                }
                                else if (constraints [i] is ForeignKeyConstraint){
-                                        if (( constraints [i] as ForeignKeyConstraint).DataColsNotValidated == true){
-                                                (constraints [i] as ForeignKeyConstraint).postAddRange (this.table);
-                                        }
-                                }
-       
+                        if (( constraints [i] as ForeignKeyConstraint).DataColsNotValidated == true){
+                            (constraints [i] as ForeignKeyConstraint).postAddRange (this.table);
                         }
-                                                                                                    
+                                       }
+                }
                         
-                        foreach (Constraint constraint in constraints)
-                                Add (constraint);
+                foreach (Constraint constraint in constraints)
+                        Add (constraint);
 
                }
 
                // Helper AddRange() - Call this function when EndInit is called
-                internal void PostEndInit()
-                {
-                        AddRange (_mostRecentConstraints);
-                }
+        internal void PostEndInit()
+        {
+                       Constraint[] constraints = _mostRecentConstraints;
+                       _mostRecentConstraints = null;
+                       AddRange (constraints);
+        }
 
 
                public bool CanRemove(Constraint constraint) 
                {
-
-                       //Rule A UniqueConstraint can't be removed if there is
-                       //a foreign key relationship to that column
-
-                       //not null 
-                       //LAMESPEC: MSFT implementation throws and exception here
-                       //spec says nothing about this
-                       if (null == constraint) throw new ArgumentNullException("Constraint can't be null.");
-                       
-                       //LAMESPEC: spec says return false (which makes sense) and throw exception for False case (?).
-                       //TODO: I may want to change how this is done
-                       //maybe put a CanRemove on the Constraint class
-                       //and have the Constraint fire this event
-
-                       //discover if there is a related ForeignKey
-                       string failReason ="";
-                       return _canRemoveConstraint(constraint, ref failReason);
-                       
+                       return constraint.CanRemoveFromCollection(this, false);
                }
 
                public void Clear() 
-               {
+               {       
+                       // Clear should also remove PrimaryKey
+                       Table.PrimaryKey = null;
                        
                        //CanRemove? See Lamespec below.
-
                        //the Constraints have a reference to us
                        //and we listen to name change events 
                        //we should remove these before clearing
@@ -393,14 +369,8 @@ namespace System.Data {
                        //not null
                        if (null == constraint) throw new ArgumentNullException();
 
-                       string failReason = "";
-                       if (! _canRemoveConstraint(constraint, ref failReason) )
-                       {
-                               if (failReason != null || failReason != "")     
-                                       throw new ArgumentException(failReason);
-                               else
-                                       throw new ArgumentException("Can't remove constraint.");                
-                       }
+                       if (!constraint.CanRemoveFromCollection(this, true))
+                               return;
                                
                        constraint.RemoveFromConstraintCollectionCleanup(this);
                        List.Remove(constraint);
@@ -434,45 +404,5 @@ namespace System.Data {
                                CollectionChanged(this, ccevent);
                        }
                }
-
-               private bool _canRemoveConstraint(Constraint constraint, ref string failReason )
-               {
-                       bool cancel = false;
-                       string tmp = "";
-                       if (null != ValidateRemoveConstraint)
-                       {
-                               ValidateRemoveConstraint(this, constraint, ref cancel, ref tmp);
-                       }
-                       failReason = tmp;
-                       return !cancel;
-               }
-
-               internal ICollection UniqueConstraints
-               {
-                       get
-                       { 
-                               return GetConstraintsCollection(typeof(UniqueConstraint));
-                       }
-               }
-
-               internal ICollection ForeignKeyConstraints
-               {
-                       get
-                       { 
-                               return GetConstraintsCollection(typeof(ForeignKeyConstraint));
-                       }
-               }
-
-               private ICollection GetConstraintsCollection (Type constraintType)
-               {
-                       ArrayList cCollection = new ArrayList();
-                       foreach (Constraint c in List) 
-                       {
-                               if (c.GetType() == constraintType)
-                                       cCollection.Add(c);
-                       }
-                       return cCollection;
-               }
-
        }
 }
index 29b8f305f07ab7578c198b9dceb4823ad7764997..afac3af74f378588d915bd253a3896595a841c00 100644 (file)
-//
-// System.Data.DataColumn.cs
-//
-// Author:
-//   Franklin Wise (gracenote@earthlink.net)
-//   Christopher Podurgiel (cpodurgiel@msn.com)
-//   Rodrigo Moya (rodrigo@ximian.com)
-//   Daniel Morgan (danmorg@sc.rr.com)
-//   Tim Coleman (tim@timcoleman.com)
-//
-// (C) Copyright 2002, Franklin Wise
-// (C) Chris Podurgiel
-// (C) Ximian, Inc 2002
-// Copyright (C) Tim Coleman, 2002
-// Copyright (C) Daniel Morgan, 2002, 2003
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.ComponentModel;
-using System.Reflection;
-using System.Collections;
-using System.Data.Common;
-using Mono.Data.SqlExpressions;
-
-namespace System.Data {
-       internal delegate void DelegateColumnValueChange(DataColumn column, DataRow row, object proposedValue);
-       
-       /// <summary>
-       /// Summary description for DataColumn.
-       /// </summary>
-
-       [Editor]
-       [ToolboxItem (false)]
-       [DefaultProperty ("ColumnName")]
-       [DesignTimeVisible (false)]
-       public class DataColumn : MarshalByValueComponent
-       {               
-               #region Events
-               [MonoTODO]
-               //used for constraint validation
-               //if an exception is fired during this event the change should be canceled
-               internal event DelegateColumnValueChange ValidateColumnValueChange;
-
-               //used for FK Constraint Cascading rules
-               internal event DelegateColumnValueChange ColumnValueChanging;
-               #endregion //Events
-               
-               #region Fields
-
-               private bool _allowDBNull = true;
-               private bool _autoIncrement;
-               private long _autoIncrementSeed;
-               private long _autoIncrementStep = 1;
-               private long _nextAutoIncrementValue;
-               private string _caption;
-               private MappingType _columnMapping;
-               private string _columnName;
-               private object _defaultValue = DBNull.Value;
-               private string expression;
-               private IExpression compiledExpression;
-               private PropertyCollection _extendedProperties = new PropertyCollection ();
-               private int maxLength = -1; //-1 represents no length limit
-               private string nameSpace = String.Empty;
-               private int _ordinal = -1; //-1 represents not part of a collection
-               private string prefix = String.Empty;
-               private bool readOnly;
-               private DataTable _table;
-               private bool unique;
-               private AbstractDataContainer _dataContainer;
-
-               #endregion // Fields
-
-               #region Constructors
-
-               public DataColumn() : this(String.Empty, typeof (string), String.Empty, MappingType.Element)
-               {
-               }
-
-               //TODO: Ctor init vars directly
-               public DataColumn(string columnName): this(columnName, typeof (string), String.Empty, MappingType.Element)
-               {
-               }
-
-               public DataColumn(string columnName, Type dataType): this(columnName, dataType, String.Empty, MappingType.Element)
-               {
-               }
-
-               public DataColumn( string columnName, Type dataType, 
-                       string expr): this(columnName, dataType, expr, MappingType.Element)
-               {
-               }
-
-               public DataColumn(string columnName, Type dataType, 
-                       string expr, MappingType type)
-               {
-                       ColumnName = (columnName == null ? String.Empty : columnName);
-                       
-                       if(dataType == null) {
-                               throw new ArgumentNullException("dataType can't be null.");
-                       }
-                       
-                       DataType = dataType;
-                       Expression = expr == null ? String.Empty : expr;
-                       ColumnMapping = type;
-               }
-               #endregion
-
-               #region Properties
-
-               internal object this[int index] {
-                       get {
-                               return DataContainer[index];
-                       }
-                       set {
-                               if ( !(value == null && AutoIncrement) ) {
-                                       DataContainer[index] = value;
-                               }
-
-                               if ( AutoIncrement && !DataContainer.IsNull(index) ) {
-                                       long value64 = Convert.ToInt64(value);
-                                       UpdateAutoIncrementValue(value64);
-                               }
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether null values are allowed in this column.")]
-               [DefaultValue (true)]
-               public bool AllowDBNull
-               {
-                       get {
-                               return _allowDBNull;
-                       }
-                       set {
-                               //TODO: If we are a part of the table and this value changes
-                               //we need to validate that all the existing values conform to the new setting
-
-                               if (true == value)
-                               {
-                                       _allowDBNull = true;
-                                       return;
-                               }
-                               
-                               //if Value == false case
-                               if (null != _table)
-                               {
-                                       if (_table.Rows.Count > 0)
-                                       {
-                                               bool nullsFound = false;
-                                               for(int r = 0; r < _table.Rows.Count; r++) {
-                                                       DataRow row = _table.Rows[r];
-                                                       if(row.IsNull(this)) {
-                                                               nullsFound = true;
-                                                               break;
-                                                       }
-                                               }
-                                               
-                                               if (nullsFound)
-                                                       throw new DataException("Column '" + ColumnName + "' has null values in it.");
-                                               //TODO: Validate no null values exist
-                                               //do we also check different versions of the row??
-                                       }
-                               }
-                                       
-                               _allowDBNull = value;
-                       }
-               }
-        
-               /// <summary>
-               /// Gets or sets a value indicating whether the column automatically increments the value of the column for new rows added to the table.
-               /// </summary>
-               /// <remarks>
-               ///             If the type of this column is not Int16, Int32, or Int64 when this property is set, 
-               ///             the DataType property is coerced to Int32. An exception is generated if this is a computed column 
-               ///             (that is, the Expression property is set.) The incremented value is used only if the row's value for this column, 
-               ///             when added to the columns collection, is equal to the default value.
-               ///     </remarks>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether the column automatically increments itself for new rows added to the table.  The type of this column must be Int16, Int32, or Int64.")]
-               [DefaultValue (false)]
-               [RefreshProperties (RefreshProperties.All)]
-               public bool AutoIncrement
-               {
-                       get {
-                               return _autoIncrement;
-                       }
-                       set {
-                               if(value == true)
-                               {
-                                       //Can't be true if this is a computed column
-                                       if (Expression != string.Empty)
-                                       {
-                                               throw new ArgumentException("Can not Auto Increment a computed column."); 
-                                       }
-
-                                       if ( DefaultValue != DBNull.Value ) {
-                                               throw new ArgumentException("Can not set AutoIncrement while" +
-                                                       " default value exists for this column.");
-                                       }
-
-                                       //If the DataType of this Column isn't an Int
-                                       //Make it an int
-                                       TypeCode typeCode = Type.GetTypeCode(DataType);
-                                       if(typeCode != TypeCode.Int16 && 
-                                               typeCode != TypeCode.Int32 && 
-                                               typeCode != TypeCode.Int64)
-                                       {
-                                               DataType = typeof(Int32); 
-                                       }
-
-                                       if (_table != null)
-                                               _table.Columns.UpdateAutoIncrement(this,true);
-                               }
-                               else
-                               {
-                                       if (_table != null)
-                                               _table.Columns.UpdateAutoIncrement(this,false);
-                               }
-                               _autoIncrement = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the starting value for an AutoIncrement column.")]
-               [DefaultValue (0)]
-               public long AutoIncrementSeed
-               {
-                       get {
-                               return _autoIncrementSeed;
-                       }
-                       set {
-                               _autoIncrementSeed = value;
-                               _nextAutoIncrementValue = _autoIncrementSeed;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the increment used by an AutoIncrement column.")]
-               [DefaultValue (1)]
-               public long AutoIncrementStep
-               {
-                       get {
-                               return _autoIncrementStep;
-                       }
-                       set {
-                               _autoIncrementStep = value;
-                       }
-               }
-
-               internal void UpdateAutoIncrementValue(long value64)
-               {
-                       if (_autoIncrementStep > 0 ) {
-                               if (value64 >= _nextAutoIncrementValue) {
-                                       _nextAutoIncrementValue = value64;
-                                       AutoIncrementValue ();
-                               }
-                       }
-                       else if (value64 <= _nextAutoIncrementValue) {
-                               AutoIncrementValue ();
-                       }
-               }
-
-               internal long AutoIncrementValue () 
-               {
-                       long currentValue = _nextAutoIncrementValue;
-                       _nextAutoIncrementValue += AutoIncrementStep;
-                       return currentValue;
-               }
-
-               internal long GetAutoIncrementValue ()
-               {
-                       return _nextAutoIncrementValue;
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the default user-interface caption for this column.")]
-               public string Caption 
-               {
-                       get {
-                               if(_caption == null)
-                                       return ColumnName;
-                               else
-                                       return _caption;
-                       }
-                       set {
-                               if (value == null)
-                                       value = String.Empty;
-                                       
-                               _caption = value;
-                       }
-               }
-               [DataSysDescription ("Indicates how this column persists in XML: as an attribute, element, simple content node, or nothing.")]
-               [DefaultValue (MappingType.Element)]
-               public virtual MappingType ColumnMapping
-               {
-                       get {
-                               return _columnMapping;
-                       }
-                       set {
-                               _columnMapping = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the name used to look up this column in the Columns collection of a DataTable.")]
-               [RefreshProperties (RefreshProperties.All)]
-               [DefaultValue ("")]
-               public string ColumnName
-               {
-                       get {
-                               return (_columnName == null ? String.Empty : _columnName);
-                       }
-                       set {
-                               //Both are checked after the column is part of the collection
-                               //TODO: Check Name duplicate
-                               //TODO: check Name != null
-                               _columnName = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the type of data stored in this column.")]
-               [DefaultValue (typeof (string))]
-               [RefreshProperties (RefreshProperties.All)]
-               [TypeConverterAttribute (typeof (ColumnTypeConverter))] 
-               public Type DataType
-               {
-                       get {
-                               return DataContainer.Type;
-                       }
-                       set {
-
-                                if ( value == null ) 
-                                        return;
-
-                               if ( _dataContainer != null ) {
-                                       if ( value == _dataContainer.Type ) 
-                                               return;
-
-                                       // check if data already exists can we change the datatype
-                                       if ( _dataContainer.Capacity > 0 )
-                                               throw new ArgumentException("The column already has data stored.");
-                               }
-
-                                if (null != GetParentRelation () || null != GetChildRelation ())
-                                        throw new InvalidConstraintException ("Cannot change datatype, " + 
-                                                                              "when column is part of a relation");
-                                
-                                _dataContainer = AbstractDataContainer.CreateInstance(value, this);
-
-                               //Check AutoIncrement status, make compatible datatype
-                               if(AutoIncrement == true) {
-                                       // we want to check that the datatype is supported?
-                                       TypeCode typeCode = Type.GetTypeCode(value);
-                                       
-                                       if(typeCode != TypeCode.Int16 &&
-                                          typeCode != TypeCode.Int32 &&
-                                          typeCode != TypeCode.Int64) {
-                                               AutoIncrement = false;
-                                       }
-                               }
-                       }
-               }
-
-               /// <summary>
-               /// 
-               /// </summary>
-               /// <remarks>When AutoIncrement is set to true, there can be no default value.</remarks>
-               /// <exception cref="System.InvalidCastException"></exception>
-               /// <exception cref="System.ArgumentException"></exception>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the default column value used when adding new rows to the table.")]
-               [TypeConverterAttribute (typeof (System.Data.DefaultValueTypeConverter))]
-               public object DefaultValue
-               {
-                       get {
-                               return _defaultValue;
-                       }
-
-                       set {
-                               if (AutoIncrement) {
-                                       throw new ArgumentException("Can not set default value while" +
-                                               " AutoIncrement is true on this column.");
-                               }
-
-                               object tmpObj;
-                               if (!this._defaultValue.Equals(value)) {                
-                                       if (value == null) {
-                                               tmpObj = DBNull.Value;
-                                       }
-                                       else {
-                                               tmpObj = value;
-                                       }
-
-                                       if ((this.DataType != typeof (object))&& (tmpObj != DBNull.Value)) {
-                                               try {
-                                                       //Casting to the new type
-                                                       tmpObj= Convert.ChangeType(tmpObj,this.DataType);
-                                               }
-                                               catch (InvalidCastException) {
-                                                       throw new InvalidCastException("Default Value type is not compatible with" + 
-                                                               " column type.");
-                                               }
-                                       }
-                                       _defaultValue = tmpObj;
-                               }
-
-                               // store default value in the table if already belongs to
-                               if (Table != null && Table.DefaultValuesRowIndex != -1) {
-                                       DataContainer[Table.DefaultValuesRowIndex] = _defaultValue;
-                               }
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the value that this column computes for each row based on other columns instead of taking user input.")]
-               [DefaultValue ("")]
-               [RefreshProperties (RefreshProperties.All)]
-               public string Expression
-               {
-                       get {
-                               return expression;
-                       }
-                       set {
-                               if (value == null)
-                                       value = String.Empty;
-                                       
-                               if (value != String.Empty) {
-                                       Parser parser = new Parser ();
-                                       compiledExpression = parser.Compile (value);
-                                       ReadOnly = true;
-                               }
-                               expression = value;  
-                       }
-               }
-
-               internal IExpression CompiledExpression {
-                       get { return compiledExpression; }
-               }
-
-               [Browsable (false)]
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds custom user information.")]
-               public PropertyCollection ExtendedProperties
-               {
-                       get {
-                               return _extendedProperties;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the maximum length of the value this column allows.")]
-               [DefaultValue (-1)]
-               public int MaxLength
-               {
-                       get {
-                               //Default == -1 no max length
-                               return maxLength;
-                       }
-                       set {
-                               if (value >= 0 &&
-                                       _columnMapping == MappingType.SimpleContent)
-                                       throw new ArgumentException (String.Format ("Cannot set MaxLength property on '{0}' column which is mapped to SimpleContent.", ColumnName));
-                               //only applies to string columns
-                               maxLength = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the XML uri for elements stored in this  column.")]
-               public string Namespace
-               {
-                       get {
-                               return nameSpace;
-                       }
-                       set {
-                               if (value == null)
-                                       value = String.Empty;
-                               nameSpace = value;
-                       }
-               }
-
-               //Need a good way to set the Ordinal when the column is added to a columnCollection.
-               [Browsable (false)]
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the index of this column in the Columns collection.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public int Ordinal
-               {
-                       get {
-                               //value is -1 if not part of a collection
-                               return _ordinal;
-                       }
-               }
-
-               internal void SetOrdinal(int ordinal)
-               {
-                       _ordinal = ordinal;
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the prefix used for this DataColumn in the xml representation.")]
-               [DefaultValue ("")]
-               public string Prefix
-               {
-                       get {
-                               return prefix;
-                       }
-                       set {
-                               if (value == null)
-                                       value = String.Empty;
-                               prefix = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether this column allows changes once a row has been added to the table.")]
-               [DefaultValue (false)]
-               public bool ReadOnly
-               {
-                       get {
-                               return readOnly;
-                       }
-                       set {
-                               readOnly = value;
-                       }
-               }
-
-               [Browsable (false)]
-               [DataCategory ("Data")]
-               [DataSysDescription ("Returns the DataTable to which this column belongs.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]      
-               public DataTable Table
-               {
-                       get {
-                               return _table;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether this column should restrict its values in the rows of the table to be unique.")]
-               [DefaultValue (false)]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-                public bool Unique 
-               {
-                       get {
-                               return unique;
-                       }
-                       set {
-                               //NOTE: In .NET 1.1 the Unique property
-                                //is left unchanged when it is added
-                                //to a UniqueConstraint
-
-                               if(unique != value)
-                               {
-                               unique = value;
-
-                                       if( value )
-                                       {
-                                               if (Expression != null && Expression != String.Empty)
-                                                       throw new ArgumentException("Cannot change Unique property for the expression column.");
-                                               if( _table != null )
-                                               {
-                                                       UniqueConstraint uc = new UniqueConstraint(this);
-                                                       _table.Constraints.Add(uc);
-                                               }
-                                       }
-                                       else
-                                       {
-                                               if( _table != null )
-                                               {
-                                                       ConstraintCollection cc = _table.Constraints;
-                                                       //foreach (Constraint c in cc) 
-                                                       for (int i = 0; i < cc.Count; i++)
-                                                       {
-                                                               Constraint c = cc[i];
-                                                               if (c is UniqueConstraint)
-                                                               {
-                                                                       DataColumn[] cols = ((UniqueConstraint)c).Columns;
-                                                                       
-                                                                       if (cols.Length == 1 && cols[0] == this)
-                                                                       {
-                                                                               if (!cc.CanRemove(c))
-                                                                                       throw new ArgumentException("Cannot remove unique constraint '" + c.ConstraintName + "'. Remove foreign key constraint first.");
-
-                                                                               cc.Remove(c);
-                                                                       }
-                                                                       
-                                                               }
-                                                       }
-                                               }
-                                       }
-
-                               }
-                       }
-               }
-
-               internal AbstractDataContainer DataContainer {
-                       get {
-                               return _dataContainer;
-                       }
-               }
-
-               #endregion // Properties
-
-               #region Methods
-               
-/* ??
-               [MonoTODO]
-               protected internal void CheckNotAllowNull() {
-               }
-
-               [MonoTODO]
-               protected void CheckUnique() {
-               }
-*/
-
-               /// <summary>
-               ///  Sets unique true whithout creating Constraint
-               /// </summary>
-               internal void SetUnique() 
-               {
-                       unique = true;
-               }
-
-               [MonoTODO]
-               internal void AssertCanAddToCollection()
-               {
-                       //Check if Default Value is set and AutoInc is set
-               }
-
-               [MonoTODO]
-               protected internal void CheckNotAllowNull ()
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               protected void CheckUnique ()
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               protected internal virtual void 
-               OnPropertyChanging (PropertyChangedEventArgs pcevent) {
-               }
-
-               [MonoTODO]
-               protected internal void RaisePropertyChanging(string name) {
-               }
-
-               /// <summary>
-               /// Gets the Expression of the column, if one exists.
-               /// </summary>
-               /// <returns>The Expression value, if the property is set; 
-               /// otherwise, the ColumnName property.</returns>
-               public override string ToString()
-               {
-                       if (expression != string.Empty)
-                               return ColumnName + " + " + expression;
-                       
-                       return ColumnName;
-               }
-
-               internal void SetTable(DataTable table) {
-                       if(_table!=null) { // serves as double check while adding to a table
-                    throw new ArgumentException("The column already belongs to a different table");
-            }
-            _table = table;
-            // this will get called by DataTable
-            // and DataColumnCollection
-            if(unique) {
-                // if the DataColumn is marked as Unique and then
-                   // added to a DataTable , then a UniqueConstraint
-                   // should be created
-                UniqueConstraint uc = new UniqueConstraint(this);
-                _table.Constraints.Add(uc);
-            }
-
-                       // allocate space in the column data container 
-                       DataContainer.Capacity = _table.RecordCache.CurrentCapacity;
-                       
-                       int defaultValuesRowIndex = _table.DefaultValuesRowIndex;
-                       if ( defaultValuesRowIndex != -1) {
-                               // store default value in the table
-                               DataContainer[defaultValuesRowIndex] = _defaultValue;
-                               // Set all the values in data container to default
-                               // it's cheaper that raise event on each row.
-                               DataContainer.FillValues(_table.DefaultValuesRowIndex);
-                       }
-               }
-
-               
-               // Returns true if all the same collumns are in columnSet and compareSet
-               internal static bool AreColumnSetsTheSame(DataColumn[] columnSet, DataColumn[] compareSet)
-               {
-                       if (null == columnSet && null == compareSet) return true;
-                       if (null == columnSet || null == compareSet) return false;
-
-                       if (columnSet.Length != compareSet.Length) return false;
-                       
-                       foreach (DataColumn col in columnSet)
-                       {
-                               bool matchFound = false;
-                               foreach (DataColumn compare in compareSet)
-                               {
-                                       if (col == compare)
-                                       {
-                                               matchFound = true;                                      
-                                       }
-                               }
-                               if (! matchFound) return false;
-                       }
-                       
-                       return true;
-               }
-               
-               internal int CompareValues (int index1, int index2)
-               {
-                       return DataContainer.CompareValues(index1, index2);
-               }
-
-                /// <summary>
-                ///     Returns the data relation, which contains this column.
-                ///     This searches in current table's parent relations.
-                /// <summary>
-                /// <returns>
-                ///     DataRelation if found otherwise null.
-                /// </returns>
-                internal DataRelation GetParentRelation ()
-                {
-                        if (_table == null)
-                                return null;
-                        foreach (DataRelation rel in _table.ParentRelations)
-                                if (rel.Contains (this))
-                                        return rel;
-                        return null;
-                }
-                
-
-                /// <summary>
-                ///     Returns the data relation, which contains this column.
-                ///     This searches in current table's child relations.
-                /// <summary>
-                /// <returns>
-                ///     DataRelation if found otherwise null.
-                /// </returns>
-                internal DataRelation GetChildRelation ()
-                {
-                        if (_table == null)
-                                return null;
-                        foreach (DataRelation rel in _table.ChildRelations)
-                                if (rel.Contains (this))
-                                        return rel;
-                        return null;
-                }
-                
-
-               #endregion // Methods
-
-       }
-}
+//\r
+// System.Data.DataColumn.cs\r
+//\r
+// Author:\r
+//   Franklin Wise (gracenote@earthlink.net)\r
+//   Christopher Podurgiel (cpodurgiel@msn.com)\r
+//   Rodrigo Moya (rodrigo@ximian.com)\r
+//   Daniel Morgan (danmorg@sc.rr.com)\r
+//   Tim Coleman (tim@timcoleman.com)\r
+//\r
+// (C) Copyright 2002, Franklin Wise\r
+// (C) Chris Podurgiel\r
+// (C) Ximian, Inc 2002\r
+// Copyright (C) Tim Coleman, 2002\r
+// Copyright (C) Daniel Morgan, 2002, 2003\r
+//\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
+using System.ComponentModel;\r
+using System.Reflection;\r
+using System.Collections;\r
+using System.Data.Common;\r
+using System.Globalization;\r
+using Mono.Data.SqlExpressions;\r
+\r
+namespace System.Data {\r
+       internal delegate void DelegateColumnValueChange(DataColumn column, DataRow row, object proposedValue);\r
+       \r
+       /// <summary>\r
+       /// Summary description for DataColumn.\r
+       /// </summary>\r
+\r
+       [Editor]\r
+       [ToolboxItem (false)]\r
+       [DefaultProperty ("ColumnName")]\r
+       [DesignTimeVisible (false)]\r
+       public class DataColumn : MarshalByValueComponent\r
+       {               \r
+               #region Events\r
+               [MonoTODO]\r
+               //used for constraint validation\r
+               //if an exception is fired during this event the change should be canceled\r
+               internal event DelegateColumnValueChange ValidateColumnValueChange;\r
+\r
+               //used for FK Constraint Cascading rules\r
+               internal event DelegateColumnValueChange ColumnValueChanging;\r
+               #endregion //Events\r
+               \r
+               #region Fields\r
+\r
+               private bool _allowDBNull = true;\r
+               private bool _autoIncrement;\r
+               private long _autoIncrementSeed;\r
+               private long _autoIncrementStep = 1;\r
+               private long _nextAutoIncrementValue;\r
+               private string _caption;\r
+               private MappingType _columnMapping;\r
+               private string _columnName = String.Empty;\r
+               private object _defaultValue = DBNull.Value;\r
+               private string _expression;\r
+               private IExpression _compiledExpression;\r
+               private PropertyCollection _extendedProperties = new PropertyCollection ();\r
+               private int _maxLength = -1; //-1 represents no length limit\r
+               private string _nameSpace;\r
+               private int _ordinal = -1; //-1 represents not part of a collection\r
+               private string _prefix = String.Empty;\r
+               private bool _readOnly;\r
+               private DataTable _table;\r
+               private bool _unique;\r
+               private AbstractDataContainer _dataContainer;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               public DataColumn() : this(String.Empty, typeof (string), String.Empty, MappingType.Element)\r
+               {\r
+               }\r
+\r
+               //TODO: Ctor init vars directly\r
+               public DataColumn(string columnName): this(columnName, typeof (string), String.Empty, MappingType.Element)\r
+               {\r
+               }\r
+\r
+               public DataColumn(string columnName, Type dataType): this(columnName, dataType, String.Empty, MappingType.Element)\r
+               {\r
+               }\r
+\r
+               public DataColumn( string columnName, Type dataType, \r
+                       string expr): this(columnName, dataType, expr, MappingType.Element)\r
+               {\r
+               }\r
+\r
+               public DataColumn(string columnName, Type dataType, \r
+                       string expr, MappingType type)\r
+               {\r
+                       ColumnName = (columnName == null ? String.Empty : columnName);\r
+                       \r
+                       if(dataType == null) {\r
+                               throw new ArgumentNullException("dataType can't be null.");\r
+                       }\r
+                       \r
+                       DataType = dataType;\r
+                       Expression = expr == null ? String.Empty : expr;\r
+                       ColumnMapping = type;\r
+               }\r
+               #endregion\r
+\r
+               #region Properties\r
+\r
+               internal object this[int index] {\r
+                       get {\r
+                               return DataContainer[index];\r
+                       }\r
+                       set {\r
+                               if ( !(value == null && AutoIncrement) ) {\r
+                                       DataContainer[index] = value;\r
+                               }\r
+\r
+                               if ( AutoIncrement && !DataContainer.IsNull(index) ) {\r
+                                       long value64 = Convert.ToInt64(value);\r
+                                       UpdateAutoIncrementValue(value64);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether null values are allowed in this column.")]\r
+               [DefaultValue (true)]\r
+               public bool AllowDBNull\r
+               {\r
+                       get {\r
+                               return _allowDBNull;\r
+                       }\r
+                       set {\r
+                               //TODO: If we are a part of the table and this value changes\r
+                               //we need to validate that all the existing values conform to the new setting\r
+\r
+                               if (true == value)\r
+                               {\r
+                                       _allowDBNull = true;\r
+                                       return;\r
+                               }\r
+                               \r
+                               //if Value == false case\r
+                               if (null != _table)\r
+                               {\r
+                                       if (_table.Rows.Count > 0)\r
+                                       {\r
+                                               bool nullsFound = false;\r
+                                               for(int r = 0; r < _table.Rows.Count; r++) {\r
+                                                       DataRow row = _table.Rows[r];\r
+                                                       if(row.IsNull(this)) {\r
+                                                               nullsFound = true;\r
+                                                               break;\r
+                                                       }\r
+                                               }\r
+                                               \r
+                                               if (nullsFound)\r
+                                                       throw new DataException("Column '" + ColumnName + "' has null values in it.");\r
+                                               //TODO: Validate no null values exist\r
+                                               //do we also check different versions of the row??\r
+                                       }\r
+                               }\r
+                                       \r
+                               _allowDBNull = value;\r
+                       }\r
+               }\r
+        \r
+               /// <summary>\r
+               /// Gets or sets a value indicating whether the column automatically increments the value of the column for new rows added to the table.\r
+               /// </summary>\r
+               /// <remarks>\r
+               ///             If the type of this column is not Int16, Int32, or Int64 when this property is set, \r
+               ///             the DataType property is coerced to Int32. An exception is generated if this is a computed column \r
+               ///             (that is, the Expression property is set.) The incremented value is used only if the row's value for this column, \r
+               ///             when added to the columns collection, is equal to the default value.\r
+               ///     </remarks>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether the column automatically increments itself for new rows added to the table.  The type of this column must be Int16, Int32, or Int64.")]\r
+               [DefaultValue (false)]\r
+               [RefreshProperties (RefreshProperties.All)]\r
+               public bool AutoIncrement\r
+               {\r
+                       get {\r
+                               return _autoIncrement;\r
+                       }\r
+                       set {\r
+                               if(value == true)\r
+                               {\r
+                                       //Can't be true if this is a computed column\r
+                                       if (Expression != string.Empty)\r
+                                       {\r
+                                               throw new ArgumentException("Can not Auto Increment a computed column."); \r
+                                       }\r
+\r
+                                       if ( DefaultValue != DBNull.Value ) {\r
+                                               throw new ArgumentException("Can not set AutoIncrement while" +\r
+                                                       " default value exists for this column.");\r
+                                       }\r
+\r
+                                       if(!CanAutoIncrement(DataType))\r
+                                       {\r
+                                               DataType = typeof(Int32); \r
+                                       }\r
+\r
+                                       if (_table != null)\r
+                                               _table.Columns.UpdateAutoIncrement(this,true);\r
+                               }\r
+                               else\r
+                               {\r
+                                       if (_table != null)\r
+                                               _table.Columns.UpdateAutoIncrement(this,false);\r
+                               }\r
+                               _autoIncrement = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the starting value for an AutoIncrement column.")]\r
+               [DefaultValue (0)]\r
+               public long AutoIncrementSeed\r
+               {\r
+                       get {\r
+                               return _autoIncrementSeed;\r
+                       }\r
+                       set {\r
+                               _autoIncrementSeed = value;\r
+                               _nextAutoIncrementValue = _autoIncrementSeed;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the increment used by an AutoIncrement column.")]\r
+               [DefaultValue (1)]\r
+               public long AutoIncrementStep\r
+               {\r
+                       get {\r
+                               return _autoIncrementStep;\r
+                       }\r
+                       set {\r
+                               _autoIncrementStep = value;\r
+                       }\r
+               }\r
+\r
+               internal void UpdateAutoIncrementValue(long value64)\r
+               {\r
+                       if (_autoIncrementStep > 0 ) {\r
+                               if (value64 >= _nextAutoIncrementValue) {\r
+                                       _nextAutoIncrementValue = value64;\r
+                                       AutoIncrementValue ();\r
+                               }\r
+                       }\r
+                       else if (value64 <= _nextAutoIncrementValue) {\r
+                               AutoIncrementValue ();\r
+                       }\r
+               }\r
+\r
+               internal long AutoIncrementValue () \r
+               {\r
+                       long currentValue = _nextAutoIncrementValue;\r
+                       _nextAutoIncrementValue += AutoIncrementStep;\r
+                       return currentValue;\r
+               }\r
+\r
+               internal long GetAutoIncrementValue ()\r
+               {\r
+                       return _nextAutoIncrementValue;\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the default user-interface caption for this column.")]\r
+               public string Caption \r
+               {\r
+                       get {\r
+                               if(_caption == null)\r
+                                       return ColumnName;\r
+                               else\r
+                                       return _caption;\r
+                       }\r
+                       set {\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+                                       \r
+                               _caption = value;\r
+                       }\r
+               }\r
+               [DataSysDescription ("Indicates how this column persists in XML: as an attribute, element, simple content node, or nothing.")]\r
+               [DefaultValue (MappingType.Element)]\r
+               public virtual MappingType ColumnMapping\r
+               {\r
+                       get {\r
+                               return _columnMapping;\r
+                       }\r
+                       set {\r
+                               _columnMapping = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the name used to look up this column in the Columns collection of a DataTable.")]\r
+               [RefreshProperties (RefreshProperties.All)]\r
+               [DefaultValue ("")]\r
+               public string ColumnName\r
+               {\r
+                       get {\r
+                               return _columnName;\r
+                       }\r
+                       set {\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+\r
+                               CultureInfo info = Table != null ? Table.Locale : CultureInfo.CurrentCulture;\r
+                               if (String.Compare(value, _columnName, true, info) != 0) {\r
+                                       if (Table != null) {\r
+                                               if (value.Length == 0)\r
+                                                       throw new ArgumentException("ColumnName is required when it is part of a DataTable.");\r
+\r
+                                               Table.Columns.RegisterName(value, this);\r
+                                               if (_columnName.Length > 0)\r
+                                                       Table.Columns.UnregisterName(_columnName);\r
+                                       }\r
+\r
+                                       RaisePropertyChanging("ColumnName");\r
+                                       _columnName = value;\r
+\r
+                                       if (Table != null)\r
+                                               Table.ResetPropertyDescriptorsCache();\r
+                               }\r
+                               else if (String.Compare(value, _columnName, false, info) != 0) {\r
+                                       RaisePropertyChanging("ColumnName");\r
+                                       _columnName = value;\r
+\r
+                                       if (Table != null)\r
+                                               Table.ResetPropertyDescriptorsCache();\r
+                               }\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the type of data stored in this column.")]\r
+               [DefaultValue (typeof (string))]\r
+               [RefreshProperties (RefreshProperties.All)]\r
+               [TypeConverterAttribute (typeof (ColumnTypeConverter))] \r
+               public Type DataType\r
+               {\r
+                       get {\r
+                               return DataContainer.Type;\r
+                       }\r
+                       set {\r
+\r
+                                if ( value == null ) \r
+                                        return;\r
+\r
+                               if ( _dataContainer != null ) {\r
+                                       if ( value == _dataContainer.Type ) \r
+                                               return;\r
+\r
+                                       // check if data already exists can we change the datatype\r
+                                       if ( _dataContainer.Capacity > 0 )\r
+                                               throw new ArgumentException("The column already has data stored.");\r
+                               }\r
+\r
+                                if (null != GetParentRelation () || null != GetChildRelation ())\r
+                                        throw new InvalidConstraintException ("Cannot change datatype, " + \r
+                                                                              "when column is part of a relation");\r
+                                \r
+                                _dataContainer = AbstractDataContainer.CreateInstance(value, this);\r
+\r
+                               //Check AutoIncrement status, make compatible datatype\r
+                               if(AutoIncrement == true) {\r
+                                       // we want to check that the datatype is supported?\r
+                                       TypeCode typeCode = Type.GetTypeCode(value);\r
+                                       \r
+                                       if(typeCode != TypeCode.Int16 &&\r
+                                          typeCode != TypeCode.Int32 &&\r
+                                          typeCode != TypeCode.Int64) {\r
+                                               AutoIncrement = false;\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// \r
+               /// </summary>\r
+               /// <remarks>When AutoIncrement is set to true, there can be no default value.</remarks>\r
+               /// <exception cref="System.InvalidCastException"></exception>\r
+               /// <exception cref="System.ArgumentException"></exception>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the default column value used when adding new rows to the table.")]\r
+               [TypeConverterAttribute (typeof (System.Data.DefaultValueTypeConverter))]\r
+               public object DefaultValue\r
+               {\r
+                       get {\r
+                               return _defaultValue;\r
+                       }\r
+\r
+                       set {\r
+                               if (AutoIncrement) {\r
+                                       throw new ArgumentException("Can not set default value while" +\r
+                                               " AutoIncrement is true on this column.");\r
+                               }\r
+\r
+                               object tmpObj;\r
+                               if (!this._defaultValue.Equals(value)) {                \r
+                                       if (value == null) {\r
+                                               tmpObj = DBNull.Value;\r
+                                       }\r
+                                       else {\r
+                                               tmpObj = value;\r
+                                       }\r
+\r
+                                       if ((this.DataType != typeof (object))&& (tmpObj != DBNull.Value)) {\r
+                                               try {\r
+                                                       //Casting to the new type\r
+                                                       tmpObj= Convert.ChangeType(tmpObj,this.DataType);\r
+                                               }\r
+                                               catch (InvalidCastException) {\r
+                                                       throw new InvalidCastException("Default Value type is not compatible with" + \r
+                                                               " column type.");\r
+                                               }\r
+                                       }\r
+                                       _defaultValue = tmpObj;\r
+                               }\r
+\r
+                               // store default value in the table if already belongs to\r
+                               if (Table != null && Table.DefaultValuesRowIndex != -1) {\r
+                                       DataContainer[Table.DefaultValuesRowIndex] = _defaultValue;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the value that this column computes for each row based on other columns instead of taking user input.")]\r
+               [DefaultValue ("")]\r
+               [RefreshProperties (RefreshProperties.All)]\r
+               public string Expression\r
+               {\r
+                       get {\r
+                               return _expression;\r
+                       }\r
+                       set {\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+                                       \r
+                               if (value != String.Empty) \r
+                               {\r
+\r
+                                       if (AutoIncrement || Unique)\r
+                                               throw new ArgumentException("Cannot create an expression on a column that has AutoIncrement or Unique.");\r
+\r
+                                       if (Table != null)\r
+                                       {\r
+                                               for (int i = 0; i < Table.Constraints.Count; i++)\r
+                                               {\r
+                                                       if (Table.Constraints[i].IsColumnContained(this))\r
+                                                               throw new ArgumentException(String.Format("Cannot set Expression property on column {0}, because it is a part of a constraint.", ColumnName));\r
+                                               }\r
+                                       }\r
+\r
+                                       Parser parser = new Parser ();\r
+                                       IExpression compiledExpression = parser.Compile (value);\r
+\r
+                                       if (Table != null)\r
+                                       {\r
+                                               if (compiledExpression.DependsOn(this))\r
+                                                       throw new ArgumentException("Cannot set Expression property due to circular reference in the expression.");\r
+                                       }\r
+                                       \r
+                                       ReadOnly = true;\r
+                                       _compiledExpression = compiledExpression;\r
+                               }\r
+                               else\r
+                               {\r
+                                       _compiledExpression = null;\r
+                                       if (Table != null)\r
+                                       {\r
+                                               int defaultValuesRowIndex = Table.DefaultValuesRowIndex;\r
+                                               if ( defaultValuesRowIndex != -1) \r
+                                                       DataContainer.FillValues(defaultValuesRowIndex);\r
+                                       }\r
+                               }\r
+                               _expression = value;  \r
+                       }\r
+               }\r
+\r
+               internal IExpression CompiledExpression {\r
+                       get { return _compiledExpression; }\r
+               }\r
+\r
+               [Browsable (false)]\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds custom user information.")]\r
+               public PropertyCollection ExtendedProperties\r
+               {\r
+                       get {\r
+                               return _extendedProperties;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the maximum length of the value this column allows.")]\r
+               [DefaultValue (-1)]\r
+               public int MaxLength\r
+               {\r
+                       get {\r
+                               //Default == -1 no max length\r
+                               return _maxLength;\r
+                       }\r
+                       set {\r
+                               if (value >= 0 &&\r
+                                       _columnMapping == MappingType.SimpleContent)\r
+                                       throw new ArgumentException (String.Format ("Cannot set MaxLength property on '{0}' column which is mapped to SimpleContent.", ColumnName));\r
+                               //only applies to string columns\r
+                               _maxLength = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the XML uri for elements stored in this  column.")]\r
+               public string Namespace\r
+               {\r
+                       get {\r
+                               if (_nameSpace != null)\r
+                               {\r
+                                       return _nameSpace;\r
+                               }\r
+                               if ((Table != null) && (_columnMapping != MappingType.Attribute))\r
+                               {\r
+                                       return Table.Namespace;\r
+                               }\r
+                               return String.Empty;\r
+                       }\r
+                       set {\r
+                               _nameSpace = value;\r
+                       }\r
+               }\r
+\r
+               //Need a good way to set the Ordinal when the column is added to a columnCollection.\r
+               [Browsable (false)]\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the index of this column in the Columns collection.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public int Ordinal\r
+               {\r
+                       get {\r
+                               //value is -1 if not part of a collection\r
+                               return _ordinal;\r
+                       }\r
+               }\r
+\r
+               internal void SetOrdinal(int ordinal)\r
+               {\r
+                       _ordinal = ordinal;\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the prefix used for this DataColumn in the xml representation.")]\r
+               [DefaultValue ("")]\r
+               public string Prefix\r
+               {\r
+                       get {\r
+                               return _prefix;\r
+                       }\r
+                       set {\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+                               _prefix = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether this column allows changes once a row has been added to the table.")]\r
+               [DefaultValue (false)]\r
+               public bool ReadOnly\r
+               {\r
+                       get {\r
+                               return _readOnly;\r
+                       }\r
+                       set {\r
+                               _readOnly = value;\r
+                       }\r
+               }\r
+\r
+               [Browsable (false)]\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Returns the DataTable to which this column belongs.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]      \r
+               public DataTable Table\r
+               {\r
+                       get {\r
+                               return _table;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether this column should restrict its values in the rows of the table to be unique.")]\r
+               [DefaultValue (false)]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+                public bool Unique \r
+               {\r
+                       get {\r
+                               return _unique;\r
+                       }\r
+                       set {\r
+                               //NOTE: In .NET 1.1 the Unique property\r
+                                //is left unchanged when it is added\r
+                                //to a UniqueConstraint\r
+\r
+                               if(_unique != value)\r
+                               {\r
+                                       _unique = value;\r
+\r
+                                       if( value )\r
+                                       {\r
+                                               if (Expression != null && Expression != String.Empty)\r
+                                                       throw new ArgumentException("Cannot change Unique property for the expression column.");\r
+                                               if( _table != null )\r
+                                               {\r
+                                                       UniqueConstraint uc = new UniqueConstraint(this);\r
+                                                       _table.Constraints.Add(uc);\r
+                                               }\r
+                                       }\r
+                                       else\r
+                                       {\r
+                                               if( _table != null )\r
+                                               {\r
+                                                       ConstraintCollection cc = _table.Constraints;\r
+                                                       //foreach (Constraint c in cc) \r
+                                                       for (int i = 0; i < cc.Count; i++)\r
+                                                       {\r
+                                                               Constraint c = cc[i];\r
+                                                               if (c is UniqueConstraint)\r
+                                                               {\r
+                                                                       DataColumn[] cols = ((UniqueConstraint)c).Columns;\r
+                                                                       \r
+                                                                       if (cols.Length == 1 && cols[0] == this)\r
+                                                                       {\r
+                                                                               cc.Remove(c);\r
+                                                                       }\r
+                                                                       \r
+                                                               }\r
+                                                       }\r
+                                               }\r
+                                       }\r
+\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal AbstractDataContainer DataContainer {\r
+                       get {\r
+                               return _dataContainer;\r
+                       }\r
+               }\r
+\r
+               internal static bool CanAutoIncrement(Type type) {\r
+                       switch (Type.GetTypeCode(type)) {\r
+                               case TypeCode.Int16:\r
+                               case TypeCode.Int32:\r
+                               case TypeCode.Int64:\r
+                               case TypeCode.Decimal:\r
+                                       return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+               \r
+/* ??\r
+               [MonoTODO]\r
+               protected internal void CheckNotAllowNull() {\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected void CheckUnique() {\r
+               }\r
+*/\r
+               [MonoTODO]\r
+               internal DataColumn Clone() {\r
+                       DataColumn copy = new DataColumn ();\r
+\r
+                       // Copy all the properties of column\r
+                       copy._allowDBNull = _allowDBNull;\r
+                       copy._autoIncrement = _autoIncrement;\r
+                       copy._autoIncrementSeed = _autoIncrementSeed;\r
+                       copy._autoIncrementStep = _autoIncrementStep;\r
+                       copy._caption = _caption;\r
+                       copy._columnMapping = _columnMapping;\r
+                       copy._columnName = _columnName;\r
+                       //Copy.Container\r
+                       copy.DataType = DataType;\r
+                       copy._defaultValue = _defaultValue;                     \r
+                       copy._expression = _expression;\r
+                       //Copy.ExtendedProperties\r
+                       copy._maxLength = _maxLength;\r
+                       copy._nameSpace = _nameSpace;\r
+                       copy._prefix = _prefix;\r
+                       copy._readOnly = _readOnly;\r
+                       //Copy.Site\r
+                       //we do not copy the unique value - it will be copyied when copying the constraints.\r
+                       //Copy.Unique = Column.Unique;\r
+                       \r
+                       return copy;\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Sets unique true whithout creating Constraint\r
+               /// </summary>\r
+               internal void SetUnique() \r
+               {\r
+                       _unique = true;\r
+               }\r
+\r
+               [MonoTODO]\r
+               internal void AssertCanAddToCollection()\r
+               {\r
+                       //Check if Default Value is set and AutoInc is set\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected internal void CheckNotAllowNull ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected void CheckUnique ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected internal virtual void \r
+               OnPropertyChanging (PropertyChangedEventArgs pcevent) {\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected internal void RaisePropertyChanging(string name) {\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the Expression of the column, if one exists.\r
+               /// </summary>\r
+               /// <returns>The Expression value, if the property is set; \r
+               /// otherwise, the ColumnName property.</returns>\r
+               public override string ToString()\r
+               {\r
+                       if (_expression != string.Empty)\r
+                               return ColumnName + " + " + _expression;\r
+                       \r
+                       return ColumnName;\r
+               }\r
+\r
+               internal void SetTable(DataTable table) {\r
+                       if(_table!=null) { // serves as double check while adding to a table\r
+                    throw new ArgumentException("The column already belongs to a different table");\r
+            }\r
+            _table = table;\r
+            // this will get called by DataTable\r
+            // and DataColumnCollection\r
+            if(_unique) {\r
+                // if the DataColumn is marked as Unique and then\r
+                   // added to a DataTable , then a UniqueConstraint\r
+                   // should be created\r
+                UniqueConstraint uc = new UniqueConstraint(this);\r
+                _table.Constraints.Add(uc);\r
+            }\r
+\r
+                       // allocate space in the column data container \r
+                       DataContainer.Capacity = _table.RecordCache.CurrentCapacity;\r
+                       \r
+                       int defaultValuesRowIndex = _table.DefaultValuesRowIndex;\r
+                       if ( defaultValuesRowIndex != -1) {\r
+                               // store default value in the table\r
+                               DataContainer[defaultValuesRowIndex] = _defaultValue;\r
+                               // Set all the values in data container to default\r
+                               // it's cheaper that raise event on each row.\r
+                               DataContainer.FillValues(defaultValuesRowIndex);\r
+                       }\r
+               }\r
+               \r
+               // Returns true if all the same collumns are in columnSet and compareSet\r
+               internal static bool AreColumnSetsTheSame(DataColumn[] columnSet, DataColumn[] compareSet)\r
+               {\r
+                       if (null == columnSet && null == compareSet) {\r
+                               return true;\r
+                       }\r
+\r
+                       if (null == columnSet || null == compareSet) {\r
+                               return false;\r
+                       }\r
+\r
+                       if (columnSet.Length != compareSet.Length) { \r
+                               return false;\r
+                       }\r
+                       \r
+                       foreach (DataColumn col in columnSet) {\r
+                               bool matchFound = false;\r
+                               foreach (DataColumn compare in compareSet) {\r
+                                       if (col == compare) {\r
+                                               matchFound = true;                                      \r
+                                       }\r
+                               }\r
+                               if (! matchFound) {\r
+                                       return false;\r
+                               }\r
+                       }                       \r
+                       return true;\r
+               }\r
+\r
+               \r
+               internal int CompareValues (int index1, int index2)\r
+               {\r
+                       return DataContainer.CompareValues(index1, index2);\r
+               }\r
+\r
+                /// <summary>\r
+                ///     Returns the data relation, which contains this column.\r
+                ///     This searches in current table's parent relations.\r
+                /// <summary>\r
+                /// <returns>\r
+                ///     DataRelation if found otherwise null.\r
+                /// </returns>\r
+        private DataRelation GetParentRelation ()\r
+                {\r
+                        if (_table == null)\r
+                                return null;\r
+                        foreach (DataRelation rel in _table.ParentRelations)\r
+                                if (rel.Contains (this))\r
+                                        return rel;\r
+                        return null;\r
+                }\r
+                \r
+\r
+                /// <summary>\r
+                ///     Returns the data relation, which contains this column.\r
+                ///     This searches in current table's child relations.\r
+                /// <summary>\r
+                /// <returns>\r
+                ///     DataRelation if found otherwise null.\r
+                /// </returns>\r
+        private DataRelation GetChildRelation ()\r
+                {\r
+                        if (_table == null)\r
+                                return null;\r
+                        foreach (DataRelation rel in _table.ChildRelations)\r
+                                if (rel.Contains (this))\r
+                                        return rel;\r
+                        return null;\r
+                }\r
+                \r
+\r
+               #endregion // Methods\r
+\r
+       }\r
+}\r
index 49539cda6fa1a38cd37a136ac577565f86be4ec6..5c8bae2d75445c85b857986ab396b34d68a1683d 100644 (file)
@@ -52,6 +52,9 @@ namespace System.Data {
                private int defaultColumnIndex = 1;
                //table should be the DataTable this DataColumnCollection belongs to.
                private DataTable parentTable = null;
+               // Keep reference to most recent columns passed to AddRange()
+               // so that they can be added when EndInit() is called.
+               DataColumn[] _mostRecentColumns = null;
 
                // Internal Constructor.  This Class can only be created from other classes in this assembly.
                internal DataColumnCollection(DataTable table):base()
@@ -66,6 +69,9 @@ namespace System.Data {
                {
                        get
                        {
+                               if (index < 0 || index > base.List.Count) {
+                                       throw new IndexOutOfRangeException("Cannot find column " + index + ".");
+                               }
                                return (DataColumn) base.List[index];
                        }
                }
@@ -132,7 +138,7 @@ namespace System.Data {
                        return column;
                }
 
-               private void RegisterName(string name, DataColumn column)
+               internal void RegisterName(string name, DataColumn column)
                {
                        if (columnFromName.Contains(name))
                                throw new DuplicateNameException("A DataColumn named '" + name + "' already belongs to this DataTable.");
@@ -149,7 +155,7 @@ namespace System.Data {
                        }
                }
 
-               private void UnregisterName(string name)
+               internal void UnregisterName(string name)
                {
                        if (columnFromName.Contains(name))
                                columnFromName.Remove(name);
@@ -291,11 +297,18 @@ namespace System.Data {
                /// <param name="columns">The array of DataColumn objects to add to the collection.</param>
                public void AddRange(DataColumn[] columns)
                {
+                       if (parentTable.fInitInProgress){
+                               _mostRecentColumns = columns;
+                               return;
+                       }
+
+                       if (columns == null)
+                               return;
+
                        foreach (DataColumn column in columns)
                        {
                                Add(column);
                        }
-                       return;
                }
 
                /// <summary>
@@ -307,32 +320,38 @@ namespace System.Data {
                {
                                                
                        //Check that the column does not have a null reference.
-                       if (column == null)
-                                return false;
+                       if (column == null) 
+                       {
+                return false;
+                       }
 
                        
                        //Check that the column is part of this collection.
-                       if (!Contains(column.ColumnName))
+                       if (parentTable != column.Table) 
                        {
                                return false;
                        }
 
+                       parentTable.OnRemoveColumn(column);
 
+                       UniqueConstraint primaryKey = parentTable.PrimaryKeyConstraint;
+                       if (primaryKey != null && primaryKey.IsColumnContained(column))
+                               return false;
                        
                        //Check if this column is part of a relationship. (this could probably be written better)
                        foreach (DataRelation childRelation in parentTable.ChildRelations)
                        {
-                               foreach (DataColumn childColumn in childRelation.ChildColumns)
+                               foreach (DataColumn childColumn in childRelation.ChildColumns) 
                                {
-                                       if (childColumn == column)
+                                       if (childColumn == column) 
                                        {
                                                return false;
                                        }
                                }
 
-                               foreach (DataColumn parentColumn in childRelation.ParentColumns)
+                               foreach (DataColumn parentColumn in childRelation.ParentColumns) 
                                {
-                                       if (parentColumn == column)
+                                       if (parentColumn == column) 
                                        {
                                                return false;
                                        }
@@ -340,66 +359,67 @@ namespace System.Data {
                        }
 
                        //Check if this column is part of a relationship. (this could probably be written better)
-                       foreach (DataRelation parentRelation in parentTable.ParentRelations)
+                       foreach (DataRelation parentRelation in parentTable.ParentRelations) 
                        {
-                               foreach (DataColumn childColumn in parentRelation.ChildColumns)
+                               foreach (DataColumn childColumn in parentRelation.ChildColumns) 
                                {
-                                       if (childColumn == column)
+                                       if (childColumn == column) 
                                        {
                                                return false;
                                        }
                                }
 
-                               foreach (DataColumn parentColumn in parentRelation.ParentColumns)
+                               foreach (DataColumn parentColumn in parentRelation.ParentColumns) 
                                {
-                                       if (parentColumn == column)
+                                       if (parentColumn == column) 
                                        {
                                                return false;
                                        }
                                }
                        }
 
+                       //TODO: check constraints
+                       for (int i = 0; i < parentTable.Constraints.Count; i++) {
+                               if (parentTable.Constraints[i].IsColumnContained(column))
+                                       return false;
+                       }
+
+                       if (parentTable.DataSet != null) {
+                               //FIXME: check whether some parent key in ForeignConstriants contains
+                               // the column
+                       }
+
                        
                        //Check if another column's expression depends on this column.
                        
-                       foreach (DataColumn dataColumn in List)
+                       foreach (DataColumn dataColumn in List) 
                        {
-                               if (dataColumn.Expression.ToString().IndexOf(column.ColumnName) > 0)
+                               if (dataColumn.CompiledExpression != null && 
+                                               dataColumn.CompiledExpression.DependsOn(column)) 
                                {
                                        return false;
                                }
                        }
-                       
-                        // check for part of pk
-                        UniqueConstraint uc = UniqueConstraint.GetPrimaryKeyConstraint (parentTable.Constraints);
-                        if (uc != null && uc.Contains (column)) 
-                                throw new ArgumentException (String.Format ("Cannot remove column {0}, because" +
-                                                             " it is part of primarykey",
-                                                             column.ColumnName));
-                        // check for part of fk
-                        DataSet ds = parentTable.DataSet;
-                        
-                        if (ds != null) {
-                                foreach (DataTable t in ds.Tables) {
-                                        if (t == parentTable)
-                                                continue;
-                                        foreach (Constraint c in t.Constraints) {
-                                                if (! (c is ForeignKeyConstraint))
-                                                        continue;
-                                                ForeignKeyConstraint fk = (ForeignKeyConstraint) c;
-                                                if (fk.Contains (column, true)      // look in parent
-                                                    || fk.Contains (column, false)) // look in children
-                                                        throw new ArgumentException (String.Format ("Cannot remove column {0}, because" +
-                                                                                     " it is part of foreign key constraint",
-                                                                                     column.ColumnName));
-                                                
-                                        }
-                                        
-                                }
-                                
-                                
-                        }
-                        
+            // check for part of pk
+            UniqueConstraint uc = UniqueConstraint.GetPrimaryKeyConstraint (parentTable.Constraints);
+            if (uc != null && uc.IsColumnContained(column)) {
+               return false;
+                       }
+            // check for part of fk
+            DataSet ds = parentTable.DataSet;            
+            if (ds != null) {
+                foreach (DataTable t in ds.Tables) {
+                    if (t == parentTable)
+                        continue;
+                    foreach (Constraint c in t.Constraints) {
+                        if (! (c is ForeignKeyConstraint))
+                            continue;
+                        ForeignKeyConstraint fk = (ForeignKeyConstraint) c;
+                        if (fk.IsColumnContained(column))
+                                return false;                        
+                    }                        
+                }                                        
+            }                    
                        return true;
                }
 
@@ -410,19 +430,15 @@ namespace System.Data {
                {
                        CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Refresh, this);
 
-
                        // FIXME: Hmm... This loop could look little nicer :)
                        foreach (DataColumn Col in List) {
-
                                foreach (DataRelation Rel in Col.Table.ParentRelations) {
-
                                        foreach (DataColumn Col2 in Rel.ParentColumns) {
                                                if (Object.ReferenceEquals (Col, Col2))
                                                        throw new ArgumentException ("Cannot remove this column, because " + 
                                                                                     "it is part of the parent key for relationship " + 
                                                                                     Rel.RelationName + ".");
                                        }
-
                                        foreach (DataColumn Col2 in Rel.ChildColumns) {
                                                if (Object.ReferenceEquals (Col, Col2))
                                                        throw new ArgumentException ("Cannot remove this column, because " + 
@@ -433,14 +449,12 @@ namespace System.Data {
                                }
 
                                foreach (DataRelation Rel in Col.Table.ChildRelations) {
-
                                        foreach (DataColumn Col2 in Rel.ParentColumns) {
                                                if (Object.ReferenceEquals (Col, Col2))
                                                        throw new ArgumentException ("Cannot remove this column, because " + 
                                                                                     "it is part of the parent key for relationship " + 
                                                                                     Rel.RelationName + ".");
                                        }
-
                                        foreach (DataColumn Col2 in Rel.ChildColumns) {
                                                if (Object.ReferenceEquals (Col, Col2))
                                                        throw new ArgumentException ("Cannot remove this column, because " + 
@@ -448,23 +462,19 @@ namespace System.Data {
                                                                                     Rel.RelationName + ".");
                                        }
                                }
-
                        }
 
-                        // whether all columns can be removed
-                        foreach (DataColumn col in this) {
-                                if (!CanRemove (col))
-                                        throw new ArgumentException ("Cannot remove column {0}", col.ColumnName);
-                        }
-
-                       try {
-                               columnFromName.Clear();
-                               autoIncrement.Clear();
-                               base.List.Clear();
-                               OnCollectionChanged(e);
-                       } catch (Exception ex) {
-                               throw new ArgumentException (ex.Message, ex);
-                       }
+            // whether all columns can be removed
+            foreach (DataColumn col in this) {
+                if (!CanRemove (col))
+                    throw new ArgumentException ("Cannot remove column {0}", col.ColumnName);
+            }
+
+                       columnFromName.Clear();
+                       autoIncrement.Clear();
+                       base.List.Clear();
+                       OnCollectionChanged(e);
+
                }
 
                /// <summary>
@@ -511,6 +521,7 @@ namespace System.Data {
                /// <param name="ccevent">A CollectionChangeEventArgs that contains the event data.</param>
                protected virtual void OnCollectionChanged(CollectionChangeEventArgs ccevent)
                {
+                       parentTable.ResetPropertyDescriptorsCache();
                        if (CollectionChanged != null) 
                        {
                                CollectionChanged(this, ccevent);
@@ -592,6 +603,13 @@ namespace System.Data {
                        Remove(column);
                }
 
+               // Helper AddRange() - Call this function when EndInit is called
+               internal void PostEndInit() {
+                       DataColumn[] cols = _mostRecentColumns;
+                       _mostRecentColumns = null;
+                       AddRange (cols);
+               }
+
 
                /// <summary>
                ///  Do the same as Constains -method but case sensitive
index 2c85a6f06609e093cd73b9c2ae59e766a8be03a9..9501d8ed6ee77c56d099e72593577262081cf337 100755 (executable)
@@ -51,6 +51,15 @@ namespace System.Data
                        this.columnIndex = columnIndex;
                }
 
+               public DataColumnPropertyDescriptor (DataColumn dc)
+                       : base (dc.ColumnName, null) 
+               {
+                       this.columnIndex = dc.Ordinal;
+                       this.componentType = typeof(DataRowView);
+                       this.propertyType = dc.DataType;
+                       this.readOnly = dc.ReadOnly;
+               }
+
                public void SetReadOnly (bool value) 
                {
                        readOnly = value;
@@ -66,29 +75,6 @@ namespace System.Data
                        propertyType = type;
                }
 
-               private PropertyInfo GetPropertyInfo () 
-               {
-                       string defaultMemberName = "";
-                       object[] attribs = componentType.GetCustomAttributes (true);
-                                               
-                       for (int at = 0; at < attribs.Length; at++) {
-                               if (attribs[at] is DefaultMemberAttribute) {
-                                       defaultMemberName = ((DefaultMemberAttribute) attribs[at]).MemberName;
-                                       break;
-                               }
-                       }
-
-                       // FIXME: what do I do if a DefaultMemeberAttribute is not found?
-                       //        should I try looking for DefaultPropertyAttribute?
-                       if (defaultMemberName.Equals(""))
-                               throw new SystemException("Default property not found.");
-
-                       Type[] parmTypes = new Type[1];
-                       parmTypes[0] = propertyType;
-                       PropertyInfo propertyInfo = componentType.GetProperty (defaultMemberName, parmTypes);
-                       return propertyInfo;
-               }
-
                public override object GetValue (object component) 
                {
                        // FIXME: what is the correct way to Get a Value?
index c2768776b96c3f6085f25cbc156353aace61e068..07fba67385d3438a336f5d178366dc33c579e952 100644 (file)
@@ -258,98 +258,97 @@ namespace System.Data
                        return relationName;
                }
                 
-                internal void UpdateConstraints ()
-                {
-                        if ( ! createConstraints)
-                                return;
-                        
-                        ForeignKeyConstraint    foreignKeyConstraint    = null;
-                        UniqueConstraint        uniqueConstraint        = null;
-                        
-                        foreignKeyConstraint    = FindForeignKey (ChildTable.Constraints);
-                        uniqueConstraint        = FindUniqueConstraint (ParentTable.Constraints); 
-
-                        // if we did not find the unique constraint in the parent table.
-                        // we generate new uniqueConstraint and add it to the parent table.
-                        if (uniqueConstraint == null) {
-                                uniqueConstraint = new UniqueConstraint (ParentColumns, false);
-                                ParentTable.Constraints.Add (uniqueConstraint);
-                        }
-                     
-                        // if we did not find the foreign key constraint in the parent table.
-                        // we generate new foreignKeyConstraint and add it to the parent table.
-                        if (foreignKeyConstraint == null) {
-                                foreignKeyConstraint = new ForeignKeyConstraint (RelationName, 
-                                                                                 ParentColumns, 
-                                                                                 ChildColumns);
-                                ChildTable.Constraints.Add (foreignKeyConstraint);
-                        }
-
-                        SetParentKeyConstraint (uniqueConstraint);
-                        SetChildKeyConstraint (foreignKeyConstraint);
-                }
-
-                private static bool CompareDataColumns (DataColumn [] dc1, DataColumn [] dc2)
-                {
-                        if (dc1.Length != dc2.Length)
-                                return false;
-
-                        for (int columnCnt = 0; columnCnt < dc1.Length; ++columnCnt){
-                                if (dc1 [columnCnt] != dc2 [columnCnt])
-                                         return false;
-                        }
-                        return true;
-                }
+        internal void UpdateConstraints ()
+        {
+            if ( ! createConstraints)
+                return;
+            
+            ForeignKeyConstraint    foreignKeyConstraint    = null;
+            UniqueConstraint        uniqueConstraint        = null;
+            
+            foreignKeyConstraint    = FindForeignKey (ChildTable.Constraints);
+            uniqueConstraint        = FindUniqueConstraint (ParentTable.Constraints); 
+
+            // if we did not find the unique constraint in the parent table.
+            // we generate new uniqueConstraint and add it to the parent table.
+            if (uniqueConstraint == null) {
+                uniqueConstraint = new UniqueConstraint (ParentColumns, false);
+                ParentTable.Constraints.Add (uniqueConstraint);
+            }
+            
+            // if we did not find the foreign key constraint in the parent table.
+            // we generate new foreignKeyConstraint and add it to the parent table.
+            if (foreignKeyConstraint == null) {
+                foreignKeyConstraint = new ForeignKeyConstraint (RelationName, 
+                                                                    ParentColumns, 
+                                                                    ChildColumns);
+                ChildTable.Constraints.Add (foreignKeyConstraint);
+            }
+
+            SetParentKeyConstraint (uniqueConstraint);
+            SetChildKeyConstraint (foreignKeyConstraint);
+        }
+
+        private static bool CompareDataColumns (DataColumn [] dc1, DataColumn [] dc2)
+        {
+            if (dc1.Length != dc2.Length)
+                return false;
+
+            for (int columnCnt = 0; columnCnt < dc1.Length; ++columnCnt){
+                if (dc1 [columnCnt] != dc2 [columnCnt])
+                    return false;
+            }
+            return true;
+        }
+        
+        private ForeignKeyConstraint FindForeignKey (ConstraintCollection cl)
+        {
+            ForeignKeyConstraint fkc = null; 
+            foreach (Constraint o in cl) {
+                if (! (o is ForeignKeyConstraint))
+                    continue;
+                fkc = (ForeignKeyConstraint) o;
+                /* Check ChildColumns & ParentColumns */
+                if (CompareDataColumns (ChildColumns, fkc.Columns) && 
+                    CompareDataColumns (ParentColumns, fkc.RelatedColumns))
+                    return fkc;
+            }
+            return null;
+        }
+
+        private UniqueConstraint FindUniqueConstraint (ConstraintCollection cl)
+        {
+            UniqueConstraint uc = null;
+            // find if the unique constraint already exists in the parent table.
+            foreach (Constraint o in cl){
+                if (! (o is UniqueConstraint))
+                    continue;
+                uc = (UniqueConstraint) o;
+                //Check in ParentColumns
+                if (CompareDataColumns (ParentColumns, uc.Columns))
+                    return uc;
+            }
+            return null;
+        }
+
+        /// <summary>
+        ///     Check whether the given column is part of this relation.
+        /// <summary>
+        /// <returns>
+        ///     true if the column is part of this relation, otherwise false.
+        /// </returns>
+        internal bool Contains (DataColumn column)
+        {
+            foreach (DataColumn col in ParentColumns)
+                if (col == column)
+                    return true;
+
+            foreach (DataColumn col in ChildColumns)
+                if (col == column)
+                    return true;
+            return false;
+        }
                 
-                private ForeignKeyConstraint FindForeignKey (ConstraintCollection cl)
-                {
-                        ForeignKeyConstraint fkc = null; 
-                        foreach (Constraint o in cl) {
-                                if (! (o is ForeignKeyConstraint))
-                                        continue;
-                                fkc = (ForeignKeyConstraint) o;
-                                /* Check ChildColumns & ParentColumns */
-                                if (CompareDataColumns (ChildColumns, fkc.Columns) && 
-                                    CompareDataColumns (ParentColumns, fkc.RelatedColumns))
-                                        return fkc;
-                        }
-                        return null;
-                }
-
-                private UniqueConstraint FindUniqueConstraint (ConstraintCollection cl)
-                {
-                        UniqueConstraint uc = null;
-                        // find if the unique constraint already exists in the parent table.
-                        foreach (Constraint o in cl){
-                                if (! (o is UniqueConstraint))
-                                        continue;
-                                uc = (UniqueConstraint) o;
-                                //Check in ParentColumns
-                                if (CompareDataColumns (ParentColumns, uc.Columns))
-                                        return uc;
-                        }
-                        return null;
-                }
-
-                /// <summary>
-                ///     Check whether the given column is part of this relation.
-                /// <summary>
-                /// <returns>
-                ///     true if the column is part of this relation, otherwise false.
-                /// </returns>
-                internal bool Contains (DataColumn column)
-                {
-                        foreach (DataColumn col in ParentColumns)
-                                if (col == column)
-                                        return true;
-
-                        foreach (DataColumn col in ChildColumns)
-                                if (col == column)
-                                        return true;
-                        return false;
-                }
-                
-
                #endregion // Methods
        }
 }
index 097ff94621ca33e5ba964ae161ea7c8cf26ad3b6..3350a3d0e6dcec5d9dbe465cca3295de3334e91a 100644 (file)
@@ -64,31 +64,6 @@ namespace System.Data {
                                this.dataSet = dataSet;
                        }
 
-                       /// <summary>
-                       /// Gets the DataRelation object specified by name.
-                       /// </summary>
-                       public override DataRelation this [string name]
-                       {
-                               get {
-                                       int index = IndexOf (name, true);
-                                       return index < 0 ? null : (DataRelation) List[index];
-                               }
-                       }
-
-                       /// <summary>
-                       /// Gets the DataRelation object at the specified index.
-                       /// </summary>
-                       public override DataRelation this [int index]
-                       {
-                               get {
-                                       try {
-                                               return List [index] as DataRelation;
-                                       } catch (ArgumentOutOfRangeException e) {
-                                               throw new IndexOutOfRangeException (String.Format ("Cannot find relation {0}.", index));
-                                       }
-                               }
-                       }
-
                        protected override DataSet GetDataSet()
                        {
                                return dataSet;
@@ -100,30 +75,25 @@ namespace System.Data {
                        /// <param name="relation">The relation to check.</param>
                        protected override void AddCore (DataRelation relation)
                        {
-                                if (relation.ChildTable.DataSet != this.dataSet 
+                               if (relation.ChildTable.DataSet != this.dataSet 
                                      || relation.ParentTable.DataSet != this.dataSet)
                                   throw new DataException ();
-                                relation.SetDataSet (dataSet);
-                                relation.ParentTable.ChildRelations.Add (relation);
-                                relation.ChildTable.ParentRelations.Add (relation);
-                                 base.AddCore (relation);
-                        }
+                                                               
+                               base.AddCore (relation);
+                               relation.ParentTable.ChildRelations.Add (relation);
+                               relation.ChildTable.ParentRelations.Add (relation);                
+                               relation.SetDataSet (dataSet);
+                               relation.UpdateConstraints ();
+            }
 
                        public override void AddRange (DataRelation[] relations)
                        {
                                base.AddRange (relations);
                        }
 
-                       public override void 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);
@@ -153,31 +123,6 @@ namespace System.Data {
                                this.dataTable = dataTable;
                        }
 
-                       /// <summary>
-                       /// Gets the DataRelation object specified by name.
-                       /// </summary>
-                       public override DataRelation this [string name]
-                       {
-                               get {
-                                       int index = IndexOf (name, true);
-                                       return index < 0 ? null : (DataRelation) List[index];
-                               }
-                       }
-
-                       /// <summary>
-                       /// Gets the DataRelation object at the specified index.
-                       /// </summary>
-                       public override DataRelation this [int index]
-                       {
-                               get {
-                                       try {
-                                               return List [index] as DataRelation;
-                                       } catch (ArgumentOutOfRangeException e) {
-                                               throw new IndexOutOfRangeException (String.Format ("Cannot find relation {0}.", index));
-                                       }
-                               }
-                       }
-
                        protected override DataSet GetDataSet()
                        {
                                return dataTable.DataSet;
@@ -189,22 +134,24 @@ namespace System.Data {
                        /// <param name="relation">The relation to check.</param>
                        protected override void AddCore (DataRelation relation)
                        {
-                                if (dataTable.ParentRelations == this && relation.ChildTable != dataTable)
-                                                throw new ArgumentException ("Cannot add a relation to this table's " +
-                                                                             "ParentRelations where this table is not" +
-                                                                             " the Child table.");
-
-                                if (dataTable.ChildRelations == this && relation.ParentTable != dataTable)   
-                                                throw new ArgumentException("Cannot add a relation to this table's " +
-                                                                            "ChildRelations where this table is not" +
-                                                                            " the Parent table.");
-                                
-                                base.AddCore (relation);
+                if (dataTable.ParentRelations == this && relation.ChildTable != dataTable)
+                    throw new ArgumentException ("Cannot add a relation to this table's " +
+                                                                                                       "ParentRelations where this table is not" +
+                                                                                                       " the Child table.");
+
+                if (dataTable.ChildRelations == this && relation.ParentTable != dataTable)   
+                    throw new ArgumentException("Cannot add a relation to this table's " +
+                                                "ChildRelations where this table is not" +
+                                                " the Parent table.");
+                
+                               dataTable.DataSet.Relations.Add(relation);
+                base.AddCore (relation);
 
                        }
                         
                        protected override void RemoveCore (DataRelation relation)
                        {
+                               relation.DataSet.Relations.Remove(relation);
                                base.RemoveCore (relation);
                        }
 
@@ -216,7 +163,7 @@ namespace System.Data {
                }
 
                private int defaultNameIndex;
-               private bool inTransition;
+               private DataRelation inTransition;
                int index;
 
                
@@ -226,19 +173,31 @@ namespace System.Data {
                protected DataRelationCollection () 
                        : base ()
                {
+                       inTransition = null;
                        defaultNameIndex = 1;
-                       inTransition = false;
                }
 
                /// <summary>
                /// Gets the DataRelation object specified by name.
                /// </summary>
-               public abstract DataRelation this[string name]{get;}
+               public DataRelation this [string name] {
+                       get {
+                               int index = IndexOf (name, true);
+                               return index < 0 ? null : (DataRelation) List[index];
+                       }
+               }
 
                /// <summary>
                /// Gets the DataRelation object at the specified index.
                /// </summary>
-               public abstract DataRelation this[int index]{get;}
+               public DataRelation this [int index] {
+                       get {
+                               if (index < 0 || index >= List.Count)
+                                       throw new IndexOutOfRangeException (String.Format ("Cannot find relation {0}.", index));
+
+                               return (DataRelation)List [index];
+                       }
+               }
 
                
                #region Add Methods
@@ -259,31 +218,30 @@ namespace System.Data {
                [MonoTODO]
                public void Add(DataRelation relation)
                {
-                        if (relation == null) {
-                               //TODO: Issue a good exception message.
-                               throw new ArgumentNullException();
+            // To prevent endless recursion
+                       if(inTransition == relation) {
+                               return; 
                        }
-                       if(List.IndexOf(relation) != -1) {
-                               //TODO: Issue a good exception message.
-                               throw new ArgumentException();
+                       else { 
+                               inTransition = relation; 
                        }
 
-                       // check if the collection has a relation with the same name.
-                       int tmp = IndexOf(relation.RelationName);
-                       // if we found a relation with same name we have to check
-                       // that it is the same case.
-                       // indexof can return a table with different case letters.
-                       if (tmp != -1 &&
-                               relation.RelationName == this[tmp].RelationName)
-                                       throw new DuplicateNameException("A DataRelation named '" + relation.RelationName + "' already belongs to this DataSet.");
-                        
-
-                       this.AddCore (relation);
-                       if(relation.RelationName == string.Empty)
-                               relation.RelationName = GenerateRelationName();
-                       CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
-                       //List.Add(relation);
-                       OnCollectionChanged(e);
+                       try
+                       {
+                               this.AddCore (relation);
+                               if(relation.RelationName == string.Empty)
+                                       relation.RelationName = GenerateRelationName();
+                       
+                               relation.ParentTable.ResetPropertyDescriptorsCache();
+                               relation.ChildTable.ResetPropertyDescriptorsCache();
+                       
+                               CollectionChangeEventArgs e = new CollectionChangeEventArgs(CollectionChangeAction.Add, this);
+                               OnCollectionChanged(e);
+                       }
+                       finally
+                       {
+                               inTransition = null;
+                       }
                }
 
                private string GenerateRelationName()
@@ -411,7 +369,25 @@ namespace System.Data {
                [MonoTODO]
                protected virtual void AddCore(DataRelation relation)
                {
-                        relation.UpdateConstraints ();
+                       if (relation == null) {
+                               //TODO: Issue a good exception message.
+                               throw new ArgumentNullException();
+                       }
+                       if(List.IndexOf(relation) != -1) {
+                               //TODO: Issue a good exception message.
+                               throw new ArgumentException();
+                       }
+
+                       // check if the collection has a relation with the same name.
+                       int tmp = IndexOf(relation.RelationName);
+                       // if we found a relation with same name we have to check
+                       // that it is the same case.
+                       // indexof can return a table with different case letters.
+                       if (tmp != -1 &&
+                               relation.RelationName == this[tmp].RelationName)
+                                       throw new DuplicateNameException("A DataRelation named '" + relation.RelationName + "' already belongs to this DataSet.");
+                        
+                       // Add to collection
                        List.Add(relation);
                }
                 
@@ -421,6 +397,8 @@ namespace System.Data {
                /// <param name="relations">The array of DataRelation objects to add to the collection.</param>
                public virtual void AddRange(DataRelation[] relations)
                {
+                       if (relations == null)
+                               return;
                        foreach (DataRelation relation in relations) Add(relation);
                }
 
@@ -447,6 +425,9 @@ namespace System.Data {
 
                public virtual void Clear()
                {
+                       for (int i = 0; i < Count; i++)
+                               Remove(this[i]);
+
                        List.Clear();
                }
 
@@ -507,37 +488,57 @@ namespace System.Data {
 
                public void Remove (DataRelation relation)
                {
+                       // To prevent endless recursion
+                       if(inTransition == relation) {
+                               return; 
+                       }
+                       else { 
+                               inTransition = relation; 
+                       }
+
                        if (relation == null)
                                return;
 
-                        // check if the list doesnot contains this relation.
-                        if (!(List.Contains(relation)))
-                                throw new ArgumentException("Relation doesnot belong to this Collection.");
+                       try
+                       {
+                               // check if the list doesnot contains this relation.
+                               if (!(List.Contains(relation)))
+                                       throw new ArgumentException("Relation doesnot belong to this Collection.");
+
+                               RemoveCore (relation);
+                               string name = "Relation" + index;
+                               if (relation.RelationName == name)
+                                       index--;
 
-                       RemoveCore (relation);
-                       List.Remove (relation);
-                       string name = "Relation" + index;
-                       if (relation.RelationName == name)
-                               index--;
-                       OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
+                               OnCollectionChanged (CreateCollectionChangeEvent (CollectionChangeAction.Remove));
+                       }
+                       finally
+                       {
+                               inTransition = null;
+                       }
                }
 
                public void Remove (string name)
                {
-                       Remove ((DataRelation) List[IndexOf (name)]);
+                       DataRelation relation = this[name];
+                       if (relation == null)
+                               throw new ArgumentException("Relation doesnot belong to this Collection.");
+                       Remove(relation);
                }
 
                public void RemoveAt (int index)
-               {
-                       if (( index < 0 ) || (index >=List.Count))
-                                throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
-                       Remove(this[index]);
+               {               
+                       DataRelation relation = this[index];
+                       if (relation == null)
+                               throw new IndexOutOfRangeException(String.Format("Cannot find relation {0}", index));
+                       Remove(relation);
                }
 
                [MonoTODO]
                protected virtual void RemoveCore(DataRelation relation)
                {
-                       // TODO: What have to be done?
+                       // Remove from collection
+                       List.Remove(relation);
                }
 
                #region Events
diff --git a/mcs/class/System.Data/System.Data/DataRelationPropertyDescriptor.cs b/mcs/class/System.Data/System.Data/DataRelationPropertyDescriptor.cs
new file mode 100644 (file)
index 0000000..0daa973
--- /dev/null
@@ -0,0 +1,99 @@
+using System;\r
+using System.ComponentModel;\r
+\r
+namespace System.Data\r
+{\r
+       internal class DataRelationPropertyDescriptor : PropertyDescriptor\r
+       {\r
+               #region Fields\r
+\r
+               DataRelation _relation;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               internal DataRelationPropertyDescriptor(DataRelation relation) : base(relation.RelationName,null)\r
+               {\r
+                       _relation = relation;\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Properties\r
+\r
+               public override Type ComponentType \r
+               { \r
+                       get {\r
+                               return typeof(DataRowView);\r
+                       }\r
+               }\r
+\r
+               public override bool IsReadOnly \r
+               { \r
+                       get {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               public override Type PropertyType \r
+               { \r
+                       get {\r
+                               return typeof(IBindingList);\r
+                       }\r
+               }\r
+\r
+               public DataRelation Relation \r
+               { \r
+                       get {\r
+                               return _relation;\r
+                       }\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+\r
+               public override bool CanResetValue(object obj)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               public override bool Equals(object obj)\r
+               {\r
+                       DataRelationPropertyDescriptor descriptor = obj as DataRelationPropertyDescriptor;\r
+\r
+                       if (descriptor == null) {\r
+                               return false;\r
+                       }\r
+\r
+                       return (Relation == descriptor.Relation);\r
+               }\r
+\r
+               public override int GetHashCode()\r
+               {\r
+                       return _relation.GetHashCode();\r
+               }\r
+\r
+        public override object GetValue(object obj)\r
+               {\r
+                       DataRowView dr = (DataRowView)obj;\r
+                       return dr.CreateChildView(Relation);\r
+               }\r
+\r
+               public override void ResetValue(object obj)\r
+               {\r
+               }\r
+\r
+               public override void SetValue(object obj, object val)\r
+               {\r
+               }\r
+\r
+               public override bool ShouldSerializeValue(object obj)\r
+               {\r
+                       return false;\r
+               }\r
+\r
+               #endregion // Methods\r
+       }\r
+}\r
index a899d7fa9b24eec491626a91bf779ce5f4a760ad..66154c183e85978e00bdd193d117bed8bebbbc34 100644 (file)
@@ -43,6 +43,8 @@ using System.Collections;
 using System.Globalization;
 using System.Xml;
 
+using System.Data.Common;
+
 namespace System.Data {
        /// <summary>
        /// Represents a row of data in a DataTable.
@@ -60,11 +62,9 @@ namespace System.Data {
 
                private ArrayList _columnErrors;
                private string rowError;
-               private DataRowState rowState;
                internal int xmlRowID = 0;
                internal bool _nullConstraintViolation;
                private string _nullConstraintMessage;
-               private bool editing = false;
                private bool _hasParentCollection;
                private bool _inChangingEvent;
                private int _rowId;
@@ -86,23 +86,8 @@ namespace System.Data {
                        // Get the row id from the builder.
                        _rowId = builder._rowId;
 
-                       _proposed = _table.RecordCache.NewRecord();
-                       // Initialise the data columns of the row with the dafault values, if any 
-                       // TODO : should proposed version be available immediately after record creation ?
-                       foreach(DataColumn column in _table.Columns) {
-                               column.DataContainer.CopyValue(_table.DefaultValuesRowIndex,_proposed);
-                       }
-                       
                        rowError = String.Empty;
 
-                       //on first creating a DataRow it is always detached.
-                       rowState = DataRowState.Detached;
-                       
-                       ArrayList aiColumns = _table.Columns.AutoIncrmentColumns;
-                       foreach (DataColumn dc in aiColumns) {
-                               this [dc] = dc.AutoIncrementValue();
-                       }
-
                        // create mapped XmlDataElement
                        DataSet ds = _table.DataSet;
                        if (ds != null && ds._xmlDataDocument != null)
@@ -186,7 +171,7 @@ namespace System.Data {
                        set {
                                if (columnIndex < 0 || columnIndex > _table.Columns.Count)
                                        throw new IndexOutOfRangeException ();
-                               if (rowState == DataRowState.Deleted)
+                               if (RowState == DataRowState.Deleted)
                                        throw new DeletedRowInaccessibleException ();
 
                                DataColumn column = _table.Columns[columnIndex];
@@ -198,12 +183,12 @@ namespace System.Data {
                                
                                CheckValue (value, column);
 
-                               bool orginalEditing = editing;
+                               bool orginalEditing = Proposed >= 0;
                                if (!orginalEditing) {
                                        BeginEdit ();
                                }
                                
-                               column[_proposed] = value;
+                               column[Proposed] = value;
                                _table.ChangedDataColumn (this, column, value);
                                if (!orginalEditing) {
                                        EndEdit ();
@@ -235,62 +220,6 @@ namespace System.Data {
                        }
                }
 
-                /// <summary>
-                /// Sets the index into the container records for the original version. Apart
-                /// from that, it makes sure it pools the record used earlier if they are not
-                /// used by other versions.
-                /// </summary>
-                internal int Original 
-                {
-                        get { return _original;}
-                        set {
-                                if (_original == value) 
-                                        return;
-                                
-                                if (_original >= 0 
-                                    && _current != _original
-                                    && _proposed != _original)
-                                        Table.RecordCache.DisposeRecord (_original);
-                                _original = value;
-                        }
-                }
-
-                /// <summary>
-                /// Sets the index into the container records for the proposed version. Apart
-                /// from that, it makes sure it pools the record used earlier if they are not
-                /// used by other versions.
-                internal int Proposed
-                {
-                        get { return _proposed;}
-                        set {
-                                if (_proposed == value)
-                                        return;
-                                if (_proposed >= 0
-                                    && _proposed != _current
-                                    && _proposed != _original)
-                                        Table.RecordCache.DisposeRecord (_proposed);
-                                _proposed = value;
-                        }
-                }
-
-                /// <summary>
-                /// Sets the index into the container records for the current version. Apart
-                /// from that, it makes sure it pools the record used earlier if they are not
-                /// used by other versions.
-                internal int Current 
-                {
-                        get { return _current;}
-                        set {
-                                if (_current == value)
-                                        return;
-                                if (_current >= 0
-                                    && _current != _original
-                                    && _current != _proposed)
-                                        Table.RecordCache.DisposeRecord (_current);
-                                _current = value;
-                        }
-                }
-
                 /// <summary>
                 /// Set a value for the column into the offset specified by the version.<br>
                 /// If the value is auto increment or null, necessary auto increment value
@@ -320,25 +249,25 @@ namespace System.Data {
                                if (columnIndex < 0 || columnIndex > _table.Columns.Count)
                                        throw new IndexOutOfRangeException ();
                                // Accessing deleted rows
-                               if (!_inExpressionEvaluation && rowState == DataRowState.Deleted && version != DataRowVersion.Original)
+                               if (!_inExpressionEvaluation && RowState == DataRowState.Deleted && version != DataRowVersion.Original)
                                        throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
                                
                                DataColumn column = _table.Columns[columnIndex];
+                               int recordIndex = IndexFromVersion(version);
+
                                if (column.Expression != String.Empty) {
                                        object o = column.CompiledExpression.Eval (this);
-                                       return Convert.ChangeType (o, column.DataType);
+                                       if (o != null && o != DBNull.Value) {
+                                               o = Convert.ChangeType (o, column.DataType);
+                                       }
+                                       column[recordIndex] = o;
+                                       return column[recordIndex];
                                }
 
-                               if (rowState == DataRowState.Detached && version == DataRowVersion.Default && _proposed < 0)
+                               if (RowState == DataRowState.Detached && version == DataRowVersion.Default && Proposed < 0)
                                        throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
                                
-                               int recordIndex = IndexFromVersion(version);
-
-                               if (recordIndex >= 0) {
-                                       return column[recordIndex];
-                               }
-                               
-                               throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));
+                               return column[recordIndex];
                        }
                }
                
@@ -348,15 +277,15 @@ namespace System.Data {
                public object[] ItemArray {
                        get { 
                                // row not in table
-                               if (rowState == DataRowState.Detached)
+                               if (RowState == DataRowState.Detached)
                                        throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
                                // Accessing deleted rows
-                               if (rowState == DataRowState.Deleted)
+                               if (RowState == DataRowState.Deleted)
                                        throw new DeletedRowInaccessibleException ("Deleted row information cannot be accessed through the row.");
                                
                                object[] items = new object[_table.Columns.Count];
                                foreach(DataColumn column in _table.Columns) {
-                                       items[column.Ordinal] = column[_current];
+                                       items[column.Ordinal] = column[Current];
                                }
                                return items;
                        }
@@ -364,41 +293,54 @@ namespace System.Data {
                                if (value.Length > _table.Columns.Count)
                                        throw new ArgumentException ();
 
-                               if (rowState == DataRowState.Deleted)
+                               if (RowState == DataRowState.Deleted)
                                        throw new DeletedRowInaccessibleException ();
                                
-                               bool orginalEditing = editing;
-                               if (!orginalEditing) { 
-                                       BeginEdit ();
-                               }
-                               object newVal = null;
+                               BeginEdit ();
+
                                DataColumnChangeEventArgs e = new DataColumnChangeEventArgs();
                                foreach(DataColumn column in _table.Columns) {
                                        int i = column.Ordinal;
-                                       newVal = (i < value.Length) ? value[i] : null;
+                                       object newVal = (i < value.Length) ? value[i] : null;
+
+                                       if (newVal == null)
+                                               continue;
                                        
                                        e.Initialize(this, column, newVal);
-                                       _table.RaiseOnColumnChanged(e);
                                        CheckValue (e.ProposedValue, column);
-                                       column[_proposed] = e.ProposedValue;
-                               }
-                               if (!orginalEditing) {
-                                       EndEdit ();
+                                       _table.RaiseOnColumnChanging(e);
+                                       column[Proposed] = e.ProposedValue;
+                                       _table.RaiseOnColumnChanged(e);
                                }
+                               
+                               EndEdit ();
                        }
                }
 
-               internal bool IsEditing {
-                       get { return editing; }
-               }
-
                /// <summary>
                /// Gets the current state of the row in regards to its relationship to the
                /// DataRowCollection.
                /// </summary>
                public DataRowState RowState {
                        get { 
-                               return rowState; 
+                               //return rowState; 
+                                 if ((Original == -1) && (Current == -1))
+                                       {
+                                               return DataRowState.Detached;
+                                       }
+                                       if (Original == Current)
+                                       {
+                                               return DataRowState.Unchanged;
+                                       }
+                                       if (Original == -1)
+                                       {
+                                               return DataRowState.Added;
+                                       }
+                                       if (Current == -1)
+                                       {
+                                               return DataRowState.Deleted;
+                                       }
+                                       return DataRowState.Modified;
                        }
                }
 
@@ -436,31 +378,107 @@ namespace System.Data {
                        }
                }
 
-               #endregion // Properties
+               internal int Original
+               {
+                       get {
+                               return _original;
+                       }
+                       set {
+                               if (Table != null) {
+                                       //Table.RecordCache[_original] = null;
+                                       Table.RecordCache[value] = this;
+                               }
+                               _original = value;
+                       }
+               }
+
+               internal int Current
+               {
+                       get {
+                               return _current;
+                       }
+                       set {
+                               if (Table != null) {
+                                       //Table.RecordCache[_current] = null;
+                                       Table.RecordCache[value] = this;
+                               }
+                               _current = value;
+                       }
+               }
+
+               internal int Proposed
+               {
+                       get {
+                               return _proposed;
+                       }
+                       set {
+                               if (Table != null) {
+                                       //Table.RecordCache[_proposed] = null;
+                                       Table.RecordCache[value] = this;
+                               }
+                               _proposed = value;
+                       }
+               }
+
+               #endregion
 
                #region Methods
 
                //FIXME?: Couldn't find a way to set the RowState when adding the DataRow
                //to a Datatable so I added this method. Delete if there is a better way.
                internal void AttachRow() {
-                       if (_current >= 0) {
-                               Table.RecordCache.DisposeRecord(_current);
+                       if (Proposed != -1) {
+                               if (Current >= 0) {
+                                       Table.RecordCache.DisposeRecord(Current);
+                               }
+                               Current = Proposed;
+                               Proposed = -1;
                        }
-                       _current = _proposed;
-                       _proposed = -1;
-                       rowState = DataRowState.Added;
                }
 
                //FIXME?: Couldn't find a way to set the RowState when removing the DataRow
                //from a Datatable so I added this method. Delete if there is a better way.
                internal void DetachRow() {
-                       if (_proposed >= 0) {
-                               _table.RecordCache.DisposeRecord(_proposed);
-                               _proposed = -1;
+                       if (Proposed >= 0) {
+                               _table.RecordCache.DisposeRecord(Proposed);
+                               if (Proposed == Current) {
+                                       Current = -1;
+                               }
+                               if (Proposed == Original) {
+                                       Original = -1;
+                               }
+                               Proposed = -1;
+                       }
+
+                       if (Current >= 0) {
+                               _table.RecordCache.DisposeRecord(Current);
+                               if (Current == Original) {
+                                       Original = -1;
+                               }
+                               Current = -1;
                        }
+
+                       if (Original >= 0) {
+                               _table.RecordCache.DisposeRecord(Original);
+                               Original = -1;
+                       }
+
                        _rowId = -1;
                        _hasParentCollection = false;
-                       rowState = DataRowState.Detached;
+               }
+
+               internal void ImportRecord(int record)
+               {
+                       if (HasVersion(DataRowVersion.Proposed)) {
+                               Table.RecordCache.DisposeRecord(Proposed);
+                       }
+
+                       Proposed = record;
+
+                       foreach(DataColumn column in Table.Columns.AutoIncrmentColumns) {
+                               column.UpdateAutoIncrementValue(column.DataContainer.GetInt64(Proposed));
+                       }
+
                }
 
                private void CheckValue (object v, DataColumn col) 
@@ -484,43 +502,6 @@ namespace System.Data {
                        }
                }
 
-               internal void SetValuesFromDataRecord(IDataRecord record, int[] mapping)
-               {
-//                     bool orginalEditing = editing;
-//                     if (!orginalEditing) { 
-//                             BeginEdit ();
-//                     }
-                       
-                       if (!HasVersion(DataRowVersion.Proposed)) {
-                               _proposed = Table.RecordCache.NewRecord();
-                       }
-
-                       try {
-                               for(int i=0; i < Table.Columns.Count; i++) {
-                                       DataColumn column = Table.Columns[i];
-                                        if (mapping [i] < 0) { // no mapping
-                                                if (! column.AutoIncrement)
-                                                        column.DataContainer [_proposed] = column.DefaultValue;
-                                                continue;
-                                        }
-
-                                       column.DataContainer.SetItemFromDataRecord(_proposed, record,mapping[i]);
-                                       if ( column.AutoIncrement ) { 
-                                               column.UpdateAutoIncrementValue(column.DataContainer.GetInt64(_proposed));
-                                       }
-                               }
-                       }
-                       catch (Exception e){
-                               Table.RecordCache.DisposeRecord(_proposed);
-                               _proposed = -1;
-                               throw e;
-                       }
-
-//                     if (!orginalEditing) {
-//                             EndEdit ();
-//                     }
-               }
-
                /// <summary>
                /// Gets or sets the custom error description for a row.
                /// </summary>
@@ -535,33 +516,50 @@ namespace System.Data {
 
                internal int IndexFromVersion(DataRowVersion version)
                {
-                       if (HasVersion(version))
-                       {
-                               int recordIndex;
-                               switch (version) {
-                                       case DataRowVersion.Default:
-                                               if (editing || rowState == DataRowState.Detached) {
-                                                       recordIndex = _proposed;
-                                               }
-                                               else {
-                                                       recordIndex = _current;
-                                               }
-                                               break;
-                                       case DataRowVersion.Proposed:
-                                               recordIndex = _proposed;
-                                               break;
-                                       case DataRowVersion.Current:
-                                               recordIndex = _current;
-                                               break;
-                                       case DataRowVersion.Original:
-                                               recordIndex = _original;
-                                               break;
-                                       default:
-                                               throw new ArgumentException ();
-                               }
-                               return recordIndex;
+                       switch (version) {
+                               case DataRowVersion.Default:
+                                       if (Proposed >= 0)
+                                               return Proposed;
+
+                                       if (Current >= 0)
+                                               return Current;
+
+                                       if (Original < 0)
+                                               throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
+
+                                       throw new DeletedRowInaccessibleException("Deleted row information cannot be accessed through the row.");
+
+                               case DataRowVersion.Proposed:
+                                       return AssertValidVersionIndex(version, Proposed);
+                               case DataRowVersion.Current:
+                                       return AssertValidVersionIndex(version, Current);
+                               case DataRowVersion.Original:
+                                       return AssertValidVersionIndex(version, Original);
+                               default:
+                                       throw new DataException ("Version must be Original, Current, or Proposed.");
                        }
-                       return -1;
+               }
+
+               private int AssertValidVersionIndex(DataRowVersion version, int index) {
+                       if (index >= 0)
+                               return index;
+
+                       throw new VersionNotFoundException(String.Format("There is no {0} data to accces.", version));
+               }
+
+               internal DataRowVersion VersionFromIndex(int index) {
+                       if (index < 0)
+                               throw new ArgumentException("Index must not be negative.");
+
+                       // the order of ifs matters
+                       if (index == Current)
+                               return DataRowVersion.Current;
+                       if (index == Original)
+                               return DataRowVersion.Original;
+                       if (index == Proposed)
+                               return DataRowVersion.Proposed;
+
+                       throw new ArgumentException(String.Format("The index {0} does not belong to this row.", index)  );
                }
 
                internal XmlDataDocument.XmlDataElement DataElement {
@@ -574,13 +572,11 @@ namespace System.Data {
                        DataColumn column = _table.Columns[columnName];
                        _table.ChangingDataColumn (this, column, val);
                                
-                       if (_original < 0 || _original == _current) { 
-                               // This really creates a new record version if one does not exist
-                               _original = Table.RecordCache.NewRecord();
+                       if (Original < 0 || Original == Current) { 
+                               Original = Table.RecordCache.NewRecord();
                        }
                        CheckValue (val, column);
-                       column[_original] = val;
-                       rowState = DataRowState.Modified;
+                       column[Original] = val;
                }
 
                /// <summary>
@@ -592,12 +588,16 @@ namespace System.Data {
                        EndEdit(); // in case it hasn't been called
 
                         _table.ChangingDataRow (this, DataRowAction.Commit);
-                       switch (rowState) {
+                       CheckChildRows(DataRowAction.Commit);
+                       switch (RowState) {
                                case DataRowState.Unchanged:
                                        return;
                        case DataRowState.Added:
                        case DataRowState.Modified:
-                               rowState = DataRowState.Unchanged;
+                                       if (Original >= 0) {
+                                               Table.RecordCache.DisposeRecord(Original);
+                                       }
+                                       Original = Current;
                                break;
                        case DataRowState.Deleted:
                                _table.Rows.RemoveInternal (this);
@@ -606,9 +606,6 @@ namespace System.Data {
                        case DataRowState.Detached:
                                throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");
                        }
-                       // Accept from detached
-                       if (_original != _current)
-                               Original = Current;
 
                         _table.ChangedDataRow (this, DataRowAction.Commit);
                }
@@ -620,16 +617,17 @@ namespace System.Data {
                {
                        if (_inChangingEvent)
                                 throw new InRowChangingEventException("Cannot call BeginEdit inside an OnRowChanging event.");
-                       if (rowState == DataRowState.Deleted)
+                       if (RowState == DataRowState.Deleted)
                                throw new DeletedRowInaccessibleException ();
+
                        if (!HasVersion (DataRowVersion.Proposed)) {
-                               _proposed = Table.RecordCache.NewRecord();
-                               foreach(DataColumn column in Table.Columns) {
-                                       column.DataContainer.CopyValue(_current,_proposed);
+                               Proposed = Table.RecordCache.NewRecord();
+                               int from = HasVersion(DataRowVersion.Current) ? Current : Table.DefaultValuesRowIndex;
+                               for(int i = 0; i < Table.Columns.Count; i++){
+                                       DataColumn column = Table.Columns[i];
+                                       column.DataContainer.CopyValue(from,Proposed);
                                }
                        }
-                       // setting editing to true stops validations on the row
-                       editing = true;
                }
 
                /// <summary>
@@ -637,15 +635,13 @@ namespace System.Data {
                /// </summary>
                public void CancelEdit () 
                {
-                        if (_inChangingEvent)
+                        if (_inChangingEvent) {
                                 throw new InRowChangingEventException("Cannot call CancelEdit inside an OnRowChanging event.");
-                       editing = false;
+                        }
+
                        if (HasVersion (DataRowVersion.Proposed)) {
-                               Table.RecordCache.DisposeRecord(_proposed);
-                               _proposed = -1;
-                               if (rowState == DataRowState.Modified) {
-                                   rowState = DataRowState.Unchanged;
-                               }
+                               Table.RecordCache.DisposeRecord(Proposed);
+                               Proposed = -1;
                        }
                }
 
@@ -665,7 +661,7 @@ namespace System.Data {
                public void Delete () 
                {
                        _table.DeletingDataRow(this, DataRowAction.Delete);
-                       switch (rowState) {
+                       switch (RowState) {
                        case DataRowState.Added:
                                // check what to do with child rows
                                CheckChildRows(DataRowAction.Delete);
@@ -676,15 +672,19 @@ namespace System.Data {
                                DetachRow();
                                break;
                        case DataRowState.Deleted:
-                        case DataRowState.Detached:
-                               break;
+                               break;          
                        default:
                                // check what to do with child rows
                                CheckChildRows(DataRowAction.Delete);
                                _table.DeleteRowFromIndexes (this);
-                               rowState = DataRowState.Deleted;
                                break;
                        }
+                       if (Current >= 0) {
+                               if (Current != Original) {
+                                       _table.RecordCache.DisposeRecord(Current);
+                               }
+                               Current = -1;
+                       }
                        _table.DeletedDataRow(this, DataRowAction.Delete);
                }
 
@@ -705,16 +705,24 @@ namespace System.Data {
                                foreach (DataTable table in _table.DataSet.Tables)
                                {
                                        // loop on all ForeignKeyConstrain of the table.
-                                       foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
-                                       {
-                                               if (fk.RelatedTable == _table)
-                                               {
-                                                       Rule rule;
-                                                       if (action == DataRowAction.Delete)
-                                                               rule = fk.DeleteRule;
-                                                       else
-                                                               rule = fk.UpdateRule;
-                                                       CheckChildRows(fk, action, rule);
+                                       foreach (Constraint constraint in table.Constraints) {
+                                               if (constraint is ForeignKeyConstraint) { 
+                                                       ForeignKeyConstraint fk = (ForeignKeyConstraint) constraint;
+                                                       if (fk.RelatedTable == _table) {
+                                                               switch (action) {
+                                                                       case DataRowAction.Delete:
+                                                                               CheckChildRows(fk, action, fk.DeleteRule);
+                                                                               break;
+                                                                       case DataRowAction.Commit:
+                                                                       case DataRowAction.Rollback:
+                                                                               if (fk.AcceptRejectRule != AcceptRejectRule.None)
+                                                                                       CheckChildRows(fk, action, Rule.Cascade);
+                                                                               break;
+                                                                       default:
+                                                                               CheckChildRows(fk, action, fk.UpdateRule);
+                                                                               break;
+                                                               }
+                                                       }                       
                                                }                       
                                        }
                                }
@@ -723,7 +731,7 @@ namespace System.Data {
 
                private void CheckChildRows(ForeignKeyConstraint fkc, DataRowAction action, Rule rule)
                {                               
-                       DataRow[] childRows = GetChildRows(fkc, DataRowVersion.Default);
+                       DataRow[] childRows = GetChildRows(fkc, DataRowVersion.Current);
                        switch (rule)
                        {
                                case Rule.Cascade:  // delete or change all relted rows.
@@ -732,18 +740,29 @@ namespace System.Data {
                                                for (int j = 0; j < childRows.Length; j++)
                                                {
                                                        // if action is delete we delete all child rows
-                                                       if (action == DataRowAction.Delete)
-                                                       {
+                                                       switch(action) {
+                                                               case DataRowAction.Delete: {
                                                                if (childRows[j].RowState != DataRowState.Deleted)
                                                                        childRows[j].Delete();
+
+                                                                       break;
                                                        }
                                                        // if action is change we change the values in the child row
-                                                       else if (action == DataRowAction.Change)
-                                                       {
+                                                               case 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 < fkc.Columns.Length; k++)
                                                                        childRows[j][fkc.Columns[k]] = this[fkc.RelatedColumns[k], DataRowVersion.Proposed];
+
+                                                                       break;
+                                                               }
+
+                                                               case DataRowAction.Rollback: {
+                                                                       if (childRows[j].RowState != DataRowState.Unchanged)
+                                                                               childRows[j].RejectChanges ();
+
+                                                                       break;
+                                                               }
                                                        }
                                                }
                                        }
@@ -802,15 +821,14 @@ namespace System.Data {
                {
                        if (_inChangingEvent)
                                throw new InRowChangingEventException("Cannot call EndEdit inside an OnRowChanging event.");
-                       if (rowState == DataRowState.Detached)
-                       {
-                               editing = false;
+
+                       if (RowState == DataRowState.Detached)
                                return;
-                       }
                        
-                       CheckReadOnlyStatus();
                        if (HasVersion (DataRowVersion.Proposed))
                        {
+                               CheckReadOnlyStatus();
+
                                _inChangingEvent = true;
                                try
                                {
@@ -820,51 +838,42 @@ namespace System.Data {
                                {
                                        _inChangingEvent = false;
                                }
-                               if (rowState == DataRowState.Unchanged)
-                                       rowState = DataRowState.Modified;
                                
                                //Calling next method validates UniqueConstraints
                                //and ForeignKeys.
+                               bool rowValidated = false;
                                try
                                {
-                                       if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
+                                       if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad) {
                                                _table.Rows.ValidateDataRowInternal(this);
+                                               rowValidated = true;
+                                       }
                                }
                                catch (Exception e)
                                {
-                                       editing = false;
-                                       Table.RecordCache.DisposeRecord(_proposed);
-                                       _proposed = -1;
+                                       Table.RecordCache.DisposeRecord(Proposed);
+                                       Proposed = -1;
                                        throw e;
                                }
 
-                               // Now we are going to check all child rows of current row.
-                               // In the case the cascade is true the child rows will look up for
-                               // parent row. since lookup in index is always on current,
-                               // we have to move proposed version of current row to current
-                               // in the case of check child row failure we are rolling 
-                               // current row state back.
-                               int backup = _current;
-                               _current = _proposed;
-                               bool editing_backup = editing;
-                               editing = false;
-                               try {
-                                       // check all child rows.
                                        CheckChildRows(DataRowAction.Change);
-                                       _proposed = -1;
-                                       if (_original != backup) {
-                                               Table.RecordCache.DisposeRecord(backup);
-                                       }
+                               if (Original != Current) {
+                                       Table.RecordCache.DisposeRecord(Current);
                                }
-                               catch (Exception ex) {
-                                       // if check child rows failed - rollback to previous state
-                                       // i.e. restore proposed and current versions
-                                       _proposed = _current;
-                                       _current = backup;
-                                       editing = editing_backup;
-                                       // since we failed - propagate an exception
-                                       throw ex;
+
+                               Current = Proposed;
+                               Proposed = -1;
+
+                               if (!rowValidated) {
+                                       // keep indexes updated even if there was no need to validate row
+                                       foreach(Index index in Table.Indexes) {
+                                               index.Update(this,Current); //FIXME: why Current ?!
+                                       }
                                }
+
+                               // Note : row state must not be changed before all the job on indexes finished,
+                               // since the indexes works with recods rather than with rows and the decision
+                               // which of row records to choose depends on row state.
                                _table.ChangedDataRow(this, DataRowAction.Change);
                        }
                }
@@ -893,9 +902,8 @@ namespace System.Data {
                public DataRow[] GetChildRows (DataRelation relation, DataRowVersion version) 
                {
                        if (relation == null)
-                               return new DataRow[0];
+                               return Table.NewRowArray(0);
 
-                       //if (this.Table == null || RowState == DataRowState.Detached)
                        if (this.Table == null)
                                throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
 
@@ -912,23 +920,34 @@ namespace System.Data {
                        DataColumn[] parentColumns = relation.ParentColumns;
                        DataColumn[] childColumns = relation.ChildColumns;
                        int numColumn = parentColumns.Length;
-                       if (HasVersion(version))
-                       {
-                               object[] vals = new object[parentColumns.Length];
-                               for (int i = 0; i < vals.Length; i++)
-                                       vals[i] = this[parentColumns[i], version];
-                               
-                               foreach (DataRow row in relation.ChildTable.Rows) 
-                               {
-                                       bool allColumnsMatch = false;
-                                       if (row.HasVersion(DataRowVersion.Default))
-                                       {
-                                               allColumnsMatch = true;
-                                               for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) 
-                                               {
-                                                       if (!vals[columnCnt].Equals(
-                                                               row[childColumns[columnCnt], DataRowVersion.Default])) 
-                                                       {
+                       DataRow[] result = null;
+
+                       int versionIndex = IndexFromVersion(version);
+                       int tmpRecord = relation.ChildTable.RecordCache.NewRecord();
+
+                       try {
+                               for (int i = 0; i < numColumn; i++) {
+                                       // according to MSDN: the DataType value for both columns must be identical.
+                                       childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, versionIndex, tmpRecord);
+                               }
+
+                               Index index = relation.ChildTable.FindIndex(childColumns);
+
+                               if (index != null) {
+                                       int[] records = index.FindAll(tmpRecord);
+                                       result = relation.ChildTable.NewRowArray(records.Length);
+                                       for(int i=0; i < records.Length; i++) {
+                                               result[i] = relation.ChildTable.RecordCache[records[i]];
+                                       }
+                               }
+                               else {
+                                       foreach (DataRow row in relation.ChildTable.Rows) {
+                                               bool allColumnsMatch = false;
+                                               if (row.HasVersion(DataRowVersion.Default)) {
+                                                       allColumnsMatch = true;
+                                                       int childIndex = row.IndexFromVersion(DataRowVersion.Default);
+                                                       for (int columnCnt = 0; columnCnt < numColumn; ++columnCnt) {
+                                                               if (childColumns[columnCnt].DataContainer.CompareValues(childIndex, tmpRecord) != 0) {
                                                                allColumnsMatch = false;
                                                                break;
                                                        }
@@ -936,11 +955,14 @@ namespace System.Data {
                                        }
                                        if (allColumnsMatch) rows.Add(row);
                                }
-                       }else
-                               throw new VersionNotFoundException("There is no " + version + " data to accces.");
+                                       result = relation.ChildTable.NewRowArray(rows.Count);
+                                       rows.CopyTo(result, 0);
+                               }
+                       }
+                       finally {
+                               relation.ChildTable.RecordCache.DisposeRecord(tmpRecord);
+                       }                       
 
-                       DataRow[] result = relation.ChildTable.NewRowArray(rows.Count);
-                       rows.CopyTo(result, 0);
                        return result;
                }
 
@@ -959,25 +981,25 @@ namespace System.Data {
                        DataColumn[] parentColumns = fkc.RelatedColumns;
                        DataColumn[] childColumns = fkc.Columns;
                        int numColumn = parentColumns.Length;
-                       if (HasVersion(version)) {
+
                                Index index = fkc.Index;
+
+                       int curIndex = IndexFromVersion(version);
+                       int tmpRecord = fkc.Table.RecordCache.NewRecord();
+                       for (int i = 0; i < numColumn; i++) {
+                               // according to MSDN: the DataType value for both columns must be identical.
+                               childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, curIndex, tmpRecord);
+                       }
+
+                       try {
                                if (index != null) {
                                        // get the child rows from the index
-                                       Node[] childNodes = index.FindAllSimple (parentColumns, IndexFromVersion(version));
-                                       for (int i = 0; i < childNodes.Length; i++) {
-                                               rows.Add (childNodes[i].Row);
+                                       int[] childRecords = index.FindAll(tmpRecord);
+                                       for (int i = 0; i < childRecords.Length; i++) {
+                                               rows.Add (childColumns[i].Table.RecordCache[childRecords[i]]);
                                        }
                                }
                                else { // if there is no index we search manualy.
-                                       int curIndex = IndexFromVersion(DataRowVersion.Default);
-                                       int tmpRecord = fkc.Table.RecordCache.NewRecord();
-
-                                       try {
-                                               for (int i = 0; i < numColumn; i++) {
-                                                       // according to MSDN: the DataType value for both columns must be identical.
-                                                       childColumns[i].DataContainer.CopyValue(parentColumns[i].DataContainer, curIndex, tmpRecord);
-                                               }
-
                                                foreach (DataRow row in fkc.Table.Rows) {
                                                        bool allColumnsMatch = false;
                                                        if (row.HasVersion(DataRowVersion.Default)) {
@@ -995,12 +1017,10 @@ namespace System.Data {
                                                        }
                                                }
                                        }
+                       }
                                        finally {
                                                fkc.Table.RecordCache.DisposeRecord(tmpRecord);
                                        }
-                               }
-                       }else
-                               throw new VersionNotFoundException("There is no " + version + " data to accces.");
 
                        DataRow[] result = fkc.Table.NewRowArray(rows.Count);
                        rows.CopyTo(result, 0);
@@ -1012,7 +1032,14 @@ namespace System.Data {
                /// </summary>
                public string GetColumnError (DataColumn column) 
                {
-                       return GetColumnError (_table.Columns.IndexOf(column));
+                       if (column == null)
+                               throw new ArgumentNullException("column");
+
+                       int index = _table.Columns.IndexOf(column);
+                       if (index < 0)
+                               throw new ArgumentException(String.Format("Column '{0}' does not belong to table {1}.", column.ColumnName, Table.TableName));
+
+                       return GetColumnError (index);
                }
 
                /// <summary>
@@ -1118,7 +1145,7 @@ namespace System.Data {
                {
                        // TODO: Caching for better preformance
                        if (relation == null)
-                               return new DataRow[0];
+                               return Table.NewRowArray(0);
 
                        if (this.Table == null)
                                throw new RowNotInTableException("This row has been removed from a table and does not have any data.  BeginEdit() will allow creation of new data in this row.");
@@ -1133,25 +1160,23 @@ namespace System.Data {
                        DataColumn[] parentColumns = relation.ParentColumns;
                        DataColumn[] childColumns = relation.ChildColumns;
                        int numColumn = parentColumns.Length;
-                       if (HasVersion(version)) {
-                               Index indx = relation.ParentTable.GetIndexByColumns (parentColumns);
-                               if (indx != null && 
-    (Table == null || Table.DataSet == null || 
-     Table.DataSet.EnforceConstraints)) { // get the child rows from the index
-                                       Node[] childNodes = indx.FindAllSimple(childColumns, IndexFromVersion(version));
-                                       for (int i = 0; i < childNodes.Length; i++) {
-                                               rows.Add (childNodes[i].Row);
-                                       }
-                               }
-                               else { // no index so we have to search manualy.
-                                       int curIndex = IndexFromVersion(DataRowVersion.Default);
+
+                       int curIndex = IndexFromVersion(version);
                                        int tmpRecord = relation.ParentTable.RecordCache.NewRecord();
-                                       try {
                                                for (int i = 0; i < numColumn; i++) {
                                                        // according to MSDN: the DataType value for both columns must be identical.
                                                        parentColumns[i].DataContainer.CopyValue(childColumns[i].DataContainer, curIndex, tmpRecord);
                                                }
 
+                       try {
+                               Index index = relation.ParentTable.FindIndex(parentColumns);
+                               if (index != null) { // get the parent rows from the index
+                                       int[] parentRecords = index.FindAll(tmpRecord);
+                                       for (int i = 0; i < parentRecords.Length; i++) {
+                                               rows.Add (parentColumns[i].Table.RecordCache[parentRecords[i]]);
+                                       }
+                               }
+                               else { // no index so we have to search manualy.
                                                foreach (DataRow row in relation.ParentTable.Rows) {
                                                        bool allColumnsMatch = false;
                                                        if (row.HasVersion(DataRowVersion.Default)) {
@@ -1169,12 +1194,10 @@ namespace System.Data {
                                                        }
                                                }
                                        }
+                       }
                                        finally {
                                                relation.ParentTable.RecordCache.DisposeRecord(tmpRecord);
                                        }
-                               }
-                       }else
-                               throw new VersionNotFoundException("There is no " + version + " data to accces.");
 
                        DataRow[] result = relation.ParentTable.NewRowArray(rows.Count);
                        rows.CopyTo(result, 0);
@@ -1195,27 +1218,18 @@ namespace System.Data {
                /// </summary>
                public bool HasVersion (DataRowVersion version) 
                {
-                        switch (version) {
-                        case DataRowVersion.Default:
-                                if (rowState == DataRowState.Deleted && !_inExpressionEvaluation)
-                                        return false;
-                                if (rowState == DataRowState.Detached)
-                                        return _proposed >= 0;
-                                return true;
-                        case DataRowVersion.Proposed:
-                                if (rowState == DataRowState.Deleted && !_inExpressionEvaluation)
-                                        return false;
-                                return _proposed >= 0;
-                        case DataRowVersion.Current:
-                                if ((rowState == DataRowState.Deleted && !_inExpressionEvaluation) || rowState == DataRowState.Detached)
-                                        return false;
-                                return _current >= 0;
-                        case DataRowVersion.Original:
-                                if (rowState == DataRowState.Detached)
-                                        return false;
-                                return _original >= 0;
-                        }
-                       return false;
+                       switch (version) {
+                               case DataRowVersion.Default:
+                                       return (Proposed >= 0 || Current >= 0);
+                               case DataRowVersion.Proposed:
+                                       return Proposed >= 0;
+                               case DataRowVersion.Current:
+                                       return Current >= 0;
+                               case DataRowVersion.Original:
+                                       return Original >= 0;
+                               default:
+                                       return IndexFromVersion(version) >= 0;
+                       }
                }
 
                /// <summary>
@@ -1249,6 +1263,7 @@ namespace System.Data {
                /// </summary>
                public bool IsNull (DataColumn column, DataRowVersion version) 
                {
+                       object o = this[column,version];
                        return column.DataContainer.IsNull(IndexFromVersion(version));
                }
 
@@ -1279,14 +1294,16 @@ namespace System.Data {
                        // If original is null, then nothing has happened since AcceptChanges
                        // was last called.  We have no "original" to go back to.
                        if (HasVersion(DataRowVersion.Original)) {
-                               if (_current >= 0 ) {
-                                       Table.RecordCache.DisposeRecord(_current);
+                               if (Current >= 0 && Current != Original) {
+                                       Table.RecordCache.DisposeRecord(Current);
                                }
-                               _current = _original;
+                               CheckChildRows(DataRowAction.Rollback);
+
+                               Current = Original;
                               
                                _table.ChangedDataRow (this, DataRowAction.Rollback);
                                CancelEdit ();
-                               switch (rowState)
+                               switch (RowState)
                                {
                                        case DataRowState.Added:
                                                _table.DeleteRowFromIndexes (this);
@@ -1295,10 +1312,8 @@ namespace System.Data {
                                        case DataRowState.Modified:
                                                if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
                                                        _table.Rows.ValidateDataRowInternal(this);
-                                               rowState = DataRowState.Unchanged;
                                                break;
                                        case DataRowState.Deleted:
-                                               rowState = DataRowState.Unchanged;
                                                if ((_table.DataSet == null || _table.DataSet.EnforceConstraints) && !_table._duringDataLoad)
                                                        _table.Rows.ValidateDataRowInternal(this);
                                                break;
@@ -1311,7 +1326,7 @@ namespace System.Data {
                                // FIXME: I'm not realy sure, does this break something else, but
                                // if so: FIXME ;)
                                
-                               if ((rowState & DataRowState.Added) > 0)
+                               if ((RowState & DataRowState.Added) > 0)
                                {
                                        _table.DeleteRowFromIndexes (this);
                                        _table.Rows.RemoveInternal (this);
@@ -1380,40 +1395,37 @@ namespace System.Data {
                                throw new ArgumentException();
                        
                        BeginEdit();
-                       if (relation == null)
-                       {
-                               foreach (DataRelation parentRel in _table.ParentRelations)
-                               {
-                                       DataColumn[] childCols = parentRel.ChildColumns;
-                                       DataColumn[] parentCols = parentRel.ParentColumns;
-                                       
-                                       for (int i = 0; i < parentCols.Length; i++)
-                                       {
-                                               if (parentRow == null)
-                                                       this[childCols[i].Ordinal] = DBNull.Value;
-                                               else
-                                                       this[childCols[i].Ordinal] = parentRow[parentCols[i]];
-                                       }
-                                       
-                               }
+
+                       IEnumerable relations; 
+                       if (relation == null) {
+                               relations = _table.ParentRelations;
+                       }
+                       else {
+                               relations = new DataRelation[] { relation };
                        }
-                       else
+
+                       foreach (DataRelation rel in relations)
                        {
-                               DataColumn[] childCols = relation.ChildColumns;
-                               DataColumn[] parentCols = relation.ParentColumns;
-                                       
+                               DataColumn[] childCols = rel.ChildColumns;
+                               DataColumn[] parentCols = rel.ParentColumns;
+                               
                                for (int i = 0; i < parentCols.Length; i++)
                                {
-                                       if (parentRow == null)
-                                               this[childCols[i].Ordinal] = DBNull.Value;
-                                       else
-                                               this[childCols[i].Ordinal] = parentRow[parentCols[i]];
+                                       if (parentRow == null) {
+                                               childCols[i].DataContainer[Proposed] = DBNull.Value;
+                                       }
+                                       else {
+                                               int defaultIdx = parentRow.IndexFromVersion(DataRowVersion.Default);
+                                               childCols[i].DataContainer.CopyValue(parentCols[i].DataContainer,defaultIdx,Proposed);
+                                       }
                                }
+                               
                        }
+
                        EndEdit();
                }
                
-               //Copy all values of this DataaRow to the row parameter.
+               //Copy all values of this DataRow to the row parameter.
                internal void CopyValuesToRow(DataRow row)
                {
                        if (row == null)
@@ -1427,48 +1439,64 @@ namespace System.Data {
                                if(targetColumn != null) {
                                        int index = targetColumn.Ordinal;
                                        if (HasVersion(DataRowVersion.Original)) {
-                                               if (row._original < 0) {
-                                                       row._original = row.Table.RecordCache.NewRecord();
+                                               if (row.Original < 0) {
+                                                       row.Original = row.Table.RecordCache.NewRecord();
                                                }
-                                               object val = column[_original];
+                                               object val = column[Original];
                                                row.CheckValue(val, targetColumn);
-                                               targetColumn[row._original] = val;
+                                               targetColumn[row.Original] = val;
+                                       }
+                                       else {
+                                               if (row.Original > 0) {
+                                                       row.Table.RecordCache.DisposeRecord(row.Original);
+                                                       row.Original = -1;
+                                               }
                                        }
+
                                        if (HasVersion(DataRowVersion.Current)) {
-                                               if (row._current < 0) {
-                                                       row._current = row.Table.RecordCache.NewRecord();
+                                               if (row.Current < 0) {
+                                                       row.Current = row.Table.RecordCache.NewRecord();
                                                }
-                                               object val = column[_current];
+                                               object val = column[Current];
                                                row.CheckValue(val, targetColumn);
-                                               targetColumn[row._current] = val;
+                                               targetColumn[row.Current] = val;
+                                       }
+                                       else {
+                                               if (row.Current > 0) {
+                                                       row.Table.RecordCache.DisposeRecord(row.Current);
+                                                       row.Current = -1;
+                                               }
                                        }
+
                                        if (HasVersion(DataRowVersion.Proposed)) {
-                                               if (row._proposed < 0) {
-                                                       row._proposed = row.Table.RecordCache.NewRecord();
+                                               if (row.Proposed < 0) {
+                                                       row.Proposed = row.Table.RecordCache.NewRecord();
                                                }
-                                               object val = column[row._proposed];
+                                               object val = column[row.Proposed];
                                                row.CheckValue(val, targetColumn);
-                                               targetColumn[row._proposed] = val;
+                                               targetColumn[row.Proposed] = val;
+                                       }
+                                       else {
+                                               if (row.Proposed > 0) {
+                                                       row.Table.RecordCache.DisposeRecord(row.Proposed);
+                                                       row.Proposed = -1;
+                                               }
                                        }
-                                       
-                                        int srcIndex = IndexFromVersion (DataRowVersion.Default);
-                                        if (srcIndex >= 0) {
-                                                //Saving the current value as the column value
-                                                // FIXME: no idea why is this required
-                                                object defaultVal = column [srcIndex];
-                                                row [index] = defaultVal;
-                                        }
                                }
                        }
-                       CopyState(row);
+                       if (HasErrors) {
+                               CopyErrors(row);
+                       }
                }
 
-               // Copy row state - rowState and errors
-               internal void CopyState(DataRow row)
+               internal void CopyErrors(DataRow row)
                {
-                       row.rowState = RowState;
                        row.RowError = RowError;
-                       row.ColumnErrors = (ArrayList)ColumnErrors.Clone();
+                       DataColumn[] errorColumns = GetColumnsInError();
+                       foreach(DataColumn col in errorColumns) {
+                               DataColumn targetColumn = row.Table.Columns[col.ColumnName];
+                               row.SetColumnError(targetColumn,GetColumnError(col));
+                       }
                }
 
                internal bool IsRowChanged(DataRowState rowState) {
@@ -1520,48 +1548,14 @@ namespace System.Data {
                        }
                }
                
-               internal void CheckReadOnlyStatus()
-                {
-                       if (HasVersion(DataRowVersion.Proposed)) {
+               internal void CheckReadOnlyStatus() {
                                int defaultIdx = IndexFromVersion(DataRowVersion.Default); 
                                foreach(DataColumn column in Table.Columns) {
-                                       if ((column.DataContainer.CompareValues(defaultIdx,_proposed) != 0) && column.ReadOnly) {
+                               if ((column.DataContainer.CompareValues(defaultIdx,Proposed) != 0) && column.ReadOnly) {
                                        throw new ReadOnlyException();
                         }
                 }
                        }                       
-                }
-
-                /// <summary>
-                ///     Internal method to get a value of the record. This is a utility 
-                ///    method to fetch a value without any restriction. The only exception is
-                ///    when the given index or record index is out of range. That has to be
-                ///    handled by the caller.
-                /// </summary>
-                internal object GetValue (int index, int record)
-                {
-                        return Table.Columns [index] [record];
-                }
-
-                /// <summary>
-                ///     Internal method to get a value of the record for a given version. 
-                ///    This is a utility to fetch a value without any restriction.
-                /// </summary>
-                /// <exception type="VersionNotFoundException">
-                ///     if the row does not have version will throw exception
-                /// </exception>
-                internal object GetValue (int index, DataRowVersion version)
-                {
-                        int record = IndexFromVersion (version); // returns -1 if version not found
-                        if (record < 0)
-                                throw new VersionNotFoundException (String.Format ("This row does not have" +
-                                                                                   " version {0}.",
-                                                                                   version)
-                                                                    );
-                        return GetValue (index, record);
-                }
-                
-
        
                #endregion // Methods
 
@@ -1630,7 +1624,4 @@ namespace System.Data {
                 }
 #endif // NET_2_0
        }
-
-       
-
 }
index 72737a8e2b63cc0d9e50366e4d091b8ca5ae2612..a3cbb45804e42ff47a371aa07769f1472cb1c2ae 100644 (file)
@@ -36,6 +36,7 @@
 using System;
 using System.Collections;
 using System.ComponentModel;
+using System.Data.Common;
 
 namespace System.Data
 {
@@ -61,7 +62,7 @@ namespace System.Data
                public DataRow this[int index] 
                {
                        get { 
-                               if (index >= Count)
+                               if (index < 0 || index >= Count)
                                        throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
 
                                return (DataRow) List[index]; 
@@ -92,11 +93,16 @@ namespace System.Data
                        if (row.RowID != -1)
                                throw new ArgumentException ("This row already belongs to this table.");
                        
+                       row.BeginEdit();
 
                        if ((table.DataSet == null || table.DataSet.EnforceConstraints) && !table._duringDataLoad)
                                // we have to check that the new row doesn't colide with existing row
                                ValidateDataRowInternal(row);
-                       
+
+                       AddInternal(row);
+               }
+
+               internal void AddInternal(DataRow row) {
                        row.Table.ChangingDataRow (row, DataRowAction.Add);
                        row.HasParentCollection = true;
                        List.Add (row);
@@ -115,11 +121,13 @@ namespace System.Data
                public virtual DataRow Add (object[] values) 
 #endif
                {
-                       if (values.Length > table.Columns.Count)
-                               throw new ArgumentException ("The array is larger than the number of columns in the table.");
-                       DataRow row = table.NewRow ();
-                       row.ItemArray = values;
-                       Add (row);
+                       DataRow row = table.NewNotInitializedRow();
+                       int newRecord = table.CreateRecord(values);
+                       row.ImportRecord(newRecord);
+                       if ((table.DataSet == null || table.DataSet.EnforceConstraints) && !table._duringDataLoad)
+                               // we have to check that the new row doesn't colide with existing row
+                               ValidateDataRowInternal(row);
+                       AddInternal (row);
                        return row;
                }
 
@@ -171,10 +179,6 @@ namespace System.Data
                /// </summary>
                public bool Contains (object[] keys) 
                {
-                       if (table.PrimaryKey.Length != keys.Length)
-                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length + " value(s) for the key " + 
-                                                            "being indexed, but received " + keys.Length + " value(s).");
-
                        return Find (keys) != null;
                }
 
@@ -183,255 +187,58 @@ namespace System.Data
                /// </summary>
                public DataRow Find (object key) 
                {
-                       return Find (key, // primary key value
-                                     true // ignore deleted records
-                                     );
-               }
-
-                /// <summary>
-                ///     Searches records for the given primary key values.
-                /// </summary>
-                public DataRow Find (object [] keys)
-                {
-                        return Find (keys, // primary key values
-                                     true  // ignore deleted records
-                                     );
-                }
-                
-                /// <summary>
-                ///     Searches records for the given primary key values populated into
-                ///     a temporary cache index.
-                /// </summary>
-                internal DataRow Find (int index, int length)
-                {
-                        return Find (index,     // record to find
-                                     length,    // length of primary key
-                                     true       // ignore deleted records
-                                     );
+                       return Find(new object[]{key});
                 }
 
-                /// <summary>
-                ///     Searches records for the given single primary key.
-                /// </summary>
-                /// <param name='key'>Primary key value to be searched </param>
-                /// <param name='ignoreDeleted'>
-                ///    Ignore the records with row state DataRowState.Deleted
-                ///    if true.
-                /// </param>
-                internal DataRow Find (object key, bool ignoreDeleted)
-                {
-                        if (table.PrimaryKey.Length == 0)
+               /// <summary>
+               /// Gets the row containing the specified primary key values.
+               /// </summary>
+               public DataRow Find (object[] keys)
+               {
+                       if (table.PrimaryKey.Length == 0)
                                throw new MissingPrimaryKeyException ("Table doesn't have a primary key.");
-                       if (table.PrimaryKey.Length > 1)
-                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received 1 value(s).");
 
-                       if (key == null)
-#if NET_1_1
-                               return null;
-#else
-                               throw new ArgumentException("Expecting 1 value(s) for the key being indexed, but received 0 value(s).");
-#endif
+                       if (keys == null)
+                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received 0 value(s).");
+                                                                                                    
+                       Index index = table.GetIndex(table.PrimaryKey,null,DataViewRowState.None,null,false);
 
-                       DataColumn primaryKey = table.PrimaryKey[0];
-                       Index primaryKeyIndex = table.GetIndexByColumns(table.PrimaryKey);
-                       int tmpRecord = table.RecordCache.NewRecord();
-                       try {
-                               primaryKey.DataContainer[tmpRecord] = key;
-
-                               // if we can search through index
-                               if (primaryKeyIndex != null) {
-                                       // get the child rows from the index
-                                       Node node = primaryKeyIndex.FindSimple(tmpRecord,1,true);
-                                       if (node != null) {
-                                               return node.Row;
-                                       }
-                               }
-                       
-                               //loop through all collection rows                      
-                               foreach (DataRow row in this) {
-                                       if (ignoreDeleted && row.RowState == DataRowState.Deleted)
-                                                continue;
-                                        int index = row.IndexFromVersion(DataRowVersion.Default);
-                                        if (row.RowState == DataRowState.Deleted)
-                                                index = row.Current;
-                                        if (primaryKey.DataContainer.CompareValues(index, tmpRecord) == 0) {
-                                                return row;
-                                       }
-                               }
-                               return null;
-                       }
-                       finally {
-                               table.RecordCache.DisposeRecord(tmpRecord);
-                       }
-                }
+                       int record = index.Find(keys);
+                       return (record != -1) ? table.RecordCache[record] : null;
+               }
 
-                /// <summary>
-                ///     Searches records for the given primary key values.
-                /// </summary>
-                /// <param name='keys'>Primary key values to be searched </param>
-                /// <param name='ignoreDeleted'>
-                ///    Ignore the records with row state DataRowState.Deleted
-                ///    if true.
-                /// </param>
-               internal DataRow Find (object[] keys, bool ignoreDeleted) 
+               internal DataRow Find(int index)
                {
-                        AssertFind (keys);
-
                        DataColumn[] primaryKey = table.PrimaryKey;
-                       int tmpRecord = table.RecordCache.NewRecord();
-                       try {
-                               int numColumn = keys.Length;
-                               for (int i = 0; i < numColumn; i++) {
-                                       // according to MSDN: the DataType value for both columns must be identical.
-                                       primaryKey[i].DataContainer[tmpRecord] = keys[i];
+                       Index primaryKeyIndex = table.FindIndex(primaryKey);
+                       // if we can search through index
+                       if (primaryKeyIndex != null) {
+                               // get the child rows from the index
+                               int record = primaryKeyIndex.Find(index);
+                               if ( record != -1 ) {
+                                       return table.RecordCache[record];
                                }
-                               return Find(tmpRecord, numColumn, ignoreDeleted);
-                       }
-                       finally {
-                               table.RecordCache.DisposeRecord(tmpRecord);
-                       }
-               }
-
-                /// <summary>
-                ///     Searches records for the given primary key values and the 
-                ///     given version.
-                /// </summary>
-                /// <param name='keys'>Primary key values to be searched </param>
-                /// <param name='version'>
-                ///    Version of the rows to be searched for.
-                /// </param>
-                internal DataRow Find (object [] values, DataRowVersion version)
-                {
-                        AssertFind (values);
-                                                                                                    
-                       DataColumn[] pk = table.PrimaryKey;
-                       int temp = table.RecordCache.NewRecord();
-                       try {
-                               for (int i = 0; i < pk.Length; i++)
-                                       pk [i].DataContainer[temp] = values [i];
-                               return Find(temp, version, false); // include deleted records also
-                       }
-                       finally {
-                               table.RecordCache.DisposeRecord(temp);
-                       }
-                }
-
-                /// <summary>
-                ///     Searches records for the given primary key values and the 
-                ///     given version.
-                /// </summary>
-                /// <param name='record'>index of the record which holds the values to be searchd.
-                /// </param>
-                /// <param name='version'>
-                ///    Version of the rows to be searched for.
-                /// </param>
-                /// <param name='ignoreDeleted'>Ignore the records with state Deleted </param>
-               private DataRow Find(int record, DataRowVersion version, bool ignoreDeleted)
-               {
-                        DataRow resultRow = null;
-                        if (version == DataRowVersion.Current) {
-                                // index engine holds only the current records.
-                                resultRow = IndexSearch (record);
-                                if (resultRow != null)
-                                        return resultRow;
-                        }
-
-                       // fallback : loop through all collection rows                  
-                        // if there is a matching record with state deleted, that won't be detected
-                        // in the above search. (deleted records are not part of index.
-                       foreach (DataRow row in this) {
-                               if (ignoreDeleted && row.RowState != DataRowState.Deleted) 
-                                        continue;
-                                
-                                int offset = row.IndexFromVersion(version);
-                                if (offset < 0)
-                                        continue;
-                                bool matching = true;
-                                for (int i = 0; matching && i < table.PrimaryKey.Length; i++) { 
-                                        if (table.PrimaryKey [i].DataContainer.CompareValues(offset, record) != 0)
-                                                matching = false;
-                                }
-                                if (matching) {
-                                        resultRow = row; 
-                                        break;
-                                }
                        }
-                       return resultRow;
-
-                }
-
-                /// <summary>
-                ///     Searches records for the given primary key values and the 
-                ///     given version.
-                /// </summary>
-                /// <param name='index'> index of the record which holds the values to be searchd.
-                /// </param>
-                /// <param name='length'> length of primary keys </param>
-                /// <param name='ignoreDeleted'> Ignore the records with state Deleted </param>
-               private DataRow Find(int index, int length, bool ignoreDeleted)
-               {
-                        DataRow resultRow = IndexSearch (index);
-                        if (resultRow != null)
-                                return resultRow;
-                        
-                       //loop through all collection rows                      
-                       foreach (DataRow row in this) {
-                               if (ignoreDeleted && row.RowState != DataRowState.Deleted) 
-                                        continue;
-                                
-                                int rowIndex = row.IndexFromVersion(DataRowVersion.Default);
-                                if (row.RowState == DataRowState.Deleted)
-                                        rowIndex = row.Current;
-                                bool match = true;
-                                for (int columnCnt = 0; columnCnt < length; ++columnCnt) { 
-                                        if (table.PrimaryKey[columnCnt].DataContainer.CompareValues(rowIndex, index) != 0) {
-                                                match = false;
-                                        }
-                                }
-                                if ( match ) {
-                                        return row;
-                                }
+                       else {
+                               //loop through all collection rows                      
+                               foreach (DataRow row in this) {
+                                       if (row.RowState != DataRowState.Deleted) {
+                                               int rowIndex = row.IndexFromVersion(DataRowVersion.Default);
+                                               bool match = true;
+                                               for (int columnCnt = 0; columnCnt < primaryKey.Length; ++columnCnt) { 
+                                                       if (primaryKey[columnCnt].DataContainer.CompareValues(rowIndex, index) != 0) {
+                                                               match = false;
+                                                       }
+                                               }
+                                               if ( match ) {
+                                                       return row;
+                                               }
+                                       }
+                               }
                        }
                        return null;
                }
 
-
-                /// <summary>
-                ///   Asserts the validity of the search.
-                /// </summary>
-                private void AssertFind (object [] values)
-                {
-                        if (table.PrimaryKey.Length == 0)
-                                throw new MissingPrimaryKeyException ("Table doesn't have a primary key.");
-
-                       if (values == null)
-                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received 0 value(s).");
-
-                       if (table.PrimaryKey.Length != values.Length)
-                               throw new ArgumentException ("Expecting " + table.PrimaryKey.Length +" value(s) for the key being indexed, but received " + values.Length +  " value(s).");
-        
-                }
-
-                /// <summary>
-                ///   Search for the record using the index.
-                /// </summary>
-                private DataRow IndexSearch (int record)
-                {
-                        Index index = table.GetIndexByColumns(table.PrimaryKey);
-                        // search in index
-                        // priority is the non-deleted recrod
-                       if (index != null) {
-                               // get the child rows from the index
-                               Node node = index.FindSimple(record,
-                                                             table.PrimaryKey.Length, 
-                                                             true
-                                                             );
-                               if (node != null)
-                                       return node.Row;
-                       }
-                        return null;
-                }                
-
                /// <summary>
                /// Inserts a new row into the collection at the specified location.
                /// </summary>
@@ -492,16 +299,18 @@ namespace System.Data
                /// </summary>
                public void Remove (DataRow row) 
                {
-                       if (row == null)
-                               throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
-                       int index = List.IndexOf(row);
-                       if (index < 0)
+                       if (!List.Contains(row))
                                throw new IndexOutOfRangeException ("The given datarow is not in the current DataRowCollection.");
-                       row.Delete();
-                       // if the row was in added state it will be in Detached state after the
-                       // delete operation, so we have to check it.
-                       if (row.RowState != DataRowState.Detached)
-                               row.AcceptChanges();
+
+                       DataRowState state = row.RowState;
+                       if (state != DataRowState.Deleted &&
+                               state != DataRowState.Detached) {
+                               row.Delete();
+                               // if the row was in added state it will be in Detached state after the
+                               // delete operation, so we have to check it.
+                               if (row.RowState != DataRowState.Detached)
+                                       row.AcceptChanges();
+                       }
                }
 
                /// <summary>
@@ -509,14 +318,7 @@ namespace System.Data
                /// </summary>
                public void RemoveAt (int index) 
                {                       
-                       if (index < 0 || index >= List.Count)
-                               throw new IndexOutOfRangeException ("There is no row at position " + index + ".");
-                       DataRow row = (DataRow)List [index];
-                       row.Delete();
-                       // if the row was in added state it will be in Detached state after the
-                       // delete operation, so we have to check it.
-                       if (row.RowState != DataRowState.Detached)
-                               row.AcceptChanges();
+                       Remove(this[index]);
                }
 
                ///<summary>
@@ -529,45 +331,26 @@ namespace System.Data
                        //first check for null violations.
                        row._nullConstraintViolation = true;
                        row.CheckNullConstraints();
-                       // This validates constraints in the specific order : 
-                       // first unique/primary keys first, then Foreignkeys, etc
-                       ArrayList uniqueConstraintsDone = new ArrayList();
-                       ArrayList foreignKeyConstraintsDone = new ArrayList();
-                       try {
-                               foreach(Constraint constraint in table.Constraints.UniqueConstraints) {
-                                       constraint.AssertConstraint(row);
-                                       uniqueConstraintsDone.Add(constraint);
-                               }
-                       
-                               foreach(Constraint constraint in table.Constraints.ForeignKeyConstraints) {
-                                       constraint.AssertConstraint(row);
-                                       foreignKeyConstraintsDone.Add(constraint);
-                               }
-                       }
-                       // if one of the AssertConstraint failed - we need to "rollback" all the changes
-                       // caused by AssertCoinstraint calls already succeeded
-                       catch(ConstraintException e) {
-                               RollbackAsserts(row,foreignKeyConstraintsDone,uniqueConstraintsDone);
-                               throw e;
-                       }
-                       catch(InvalidConstraintException e) {   
-                               RollbackAsserts(row,foreignKeyConstraintsDone,uniqueConstraintsDone);
-                               throw e;
-                       }
-               }
 
-               private void RollbackAsserts(DataRow row,ICollection foreignKeyConstraintsDone,
-                       ICollection uniqueConstraintsDone)
-               {
-                       // if any of constraints assert failed - 
-                       // we have to rollback all the asserts scceeded
-                       // on order reverse to thier original execution
-                       foreach(Constraint constraint in foreignKeyConstraintsDone) {
-                               constraint.RollbackAssert(row);
+                       int newRecord = (row.Proposed >= 0) ? row.Proposed : row.Current;
+                       if (newRecord < 0)
+                               return;
+
+                       foreach(Index index in table.Indexes) {
+                               index.Update(row,newRecord);
                        }
 
-                       foreach(Constraint constraint in uniqueConstraintsDone) {
-                               constraint.RollbackAssert(row);
+                       foreach(Constraint constraint in table.Constraints) {
+                               try {
+                                       constraint.AssertConstraint(row);
+                               }
+                               catch(Exception e) {
+                                       // remove row from indexes
+                                       foreach(Index index in table.Indexes) {
+                                               index.Delete(newRecord);
+                                       }
+                                       throw e;
+                               }
                        }
                }
        }
index 29e564807e18b0c7d6e601552059a2939ad540ad..d0593c7191fc234912f679b71f161af4e839c5c8 100644 (file)
-//
-// System.Data.DataRowView.cs
-//
-// Author:
-//    Rodrigo Moya <rodrigo@ximian.com>
-//    Miguel de Icaza <miguel@ximian.com>
-//    Daniel Morgan <danmorg@sc.rr.com>
-//
-// (C) Ximian, Inc 2002
-// (C) Daniel Morgan 2002
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.ComponentModel;
-using System.Reflection;
-
-namespace System.Data
-{
-       /// <summary>
-       /// Represents a customized view of a DataRow exposed as a fully featured Windows Forms control.
-       /// </summary>
-       public class DataRowView : ICustomTypeDescriptor, IEditableObject, IDataErrorInfo
-       {
-               #region Fields
-
-               DataView dataView;
-               DataRow dataRow;
-               DataRowVersion rowVersion = DataRowVersion.Current;
-
-               bool isNew;
-
-               #endregion // Fields
-
-               #region Constructors
-
-               internal DataRowView (DataView dataView, DataRow row) : this(dataView, row, false){
-               }
-
-               internal DataRowView (DataView dataView, DataRow row, bool isNew) {
-                       this.dataView = dataView;
-                       this.dataRow = row;
-                       this.isNew = isNew;
-               }
-
-               #endregion // Constructors
-
-               #region Methods
-
-               public override bool Equals(object other)
-               {
-                       return (other != null &&
-                                       other is DataRowView && 
-                                       ((DataRowView)other).dataRow != null && 
-                                       ((DataRowView)other).dataRow.Equals(this.dataRow));
-               }
-
-               public void BeginEdit ()
-               {
-                       dataRow.BeginEdit ();
-               }
-
-               public void CancelEdit ()
-               {
-                       dataView.CancelEditRowView (this);
-                       isNew = false;
-               }
-
-               public DataView CreateChildView (DataRelation relation)
-               {
-                       if (relation == null)
-                               throw new ArgumentException ("The relation is not parented to the table.");
-                       return new DataView (relation.ChildTable,
-                               dataRow.GetChildRows (relation));
-               }
-
-               public DataView CreateChildView (string name)
-               {
-                       return CreateChildView (
-                               dataRow.Table.ChildRelations [name]);
-               }
-
-               public void Delete ()
-               {
-                       dataView.DeleteRowView (this);
-                       isNew = false;
-               }
-
-               public void EndEdit ()
-               {
-                       dataView.EndEditRowView (this);
-                       isNew = false;
-               }
-
-               #endregion // Methods
-
-               #region Properties
-               
-               public DataView DataView {
-                       get { return dataView; }
-               }
-
-               public bool IsEdit {
-                       get { return dataRow.IsEditing; }
-               }
-
-               // It becomes true when this instance is created by
-               // DataView.AddNew(). If it is true, then the DataRow is
-               // "Detached", and when this.EndEdit() is invoked, the row
-               // will be added to the table.
-               public bool IsNew {
-                       get { return isNew; }
-               }
-               
-               [System.Runtime.CompilerServices.IndexerName("Item")]
-               public object this[string column] {
-                       get {
-                               DataColumn dc = dataView.Table.Columns[column];
-                               return dataRow[dc, GetActualRowVersion ()];
-                       }
-                       set {
-                               DataColumn dc = dataView.Table.Columns[column];
-                               dataRow[dc] = value;
-                       }
-               }
-
-               // the compiler creates a DefaultMemeberAttribute from
-               // this IndexerNameAttribute
-               public object this[int column] {
-                       get {
-                               DataColumn dc = dataView.Table.Columns[column];
-                               return dataRow[dc, GetActualRowVersion ()];
-                       }
-                       set {
-                               DataColumn dc = dataView.Table.Columns[column];
-                               dataRow[dc] = value;
-
-                       }
-               }
-
-               private DataRowVersion GetActualRowVersion ()
-               {
-                       switch (dataView.RowStateFilter) {
-                       case DataViewRowState.Added:
-                               return DataRowVersion.Proposed;
-                       case DataViewRowState.ModifiedOriginal:
-                       case DataViewRowState.Deleted:
-                       case DataViewRowState.Unchanged:
-                       case DataViewRowState.OriginalRows:
-                               return DataRowVersion.Original;
-                       case DataViewRowState.ModifiedCurrent:
-                               return DataRowVersion.Current;
-                       }
-                       return DataRowVersion.Default;
-               }
-
-               public DataRow Row {
-                       get { return dataRow; }
-               }
-
-               public DataRowVersion RowVersion {
-                       [MonoTODO]
-                       get {
-                               return rowVersion;
-                       }
-               }
-
-               // It returns the hash code of the DataRow object.
-               public override int GetHashCode ()
-               {
-                       return dataRow.GetHashCode ();
-               }
-
-               #endregion // Properties
-               
-               #region ICustomTypeDescriptor implementations
-               
-               [MonoTODO]
-               AttributeCollection ICustomTypeDescriptor.GetAttributes  ()
-               {
-                       System.ComponentModel.AttributeCollection attributes;
-                       attributes = AttributeCollection.Empty;
-                       return attributes;
-               }
-
-               [MonoTODO]
-               string ICustomTypeDescriptor.GetClassName ()
-               {
-                       return "";
-               }
-               
-               [MonoTODO]
-               string ICustomTypeDescriptor.GetComponentName ()
-               {
-                       return null;
-               }
-
-               [MonoTODO]
-               TypeConverter ICustomTypeDescriptor.GetConverter ()
-               {
-                       return null;
-               }
-
-               [MonoTODO]
-               EventDescriptor ICustomTypeDescriptor.GetDefaultEvent ()
-               {
-                       return null;
-               }
-               
-               [MonoTODO]
-               PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty ()
-               {
-                       return null;
-               }
-               
-               [MonoTODO]
-               object ICustomTypeDescriptor.GetEditor (Type editorBaseType)
-               {
-                       return null;
-               }
-               
-               [MonoTODO]
-               EventDescriptorCollection ICustomTypeDescriptor.GetEvents ()
-               {
-                       return new EventDescriptorCollection(null);
-               }
-
-               [MonoTODO]
-               EventDescriptorCollection ICustomTypeDescriptor.GetEvents (Attribute [] attributes)
-               {
-                       return new EventDescriptorCollection(null);
-               }
-
-               [MonoTODO]
-               PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties ()
-               {
-                       ITypedList typedList = (ITypedList) dataView;
-                       return typedList.GetItemProperties(new PropertyDescriptor[0]);
-               }
-
-               [MonoTODO]
-               PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties (Attribute [] attributes)
-               {
-                       PropertyDescriptorCollection descriptors;
-                       descriptors = ((ICustomTypeDescriptor) this).GetProperties ();
-                       // TODO: filter out descriptors which do not contain
-                       //       any of those attributes
-                       //       except, those descriptors 
-                       //       that contain DefaultMemeberAttribute
-                       return descriptors;
-               }
-               
-               [MonoTODO]
-               object ICustomTypeDescriptor.GetPropertyOwner (PropertyDescriptor pd)
-               {
-                       return this;
-               }
-
-               #endregion // ICustomTypeDescriptor implementations
-
-               #region IDataErrorInfo implementation
-
-               string IDataErrorInfo.Error {
-                       [MonoTODO]
-                       get {
-                               return ""; // FIXME
-                       }
-               }
-
-               string IDataErrorInfo.this[string columnName] {
-                       [MonoTODO]
-                       get {
-                               return ""; // FIXME
-                       }
-               }
-
-               #endregion // IDataErrorInfo implementation
-       }
-}
+//\r
+// System.Data.DataRowView.cs\r
+//\r
+// Author:\r
+//    Rodrigo Moya <rodrigo@ximian.com>\r
+//    Miguel de Icaza <miguel@ximian.com>\r
+//    Daniel Morgan <danmorg@sc.rr.com>\r
+//\r
+// (C) Ximian, Inc 2002\r
+// (C) Daniel Morgan 2002\r
+//\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
+using System.Collections;\r
+using System.ComponentModel;\r
+using System.Reflection;\r
+\r
+namespace System.Data\r
+{\r
+       /// <summary>\r
+       /// Represents a customized view of a DataRow exposed as a fully featured Windows Forms control.\r
+       /// </summary>\r
+       // FIXME: correct exceptions in this[] methods\r
+       public class DataRowView : ICustomTypeDescriptor, IEditableObject, IDataErrorInfo\r
+       {\r
+               #region Fields\r
+\r
+               DataView _dataView;\r
+               DataRow _dataRow;\r
+               int _index = -1;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               internal DataRowView (DataView dataView, DataRow row, int index) {\r
+                       _dataView = dataView;\r
+                       _dataRow = row;\r
+                       _index = index;\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Methods\r
+\r
+               public override bool Equals(object other)\r
+               {\r
+                       return (other != null &&\r
+                                       other is DataRowView && \r
+                                       ((DataRowView)other)._dataRow != null && \r
+                                       ((DataRowView)other)._dataRow.Equals(_dataRow));\r
+               }\r
+\r
+               public void BeginEdit ()\r
+               {\r
+                       _dataRow.BeginEdit();\r
+               }\r
+\r
+               public void CancelEdit ()\r
+               {\r
+                       // FIXME:\r
+                       if (this.Row == DataView._lastAdded) {\r
+                               DataView.CompleteLastAdded(false);\r
+                       }\r
+                       else {\r
+                               _dataRow.CancelEdit();\r
+                       }\r
+               }\r
+\r
+               [MonoTODO]\r
+               public DataView CreateChildView (DataRelation relation)\r
+               {\r
+                       if (relation == null)\r
+                               throw new ArgumentException ("The relation is not parented to the table.");\r
+                       // FIXME : provide more efficient implementation using records\r
+                       object[] keyValues = new object[relation.ParentColumns.Length];\r
+                       for(int i=0; i < relation.ParentColumns.Length; i++) {\r
+                               keyValues[i] = this[relation.ParentColumns[i].Ordinal];\r
+                       }\r
+                       return DataView.CreateChildView(relation,keyValues);\r
+               }\r
+\r
+               public DataView CreateChildView (string name)\r
+               {\r
+                       return CreateChildView (\r
+                               Row.Table.ChildRelations [name]);\r
+               }\r
+\r
+               public void Delete ()\r
+               {\r
+                       DataView.Delete(_index);\r
+               }\r
+\r
+               public void EndEdit ()\r
+               {\r
+                       // FIXME:\r
+                       if (this.Row == DataView._lastAdded) {\r
+                               DataView.CompleteLastAdded(true);\r
+                       }\r
+                       else {\r
+                               _dataRow.EndEdit();\r
+                       }\r
+               }\r
+\r
+               private void CheckAllowEdit()\r
+               {\r
+                       if (!DataView.AllowEdit && (Row != DataView._lastAdded))\r
+                               throw new DataException("Cannot edit on a DataSource where AllowEdit is false.");\r
+               }\r
+\r
+               #endregion // Methods\r
+\r
+               #region Properties\r
+               \r
+               public DataView DataView {\r
+                       get { return _dataView; }\r
+               }\r
+\r
+               public bool IsEdit {\r
+                       get { return _dataRow.HasVersion(DataRowVersion.Proposed); }\r
+               }\r
+\r
+               // It becomes true when this instance is created by\r
+               // DataView.AddNew(). If it is true, then the DataRow is\r
+               // "Detached", and when this.EndEdit() is invoked, the row\r
+               // will be added to the table.\r
+               public bool IsNew {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return Row == DataView._lastAdded;\r
+                       }\r
+               }\r
+               \r
+               [System.Runtime.CompilerServices.IndexerName("Item")]\r
+               public object this[string column] {\r
+                       get {\r
+                               DataColumn dc = _dataView.Table.Columns[column];\r
+\r
+                               if (dc == null) {\r
+                                       string error = column + " is neither a DataColumn nor a DataRelation for table " + _dataView.Table.TableName;\r
+                                       throw new ArgumentException(error);\r
+                               }\r
+                               return _dataRow[dc, GetActualRowVersion ()];\r
+                       }\r
+                       set {\r
+                               CheckAllowEdit();\r
+                               DataColumn dc = _dataView.Table.Columns[column];\r
+\r
+                               if (dc == null) {\r
+                                       string error = column + " is neither a DataColumn nor a DataRelation for table " + _dataView.Table.TableName;\r
+                                       throw new ArgumentException(error);\r
+                               }\r
+                               _dataRow[dc] = value;\r
+                       }\r
+               }\r
+\r
+               // the compiler creates a DefaultMemeberAttribute from\r
+               // this IndexerNameAttribute\r
+               public object this[int column] {\r
+                       get {\r
+                               DataColumn dc = _dataView.Table.Columns[column];\r
+\r
+                               if (dc == null) {\r
+                                       string error = column + " is neither a DataColumn nor a DataRelation for table " + _dataView.Table.TableName;\r
+                                       throw new ArgumentException(error);\r
+                               }\r
+                               return _dataRow[dc, GetActualRowVersion ()];\r
+                       }\r
+                       set {\r
+                               CheckAllowEdit();\r
+                               DataColumn dc = _dataView.Table.Columns[column];\r
+\r
+                               if (dc == null) {\r
+                                       string error = column + " is neither a DataColumn nor a DataRelation for table " + _dataView.Table.TableName;\r
+                                       throw new ArgumentException(error);\r
+                               }\r
+                               _dataRow[dc] = value;\r
+\r
+                       }\r
+               }\r
+\r
+               private DataRowVersion GetActualRowVersion ()\r
+               {\r
+                       switch (_dataView.RowStateFilter) {\r
+                       case DataViewRowState.Added:\r
+                               return DataRowVersion.Proposed;\r
+                       case DataViewRowState.ModifiedOriginal:\r
+                       case DataViewRowState.Deleted:\r
+                       case DataViewRowState.Unchanged:\r
+                       case DataViewRowState.OriginalRows:\r
+                               return DataRowVersion.Original;\r
+                       case DataViewRowState.ModifiedCurrent:\r
+                               return DataRowVersion.Current;\r
+                       }\r
+                       return DataRowVersion.Default;\r
+               }\r
+\r
+               public DataRow Row {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return _dataRow;\r
+                       }\r
+               }\r
+\r
+               public DataRowVersion RowVersion {\r
+                       [MonoTODO]\r
+                       get {\r
+                               DataRowVersion version = DataView.GetRowVersion(_index);\r
+                               if (version != DataRowVersion.Original)\r
+                                       version = DataRowVersion.Current;\r
+\r
+                               return version;\r
+                       }\r
+               }\r
+\r
+               [MonoTODO]\r
+               public override int GetHashCode() {\r
+                       return _dataRow.GetHashCode();\r
+               }       \r
+\r
+               internal int Index {\r
+                       get { return _index; }\r
+               }\r
+\r
+               #endregion // Properties\r
+               \r
+               #region ICustomTypeDescriptor implementations\r
+               \r
+               [MonoTODO]\r
+               AttributeCollection ICustomTypeDescriptor.GetAttributes  ()\r
+               {\r
+                       System.ComponentModel.AttributeCollection attributes;\r
+                       attributes = AttributeCollection.Empty;\r
+                       return attributes;\r
+               }\r
+\r
+               [MonoTODO]\r
+               string ICustomTypeDescriptor.GetClassName ()\r
+               {\r
+                       return "";\r
+               }\r
+               \r
+               [MonoTODO]\r
+               string ICustomTypeDescriptor.GetComponentName ()\r
+               {\r
+                       return null;\r
+               }\r
+\r
+               [MonoTODO]\r
+               TypeConverter ICustomTypeDescriptor.GetConverter ()\r
+               {\r
+                       return null;\r
+               }\r
+\r
+               [MonoTODO]\r
+               EventDescriptor ICustomTypeDescriptor.GetDefaultEvent ()\r
+               {\r
+                       return null;\r
+               }\r
+               \r
+               [MonoTODO]\r
+               PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty ()\r
+               {\r
+                       return null;\r
+               }\r
+               \r
+               [MonoTODO]\r
+               object ICustomTypeDescriptor.GetEditor (Type editorBaseType)\r
+               {\r
+                       return null;\r
+               }\r
+               \r
+               [MonoTODO]\r
+               EventDescriptorCollection ICustomTypeDescriptor.GetEvents ()\r
+               {\r
+                       return new EventDescriptorCollection(null);\r
+               }\r
+\r
+               [MonoTODO]\r
+               EventDescriptorCollection ICustomTypeDescriptor.GetEvents (Attribute [] attributes)\r
+               {\r
+                       return new EventDescriptorCollection(null);\r
+               }\r
+\r
+               [MonoTODO]\r
+               PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties ()\r
+               {\r
+                       if (DataView == null) {\r
+                               ITypedList typedList = (ITypedList) _dataView;\r
+                       return typedList.GetItemProperties(new PropertyDescriptor[0]);\r
+                       }\r
+                       else {\r
+                               return DataView.Table.GetPropertyDescriptorCollection();\r
+                       }\r
+               }\r
+\r
+               [MonoTODO]\r
+               PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties (Attribute [] attributes)\r
+               {\r
+                       PropertyDescriptorCollection descriptors;\r
+                       descriptors = ((ICustomTypeDescriptor) this).GetProperties ();\r
+                       // TODO: filter out descriptors which do not contain\r
+                       //       any of those attributes\r
+                       //       except, those descriptors \r
+                       //       that contain DefaultMemeberAttribute\r
+                       return descriptors;\r
+               }\r
+               \r
+               [MonoTODO]\r
+               object ICustomTypeDescriptor.GetPropertyOwner (PropertyDescriptor pd)\r
+               {\r
+                       return this;\r
+               }\r
+\r
+               #endregion // ICustomTypeDescriptor implementations\r
+\r
+               #region IDataErrorInfo implementation\r
+\r
+               string IDataErrorInfo.Error {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return ""; // FIXME\r
+                       }\r
+               }\r
+\r
+               string IDataErrorInfo.this[string columnName] {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return ""; // FIXME\r
+                       }\r
+               }\r
+\r
+               #endregion // IDataErrorInfo implementation\r
+       }\r
+}\r
index f211ce75572d0d4bea8e2482a645843272e9cb44..2e54e521451aa9a13e10746cbf878215e98230c4 100644 (file)
-// 
-// System.Data/DataSet.cs
-//
-// Author:
-//   Christopher Podurgiel <cpodurgiel@msn.com>
-//   Daniel Morgan <danmorg@sc.rr.com>
-//   Rodrigo Moya <rodrigo@ximian.com>
-//   Stuart Caborn <stuart.caborn@virgin.net>
-//   Tim Coleman (tim@timcoleman.com)
-//   Ville Palo <vi64pa@koti.soon.fi>
-//   Atsushi Enomoto <atsushi@ximian.com>
-//
-// (C) Ximian, Inc. 2002
-// Copyright (C) Tim Coleman, 2002, 2003
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.ComponentModel;
-using System.Globalization;
-using System.Threading;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Xml;
-using System.Xml.Schema;
-using System.Xml.Serialization;
-using System.Data.Common;
-
-namespace System.Data {
-
-       [ToolboxItem (false)]
-       [DefaultProperty ("DataSetName")]
-       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataSetDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
-
-       [Serializable]
-       public class DataSet : MarshalByValueComponent, IListSource, 
-               ISupportInitialize, ISerializable, IXmlSerializable 
-       {
-               private string dataSetName;
-               private string _namespace = "";
-               private string prefix;
-               private bool caseSensitive;
-               private bool enforceConstraints = true;
-               private DataTableCollection tableCollection;
-               private DataRelationCollection relationCollection;
-               private PropertyCollection properties;
-               private DataViewManager defaultView;
-               private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;
-               internal XmlDataDocument _xmlDataDocument = null;
-               
-               #region Constructors
-
-               public DataSet () : this ("NewDataSet") 
-               {               
-               }
-               
-               public DataSet (string name)
-               {
-                       dataSetName = name;
-                       tableCollection = new DataTableCollection (this);
-                       relationCollection = new DataRelationCollection.DataSetRelationCollection (this);
-                       properties = new PropertyCollection ();
-                       this.prefix = String.Empty;
-                       
-                       this.Locale = CultureInfo.CurrentCulture;
-               }
-
-               protected DataSet (SerializationInfo info, StreamingContext context) : this ()
-               {
-                       GetSerializationData (info, context);
-               }
-
-               #endregion // Constructors
-
-               #region Public Properties
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]
-               [DefaultValue (false)]
-               public bool CaseSensitive {
-                       get {
-                               return caseSensitive;
-                       } 
-                       set {
-                               caseSensitive = value; 
-                               if (!caseSensitive) {
-                                       foreach (DataTable table in Tables) {
-                                               foreach (Constraint c in table.Constraints)
-                                                       c.AssertConstraint ();
-                                       }
-                               }
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("The name of this DataSet.")]
-               [DefaultValue ("")]
-               public string DataSetName {
-                       get { return dataSetName; } 
-                       set { dataSetName = value; }
-               }
-
-               [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]
-               [Browsable (false)]
-               public DataViewManager DefaultViewManager {
-                       get {
-                               if (defaultView == null)
-                                       defaultView = new DataViewManager (this);
-                               return defaultView;
-                       } 
-               }
-
-               [DataSysDescription ("Indicates whether constraint rules are to be followed.")]
-               [DefaultValue (true)]
-               public bool EnforceConstraints {
-                       get { return enforceConstraints; } 
-                       set { 
-                               if (value != enforceConstraints) {
-                                       enforceConstraints = value; 
-                                       if (value) {
-                                               foreach (DataTable table in Tables) {
-                                                       // first assert all unique constraints
-                                                       foreach (UniqueConstraint uc in table.Constraints.UniqueConstraints)
-                                                               uc.AssertConstraint ();
-                                                       // then assert all foreign keys
-                                                       foreach (ForeignKeyConstraint fk in table.Constraints.ForeignKeyConstraints)
-                                                               fk.AssertConstraint ();
-                                               }
-                                       }
-                               }
-                       }
-               }
-
-               [Browsable (false)]
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds custom user information.")]
-               public PropertyCollection ExtendedProperties {
-                       get { return properties; }
-               }
-
-               [Browsable (false)]
-               [DataSysDescription ("Indicates that the DataSet has errors.")]
-               public bool HasErrors {
-                       [MonoTODO]
-                       get {
-                               for (int i = 0; i < Tables.Count; i++) {
-                                       if (Tables[i].HasErrors)
-                                               return true;
-                               }
-                               return false;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]
-               public CultureInfo Locale {
-                       get {
-                               return locale;
-                       }
-                       set {
-                               if (locale == null || !locale.Equals (value)) {
-                                       // TODO: check if the new locale is valid
-                                       // TODO: update locale of all tables
-                                       locale = value;
-                               }
-                       }
-               }
-
-               public void Merge (DataRow[] rows)
-               {
-                       Merge (rows, false, MissingSchemaAction.Add);
-               }
-               
-               public void Merge (DataSet dataSet)
-               {
-                       Merge (dataSet, false, MissingSchemaAction.Add);
-               }
-               
-               public void Merge (DataTable table)
-               {
-                       Merge (table, false, MissingSchemaAction.Add);
-               }
-               
-               public void Merge (DataSet dataSet, bool preserveChanges)
-               {
-                       Merge (dataSet, preserveChanges, MissingSchemaAction.Add);
-               }
-               
-               [MonoTODO]
-               public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
-               {
-                       if (rows == null)
-                               throw new ArgumentNullException ("rows");
-                       if (!IsLegalSchemaAction (missingSchemaAction))
-                               throw new ArgumentOutOfRangeException ("missingSchemaAction");
-                       
-                       MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);
-               }
-               
-               [MonoTODO]
-               public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)
-               {
-                       if (dataSet == null)
-                               throw new ArgumentNullException ("dataSet");
-                       if (!IsLegalSchemaAction (missingSchemaAction))
-                               throw new ArgumentOutOfRangeException ("missingSchemaAction");
-                       
-                       MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);
-               }
-               
-               [MonoTODO]
-               public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
-               {
-                       if (table == null)
-                               throw new ArgumentNullException ("table");
-                       if (!IsLegalSchemaAction (missingSchemaAction))
-                               throw new ArgumentOutOfRangeException ("missingSchemaAction");
-                       
-                       MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);
-               }
-
-               private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)
-               {
-                       if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey
-                               || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)
-                               return true;
-                       return false;
-               }
-               
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]
-               [DefaultValue ("")]
-               public string Namespace {
-                       get { return _namespace; } 
-                       set {
-                               //TODO - trigger an event if this happens?
-                               if (value == null)
-                                       value = String.Empty;
-                                if (value != this._namespace)
-                                        RaisePropertyChanging ("Namespace");
-                               _namespace = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]
-               [DefaultValue ("")]
-               public string Prefix {
-                       get { return prefix; } 
-                       set {
-                               if (value == null)
-                                       value = String.Empty;
-                              // Prefix cannot contain any special characters other than '_' and ':'
-                               for (int i = 0; i < value.Length; i++) {
-                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))
-                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");
-                               }
-
-
-                               if (value == null)
-                                       value = string.Empty;
-                               
-                               if (value != this.prefix) 
-                                       RaisePropertyChanging ("Prefix");
-                               prefix = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds the relations for this DatSet.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public DataRelationCollection Relations {
-                       get {
-                               return relationCollection;              
-                       }
-               }
-
-               [Browsable (false)]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public override ISite Site {
-                       [MonoTODO]
-                       get {
-                               throw new NotImplementedException ();
-                       } 
-                       
-                       [MonoTODO]
-                       set {
-                               throw new NotImplementedException ();
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds the tables for this DataSet.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public DataTableCollection Tables {
-                       get { return tableCollection; }
-               }
-
-               #endregion // Public Properties
-
-               #region Public Methods
-
-               [MonoTODO]
-               public void AcceptChanges ()
-               {
-                       foreach (DataTable tempTable in tableCollection)
-                               tempTable.AcceptChanges ();
-               }
-
-                /// <summary>
-                /// Clears all the tables
-                /// </summary>
-               public void Clear ()
-               {
-                       if (_xmlDataDocument != null)
-                               throw new NotSupportedException ("Clear function on dataset and datatable is not supported when XmlDataDocument is bound to the DataSet.");
-                        bool enforceConstraints = this.EnforceConstraints;
-                        this.EnforceConstraints = false;
-                        for (int t = 0; t < tableCollection.Count; t++) {
-                               tableCollection[t].Clear ();
-                       }
-                        this.EnforceConstraints = enforceConstraints;
-               }
-
-               public virtual DataSet Clone ()
-               {
-                       // need to return the same type as this...
-                       DataSet Copy = (DataSet) Activator.CreateInstance(GetType(), true);
-       
-                       CopyProperties (Copy);
-
-                       foreach (DataTable Table in Tables) {
-                       // tables are often added in no-args constructor, don't add them
-                       // twice.
-                               if (!Copy.Tables.Contains(Table.TableName)) {
-                                       Copy.Tables.Add (Table.Clone ());
-                               }
-                       }
-
-                       //Copy Relationships between tables after existance of tables
-                       //and setting properties correctly
-                       CopyRelations (Copy);
-                       
-                       return Copy;
-               }
-
-               // Copies both the structure and data for this DataSet.
-               public DataSet Copy ()
-               {
-                       DataSet Copy = new DataSet ();
-                       CopyProperties (Copy);
-
-                       // Copy DatSet's tables
-                       foreach (DataTable Table in Tables) 
-                               Copy.Tables.Add (Table.Copy ());
-
-                       //Copy Relationships between tables after existance of tables
-                       //and setting properties correctly
-                       CopyRelations (Copy);
-
-                       return Copy;
-               }
-
-               private void CopyProperties (DataSet Copy)
-               {
-                       Copy.CaseSensitive = CaseSensitive;
-                       //Copy.Container = Container
-                       Copy.DataSetName = DataSetName;
-                       //Copy.DefaultViewManager
-                       //Copy.DesignMode
-                       Copy.EnforceConstraints = EnforceConstraints;
-                       if(ExtendedProperties.Count > 0) {
-                               //  Cannot copy extended properties directly as the property does not have a set accessor
-                Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);
-                ExtendedProperties.Keys.CopyTo (tgtArray, 0);
-                for (int i=0; i < ExtendedProperties.Count; i++)
-                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);
-                       }
-            Copy.Locale = Locale;
-                       Copy.Namespace = Namespace;
-                       Copy.Prefix = Prefix;                   
-                       //Copy.Site = Site; // FIXME : Not sure of this.
-
-               }
-               
-               
-               private void CopyRelations (DataSet Copy)
-               {
-
-                       //Creation of the relation contains some of the properties, and the constructor
-                       //demands these values. instead changing the DataRelation constructor and behaviour the
-                       //parameters are pre-configured and sent to the most general constructor
-
-                       foreach (DataRelation MyRelation in this.Relations) {
-                               string pTable = MyRelation.ParentTable.TableName;
-                               string cTable = MyRelation.ChildTable.TableName;
-                               DataColumn[] P_DC = new DataColumn[MyRelation.ParentColumns.Length]; 
-                               DataColumn[] C_DC = new DataColumn[MyRelation.ChildColumns.Length];
-                               int i = 0;
-                               
-                               foreach (DataColumn DC in MyRelation.ParentColumns) {
-                                       P_DC[i]=Copy.Tables[pTable].Columns[DC.ColumnName];
-                                       i++;
-                               }
-
-                               i = 0;
-
-                               foreach (DataColumn DC in MyRelation.ChildColumns) {
-                                       C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];
-                                       i++;
-                               }
-                               
-                               DataRelation cRel = new DataRelation (MyRelation.RelationName, P_DC, C_DC);
-                               //cRel.ChildColumns = MyRelation.ChildColumns;
-                               //cRel.ChildTable = MyRelation.ChildTable;
-                               //cRel.ExtendedProperties = cRel.ExtendedProperties; 
-                               //cRel.Nested = MyRelation.Nested;
-                               //cRel.ParentColumns = MyRelation.ParentColumns;
-                               //cRel.ParentTable = MyRelation.ParentTable;
-                                                               
-                               Copy.Relations.Add (cRel);
-                       }
-               }
-
-               
-
-
-               public DataSet GetChanges ()
-               {
-                       return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
-               }
-
-               
-               public DataSet GetChanges (DataRowState rowStates)
-               {
-                       if (!HasChanges (rowStates))
-                               return null;
-                       
-                       DataSet copySet = Clone ();
-                       Hashtable addedRows = new Hashtable ();
-
-                       IEnumerator tableEnumerator = Tables.GetEnumerator ();
-                       DataTable origTable;
-                       DataTable copyTable;
-                       while (tableEnumerator.MoveNext ()) {
-                               origTable = (DataTable)tableEnumerator.Current;
-                               copyTable = copySet.Tables[origTable.TableName];
-                               
-                               // Look for relations that have this table as child
-                               IEnumerator relations = origTable.ParentRelations.GetEnumerator ();
-
-                               IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();
-                               while (rowEnumerator.MoveNext ()) {
-                                       DataRow row = (DataRow)rowEnumerator.Current;
-                                       
-                                       if (row.IsRowChanged (rowStates))
-                                               AddChangedRow (addedRows, copySet, copyTable, relations, row);
-                               }
-                       }
-                       return copySet;
-               }
-               
-               void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)
-               {
-                       if (addedRows.ContainsKey (row)) return;
-                       
-                       relations.Reset ();
-                       while (relations.MoveNext ()) {
-                               DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);
-                               if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;
-                               DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];
-                               AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);
-                       }
-               
-                       DataRow newRow = copyTable.NewRow ();
-                       row.CopyValuesToRow (newRow);
-                       copyTable.Rows.Add (newRow);
-                       newRow.XmlRowID = row.XmlRowID;
-                       addedRows.Add (row,row);
-               }
-
-#if NET_2_0
-               [MonoTODO]
-               public DataTableReader GetDataReader (DataTable[] dataTables)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public DataTableReader GetDataReader ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-               
-               public string GetXml ()
-               {
-                       StringWriter Writer = new StringWriter ();
-                       WriteXml (Writer, XmlWriteMode.IgnoreSchema);
-                       return Writer.ToString ();
-               }
-
-               public string GetXmlSchema ()
-               {
-                       StringWriter Writer = new StringWriter ();
-                       WriteXmlSchema (Writer);
-                       return Writer.ToString ();
-               }
-
-               [MonoTODO]
-               public bool HasChanges ()
-               {
-                       return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
-               }
-
-               [MonoTODO]
-               public bool HasChanges (DataRowState rowState)
-               {
-                       if (((int)rowState & 0xffffffe0) != 0)
-                               throw new ArgumentOutOfRangeException ("rowState");
-
-                       DataTableCollection tableCollection = Tables;
-                       DataTable table;
-                       DataRowCollection rowCollection;
-                       DataRow row;
-
-                       for (int i = 0; i < tableCollection.Count; i++) {
-                               table = tableCollection[i];
-                               rowCollection = table.Rows;
-                               for (int j = 0; j < rowCollection.Count; j++) {
-                                       row = rowCollection[j];
-                                       if ((row.RowState & rowState) != 0)
-                                               return true;
-                               }
-                       }
-
-                       return false;           
-               }
-
-               public void InferXmlSchema (XmlReader reader, string[] nsArray)
-               {
-                       if (reader == null)
-                               return;
-                       XmlDocument doc = new XmlDocument ();
-                       doc.Load (reader);
-                       InferXmlSchema (doc, nsArray);
-               }
-
-               private void InferXmlSchema (XmlDocument doc, string [] nsArray)
-               {
-                       XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);
-               }
-
-               public void InferXmlSchema (Stream stream, string[] nsArray)
-               {
-                       InferXmlSchema (new XmlTextReader (stream), nsArray);
-               }
-
-               public void InferXmlSchema (TextReader reader, string[] nsArray)
-               {
-                       InferXmlSchema (new XmlTextReader (reader), nsArray);
-               }
-
-               public void InferXmlSchema (string fileName, string[] nsArray)
-               {
-                       XmlTextReader reader = new XmlTextReader (fileName);
-                       try {
-                               InferXmlSchema (reader, nsArray);
-                       } finally {
-                               reader.Close ();
-                       }
-               }
-
-#if NET_2_0
-               [MonoTODO]
-               public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void Load (IDataReader reader, LoadOption loadOption, string[] tables)
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               public virtual void RejectChanges ()
-               {
-                       int i;
-                       bool oldEnforceConstraints = this.EnforceConstraints;
-                       this.EnforceConstraints = false;
-                       
-                       for (i = 0; i < this.Tables.Count;i++) 
-                               this.Tables[i].RejectChanges ();
-
-                       this.EnforceConstraints = oldEnforceConstraints;
-               }
-
-               public virtual void Reset ()
-               {
-                       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)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (stream, null);
-                       writer.Formatting = Formatting.Indented;
-                       WriteXml (writer);
-               }
-
-               ///<summary>
-               /// Writes the current data for the DataSet to the specified file.
-               /// </summary>
-               /// <param name="filename">Fully qualified filename to write to</param>
-               public void WriteXml (string fileName)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (fileName, null);
-                       writer.Formatting = Formatting.Indented;
-                       writer.WriteStartDocument (true);
-                       try {
-                               WriteXml (writer);
-                       }
-                       finally {
-                               writer.WriteEndDocument ();
-                               writer.Close ();
-                       }
-               }
-
-               public void WriteXml (TextWriter writer)
-               {
-                       XmlTextWriter xwriter = new XmlTextWriter (writer);
-                       xwriter.Formatting = Formatting.Indented;
-                       WriteXml (xwriter);
-               }
-
-               public void WriteXml (XmlWriter writer)
-               {
-                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
-               }
-
-               public void WriteXml (string filename, XmlWriteMode mode)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (filename, null);
-                       writer.Formatting = Formatting.Indented;
-                       writer.WriteStartDocument (true);
-                       
-                       try {
-                               WriteXml (writer, mode);
-                       }
-                       finally {
-                               writer.WriteEndDocument ();
-                               writer.Close ();
-                       }
-               }
-
-               public void WriteXml (Stream stream, XmlWriteMode mode)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (stream, null);
-                       writer.Formatting = Formatting.Indented;
-                       WriteXml (writer, mode);
-               }
-
-               public void WriteXml (TextWriter writer, XmlWriteMode mode)
-               {
-                       XmlTextWriter xwriter = new XmlTextWriter (writer);
-                       xwriter.Formatting = Formatting.Indented;
-                       WriteXml (xwriter, mode);
-               }
-
-               public void WriteXml (XmlWriter writer, XmlWriteMode mode)
-               {
-                       if (mode == XmlWriteMode.DiffGram) {
-                               SetRowsID();
-                               WriteDiffGramElement(writer);
-                       }
-                       
-                       // It should not write when there is no content to be written
-                       bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);
-                       for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)
-                               shouldOutputContent = tableCollection [n].Rows.Count > 0;
-                               
-                       if (shouldOutputContent) {
-                               WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
-                               
-                               if (mode == XmlWriteMode.WriteSchema)
-                                       DoWriteXmlSchema (writer);
-                               
-                               WriteTables (writer, mode, Tables, DataRowVersion.Default);
-                               writer.WriteEndElement ();
-                       }
-                       
-                       if (mode == XmlWriteMode.DiffGram) {
-                               if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {
-
-                                       DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);
-                                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
-                                       WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);
-                                       writer.WriteEndElement ();
-                               }
-                       }
-                       
-                       if (mode == XmlWriteMode.DiffGram)
-                               writer.WriteEndElement (); // diffgr:diffgram
-
-                       writer.Flush ();
-               }
-
-               public void WriteXmlSchema (Stream stream)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (stream, null );
-                       writer.Formatting = Formatting.Indented;
-                       WriteXmlSchema (writer);        
-               }
-
-               public void WriteXmlSchema (string fileName)
-               {
-                       XmlTextWriter writer = new XmlTextWriter (fileName, null);
-                       try {
-                               writer.Formatting = Formatting.Indented;
-                               writer.WriteStartDocument (true);
-                               WriteXmlSchema (writer);
-                       } finally {
-                               writer.WriteEndDocument ();
-                               writer.Close ();
-                       }
-               }
-
-               public void WriteXmlSchema (TextWriter writer)
-               {
-                       XmlTextWriter xwriter = new XmlTextWriter (writer);
-                       try {
-                               xwriter.Formatting = Formatting.Indented;
-                               WriteXmlSchema (xwriter);
-                       } finally {
-                               xwriter.Close ();
-                       }
-               }
-
-               public void WriteXmlSchema (XmlWriter writer)
-               {
-                       //Create a skeleton doc and then write the schema 
-                       //proper which is common to the WriteXml method in schema mode
-                       DoWriteXmlSchema (writer);
-               }
-
-               public void ReadXmlSchema (Stream stream)
-               {
-                       XmlReader reader = new XmlTextReader (stream, null);
-                       ReadXmlSchema (reader);
-               }
-
-               public void ReadXmlSchema (string str)
-               {
-                       XmlReader reader = new XmlTextReader (str);
-                       try {
-                               ReadXmlSchema (reader);
-                       }
-                       finally {
-                               reader.Close ();
-                       }
-               }
-
-               public void ReadXmlSchema (TextReader treader)
-               {
-                       XmlReader reader = new XmlTextReader (treader);
-                       ReadXmlSchema (reader);                 
-               }
-
-               public void ReadXmlSchema (XmlReader reader)
-               {
-#if true
-                       new XmlSchemaDataImporter (this, reader).Process ();
-#else
-                       XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);
-                       SchemaMapper.Read (reader);
-#endif
-               }
-
-               public XmlReadMode ReadXml (Stream stream)
-               {
-                       return ReadXml (new XmlTextReader (stream));
-               }
-
-               public XmlReadMode ReadXml (string str)
-               {
-                       XmlTextReader reader = new XmlTextReader (str);
-                       try {
-                               return ReadXml (reader);
-                       }
-                       finally {
-                               reader.Close ();
-                       }
-               }
-
-               public XmlReadMode ReadXml (TextReader reader)
-               {
-                       return ReadXml (new XmlTextReader (reader));
-               }
-
-               public XmlReadMode ReadXml (XmlReader r)
-               {
-                       return ReadXml (r, XmlReadMode.Auto);
-               }
-
-               public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)
-               {
-                       return ReadXml (new XmlTextReader (stream), mode);
-               }
-
-               public XmlReadMode ReadXml (string str, XmlReadMode mode)
-               {
-                       XmlTextReader reader = new XmlTextReader (str);
-                       try {
-                               return ReadXml (reader, mode);
-                       }
-                       finally {
-                               reader.Close ();
-                       }
-               }
-
-               public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)
-               {
-                       return ReadXml (new XmlTextReader (reader), mode);
-               }
-
-               // LAMESPEC: XmlReadMode.Fragment is far from presisely
-               // documented. MS.NET infers schema against this mode.
-               public XmlReadMode ReadXml (XmlReader input, XmlReadMode mode)
-               {
-                       switch (input.ReadState) {
-                       case ReadState.EndOfFile:
-                       case ReadState.Error:
-                       case ReadState.Closed:
-                               return mode;
-                       }
-                       // Skip XML declaration and prolog
-                       input.MoveToContent ();
-                       if (input.EOF)
-                               return mode;
-
-                       // FIXME: We need more decent code here, but for now
-                       // I don't know the precise MS.NET behavior, I just
-                       // delegate to specific read process.
-                       switch (mode) {
-                       case XmlReadMode.IgnoreSchema:
-                               return ReadXmlIgnoreSchema (input, mode, true);
-                       case XmlReadMode.ReadSchema:
-                               return ReadXmlReadSchema (input, mode, true);
-                       }
-                       // remaining modes are: Auto, InferSchema, Fragment, Diffgram
-
-                       XmlReader reader = input;
-
-                       int depth = reader.Depth;
-                       XmlReadMode result = mode;
-                       bool skippedTopLevelElement = false;
-                       string potentialDataSetName = null;
-                       XmlDocument doc = null;
-                       bool shouldReadData = mode != XmlReadMode.DiffGram;
-                       bool shouldNotInfer = Tables.Count > 0;
-
-                       switch (mode) {
-                       case XmlReadMode.Auto:
-                       case XmlReadMode.InferSchema:
-                               doc = new XmlDocument ();
-                               do {
-                                       doc.AppendChild (doc.ReadNode (reader));
-                               } while (!reader.EOF &&
-                                       doc.DocumentElement == null);
-                               reader = new XmlNodeReader (doc);
-                               reader.MoveToContent ();
-                               break;
-                       case XmlReadMode.DiffGram:
-                               if (!(reader.LocalName == "diffgram" &&
-                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace))
-                                       goto case XmlReadMode.Auto;
-                               break;
-                       }
-
-                       switch (mode) {
-                       case XmlReadMode.Auto:
-                       case XmlReadMode.InferSchema:
-                       case XmlReadMode.ReadSchema:
-                               if (!(reader.LocalName == "diffgram" &&
-                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
-                                       !(reader.LocalName == "schema" &&
-                                       reader.NamespaceURI == XmlSchema.Namespace))
-                                       potentialDataSetName = reader.LocalName;
-                               goto default;
-                       case XmlReadMode.Fragment:
-                               break;
-                       default:
-                               if (!(reader.LocalName == "diffgram" &&
-                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&
-                                       !(reader.LocalName == "schema" &&
-                                       reader.NamespaceURI == XmlSchema.Namespace)) {
-                                       if (!reader.IsEmptyElement) {
-                                               reader.Read ();
-                                               reader.MoveToContent ();
-                                               skippedTopLevelElement = true;
-                                       }
-                                       else {
-                                               switch (mode) {
-                                               case XmlReadMode.Auto:
-                                               case XmlReadMode.InferSchema:
-                                                       DataSetName = reader.LocalName;
-                                                       break;
-                                               }
-                                               reader.Read ();
-                                       }
-                               }
-                               break;
-                       }
-
-                       // If schema, then read the first element as schema 
-                       if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
-                               shouldNotInfer = true;
-                               switch (mode) {
-                               case XmlReadMode.IgnoreSchema:
-                               case XmlReadMode.InferSchema:
-                                       reader.Skip ();
-                                       break;
-                               case XmlReadMode.Fragment:
-                                       ReadXmlSchema (reader);
-                                       break;
-                               case XmlReadMode.DiffGram:
-                               case XmlReadMode.Auto:
-                                       if (Tables.Count == 0) {
-                                               ReadXmlSchema (reader);
-                                               if (mode == XmlReadMode.Auto)
-                                                       result = XmlReadMode.ReadSchema;
-                                       } else {
-                                       // otherwise just ignore and return IgnoreSchema
-                                               reader.Skip ();
-                                               result = XmlReadMode.IgnoreSchema;
-                                       }
-                                       break;
-                               case XmlReadMode.ReadSchema:
-                                       ReadXmlSchema (reader);
-                                       break;
-                               }
-                       }
-
-                       // If diffgram, then read the first element as diffgram 
-                       if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {
-                               switch (mode) {
-                               case XmlReadMode.Auto:
-                               case XmlReadMode.IgnoreSchema:
-                               case XmlReadMode.DiffGram:
-                                       XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
-                                       DiffLoader.Load (reader);
-                                       if (mode == XmlReadMode.Auto)
-                                               result = XmlReadMode.DiffGram;
-                                       shouldReadData = false;
-                                       break;
-                               case XmlReadMode.Fragment:
-                                       reader.Skip ();
-                                       break;
-                               default:
-                                       reader.Skip ();
-                                       break;
-                               }
-                       }
-
-                       // if schema after diffgram, just skip it.
-                       if (!shouldReadData && reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {
-                               shouldNotInfer = true;
-                               switch (mode) {
-                               default:
-                                       reader.Skip ();
-                                       break;
-                               case XmlReadMode.ReadSchema:
-                               case XmlReadMode.DiffGram:
-                                       if (Tables.Count == 0)
-                                               ReadXmlSchema (reader);
-                                       break;
-                               }
-                       }
-
-                       if (reader.EOF)
-                               return result == XmlReadMode.Auto ?
-                                       potentialDataSetName != null && !shouldNotInfer ?
-                                       XmlReadMode.InferSchema :
-                                       XmlReadMode.IgnoreSchema : result;
-
-                       // Otherwise, read as dataset... but only when required.
-                       if (shouldReadData && !shouldNotInfer) {
-                               switch (mode) {
-                               case XmlReadMode.Auto:
-                                       if (Tables.Count > 0)
-                                               goto case XmlReadMode.IgnoreSchema;
-                                       else
-                                               goto case XmlReadMode.InferSchema;
-                               case XmlReadMode.InferSchema:
-                                       InferXmlSchema (doc, null);
-                                       if (mode == XmlReadMode.Auto)
-                                               result = XmlReadMode.InferSchema;
-                                       break;
-                               case XmlReadMode.IgnoreSchema:
-                               case XmlReadMode.Fragment:
-                               case XmlReadMode.DiffGram:
-                                       break;
-                               default:
-                                       shouldReadData = false;
-                                       break;
-                               }
-                       }
-
-                       if (shouldReadData) {
-                               XmlReader dataReader = reader;
-                               if (doc != null) {
-                                       dataReader = new XmlNodeReader (doc);
-                                       dataReader.MoveToContent ();
-                               }
-                               if (reader.NodeType == XmlNodeType.Element)
-                                       XmlDataReader.ReadXml (this, dataReader,
-                                               mode);
-                       }
-
-                       if (skippedTopLevelElement) {
-                               switch (result) {
-                               case XmlReadMode.Auto:
-                               case XmlReadMode.InferSchema:
-//                                     DataSetName = potentialDataSetName;
-//                                     result = XmlReadMode.InferSchema;
-                                       break;
-                               }
-                               if (reader.NodeType == XmlNodeType.EndElement)
-                                       reader.ReadEndElement ();
-                       }
-//*
-                       while (input.Depth > depth)
-                               input.Read ();
-                       if (input.NodeType == XmlNodeType.EndElement)
-                               input.Read ();
-//*/
-                       input.MoveToContent ();
-
-                       return result == XmlReadMode.Auto ?
-                               XmlReadMode.IgnoreSchema : result;
-               }
-               #endregion // Public Methods
-
-               #region Public Events
-
-               [DataCategory ("Action")]
-               [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]
-               public event MergeFailedEventHandler MergeFailed;
-
-               #endregion // Public Events
-
-               #region IListSource methods
-               IList IListSource.GetList ()
-               {
-                       return DefaultViewManager;
-               }
-               
-               bool IListSource.ContainsListCollection {
-                       get {
-                               return true;
-                       }
-               }
-               #endregion IListSource methods
-               
-               #region ISupportInitialize methods
-               public void BeginInit ()
-               {
-               }
-               
-               public void EndInit ()
-               {
-               }
-               #endregion
-
-               #region ISerializable
-               void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)
-               {
-                       StringWriter sw = new StringWriter ();
-                       XmlTextWriter writer = new XmlTextWriter (sw);
-                       DoWriteXmlSchema (writer);
-                       writer.Flush ();
-                       si.AddValue ("XmlSchema", sw.ToString ());
-                       
-                       sw = new StringWriter ();
-                       writer = new XmlTextWriter (sw);
-                       WriteXml (writer, XmlWriteMode.DiffGram);
-                       writer.Flush ();
-                       si.AddValue ("XmlDiffGram", sw.ToString ());
-               }
-               #endregion
-               
-               #region Protected Methods
-               protected void GetSerializationData (SerializationInfo info, StreamingContext context)
-               {
-                       string s = info.GetValue ("XmlSchema", typeof (String)) as String;
-                       XmlTextReader reader = new XmlTextReader (new StringReader (s));
-                       ReadXmlSchema (reader);
-                       reader.Close ();
-                       
-                       s = info.GetValue ("XmlDiffGram", typeof (String)) as String;
-                       reader = new XmlTextReader (new StringReader (s));
-                       ReadXml (reader, XmlReadMode.DiffGram);
-                       reader.Close ();
-               }
-               
-               
-               protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()
-               {
-                       return null;
-               }
-               
-               protected virtual void ReadXmlSerializable (XmlReader reader)
-               {
-                       ReadXml (reader);
-               }
-
-               void IXmlSerializable.ReadXml (XmlReader reader)
-               {
-                       ReadXmlSerializable(reader);
-               }
-               
-               void IXmlSerializable.WriteXml (XmlWriter writer)
-               {
-                       DoWriteXmlSchema (writer);
-                       WriteXml (writer, XmlWriteMode.DiffGram);
-               }
-
-               XmlSchema IXmlSerializable.GetSchema ()
-               {
-                       return GetSchemaSerializable ();
-               }
-
-               protected virtual bool ShouldSerializeRelations ()
-               {
-                       return true;
-               }
-               
-               protected virtual bool ShouldSerializeTables ()
-               {
-                       return true;
-               }
-
-               [MonoTODO]
-               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)
-               {
-               }
-
-               [MonoTODO]
-               protected virtual void OnRemoveRelation (DataRelation relation)
-               {
-               }
-
-               [MonoTODO]
-               protected virtual void OnRemoveTable (DataTable table)
-               {
-               }
-
-               internal virtual void OnMergeFailed (MergeFailedEventArgs e)
-               {
-                       if (MergeFailed != null)
-                               MergeFailed (this, e);
-               }
-
-               [MonoTODO]
-               protected internal void RaisePropertyChanging (string name)
-               {
-               }
-               #endregion
-
-               #region Private Methods
-
-               private XmlReadMode ReadXmlIgnoreSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)
-               {
-                       if (input.LocalName == "schema" &&
-                               input.NamespaceURI == XmlSchema.Namespace) {
-                               input.Skip ();
-                       }
-                       else if (input.LocalName == "diffgram" &&
-                               input.NamespaceURI == XmlConstants.DiffgrNamespace) {
-                               XmlDiffLoader DiffLoader = new XmlDiffLoader (this);
-                               DiffLoader.Load (input);
-                       }
-                       else if (checkRecurse ||
-                               input.LocalName == DataSetName &&
-                               input.NamespaceURI == Namespace) {
-                               XmlDataReader.ReadXml (this, input, mode);
-                       }
-                       else if (checkRecurse && !input.IsEmptyElement) {
-                               int depth = input.Depth;
-                               input.Read ();
-                               input.MoveToContent ();
-                               ReadXmlIgnoreSchema (input, mode, false);
-                               while (input.Depth > depth)
-                                       input.Skip ();
-                               if (input.NodeType == XmlNodeType.EndElement)
-                                       input.ReadEndElement ();
-                       }
-                       input.MoveToContent ();
-                       return XmlReadMode.IgnoreSchema;
-               }
-
-               private XmlReadMode ReadXmlReadSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)
-               {
-                       if (input.LocalName == "schema" &&
-                               input.NamespaceURI == XmlSchema.Namespace) {
-                               ReadXmlSchema (input);
-                       }
-                       else if (checkRecurse && !input.IsEmptyElement) {
-                               int depth = input.Depth;
-                               input.Read ();
-                               input.MoveToContent ();
-                               ReadXmlReadSchema (input, mode, false);
-                               while (input.Depth > depth)
-                                       input.Skip ();
-                               if (input.NodeType == XmlNodeType.EndElement)
-                                       input.ReadEndElement ();
-                       }
-                       else
-                               input.Skip ();
-                       input.MoveToContent ();
-                       return XmlReadMode.ReadSchema;
-               }
-
-               internal static string WriteObjectXml (object o)
-               {
-                       switch (Type.GetTypeCode (o.GetType ())) {
-                               case TypeCode.Boolean:
-                                       return XmlConvert.ToString ((Boolean) o);
-                               case TypeCode.Byte:
-                                       return XmlConvert.ToString ((Byte) o);
-                               case TypeCode.Char:
-                                       return XmlConvert.ToString ((Char) o);
-                               case TypeCode.DateTime:
-                                       return XmlConvert.ToString ((DateTime) o);
-                               case TypeCode.Decimal:
-                                       return XmlConvert.ToString ((Decimal) o);
-                               case TypeCode.Double:
-                                       return XmlConvert.ToString ((Double) o);
-                               case TypeCode.Int16:
-                                       return XmlConvert.ToString ((Int16) o);
-                               case TypeCode.Int32:
-                                       return XmlConvert.ToString ((Int32) o);
-                               case TypeCode.Int64:
-                                       return XmlConvert.ToString ((Int64) o);
-                               case TypeCode.SByte:
-                                       return XmlConvert.ToString ((SByte) o);
-                               case TypeCode.Single:
-                                       return XmlConvert.ToString ((Single) o);
-                               case TypeCode.UInt16:
-                                       return XmlConvert.ToString ((UInt16) o);
-                               case TypeCode.UInt32:
-                                       return XmlConvert.ToString ((UInt32) o);
-                               case TypeCode.UInt64:
-                                       return XmlConvert.ToString ((UInt64) o);
-                       }
-                       if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);
-                       if (o is Guid) return XmlConvert.ToString ((Guid) o);
-                       if (o is byte[]) return Convert.ToBase64String ((byte[])o);
-                       return o.ToString ();
-               }
-               
-               private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)
-               {
-                       //Write out each table in order, providing it is not
-                       //part of another table structure via a nested parent relationship
-                       foreach (DataTable table in tableCollection) {
-                               bool isTopLevel = true;
-                               /*
-                               foreach (DataRelation rel in table.ParentRelations) {
-                                       if (rel.Nested) {
-                                               isTopLevel = false;
-                                               break;
-                                       }
-                               }
-                               */
-                               if (isTopLevel) {
-                                       WriteTable ( writer, table, mode, version);
-                               }
-                       }
-               }
-
-               private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)
-               {
-                       DataRow[] rows = new DataRow [table.Rows.Count];
-                       table.Rows.CopyTo (rows, 0);
-                       WriteTable (writer, rows, mode, version, true);
-               }
-
-               private void WriteTable (XmlWriter writer,
-                       DataRow [] rows,
-                       XmlWriteMode mode,
-                       DataRowVersion version, bool skipIfNested)
-               {
-                       //The columns can be attributes, hidden, elements, or simple content
-                       //There can be 0-1 simple content cols or 0-* elements
-                       System.Collections.ArrayList atts;
-                       System.Collections.ArrayList elements;
-                       DataColumn simple = null;
-
-                       if (rows.Length == 0) return;
-                       DataTable table = rows[0].Table;
-                       SplitColumns (table, out atts, out elements, out simple);
-                       //sort out the namespacing
-                       string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
-                       int relationCount = table.ParentRelations.Count;
-                       DataRelation oneRel = relationCount == 1 ? table.ParentRelations [0] : null;
-
-                       foreach (DataRow row in rows) {
-                               if (skipIfNested) {
-                                       // Skip rows that is a child of any tables.
-                                       switch (relationCount) {
-                                       case 0:
-                                               break;
-                                       case 1:
-                                               if (!oneRel.Nested)
-                                                       break;
-                                               if (row.GetParentRow (oneRel) != null)
-                                                       continue;
-                                               break;
-                                       case 2:
-                                               bool skip = false;
-                                               for (int i = 0; i < table.ParentRelations.Count; i++) {
-                                                       DataRelation prel = table.ParentRelations [i];
-                                                       if (!prel.Nested)
-                                                               continue;
-                                                       if (row.GetParentRow (prel) != null) {
-                                                               skip = true;
-                                                               continue;
-                                                       }
-                                               }
-                                               if (skip)
-                                                       continue;
-                                               break;
-                                       }
-                               }
-
-                               if (!row.HasVersion(version) || 
-                                  (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged 
-                                     && version == DataRowVersion.Original))
-                                       continue;
-                               
-                               // First check are all the rows null. If they are we just write empty element
-                               bool AllNulls = true;
-                               foreach (DataColumn dc in table.Columns) {
-                               
-                                       if (row [dc.ColumnName, version] != DBNull.Value) {
-                                               AllNulls = false;
-                                               break;
-                                       } 
-                               }
-
-                               // If all of the columns were null, we have to write empty element
-                               if (AllNulls) {
-                                       writer.WriteElementString (XmlConvert.EncodeLocalName (table.TableName), "");
-                                       continue;
-                               }
-                               
-                               WriteTableElement (writer, mode, table, row, version);
-                               
-                               foreach (DataColumn col in atts) {                                      
-                                       WriteColumnAsAttribute (writer, mode, col, row, version);
-                               }
-                               
-                               if (simple != null) {
-                                       writer.WriteString (WriteObjectXml (row[simple, version]));
-                               }
-                               else {                                  
-                                       foreach (DataColumn col in elements) {
-                                               WriteColumnAsElement (writer, mode, col, row, version);
-                                       }
-                               }
-                               
-                               foreach (DataRelation relation in table.ChildRelations) {
-                                       if (relation.Nested) {
-                                               WriteTable (writer, row.GetChildRows (relation), mode, version, false);
-                                       }
-                               }
-                               
-                               writer.WriteEndElement ();
-                       }
-
-               }
-
-               private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
-               {
-                       string colnspc = null;
-                       object rowObject = row [col, version];
-                                                                       
-                       if (rowObject == null || rowObject == DBNull.Value)
-                               return;
-
-                       if (col.Namespace != String.Empty)
-                               colnspc = col.Namespace;
-       
-                       //TODO check if I can get away with write element string
-                       WriteStartElement (writer, mode, colnspc, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName));
-                       writer.WriteString (WriteObjectXml (rowObject));
-                       writer.WriteEndElement ();
-               }
-
-               private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)
-               {
-                       if (!row.IsNull (col))
-                               WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName), WriteObjectXml (row[col, version]));
-               }
-
-               private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)
-               {
-                       //sort out the namespacing
-                       string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;
-
-                       WriteStartElement (writer, mode, nspc, table.Prefix, XmlConvert.EncodeLocalName (table.TableName));
-
-                       if (mode == XmlWriteMode.DiffGram) {
-                               WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));
-                               WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));
-                               string modeName = null;
-                               if (row.RowState == DataRowState.Modified)
-                                       modeName = "modified";
-                               else if (row.RowState == DataRowState.Added)
-                                       modeName = "inserted";
-
-                               if (version != DataRowVersion.Original && modeName != null)
-                                       WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);
-                       }
-               }
-                   
-               private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)
-               {
-                       writer.WriteStartElement (prefix, name, nspc);
-               }
-               
-               private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)
-               {
-                       switch ( mode) {
-                               case XmlWriteMode.WriteSchema:
-                                       writer.WriteAttributeString (prefix, name, nspc);
-                                       break;
-                               case XmlWriteMode.DiffGram:
-                                       writer.WriteAttributeString (prefix, name, nspc,stringValue);
-                                       break;
-                               default:
-                                       writer.WriteAttributeString (name, stringValue);
-                                       break;                                  
-                       };
-               }
-               
-               internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)
-               {
-                       if (mode == XmlWriteMode.DiffGram) {
-                               SetTableRowsID (table);
-                               WriteDiffGramElement (writer);
-                       }
-                       
-                       WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));
-                       
-                       WriteTable (writer, table, mode, DataRowVersion.Default);
-                       
-                       if (mode == XmlWriteMode.DiffGram) {
-                               writer.WriteEndElement (); //DataSet name
-                               if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {
-
-                                       DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);   
-                                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");
-                                       WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);
-                                       writer.WriteEndElement ();
-                               }
-                       }
-                       writer.WriteEndElement (); // DataSet name or diffgr:diffgram
-               }
-
-               private void DoWriteXmlSchema (XmlWriter writer)
-               {
-                       if (writer.WriteState == WriteState.Start)
-                               writer.WriteStartDocument ();
-                       XmlSchemaWriter.WriteXmlSchema (this, writer);
-               }
-               
-               ///<summary>
-               /// Helper function to split columns into attributes elements and simple
-               /// content
-               /// </summary>
-               internal static void SplitColumns (DataTable table, 
-                       out ArrayList atts, 
-                       out ArrayList elements, 
-                       out DataColumn simple)
-               {
-                       //The columns can be attributes, hidden, elements, or simple content
-                       //There can be 0-1 simple content cols or 0-* elements
-                       atts = new System.Collections.ArrayList ();
-                       elements = new System.Collections.ArrayList ();
-                       simple = null;
-                       
-                       //Sort out the columns
-                       foreach (DataColumn col in table.Columns) {
-                               switch (col.ColumnMapping) {
-                                       case MappingType.Attribute:
-                                               atts.Add (col);
-                                               break;
-                                       case MappingType.Element:
-                                               elements.Add (col);
-                                               break;
-                                       case MappingType.SimpleContent:
-                                               if (simple != null) {
-                                                       throw new System.InvalidOperationException ("There may only be one simple content element");
-                                               }
-                                               simple = col;
-                                               break;
-                                       default:
-                                               //ignore Hidden elements
-                                               break;
-                               }
-                       }
-               }
-
-               private void WriteDiffGramElement(XmlWriter writer)
-               {
-                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");
-                       WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);
-               }
-
-               private void SetRowsID()
-               {
-                       foreach (DataTable Table in Tables)
-                               SetTableRowsID (Table);
-               }
-               
-               private void SetTableRowsID (DataTable Table)
-               {
-                       int dataRowID = 0;
-                       foreach (DataRow Row in Table.Rows) {
-                               Row.XmlRowID = dataRowID;
-                               dataRowID++;
-                       }
-               }
-               #endregion //Private Xml Serialisation
-       }
-}
+// \r
+// System.Data/DataSet.cs\r
+//\r
+// Author:\r
+//   Christopher Podurgiel <cpodurgiel@msn.com>\r
+//   Daniel Morgan <danmorg@sc.rr.com>\r
+//   Rodrigo Moya <rodrigo@ximian.com>\r
+//   Stuart Caborn <stuart.caborn@virgin.net>\r
+//   Tim Coleman (tim@timcoleman.com)\r
+//   Ville Palo <vi64pa@koti.soon.fi>\r
+//   Atsushi Enomoto <atsushi@ximian.com>\r
+//   Konstantin Triger <kostat@mainsoft.com>\r
+//\r
+// (C) Ximian, Inc. 2002\r
+// Copyright (C) Tim Coleman, 2002, 2003\r
+//\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
+using System.Collections;\r
+using System.ComponentModel;\r
+using System.Globalization;\r
+using System.Threading;\r
+using System.IO;\r
+using System.Runtime.Serialization;\r
+using System.Xml;\r
+using System.Xml.Schema;\r
+using System.Xml.Serialization;\r
+using System.Data.Common;\r
+\r
+namespace System.Data {\r
+\r
+       [ToolboxItem (false)]\r
+       [DefaultProperty ("DataSetName")]\r
+       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataSetDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]\r
+\r
+       [Serializable]\r
+       public class DataSet : MarshalByValueComponent, IListSource, \r
+               ISupportInitialize, ISerializable, IXmlSerializable \r
+       {\r
+               private string dataSetName;\r
+               private string _namespace = "";\r
+               private string prefix;\r
+               private bool caseSensitive;\r
+               private bool enforceConstraints = true;\r
+               private DataTableCollection tableCollection;\r
+               private DataRelationCollection relationCollection;\r
+               private PropertyCollection properties;\r
+               private DataViewManager defaultView;\r
+               private CultureInfo locale = System.Threading.Thread.CurrentThread.CurrentCulture;\r
+               internal XmlDataDocument _xmlDataDocument = null;\r
+               \r
+               #region Constructors\r
+\r
+               public DataSet () : this ("NewDataSet") \r
+               {               \r
+               }\r
+               \r
+               public DataSet (string name)\r
+               {\r
+                       dataSetName = name;\r
+                       tableCollection = new DataTableCollection (this);\r
+                       relationCollection = new DataRelationCollection.DataSetRelationCollection (this);\r
+                       properties = new PropertyCollection ();\r
+                       this.prefix = String.Empty;\r
+                       \r
+                       this.Locale = CultureInfo.CurrentCulture;\r
+               }\r
+\r
+               protected DataSet (SerializationInfo info, StreamingContext context) : this ()\r
+               {\r
+                       GetSerializationData (info, context);\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Public Properties\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether comparing strings within the DataSet is case sensitive.")]\r
+               [DefaultValue (false)]\r
+               public bool CaseSensitive {\r
+                       get {\r
+                               return caseSensitive;\r
+                       } \r
+                       set {\r
+                               caseSensitive = value; \r
+                               if (!caseSensitive) {\r
+                                       foreach (DataTable table in Tables) {\r
+                                               table.ResetCaseSensitiveIndexes();\r
+                                               foreach (Constraint c in table.Constraints)\r
+                                                       c.AssertConstraint ();\r
+                                       }\r
+                               }\r
+                               else {\r
+                                       foreach (DataTable table in Tables) {\r
+                                               table.ResetCaseSensitiveIndexes();\r
+                                       }\r
+                               }\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The name of this DataSet.")]\r
+               [DefaultValue ("")]\r
+               public string DataSetName {\r
+                       get { return dataSetName; } \r
+                       set { dataSetName = value; }\r
+               }\r
+\r
+               [DataSysDescription ("Indicates a custom \"view\" of the data contained by the DataSet. This view allows filtering, searching, and navigating through the custom data view.")]\r
+               [Browsable (false)]\r
+               public DataViewManager DefaultViewManager {\r
+                       get {\r
+                               if (defaultView == null)\r
+                                       defaultView = new DataViewManager (this);\r
+                               return defaultView;\r
+                       } \r
+               }\r
+\r
+               [DataSysDescription ("Indicates whether constraint rules are to be followed.")]\r
+               [DefaultValue (true)]\r
+               public bool EnforceConstraints {\r
+                       get { return enforceConstraints; } \r
+                       set { \r
+                               InternalEnforceConstraints(value,true);\r
+                       }\r
+               }\r
+\r
+               [Browsable (false)]\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds custom user information.")]\r
+               public PropertyCollection ExtendedProperties {\r
+                       get { return properties; }\r
+               }\r
+\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Indicates that the DataSet has errors.")]\r
+               public bool HasErrors {\r
+                       [MonoTODO]\r
+                       get {\r
+                               for (int i = 0; i < Tables.Count; i++) {\r
+                                       if (Tables[i].HasErrors)\r
+                                               return true;\r
+                               }\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates a locale under which to compare strings within the DataSet.")]\r
+               public CultureInfo Locale {\r
+                       get {\r
+                               return locale;\r
+                       }\r
+                       set {\r
+                               if (locale == null || !locale.Equals (value)) {\r
+                                       // TODO: check if the new locale is valid\r
+                                       // TODO: update locale of all tables\r
+                                       locale = value;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal void InternalEnforceConstraints(bool value,bool resetIndexes)\r
+               {\r
+                               if (value != enforceConstraints) {\r
+                                       if (value) {\r
+                                               foreach (DataTable table in Tables) {\r
+                                                       // FIXME : is that correct?\r
+                                                       // By design  the indexes should be updated at this point.\r
+                                                       // In Fill from BeginLoadData till EndLoadData indexes are not updated (reset in EndLoadData)\r
+                                                       // In DataRow.EndEdit indexes are always updated.\r
+                                                       if (resetIndexes) {\r
+                                                               table.ResetIndexes();\r
+                                                       }\r
+                                                       // assert all constraints\r
+                                                       foreach (Constraint constraint in table.Constraints)\r
+                                                               constraint.AssertConstraint();\r
+                                               }\r
+                                       }\r
+\r
+                                       enforceConstraints = value;\r
+                               }\r
+               }\r
+\r
+               public void Merge (DataRow[] rows)\r
+               {\r
+                       Merge (rows, false, MissingSchemaAction.Add);\r
+               }\r
+               \r
+               public void Merge (DataSet dataSet)\r
+               {\r
+                       Merge (dataSet, false, MissingSchemaAction.Add);\r
+               }\r
+               \r
+               public void Merge (DataTable table)\r
+               {\r
+                       Merge (table, false, MissingSchemaAction.Add);\r
+               }\r
+               \r
+               public void Merge (DataSet dataSet, bool preserveChanges)\r
+               {\r
+                       Merge (dataSet, preserveChanges, MissingSchemaAction.Add);\r
+               }\r
+               \r
+               [MonoTODO]\r
+               public void Merge (DataRow[] rows, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
+               {\r
+                       if (rows == null)\r
+                               throw new ArgumentNullException ("rows");\r
+                       if (!IsLegalSchemaAction (missingSchemaAction))\r
+                               throw new ArgumentOutOfRangeException ("missingSchemaAction");\r
+                       \r
+                       MergeManager.Merge (this, rows, preserveChanges, missingSchemaAction);\r
+               }\r
+               \r
+               [MonoTODO]\r
+               public void Merge (DataSet dataSet, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
+               {\r
+                       if (dataSet == null)\r
+                               throw new ArgumentNullException ("dataSet");\r
+                       if (!IsLegalSchemaAction (missingSchemaAction))\r
+                               throw new ArgumentOutOfRangeException ("missingSchemaAction");\r
+                       \r
+                       MergeManager.Merge (this, dataSet, preserveChanges, missingSchemaAction);\r
+               }\r
+               \r
+               [MonoTODO]\r
+               public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
+               {\r
+                       if (table == null)\r
+                               throw new ArgumentNullException ("table");\r
+                       if (!IsLegalSchemaAction (missingSchemaAction))\r
+                               throw new ArgumentOutOfRangeException ("missingSchemaAction");\r
+                       \r
+                       MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);\r
+               }\r
+\r
+               private static bool IsLegalSchemaAction (MissingSchemaAction missingSchemaAction)\r
+               {\r
+                       if (missingSchemaAction == MissingSchemaAction.Add || missingSchemaAction == MissingSchemaAction.AddWithKey\r
+                               || missingSchemaAction == MissingSchemaAction.Error || missingSchemaAction == MissingSchemaAction.Ignore)\r
+                               return true;\r
+                       return false;\r
+               }\r
+               \r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the XML uri namespace for the root element pointed at by this DataSet.")]\r
+               [DefaultValue ("")]\r
+               public string Namespace {\r
+                       get { return _namespace; } \r
+                       set {\r
+                               //TODO - trigger an event if this happens?\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+                                if (value != this._namespace)\r
+                                        RaisePropertyChanging ("Namespace");\r
+                               _namespace = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the prefix of the namespace used for this DataSet.")]\r
+               [DefaultValue ("")]\r
+               public string Prefix {\r
+                       get { return prefix; } \r
+                       set {\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+                              // Prefix cannot contain any special characters other than '_' and ':'\r
+                               for (int i = 0; i < value.Length; i++) {\r
+                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))\r
+                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");\r
+                               }\r
+\r
+\r
+                               if (value == null)\r
+                                       value = string.Empty;\r
+                               \r
+                               if (value != this.prefix) \r
+                                       RaisePropertyChanging ("Prefix");\r
+                               prefix = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds the relations for this DatSet.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public DataRelationCollection Relations {\r
+                       get {\r
+                               return relationCollection;              \r
+                       }\r
+               }\r
+\r
+               [Browsable (false)]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public override ISite Site {\r
+                       [MonoTODO]\r
+                       get {\r
+                               throw new NotImplementedException ();\r
+                       } \r
+                       \r
+                       [MonoTODO]\r
+                       set {\r
+                               throw new NotImplementedException ();\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds the tables for this DataSet.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public DataTableCollection Tables {\r
+                       get { return tableCollection; }\r
+               }\r
+\r
+               #endregion // Public Properties\r
+\r
+               #region Public Methods\r
+\r
+               [MonoTODO]\r
+               public void AcceptChanges ()\r
+               {\r
+                       foreach (DataTable tempTable in tableCollection)\r
+                               tempTable.AcceptChanges ();\r
+               }\r
+\r
+                /// <summary>\r
+                /// Clears all the tables\r
+                /// </summary>\r
+               public void Clear ()\r
+               {\r
+                       if (_xmlDataDocument != null)\r
+                               throw new NotSupportedException ("Clear function on dataset and datatable is not supported when XmlDataDocument is bound to the DataSet.");\r
+                        bool enforceConstraints = this.EnforceConstraints;\r
+                        this.EnforceConstraints = false;\r
+                        for (int t = 0; t < tableCollection.Count; t++) {\r
+                               tableCollection[t].Clear ();\r
+                       }\r
+                        this.EnforceConstraints = enforceConstraints;\r
+               }\r
+\r
+               public virtual DataSet Clone ()\r
+               {\r
+                       // need to return the same type as this...\r
+                       DataSet Copy = (DataSet) Activator.CreateInstance(GetType(), true);\r
+       \r
+                       CopyProperties (Copy);\r
+\r
+                       foreach (DataTable Table in Tables) {\r
+                       // tables are often added in no-args constructor, don't add them\r
+                       // twice.\r
+                               if (!Copy.Tables.Contains(Table.TableName)) {\r
+                                       Copy.Tables.Add (Table.Clone ());\r
+                               }\r
+                       }\r
+\r
+                       //Copy Relationships between tables after existance of tables\r
+                       //and setting properties correctly\r
+                       CopyRelations (Copy);\r
+                       \r
+                       return Copy;\r
+               }\r
+\r
+               // Copies both the structure and data for this DataSet.\r
+               public DataSet Copy ()\r
+               {\r
+                       DataSet Copy = new DataSet ();\r
+                       CopyProperties (Copy);\r
+\r
+                       // Copy DatSet's tables\r
+                       foreach (DataTable Table in Tables) \r
+                               Copy.Tables.Add (Table.Copy ());\r
+\r
+                       //Copy Relationships between tables after existance of tables\r
+                       //and setting properties correctly\r
+                       CopyRelations (Copy);\r
+\r
+                       return Copy;\r
+               }\r
+\r
+               private void CopyProperties (DataSet Copy)\r
+               {\r
+                       Copy.CaseSensitive = CaseSensitive;\r
+                       //Copy.Container = Container\r
+                       Copy.DataSetName = DataSetName;\r
+                       //Copy.DefaultViewManager\r
+                       //Copy.DesignMode\r
+                       Copy.EnforceConstraints = EnforceConstraints;\r
+                       if(ExtendedProperties.Count > 0) {\r
+                               //  Cannot copy extended properties directly as the property does not have a set accessor\r
+                Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);\r
+                ExtendedProperties.Keys.CopyTo (tgtArray, 0);\r
+                for (int i=0; i < ExtendedProperties.Count; i++)\r
+                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);\r
+                       }\r
+            Copy.Locale = Locale;\r
+                       Copy.Namespace = Namespace;\r
+                       Copy.Prefix = Prefix;                   \r
+                       //Copy.Site = Site; // FIXME : Not sure of this.\r
+\r
+               }\r
+               \r
+               \r
+               private void CopyRelations (DataSet Copy)\r
+               {\r
+\r
+                       //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\r
+\r
+                       foreach (DataRelation MyRelation in this.Relations) {\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
+                               \r
+                               foreach (DataColumn DC in MyRelation.ParentColumns) {\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
+                                       C_DC[i]=Copy.Tables[cTable].Columns[DC.ColumnName];\r
+                                       i++;\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
+                       }\r
+               }\r
+\r
+               \r
+\r
+\r
+               public DataSet GetChanges ()\r
+               {\r
+                       return GetChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
+               }\r
+\r
+               \r
+               public DataSet GetChanges (DataRowState rowStates)\r
+               {\r
+                       if (!HasChanges (rowStates))\r
+                               return null;\r
+                       \r
+                       DataSet copySet = Clone ();\r
+                       Hashtable addedRows = new Hashtable ();\r
+\r
+                       IEnumerator tableEnumerator = Tables.GetEnumerator ();\r
+                       DataTable origTable;\r
+                       DataTable copyTable;\r
+                       while (tableEnumerator.MoveNext ()) {\r
+                               origTable = (DataTable)tableEnumerator.Current;\r
+                               copyTable = copySet.Tables[origTable.TableName];\r
+                               \r
+                               // Look for relations that have this table as child\r
+                               IEnumerator relations = origTable.ParentRelations.GetEnumerator ();\r
+\r
+                               IEnumerator rowEnumerator = origTable.Rows.GetEnumerator ();\r
+                               while (rowEnumerator.MoveNext ()) {\r
+                                       DataRow row = (DataRow)rowEnumerator.Current;\r
+                                       \r
+                                       if (row.IsRowChanged (rowStates))\r
+                                               AddChangedRow (addedRows, copySet, copyTable, relations, row);\r
+                               }\r
+                       }\r
+                       return copySet;\r
+               }\r
+               \r
+               void AddChangedRow (Hashtable addedRows, DataSet copySet, DataTable copyTable, IEnumerator relations, DataRow row)\r
+               {\r
+                       if (addedRows.ContainsKey (row)) return;\r
+                       \r
+                       relations.Reset ();\r
+                       while (relations.MoveNext ()) {\r
+                               DataRow parentRow = row.GetParentRow ((DataRelation) relations.Current);\r
+                               if (parentRow == null || addedRows.ContainsKey (parentRow)) continue;\r
+                               DataTable parentCopyTable = copySet.Tables [parentRow.Table.TableName];\r
+                               AddChangedRow (addedRows, copySet, parentCopyTable, parentRow.Table.ParentRelations.GetEnumerator (), parentRow);\r
+                       }\r
+               \r
+                       DataRow newRow = copyTable.NewRow ();\r
+                       copyTable.Rows.Add (newRow);\r
+                       row.CopyValuesToRow (newRow);                   \r
+                       newRow.XmlRowID = row.XmlRowID;\r
+                       addedRows.Add (row,row);\r
+               }\r
+\r
+#if NET_2_0\r
+               [MonoTODO]\r
+               public DataTableReader GetDataReader (DataTable[] dataTables)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               public DataTableReader GetDataReader ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+#endif\r
+               \r
+               public string GetXml ()\r
+               {\r
+                       StringWriter Writer = new StringWriter ();\r
+                       WriteXml (Writer, XmlWriteMode.IgnoreSchema);\r
+                       return Writer.ToString ();\r
+               }\r
+\r
+               public string GetXmlSchema ()\r
+               {\r
+                       StringWriter Writer = new StringWriter ();\r
+                       WriteXmlSchema (Writer);\r
+                       return Writer.ToString ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               public bool HasChanges ()\r
+               {\r
+                       return HasChanges (DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
+               }\r
+\r
+               [MonoTODO]\r
+               public bool HasChanges (DataRowState rowState)\r
+               {\r
+                       if (((int)rowState & 0xffffffe0) != 0)\r
+                               throw new ArgumentOutOfRangeException ("rowState");\r
+\r
+                       DataTableCollection tableCollection = Tables;\r
+                       DataTable table;\r
+                       DataRowCollection rowCollection;\r
+                       DataRow row;\r
+\r
+                       for (int i = 0; i < tableCollection.Count; i++) {\r
+                               table = tableCollection[i];\r
+                               rowCollection = table.Rows;\r
+                               for (int j = 0; j < rowCollection.Count; j++) {\r
+                                       row = rowCollection[j];\r
+                                       if ((row.RowState & rowState) != 0)\r
+                                               return true;\r
+                               }\r
+                       }\r
+\r
+                       return false;           \r
+               }\r
+\r
+               public void InferXmlSchema (XmlReader reader, string[] nsArray)\r
+               {\r
+                       if (reader == null)\r
+                               return;\r
+                       XmlDocument doc = new XmlDocument ();\r
+                       doc.Load (reader);\r
+                       InferXmlSchema (doc, nsArray);\r
+               }\r
+\r
+               private void InferXmlSchema (XmlDocument doc, string [] nsArray)\r
+               {\r
+                       XmlDataInferenceLoader.Infer (this, doc, XmlReadMode.InferSchema, nsArray);\r
+               }\r
+\r
+               public void InferXmlSchema (Stream stream, string[] nsArray)\r
+               {\r
+                       InferXmlSchema (new XmlTextReader (stream), nsArray);\r
+               }\r
+\r
+               public void InferXmlSchema (TextReader reader, string[] nsArray)\r
+               {\r
+                       InferXmlSchema (new XmlTextReader (reader), nsArray);\r
+               }\r
+\r
+               public void InferXmlSchema (string fileName, string[] nsArray)\r
+               {\r
+                       XmlTextReader reader = new XmlTextReader (fileName);\r
+                       try {\r
+                               InferXmlSchema (reader, nsArray);\r
+                       } finally {\r
+                               reader.Close ();\r
+                       }\r
+               }\r
+\r
+#if NET_2_0\r
+               [MonoTODO]\r
+               public void Load (IDataReader reader, LoadOption loadOption, DataTable[] tables)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void Load (IDataReader reader, LoadOption loadOption, string[] tables)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+#endif\r
+\r
+               public virtual void RejectChanges ()\r
+               {\r
+                       int i;\r
+                       bool oldEnforceConstraints = this.EnforceConstraints;\r
+                       this.EnforceConstraints = false;\r
+                       \r
+                       for (i = 0; i < this.Tables.Count;i++) \r
+                               this.Tables[i].RejectChanges ();\r
+\r
+                       this.EnforceConstraints = oldEnforceConstraints;\r
+               }\r
+\r
+               public virtual void Reset ()\r
+               {\r
+                       IEnumerator constraintEnumerator;\r
+\r
+                       // first we remove all ForeignKeyConstraints (if we will not do that\r
+                       // we will get an exception when clearing the tables).\r
+                       for (int i = 0; i < Tables.Count; i++) {\r
+                               ConstraintCollection cc = Tables[i].Constraints;\r
+                               for (int j = 0; j < cc.Count; j++) {\r
+                                       if (cc[j] is ForeignKeyConstraint)\r
+                                               cc.Remove (cc[j]);\r
+                               }\r
+                       }\r
+\r
+                       Clear ();\r
+                       Relations.Clear ();\r
+                       Tables.Clear ();\r
+               }\r
+\r
+               public void WriteXml (Stream stream)\r
+               {\r
+                       XmlTextWriter writer = new XmlTextWriter (stream, null);\r
+                       writer.Formatting = Formatting.Indented;\r
+                       WriteXml (writer);\r
+               }\r
+\r
+               ///<summary>\r
+               /// Writes the current data for the DataSet to the specified file.\r
+               /// </summary>\r
+               /// <param name="filename">Fully qualified filename to write to</param>\r
+               public void WriteXml (string fileName)\r
+               {\r
+                       XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
+                       writer.Formatting = Formatting.Indented;\r
+                       writer.WriteStartDocument (true);\r
+                       try {\r
+                               WriteXml (writer);\r
+                       }\r
+                       finally {\r
+                               writer.WriteEndDocument ();\r
+                               writer.Close ();\r
+                       }\r
+               }\r
+\r
+               public void WriteXml (TextWriter writer)\r
+               {\r
+                       XmlTextWriter xwriter = new XmlTextWriter (writer);\r
+                       xwriter.Formatting = Formatting.Indented;\r
+                       WriteXml (xwriter);\r
+               }\r
+\r
+               public void WriteXml (XmlWriter writer)\r
+               {\r
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
+               }\r
+\r
+               public void WriteXml (string filename, XmlWriteMode mode)\r
+               {\r
+                       XmlTextWriter writer = new XmlTextWriter (filename, null);\r
+                       writer.Formatting = Formatting.Indented;\r
+                       writer.WriteStartDocument (true);\r
+                       \r
+                       try {\r
+                               WriteXml (writer, mode);\r
+                       }\r
+                       finally {\r
+                               writer.WriteEndDocument ();\r
+                               writer.Close ();\r
+                       }\r
+               }\r
+\r
+               public void WriteXml (Stream stream, XmlWriteMode mode)\r
+               {\r
+                       XmlTextWriter writer = new XmlTextWriter (stream, null);\r
+                       writer.Formatting = Formatting.Indented;\r
+                       WriteXml (writer, mode);\r
+               }\r
+\r
+               public void WriteXml (TextWriter writer, XmlWriteMode mode)\r
+               {\r
+                       XmlTextWriter xwriter = new XmlTextWriter (writer);\r
+                       xwriter.Formatting = Formatting.Indented;\r
+                       WriteXml (xwriter, mode);\r
+               }\r
+\r
+               public void WriteXml (XmlWriter writer, XmlWriteMode mode)\r
+               {\r
+                       if (mode == XmlWriteMode.DiffGram) {\r
+                               SetRowsID();\r
+                               WriteDiffGramElement(writer);\r
+                       }\r
+                       \r
+                       // It should not write when there is no content to be written\r
+                       bool shouldOutputContent = (mode != XmlWriteMode.DiffGram);\r
+                       for (int n = 0; n < tableCollection.Count && !shouldOutputContent; n++)\r
+                               shouldOutputContent = tableCollection [n].Rows.Count > 0;\r
+                               \r
+                       if (shouldOutputContent) {\r
+                               WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));\r
+                               \r
+                               if (mode == XmlWriteMode.WriteSchema)\r
+                                       DoWriteXmlSchema (writer);\r
+                               \r
+                               WriteTables (writer, mode, Tables, DataRowVersion.Default);\r
+                               writer.WriteEndElement ();\r
+                       }\r
+                       \r
+                       if (mode == XmlWriteMode.DiffGram) {\r
+                               if (HasChanges(DataRowState.Modified | DataRowState.Deleted)) {\r
+\r
+                                       DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);\r
+                                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");\r
+                                       WriteTables (writer, mode, beforeDS.Tables, DataRowVersion.Original);\r
+                                       writer.WriteEndElement ();\r
+                               }\r
+                       }\r
+                       \r
+                       if (mode == XmlWriteMode.DiffGram)\r
+                               writer.WriteEndElement (); // diffgr:diffgram\r
+\r
+                       writer.Flush ();\r
+               }\r
+\r
+               public void WriteXmlSchema (Stream stream)\r
+               {\r
+                       XmlTextWriter writer = new XmlTextWriter (stream, null );\r
+                       writer.Formatting = Formatting.Indented;\r
+                       WriteXmlSchema (writer);        \r
+               }\r
+\r
+               public void WriteXmlSchema (string fileName)\r
+               {\r
+                       XmlTextWriter writer = new XmlTextWriter (fileName, null);\r
+                       try {\r
+                               writer.Formatting = Formatting.Indented;\r
+                               writer.WriteStartDocument (true);\r
+                               WriteXmlSchema (writer);\r
+                       } finally {\r
+                               writer.WriteEndDocument ();\r
+                               writer.Close ();\r
+                       }\r
+               }\r
+\r
+               public void WriteXmlSchema (TextWriter writer)\r
+               {\r
+                       XmlTextWriter xwriter = new XmlTextWriter (writer);\r
+                       try {\r
+                               xwriter.Formatting = Formatting.Indented;\r
+                               WriteXmlSchema (xwriter);\r
+                       } finally {\r
+                               xwriter.Close ();\r
+                       }\r
+               }\r
+\r
+               public void WriteXmlSchema (XmlWriter writer)\r
+               {\r
+                       //Create a skeleton doc and then write the schema \r
+                       //proper which is common to the WriteXml method in schema mode\r
+                       DoWriteXmlSchema (writer);\r
+               }\r
+\r
+               public void ReadXmlSchema (Stream stream)\r
+               {\r
+                       XmlReader reader = new XmlTextReader (stream, null);\r
+                       ReadXmlSchema (reader);\r
+               }\r
+\r
+               public void ReadXmlSchema (string str)\r
+               {\r
+                       XmlReader reader = new XmlTextReader (str);\r
+                       try {\r
+                               ReadXmlSchema (reader);\r
+                       }\r
+                       finally {\r
+                               reader.Close ();\r
+                       }\r
+               }\r
+\r
+               public void ReadXmlSchema (TextReader treader)\r
+               {\r
+                       XmlReader reader = new XmlTextReader (treader);\r
+                       ReadXmlSchema (reader);                 \r
+               }\r
+\r
+               public void ReadXmlSchema (XmlReader reader)\r
+               {\r
+#if true\r
+                       new XmlSchemaDataImporter (this, reader).Process ();\r
+#else\r
+                       XmlSchemaMapper SchemaMapper = new XmlSchemaMapper (this);\r
+                       SchemaMapper.Read (reader);\r
+#endif\r
+               }\r
+\r
+               public XmlReadMode ReadXml (Stream stream)\r
+               {\r
+                       return ReadXml (new XmlTextReader (stream));\r
+               }\r
+\r
+               public XmlReadMode ReadXml (string str)\r
+               {\r
+                       XmlTextReader reader = new XmlTextReader (str);\r
+                       try {\r
+                               return ReadXml (reader);\r
+                       }\r
+                       finally {\r
+                               reader.Close ();\r
+                       }\r
+               }\r
+\r
+               public XmlReadMode ReadXml (TextReader reader)\r
+               {\r
+                       return ReadXml (new XmlTextReader (reader));\r
+               }\r
+\r
+               public XmlReadMode ReadXml (XmlReader r)\r
+               {\r
+                       return ReadXml (r, XmlReadMode.Auto);\r
+               }\r
+\r
+               public XmlReadMode ReadXml (Stream stream, XmlReadMode mode)\r
+               {\r
+                       return ReadXml (new XmlTextReader (stream), mode);\r
+               }\r
+\r
+               public XmlReadMode ReadXml (string str, XmlReadMode mode)\r
+               {\r
+                       XmlTextReader reader = new XmlTextReader (str);\r
+                       try {\r
+                               return ReadXml (reader, mode);\r
+                       }\r
+                       finally {\r
+                               reader.Close ();\r
+                       }\r
+               }\r
+\r
+               public XmlReadMode ReadXml (TextReader reader, XmlReadMode mode)\r
+               {\r
+                       return ReadXml (new XmlTextReader (reader), mode);\r
+               }\r
+\r
+               // LAMESPEC: XmlReadMode.Fragment is far from presisely\r
+               // documented. MS.NET infers schema against this mode.\r
+               public XmlReadMode ReadXml (XmlReader input, XmlReadMode mode)\r
+               {\r
+                       switch (input.ReadState) {\r
+                       case ReadState.EndOfFile:\r
+                       case ReadState.Error:\r
+                       case ReadState.Closed:\r
+                               return mode;\r
+                       }\r
+                       // Skip XML declaration and prolog\r
+                       input.MoveToContent ();\r
+                       if (input.EOF)\r
+                               return mode;\r
+\r
+                       // FIXME: We need more decent code here, but for now\r
+                       // I don't know the precise MS.NET behavior, I just\r
+                       // delegate to specific read process.\r
+                       switch (mode) {\r
+                       case XmlReadMode.IgnoreSchema:\r
+                               return ReadXmlIgnoreSchema (input, mode, true);\r
+                       case XmlReadMode.ReadSchema:\r
+                               return ReadXmlReadSchema (input, mode, true);\r
+                       }\r
+                       // remaining modes are: Auto, InferSchema, Fragment, Diffgram\r
+\r
+                       XmlReader reader = input;\r
+\r
+                       int depth = reader.Depth;\r
+                       XmlReadMode result = mode;\r
+                       bool skippedTopLevelElement = false;\r
+                       string potentialDataSetName = null;\r
+                       XmlDocument doc = null;\r
+                       bool shouldReadData = mode != XmlReadMode.DiffGram;\r
+                       bool shouldNotInfer = Tables.Count > 0;\r
+\r
+                       switch (mode) {\r
+                       case XmlReadMode.Auto:\r
+                       case XmlReadMode.InferSchema:\r
+                               doc = new XmlDocument ();\r
+                               do {\r
+                                       doc.AppendChild (doc.ReadNode (reader));\r
+                               } while (!reader.EOF &&\r
+                                       doc.DocumentElement == null);\r
+                               reader = new XmlNodeReader (doc);\r
+                               reader.MoveToContent ();\r
+                               break;\r
+                       case XmlReadMode.DiffGram:\r
+                               if (!(reader.LocalName == "diffgram" &&\r
+                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace))\r
+                                       goto case XmlReadMode.Auto;\r
+                               break;\r
+                       }\r
+\r
+                       switch (mode) {\r
+                       case XmlReadMode.Auto:\r
+                       case XmlReadMode.InferSchema:\r
+                       case XmlReadMode.ReadSchema:\r
+                               if (!(reader.LocalName == "diffgram" &&\r
+                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&\r
+                                       !(reader.LocalName == "schema" &&\r
+                                       reader.NamespaceURI == XmlSchema.Namespace))\r
+                                       potentialDataSetName = reader.LocalName;\r
+                               goto default;\r
+                       case XmlReadMode.Fragment:\r
+                               break;\r
+                       default:\r
+                               if (!(reader.LocalName == "diffgram" &&\r
+                                       reader.NamespaceURI == XmlConstants.DiffgrNamespace) &&\r
+                                       !(reader.LocalName == "schema" &&\r
+                                       reader.NamespaceURI == XmlSchema.Namespace)) {\r
+                                       if (!reader.IsEmptyElement) {\r
+                                               reader.Read ();\r
+                                               reader.MoveToContent ();\r
+                                               skippedTopLevelElement = true;\r
+                                       }\r
+                                       else {\r
+                                               switch (mode) {\r
+                                               case XmlReadMode.Auto:\r
+                                               case XmlReadMode.InferSchema:\r
+                                                       DataSetName = reader.LocalName;\r
+                                                       break;\r
+                                               }\r
+                                               reader.Read ();\r
+                                       }\r
+                               }\r
+                               break;\r
+                       }\r
+\r
+                       // If schema, then read the first element as schema \r
+                       if (reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {\r
+                               shouldNotInfer = true;\r
+                               switch (mode) {\r
+                               case XmlReadMode.IgnoreSchema:\r
+                               case XmlReadMode.InferSchema:\r
+                                       reader.Skip ();\r
+                                       break;\r
+                               case XmlReadMode.Fragment:\r
+                                       ReadXmlSchema (reader);\r
+                                       break;\r
+                               case XmlReadMode.DiffGram:\r
+                               case XmlReadMode.Auto:\r
+                                       if (Tables.Count == 0) {\r
+                                               ReadXmlSchema (reader);\r
+                                               if (mode == XmlReadMode.Auto)\r
+                                                       result = XmlReadMode.ReadSchema;\r
+                                       } else {\r
+                                       // otherwise just ignore and return IgnoreSchema\r
+                                               reader.Skip ();\r
+                                               result = XmlReadMode.IgnoreSchema;\r
+                                       }\r
+                                       break;\r
+                               case XmlReadMode.ReadSchema:\r
+                                       ReadXmlSchema (reader);\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       // If diffgram, then read the first element as diffgram \r
+                       if (reader.LocalName == "diffgram" && reader.NamespaceURI == XmlConstants.DiffgrNamespace) {\r
+                               switch (mode) {\r
+                               case XmlReadMode.Auto:\r
+                               case XmlReadMode.IgnoreSchema:\r
+                               case XmlReadMode.DiffGram:\r
+                                       XmlDiffLoader DiffLoader = new XmlDiffLoader (this);\r
+                                       DiffLoader.Load (reader);\r
+                                       if (mode == XmlReadMode.Auto)\r
+                                               result = XmlReadMode.DiffGram;\r
+                                       shouldReadData = false;\r
+                                       break;\r
+                               case XmlReadMode.Fragment:\r
+                                       reader.Skip ();\r
+                                       break;\r
+                               default:\r
+                                       reader.Skip ();\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       // if schema after diffgram, just skip it.\r
+                       if (!shouldReadData && reader.LocalName == "schema" && reader.NamespaceURI == XmlSchema.Namespace) {\r
+                               shouldNotInfer = true;\r
+                               switch (mode) {\r
+                               default:\r
+                                       reader.Skip ();\r
+                                       break;\r
+                               case XmlReadMode.ReadSchema:\r
+                               case XmlReadMode.DiffGram:\r
+                                       if (Tables.Count == 0)\r
+                                               ReadXmlSchema (reader);\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (reader.EOF)\r
+                               return result == XmlReadMode.Auto ?\r
+                                       potentialDataSetName != null && !shouldNotInfer ?\r
+                                       XmlReadMode.InferSchema :\r
+                                       XmlReadMode.IgnoreSchema : result;\r
+\r
+                       // Otherwise, read as dataset... but only when required.\r
+                       if (shouldReadData && !shouldNotInfer) {\r
+                               switch (mode) {\r
+                               case XmlReadMode.Auto:\r
+                                       if (Tables.Count > 0)\r
+                                               goto case XmlReadMode.IgnoreSchema;\r
+                                       else\r
+                                               goto case XmlReadMode.InferSchema;\r
+                               case XmlReadMode.InferSchema:\r
+                                       InferXmlSchema (doc, null);\r
+                                       if (mode == XmlReadMode.Auto)\r
+                                               result = XmlReadMode.InferSchema;\r
+                                       break;\r
+                               case XmlReadMode.IgnoreSchema:\r
+                               case XmlReadMode.Fragment:\r
+                               case XmlReadMode.DiffGram:\r
+                                       break;\r
+                               default:\r
+                                       shouldReadData = false;\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       if (shouldReadData) {\r
+                               XmlReader dataReader = reader;\r
+                               if (doc != null) {\r
+                                       dataReader = new XmlNodeReader (doc);\r
+                                       dataReader.MoveToContent ();\r
+                               }\r
+                               if (reader.NodeType == XmlNodeType.Element)\r
+                                       XmlDataReader.ReadXml (this, dataReader,\r
+                                               mode);\r
+                       }\r
+\r
+                       if (skippedTopLevelElement) {\r
+                               switch (result) {\r
+                               case XmlReadMode.Auto:\r
+                               case XmlReadMode.InferSchema:\r
+//                                     DataSetName = potentialDataSetName;\r
+//                                     result = XmlReadMode.InferSchema;\r
+                                       break;\r
+                               }\r
+                               if (reader.NodeType == XmlNodeType.EndElement)\r
+                                       reader.ReadEndElement ();\r
+                       }\r
+//*\r
+                       while (input.Depth > depth)\r
+                               input.Read ();\r
+                       if (input.NodeType == XmlNodeType.EndElement)\r
+                               input.Read ();\r
+//*/\r
+                       input.MoveToContent ();\r
+\r
+                       return result == XmlReadMode.Auto ?\r
+                               XmlReadMode.IgnoreSchema : result;\r
+               }\r
+               #endregion // Public Methods\r
+\r
+               #region Public Events\r
+\r
+               [DataCategory ("Action")]\r
+               [DataSysDescription ("Occurs when it is not possible to merge schemas for two tables with the same name.")]\r
+               public event MergeFailedEventHandler MergeFailed;\r
+\r
+               #endregion // Public Events\r
+\r
+               #region IListSource methods\r
+               IList IListSource.GetList ()\r
+               {\r
+                       return DefaultViewManager;\r
+               }\r
+               \r
+               bool IListSource.ContainsListCollection {\r
+                       get {\r
+                               return true;\r
+                       }\r
+               }\r
+               #endregion IListSource methods\r
+               \r
+               #region ISupportInitialize methods\r
+               public void BeginInit ()\r
+               {\r
+               }\r
+               \r
+               public void EndInit ()\r
+               {\r
+               }\r
+               #endregion\r
+\r
+               #region ISerializable\r
+               void ISerializable.GetObjectData (SerializationInfo si, StreamingContext sc)\r
+               {\r
+                       StringWriter sw = new StringWriter ();\r
+                       XmlTextWriter writer = new XmlTextWriter (sw);\r
+                       DoWriteXmlSchema (writer);\r
+                       writer.Flush ();\r
+                       si.AddValue ("XmlSchema", sw.ToString ());\r
+                       \r
+                       sw = new StringWriter ();\r
+                       writer = new XmlTextWriter (sw);\r
+                       WriteXml (writer, XmlWriteMode.DiffGram);\r
+                       writer.Flush ();\r
+                       si.AddValue ("XmlDiffGram", sw.ToString ());\r
+               }\r
+               #endregion\r
+               \r
+               #region Protected Methods\r
+               protected void GetSerializationData (SerializationInfo info, StreamingContext context)\r
+               {\r
+                       string s = info.GetValue ("XmlSchema", typeof (String)) as String;\r
+                       XmlTextReader reader = new XmlTextReader (new StringReader (s));\r
+                       ReadXmlSchema (reader);\r
+                       reader.Close ();\r
+                       \r
+                       s = info.GetValue ("XmlDiffGram", typeof (String)) as String;\r
+                       reader = new XmlTextReader (new StringReader (s));\r
+                       ReadXml (reader, XmlReadMode.DiffGram);\r
+                       reader.Close ();\r
+               }\r
+               \r
+               \r
+               protected virtual System.Xml.Schema.XmlSchema GetSchemaSerializable ()\r
+               {\r
+                       return null;\r
+               }\r
+               \r
+               protected virtual void ReadXmlSerializable (XmlReader reader)\r
+               {\r
+                       ReadXml (reader);\r
+               }\r
+\r
+               void IXmlSerializable.ReadXml (XmlReader reader)\r
+               {\r
+                       ReadXmlSerializable(reader);\r
+               }\r
+               \r
+               void IXmlSerializable.WriteXml (XmlWriter writer)\r
+               {\r
+                       DoWriteXmlSchema (writer);\r
+                       WriteXml (writer, XmlWriteMode.DiffGram);\r
+               }\r
+\r
+               XmlSchema IXmlSerializable.GetSchema ()\r
+               {\r
+                       return GetSchemaSerializable ();\r
+               }\r
+\r
+               protected virtual bool ShouldSerializeRelations ()\r
+               {\r
+                       return true;\r
+               }\r
+               \r
+               protected virtual bool ShouldSerializeTables ()\r
+               {\r
+                       return true;\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent)\r
+               {\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected virtual void OnRemoveRelation (DataRelation relation)\r
+               {\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected virtual void OnRemoveTable (DataTable table)\r
+               {\r
+               }\r
+\r
+               internal virtual void OnMergeFailed (MergeFailedEventArgs e)\r
+               {\r
+                       if (MergeFailed != null)\r
+                               MergeFailed (this, e);\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected internal void RaisePropertyChanging (string name)\r
+               {\r
+               }\r
+               #endregion\r
+\r
+               #region Private Methods\r
+\r
+               private XmlReadMode ReadXmlIgnoreSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)\r
+               {\r
+                       if (input.LocalName == "schema" &&\r
+                               input.NamespaceURI == XmlSchema.Namespace) {\r
+                               input.Skip ();\r
+                       }\r
+                       else if (input.LocalName == "diffgram" &&\r
+                               input.NamespaceURI == XmlConstants.DiffgrNamespace) {\r
+                               XmlDiffLoader DiffLoader = new XmlDiffLoader (this);\r
+                               DiffLoader.Load (input);\r
+                       }\r
+                       else if (checkRecurse ||\r
+                               input.LocalName == DataSetName &&\r
+                               input.NamespaceURI == Namespace) {\r
+                               XmlDataReader.ReadXml (this, input, mode);\r
+                       }\r
+                       else if (checkRecurse && !input.IsEmptyElement) {\r
+                               int depth = input.Depth;\r
+                               input.Read ();\r
+                               input.MoveToContent ();\r
+                               ReadXmlIgnoreSchema (input, mode, false);\r
+                               while (input.Depth > depth)\r
+                                       input.Skip ();\r
+                               if (input.NodeType == XmlNodeType.EndElement)\r
+                                       input.ReadEndElement ();\r
+                       }\r
+                       input.MoveToContent ();\r
+                       return XmlReadMode.IgnoreSchema;\r
+               }\r
+\r
+               private XmlReadMode ReadXmlReadSchema (XmlReader input, XmlReadMode mode, bool checkRecurse)\r
+               {\r
+                       if (input.LocalName == "schema" &&\r
+                               input.NamespaceURI == XmlSchema.Namespace) {\r
+                               ReadXmlSchema (input);\r
+                       }\r
+                       else if (checkRecurse && !input.IsEmptyElement) {\r
+                               int depth = input.Depth;\r
+                               input.Read ();\r
+                               input.MoveToContent ();\r
+                               ReadXmlReadSchema (input, mode, false);\r
+                               while (input.Depth > depth)\r
+                                       input.Skip ();\r
+                               if (input.NodeType == XmlNodeType.EndElement)\r
+                                       input.ReadEndElement ();\r
+                       }\r
+                       else\r
+                               input.Skip ();\r
+                       input.MoveToContent ();\r
+                       return XmlReadMode.ReadSchema;\r
+               }\r
+\r
+               internal static string WriteObjectXml (object o)\r
+               {\r
+                       switch (Type.GetTypeCode (o.GetType ())) {\r
+                               case TypeCode.Boolean:\r
+                                       return XmlConvert.ToString ((Boolean) o);\r
+                               case TypeCode.Byte:\r
+                                       return XmlConvert.ToString ((Byte) o);\r
+                               case TypeCode.Char:\r
+                                       return XmlConvert.ToString ((Char) o);\r
+                               case TypeCode.DateTime:\r
+                                       return XmlConvert.ToString ((DateTime) o);\r
+                               case TypeCode.Decimal:\r
+                                       return XmlConvert.ToString ((Decimal) o);\r
+                               case TypeCode.Double:\r
+                                       return XmlConvert.ToString ((Double) o);\r
+                               case TypeCode.Int16:\r
+                                       return XmlConvert.ToString ((Int16) o);\r
+                               case TypeCode.Int32:\r
+                                       return XmlConvert.ToString ((Int32) o);\r
+                               case TypeCode.Int64:\r
+                                       return XmlConvert.ToString ((Int64) o);\r
+                               case TypeCode.SByte:\r
+                                       return XmlConvert.ToString ((SByte) o);\r
+                               case TypeCode.Single:\r
+                                       return XmlConvert.ToString ((Single) o);\r
+                               case TypeCode.UInt16:\r
+                                       return XmlConvert.ToString ((UInt16) o);\r
+                               case TypeCode.UInt32:\r
+                                       return XmlConvert.ToString ((UInt32) o);\r
+                               case TypeCode.UInt64:\r
+                                       return XmlConvert.ToString ((UInt64) o);\r
+                       }\r
+                       if (o is TimeSpan) return XmlConvert.ToString ((TimeSpan) o);\r
+                       if (o is Guid) return XmlConvert.ToString ((Guid) o);\r
+                       if (o is byte[]) return Convert.ToBase64String ((byte[])o);\r
+                       return o.ToString ();\r
+               }\r
+               \r
+               private void WriteTables (XmlWriter writer, XmlWriteMode mode, DataTableCollection tableCollection, DataRowVersion version)\r
+               {\r
+                       //Write out each table in order, providing it is not\r
+                       //part of another table structure via a nested parent relationship\r
+                       foreach (DataTable table in tableCollection) {\r
+                               bool isTopLevel = true;\r
+                               /*\r
+                               foreach (DataRelation rel in table.ParentRelations) {\r
+                                       if (rel.Nested) {\r
+                                               isTopLevel = false;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                               */\r
+                               if (isTopLevel) {\r
+                                       WriteTable ( writer, table, mode, version);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void WriteTable (XmlWriter writer, DataTable table, XmlWriteMode mode, DataRowVersion version)\r
+               {\r
+                       DataRow[] rows = new DataRow [table.Rows.Count];\r
+                       table.Rows.CopyTo (rows, 0);\r
+                       WriteTable (writer, rows, mode, version, true);\r
+               }\r
+\r
+               private void WriteTable (XmlWriter writer,\r
+                       DataRow [] rows,\r
+                       XmlWriteMode mode,\r
+                       DataRowVersion version, bool skipIfNested)\r
+               {\r
+                       //The columns can be attributes, hidden, elements, or simple content\r
+                       //There can be 0-1 simple content cols or 0-* elements\r
+                       System.Collections.ArrayList atts;\r
+                       System.Collections.ArrayList elements;\r
+                       DataColumn simple = null;\r
+\r
+                       if (rows.Length == 0) return;\r
+                       DataTable table = rows[0].Table;\r
+                       SplitColumns (table, out atts, out elements, out simple);\r
+                       //sort out the namespacing\r
+                       string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;\r
+                       int relationCount = table.ParentRelations.Count;\r
+                       DataRelation oneRel = relationCount == 1 ? table.ParentRelations [0] : null;\r
+\r
+                       foreach (DataRow row in rows) {\r
+                               if (skipIfNested) {\r
+                                       // Skip rows that is a child of any tables.\r
+                                       switch (relationCount) {\r
+                                       case 0:\r
+                                               break;\r
+                                       case 1:\r
+                                               if (!oneRel.Nested)\r
+                                                       break;\r
+                                               if (row.GetParentRow (oneRel) != null)\r
+                                                       continue;\r
+                                               break;\r
+                                       case 2:\r
+                                               bool skip = false;\r
+                                               for (int i = 0; i < table.ParentRelations.Count; i++) {\r
+                                                       DataRelation prel = table.ParentRelations [i];\r
+                                                       if (!prel.Nested)\r
+                                                               continue;\r
+                                                       if (row.GetParentRow (prel) != null) {\r
+                                                               skip = true;\r
+                                                               continue;\r
+                                                       }\r
+                                               }\r
+                                               if (skip)\r
+                                                       continue;\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+                               if (!row.HasVersion(version) || \r
+                                  (mode == XmlWriteMode.DiffGram && row.RowState == DataRowState.Unchanged \r
+                                     && version == DataRowVersion.Original))\r
+                                       continue;\r
+                               \r
+                               // First check are all the rows null. If they are we just write empty element\r
+                               bool AllNulls = true;\r
+                               foreach (DataColumn dc in table.Columns) {\r
+                               \r
+                                       if (row [dc.ColumnName, version] != DBNull.Value) {\r
+                                               AllNulls = false;\r
+                                               break;\r
+                                       } \r
+                               }\r
+\r
+                               // If all of the columns were null, we have to write empty element\r
+                               if (AllNulls) {\r
+                                       writer.WriteElementString (XmlConvert.EncodeLocalName (table.TableName), "");\r
+                                       continue;\r
+                               }\r
+                               \r
+                               WriteTableElement (writer, mode, table, row, version);\r
+                               \r
+                               foreach (DataColumn col in atts) {                                      \r
+                                       WriteColumnAsAttribute (writer, mode, col, row, version);\r
+                               }\r
+                               \r
+                               if (simple != null) {\r
+                                       writer.WriteString (WriteObjectXml (row[simple, version]));\r
+                               }\r
+                               else {                                  \r
+                                       foreach (DataColumn col in elements) {\r
+                                               WriteColumnAsElement (writer, mode, col, row, version);\r
+                                       }\r
+                               }\r
+                               \r
+                               foreach (DataRelation relation in table.ChildRelations) {\r
+                                       if (relation.Nested) {\r
+                                               WriteTable (writer, row.GetChildRows (relation), mode, version, false);\r
+                                       }\r
+                               }\r
+                               \r
+                               writer.WriteEndElement ();\r
+                       }\r
+\r
+               }\r
+\r
+               private void WriteColumnAsElement (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)\r
+               {\r
+                       string colnspc = null;\r
+                       object rowObject = row [col, version];\r
+                                                                       \r
+                       if (rowObject == null || rowObject == DBNull.Value)\r
+                               return;\r
+\r
+                       if (col.Namespace != String.Empty)\r
+                               colnspc = col.Namespace;\r
+       \r
+                       //TODO check if I can get away with write element string\r
+                       WriteStartElement (writer, mode, colnspc, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName));\r
+                       writer.WriteString (WriteObjectXml (rowObject));\r
+                       writer.WriteEndElement ();\r
+               }\r
+\r
+               private void WriteColumnAsAttribute (XmlWriter writer, XmlWriteMode mode, DataColumn col, DataRow row, DataRowVersion version)\r
+               {\r
+                       if (!row.IsNull (col))\r
+                               WriteAttributeString (writer, mode, col.Namespace, col.Prefix, XmlConvert.EncodeLocalName (col.ColumnName), WriteObjectXml (row[col, version]));\r
+               }\r
+\r
+               private void WriteTableElement (XmlWriter writer, XmlWriteMode mode, DataTable table, DataRow row, DataRowVersion version)\r
+               {\r
+                       //sort out the namespacing\r
+                       string nspc = table.Namespace.Length > 0 ? table.Namespace : Namespace;\r
+\r
+                       WriteStartElement (writer, mode, nspc, table.Prefix, XmlConvert.EncodeLocalName (table.TableName));\r
+\r
+                       if (mode == XmlWriteMode.DiffGram) {\r
+                               WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "id", table.TableName + (row.XmlRowID + 1));\r
+                               WriteAttributeString (writer, mode, XmlConstants.MsdataNamespace, XmlConstants.MsdataPrefix, "rowOrder", XmlConvert.ToString (row.XmlRowID));\r
+                               string modeName = null;\r
+                               if (row.RowState == DataRowState.Modified)\r
+                                       modeName = "modified";\r
+                               else if (row.RowState == DataRowState.Added)\r
+                                       modeName = "inserted";\r
+\r
+                               if (version != DataRowVersion.Original && modeName != null)\r
+                                       WriteAttributeString (writer, mode, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "hasChanges", modeName);\r
+                       }\r
+               }\r
+                   \r
+               private void WriteStartElement (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name)\r
+               {\r
+                       writer.WriteStartElement (prefix, name, nspc);\r
+               }\r
+               \r
+               private void WriteAttributeString (XmlWriter writer, XmlWriteMode mode, string nspc, string prefix, string name, string stringValue)\r
+               {\r
+                       switch ( mode) {\r
+                               case XmlWriteMode.WriteSchema:\r
+                                       writer.WriteAttributeString (prefix, name, nspc);\r
+                                       break;\r
+                               case XmlWriteMode.DiffGram:\r
+                                       writer.WriteAttributeString (prefix, name, nspc,stringValue);\r
+                                       break;\r
+                               default:\r
+                                       writer.WriteAttributeString (name, stringValue);\r
+                                       break;                                  \r
+                       };\r
+               }\r
+               \r
+               internal void WriteIndividualTableContent (XmlWriter writer, DataTable table, XmlWriteMode mode)\r
+               {\r
+                       if (mode == XmlWriteMode.DiffGram) {\r
+                               SetTableRowsID (table);\r
+                               WriteDiffGramElement (writer);\r
+                       }\r
+                       \r
+                       WriteStartElement (writer, mode, Namespace, Prefix, XmlConvert.EncodeName (DataSetName));\r
+                       \r
+                       WriteTable (writer, table, mode, DataRowVersion.Default);\r
+                       \r
+                       if (mode == XmlWriteMode.DiffGram) {\r
+                               writer.WriteEndElement (); //DataSet name\r
+                               if (HasChanges (DataRowState.Modified | DataRowState.Deleted)) {\r
+\r
+                                       DataSet beforeDS = GetChanges (DataRowState.Modified | DataRowState.Deleted);   \r
+                                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "before");\r
+                                       WriteTable (writer, beforeDS.Tables [table.TableName], mode, DataRowVersion.Original);\r
+                                       writer.WriteEndElement ();\r
+                               }\r
+                       }\r
+                       writer.WriteEndElement (); // DataSet name or diffgr:diffgram\r
+               }\r
+               \r
+               private void DoWriteXmlSchema (XmlWriter writer)\r
+               {\r
+                       if (writer.WriteState == WriteState.Start)\r
+                               writer.WriteStartDocument ();\r
+                       XmlSchemaWriter.WriteXmlSchema (this, writer);\r
+               }\r
+               \r
+               ///<summary>\r
+               /// Helper function to split columns into attributes elements and simple\r
+               /// content\r
+               /// </summary>\r
+               internal static void SplitColumns (DataTable table, \r
+                       out ArrayList atts, \r
+                       out ArrayList elements, \r
+                       out DataColumn simple)\r
+               {\r
+                       //The columns can be attributes, hidden, elements, or simple content\r
+                       //There can be 0-1 simple content cols or 0-* elements\r
+                       atts = new System.Collections.ArrayList ();\r
+                       elements = new System.Collections.ArrayList ();\r
+                       simple = null;\r
+                       \r
+                       //Sort out the columns\r
+                       foreach (DataColumn col in table.Columns) {\r
+                               switch (col.ColumnMapping) {\r
+                                       case MappingType.Attribute:\r
+                                               atts.Add (col);\r
+                                               break;\r
+                                       case MappingType.Element:\r
+                                               elements.Add (col);\r
+                                               break;\r
+                                       case MappingType.SimpleContent:\r
+                                               if (simple != null) {\r
+                                                       throw new System.InvalidOperationException ("There may only be one simple content element");\r
+                                               }\r
+                                               simple = col;\r
+                                               break;\r
+                                       default:\r
+                                               //ignore Hidden elements\r
+                                               break;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void WriteDiffGramElement(XmlWriter writer)\r
+               {\r
+                       WriteStartElement (writer, XmlWriteMode.DiffGram, XmlConstants.DiffgrNamespace, XmlConstants.DiffgrPrefix, "diffgram");\r
+                       WriteAttributeString(writer, XmlWriteMode.DiffGram, null, "xmlns", XmlConstants.MsdataPrefix, XmlConstants.MsdataNamespace);\r
+               }\r
+\r
+               private void SetRowsID()\r
+               {\r
+                       foreach (DataTable Table in Tables)\r
+                               SetTableRowsID (Table);\r
+               }\r
+               \r
+               private void SetTableRowsID (DataTable Table)\r
+               {\r
+                       int dataRowID = 0;\r
+                       foreach (DataRow Row in Table.Rows) {\r
+                               Row.XmlRowID = dataRowID;\r
+                               dataRowID++;\r
+                       }\r
+               }\r
+               #endregion //Private Xml Serialisation\r
+       }\r
+}\r
index da7d68cea220c8a2e9f9311de19b919c7732d93d..05bf1e9eda3b0e9e501fca09363f5890157776af 100644 (file)
-//
-// System.Data.DataTable.cs
-//
-// Author:
-//   Franklin Wise <gracenote@earthlink.net>
-//   Christopher Podurgiel (cpodurgiel@msn.com)
-//   Daniel Morgan <danmorg@sc.rr.com>
-//   Rodrigo Moya <rodrigo@ximian.com>
-//   Tim Coleman (tim@timcoleman.com)
-//   Ville Palo <vi64pa@koti.soon.fi>
-//   Sureshkumar T <tsureshkumar@novell.com>
-//
-// (C) Chris Podurgiel
-// (C) Ximian, Inc 2002
-// Copyright (C) Tim Coleman, 2002-2003
-// Copyright (C) Daniel Morgan, 2002-2003
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Data.Common;
-using System.Collections;
-using System.ComponentModel;
-using System.Globalization;
-using System.IO;
-using System.Runtime.Serialization;
-using System.Xml;
-using System.Xml.Schema;
-using Mono.Data.SqlExpressions;
-
-namespace System.Data {
-       //[Designer]
-       [ToolboxItem (false)]
-       [DefaultEvent ("RowChanging")]
-       [DefaultProperty ("TableName")]
-       [DesignTimeVisible (false)]
-       [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DataTableEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
-       [Serializable]
-       public class DataTable : MarshalByValueComponent, IListSource, ISupportInitialize, ISerializable 
-       {
-               #region Fields
-
-               internal DataSet dataSet;   
-               
-               private bool _caseSensitive;
-               private DataColumnCollection _columnCollection;
-               private ConstraintCollection _constraintCollection;
-               // never access it. Use DefaultView.
-               private DataView _defaultView;
-
-               private string _displayExpression;
-               private PropertyCollection _extendedProperties;
-               private bool _hasErrors;
-               private CultureInfo _locale;
-               private int _minimumCapacity;
-               private string _nameSpace;
-               private DataRelationCollection _childRelations; 
-               private DataRelationCollection _parentRelations;
-               private string _prefix;
-               private DataColumn[] _primaryKey;
-               private DataRowCollection _rows;
-               private ISite _site;
-               private string _tableName;
-               private bool _containsListCollection;
-               private string _encodedTableName;
-               internal bool _duringDataLoad;
-               internal bool _nullConstraintViolationDuringDataLoad;
-               private bool dataSetPrevEnforceConstraints;
-               private bool dataTablePrevEnforceConstraints;
-               private bool enforceConstraints = true;
-               private DataRowBuilder _rowBuilder;
-               private ArrayList _indexes;
-               private RecordCache _recordCache;
-               private int _defaultValuesRowIndex = -1;
-               protected internal bool fInitInProgress;
-
-               // If CaseSensitive property is changed once it does not anymore follow owner DataSet's 
-               // CaseSensitive property. So when you lost you virginity it's gone for ever
-               private bool _virginCaseSensitive = true;
-               
-               #endregion //Fields
-               
-               private delegate void PostEndInit();
-
-               /// <summary>
-               /// Initializes a new instance of the DataTable class with no arguments.
-               /// </summary>
-               public DataTable () 
-               {
-                       dataSet = null;
-                       _columnCollection = new DataColumnCollection(this);
-                       _constraintCollection = new ConstraintCollection(this); 
-                       _extendedProperties = new PropertyCollection();
-                       _tableName = "";
-                       _nameSpace = null;
-                       _caseSensitive = false;         //default value
-                       _displayExpression = null;
-                       _primaryKey = null;
-                       _site = null;
-                       _rows = new DataRowCollection (this);
-                       _indexes = new ArrayList();
-                       _recordCache = new RecordCache(this);
-                       
-                       //LAMESPEC: spec says 25 impl does 50
-                       _minimumCapacity = 50;
-                       
-                       _childRelations = new DataRelationCollection.DataTableRelationCollection (this);
-                       _parentRelations = new DataRelationCollection.DataTableRelationCollection (this);
-               }
-
-               /// <summary>
-               /// Intitalizes a new instance of the DataTable class with the specified table name.
-               /// </summary>
-               public DataTable (string tableName) : this () 
-               {
-                       _tableName = tableName;
-               }
-
-               /// <summary>
-               /// Initializes a new instance of the DataTable class with the SerializationInfo and the StreamingContext.
-               /// </summary>
-               [MonoTODO]
-               protected DataTable (SerializationInfo info, StreamingContext context)
-                       : this () 
-               {
-                       string schema = info.GetString ("XmlSchema");
-                       string data = info.GetString ("XmlDiffGram");
-                       
-                       DataSet ds = new DataSet ();
-                       ds.ReadXmlSchema (new StringReader (schema));
-                       ds.Tables [0].CopyProperties (this);
-                       ds = new DataSet ();
-                       ds.Tables.Add (this);
-                       ds.ReadXml (new StringReader (data), XmlReadMode.DiffGram);
-                       ds.Tables.Remove (this);
-/* keeping for a while. With the change above, we shouldn't have to consider 
- * DataTable mode in schema inference/read.
-                       XmlSchemaMapper mapper = new XmlSchemaMapper (this);
-                       XmlTextReader xtr = new XmlTextReader(new StringReader (schema));
-                       mapper.Read (xtr);
-                       
-                       XmlDiffLoader loader = new XmlDiffLoader (this);
-                       xtr = new XmlTextReader(new StringReader (data));
-                       loader.Load (xtr);
-*/
-               }
-
-#if NET_2_0
-               public DataTable (string tableName, string tbNamespace)
-                       : this (tableName)
-               {
-                       _nameSpace = tbNamespace;
-               }
-#endif
-
-               /// <summary>
-               /// Indicates whether string comparisons within the table are case-sensitive.
-               /// </summary>
-               [DataSysDescription ("Indicates whether comparing strings within the table is case sensitive.")]        
-               public bool CaseSensitive {
-                       get { 
-                               if (_virginCaseSensitive && dataSet != null)
-                                       return dataSet.CaseSensitive; 
-                               else
-                                       return _caseSensitive;
-                               }
-                       set {
-                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {
-                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");
-                               }
-                               _virginCaseSensitive = false;
-                               _caseSensitive = value; 
-                       }
-               }
-
-               internal void ChangedDataColumn (DataRow dr, DataColumn dc, object pv) 
-               {
-                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);
-                       OnColumnChanged(e);
-               }
-
-               internal void ChangingDataColumn (DataRow dr, DataColumn dc, object pv) 
-               {
-                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);
-                       OnColumnChanging (e);
-               }
-
-               internal void DeletedDataRow (DataRow dr, DataRowAction action) 
-               {
-                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);
-                       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>
-               [Browsable (false)]
-               [DataSysDescription ("Returns the child relations for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public DataRelationCollection ChildRelations {
-                       get {
-                               return _childRelations;
-                       }
-               }
-
-               /// <summary>
-               /// Gets the collection of columns that belong to this table.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds the columns for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public DataColumnCollection Columns {
-                       get { return _columnCollection; }
-               }
-
-               /// <summary>
-               /// Gets the collection of constraints maintained by this table.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("The collection that holds the constraints for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public ConstraintCollection Constraints {
-                       get { return _constraintCollection; }
-               }
-
-               /// <summary>
-               /// Gets the DataSet that this table belongs to.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Indicates the DataSet to which this table belongs.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public DataSet DataSet {
-                       get { return dataSet; }
-               }
-
-               
-
-               /// <summary>
-               /// Gets a customized view of the table which may 
-               /// include a filtered view, or a cursor position.
-               /// </summary>
-               [MonoTODO]      
-               [Browsable (false)]
-               [DataSysDescription ("This is the default DataView for the table.")]
-               public DataView DefaultView {
-                       get {
-                               if (_defaultView == null)
-                                       _defaultView = new DataView (this);
-                               return _defaultView;
-                       }
-               }
-               
-
-               /// <summary>
-               /// Gets or sets the expression that will return 
-               /// a value used to represent this table in the user interface.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("The expression used to compute the data-bound value of this row.")]       
-               [DefaultValue ("")]
-               public string DisplayExpression {
-                       get { return _displayExpression == null ? "" : _displayExpression; }
-                       set { _displayExpression = value; }
-               }
-
-               /// <summary>
-               /// Gets the collection of customized user information.
-               /// </summary>
-               [Browsable (false)]
-               [DataCategory ("Data")]
-               [DataSysDescription ("The collection that holds custom user information.")]
-               public PropertyCollection ExtendedProperties {
-                       get { return _extendedProperties; }
-               }
-
-               /// <summary>
-               /// Gets a value indicating whether there are errors in 
-               /// any of the_rows in any of the tables of the DataSet to 
-               /// which the table belongs.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Returns whether the table has errors.")]
-               public bool 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>
-               /// Gets or sets the locale information used to 
-               /// compare strings within the table.
-               /// </summary>
-               [DataSysDescription ("Indicates a locale under which to compare strings within the table.")]
-               public CultureInfo Locale {
-                       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 (_childRelations.Count > 0 || _parentRelations.Count > 0) {
-                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");
-                               }
-                               if (_locale == null || !_locale.Equals(value))
-                                       _locale = value; 
-                       }
-               }
-
-               /// <summary>
-               /// Gets or sets the initial starting size for this table.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates an initial starting size for this table.")]
-               [DefaultValue (50)]
-               public int MinimumCapacity {
-                       get { return _minimumCapacity; }
-                       set { _minimumCapacity = value; }
-               }
-
-               /// <summary>
-               /// Gets or sets the namespace for the XML represenation 
-               /// of the data stored in the DataTable.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the XML uri namespace for the elements contained in this table.")]
-               public string Namespace {
-                       get {
-                               if (_nameSpace != null)
-                                       return _nameSpace;
-                               else if (dataSet != null)
-                                       return dataSet.Namespace;
-                               return String.Empty;
-                       }
-                       set { _nameSpace = value; }
-               }
-
-               /// <summary>
-               /// Gets the collection of parent relations for 
-               /// this DataTable.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Returns the parent relations for this table.")]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public DataRelationCollection ParentRelations {
-                       get {   
-                               return _parentRelations;
-                       }
-               }
-
-               /// <summary>
-               /// Gets or sets the namespace for the XML represenation
-               ///  of the data stored in the DataTable.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the Prefix of the namespace used for this table in XML representation.")]
-               [DefaultValue ("")]
-               public string Prefix {
-                       get { return _prefix == null ? "" : _prefix; }
-                       set {
-                               // Prefix cannot contain any special characters other than '_' and ':'
-                               for (int i = 0; i < value.Length; i++) {
-                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))
-                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");
-                               }
-                               _prefix = value;
-                       }
-               }
-
-               /// <summary>
-               /// Gets or sets an array of columns that function as 
-               /// primary keys for the data table.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the column(s) that represent the primary key for this table.")]
-               [EditorAttribute ("Microsoft.VSDesigner.Data.Design.PrimaryKeyEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]
-               [TypeConverterAttribute ("System.Data.PrimaryKeyTypeConverter, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
-               public DataColumn[] PrimaryKey {
-                       get {
-                               UniqueConstraint uc = UniqueConstraint.GetPrimaryKeyConstraint( Constraints);
-                               if (null == uc) return new DataColumn[] {};
-                               return uc.Columns;
-                       }
-                       set {
-                               UniqueConstraint oldPKConstraint = UniqueConstraint.GetPrimaryKeyConstraint( Constraints);
-                               
-                               // first check if value is the same as current PK.
-                               if (oldPKConstraint != null && DataColumn.AreColumnSetsTheSame(value, oldPKConstraint.Columns))
-                                       return;
-
-                               // remove PK Constraint
-                               if(oldPKConstraint != null) {
-                                       Constraints.Remove(oldPKConstraint);
-                               }
-                               
-                               if (value != null) {
-                                       //Does constraint exist for these columns
-                                       UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet(
-                                               this.Constraints, (DataColumn[]) value);
-                               
-                                       //if constraint doesn't exist for columns
-                                       //create new unique primary key constraint
-                                       if (null == uc) {
-                                               foreach (DataColumn Col in (DataColumn[]) value) {
-
-                                                       if (Col.Table == null)
-                                                               break;
-
-                                                       if (Columns.IndexOf (Col) < 0)
-                                                               throw new ArgumentException ("PrimaryKey columns do not belong to this table.");
-                                               }
-
-
-                                               uc = new UniqueConstraint( (DataColumn[]) value, true);
-                                       
-                                               Constraints.Add (uc);
-                                       }
-                                       else { 
-                                               //set existing constraint as the new primary key
-                                               UniqueConstraint.SetAsPrimaryKey(this.Constraints, uc);
-                                       }
-
-                                       // if we really supplied some columns fo primary key - 
-                                       // rebuild indexes fo all foreign key constraints
-                                       if(value.Length > 0) {
-                                               foreach(ForeignKeyConstraint constraint in this.Constraints.ForeignKeyConstraints){
-                                                       try {
-                                                               constraint.AssertConstraint();
-                                                       } catch (ConstraintException ex) {
-                                                               throw new ArgumentException (ex.Message, ex);
-                                                       }
-                                               }
-                                       }
-                               }
-                               else {
-                                       // if primary key is null now - drop all the indexes for foreign key constraints
-                                       foreach(ForeignKeyConstraint constraint in this.Constraints.ForeignKeyConstraints){
-                                               Index index = constraint.Index;
-                                               constraint.Index = null;
-                                               this.DropIndex(index);
-                                       }
-                               }
-                               
-                       }
-               }
-
-               /// <summary>
-               /// Gets the collection of_rows that belong to this table.
-               /// </summary>
-               [Browsable (false)]
-               [DataSysDescription ("Indicates the collection that holds the rows of data for this table.")]   
-               public DataRowCollection Rows {
-                       get { return _rows; }
-               }
-
-               /// <summary>
-               /// Gets or sets an System.ComponentModel.ISite 
-               /// for the DataTable.
-               /// </summary>
-               [Browsable (false)]
-               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]
-               public override ISite Site {
-                       get { return _site; }
-                       set { _site = value; }
-               }
-
-               /// <summary>
-               /// Gets or sets the name of the the DataTable.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the name used to look up this table in the Tables collection of a DataSet.")]
-               [DefaultValue ("")]     
-               [RefreshProperties (RefreshProperties.All)]
-               public string TableName {
-                       get { return _tableName == null ? "" : _tableName; }
-                       set { _tableName = value; }
-               }
-               
-               bool IListSource.ContainsListCollection {
-                       get {
-                               // the collection is a DataView
-                               return false;
-                       }
-               }
-               
-               internal RecordCache RecordCache {
-                       get {
-                               return _recordCache;
-                       }
-               }
-               
-               private bool EnforceConstraints {
-                       get { return enforceConstraints; }
-                       set {
-                               if (value != enforceConstraints) {
-                                       if (value) {
-                                               // first assert all unique constraints
-                                               foreach (UniqueConstraint uc in this.Constraints.UniqueConstraints)
-                                               uc.AssertConstraint ();
-                                               // then assert all foreign keys
-                                               foreach (ForeignKeyConstraint fk in this.Constraints.ForeignKeyConstraints)
-                                                       fk.AssertConstraint ();
-                                       }
-                                       enforceConstraints = value;
-                               }
-                       }
-               }
-
-               internal bool RowsExist(DataColumn[] columns, DataColumn[] relatedColumns,DataRow row)
-               {
-                       int curIndex = row.IndexFromVersion(DataRowVersion.Default);
-                       int tmpRecord = RecordCache.NewRecord();
-
-                       try {
-                               for (int i = 0; i < relatedColumns.Length; i++) {
-                                       // according to MSDN: the DataType value for both columns must be identical.
-                                       columns[i].DataContainer.CopyValue(relatedColumns[i].DataContainer, curIndex, tmpRecord);
-                               }
-
-                               return RowsExist(columns, tmpRecord, relatedColumns.Length);
-                       }
-                       finally {
-                               RecordCache.DisposeRecord(tmpRecord);
-                       }
-               }
-
-               bool RowsExist(DataColumn[] columns, int index, int length)
-               {
-                       bool rowsExist = false;
-                       Index indx = this.GetIndexByColumns (columns);
-
-                       if (indx != null) { // lookup for a row in index                        
-                               rowsExist = (indx.FindSimple (index, length, false) != null);
-                       } 
-                       
-                       if(indx == null || rowsExist == false) { 
-                               // no index or rowExist= false, we have to perform full-table scan
-                               // check that there is a parent for this row.
-                               foreach (DataRow thisRow in this.Rows) {
-                                       if (thisRow.RowState != DataRowState.Deleted) {
-                                               bool match = true;
-                                               // check if the values in the columns are equal
-                                               int thisIndex = thisRow.IndexFromVersion(DataRowVersion.Current);
-                                               foreach (DataColumn column in columns) {
-                                                       if (column.DataContainer.CompareValues(thisIndex, index) != 0) {
-                                                               match = false;
-                                                               break;
-                                                       }       
-                                               }
-                                               if (match) {// there is a row with columns values equals to those supplied.
-                                                       rowsExist = true;
-                                                       break;
-                                               }
-                                       }
-                               }                               
-                       }
-                       return rowsExist;
-               }
-
-               /// <summary>
-               /// Commits all the changes made to this table since the 
-               /// last time AcceptChanges was called.
-               /// </summary>
-               public void AcceptChanges () 
-               {
-                       //FIXME: Do we need to validate anything here or
-                       //try to catch any errors to deal with them?
-                       
-                       // 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++;
-                       }
-               }
-
-               /// <summary>
-               /// Begins the initialization of a DataTable that is used 
-               /// on a form or used by another component. The initialization
-               /// occurs at runtime.
-               /// </summary>
-               public virtual void BeginInit () 
-               {
-                       fInitInProgress = true;
-               }
-
-               /// <summary>
-               /// Turns off notifications, index maintenance, and 
-               /// constraints while loading data.
-               /// </summary>
-               [MonoTODO]
-               public void BeginLoadData () 
-               {
-                       if (!this._duringDataLoad)
-                       {
-                               //duringDataLoad is important to EndLoadData and
-                               //for not throwing unexpected exceptions.
-                               this._duringDataLoad = true;
-                               this._nullConstraintViolationDuringDataLoad = false;
-                       
-                               if (this.dataSet != null)
-                               {
-                                       //Saving old Enforce constraints state for later
-                                       //use in the EndLoadData.
-                                       this.dataSetPrevEnforceConstraints = this.dataSet.EnforceConstraints;
-                                       this.dataSet.EnforceConstraints = false;
-                               }
-                               else {
-                                       //if table does not belong to any data set use EnforceConstraints of the table
-                                       this.dataTablePrevEnforceConstraints = this.EnforceConstraints;
-                                       this.EnforceConstraints = false;
-                               }
-                       }
-                       return;
-               }
-
-               /// <summary>
-               /// Clears the DataTable of all data.
-               /// </summary>
-               public void Clear () {
-                        // Foriegn key constraints are checked in _rows.Clear method
-                       _rows.Clear ();
-#if NET_2_0
-                        OnTableCleared (new DataTableClearEventArgs (this));
-#endif // NET_2_0
-
-               }
-
-               /// <summary>
-               /// Clones the structure of the DataTable, including
-               ///  all DataTable schemas and constraints.
-               /// </summary>
-               public virtual DataTable Clone () 
-               {
-                        // Use Activator so we can use non-public constructors.
-                       DataTable Copy = (DataTable) Activator.CreateInstance(GetType(), true);                 
-                       CopyProperties (Copy);
-                       return Copy;
-               }
-
-               /// <summary>
-               /// Computes the given expression on the current_rows that 
-               /// pass the filter criteria.
-               /// </summary>
-               [MonoTODO]
-               public object Compute (string expression, string filter) 
-               {
-                       // expression is an aggregate function
-                       // filter is an expression used to limit rows
-
-                       DataRow[] rows = Select(filter);
-                       
-                       Parser parser = new Parser (rows);
-                       IExpression expr = parser.Compile (expression);
-                       object obj = expr.Eval (rows[0]);
-                       
-                       return obj;
-               }
-
-               /// <summary>
-               /// Copies both the structure and data for this DataTable.
-               /// </summary>
-               public DataTable Copy () 
-               {
-                       DataTable copy = Clone();
-
-                       copy._duringDataLoad = true;
-                       foreach (DataRow row in Rows) {
-                               DataRow newRow = copy.NewNotInitializedRow();
-                               copy.Rows.Add(newRow);
-                               CopyRow(row,newRow);
-                       }
-                       copy._duringDataLoad = false;           
-                       return copy;
-               }
-
-               internal void CopyRow(DataRow fromRow,DataRow toRow)
-               {
-                       fromRow.CopyState(toRow);
-
-                       if (fromRow.HasVersion(DataRowVersion.Original)) {
-                               toRow._original = toRow.Table.RecordCache.CopyRecord(this,fromRow._original,-1);
-                       }
-
-                       if (fromRow.HasVersion(DataRowVersion.Current)) {
-                               toRow._current = toRow.Table.RecordCache.CopyRecord(this,fromRow._current,-1);
-                       }
-               }
-
-               private void CopyProperties (DataTable Copy) 
-               {
-                                       
-                       Copy.CaseSensitive = CaseSensitive;
-                       Copy._virginCaseSensitive = _virginCaseSensitive;
-
-                       // Copy.ChildRelations
-                       // Copy.Constraints
-                       // Copy.Container
-                       // Copy.DefaultView
-                       // Copy.DesignMode
-                       Copy.DisplayExpression = DisplayExpression;
-                       if(ExtendedProperties.Count > 0) {
-                               //  Cannot copy extended properties directly as the property does not have a set accessor
-                               Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);
-                               ExtendedProperties.Keys.CopyTo (tgtArray, 0);
-                               for (int i=0; i < ExtendedProperties.Count; i++)
-                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);
-                       }
-                       Copy.Locale = Locale;
-                       Copy.MinimumCapacity = MinimumCapacity;
-                       Copy.Namespace = Namespace;
-                       // Copy.ParentRelations
-                       Copy.Prefix = Prefix;
-                       Copy.Site = Site;
-                       Copy.TableName = TableName;
-
-
-
-                       // Copy columns
-                       foreach (DataColumn Column in Columns) {
-                               // When cloning a table, the columns may be added in the default
-                               // constructor.
-                               if (!Copy.Columns.Contains(Column.ColumnName))                                                          Copy.Columns.Add (CopyColumn (Column)); 
-                       }
-
-                       CopyConstraints(Copy);
-                       // 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;
-                       }
-               }
-
-               private void CopyConstraints(DataTable copy)
-               {
-                       UniqueConstraint origUc;
-                       UniqueConstraint copyUc;
-                       for (int i = 0; i < this.Constraints.Count; i++)
-                       {
-                               if (this.Constraints[i] is UniqueConstraint)
-                               {
-                                       origUc = (UniqueConstraint)this.Constraints[i];
-                                       DataColumn[] columns = new DataColumn[origUc.Columns.Length];
-                                       for (int j = 0; j < columns.Length; j++)
-                                               columns[j] = copy.Columns[origUc.Columns[j].ColumnName];
-                                       
-                                       copyUc = new UniqueConstraint(origUc.ConstraintName, columns, origUc.IsPrimaryKey);
-                                       copy.Constraints.Add(copyUc);
-                               }
-                       }
-               }
-               /// <summary>
-               /// Ends the initialization of a DataTable that is used 
-               /// on a form or used by another component. The 
-               /// initialization occurs at runtime.
-               /// </summary>
-               [MonoTODO]
-               public virtual void EndInit () 
-               {
-                       fInitInProgress = false;
-                       // Add the constraints
-                       PostEndInit _postEndInit = new PostEndInit (_constraintCollection.PostEndInit);
-                       _postEndInit();
-               }
-
-               /// <summary>
-               /// Turns on notifications, index maintenance, and 
-               /// constraints after loading data.
-               /// </summary>
-               public void EndLoadData() 
-               {
-                       int i = 0;
-                       if (this._duringDataLoad) 
-                       {
-                               
-                               if (this.dataSet !=null)
-                               {
-                                       //Getting back to previous EnforceConstraint state
-                                       this.dataSet.EnforceConstraints = this.dataSetPrevEnforceConstraints;
-                               }
-                               else {
-                                       //Getting back to the table's previous EnforceConstraint state
-                                       this.EnforceConstraints = this.dataTablePrevEnforceConstraints;
-                               }
-
-                               if(this._nullConstraintViolationDuringDataLoad) {
-                                       this._nullConstraintViolationDuringDataLoad = false;
-                                       throw new ConstraintException ("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");
-                               }
-
-                               //Returning from loading mode, raising exceptions as usual
-                               this._duringDataLoad = false;
-
-                       }
-
-               }
-
-               /// <summary>
-               /// Gets a copy of the DataTable that contains all
-               ///  changes made to it since it was loaded or 
-               ///  AcceptChanges was last called.
-               /// </summary>
-               public DataTable GetChanges() 
-               {
-                       return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);
-               }
-
-               /// <summary>
-               /// Gets a copy of the DataTable containing all 
-               /// changes made to it since it was last loaded, or 
-               /// since AcceptChanges was called, filtered by DataRowState.
-               /// </summary>
-               public DataTable GetChanges(DataRowState rowStates) 
-               {
-                       DataTable copyTable = null;
-
-                       IEnumerator rowEnumerator = Rows.GetEnumerator();
-                       while (rowEnumerator.MoveNext()) {
-                               DataRow row = (DataRow)rowEnumerator.Current;
-                               // The spec says relationship constraints may cause Unchanged parent rows to be included but
-                               // MS .NET 1.1 does not include Unchanged rows even if their child rows are changed.
-                               if (row.IsRowChanged(rowStates)) {
-                                       if (copyTable == null)
-                                               copyTable = Clone();
-                                       DataRow newRow = copyTable.NewRow();
-                                       row.CopyValuesToRow(newRow);
-                                       copyTable.Rows.Add (newRow);
-                               }
-                       }
-                        
-                       return copyTable;
-               }
-
-#if NET_2_0
-               [MonoTODO]
-               public DataTableReader GetDataReader ()
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               /// <summary>
-               /// Gets an array of DataRow objects that contain errors.
-               /// </summary>
-               public DataRow[] GetErrors () 
-               {
-                       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>
-               /// This member is only meant to support Mono's infrastructure 
-               /// </summary>
-               protected virtual DataTable CreateInstance () 
-               {
-                       return Activator.CreateInstance (this.GetType (), true) as DataTable;
-               }
-
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure 
-               /// </summary>
-               protected virtual Type GetRowType () 
-               {
-                       return typeof (DataRow);
-               }
-
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure 
-               /// 
-               /// Used for Data Binding between System.Web.UI. controls 
-               /// like a DataGrid
-               /// or
-               /// System.Windows.Forms controls like a DataGrid
-               /// </summary>
-               IList IListSource.GetList () 
-               {
-                       IList list = (IList) DefaultView;
-                       return list;
-               }
-                               
-               /// <summary>
-               /// Copies a DataRow into a DataTable, preserving any 
-               /// property settings, as well as original and current values.
-               /// </summary>
-               public void ImportRow (DataRow row) 
-               {
-                       DataRow newRow = NewRow();
-                       row.CopyValuesToRow (newRow);
-                        if (row.RowState != DataRowState.Detached)
-                                Rows.Add (newRow);
-                       row.CopyState (newRow);
-               }
-
-               internal int DefaultValuesRowIndex
-               {
-                       get {
-                               return _defaultValuesRowIndex;
-                       }       
-               }
-
-               /// <summary>
-               /// This member is only meant to support Mono's infrastructure          
-               /// </summary>
-               void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) 
-               {
-                       DataSet dset;
-                       if (dataSet != null)
-                               dset = dataSet;
-                       else {
-                               dset = new DataSet ("tmpDataSet");
-                               dset.Tables.Add (this);
-                       }
-                       
-                       StringWriter sw = new StringWriter ();
-                       XmlTextWriter tw = new XmlTextWriter (sw);
-                       tw.Formatting = Formatting.Indented;
-                       dset.WriteIndividualTableContent (tw, this, XmlWriteMode.DiffGram);
-                       tw.Close ();
-                       
-                       StringWriter sw2 = new StringWriter ();
-                       DataTableCollection tables = new DataTableCollection (dset);
-                       tables.Add (this);
-                       XmlSchemaWriter.WriteXmlSchema (dset, new XmlTextWriter (sw2), tables, null);
-                       sw2.Close ();
-                       
-                       info.AddValue ("XmlSchema", sw2.ToString(), typeof(string));
-                       info.AddValue ("XmlDiffGram", sw.ToString(), typeof(string));
-               }
-
-#if NET_2_0
-                /// <summary>
-                ///     Loads the table with the values from the reader
-                /// </summary>
-               public void Load (IDataReader reader)
-               {
-                        Load (reader, LoadOption.PreserveChanges);
-               }
-
-                /// <summary>
-                ///     Loads the table with the values from the reader and the pattern
-                ///     of the changes to the existing rows or the new rows are based on
-                ///     the LoadOption passed.
-                /// </summary>
-               public void Load (IDataReader reader, LoadOption loadOption)
-               {
-                        bool prevEnforceConstr = this.EnforceConstraints;
-                        try {
-                                this.EnforceConstraints = false;
-                                int [] mapping = DbDataAdapter.BuildSchema (reader, this, SchemaType.Mapped, 
-                                                                            MissingSchemaAction.AddWithKey,
-                                                                            MissingMappingAction.Passthrough, 
-                                                                            new DataTableMappingCollection ());
-                                DbDataAdapter.FillFromReader (this,
-                                                              reader,
-                                                              0, // start from
-                                                              0, // all records
-                                                              mapping,
-                                                              loadOption);
-                        } finally {
-                                this.EnforceConstraints = prevEnforceConstr;
-                        }
-               }
-
-                
-#endif
-
-               /// <summary>
-               /// Finds and updates a specific row. If no matching row
-               ///  is found, a new row is created using the given values.
-               /// </summary>
-               public DataRow LoadDataRow (object[] values, bool fAcceptChanges) 
-               {
-                       DataRow row = null;
-                       if (PrimaryKey.Length == 0) {
-                               row = Rows.Add (values);
-                               if (fAcceptChanges)
-                                       row.AcceptChanges ();
-                       }
-                       else {
-                               bool hasPrimaryValues = true;
-                               // initiate an array that has the values of the primary keys.
-                               object[] keyValues = new object[PrimaryKey.Length];
-                               for (int i = 0; i < keyValues.Length && hasPrimaryValues; i++)
-                               {
-                                       if(PrimaryKey[i].Ordinal < values.Length)
-                                               keyValues[i] = values[PrimaryKey[i].Ordinal];
-                                       else
-                                               hasPrimaryValues = false;
-                               }
-                               
-                               if (hasPrimaryValues){
-                                       // find the row in the table.
-                                       row = Rows.Find(keyValues);
-                               }
-                               
-                               if (row == null)
-                                       row = Rows.Add (values);
-                               else
-                                       row.ItemArray = values;
-                               
-                               if (fAcceptChanges)
-                                       row.AcceptChanges ();
-                       }
-                               
-                       return row;
-               }
-
-               internal DataRow LoadDataRow(IDataRecord record, int[] mapping, bool fAcceptChanges)
-               {
-                       DataRow row = null;
-                       if (PrimaryKey.Length == 0) {
-                               row = NewRow();
-                               row.SetValuesFromDataRecord(record, mapping);
-                               Rows.Add (row);
-
-                               if (fAcceptChanges) {
-                                       row.AcceptChanges();
-                               }
-                       }
-                       else {
-                               bool hasPrimaryValues = true;
-                               int tmpRecord = this.RecordCache.NewRecord();
-                               try {
-                                       for (int i = 0; i < PrimaryKey.Length && hasPrimaryValues; i++) {
-                                               DataColumn primaryKeyColumn = PrimaryKey[i];
-                                               int ordinal = primaryKeyColumn.Ordinal;
-                                               if(mapping [ordinal] >= 0) {
-                                                       primaryKeyColumn.DataContainer.SetItemFromDataRecord(tmpRecord,record,mapping[ordinal]);
-                                               }
-                                               else {
-                                                       hasPrimaryValues = false;
-                                               }
-                                       }
-                                       
-                                       if (hasPrimaryValues) {
-                                               // find the row in the table.
-                                               row = Rows.Find(tmpRecord, PrimaryKey.Length);
-                                       }
-                               }
-                               finally {
-                                       this.RecordCache.DisposeRecord(tmpRecord);
-                               }
-
-                               if (row == null) {
-                                       row = NewRow();
-                                       row.SetValuesFromDataRecord(record, mapping);
-                                       Rows.Add (row);
-                               }
-                               else {
-                                       row.SetValuesFromDataRecord(record, mapping);
-                               }
-                               
-                               if (fAcceptChanges) {
-                                       row.AcceptChanges();
-                               }
-                       }                               
-                       return row;
-               }
-
-#if NET_2_0
-                /// <summary>
-                ///     Loads the given values into an existing row if matches or creates
-                ///     the new row popluated with the values.
-                /// </summary>
-                /// <remarks>
-                ///     This method searches for the values using primary keys and it first
-                ///     searches using the original values of the rows and if not found, it
-                ///     searches using the current version of the row.
-                /// </remarks>
-               public DataRow LoadDataRow (object [] values, LoadOption loadOption)
-               {
-                        DataRow row  = null;
-                        bool new_row = false;
-                        
-                        // Find Data DataRow
-                        if (this.PrimaryKey.Length > 0) {
-                                object [] keyValues = new object [this.PrimaryKey.Length];
-                                for (int i = 0; i < keyValues.Length; i++)
-                                        keyValues [i] = values [this.PrimaryKey [i].Ordinal];
-                                row = this.Rows.Find (keyValues, DataRowVersion.Original );
-                                if (row == null) 
-                                        row = this.Rows.Find (keyValues, DataRowVersion.Current);
-                        }
-                                
-                        // If not found, add new row
-                        if (row == null) {
-                                row = this.NewRow ();
-                                new_row = true;
-                        }
-
-                        bool deleted = row.RowState == DataRowState.Deleted;
-
-                        if (deleted && loadOption == LoadOption.OverwriteChanges)
-                                row.RejectChanges ();                        
-
-                        row.Load (values, loadOption, new_row);
-
-                        if (deleted && loadOption == LoadOption.Upsert) {
-                                row = this.NewRow ();
-                                row.Load (values, loadOption, new_row = true);
-                        }
-
-                        if (new_row) {
-                                this.Rows.Add (row);
-                                if (loadOption == LoadOption.OverwriteChanges ||
-                                    loadOption == LoadOption.PreserveChanges) {
-                                        row.AcceptChanges ();
-                                }
-                        }
-
-                        return row;
-               }
-
-               [MonoTODO]
-               public void Merge (DataTable table)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void Merge (DataTable table, bool preserveChanges)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               /// <summary>
-               /// Creates a new DataRow with the same schema as the table.
-               /// </summary>
-               public DataRow NewRow () 
-               {
-                       // initiate only one row builder.
-                       if (_rowBuilder == null)
-                               _rowBuilder = new DataRowBuilder (this, 0, 0);
-                       
-                       // new row get id -1.
-                       _rowBuilder._rowId = -1;
-
-                       // initialize default values row for the first time
-                       if ( _defaultValuesRowIndex == -1 ) {
-                               _defaultValuesRowIndex = RecordCache.NewRecord();
-                               foreach(DataColumn column in Columns) {
-                                       column.DataContainer[_defaultValuesRowIndex] = column.DefaultValue;
-                               }
-                       }
-
-                       return this.NewRowFromBuilder (_rowBuilder);
-               }
-
-               /// <summary>
-               /// This member supports the .NET Framework infrastructure
-               ///  and is not intended to be used directly from your code.
-               /// </summary>
-               protected internal DataRow[] NewRowArray (int size) 
-               {
-                       return (DataRow[]) Array.CreateInstance (GetRowType (), size);
-               }
-
-               /// <summary>
-               /// Creates a new row from an existing row.
-               /// </summary>
-               protected virtual DataRow NewRowFromBuilder (DataRowBuilder builder) 
-               {
-                       return new DataRow (builder);
-               }
-               
-               internal DataRow NewNotInitializedRow()
-               {
-                       return new DataRow(this,-1);
-               }
-
-#if NET_2_0
-               [MonoTODO]
-               XmlReadMode ReadXml (Stream stream)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               public void ReadXmlSchema (Stream stream)
-               {
-                       ReadXmlSchema (new XmlTextReader (stream));
-               }
-
-               public void ReadXmlSchema (TextReader reader)
-               {
-                       ReadXmlSchema (new XmlTextReader (reader));
-               }
-
-               public void ReadXmlSchema (string fileName)
-               {
-                       XmlTextReader reader = null;
-                       try {
-                               reader = new XmlTextReader (fileName);
-                               ReadXmlSchema (reader);
-                       } finally {
-                               if (reader != null)
-                                       reader.Close ();
-                       }
-               }
-
-               public void ReadXmlSchema (XmlReader reader)
-               {
-                       DataSet ds = new DataSet ();
-                       new XmlSchemaDataImporter (ds, reader).Process ();
-                       DataTable target = null;
-                       if (TableName == String.Empty) {
-                               if (ds.Tables.Count > 0)
-                                       target = ds.Tables [0];
-                       }
-                       else {
-                               target = ds.Tables [TableName];
-                               if (target == null)
-                                       throw new ArgumentException (String.Format ("DataTable '{0}' does not match to any DataTable in source.", TableName));
-                       }
-                       if (target != null)
-                               target.CopyProperties (this);
-               }
-#endif
-
-               /// <summary>
-               /// Rolls back all changes that have been made to the 
-               /// table since it was loaded, or the last time AcceptChanges
-               ///  was called.
-               /// </summary>
-               public void RejectChanges () 
-               {       
-                       for (int i = _rows.Count - 1; i >= 0; i--) {
-                               DataRow row = _rows [i];
-                               if (row.RowState != DataRowState.Unchanged)
-                                       _rows [i].RejectChanges ();
-                       }
-               }
-
-               /// <summary>
-               /// Resets the DataTable to its original state.
-               /// </summary>          
-               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>
-               /// Gets an array of all DataRow objects.
-               /// </summary>
-               public DataRow[] Select () 
-               {
-                       return Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);
-               }
-
-               /// <summary>
-               /// Gets an array of all DataRow objects that match 
-               /// the filter criteria in order of primary key (or 
-               /// lacking one, order of addition.)
-               /// </summary>
-               public DataRow[] Select (string filterExpression) 
-               {
-                       return Select(filterExpression, String.Empty, DataViewRowState.CurrentRows);
-               }
-
-               /// <summary>
-               /// Gets an array of all DataRow objects that 
-               /// match the filter criteria, in the the 
-               /// specified sort order.
-               /// </summary>
-               public DataRow[] Select (string filterExpression, string sort) 
-               {
-                       return Select(filterExpression, sort, DataViewRowState.CurrentRows);
-               }
-
-               /// <summary>
-               /// Gets an array of all DataRow objects that match
-               /// the filter in the order of the sort, that match 
-               /// the specified state.
-               /// </summary>
-               [MonoTODO]
-               public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates) 
-               {
-                       if (filterExpression == null)
-                               filterExpression = String.Empty;
-
-                       IExpression filter = null;
-                       if (filterExpression != String.Empty) {
-                               Parser parser = new Parser ();
-                               filter = parser.Compile (filterExpression);
-                       }
-                       SortableColumn[] sortableColumns = null;
-                       if (sort != null && !sort.Equals(String.Empty))
-                               sortableColumns = SortableColumn.ParseSortString (this, sort, true);
-
-                       return Select (filter, sortableColumns, recordStates);
-               }
-
-               internal DataRow [] Select (IExpression filter, SortableColumn [] sortableColumns, DataViewRowState recordStates)
-               {
-                       ArrayList rowList = new ArrayList();
-                       int recordStateFilter = GetRowStateFilter(recordStates);
-                       foreach (DataRow row in Rows) {
-                               if (((int)row.RowState & recordStateFilter) != 0) {
-                                       if (filter != null && !filter.EvalBoolean (row))
-                                               continue;
-                                       rowList.Add (row);
-                               }
-                       }
-
-                       DataRow[] dataRows = (DataRow[])rowList.ToArray(GetRowType ());
-
-                       if (sortableColumns != null) {
-                               RowSorter rowSorter = new RowSorter (this, sortableColumns);
-                               dataRows = rowSorter.SortRows (dataRows);
-
-                               sortableColumns = null;
-                               rowSorter = null;
-                       }
-
-                       return dataRows;
-               }
-
-               internal void AddIndex (Index index)
-               {
-                       if (_indexes == null)
-                               _indexes = new ArrayList();
-
-                       _indexes.Add (index);
-               }
-
-               internal void RemoveIndex (Index indx)
-               {
-                       _indexes.Remove (indx);
-               }
-
-               internal Index GetIndexByColumns (DataColumn[] columns)
-               {
-                       return GetIndexByColumns(columns,false,false);
-               }
-
-//             internal Index GetIndexByColumnsExtended(DataColumn[] columns)
-//             {
-//                     DataColumn[] pkColumns = this.PrimaryKey;
-//                     if((pkColumns != null) && (pkColumns.Length > 0)) {
-//                             DataColumn[] cols = new DataColumn[columns.Length + pkColumns.Length];                                  
-//                             Array.Copy(columns,0,cols,0,columns.Length);
-//                             Array.Copy(pkColumns,0,cols,columns.Length,pkColumns.Length);
-//
-//                             return _getIndexByColumns(cols,false,false);
-//                     } else {
-//                             return null;
-//                     }
-//             }
-
-               internal Index GetIndexByColumns (DataColumn[] columns, bool unique)
-               {
-                       return GetIndexByColumns(columns,unique,true);
-               }
-
-//             internal Index GetIndexByColumnsExtended(DataColumn[] columns, bool unique)
-//             {
-//                     DataColumn[] pkColumns = this.PrimaryKey;
-//                     if((pkColumns != null) && (pkColumns.Length > 0)) {
-//                             DataColumn[] cols = new DataColumn[columns.Length + pkColumns.Length];                                  
-//                             Array.Copy(columns,0,cols,0,columns.Length);
-//                             Array.Copy(pkColumns,0,cols,columns.Length,pkColumns.Length);
-//
-//                             return _getIndexByColumns(cols,unique,true);
-//                     } else  {
-//                             return null;
-//                     }
-//             }
-
-               internal Index GetIndexByColumns(DataColumn[] columns, bool unique, bool useUnique)
-               {
-                       if (_indexes != null) {
-                               foreach (Index indx in _indexes) {
-                                       bool found = false;
-                                       if ((!useUnique) || ((useUnique)&& (indx.IsUnique))) {
-                                               found = DataColumn.AreColumnSetsTheSame (indx.Columns, columns);
-                                       }
-                                       if (found)
-                                               return indx;
-                               }
-                       }
-
-                       return null;
-               }
-
-               internal void DeleteRowFromIndexes (DataRow row)
-               {
-                       if (_indexes != null) {
-                               foreach (Index indx in _indexes) {
-                                       indx.Delete (row);
-                               }
-                       }
-               }
-
-               private static int GetRowStateFilter(DataViewRowState recordStates)
-               {
-                       int flag = 0;
-
-                       if ((recordStates & DataViewRowState.Added) != 0)
-                               flag |= (int)DataRowState.Added;
-                       if ((recordStates & DataViewRowState.Deleted) != 0)
-                               flag |= (int)DataRowState.Deleted;
-                       if ((recordStates & DataViewRowState.ModifiedCurrent) != 0)
-                               flag |= (int)DataRowState.Modified;
-                       if ((recordStates & DataViewRowState.ModifiedOriginal) != 0)
-                               flag |= (int)DataRowState.Modified;
-                       if ((recordStates & DataViewRowState.Unchanged) != 0)
-                               flag |= (int)DataRowState.Unchanged;
-
-                       return flag;
-               }
-
-               /// <summary>
-               /// Gets the TableName and DisplayExpression, if 
-               /// there is one as a concatenated string.
-               /// </summary>
-               public override string ToString() 
-               {
-                       //LAMESPEC: spec says concat the two. impl puts a 
-                       //plus sign infront of DisplayExpression
-                       string retVal = TableName;
-                       if(DisplayExpression != null && DisplayExpression != "")
-                               retVal += " + " + DisplayExpression;
-                       return retVal;
-               }
-
-#if NET_2_0
-               private XmlWriterSettings GetWriterSettings ()
-               {
-                       XmlWriterSettings s = new XmlWriterSettings ();
-                       s.Indent = true;
-                       return s;
-               }
-
-               public void WriteXml (Stream stream)
-               {
-                       WriteXml (stream, XmlWriteMode.IgnoreSchema);
-               }
-
-               public void WriteXml (TextWriter writer)
-               {
-                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
-               }
-
-               public void WriteXml (XmlWriter writer)
-               {
-                       WriteXml (writer, XmlWriteMode.IgnoreSchema);
-               }
-
-               public void WriteXml (string fileName)
-               {
-                       WriteXml (fileName, XmlWriteMode.IgnoreSchema);
-               }
-
-               public void WriteXml (Stream stream, XmlWriteMode mode)
-               {
-                       WriteXml (XmlWriter.Create (stream, GetWriterSettings ()), mode);
-               }
-
-               public void WriteXml (TextWriter writer, XmlWriteMode mode)
-               {
-                       WriteXml (XmlWriter.Create (writer, GetWriterSettings ()), mode);
-               }
-
-               [MonoTODO]
-               public void WriteXml (XmlWriter writer, XmlWriteMode mode)
-               {
-                       throw new NotImplementedException ();
-               }
-
-               public void WriteXml (string fileName, XmlWriteMode mode)
-               {
-                       XmlWriter xw = null;
-                       try {
-                               xw = XmlWriter.Create (fileName, GetWriterSettings ());
-                               WriteXml (xw, mode);
-                       } finally {
-                               if (xw != null)
-                                       xw.Close ();
-                       }
-               }
-
-               public void WriteXmlSchema (Stream stream)
-               {
-                       WriteXmlSchema (XmlWriter.Create (stream, GetWriterSettings ()));
-               }
-
-               public void WriteXmlSchema (TextWriter writer)
-               {
-                       WriteXmlSchema (XmlWriter.Create (writer, GetWriterSettings ()));
-               }
-
-               public void WriteXmlSchema (XmlWriter writer)
-               {
-                       DataSet ds = DataSet;
-                       DataSet tmp = null;
-                       try {
-                               if (ds == null) {
-                                       tmp = ds = new DataSet ();
-                                       ds.Tables.Add (this);
-                               }
-                               DataTableCollection col = new DataTableCollection (ds);
-                               col.Add (this);
-                               XmlSchemaWriter.WriteXmlSchema (ds, writer, col, null);
-                       } finally {
-                               if (tmp != null)
-                                       ds.Tables.Remove (this);
-                       }
-               }
-
-               public void WriteXmlSchema (string fileName)
-               {
-                       XmlWriter xw = null;
-                       try {
-                               xw = XmlWriter.Create (fileName, GetWriterSettings ());
-                               WriteXmlSchema (xw);
-                       } finally {
-                               if (xw != null)
-                                       xw.Close ();
-                       }
-               }
-#endif
-               
-               #region Events 
-               
-               /// <summary>
-               /// Raises the ColumnChanged event.
-               /// </summary>
-               protected virtual void OnColumnChanged (DataColumnChangeEventArgs e) {
-                       if (null != ColumnChanged) {
-                               ColumnChanged (this, e);
-                       }
-               }
-
-               internal void RaiseOnColumnChanged (DataColumnChangeEventArgs e) {
-                       OnColumnChanged(e);
-               }
-
-#if NET_2_0
-                /// <summary>
-               /// Raises TableCleared Event and delegates to subscribers
-               /// </summary>
-               protected virtual void OnTableCleared (DataTableClearEventArgs e) {
-                       if (TableCleared != null)
-                               TableCleared (this, e);
-               }
-#endif // NET_2_0
-
-               /// <summary>
-               /// Raises the ColumnChanging event.
-               /// </summary>
-               protected virtual void OnColumnChanging (DataColumnChangeEventArgs e) {
-                       if (null != ColumnChanging) {
-                               ColumnChanging (this, e);
-                       }
-               }
-
-               /// <summary>
-               /// Raises the PropertyChanging event.
-               /// </summary>
-               [MonoTODO]
-               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent) {
-                       //      if (null != PropertyChanging)
-                       //      {
-                       //              PropertyChanging (this, e);
-                       //      }
-               }
-
-               /// <summary>
-               /// Notifies the DataTable that a DataColumn is being removed.
-               /// </summary>
-               [MonoTODO]
-               protected internal virtual void OnRemoveColumn (DataColumn column) {
-               }
-
-
-               /// <summary>
-               /// Raises the RowChanged event.
-               /// </summary>
-               protected virtual void OnRowChanged (DataRowChangeEventArgs e) {
-                       if (null != RowChanged) {
-                               RowChanged(this, e);
-                       }
-               }
-
-
-               /// <summary>
-               /// Raises the RowChanging event.
-               /// </summary>
-               protected virtual void OnRowChanging (DataRowChangeEventArgs e) {
-                       if (null != RowChanging) {
-                               RowChanging(this, e);
-                       }
-               }
-
-               /// <summary>
-               /// Raises the RowDeleted event.
-               /// </summary>
-               protected virtual void OnRowDeleted (DataRowChangeEventArgs e) {
-                       if (null != RowDeleted) {
-                               RowDeleted(this, e);
-                       }
-               }
-
-               /// <summary>
-               /// Raises the RowDeleting event.
-               /// </summary>
-               protected virtual void OnRowDeleting (DataRowChangeEventArgs e) {
-                       if (null != RowDeleting) {
-                               RowDeleting(this, e);
-                       }
-               }
-
-               [MonoTODO]
-               private DataColumn CopyColumn (DataColumn Column) {
-                       DataColumn Copy = new DataColumn ();
-
-                       // Copy all the properties of column
-                       Copy.Caption = Column.Caption;
-                       Copy.ColumnMapping = Column.ColumnMapping;
-                       Copy.ColumnName = Column.ColumnName;
-                       //Copy.Container
-                       Copy.DataType = Column.DataType;
-                       Copy.DefaultValue = Column.DefaultValue;                        
-                       Copy.Expression = Column.Expression;
-                       //Copy.ExtendedProperties
-                       Copy.MaxLength = Column.MaxLength;
-                       Copy.Namespace = Column.Namespace;
-                       Copy.Prefix = Column.Prefix;
-                       Copy.ReadOnly = Column.ReadOnly;
-                       //Copy.Site
-                       //we do not copy the unique value - it will be copyied when copying the constraints.
-                       //Copy.Unique = Column.Unique;
-
-                       // At least AutoIncrement must be set after DefaultValue
-                       Copy.AllowDBNull = Column.AllowDBNull;
-                       Copy.AutoIncrement = Column.AutoIncrement;
-                       Copy.AutoIncrementSeed = Column.AutoIncrementSeed;
-                       Copy.AutoIncrementStep = Column.AutoIncrementStep;
-                       
-                       return Copy;
-               }                       
-
-               /// <summary>
-               /// Occurs when after a value has been changed for 
-               /// the specified DataColumn in a DataRow.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when a value has been changed for this column.")]
-               public event DataColumnChangeEventHandler ColumnChanged;
-
-               /// <summary>
-               /// Occurs when a value is being changed for the specified 
-               /// DataColumn in a DataRow.
-               /// </summary>
-               [DataCategory ("Data")]
-               [DataSysDescription ("Occurs when a value has been submitted for this column. The user can modify the proposed value and should throw an exception to cancel the edit.")]
-               public event DataColumnChangeEventHandler ColumnChanging;
-
-               /// <summary>
-               /// Occurs after a DataRow has been changed successfully.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs after a row in the table has been successfully edited.")]
-               public event DataRowChangeEventHandler RowChanged;
-
-               /// <summary>
-               /// Occurs when a DataRow is changing.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when the row is being changed so that the event handler can modify or cancel the change. The user can modify values in the row and should throw an  exception to cancel the edit.")]
-               public event DataRowChangeEventHandler RowChanging;
-
-               /// <summary>
-               /// Occurs after a row in the table has been deleted.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs after a row in the table has been successfully deleted.")] 
-               public event DataRowChangeEventHandler RowDeleted;
-
-               /// <summary>
-               /// Occurs before a row in the table is about to be deleted.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when a row in the table marked for deletion. Throw an exception to cancel the deletion.")]
-               public event DataRowChangeEventHandler RowDeleting;
-
-#if NET_2_0
-               /// <summary>
-               /// Occurs after the Clear method is called on the datatable.
-               /// </summary>
-               [DataCategory ("Data")] 
-               [DataSysDescription ("Occurs when the rows in a table is cleared . Throw an exception to cancel the deletion.")]
-               public event DataTableClearEventHandler TableCleared;
-#endif // NET_2_0
-
-               #endregion // Events
-
-               /// <summary>
-               ///  Removes all UniqueConstraints
-               /// </summary>
-               private void RemoveUniqueConstraints () 
-               {
-                       foreach (Constraint Cons in Constraints) {
-                               
-                               if (Cons is UniqueConstraint) {
-                                       Constraints.Remove (Cons);
-                                       break;
-                               }
-                       }
-                       
-                       UniqueConstraint.SetAsPrimaryKey(this.Constraints, null);
-               }
-
-               internal class RowSorter : IComparer 
-               {
-                       private DataTable table;
-                       private SortableColumn[] sortColumns;
-                       
-                       internal RowSorter(DataTable table,
-                                       SortableColumn[] sortColumns) 
-                       {
-                               this.table = table;
-                               this.sortColumns = sortColumns;
-                       }
-
-                       public SortableColumn[] SortColumns {
-                               get {
-                                       return sortColumns;
-                               }
-                       }
-                       
-                       public DataRow[] SortRows (DataRow [] rowsToSort) 
-                       {
-                               Array.Sort (rowsToSort, this);
-                               return rowsToSort;
-                       }
-
-                       int IComparer.Compare (object x, object y) 
-                       {
-                               if(x == null)
-                                       throw new SystemException ("Object to compare is null: x");
-                               if(y == null)
-                                       throw new SystemException ("Object to compare is null: y");
-                               if(!(x is DataRow))
-                                       throw new SystemException ("Object to compare is not DataRow: x is " + x.GetType().ToString());
-                               if(!(y is DataRow))
-                                       throw new SystemException ("Object to compare is not DataRow: y is " + x.GetType().ToString());
-
-                               if (x == y)
-                                       return 0;
-
-                               DataRow rowx = (DataRow) x;
-                               DataRow rowy = (DataRow) y;
-
-                               for(int i = 0; i < sortColumns.Length; i++) {
-                                       SortableColumn sortColumn = sortColumns[i];
-                                       DataColumn dc = sortColumn.Column;
-
-                                       int result = dc.CompareValues(
-                                               rowx.IndexFromVersion(DataRowVersion.Default),
-                                               rowy.IndexFromVersion(DataRowVersion.Default));
-
-                                       if (result != 0) {
-                                               if (sortColumn.SortDirection == ListSortDirection.Ascending) {
-                                                       return result;
-                                               }
-                                               else {
-                                                       return -result;
-                                               }
-                                       }
-                               }
-                               return x.GetHashCode () - y.GetHashCode ();
-                       }
-               }
-
-               /// <summary>
-               /// Creates new index for a table
-               /// </summary>
-               internal Index CreateIndex(string name, DataColumn[] columns, bool unique)
-               {
-                       // first check whenever index exists on the columns
-                       Index idx = this.GetIndexByColumns(columns);
-                       if(idx != null) {
-                       // if index on this columns already exists - return it
-                               return idx;
-                       }
-
-                       // create new index
-                       Index newIndex = new Index(name,this,columns,unique);
-
-                       //InitializeIndex (newIndex);                   
-
-                       // add new index to table indexes
-                       this.AddIndex(newIndex);
-                       return newIndex;
-               }
-
-//             /// <summary>
-//             /// Creates new extended index for a table
-//             /// </summary>
-//             internal Index CreateIndexExtended(string name, DataColumn[] columns, bool unique)
-//             {
-//                     // first check whenever extended index exists on the columns
-//                     Index idx = this.GetIndexByColumnsExtended(columns);
-//                     if(idx != null) {
-//                             // if extended index on this columns already exists - return it
-//                             return idx;
-//                     }
-//
-//                     DataColumn[] pkColumns = this.PrimaryKey;
-//                     if((pkColumns != null) && (pkColumns.Length > 0)) {
-//                             DataColumn[] cols = new DataColumn[columns.Length + pkColumns.Length];                                  
-//                             Array.Copy(columns,0,cols,0,columns.Length);
-//                             Array.Copy(pkColumns,0,cols,columns.Length,pkColumns.Length);
-//                             return this.CreateIndex(name, cols, unique);
-//                     } 
-//                     else {
-//                             throw new InvalidOperationException("Can not create extended index if the primary key is null or primary key does not contains any row");
-//                     }
-//             }
-
-//             /// <summary>
-//             /// Drops extended index if it is not referenced anymore
-//             /// by any of table constraints
-//             /// </summary>
-//             internal void DropIndexExtended(DataColumn[] columns)
-//             {
-//                     // first check whenever extended index exists on the columns
-//                     Index index = this.GetIndexByColumnsExtended(columns);
-//                     if(index == null) {
-//                             // if no extended index on this columns exists - do nothing
-//                             return;
-//                     }
-//                     this.DropIndex(index);
-//             }
-
-               /// <summary>
-               /// Drops index specified by columns if it is not referenced anymore
-               /// by any of table constraints
-               /// </summary>
-               internal void DropIndex(DataColumn[] columns)
-               {
-                       // first check whenever index exists for the columns
-                       Index index = this.GetIndexByColumns(columns);
-                       if(index == null) {
-                       // if no index on this columns already exists - do nothing
-                               return;
-                       }
-                       this.DropIndex(index);
-               }
-
-               internal void DropIndex(Index index)
-               {
-                       // loop through table constraints and checks 
-                       foreach(Constraint constraint in Constraints) {
-                               // if we found another reference to the index we do not remove the index.
-                               if (index == constraint.Index)
-                                       return; 
-                       }
-                       
-                       this.RemoveIndex(index);
-               }
-
-               internal void InitializeIndex (Index indx)
-               {
-                       DataRow[] rows = new DataRow[this.Rows.Count];
-                       this.Rows.CopyTo (rows, 0);
-                       indx.Root = null;
-                       // fill index with table rows
-                       foreach(DataRow row in this.Rows) {
-                               if(row.RowState != DataRowState.Deleted) {
-                                       indx.Insert(new Node(row), DataRowVersion.Default);
-                               }
-                       }
-               }
-       }
-
-       // to parse the sort string for DataTable:Select(expression,sort)
-       // into sortable columns (think ORDER BY, 
-       // such as, "customer ASC, price DESC" ), as well as DataView.Sort.
-       internal class SortableColumn 
-       {
-               private DataColumn col;
-               private ListSortDirection dir;
-
-               internal SortableColumn (DataColumn column, 
-                                       ListSortDirection direction) 
-               {
-                       col = column;
-                       dir = direction;
-               }
-
-               public DataColumn Column {
-                       get {
-                               return col;
-                       }
-               }
-
-               public ListSortDirection SortDirection {
-                       get {
-                               return dir;
-                       }
-               }
-
-               internal static SortableColumn[] ParseSortString (DataTable table, string sort, bool rejectNoResult)
-               {
-                       SortableColumn[] sortColumns = null;
-                       ArrayList columns = null;
-               
-                       if (sort != null && !sort.Equals ("")) {
-                               columns = new ArrayList ();
-                               string[] columnExpression = sort.Trim ().Split (new char[1] {','});
-                       
-                               for (int c = 0; c < columnExpression.Length; c++) {
-                                       string[] columnSortInfo = columnExpression[c].Trim ().Split (new char[1] {' '});
-                               
-                                       string columnName = columnSortInfo[0].Trim ();
-                                       string sortOrder = "ASC";
-                                       if (columnSortInfo.Length > 1) 
-                                               sortOrder = columnSortInfo[1].Trim ().ToUpper (table.Locale);
-                                       
-                                       ListSortDirection sortDirection = ListSortDirection.Ascending;
-                                       switch (sortOrder) {
-                                       case "ASC":
-                                               sortDirection = ListSortDirection.Ascending;
-                                               break;
-                                       case "DESC":
-                                               sortDirection = ListSortDirection.Descending;
-                                               break;
-                                       default:
-                                               throw new IndexOutOfRangeException ("Could not find column: " + columnExpression[c]);
-                                       }
-                                       Int32 ord = 0;
-                                       try {
-                                               ord = Int32.Parse (columnName);
-                                       }
-                                       catch (FormatException) {
-                                               ord = -1;
-                                       }
-                                       DataColumn dc = null;
-                                       if (ord == -1)                          
-                                               dc = table.Columns [columnName];
-                                       else
-                                               dc = table.Columns [ord];
-                                       SortableColumn sortCol = new SortableColumn (dc,sortDirection);
-                                       columns.Add (sortCol);
-                               }       
-                               sortColumns = (SortableColumn[]) columns.ToArray (typeof (SortableColumn));
-                       }               
-
-                       if (rejectNoResult) {
-                               if (sortColumns == null)
-                                       throw new SystemException ("sort expression result is null");
-                               if (sortColumns.Length == 0)
-                                       throw new SystemException("sort expression result is 0");
-                       }
-                       return sortColumns;
-               }
-       }
-
-}
+//\r
+// System.Data.DataTable.cs\r
+//\r
+// Author:\r
+//   Franklin Wise <gracenote@earthlink.net>\r
+//   Christopher Podurgiel (cpodurgiel@msn.com)\r
+//   Daniel Morgan <danmorg@sc.rr.com>\r
+//   Rodrigo Moya <rodrigo@ximian.com>\r
+//   Tim Coleman (tim@timcoleman.com)\r
+//   Ville Palo <vi64pa@koti.soon.fi>\r
+//   Sureshkumar T <tsureshkumar@novell.com>\r
+//   Konstantin Triger <kostat@mainsoft.com>\r
+//\r
+// (C) Chris Podurgiel\r
+// (C) Ximian, Inc 2002\r
+// Copyright (C) Tim Coleman, 2002-2003\r
+// Copyright (C) Daniel Morgan, 2002-2003\r
+//\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
+using System.Data.Common;\r
+using System.Collections;\r
+using System.ComponentModel;\r
+using System.Globalization;\r
+using System.IO;\r
+using System.Runtime.Serialization;\r
+using System.Xml;\r
+using System.Xml.Schema;\r
+using Mono.Data.SqlExpressions;\r
+\r
+namespace System.Data {\r
+       //[Designer]\r
+       [ToolboxItem (false)]\r
+       [DefaultEvent ("RowChanging")]\r
+       [DefaultProperty ("TableName")]\r
+       [DesignTimeVisible (false)]\r
+       [EditorAttribute ("Microsoft.VSDesigner.Data.Design.DataTableEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]\r
+       [Serializable]\r
+       public class DataTable : MarshalByValueComponent, IListSource, ISupportInitialize, ISerializable \r
+       {\r
+               #region Fields\r
+\r
+               internal DataSet dataSet;   \r
+               \r
+               private bool _caseSensitive;\r
+               private DataColumnCollection _columnCollection;\r
+               private ConstraintCollection _constraintCollection;\r
+               // never access it. Use DefaultView.\r
+               private DataView _defaultView = null;\r
+\r
+               private string _displayExpression;\r
+               private PropertyCollection _extendedProperties;\r
+               private bool _hasErrors;\r
+               private CultureInfo _locale;\r
+               private int _minimumCapacity;\r
+               private string _nameSpace;\r
+               private DataRelationCollection _childRelations; \r
+               private DataRelationCollection _parentRelations;\r
+               private string _prefix;\r
+               private UniqueConstraint _primaryKeyConstraint;\r
+               private DataRowCollection _rows;\r
+               private ISite _site;\r
+               private string _tableName;\r
+               private bool _containsListCollection;\r
+               private string _encodedTableName;\r
+               internal bool _duringDataLoad;\r
+               internal bool _nullConstraintViolationDuringDataLoad;\r
+               private bool dataSetPrevEnforceConstraints;\r
+               private bool dataTablePrevEnforceConstraints;\r
+               private bool enforceConstraints = true;\r
+               private DataRowBuilder _rowBuilder;\r
+               private ArrayList _indexes;\r
+               private RecordCache _recordCache;\r
+               private int _defaultValuesRowIndex = -1;\r
+               protected internal bool fInitInProgress;\r
+\r
+               // If CaseSensitive property is changed once it does not anymore follow owner DataSet's \r
+               // CaseSensitive property. So when you lost you virginity it's gone for ever\r
+               private bool _virginCaseSensitive = true;\r
+               \r
+               private PropertyDescriptorCollection _propertyDescriptorsCache;\r
+               static DataColumn[] _emptyColumnArray = new DataColumn[0];\r
+               \r
+               #endregion //Fields\r
+               \r
+               /// <summary>\r
+               /// Initializes a new instance of the DataTable class with no arguments.\r
+               /// </summary>\r
+               public DataTable () \r
+               {\r
+                       dataSet = null;\r
+                       _columnCollection = new DataColumnCollection(this);\r
+                       _constraintCollection = new ConstraintCollection(this); \r
+                       _extendedProperties = new PropertyCollection();\r
+                       _tableName = "";\r
+                       _nameSpace = null;\r
+                       _caseSensitive = false;         //default value\r
+                       _displayExpression = null;\r
+                       _primaryKeyConstraint = null;\r
+                       _site = null;\r
+                       _rows = new DataRowCollection (this);\r
+                       _indexes = new ArrayList();\r
+                       _recordCache = new RecordCache(this);\r
+                       \r
+                       //LAMESPEC: spec says 25 impl does 50\r
+                       _minimumCapacity = 50;\r
+                       \r
+                       _childRelations = new DataRelationCollection.DataTableRelationCollection (this);\r
+                       _parentRelations = new DataRelationCollection.DataTableRelationCollection (this);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Intitalizes a new instance of the DataTable class with the specified table name.\r
+               /// </summary>\r
+               public DataTable (string tableName) : this () \r
+               {\r
+                       _tableName = tableName;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Initializes a new instance of the DataTable class with the SerializationInfo and the StreamingContext.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               protected DataTable (SerializationInfo info, StreamingContext context)\r
+                       : this () \r
+               {\r
+                       string schema = info.GetString ("XmlSchema");\r
+                       string data = info.GetString ("XmlDiffGram");\r
+                       \r
+                       DataSet ds = new DataSet ();\r
+                       ds.ReadXmlSchema (new StringReader (schema));\r
+                       ds.Tables [0].CopyProperties (this);\r
+                       ds = new DataSet ();\r
+                       ds.Tables.Add (this);\r
+                       ds.ReadXml (new StringReader (data), XmlReadMode.DiffGram);\r
+                       ds.Tables.Remove (this);\r
+/* keeping for a while. With the change above, we shouldn't have to consider \r
+ * DataTable mode in schema inference/read.\r
+                       XmlSchemaMapper mapper = new XmlSchemaMapper (this);\r
+                       XmlTextReader xtr = new XmlTextReader(new StringReader (schema));\r
+                       mapper.Read (xtr);\r
+                       \r
+                       XmlDiffLoader loader = new XmlDiffLoader (this);\r
+                       xtr = new XmlTextReader(new StringReader (data));\r
+                       loader.Load (xtr);\r
+*/\r
+               }\r
+\r
+#if NET_2_0\r
+               public DataTable (string tableName, string tbNamespace)\r
+                       : this (tableName)\r
+               {\r
+                       _nameSpace = tbNamespace;\r
+               }\r
+#endif\r
+\r
+               /// <summary>\r
+               /// Indicates whether string comparisons within the table are case-sensitive.\r
+               /// </summary>\r
+               [DataSysDescription ("Indicates whether comparing strings within the table is case sensitive.")]        \r
+               public bool CaseSensitive {\r
+                       get { \r
+                               if (_virginCaseSensitive && dataSet != null)\r
+                                       return dataSet.CaseSensitive; \r
+                               else\r
+                                       return _caseSensitive;\r
+                               }\r
+                       set {\r
+                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {\r
+                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");\r
+                               }\r
+                               _virginCaseSensitive = false;\r
+                               _caseSensitive = value; \r
+                               ResetCaseSensitiveIndexes();\r
+                       }\r
+               }\r
+               \r
+               internal ArrayList Indexes{\r
+                       get { return _indexes; }\r
+               }\r
+\r
+               internal void ChangedDataColumn (DataRow dr, DataColumn dc, object pv) \r
+               {\r
+                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);\r
+                       OnColumnChanged(e);\r
+               }\r
+\r
+               internal void ChangingDataColumn (DataRow dr, DataColumn dc, object pv) \r
+               {\r
+                       DataColumnChangeEventArgs e = new DataColumnChangeEventArgs (dr, dc, pv);\r
+                       OnColumnChanging (e);\r
+               }\r
+\r
+               internal void DeletedDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowDeleted (e);\r
+               }\r
+\r
+               internal void DeletingDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowDeleting(e);\r
+               }\r
+\r
+               internal void ChangedDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowChanged (e);\r
+               }\r
+\r
+               internal void ChangingDataRow (DataRow dr, DataRowAction action) \r
+               {\r
+                       DataRowChangeEventArgs e = new DataRowChangeEventArgs (dr, action);\r
+                       OnRowChanging (e);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the collection of child relations for this DataTable.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns the child relations for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataRelationCollection ChildRelations {\r
+                       get {\r
+                               return _childRelations;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the collection of columns that belong to this table.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds the columns for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public DataColumnCollection Columns {\r
+                       get { return _columnCollection; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the collection of constraints maintained by this table.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("The collection that holds the constraints for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public ConstraintCollection Constraints {\r
+                       get { return _constraintCollection; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the DataSet that this table belongs to.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Indicates the DataSet to which this table belongs.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataSet DataSet {\r
+                       get { return dataSet; }\r
+               }\r
+\r
+               \r
+\r
+               /// <summary>\r
+               /// Gets a customized view of the table which may \r
+               /// include a filtered view, or a cursor position.\r
+               /// </summary>\r
+               [MonoTODO]      \r
+               [Browsable (false)]\r
+               [DataSysDescription ("This is the default DataView for the table.")]\r
+               public DataView DefaultView {\r
+                       get {\r
+                               if (_defaultView == null) {\r
+                                       lock(this){\r
+                                               if (_defaultView == null){\r
+                                                       if (dataSet != null)\r
+                                                               _defaultView = dataSet.DefaultViewManager.CreateDataView(this);\r
+                                                       else\r
+                                                               _defaultView = new DataView(this);\r
+                                               }\r
+                                       }\r
+                               }\r
+                               return _defaultView;\r
+                       }\r
+               }\r
+               \r
+\r
+               /// <summary>\r
+               /// Gets or sets the expression that will return \r
+               /// a value used to represent this table in the user interface.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The expression used to compute the data-bound value of this row.")]       \r
+               [DefaultValue ("")]\r
+               public string DisplayExpression {\r
+                       get { return _displayExpression == null ? "" : _displayExpression; }\r
+                       set { _displayExpression = value; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the collection of customized user information.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("The collection that holds custom user information.")]\r
+               public PropertyCollection ExtendedProperties {\r
+                       get { return _extendedProperties; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets a value indicating whether there are errors in \r
+               /// any of the_rows in any of the tables of the DataSet to \r
+               /// which the table belongs.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns whether the table has errors.")]\r
+               public bool HasErrors {\r
+                       get { \r
+                               // we can not use the _hasError flag because we do not know when to turn it off!\r
+                               for (int i = 0; i < _rows.Count; i++)\r
+                               {\r
+                                       if (_rows[i].HasErrors)\r
+                                               return true;\r
+                               }\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets the locale information used to \r
+               /// compare strings within the table.\r
+               /// </summary>\r
+               [DataSysDescription ("Indicates a locale under which to compare strings within the table.")]\r
+               public CultureInfo Locale {\r
+                       get { \r
+                               // if the locale is null, we check for the DataSet locale\r
+                               // and if the DataSet is null we return the current culture.\r
+                               // this way if DataSet locale is changed, only if there is no locale for \r
+                               // the DataTable it influece the Locale get;\r
+                               if (_locale != null)\r
+                                       return _locale;\r
+                               if (DataSet != null)\r
+                                       return DataSet.Locale;\r
+                               return CultureInfo.CurrentCulture;\r
+                       }\r
+                       set { \r
+                               if (_childRelations.Count > 0 || _parentRelations.Count > 0) {\r
+                                       throw new ArgumentException ("Cannot change CaseSensitive or Locale property. This change would lead to at least one DataRelation or Constraint to have different Locale or CaseSensitive settings between its related tables.");\r
+                               }\r
+                               if (_locale == null || !_locale.Equals(value))\r
+                                       _locale = value; \r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets the initial starting size for this table.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates an initial starting size for this table.")]\r
+               [DefaultValue (50)]\r
+               public int MinimumCapacity {\r
+                       get { return _minimumCapacity; }\r
+                       set { _minimumCapacity = value; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets the namespace for the XML represenation \r
+               /// of the data stored in the DataTable.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the XML uri namespace for the elements contained in this table.")]\r
+               public string Namespace {\r
+                       get\r
+                       {\r
+                               if (_nameSpace != null)\r
+                               {\r
+                                       return _nameSpace;\r
+                               }\r
+                               if (DataSet != null)\r
+                               {\r
+                                       return DataSet.Namespace;\r
+                               }\r
+                               return String.Empty;\r
+                       }\r
+                       set { _nameSpace = value; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the collection of parent relations for \r
+               /// this DataTable.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns the parent relations for this table.")]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public DataRelationCollection ParentRelations {\r
+                       get {   \r
+                               return _parentRelations;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets the namespace for the XML represenation\r
+               ///  of the data stored in the DataTable.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the Prefix of the namespace used for this table in XML representation.")]\r
+               [DefaultValue ("")]\r
+               public string Prefix {\r
+                       get { return _prefix == null ? "" : _prefix; }\r
+                       set {\r
+                               // Prefix cannot contain any special characters other than '_' and ':'\r
+                               for (int i = 0; i < value.Length; i++) {\r
+                                       if (!(Char.IsLetterOrDigit (value [i])) && (value [i] != '_') && (value [i] != ':'))\r
+                                               throw new DataException ("Prefix '" + value + "' is not valid, because it contains special characters.");\r
+                               }\r
+                               _prefix = value;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets an array of columns that function as \r
+               /// primary keys for the data table.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the column(s) that represent the primary key for this table.")]\r
+               [EditorAttribute ("Microsoft.VSDesigner.Data.Design.PrimaryKeyEditor, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.Drawing.Design.UITypeEditor, "+ Consts.AssemblySystem_Drawing )]\r
+               [TypeConverterAttribute ("System.Data.PrimaryKeyTypeConverter, System.Data, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]\r
+               public DataColumn[] PrimaryKey {\r
+                       get {\r
+                               if (_primaryKeyConstraint == null) { \r
+                                       return new DataColumn[] {};\r
+                               }\r
+                               return _primaryKeyConstraint.Columns;\r
+                       }\r
+                       set {\r
+                               UniqueConstraint oldPKConstraint = _primaryKeyConstraint;\r
+                               \r
+                               // first check if value is the same as current PK.\r
+                               if (oldPKConstraint != null && DataColumn.AreColumnSetsTheSame(value, oldPKConstraint.Columns))\r
+                                       return;\r
+\r
+                               // remove PK Constraint\r
+                               if(oldPKConstraint != null) {\r
+                                       _primaryKeyConstraint = null;\r
+                                       Constraints.Remove(oldPKConstraint);\r
+                               }\r
+                               \r
+                               if (value != null) {\r
+                                       //Does constraint exist for these columns\r
+                                       UniqueConstraint uc = UniqueConstraint.GetUniqueConstraintForColumnSet(this.Constraints, (DataColumn[]) value);\r
+                               \r
+                                       //if constraint doesn't exist for columns\r
+                                       //create new unique primary key constraint\r
+                                       if (null == uc) {\r
+                                               foreach (DataColumn Col in (DataColumn[]) value) {\r
+                                                       if (Col.Table == null)\r
+                                                               break;\r
+\r
+                                                       if (Columns.IndexOf (Col) < 0)\r
+                                                               throw new ArgumentException ("PrimaryKey columns do not belong to this table.");\r
+                                               }\r
+                                               // create constraint with primary key indication set to false\r
+                                               // to avoid recursion\r
+                                               uc = new UniqueConstraint( (DataColumn[]) value, false);                \r
+                                               Constraints.Add (uc);\r
+                                       }\r
+\r
+                                       //set the constraint as the new primary key\r
+                                               UniqueConstraint.SetAsPrimaryKey(this.Constraints, uc);\r
+                                       _primaryKeyConstraint = uc;\r
+                               }                               \r
+                       }\r
+               }\r
+\r
+               internal UniqueConstraint PrimaryKeyConstraint {\r
+                       get{\r
+                               return _primaryKeyConstraint;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the collection of_rows that belong to this table.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Indicates the collection that holds the rows of data for this table.")]   \r
+               public DataRowCollection Rows {\r
+                       get { return _rows; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets an System.ComponentModel.ISite \r
+               /// for the DataTable.\r
+               /// </summary>\r
+               [Browsable (false)]\r
+               [DesignerSerializationVisibility (DesignerSerializationVisibility.Hidden)]\r
+               public override ISite Site {\r
+                       get { return _site; }\r
+                       set { _site = value; }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets or sets the name of the the DataTable.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the name used to look up this table in the Tables collection of a DataSet.")]\r
+               [DefaultValue ("")]     \r
+               [RefreshProperties (RefreshProperties.All)]\r
+               public string TableName {\r
+                       get { return _tableName == null ? "" : _tableName; }\r
+                       set { _tableName = value; }\r
+               }\r
+               \r
+               bool IListSource.ContainsListCollection {\r
+                       get {\r
+                               // the collection is a DataView\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               internal RecordCache RecordCache {\r
+                       get {\r
+                               return _recordCache;\r
+                       }\r
+               }\r
+               \r
+               private DataRowBuilder RowBuilder\r
+               {\r
+                       get\r
+                       {\r
+                               // initiate only one row builder.\r
+                               if (_rowBuilder == null)\r
+                                       _rowBuilder = new DataRowBuilder (this, -1, 0);\r
+                               else                    \r
+                                       // new row get id -1.\r
+                                       _rowBuilder._rowId = -1;\r
+\r
+                               return _rowBuilder;\r
+                       }\r
+               }\r
+               \r
+               private bool EnforceConstraints {\r
+                       get { return enforceConstraints; }\r
+                       set {\r
+                               if (value != enforceConstraints) {\r
+                                       if (value) {\r
+                                               // reset indexes since they may be outdated\r
+                                               ResetIndexes();\r
+\r
+                                               bool violatesConstraints = false;\r
+\r
+                                               //FIXME: use index for AllowDBNull\r
+                                               for (int i = 0; i < Columns.Count; i++) {\r
+                                                       DataColumn column = Columns[i];\r
+                                                       if (!column.AllowDBNull) {\r
+                                                               for (int j = 0; j < Rows.Count; j++){\r
+                                                                       if (Rows[j].IsNull(column)) {\r
+                                                                               violatesConstraints = true;\r
+                                                                               Rows[j].RowError = String.Format("Column '{0}' does not allow DBNull.Value.", column.ColumnName);\r
+                                                                       }\r
+                                                               }\r
+                                                       }\r
+                                               }\r
+\r
+                                               if (violatesConstraints)\r
+                                                       Constraint.ThrowConstraintException();\r
+\r
+                                               // assert all constraints\r
+                                               foreach (Constraint constraint in Constraints) {\r
+                                                       constraint.AssertConstraint();\r
+                                               }\r
+                                       }\r
+                                       enforceConstraints = value;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal bool RowsExist(DataColumn[] columns, DataColumn[] relatedColumns,DataRow row)\r
+               {\r
+                       int curIndex = row.IndexFromVersion(DataRowVersion.Default);\r
+                       int tmpRecord = RecordCache.NewRecord();\r
+\r
+                       try {\r
+                               for (int i = 0; i < relatedColumns.Length; i++) {\r
+                                       // according to MSDN: the DataType value for both columns must be identical.\r
+                                       columns[i].DataContainer.CopyValue(relatedColumns[i].DataContainer, curIndex, tmpRecord);\r
+                               }\r
+                               return RowsExist(columns, tmpRecord);\r
+                       }\r
+                       finally {\r
+                               RecordCache.DisposeRecord(tmpRecord);\r
+                       }\r
+               }\r
+\r
+               bool RowsExist(DataColumn[] columns, int index)\r
+               {\r
+                       bool rowsExist = false;\r
+                       Index indx = this.FindIndex(columns);\r
+\r
+                       if (indx != null) { // lookup for a row in index                        \r
+                               rowsExist = (indx.Find(index) != -1);\r
+                       } \r
+                       else { \r
+                               // we have to perform full-table scan\r
+                               // check that there is a parent for this row.\r
+                               foreach (DataRow thisRow in this.Rows) {\r
+                                       if (thisRow.RowState != DataRowState.Deleted) {\r
+                                               bool match = true;\r
+                                               // check if the values in the columns are equal\r
+                                               int thisIndex = thisRow.IndexFromVersion(DataRowVersion.Current);\r
+                                               foreach (DataColumn column in columns) {\r
+                                                       if (column.DataContainer.CompareValues(thisIndex, index) != 0) {\r
+                                                               match = false;\r
+                                                               break;\r
+                                                       }       \r
+                                               }\r
+                                               if (match) {// there is a row with columns values equals to those supplied.\r
+                                                       rowsExist = true;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                               }                               \r
+                       }\r
+                       return rowsExist;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Commits all the changes made to this table since the \r
+               /// last time AcceptChanges was called.\r
+               /// </summary>\r
+               public void AcceptChanges () \r
+               {\r
+                       //FIXME: Do we need to validate anything here or\r
+                       //try to catch any errors to deal with them?\r
+                       \r
+                       // we do not use foreach because if one of the rows is in Delete state\r
+                       // it will be romeved from Rows and we get an exception.\r
+                       DataRow myRow;\r
+                       for (int i = 0; i < Rows.Count; )\r
+                       {\r
+                               myRow = Rows[i];\r
+                               myRow.AcceptChanges();\r
+\r
+                               // if the row state is Detached it meens that it was removed from row list (Rows)\r
+                               // so we should not increase 'i'.\r
+                               if (myRow.RowState != DataRowState.Detached)\r
+                                       i++;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Begins the initialization of a DataTable that is used \r
+               /// on a form or used by another component. The initialization\r
+               /// occurs at runtime.\r
+               /// </summary>\r
+               public virtual void BeginInit () \r
+               {\r
+                       fInitInProgress = true;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Turns off notifications, index maintenance, and \r
+               /// constraints while loading data.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public void BeginLoadData () \r
+               {\r
+                       if (!this._duringDataLoad)\r
+                       {\r
+                               //duringDataLoad is important to EndLoadData and\r
+                               //for not throwing unexpected exceptions.\r
+                               this._duringDataLoad = true;\r
+                               this._nullConstraintViolationDuringDataLoad = false;\r
+                       \r
+                               if (this.dataSet != null)\r
+                               {\r
+                                       //Saving old Enforce constraints state for later\r
+                                       //use in the EndLoadData.\r
+                                       this.dataSetPrevEnforceConstraints = this.dataSet.EnforceConstraints;\r
+                                       this.dataSet.EnforceConstraints = false;\r
+                               }\r
+                               else {\r
+                                       //if table does not belong to any data set use EnforceConstraints of the table\r
+                                       this.EnforceConstraints = false;\r
+                               }\r
+                       }\r
+                       return;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Clears the DataTable of all data.\r
+               /// </summary>\r
+               public void Clear () {\r
+                        // Foriegn key constraints are checked in _rows.Clear method\r
+                       _rows.Clear ();\r
+#if NET_2_0\r
+                        OnTableCleared (new DataTableClearEventArgs (this));\r
+#endif // NET_2_0\r
+\r
+               }\r
+\r
+               /// <summary>\r
+               /// Clones the structure of the DataTable, including\r
+               ///  all DataTable schemas and constraints.\r
+               /// </summary>\r
+               public virtual DataTable Clone () \r
+               {\r
+                        // Use Activator so we can use non-public constructors.\r
+                       DataTable Copy = (DataTable) Activator.CreateInstance(GetType(), true);                 \r
+                       CopyProperties (Copy);\r
+                       return Copy;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Computes the given expression on the current_rows that \r
+               /// pass the filter criteria.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public object Compute (string expression, string filter) \r
+               {\r
+                       // expression is an aggregate function\r
+                       // filter is an expression used to limit rows\r
+\r
+                       DataRow[] rows = Select(filter);\r
+                       \r
+                       if (rows == null || rows.Length == 0)\r
+                               return DBNull.Value;\r
+                       \r
+                       Parser parser = new Parser (rows);\r
+                       IExpression expr = parser.Compile (expression);\r
+                       object obj = expr.Eval (rows[0]);\r
+                       \r
+                       return obj;\r
+               }\r
+\r
+               /// <summary>\r
+               /// Copies both the structure and data for this DataTable.\r
+               /// </summary>\r
+               public DataTable Copy () \r
+               {\r
+                       DataTable copy = Clone();\r
+\r
+                       copy._duringDataLoad = true;\r
+                       foreach (DataRow row in Rows) {\r
+                               DataRow newRow = copy.NewNotInitializedRow();\r
+                               copy.Rows.AddInternal(newRow);\r
+                               CopyRow(row,newRow);\r
+                       }\r
+                       copy._duringDataLoad = false;           \r
+               \r
+                       // rebuild copy indexes after loading all rows\r
+                       copy.ResetIndexes();\r
+                       return copy;\r
+               }\r
+\r
+               internal void CopyRow(DataRow fromRow,DataRow toRow)\r
+               {\r
+                       if (fromRow.HasErrors) {\r
+                               fromRow.CopyErrors(toRow);\r
+                       }\r
+\r
+                       if (fromRow.HasVersion(DataRowVersion.Original)) {\r
+                               toRow.Original = toRow.Table.RecordCache.CopyRecord(this,fromRow.Original,-1);\r
+                       }\r
+\r
+                       if (fromRow.HasVersion(DataRowVersion.Current)) {\r
+                               if (fromRow.Original != fromRow.Current) {\r
+                                       toRow.Current = toRow.Table.RecordCache.CopyRecord(this,fromRow.Current,-1);\r
+                               }\r
+                               else {\r
+                                       toRow.Current = toRow.Original;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void CopyProperties (DataTable Copy) \r
+               {\r
+                       Copy.CaseSensitive = CaseSensitive;\r
+                       Copy._virginCaseSensitive = _virginCaseSensitive;\r
+\r
+                       // Copy.ChildRelations\r
+                       // Copy.Constraints\r
+                       // Copy.Container\r
+                       // Copy.DefaultView\r
+                       // Copy.DesignMode\r
+                       Copy.DisplayExpression = DisplayExpression;\r
+                       if(ExtendedProperties.Count > 0) {\r
+                               //  Cannot copy extended properties directly as the property does not have a set accessor\r
+                               Array tgtArray = Array.CreateInstance( typeof (object), ExtendedProperties.Count);\r
+                               ExtendedProperties.Keys.CopyTo (tgtArray, 0);\r
+                               for (int i=0; i < ExtendedProperties.Count; i++)\r
+                                       Copy.ExtendedProperties.Add (tgtArray.GetValue (i), ExtendedProperties[tgtArray.GetValue (i)]);\r
+                       }\r
+                       Copy.Locale = Locale;\r
+                       Copy.MinimumCapacity = MinimumCapacity;\r
+                       Copy.Namespace = Namespace;\r
+                       // Copy.ParentRelations\r
+                       Copy.Prefix = Prefix;\r
+                       Copy.Site = Site;\r
+                       Copy.TableName = TableName;\r
+\r
+                       bool isEmpty = Copy.Columns.Count == 0;\r
+\r
+                       // Copy columns\r
+                       foreach (DataColumn column in Columns) {                        \r
+                               // When cloning a table, the columns may be added in the default constructor.\r
+                               if (isEmpty || !Copy.Columns.Contains(column.ColumnName)) {\r
+                                       Copy.Columns.Add (column.Clone());      \r
+                               }\r
+                       }\r
+\r
+                       CopyConstraints(Copy);\r
+                       // add primary key to the copy\r
+                       if (PrimaryKey.Length > 0) {\r
+                               DataColumn[] pColumns = new DataColumn[PrimaryKey.Length];\r
+                               for (int i = 0; i < pColumns.Length; i++)\r
+                                       pColumns[i] = Copy.Columns[PrimaryKey[i].ColumnName];\r
+\r
+                               Copy.PrimaryKey = pColumns;\r
+                       }\r
+               }\r
+\r
+               private void CopyConstraints(DataTable copy)\r
+               {\r
+                       UniqueConstraint origUc;\r
+                       UniqueConstraint copyUc;\r
+                       for (int i = 0; i < this.Constraints.Count; i++)\r
+                       {\r
+                               if (this.Constraints[i] is UniqueConstraint)\r
+                               {\r
+                                       origUc = (UniqueConstraint)this.Constraints[i];\r
+                                       DataColumn[] columns = new DataColumn[origUc.Columns.Length];\r
+                                       for (int j = 0; j < columns.Length; j++)\r
+                                               columns[j] = copy.Columns[origUc.Columns[j].ColumnName];\r
+                                       \r
+                                       copyUc = new UniqueConstraint(origUc.ConstraintName, columns, origUc.IsPrimaryKey);\r
+                                       copy.Constraints.Add(copyUc);\r
+                               }\r
+                       }\r
+               }\r
+               /// <summary>\r
+               /// Ends the initialization of a DataTable that is used \r
+               /// on a form or used by another component. The \r
+               /// initialization occurs at runtime.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public virtual void EndInit () \r
+               {\r
+                       fInitInProgress = false;\r
+                       // Add the constraints\r
+                       _constraintCollection.PostEndInit();\r
+                       Columns.PostEndInit();\r
+               }\r
+\r
+               /// <summary>\r
+               /// Turns on notifications, index maintenance, and \r
+               /// constraints after loading data.\r
+               /// </summary>\r
+               public void EndLoadData() \r
+               {\r
+                       if (this._duringDataLoad) {\r
+                               if(this._nullConstraintViolationDuringDataLoad) {\r
+                                       this._nullConstraintViolationDuringDataLoad = false;\r
+                                       throw new ConstraintException ("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");\r
+                               }\r
+                               \r
+                               if (this.dataSet !=null) {\r
+                                       //Getting back to previous EnforceConstraint state\r
+                                       this.dataSet.InternalEnforceConstraints(this.dataSetPrevEnforceConstraints,true);\r
+                               }\r
+                               else {\r
+                                       //Getting back to the table's previous EnforceConstraint state\r
+                                       this.EnforceConstraints = true;\r
+                               }\r
+\r
+                               //Returning from loading mode, raising exceptions as usual\r
+                               this._duringDataLoad = false;\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets a copy of the DataTable that contains all\r
+               ///  changes made to it since it was loaded or \r
+               ///  AcceptChanges was last called.\r
+               /// </summary>\r
+               public DataTable GetChanges() \r
+               {\r
+                       return GetChanges(DataRowState.Added | DataRowState.Deleted | DataRowState.Modified);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets a copy of the DataTable containing all \r
+               /// changes made to it since it was last loaded, or \r
+               /// since AcceptChanges was called, filtered by DataRowState.\r
+               /// </summary>\r
+               public DataTable GetChanges(DataRowState rowStates) \r
+               {\r
+                       DataTable copyTable = null;\r
+\r
+                       IEnumerator rowEnumerator = Rows.GetEnumerator();\r
+                       while (rowEnumerator.MoveNext()) {\r
+                               DataRow row = (DataRow)rowEnumerator.Current;\r
+                               // The spec says relationship constraints may cause Unchanged parent rows to be included but\r
+                               // MS .NET 1.1 does not include Unchanged rows even if their child rows are changed.\r
+                               if (row.IsRowChanged(rowStates)) {\r
+                                       if (copyTable == null)\r
+                                               copyTable = Clone();\r
+                                       DataRow newRow = copyTable.NewNotInitializedRow();\r
+                                       row.CopyValuesToRow(newRow);\r
+                                       copyTable.Rows.AddInternal (newRow);\r
+                               }\r
+                       }\r
+                        \r
+                       return copyTable;\r
+               }\r
+\r
+#if NET_2_0\r
+               [MonoTODO]\r
+               public DataTableReader GetDataReader ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+#endif\r
+\r
+               /// <summary>\r
+               /// Gets an array of DataRow objects that contain errors.\r
+               /// </summary>\r
+               public DataRow[] GetErrors () \r
+               {\r
+                       ArrayList errors = new ArrayList();\r
+                       for (int i = 0; i < _rows.Count; i++)\r
+                       {\r
+                               if (_rows[i].HasErrors)\r
+                                       errors.Add(_rows[i]);\r
+                       }\r
+                       \r
+                       DataRow[] ret = NewRowArray(errors.Count);\r
+                       errors.CopyTo(ret, 0);\r
+                       return ret;\r
+               }\r
+       \r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure \r
+               /// </summary>\r
+               protected virtual DataTable CreateInstance () \r
+               {\r
+                       return Activator.CreateInstance (this.GetType (), true) as DataTable;\r
+               }\r
+\r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure \r
+               /// </summary>\r
+               protected virtual Type GetRowType () \r
+               {\r
+                       return typeof (DataRow);\r
+               }\r
+\r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure \r
+               /// \r
+               /// Used for Data Binding between System.Web.UI. controls \r
+               /// like a DataGrid\r
+               /// or\r
+               /// System.Windows.Forms controls like a DataGrid\r
+               /// </summary>\r
+               IList IListSource.GetList () \r
+               {\r
+                       IList list = (IList) DefaultView;\r
+                       return list;\r
+               }\r
+                               \r
+               /// <summary>\r
+               /// Copies a DataRow into a DataTable, preserving any \r
+               /// property settings, as well as original and current values.\r
+               /// </summary>\r
+               public void ImportRow (DataRow row) \r
+               {\r
+                       DataRow newRow = NewNotInitializedRow();\r
+\r
+                       int original = -1;\r
+                       if (row.HasVersion(DataRowVersion.Original)) {\r
+                               original = row.IndexFromVersion(DataRowVersion.Original);\r
+                               newRow.Original = RecordCache.NewRecord();\r
+                               RecordCache.CopyRecord(row.Table,original,newRow.Original);\r
+                       }\r
+\r
+                       if (row.HasVersion(DataRowVersion.Current)) {\r
+                               int current = row.IndexFromVersion(DataRowVersion.Current);\r
+                               if (current == original)\r
+                                       newRow.Current = newRow.Original;\r
+                               else {\r
+                                       newRow.Current = RecordCache.NewRecord();\r
+                                       RecordCache.CopyRecord(row.Table,current,newRow.Current);\r
+                               }\r
+                       }\r
+\r
+                       if (EnforceConstraints)\r
+                               // we have to check that the new row doesn't colide with existing row\r
+                               Rows.ValidateDataRowInternal(newRow);\r
+\r
+                       Rows.AddInternal(newRow);               \r
+       \r
+                       if (row.HasErrors) {\r
+                               row.CopyErrors(newRow);\r
+                       }\r
+               }\r
+\r
+               internal int DefaultValuesRowIndex\r
+               {\r
+                       get {\r
+                               return _defaultValuesRowIndex;\r
+                       }       \r
+               }\r
+\r
+               /// <summary>\r
+               /// This member is only meant to support Mono's infrastructure          \r
+               /// </summary>\r
+               void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context) \r
+               {\r
+                       DataSet dset;\r
+                       if (dataSet != null)\r
+                               dset = dataSet;\r
+                       else {\r
+                               dset = new DataSet ("tmpDataSet");\r
+                               dset.Tables.Add (this);\r
+                       }\r
+                       \r
+                       StringWriter sw = new StringWriter ();\r
+                       XmlTextWriter tw = new XmlTextWriter (sw);\r
+                       tw.Formatting = Formatting.Indented;\r
+                       dset.WriteIndividualTableContent (tw, this, XmlWriteMode.DiffGram);\r
+                       tw.Close ();\r
+                       \r
+                       StringWriter sw2 = new StringWriter ();\r
+                       DataTableCollection tables = new DataTableCollection (dset);\r
+                       tables.Add (this);\r
+                       XmlSchemaWriter.WriteXmlSchema (dset, new XmlTextWriter (sw2), tables, null);\r
+                       sw2.Close ();\r
+                       \r
+                       info.AddValue ("XmlSchema", sw2.ToString(), typeof(string));\r
+                       info.AddValue ("XmlDiffGram", sw.ToString(), typeof(string));\r
+               }\r
+\r
+#if NET_2_0\r
+                /// <summary>\r
+                ///     Loads the table with the values from the reader\r
+                /// </summary>\r
+               public void Load (IDataReader reader)\r
+               {\r
+                        Load (reader, LoadOption.PreserveChanges);\r
+               }\r
+\r
+                /// <summary>\r
+                ///     Loads the table with the values from the reader and the pattern\r
+                ///     of the changes to the existing rows or the new rows are based on\r
+                ///     the LoadOption passed.\r
+                /// </summary>\r
+               public void Load (IDataReader reader, LoadOption loadOption)\r
+               {\r
+                        bool prevEnforceConstr = this.EnforceConstraints;\r
+                        try {\r
+                                this.EnforceConstraints = false;\r
+                                int [] mapping = DbDataAdapter.BuildSchema (reader, this, SchemaType.Mapped, \r
+                                                                            MissingSchemaAction.AddWithKey,\r
+                                                                            MissingMappingAction.Passthrough, \r
+                                                                            new DataTableMappingCollection ());\r
+                                DbDataAdapter.FillFromReader (this,\r
+                                                              reader,\r
+                                                              0, // start from\r
+                                                              0, // all records\r
+                                                              mapping,\r
+                                                              loadOption);\r
+                        } finally {\r
+                                this.EnforceConstraints = prevEnforceConstr;\r
+                        }\r
+               }\r
+\r
+                \r
+#endif\r
+\r
+               /// <summary>\r
+               /// Finds and updates a specific row. If no matching row\r
+               ///  is found, a new row is created using the given values.\r
+               /// </summary>\r
+               public DataRow LoadDataRow (object[] values, bool fAcceptChanges) \r
+               {\r
+                       DataRow row = null;\r
+                       if (PrimaryKey.Length == 0) {\r
+                               row = Rows.Add (values);\r
+                               if (fAcceptChanges)\r
+                                       row.AcceptChanges ();\r
+                       }\r
+                       else {\r
+                               int newRecord = CreateRecord(values);\r
+                               int existingRecord = _primaryKeyConstraint.Index.Find(newRecord);\r
+\r
+                               if (existingRecord < 0) {\r
+                                       row = NewRowFromBuilder (RowBuilder);\r
+                                       row.Proposed = newRecord;\r
+                                       Rows.AddInternal(row);\r
+                               }\r
+                               else {\r
+                                       row = RecordCache[existingRecord];\r
+                                       row.BeginEdit();\r
+                                       row.ImportRecord(newRecord);\r
+                                       row.EndEdit();\r
+                                       \r
+                               }\r
+                               \r
+                               if (fAcceptChanges)\r
+                                       row.AcceptChanges ();\r
+                       }\r
+                               \r
+                       return row;\r
+               }\r
+\r
+               internal DataRow LoadDataRow(IDataRecord record, int[] mapping, int length, bool fAcceptChanges)\r
+               {\r
+                       DataRow row = null;\r
+                               int tmpRecord = this.RecordCache.NewRecord();\r
+                               try {\r
+                               RecordCache.ReadIDataRecord(tmpRecord,record,mapping,length);\r
+                               if (PrimaryKey.Length != 0) {\r
+                                       bool hasPrimaryValues = true;\r
+                                       foreach(DataColumn col in PrimaryKey) {\r
+                                               if(!(col.Ordinal < mapping.Length)) {\r
+                                                       hasPrimaryValues = false;\r
+                                                       break;\r
+                                               }\r
+                                       }\r
+                                       \r
+                                       if (hasPrimaryValues) {\r
+                                               // find the row in the table.\r
+                                               row = Rows.Find(tmpRecord);\r
+                                       }\r
+                               }\r
+                                       \r
+                               bool shouldUpdateIndex = false;\r
+                               if (row == null) {\r
+                                       row = NewNotInitializedRow();\r
+                                       row.ImportRecord(tmpRecord);\r
+                                       Rows.AddInternal (row);\r
+                                       shouldUpdateIndex = true;\r
+                               }\r
+                               else {\r
+                                       // Proposed = tmpRecord\r
+                                       row.ImportRecord(tmpRecord);\r
+                               }\r
+                               \r
+                               if (fAcceptChanges) {\r
+                                       row.AcceptChanges();\r
+                               }\r
+                               \r
+                               if (shouldUpdateIndex || !fAcceptChanges) {\r
+                                       // AcceptChanges not always updates indexes because it calls EndEdit\r
+                                       foreach(Index index in Indexes) {\r
+                                               index.Update(row,tmpRecord);\r
+                                       }\r
+                               }\r
+\r
+                       }\r
+                       catch(Exception e) {\r
+                               this.RecordCache.DisposeRecord(tmpRecord);\r
+                               throw e;\r
+                       }                               \r
+                       return row;\r
+               }\r
+\r
+#if NET_2_0\r
+                /// <summary>\r
+                ///     Loads the given values into an existing row if matches or creates\r
+                ///     the new row popluated with the values.\r
+                /// </summary>\r
+                /// <remarks>\r
+                ///     This method searches for the values using primary keys and it first\r
+                ///     searches using the original values of the rows and if not found, it\r
+                ///     searches using the current version of the row.\r
+                /// </remarks>\r
+               public DataRow LoadDataRow (object [] values, LoadOption loadOption)\r
+               {\r
+                        DataRow row  = null;\r
+                        bool new_row = false;\r
+                        \r
+                        // Find Data DataRow\r
+                        if (this.PrimaryKey.Length > 0) {\r
+                                object [] keyValues = new object [this.PrimaryKey.Length];\r
+                                for (int i = 0; i < keyValues.Length; i++)\r
+                                        keyValues [i] = values [this.PrimaryKey [i].Ordinal];\r
+                                row = this.Rows.Find (keyValues, DataRowVersion.Original );\r
+                                if (row == null) \r
+                                        row = this.Rows.Find (keyValues, DataRowVersion.Current);\r
+                        }\r
+                                \r
+                        // If not found, add new row\r
+                        if (row == null) {\r
+                                row = this.NewRow ();\r
+                                new_row = true;\r
+                        }\r
+\r
+                        bool deleted = row.RowState == DataRowState.Deleted;\r
+\r
+                        if (deleted && loadOption == LoadOption.OverwriteChanges)\r
+                                row.RejectChanges ();                        \r
+\r
+                        row.Load (values, loadOption, new_row);\r
+\r
+                        if (deleted && loadOption == LoadOption.Upsert) {\r
+                                row = this.NewRow ();\r
+                                row.Load (values, loadOption, new_row = true);\r
+                        }\r
+\r
+                        if (new_row) {\r
+                                this.Rows.Add (row);\r
+                                if (loadOption == LoadOption.OverwriteChanges ||\r
+                                    loadOption == LoadOption.PreserveChanges) {\r
+                                        row.AcceptChanges ();\r
+                                }\r
+                        }\r
+\r
+                        return row;\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void Merge (DataTable table)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void Merge (DataTable table, bool preserveChanges)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+#endif\r
+\r
+               /// <summary>\r
+               /// Creates a new DataRow with the same schema as the table.\r
+               /// </summary>\r
+               public DataRow NewRow () \r
+               {\r
+                       EnsureDefaultValueRowIndex();\r
+\r
+                       DataRow newRow = NewRowFromBuilder (RowBuilder);\r
+\r
+                       newRow.Proposed = CreateRecord(null);\r
+                       return newRow;\r
+               }\r
+\r
+               internal int CreateRecord(object[] values) {\r
+                       int valCount = values != null ? values.Length : 0;\r
+                       if (valCount > Columns.Count)\r
+                               throw new ArgumentException("Input array is longer than the number of columns in this table.");\r
+\r
+                       int index = RecordCache.NewRecord();\r
+\r
+                       try {\r
+                               for (int i = 0; i < valCount; i++) {\r
+                                       try {\r
+                                               Columns[i].DataContainer[index] = values[i];\r
+                                       }\r
+                                       catch(Exception e) {\r
+                                               throw new ArgumentException(e.Message +\r
+                                                       String.Format("Couldn't store <{0}> in {1} Column.  Expected type is {2}.",\r
+                                                       values[i], Columns[i].ColumnName, Columns[i].DataType.Name), e);\r
+                                       }\r
+                               }\r
+\r
+                               for(int i = valCount; i < Columns.Count; i++) {\r
+                                       DataColumn column = Columns[i];\r
+                                       if (column.AutoIncrement)\r
+                                               column.DataContainer[index] = column.AutoIncrementValue ();\r
+                                       else\r
+                                               column.DataContainer.CopyValue(DefaultValuesRowIndex, index);\r
+                               }\r
+\r
+                               return index;\r
+                       }\r
+                       catch {\r
+                               RecordCache.DisposeRecord(index);\r
+                               throw;\r
+                       }\r
+               }\r
+\r
+               private void EnsureDefaultValueRowIndex()\r
+               {\r
+                       // initialize default values row for the first time\r
+                       if ( _defaultValuesRowIndex == -1 ) {\r
+                               _defaultValuesRowIndex = RecordCache.NewRecord();\r
+                               foreach(DataColumn column in Columns) {\r
+                                       column.DataContainer[_defaultValuesRowIndex] = column.DefaultValue;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// This member supports the .NET Framework infrastructure\r
+               ///  and is not intended to be used directly from your code.\r
+               /// </summary>\r
+               protected internal DataRow[] NewRowArray (int size) \r
+               {\r
+                       return (DataRow[]) Array.CreateInstance (GetRowType (), size);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Creates a new row from an existing row.\r
+               /// </summary>\r
+               protected virtual DataRow NewRowFromBuilder (DataRowBuilder builder) \r
+               {\r
+                       return new DataRow (builder);\r
+               }\r
+               \r
+               internal DataRow NewNotInitializedRow()\r
+               {\r
+                       EnsureDefaultValueRowIndex();\r
+\r
+                       return NewRowFromBuilder (RowBuilder);\r
+               }\r
+\r
+#if NET_2_0\r
+               [MonoTODO]\r
+               XmlReadMode ReadXml (Stream stream)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               public void ReadXmlSchema (Stream stream)\r
+               {\r
+                       ReadXmlSchema (new XmlTextReader (stream));\r
+               }\r
+\r
+               public void ReadXmlSchema (TextReader reader)\r
+               {\r
+                       ReadXmlSchema (new XmlTextReader (reader));\r
+               }\r
+\r
+               public void ReadXmlSchema (string fileName)\r
+               {\r
+                       XmlTextReader reader = null;\r
+                       try {\r
+                               reader = new XmlTextReader (fileName);\r
+                       ReadXmlSchema (reader);\r
+                       } finally {\r
+                               if (reader != null)\r
+                       reader.Close ();\r
+               }\r
+               }\r
+\r
+               public void ReadXmlSchema (XmlReader reader)\r
+               {\r
+                       DataSet ds = new DataSet ();\r
+                       new XmlSchemaDataImporter (ds, reader).Process ();\r
+                       DataTable target = null;\r
+                       if (TableName == String.Empty) {\r
+                               if (ds.Tables.Count > 0)\r
+                                       target = ds.Tables [0];\r
+                       }\r
+                       else {\r
+                               target = ds.Tables [TableName];\r
+                               if (target == null)\r
+                                       throw new ArgumentException (String.Format ("DataTable '{0}' does not match to any DataTable in source.", TableName));\r
+                       }\r
+                       if (target != null)\r
+                               target.CopyProperties (this);\r
+               }\r
+#endif\r
+\r
+               /// <summary>\r
+               /// Rolls back all changes that have been made to the \r
+               /// table since it was loaded, or the last time AcceptChanges\r
+               ///  was called.\r
+               /// </summary>\r
+               public void RejectChanges () \r
+               {       \r
+                       for (int i = _rows.Count - 1; i >= 0; i--) {\r
+                               DataRow row = _rows [i];\r
+                               if (row.RowState != DataRowState.Unchanged)\r
+                                       _rows [i].RejectChanges ();\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Resets the DataTable to its original state.\r
+               /// </summary>          \r
+               public virtual void Reset () \r
+               {\r
+                       Clear();\r
+                       while (ParentRelations.Count > 0)\r
+                       {\r
+                               if (dataSet.Relations.Contains(ParentRelations[ParentRelations.Count - 1].RelationName))\r
+                                       dataSet.Relations.Remove(ParentRelations[ParentRelations.Count - 1]);\r
+                       }\r
+\r
+                       while (ChildRelations.Count > 0)\r
+                       {\r
+                               if (dataSet.Relations.Contains(ChildRelations[ChildRelations.Count - 1].RelationName))\r
+                                       dataSet.Relations.Remove(ChildRelations[ChildRelations.Count - 1]);\r
+                       }\r
+                       Constraints.Clear();\r
+                       Columns.Clear();\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects.\r
+               /// </summary>\r
+               public DataRow[] Select () \r
+               {\r
+                       return Select(String.Empty, String.Empty, DataViewRowState.CurrentRows);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects that match \r
+               /// the filter criteria in order of primary key (or \r
+               /// lacking one, order of addition.)\r
+               /// </summary>\r
+               public DataRow[] Select (string filterExpression) \r
+               {\r
+                       return Select(filterExpression, String.Empty, DataViewRowState.CurrentRows);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects that \r
+               /// match the filter criteria, in the the \r
+               /// specified sort order.\r
+               /// </summary>\r
+               public DataRow[] Select (string filterExpression, string sort) \r
+               {\r
+                       return Select(filterExpression, sort, DataViewRowState.CurrentRows);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets an array of all DataRow objects that match\r
+               /// the filter in the order of the sort, that match \r
+               /// the specified state.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               public DataRow[] Select(string filterExpression, string sort, DataViewRowState recordStates) \r
+               {\r
+                       if (filterExpression == null)\r
+                               filterExpression = String.Empty;\r
+\r
+                       DataColumn[] columns = _emptyColumnArray;\r
+                       ListSortDirection[] sorts = null;\r
+                       if (sort != null && !sort.Equals(String.Empty))\r
+                               columns = ParseSortString (this, sort, out sorts, false);\r
+\r
+                       IExpression filter = null;\r
+                       if (filterExpression != String.Empty) {\r
+                               Parser parser = new Parser ();\r
+                               filter = parser.Compile (filterExpression);\r
+                       }\r
+\r
+                       Index index = FindIndex(columns, sorts, recordStates, filter);\r
+                       if (index == null)\r
+                               index = new Index(new Key(this,columns,sorts,recordStates,filter));\r
+\r
+                       int[] records = index.GetAll();\r
+                       DataRow[] dataRows = NewRowArray(index.Size);\r
+                       for (int i = 0; i < dataRows.Length; i++)\r
+                               dataRows[i] = RecordCache[records[i]];\r
+\r
+                       return dataRows;\r
+               }\r
+\r
+               \r
+               private void AddIndex (Index index)\r
+               {\r
+                       if (_indexes == null) {\r
+                               _indexes = new ArrayList();\r
+                       }\r
+\r
+                       _indexes.Add (index);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Returns index corresponding to columns,sort,row state filter and unique values given.\r
+               /// If such an index not exists, creates a new one.\r
+               /// </summary>\r
+               /// <param name="columns">Columns set of the index to look for.</param>\r
+               /// <param name="sort">Columns sort order of the index to look for.</param>\r
+               /// <param name="rowState">Rpw state filter of the index to look for.</param>\r
+               /// <param name="unique">Uniqueness of the index to look for.</param>\r
+               /// <param name="strict">Indicates whenever the index found should correspond in its uniquness to the value of unique parameter specified.</param>\r
+               /// <param name="reset">Indicates whenever the already existing index should be forced to reset.</param>\r
+               /// <returns></returns>\r
+               internal Index GetIndex(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter, bool reset)\r
+               {\r
+                       Index index = FindIndex(columns,sort,rowState,filter);\r
+                       if (index == null ) {\r
+                               index = new Index(new Key(this,columns,sort,rowState,filter));\r
+\r
+                               AddIndex(index);\r
+                       }\r
+                       else if (reset) {\r
+                               // reset existing index only if asked for this\r
+                               index.Reset();\r
+                       }\r
+                       return index;\r
+               }\r
+\r
+               internal Index FindIndex(DataColumn[] columns)\r
+               {\r
+                       return FindIndex(columns,null,DataViewRowState.None, null);\r
+               }\r
+\r
+               internal Index FindIndex(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter)\r
+               {\r
+                       if (Indexes != null) {\r
+                               foreach (Index index in Indexes) {\r
+                                       if (index.Key.Equals(columns,sort,rowState, filter)) {\r
+                                               return index;\r
+                                       }\r
+                               }\r
+                       }\r
+                       return null;\r
+               }\r
+\r
+               internal void ResetIndexes()\r
+               {\r
+                       foreach(Index index in Indexes) {\r
+                               index.Reset();\r
+                       }\r
+               }\r
+\r
+               internal void ResetCaseSensitiveIndexes()\r
+               {\r
+                       foreach(Index index in Indexes) {\r
+                               bool containsStringcolumns = false;\r
+                               foreach(DataColumn column in index.Key.Columns) {\r
+                                       if (column.DataType == typeof(string)) {\r
+                                               containsStringcolumns = true;\r
+                                               break;\r
+                                       }\r
+                               }\r
+\r
+                               if (containsStringcolumns) {\r
+                                       index.Reset();\r
+                               }\r
+                       }\r
+               }\r
+\r
+               internal void DropIndex(Index index)\r
+               {\r
+                       if (index != null && index.RefCount == 0) {     \r
+                               _indexes.Remove(index);\r
+                       }\r
+               }\r
+\r
+               internal void DeleteRowFromIndexes (DataRow row)\r
+               {\r
+                       if (_indexes != null) {\r
+                               foreach (Index indx in _indexes) {\r
+                                       indx.Delete (row);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Gets the TableName and DisplayExpression, if \r
+               /// there is one as a concatenated string.\r
+               /// </summary>\r
+               public override string ToString() \r
+               {\r
+                       //LAMESPEC: spec says concat the two. impl puts a \r
+                       //plus sign infront of DisplayExpression\r
+                       string retVal = TableName;\r
+                       if(DisplayExpression != null && DisplayExpression != "")\r
+                               retVal += " + " + DisplayExpression;\r
+                       return retVal;\r
+               }\r
+\r
+#if NET_2_0\r
+               private XmlWriterSettings GetWriterSettings ()\r
+               {\r
+                       XmlWriterSettings s = new XmlWriterSettings ();\r
+                       s.Indent = true;\r
+                       return s;\r
+               }\r
+\r
+               public void WriteXml (Stream stream)\r
+               {\r
+                       WriteXml (stream, XmlWriteMode.IgnoreSchema);\r
+               }\r
+\r
+               public void WriteXml (TextWriter writer)\r
+               {\r
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
+               }\r
+\r
+               public void WriteXml (XmlWriter writer)\r
+               {\r
+                       WriteXml (writer, XmlWriteMode.IgnoreSchema);\r
+               }\r
+\r
+               public void WriteXml (string fileName)\r
+               {\r
+                       WriteXml (fileName, XmlWriteMode.IgnoreSchema);\r
+               }\r
+\r
+               public void WriteXml (Stream stream, XmlWriteMode mode)\r
+               {\r
+                       WriteXml (XmlWriter.Create (stream, GetWriterSettings ()), mode);\r
+               }\r
+\r
+               public void WriteXml (TextWriter writer, XmlWriteMode mode)\r
+               {\r
+                       WriteXml (XmlWriter.Create (writer, GetWriterSettings ()), mode);\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void WriteXml (XmlWriter writer, XmlWriteMode mode)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               public void WriteXml (string fileName, XmlWriteMode mode)\r
+               {\r
+                       XmlWriter xw = null;\r
+                       try {\r
+                               xw = XmlWriter.Create (fileName, GetWriterSettings ());\r
+                               WriteXml (xw, mode);\r
+                       } finally {\r
+                               if (xw != null)\r
+                                       xw.Close ();\r
+                       }\r
+               }\r
+\r
+               public void WriteXmlSchema (Stream stream)\r
+               {\r
+                       WriteXmlSchema (XmlWriter.Create (stream, GetWriterSettings ()));\r
+               }\r
+\r
+               public void WriteXmlSchema (TextWriter writer)\r
+               {\r
+                       WriteXmlSchema (XmlWriter.Create (writer, GetWriterSettings ()));\r
+               }\r
+\r
+               public void WriteXmlSchema (XmlWriter writer)\r
+               {\r
+                       DataSet ds = DataSet;\r
+                       DataSet tmp = null;\r
+                       try {\r
+                               if (ds == null) {\r
+                                       tmp = ds = new DataSet ();\r
+                                       ds.Tables.Add (this);\r
+                               }\r
+                               DataTableCollection col = new DataTableCollection (ds);\r
+                               col.Add (this);\r
+                               XmlSchemaWriter.WriteXmlSchema (ds, writer, col, null);\r
+                       } finally {\r
+                               if (tmp != null)\r
+                                       ds.Tables.Remove (this);\r
+                       }\r
+               }\r
+\r
+               public void WriteXmlSchema (string fileName)\r
+               {\r
+                       XmlWriter xw = null;\r
+                       try {\r
+                               xw = XmlWriter.Create (fileName, GetWriterSettings ());\r
+                               WriteXmlSchema (xw);\r
+                       } finally {\r
+                               if (xw != null)\r
+                                       xw.Close ();\r
+                       }\r
+               }\r
+#endif\r
+               \r
+               #region Events \r
+               \r
+               /// <summary>\r
+               /// Raises the ColumnChanged event.\r
+               /// </summary>\r
+               protected virtual void OnColumnChanged (DataColumnChangeEventArgs e) {\r
+                       if (null != ColumnChanged) {\r
+                               ColumnChanged (this, e);\r
+                       }\r
+               }\r
+\r
+               internal void RaiseOnColumnChanged (DataColumnChangeEventArgs e) {\r
+                       OnColumnChanged(e);\r
+               }\r
+\r
+#if NET_2_0\r
+                /// <summary>\r
+               /// Raises TableCleared Event and delegates to subscribers\r
+               /// </summary>\r
+               protected virtual void OnTableCleared (DataTableClearEventArgs e) {\r
+                       if (TableCleared != null)\r
+                               TableCleared (this, e);\r
+               }\r
+#endif // NET_2_0\r
+\r
+               /// <summary>\r
+               /// Raises the ColumnChanging event.\r
+               /// </summary>\r
+               protected virtual void OnColumnChanging (DataColumnChangeEventArgs e) {\r
+                       if (null != ColumnChanging) {\r
+                               ColumnChanging (this, e);\r
+                       }\r
+               }\r
+\r
+               internal void RaiseOnColumnChanging (DataColumnChangeEventArgs e) {\r
+                       OnColumnChanging(e);\r
+               }\r
+\r
+               /// <summary>\r
+               /// Raises the PropertyChanging event.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               protected internal virtual void OnPropertyChanging (PropertyChangedEventArgs pcevent) {\r
+                       //      if (null != PropertyChanging)\r
+                       //      {\r
+                       //              PropertyChanging (this, e);\r
+                       //      }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Notifies the DataTable that a DataColumn is being removed.\r
+               /// </summary>\r
+               [MonoTODO]\r
+               protected internal virtual void OnRemoveColumn (DataColumn column) {\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Raises the RowChanged event.\r
+               /// </summary>\r
+               protected virtual void OnRowChanged (DataRowChangeEventArgs e) {\r
+                       if (null != RowChanged) {\r
+                               RowChanged(this, e);\r
+                       }\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               /// Raises the RowChanging event.\r
+               /// </summary>\r
+               protected virtual void OnRowChanging (DataRowChangeEventArgs e) {\r
+                       if (null != RowChanging) {\r
+                               RowChanging(this, e);\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Raises the RowDeleted event.\r
+               /// </summary>\r
+               protected virtual void OnRowDeleted (DataRowChangeEventArgs e) {\r
+                       if (null != RowDeleted) {\r
+                               RowDeleted(this, e);\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Raises the RowDeleting event.\r
+               /// </summary>\r
+               protected virtual void OnRowDeleting (DataRowChangeEventArgs e) {\r
+                       if (null != RowDeleting) {\r
+                               RowDeleting(this, e);\r
+                       }\r
+               }\r
+\r
+               /// <summary>\r
+               /// Occurs when after a value has been changed for \r
+               /// the specified DataColumn in a DataRow.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when a value has been changed for this column.")]\r
+               public event DataColumnChangeEventHandler ColumnChanged;\r
+\r
+               /// <summary>\r
+               /// Occurs when a value is being changed for the specified \r
+               /// DataColumn in a DataRow.\r
+               /// </summary>\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Occurs when a value has been submitted for this column. The user can modify the proposed value and should throw an exception to cancel the edit.")]\r
+               public event DataColumnChangeEventHandler ColumnChanging;\r
+\r
+               /// <summary>\r
+               /// Occurs after a DataRow has been changed successfully.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs after a row in the table has been successfully edited.")]\r
+               public event DataRowChangeEventHandler RowChanged;\r
+\r
+               /// <summary>\r
+               /// Occurs when a DataRow is changing.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when the row is being changed so that the event handler can modify or cancel the change. The user can modify values in the row and should throw an  exception to cancel the edit.")]\r
+               public event DataRowChangeEventHandler RowChanging;\r
+\r
+               /// <summary>\r
+               /// Occurs after a row in the table has been deleted.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs after a row in the table has been successfully deleted.")] \r
+               public event DataRowChangeEventHandler RowDeleted;\r
+\r
+               /// <summary>\r
+               /// Occurs before a row in the table is about to be deleted.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when a row in the table marked for deletion. Throw an exception to cancel the deletion.")]\r
+               public event DataRowChangeEventHandler RowDeleting;\r
+\r
+#if NET_2_0\r
+               /// <summary>\r
+               /// Occurs after the Clear method is called on the datatable.\r
+               /// </summary>\r
+               [DataCategory ("Data")] \r
+               [DataSysDescription ("Occurs when the rows in a table is cleared . Throw an exception to cancel the deletion.")]\r
+               public event DataTableClearEventHandler TableCleared;\r
+#endif // NET_2_0\r
+\r
+               #endregion // Events\r
+\r
+               /// <summary>\r
+               ///  Removes all UniqueConstraints\r
+               /// </summary>\r
+               private void RemoveUniqueConstraints () \r
+               {\r
+                       foreach (Constraint Cons in Constraints) {\r
+                               \r
+                               if (Cons is UniqueConstraint) {\r
+                                       Constraints.Remove (Cons);\r
+                                       break;\r
+                               }\r
+                       }\r
+                       \r
+                       UniqueConstraint.SetAsPrimaryKey(this.Constraints, null);\r
+               }\r
+\r
+               internal static DataColumn[] ParseSortString (DataTable table, string sort, out ListSortDirection[] sortDirections, bool rejectNoResult)\r
+               {\r
+                       DataColumn[] sortColumns = _emptyColumnArray;\r
+                       sortDirections = null;\r
+                       \r
+                       ArrayList columns = null;\r
+                       ArrayList sorts = null;\r
+               \r
+                       if (sort != null && !sort.Equals ("")) {\r
+                               columns = new ArrayList ();\r
+                               sorts = new ArrayList();\r
+                               string[] columnExpression = sort.Trim ().Split (new char[1] {','});\r
+                       \r
+                               for (int c = 0; c < columnExpression.Length; c++) {\r
+                                       string[] columnSortInfo = columnExpression[c].Trim ().Split (new char[1] {' '});\r
+                               \r
+                                       string columnName = columnSortInfo[0].Trim ();\r
+                                       string sortOrder = "ASC";\r
+                                       if (columnSortInfo.Length > 1) \r
+                                               sortOrder = columnSortInfo[1].Trim ().ToUpper (table.Locale);\r
+                                       \r
+                                       ListSortDirection sortDirection = ListSortDirection.Ascending;\r
+                                       switch (sortOrder) {\r
+                                       case "ASC":\r
+                                               sortDirection = ListSortDirection.Ascending;\r
+                                               break;\r
+                                       case "DESC":\r
+                                               sortDirection = ListSortDirection.Descending;\r
+                                               break;\r
+                                       default:\r
+                                               throw new IndexOutOfRangeException ("Could not find column: " + columnExpression[c]);\r
+                                       }\r
+\r
+                                       if (columnName.StartsWith("[") || columnName.EndsWith("]")) {\r
+                                               if (columnName.StartsWith("[") && columnName.EndsWith("]"))\r
+                                                       columnName = columnName.Substring(1, columnName.Length - 2);\r
+                                               else\r
+                                                       throw new ArgumentException(String.Format("{0} isn't a valid Sort string entry.", columnName));\r
+                                       }\r
+\r
+                                       DataColumn dc = table.Columns[columnName];\r
+                                       if (dc == null){\r
+                                               try {\r
+                                                       dc = table.Columns[Int32.Parse (columnName)];\r
+                                       }\r
+                                       catch (FormatException) {\r
+                                                       throw new IndexOutOfRangeException("Cannot find column " + columnName);\r
+                                       }\r
+                                       }\r
+\r
+                                       columns.Add (dc);\r
+                                       sorts.Add(sortDirection);\r
+                               }       \r
+                               sortColumns = (DataColumn[]) columns.ToArray (typeof (DataColumn));\r
+                               sortDirections = new ListSortDirection[sorts.Count];\r
+                               for (int i = 0; i < sortDirections.Length; i++)\r
+                                       sortDirections[i] = (ListSortDirection)sorts[i];\r
+                       }               \r
+\r
+                       if (rejectNoResult) {\r
+                               if (sortColumns == null)\r
+                                       throw new SystemException ("sort expression result is null");\r
+                               if (sortColumns.Length == 0)\r
+                                       throw new SystemException("sort expression result is 0");\r
+                       }\r
+\r
+                       return sortColumns;\r
+               }\r
+\r
+               private void UpdatePropertyDescriptorsCache()\r
+               {\r
+                       PropertyDescriptor[] descriptors = new PropertyDescriptor[Columns.Count + ChildRelations.Count];\r
+                       int index = 0;\r
+                       foreach(DataColumn col in Columns) {\r
+                               descriptors[index++] = new DataColumnPropertyDescriptor(col);\r
+                       }\r
+\r
+                       foreach(DataRelation rel in ChildRelations) {\r
+                               descriptors[index++] = new DataRelationPropertyDescriptor(rel);\r
+                       }\r
+\r
+                       _propertyDescriptorsCache = new PropertyDescriptorCollection(descriptors);\r
+               }\r
+\r
+               internal PropertyDescriptorCollection GetPropertyDescriptorCollection()\r
+               {\r
+                       if (_propertyDescriptorsCache == null) {\r
+                               UpdatePropertyDescriptorsCache();\r
+                       }\r
+\r
+                       return _propertyDescriptorsCache;\r
+               }\r
+\r
+               internal void ResetPropertyDescriptorsCache() {\r
+                       _propertyDescriptorsCache = null;\r
+               }\r
+       }\r
+}\r
index 924c024b9a5230d86097dd5e473d50b9f87a8ab5..d640eea4d5d58a44241c558ffb498387571f1e0a 100644 (file)
@@ -62,7 +62,11 @@ namespace System.Data {
                #region Properties
 
                public DataTable this[int index] {
-                       get { return (DataTable)(List[index]); }
+                       get {
+                               if (index < 0 || index >= List.Count)
+                                       throw new IndexOutOfRangeException(String.Format("Cannot find table {0}", index));
+                               return (DataTable)(List[index]);
+                       }
                }
 
                public DataTable this[string name] {
@@ -96,7 +100,7 @@ namespace System.Data {
 
                public virtual void Add (DataTable table) 
                {
-                       
+                       OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Add, table));
                        // check if the reference is a null reference
                        if(table == null)
                                throw new ArgumentNullException("table");
@@ -142,10 +146,15 @@ namespace System.Data {
                }
 #endif
 
-               public void AddRange (DataTable[] tables) 
-               {
-                       foreach (DataTable table in tables)
-                               this.Add (table);
+               public void AddRange (DataTable[] tables) {
+                       if (tables == null)
+                               return;
+
+                       for (int i = 0; i < tables.Length; i++){
+                               DataTable table = tables[i];
+                               if (table != null)
+                                       this.Add (table);
+                       }
                }
 
                public bool CanRemove (DataTable table) 
@@ -175,7 +184,10 @@ namespace System.Data {
 
                public void Remove (DataTable table) 
                {
-                       CanRemove(table, true);
+                       OnCollectionChanging (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
+                       if (CanRemove(table, true))
+                               table.dataSet = null;
+
                        List.Remove(table);
                        table.dataSet = null;
                        OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, table));
@@ -188,13 +200,7 @@ namespace System.Data {
 
                public void RemoveAt (int index) 
                {
-                       if (( index < 0 ) || (index >=List.Count))
-                               throw new IndexOutOfRangeException (String.Format ("There is no row at position {0}.", index));
-                       DataTable t = this [index];     
-                       CanRemove (t, true);
-                       List.RemoveAt (index);
-                       t.dataSet = null;
-                       OnCollectionChanged (new CollectionChangeEventArgs (CollectionChangeAction.Remove, t));
+                       Remove(this[index]);
                }
 
                #endregion
index 59a91eb8e5c2ac46ddee1d6e98ca70f08e12e06b..b5234cbe8ccd40c871ae86084c41b67a8b7e7cec 100644 (file)
-//
-// System.Data.DataView.cs
-//
-// Author:
-//    Daniel Morgan <danmorg@sc.rr.com>
-//    Tim Coleman (tim@timcoleman.com)
-//    Punit Todi (punits_mailbox@yahoo.com)
-//    Atsushi Enomoto <atsushi@ximian.com>
-//
-// Copyright (C) Daniel Morgan, 2002, 2003
-// (C) Ximian, Inc 2002
-// Copyright (C) Tim Coleman, 2002-2003                
-// (C) 2005 Novell, Inc
-//
-
-using System;
-using System.Collections;
-using System.Collections.Specialized;
-using System.ComponentModel;
-using System.Reflection;
-using Mono.Data.SqlExpressions;
-
-namespace System.Data 
-{
-       /// <summary>
-       /// A DataView is used in the binding of data between
-       /// a DataTable and Windows Forms or Web Forms allowing
-       /// a view of a DataTable for editing, filtering,
-       /// navigation, searching, and sorting.
-       /// </summary>
-       //[Designer]
-       [Editor]
-       [DefaultEvent ("PositionChanged")]
-       [DefaultProperty ("Table")]
-       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataViewDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
-       public class DataView : MarshalByValueComponent, IBindingList, IList, ICollection, IEnumerable, ITypedList, ISupportInitialize
-       {
-               DataTable dataTable = null;
-               string rowFilter = "";
-               IExpression rowFilterExpr;
-               string sort = "";
-               SortableColumn [] sortedColumns = null;
-               DataViewRowState rowState;
-               // DataRow -> DataRowView
-               UnsortedList addNewCache = new UnsortedList ();
-               OptionalSortedList rowViewPool = new OptionalSortedList ();
-
-               // BeginInit() support
-               bool isInitPhase = false;
-               bool inEndInit = false;
-               DataTable initTable;
-               bool initApplyDefaultSort;
-               string initSort;
-               string initRowFilter;
-               DataViewRowState initRowState;
-
-               bool allowNew = true; 
-               bool allowEdit = true;
-               bool allowDelete = true;
-               bool applyDefaultSort = false;
-               bool isSorted = false;
-
-               bool isOpen = false;
-
-               bool useDefaultSort = true;
-               
-               DataViewManager dataViewManager = null;
-
-               // These fields are used to store items temporarilly 
-               // during value change events.
-               DataRowView changingRowView;
-               int oldIndex;
-               int deletedIndex;
-
-               #region Constructors
-               public DataView () 
-               {
-                       rowState = DataViewRowState.CurrentRows;
-                       Open ();
-               }
-
-               public DataView (DataTable table)
-                       : this (table, (DataViewManager) null)
-               {
-               }
-
-               // This ctor() is for DataRowView.CreateChildView() support,
-               // which does not expose precise RowFilter, Sort and so on.
-               internal DataView (DataTable table, DataRow [] rows)
-               {
-                       dataTable = table;
-                       rowState = DataViewRowState.CurrentRows;
-                       RegisterEventHandlers ();
-
-                       foreach (DataRow dr in rows)
-                               rowViewPool.Add (dr, new DataRowView (this, dr));
-                       isOpen = true;
-               }
-
-               internal DataView (DataTable table, DataViewManager manager)
-               {
-                       dataTable = table;
-                       rowState = DataViewRowState.CurrentRows;
-                       dataViewManager = manager;
-                       Open ();
-               }
-
-               public DataView (DataTable table, string rowFilter,
-                       string sort, DataViewRowState rowState)
-                       : this (table, null, rowFilter, sort, rowState)
-               {
-               }
-
-               internal DataView (DataTable table, DataViewManager manager,
-                       string RowFilter, string Sort, DataViewRowState RowState)
-               {
-                       dataTable = table;
-                       dataViewManager = manager;
-                       rowState = DataViewRowState.CurrentRows;
-                       this.RowFilter = RowFilter;
-                       this.Sort = Sort;
-                       rowState = RowState;
-                       Open ();
-               }
-               #endregion // Constructors
-               #region PublicProperties
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows deletes.")]
-               [DefaultValue (true)]
-               public bool AllowDelete {
-                       get {
-                               return allowDelete;
-                       }
-                       set {
-                               allowDelete = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows edits.")]
-               [DefaultValue (true)]
-               public bool AllowEdit {
-                       get {
-                               return allowEdit;
-                       }
-                       set {
-                               allowEdit = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows new rows to be added.")]
-               [DefaultValue (true)]
-               public bool AllowNew {
-                       get {
-                               return allowNew;
-                       }
-                       
-                       set {
-                               allowNew = value;
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates whether to use the default sort if the Sort property is not set.")]
-               [DefaultValue (false)]
-               [RefreshProperties (RefreshProperties.All)]
-               public bool ApplyDefaultSort {
-                       get { return applyDefaultSort; }
-                       set {
-                               if (isInitPhase) {
-                                       initApplyDefaultSort = value;
-                                       return;
-                               }
-                               if (applyDefaultSort == value)
-                                       return;
-
-                               applyDefaultSort = value;
-                               if (applyDefaultSort == true &&
-                                       (sort == null || sort == string.Empty))
-                                       PopulateDefaultSort ();
-                               if (!inEndInit)
-                                       UpdateIndex (true);
-                       }
-               }
-               // get the count of rows in the DataView after RowFilter 
-               // and RowStateFilter have been applied
-               [Browsable (false)]
-               [DataSysDescription ("Returns the number of items currently in this view.")]
-               public int Count {
-                       get { return rowViewPool.Count + addNewCache.Count; }
-               }
-
-               [Browsable (false)]
-               [DataSysDescription ("This returns a pointer to back to the DataViewManager that owns this DataSet (if any).")]
-               public DataViewManager DataViewManager {
-                       get { return dataViewManager; }
-               }
-
-               // Item indexer
-               // the compiler creates a DefaultMemeberAttribute from
-               // this IndexerNameAttribute
-               [System.Runtime.CompilerServices.IndexerName("Item")]
-               public DataRowView this[int recordIndex] {
-                       get {
-                               if (recordIndex >= rowViewPool.Count + addNewCache.Count)
-                                       throw new IndexOutOfRangeException ();
-
-                               if (recordIndex < rowViewPool.Count)
-                                       return (DataRowView) rowViewPool.GetByIndex (recordIndex);
-                               else
-                                       return (DataRowView) addNewCache.GetByIndex (recordIndex - rowViewPool.Count);
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates an expression used to filter the data returned by this DataView.")]
-               [DefaultValue ("")]
-               public virtual string RowFilter {
-                       get { return rowFilter; }
-                       set {
-                               if (value == null)
-                                       value = String.Empty;
-                               if (isInitPhase) {
-                                       initRowFilter = value;
-                                       return;
-                               }
-
-                               if (rowFilter == value)
-                                       return;
-
-                               if (value == String.Empty) 
-                                       rowFilterExpr = null;
-                               else {
-                                       Parser parser = new Parser ();
-                                       rowFilterExpr = parser.Compile (value);
-                               }
-                               rowFilter = value;
-                               if (!inEndInit)
-                                       UpdateIndex (true);
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the versions of data returned by this DataView.")]
-               [DefaultValue (DataViewRowState.CurrentRows)]
-               public DataViewRowState RowStateFilter {
-                       get { return rowState; }
-                       set {
-                               if (isInitPhase) {
-                                       initRowState = value;
-                                       return;
-                               }
-
-                               if (value == rowState)
-                                       return;
-
-                               rowState = value;
-                               if (!inEndInit)
-                                       UpdateIndex (true);
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the order in which data is returned by this DataView.")]
-               [DefaultValue ("")]
-               public string Sort {
-                       get { return sort; }
-                       set {
-                               if (isInitPhase) {
-                                       initSort = value;
-                                       return;
-                               }
-                               if (value == sort)
-                                       return;
-
-                               if (value == null) {    
-                               /* if given value is null useDefaultSort */
-                                       useDefaultSort = true;
-                                       /* if ApplyDefault sort is true try appling it */
-                                       if (ApplyDefaultSort == true)
-                                               PopulateDefaultSort ();
-                               }
-                               else {  
-                                       /* else donot useDefaultSort. set it as false */
-                                       /* sort is set to value specified */
-                                       useDefaultSort = false;
-                                       sort = value;
-                                       sortedColumns = SortableColumn.ParseSortString (dataTable, value, true);
-                               }
-                               if (!inEndInit)
-                                       UpdateIndex (true);
-                       }
-               }
-
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the table this DataView uses to get data.")]
-               [DefaultValue (null)]
-               [RefreshProperties (RefreshProperties.All)]
-               [TypeConverter (typeof (DataTableTypeConverter))]
-               public DataTable Table {
-                       get { return dataTable; }
-                       set {
-                               if (isInitPhase) {
-                                       initTable = value;
-                                       return;
-                               }
-
-                               if (value != null && value.TableName.Equals("")) {
-                                       throw new DataException("Cannot bind to DataTable with no name.");
-                               }
-
-                               if (dataTable != null) {
-                                       UnregisterEventHandlers ();
-                               }
-
-                               dataTable = value;
-
-                               if (dataTable != null) {
-                                       RegisterEventHandlers ();
-                                       OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged, 0, 0));
-                                       sort = null;
-                                       sortedColumns = null;
-                                       rowFilter = null;
-                                       rowFilterExpr = null;
-                                       if (!inEndInit)
-                                               UpdateIndex (true);
-                               }
-                       }
-               }
-               #endregion // PublicProperties
-               
-               #region PublicMethods
-               public virtual DataRowView AddNew() 
-               {
-                       if (!IsOpen)
-                               throw new DataException ("DataView is not open.");
-                       if (!AllowNew)
-                               throw new DataException ("Cannot call AddNew on a DataView where AllowNew is false.");
-                       
-                       DataRow row = dataTable.NewRow ();
-                       if (row == null)
-                               throw new SystemException ("Row not created");
-                       DataRowView rowView = new DataRowView (this, row, true);
-                       addNewCache.Add (row, rowView);
-
-                       // DataRowView is added, but DataRow is still Detached.
-                       OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, rowViewPool.Count + addNewCache.Count - 1, -1));
-                       return rowView;
-               }
-
-               public void BeginInit ()
-               {
-                       initTable = Table;
-                       initApplyDefaultSort = ApplyDefaultSort;
-                       initSort = Sort;
-                       initRowFilter = RowFilter;
-                       initRowState = RowStateFilter;
-
-                       isInitPhase = true;
-               }
-
-               public void CopyTo (Array array, int index) 
-               {
-                       rowViewPool.CopyTo (array, index);
-                       addNewCache.CopyTo (array, index + rowViewPool.Count);
-               }
-
-               public void Delete(int index) 
-               {
-                       if (!IsOpen)
-                               throw new DataException ("DataView is not open.");
-                       if (!AllowDelete)
-                               throw new DataException ("Cannot delete on a DataSource where AllowDelete is false.");
-                       
-                       if (index > rowViewPool.Count + addNewCache.Count)
-                               throw new IndexOutOfRangeException ("There is no row at " +
-                                               "position: " + index + ".");
-                       DataRowView row = this [index];
-                       DeleteRowView (row);
-               }
-
-#if NET_2_0
-               [MonoTODO]
-               public virtual bool Equals (DataView dv)
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               public void EndInit ()
-               {
-                       isInitPhase = false;
-
-                       inEndInit = true;
-
-                       Table = initTable;
-                       ApplyDefaultSort = initApplyDefaultSort;
-                       Sort = initSort;
-                       RowFilter = initRowFilter;
-                       RowStateFilter = initRowState;
-
-                       inEndInit = false;
-
-                       UpdateIndex (true);
-               }
-
-               internal void CancelEditRowView (DataRowView rowView)
-               {
-                       int index = IndexOfRowView (rowView);
-                       if (addNewCache.Contains (rowView.Row))
-                               addNewCache.Remove (rowView.Row);
-                       else
-                               rowViewPool.Remove (rowView.Row);
-                       if (index >= 0)
-                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index, -1));
-                       rowView.Row.CancelEdit ();
-               }
-
-               internal void DeleteRowView (DataRowView rowView)
-               {
-                       int index = IndexOfRowView (rowView);
-                       if (addNewCache.Contains (rowView.Row))
-                               addNewCache.Remove (rowView.Row);
-                       else
-                               rowViewPool.Remove (rowView.Row);
-                       if (index >= 0)
-                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index, -1));
-                       rowView.Row.Delete ();
-               }
-
-               internal void EndEditRowView (DataRowView rowView)
-               {
-                       int index = IndexOfRow (rowView.Row);
-                       addNewCache.Remove (rowView.Row);
-                       OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, index, -1));
-
-                       rowView.Row.EndEdit ();
-                       if (rowView.Row.RowState == DataRowState.Detached)
-                               Table.Rows.Add (rowView.Row);
-                       int newIndex = int.MinValue;
-                       if (rowFilterExpr == null || rowFilterExpr.EvalBoolean (rowView.Row))
-                               newIndex = IndexOfRow (rowView.Row);
-                       OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, newIndex, index));
-               }
-
-               private IExpression [] PrepareExpr (object [] key)
-               {
-                       if (Sort == String.Empty)
-                               throw new ArgumentException ("Find method depends on an explicit Sort property value.");
-                       if (sortedColumns == null)
-                               throw new SystemException ("sort expression result is null");
-                       if (sortedColumns.Length == 0)
-                               throw new SystemException ("sort expression result is 0");
-                       if (sortedColumns.Length != key.Length)
-                               throw new ArgumentException (String.Format ("Expecting {0} keys being indexed based on Sort property, but got {1} keys.", sortedColumns.Length, key.Length));
-
-                       IExpression [] compExpr = new IExpression [sortedColumns.Length];
-                       for (int i = 0; i < sortedColumns.Length; i++)
-                               compExpr [i] = new Comparison (Operation.EQ,
-                                       new ColumnReference (sortedColumns [i].Column.ColumnName),
-                                       new Literal (key [i]));
-                       return compExpr;
-               }
-
-               public int Find (object key) 
-               {
-                       return Find (new object [] {key});
-               }
-               
-               public int Find (object[] key) 
-               {
-                       IExpression [] compExpr = PrepareExpr (key);
-
-                       // Find first match.
-                       int r = 0;
-                       IEnumerator e = GetEnumerator ();
-                       bool hasNext = false;
-                       for (; e.MoveNext (); r++) {
-                               if (!hasNext)
-                                       hasNext = true;
-                               if (!compExpr [0].EvalBoolean (((DataRowView) e.Current).Row))
-                                       continue;
-                               break;
-                       }
-                       if (!hasNext)
-                               return -1;
-                       bool finish = false;
-                       for (int c = 0; c < key.Length; c++)
-                               if (!compExpr [c].EvalBoolean (((DataRowView) e.Current).Row))
-                                       return -1;
-                       return r;
-               }
-
-               public DataRowView[] FindRows (object key) 
-               {
-                       return FindRows (new object [] {key});
-               }
-
-               public DataRowView [] FindRows (object[] key) 
-               {
-                       IExpression [] compExpr = PrepareExpr (key);
-
-                       // Find first match.
-                       int r = 0;
-                       IEnumerator e = GetEnumerator ();
-                       bool hasNext = false;
-                       while (e.MoveNext ()) {
-                               if (!hasNext)
-                                       hasNext = true;
-                               if (!compExpr [0].EvalBoolean (((DataRowView) e.Current).Row))
-                                       continue;
-                               break;
-                       }
-                       ArrayList al = new ArrayList ();
-                       // Find first no-match from here.
-                       do {
-                               if (!hasNext)
-                                       break;
-                               bool finish = false;
-                               for (int c = 0; c < key.Length; c++) {
-                                       if (!compExpr [c].EvalBoolean (((DataRowView) e.Current).Row)) {
-                                               finish = true;
-                                               break;
-                                       }
-                               }
-                               if (finish)
-                                       break;
-                               al.Add (e.Current);
-                       } while (e.MoveNext ());
-
-                       return (DataRowView []) al.ToArray (typeof (DataRowView));
-               }
-
-               public IEnumerator GetEnumerator() 
-               {
-                       ArrayList al = new ArrayList (rowViewPool.Count + addNewCache.Count);
-                       al.AddRange (rowViewPool.Values);
-                       al.AddRange (addNewCache.Values);
-                       return new DataViewEnumerator ((DataRowView [])
-                               al.ToArray (typeof (DataRowView)));
-               }
-               #endregion // PublicMethods
-               
-               [DataCategory ("Data")]
-               [DataSysDescription ("Indicates the data returned by this DataView has somehow changed.")]
-               public event ListChangedEventHandler ListChanged;
-
-               [Browsable (false)]
-               [DataSysDescription ("Indicates whether the view is open.")]
-               protected bool IsOpen {
-                       get { return isOpen; }
-               }
-
-               protected void Close ()
-               {
-                       if (dataTable != null)
-                               UnregisterEventHandlers ();
-                       UpdateIndex (false);
-                       rowViewPool.Clear ();
-                       addNewCache.Clear ();
-                       isOpen = false;
-               }
-
-               protected override void Dispose (bool disposing)
-               {
-                       if (disposing)
-                               Close ();
-
-                       base.Dispose (disposing);
-               }
-
-               protected virtual void IndexListChanged (
-                       object sender, ListChangedEventArgs e)
-               {
-               }
-
-               protected virtual void OnListChanged (ListChangedEventArgs e) 
-               {
-                       // Yes, under MS.NET, when it is overriden, the 
-                       // events are not fired (even if it is essential
-                       // to internal processing).
-                       if (ListChanged != null)
-                               ListChanged (this, e);
-               }
-
-               protected void Open () 
-               {
-                       // I wonder if this comment is still valid, but keep
-                       // in the meantime.
-
-                       // FIXME: create the initial index cache to the DataTable, and 
-                       //        only refresh the index when the DataTable
-                       //        has changes via column, row, or constraint
-                       //        changed events. the index cache is generally
-                       //        a DataViewRow array that points to the actual
-                       //        DataRows in the this DataTable's DataRowCollection;
-                       //        this index is really a cache that gets 
-                       //        created during Open(), gets Updated 
-                       //        when various properties of this view
-                       //        changes, gets Updated when this DataTable's 
-                       //        row, column, or constraint collections have changed.
-                       //        I'm not sure what else.
-                       //        The data view will know one of the DataTable's
-                       //        collections have changed via one of 
-                       //        its changed events.
-                       //        Otherwise, if getting a/the DataRowView(s),
-                       //        Count, or other properties, then just use the
-                       //        index cache.
-                       if (dataTable != null) {
-                               RegisterEventHandlers ();
-                       }
-                       UpdateIndex (true);
-                       isOpen = true;
-               }
-               
-               private void RegisterEventHandlers()
-               {
-                       dataTable.ColumnChanging += new DataColumnChangeEventHandler(OnColumnChanging);
-                       dataTable.ColumnChanged  += new DataColumnChangeEventHandler(OnColumnChanged);
-                       dataTable.RowChanged     += new DataRowChangeEventHandler(OnRowChanged);
-                       dataTable.RowDeleting    += new DataRowChangeEventHandler(OnRowDeleting);
-                       dataTable.RowDeleted     += new DataRowChangeEventHandler(OnRowDeleted);
-                       dataTable.Columns.CollectionChanged += new CollectionChangeEventHandler(ColumnCollectionChanged);
-                       dataTable.Constraints.CollectionChanged += new CollectionChangeEventHandler(OnConstraintCollectionChanged);
-               }
-
-               private void UnregisterEventHandlers()
-               {
-                       dataTable.ColumnChanging -= new DataColumnChangeEventHandler(OnColumnChanging);
-                       dataTable.ColumnChanged  -= new DataColumnChangeEventHandler(OnColumnChanged);
-                       dataTable.RowChanged     -= new DataRowChangeEventHandler(OnRowChanged);
-                       dataTable.RowDeleting    -= new DataRowChangeEventHandler(OnRowDeleting);
-                       dataTable.RowDeleted     -= new DataRowChangeEventHandler(OnRowDeleted);
-                       dataTable.Columns.CollectionChanged -= new CollectionChangeEventHandler(ColumnCollectionChanged);
-                       dataTable.Constraints.CollectionChanged -= new CollectionChangeEventHandler(OnConstraintCollectionChanged);
-               }
-
-               // These index storing and rowView preservation must be done
-               // before the actual row value is changed; thus we can't use
-               // RowChanging which accepts "already modified" DataRow.
-
-               private void OnColumnChanging (object sender, DataColumnChangeEventArgs e)
-               {
-                       changingRowView = (DataRowView) rowViewPool [e.Row];
-                       if (changingRowView != null) {
-                               oldIndex = rowViewPool.IndexOfKey (changingRowView.Row);
-                               rowViewPool.Remove (changingRowView.Row);
-                       }
-                       else
-                               oldIndex = int.MinValue;
-               }
-
-               private void OnColumnChanged (object sender, DataColumnChangeEventArgs e)
-               {
-                       if (changingRowView != null)
-                               rowViewPool.Add (changingRowView.Row, changingRowView);
-                       changingRowView = null;
-               }
-
-               private void OnRowChanged (object sender, DataRowChangeEventArgs args)
-               {
-                       if (args.Row == null)
-                               throw new SystemException ("Should not happen. Row is not supplied.");
-
-                       int newIndex;
-
-                       /* ItemAdded */
-                       if(args.Action == DataRowAction.Add)
-                       {
-                               if (rowFilterExpr != null &&
-                                       !rowFilterExpr.EvalBoolean (args.Row))
-                                       return; // do nothing.
-                               rowViewPool.Add (args.Row, new DataRowView (this, args.Row, false));
-                               newIndex = IndexOfRow (args.Row);
-                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, newIndex, -1));
-                       }
-                               
-                       /* ItemChanged or ItemMoved */
-                       if (args.Action == DataRowAction.Change) {
-                               DataRowView drv = (DataRowView) rowViewPool [args.Row];
-                               if (rowFilterExpr != null &&
-                                       !rowFilterExpr.EvalBoolean (args.Row)) {
-                                       // RowView disappearing from this view.
-                                       if (drv != null) {
-                                               oldIndex = IndexOfRowView (drv);
-                                               rowViewPool.Remove (args.Row);
-                                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, int.MinValue, oldIndex));
-                                       }
-                                       return;
-                               }
-                               else if (drv == null) {
-                                       // new RowView showing up in this view.
-                                       drv = new DataRowView (this, args.Row, false);
-                                       rowViewPool.Add (args.Row, drv);
-                                       newIndex = IndexOfRowView (drv);
-                                       OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, newIndex, int.MinValue));
-                                       return;
-                               }
-                               else {
-                                       newIndex = IndexOfRow (args.Row);
-                                       if (oldIndex == newIndex)
-                                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, newIndex, -1));
-                                       else
-                                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, newIndex, oldIndex));
-                               }
-                       }
-               }
-
-               private void OnRowDeleting (object sender,
-                       DataRowChangeEventArgs args)
-               {
-                       deletedIndex = IndexOfRow (args.Row);
-               }
-
-               private void OnRowDeleted (object sender, DataRowChangeEventArgs args)
-               {
-                       OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, deletedIndex, -1));
-               }
-               
-               protected virtual void ColumnCollectionChanged (object sender, CollectionChangeEventArgs args)
-               {
-                       // UpdateIndex() is not invoked here (even if the sort
-                       // column is being removed).
-
-                       /* PropertyDescriptor Add */
-                       if (args.Action == CollectionChangeAction.Add)
-                               OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorAdded,0,0));
-                       /* PropertyDescriptor Removed */
-                       if (args.Action == CollectionChangeAction.Remove)
-                               OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorDeleted,0,0));
-                       /* FIXME: PropertyDescriptor Changed ???*/
-                       if (args.Action == CollectionChangeAction.Refresh)
-                               OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged,0,0));
-               }
-               private void OnConstraintCollectionChanged(object sender, CollectionChangeEventArgs args)
-               {
-                       //      The Sort variable is set to the UniqueConstraint column.
-                       //  if ApplyDefault Sort is true and Sort is null or is not set Explicitly
-                       
-                       // FIXME: The interal cache may change as result of change in Constraint collection
-                       // one such scenerio is taken care.
-                       // There may be more. I dont know what else can be done.
-                       /* useDefaultSort is set to false when Sort is set explicitly */
-                       if (args.Action == CollectionChangeAction.Add && args.Element is UniqueConstraint) {
-                               if (ApplyDefaultSort == true && useDefaultSort == true)
-                                       PopulateDefaultSort ((UniqueConstraint) args.Element);
-                       }
-
-                       // UpdateIndex() is not invoked here.
-               }
-
-               // internal use by Mono
-               protected void Reset ()
-               {
-                       // TODO: what really happens? at least it does not Open, Close and Update Index.
-                       OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
-               }
-
-#if NET_2_0
-               [MonoTODO]
-               public DataTable ToTable ()
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               public DataTable ToTable (bool isDistinct, string[] columnNames)
-               {
-                       throw new NotImplementedException ();
-               }
-#endif
-
-               // internal use by Mono
-               protected void UpdateIndex () 
-               {
-                       UpdateIndex (false);
-               }
-
-               // This is method is internal to 
-               // the Mono implementation of DataView; it
-               // is not to be used from your code.
-               //
-               // Update the DataRowView array which is an index cache
-               // into the DataTable's DataRowCollection.
-               //
-               // I assume this is what UpdateIndex is used for
-               protected virtual void UpdateIndex (bool force) 
-               {
-                       if (dataTable == null || !force)
-                               return;
-                       DataRow[] rows = null;
-
-                       // I guess, "force" parameter is used to indicate
-                       // whether we should "query" against DataTable.
-                       // For example, when adding a new row, we don't have
-                       // to re-query.
-
-                       // Handle sort by itself, considering AddNew rows.
-                       rows = dataTable.Select (rowFilterExpr, null, RowStateFilter);
-
-                       OptionalSortedList newPool = null;
-                       if (sortedColumns != null)
-                               newPool = new OptionalSortedList (
-                                       dataTable,
-                                       sortedColumns,
-                                       rows.Length + 3);
-                       else
-                               newPool = new OptionalSortedList (rows.Length + 3);
-
-                       for (int r = 0; r < rows.Length; r++) {
-                               DataRow dr = rows [r];
-                               DataRowView rv = (DataRowView) rowViewPool [dr];
-                               if (rv == null)
-                                       rv = new DataRowView (this, dr);
-                               newPool.Add (dr, rv);
-                       }
-
-                       rowViewPool = newPool;
-
-                       OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));
-               }
-
-               [MonoTODO]
-               PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors) 
-               {
-                       // FIXME: use listAccessors somehow
-                       DataColumnPropertyDescriptor [] descriptors = 
-                               new DataColumnPropertyDescriptor [dataTable.Columns.Count];
-
-                       DataColumnPropertyDescriptor descriptor;
-                       DataColumn dataColumn;
-                       for (int col = 0; col < dataTable.Columns.Count; col ++) {
-                               dataColumn = dataTable.Columns[col];
-                               descriptor = new DataColumnPropertyDescriptor(
-                                       dataColumn.ColumnName, col, null);
-                               descriptor.SetComponentType (typeof (System.Data.DataRowView));
-                               descriptor.SetPropertyType (dataColumn.DataType);
-                               descriptor.SetReadOnly (dataColumn.ReadOnly);
-                               descriptors [col] = descriptor;
-                       }
-                       return new PropertyDescriptorCollection (descriptors);
-               }
-
-               [MonoTODO]
-               string ITypedList.GetListName (PropertyDescriptor[] listAccessors) 
-               {
-                       return "";
-               }
-
-               //int ICollection.Count { 
-               //      get {
-               //              return Count;
-               //      } 
-               //}
-
-               bool ICollection.IsSynchronized { 
-                       [MonoTODO]
-                       get {
-                               return false;
-                       } 
-               }
-
-               object ICollection.SyncRoot { 
-                       [MonoTODO]
-                       get {
-                               // FIXME:
-                               return this;
-                       }
-               }
-
-               //void ICollection.CopyTo (Array array, int index) 
-               //{
-               //      CopyTo (array, index);
-               //}
-
-               bool IList.IsFixedSize {
-                       [MonoTODO]
-                       get {
-                               return false;
-                       }
-               }
-               
-               bool IList.IsReadOnly {
-                       [MonoTODO]
-                       get {
-                               return false;
-                       }
-               }
-
-               object IList.this[int recordIndex] {
-                       [MonoTODO]
-                       get {
-                               return this[recordIndex];
-                       }
-
-                       [MonoTODO]
-                       set{
-                               throw new InvalidOperationException();
-                       }
-               }
-
-               int IList.Add (object value) 
-               {
-                       throw new ArgumentException ("Cannot add external objects to this list.");
-               }
-
-               void IList.Clear () 
-               {
-                       throw new ArgumentException ("Cannot clear this list.");
-               }
-
-               bool IList.Contains (object value) 
-               {
-                       DataRowView drv = value as DataRowView;
-                       if (drv == null)
-                               return false;
-                       return rowViewPool.Contains (drv) || addNewCache.Contains (drv);
-               }
-
-               int IList.IndexOf (object value) 
-               {
-                       DataRowView drv = value as DataRowView;
-                       if (drv == null)
-                               return -1;
-                       return IndexOfRowView (drv);
-               }
-                       
-               void IList.Insert (int index,object value) 
-               {
-                       throw new ArgumentException ("Cannot insert external objects to this list.");
-               }
-
-               void IList.Remove (object value) 
-               {
-                       // LAMESPEC: MS.NET's behavior is weird. It raises
-                       // events and*then* raises this exception.
-                       throw new ArgumentException ("Cannot remove from this list.");
-               }
-
-               void IList.RemoveAt (int index) 
-               {
-                       DataRowView drv = this [index]; // might raise OutOfRangeException here.
-                       if (drv == null)
-                               throw new ArgumentException ("Cannot remove from this list.");
-                       drv.Delete ();
-               }
-
-               #region IBindingList implementation
-
-               [MonoTODO]
-               void IBindingList.AddIndex (PropertyDescriptor property) 
-               {
-                       throw new NotImplementedException ();
-               }
-
-               object IBindingList.AddNew () 
-               {
-                       return this.AddNew ();
-               }
-
-               [MonoTODO]
-               void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction) 
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               int IBindingList.Find (PropertyDescriptor property, object key) 
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               void IBindingList.RemoveIndex (PropertyDescriptor property) 
-               {
-                       throw new NotImplementedException ();
-               }
-
-               [MonoTODO]
-               void IBindingList.RemoveSort () 
-               {
-                       throw new NotImplementedException ();
-               }
-               
-               bool IBindingList.AllowEdit {
-                       [MonoTODO]
-                       get {
-                               return AllowEdit;
-                       }
-               }
-
-               bool IBindingList.AllowNew {
-                       [MonoTODO]
-                       get {
-                               return AllowNew;
-                       }
-               }
-
-               bool IBindingList.AllowRemove {
-                       [MonoTODO]
-                       get {
-                               return AllowDelete;
-                       }
-               }
-
-               bool IBindingList.IsSorted {
-                       [MonoTODO]
-                       get {
-                               return isSorted;
-                       }
-               }
-
-               ListSortDirection IBindingList.SortDirection {
-                       [MonoTODO]
-                       get {
-                               // FIXME: 
-                               return ListSortDirection.Ascending;
-                       }
-               }
-
-               PropertyDescriptor IBindingList.SortProperty {
-                       [MonoTODO]
-                       get {
-                               // FIXME:
-                               return null;
-                       }
-               }
-
-               bool IBindingList.SupportsChangeNotification {
-                       [MonoTODO]
-                       get {
-                               return false;
-                       }
-               }
-
-               bool IBindingList.SupportsSearching {
-                       [MonoTODO]
-                       get {
-                               return false;
-                       }
-               }
-
-               bool IBindingList.SupportsSorting {
-                       [MonoTODO]
-                       get {
-                               return false;
-                       }
-               }
-
-               #endregion // IBindingList implementation
-               private int IndexOfRowView (DataRowView drv)
-               {
-                       int i = rowViewPool.IndexOfValue (drv);
-                       if (i >= 0)
-                               return i;
-                       if (addNewCache.Count == 0)
-                               return -1;
-                       IEnumerator e = addNewCache.Values.GetEnumerator ();
-                       for (i = 0; e.MoveNext (); i++)
-                               if (((DataRowView) e.Current) == drv)
-                                       return rowViewPool.Count + i;
-                       return -1;
-               }
-
-               private int IndexOfRow (DataRow dr)
-               {
-                       int i = rowViewPool.IndexOfKey (dr);
-                       if (i >= 0)
-                               return i;
-                       if (addNewCache.Count == 0)
-                               return -1;
-                       IEnumerator e = addNewCache.Keys.GetEnumerator ();
-                       for (i = 0; e.MoveNext (); i++)
-                               if (((DataRow) e.Current) == dr)
-                                       return rowViewPool.Count + i;
-                       throw new SystemException ("Should not happen.");
-               }
-
-               private void PopulateDefaultSort ()
-               {
-                       sort = "";
-                       foreach (Constraint c in dataTable.Constraints) {
-                               if (c is UniqueConstraint) {
-                                       PopulateDefaultSort ((UniqueConstraint) c);
-                                       break;
-                               }
-                       }
-               }
-
-               private void PopulateDefaultSort (UniqueConstraint uc)
-               {
-                       if (isInitPhase)
-                               return;
-
-                       sort = "";
-                       sortedColumns = new SortableColumn [uc.Columns.Length];
-                       int i = 0;
-                       foreach (DataColumn dc in uc.Columns) {
-                               sort += dc.ColumnName + ", ";
-                               sortedColumns [i++] = new SortableColumn (dc, ListSortDirection.Ascending);
-                       }
-                       sort = sort.Substring (0, sort.Length - 2);
-               }
-               
-               private object [] GetSearchKey (DataRow dr)
-               {
-                       if (sortedColumns == null) 
-                               return null;
-                       object [] keys = new object [sortedColumns.Length];
-                       int i = 0;
-                       foreach (SortableColumn sc in sortedColumns) {
-                               keys [i] = dr [sc.Column];
-                               i++;
-                       }
-                       return keys;
-               }
-
-               private class DataViewEnumerator : IEnumerator 
-               {
-                       private DataRowView [] rows;
-                       int on = -1;
-
-                       internal DataViewEnumerator (DataRowView [] dataRowViews) 
-                       {
-                               rows = dataRowViews;
-                       }
-
-                       public object Current {
-                               get {
-                                       if (on == -1 || on >= rows.Length)
-                                               throw new InvalidOperationException ();
-                                       return rows [on];
-                               }
-                       }
-
-                       public bool MoveNext () 
-                       {
-                               // It does not care about collection being changed.
-                               if (on < rows.Length - 1) {
-                                       on++;
-                                       return true;
-                               }
-
-                               return false; // EOF
-                       }
-
-                       public void Reset () {
-                               on = -1;
-                       }
-               }
-
-               private class RowViewFindComparer : IComparer 
-               {
-                       private SortableColumn [] sortColumns;
-                       private DataTable table;
-                       public RowViewFindComparer (DataTable table, SortableColumn[] sortColumns) 
-                       {
-                               this.table = table;                     
-                               this.sortColumns = sortColumns;
-                       }
-
-                       public SortableColumn[] SortedColumns {
-                               get {
-                                       return sortColumns;
-                               }
-                       }
-                       
-                       int IComparer.Compare (object x, object y) 
-                       {
-                               if(x == null)
-                                       throw new SystemException ("Object to compare is null: x");
-                               if(y == null)
-                                       throw new SystemException ("Object to compare is null: y");
-                               DataRowView rowView = (DataRowView) y;
-                               object [] keys = (object [])x;
-                               for(int i = 0; i < sortColumns.Length; i++) {
-                                       SortableColumn sortColumn = sortColumns [i];
-                                       DataColumn dc = sortColumn.Column;
-
-                                       IComparable row = (IComparable) rowView.Row [dc];
-                                       object key = keys [i];
-                                       
-                                       int result = CompareObjects (key,row);
-                                       if (result != 0) {
-                                               if (sortColumn.SortDirection == ListSortDirection.Ascending)
-                                                       return result;
-                                               else 
-                                                       return -result;
-                                       }
-                               }
-                               return 0;
-                       }
-
-                       private int CompareObjects (object a, object b) 
-                       {
-                               if (a == b)
-                                       return 0;
-                               else if (a == null)
-                                       return -1;
-                               else if (a == DBNull.Value)
-                                       return -1;
-                               else if (b == null)
-                                       return 1;
-                               else if (b == DBNull.Value)
-                                       return 1;
-
-                               if((a is string) && (b is string)) {
-                                       a = ((string) a).ToUpper (table.Locale);
-                                       b = ((string) b).ToUpper (table.Locale);                        
-                               }
-
-                               if (a is IComparable)
-                                       return ((a as IComparable).CompareTo (b));
-                               else if (b is IComparable)
-                                       return -((b as IComparable).CompareTo (a));
-
-                               throw new ArgumentException ("Neither a nor b IComparable");
-                       }
-               }
-
-       }
-
-       internal class UnsortedList : IDictionary
-       {
-               Hashtable items;
-               ArrayList orders;
-
-               public UnsortedList ()
-               {
-                       items = new Hashtable ();
-                       orders = new ArrayList ();
-               }
-
-               public UnsortedList (int size)
-               {
-                       items = new Hashtable (size);
-                       orders = new ArrayList (size);
-               }
-
-               public void Add (object key, object value)
-               {
-                       orders.Add (key);
-                       items.Add (key, value);
-               }
-
-               public bool Contains (object key)
-               {
-                       return orders.Contains (key);
-               }
-
-               public IDictionaryEnumerator GetEnumerator ()
-               {
-                       return new UnsortedListDictionaryEnumerator (
-                               orders, items);
-               }
-
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       return new UnsortedListDictionaryEnumerator (
-                               orders, items);
-               }
-
-               public object GetByIndex (int i)
-               {
-                       return items [orders [i]];
-               }
-
-               public int IndexOfKey (object key)
-               {
-                       for (int i = orders.Count - 1; i >= 0; i--)
-                               if (orders [i] == key)
-                                       return i;
-                       return -1;
-               }
-
-               public int IndexOfValue (object value)
-               {
-                       for (int i = orders.Count - 1; i >= 0; i--)
-                               if (items [orders [i]] == value)
-                                       return i;
-                       return -1;
-               }
-
-               public object this [object key] {
-                       get { return items [key]; }
-                       set { items [key] = value; }
-               }
-
-               public bool IsFixedSize {
-                       get { return false; }
-               }
-
-               public bool IsReadOnly {
-                       get { return false; }
-               }
-
-               public int Count {
-                       get { return orders.Count; }
-               }
-
-               public object SyncRoot {
-                       get { return this; }
-               }
-
-               public bool IsSynchronized {
-                       get { return false; }
-               }
-
-               public ICollection Keys {
-                       get { return orders; }
-               }
-
-               public ICollection Values {
-                       get {
-                               
-                               return SortedValues;
-                       }
-               }
-
-               public Array SortedValues {
-                       get {
-                               object [] results = new object [items.Count];
-                               for (int i = 0; i < orders.Count; i++)
-                                       results [i] = items [orders [i]];
-                               return results;
-                       }
-               }
-
-               public void CopyTo (Array array, int index)
-               {
-                       SortedValues.CopyTo (array, index);
-               }
-
-               public void Clear ()
-               {
-                       orders.Clear ();
-                       items.Clear ();
-               }
-
-               public void Remove (object o)
-               {
-                       orders.Remove (o);
-                       items.Remove (o);
-               }
-
-               internal class UnsortedListDictionaryEnumerator
-                       : IEnumerator, IDictionaryEnumerator
-               {
-                       ArrayList orders;
-                       Hashtable items;
-                       int index = -1;
-                       DictionaryEntry current;
-
-                       public UnsortedListDictionaryEnumerator (
-                               ArrayList orders, Hashtable items)
-                       {
-                               this.orders = orders;
-                               this.items = items;
-                       }
-
-                       public bool MoveNext ()
-                       {
-                               if (index + 1 == orders.Count)
-                                       return false;
-                               index++;
-                               object key = orders [index];
-                               current = new DictionaryEntry (key, items [key]);
-                               return true;
-                       }
-
-                       public DictionaryEntry Entry {
-                               get { return current; }
-                       }
-
-                       public object Current {
-                               get { return index < 0 ? (object) null : current; }
-                       }
-
-                       public object Key {
-                               get { return index < 0 ? (object) null : current.Key; }
-                       }
-
-                       public object Value {
-                               get { return index < 0 ? (object) null : current.Value; }
-                       }
-
-                       public void Reset ()
-                       {
-                               index = -1;
-                       }
-               }
-       }
-
-       // Since IndexOf() is not always working fine, we cannot make
-       // full use of SortedList (because RowSorter depends on "current"
-       // value of the value.
-       internal class OptionalSortedList : IDictionary
-       {
-               SortedList sorted;
-               UnsortedList unsorted;
-
-               public OptionalSortedList ()
-               {
-                       unsorted = new UnsortedList ();
-               }
-
-               public OptionalSortedList (int size)
-               {
-                       unsorted = new UnsortedList (size);
-               }
-
-               public OptionalSortedList (DataTable table,
-                       SortableColumn [] columns, int initSize)
-               {
-                       sorted = new SortedList (new DataTable.RowSorter (
-                               table, columns), initSize);
-               }
-
-               IDictionary Instance {
-                       get { return sorted != null ? (IDictionary) sorted : unsorted; }
-               }
-
-               public void Add (object key, object value)
-               {
-                       Instance.Add (key, value);
-               }
-
-               public bool Contains (object key)
-               {
-                       return Instance.Contains (key);
-               }
-
-               public IDictionaryEnumerator GetEnumerator ()
-               {
-                       return Instance.GetEnumerator ();
-               }
-
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       return Instance.GetEnumerator ();
-               }
-
-               public object GetByIndex (int i)
-               {
-                       if (sorted != null)
-                               return sorted.GetByIndex (i);
-                       else
-                               return unsorted.GetByIndex (i);
-               }
-
-               public int IndexOfKey (object key)
-               {
-                       if (sorted != null)
-                               return sorted.IndexOfKey (key);
-                       else
-                               return unsorted.IndexOfKey (key);
-               }
-
-               public int IndexOfValue (object value)
-               {
-                       if (sorted != null)
-                               return sorted.IndexOfValue (value);
-                       else
-                               return unsorted.IndexOfValue (value);
-               }
-
-               public object this [object key] {
-                       get { return Instance [key]; }
-                       set { Instance [key] = value; }
-               }
-
-               public bool IsFixedSize {
-                       get { return Instance.IsFixedSize; }
-               }
-
-               public bool IsReadOnly {
-                       get { return Instance.IsReadOnly; }
-               }
-
-               public int Count {
-                       get { return Instance.Count; }
-               }
-
-               public object SyncRoot {
-                       get { return Instance.SyncRoot; }
-               }
-
-               public bool IsSynchronized {
-                       get { return Instance.IsSynchronized; }
-               }
-
-               public ICollection Keys {
-                       get { return Instance.Keys; }
-               }
-
-               public ICollection Values {
-                       get { return Instance.Values; }
-               }
-
-               public void CopyTo (Array array, int index)
-               {
-                       Instance.CopyTo (array, index);
-               }
-
-               public void Clear ()
-               {
-                       Instance.Clear ();
-               }
-
-               public void Remove (object o)
-               {
-                       Instance.Remove (o);
-               }
-       }
-}
+//\r
+// System.Data.DataView.cs\r
+//\r
+// Author:\r
+//    Daniel Morgan <danmorg@sc.rr.com>\r
+//    Tim Coleman (tim@timcoleman.com)\r
+//    Punit Todi (punits_mailbox@yahoo.com)\r
+//    Atsushi Enomoto <atsushi@ximian.com>\r
+//    Konstantin Triger (kostat@mainsoft.com)\r
+//\r
+// Copyright (C) Daniel Morgan, 2002, 2003\r
+// (C) Ximian, Inc 2002\r
+// Copyright (C) Tim Coleman, 2002-2003                \r
+\r
+using System;\r
+using System.Collections;\r
+using System.ComponentModel;\r
+using System.Reflection;\r
+using System.Data.Common;\r
+using System.Globalization;\r
+using Mono.Data.SqlExpressions;\r
+using System.Text;\r
+\r
+namespace System.Data \r
+{\r
+       /// <summary>\r
+       /// A DataView is used in the binding of data between\r
+       /// a DataTable and Windows Forms or Web Forms allowing\r
+       /// a view of a DataTable for editing, filtering,\r
+       /// navigation, searching, and sorting.\r
+       /// </summary>\r
+       //[Designer]\r
+       [Editor]\r
+       [DefaultEvent ("PositionChanged")]\r
+       [DefaultProperty ("Table")]\r
+       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataViewDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]\r
+       public class DataView : MarshalByValueComponent, IBindingList, IList, ICollection, IEnumerable, ITypedList, ISupportInitialize\r
+       {\r
+               protected DataTable dataTable = null;\r
+               string rowFilter = String.Empty;\r
+               IExpression rowFilterExpr;\r
+               string sort = String.Empty;\r
+               DataViewRowState rowState;\r
+               protected DataRowView[] rowCache = null;\r
+\r
+               // BeginInit() support\r
+               bool isInitPhase = false;\r
+               bool inEndInit = false;\r
+               DataTable initTable;\r
+               bool initApplyDefaultSort;\r
+               string initSort;\r
+               string initRowFilter;\r
+               DataViewRowState initRowState;\r
+\r
+               // FIXME: what are the default values?\r
+               bool allowNew = true; \r
+               bool allowEdit = true;\r
+               bool allowDelete = true;\r
+               bool applyDefaultSort = false;\r
+               bool isSorted = false;\r
+\r
+               bool isOpen = false;\r
+\r
+               bool useDefaultSort = true;\r
+               \r
+               Index _index;\r
+               internal DataRow _lastAdded = null;\r
+               \r
+               private DataViewManager dataViewManager = null;\r
+               internal static ListChangedEventArgs ListResetEventArgs = new ListChangedEventArgs (ListChangedType.Reset,-1,-1);\r
+\r
+               #region Constructors\r
+\r
+               public DataView () \r
+               {\r
+                       rowState = DataViewRowState.CurrentRows;\r
+                       Open ();\r
+               }\r
+\r
+               public DataView (DataTable table)\r
+                       : this (table, (DataViewManager) null)\r
+               {\r
+               }\r
+\r
+               internal DataView (DataTable table, DataViewManager manager)\r
+               {\r
+                       dataTable = table;\r
+                       rowState = DataViewRowState.CurrentRows;\r
+                       dataViewManager = manager;\r
+                       Open ();\r
+               }\r
+\r
+               public DataView (DataTable table, string rowFilter,\r
+                       string sort, DataViewRowState rowState)\r
+                       : this (table, null, rowFilter, sort, rowState)\r
+               {\r
+               }\r
+\r
+               internal DataView (DataTable table, DataViewManager manager,\r
+                       string RowFilter, string Sort, DataViewRowState RowState)\r
+               {\r
+                       dataTable = table;\r
+                       dataViewManager = manager;\r
+                       rowState = DataViewRowState.CurrentRows;\r
+                       this.RowFilter = RowFilter;\r
+                       this.Sort = Sort;\r
+                       rowState = RowState;\r
+                       Open ();\r
+               }\r
+               #endregion // Constructors\r
+\r
+               #region PublicProperties\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows deletes.")]\r
+               [DefaultValue (true)]\r
+               public bool AllowDelete {\r
+                       get {\r
+                               return allowDelete;\r
+                       }\r
+                       set {\r
+                               allowDelete = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows edits.")]\r
+               [DefaultValue (true)]\r
+               public bool AllowEdit {\r
+                       get {\r
+                               return allowEdit;\r
+                       }\r
+                       set {\r
+                               allowEdit = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether this DataView and the user interface associated with it allows new rows to be added.")]\r
+               [DefaultValue (true)]\r
+               public bool AllowNew {\r
+                       get {\r
+                               return allowNew;\r
+                       }\r
+                       \r
+                       set {\r
+                               allowNew = value;\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates whether to use the default sort if the Sort property is not set.")]\r
+               [DefaultValue (false)]\r
+               [RefreshProperties (RefreshProperties.All)]\r
+               public bool ApplyDefaultSort {\r
+                       get { return applyDefaultSort; }\r
+                       set {\r
+                               if (isInitPhase) {\r
+                                       initApplyDefaultSort = value;\r
+                                       return;\r
+                               }\r
+                               if (applyDefaultSort == value)\r
+                                       return;\r
+\r
+                               applyDefaultSort = value;\r
+                               if (applyDefaultSort == true &&\r
+                                       (sort == null || sort == string.Empty))\r
+                                       PopulateDefaultSort ();\r
+                               if (!inEndInit)\r
+                                       UpdateIndex (true);\r
+                       }\r
+               }\r
+               // get the count of rows in the DataView after RowFilter \r
+               // and RowStateFilter have been applied\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Returns the number of items currently in this view.")]\r
+               public int Count {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return rowCache.Length;\r
+                       }\r
+               }\r
+\r
+               [Browsable (false)]\r
+               [DataSysDescription ("This returns a pointer to back to the DataViewManager that owns this DataSet (if any).")]\r
+               public DataViewManager DataViewManager {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return dataViewManager;\r
+                       }\r
+               }\r
+\r
+               // Item indexer\r
+               // the compiler creates a DefaultMemeberAttribute from\r
+               // this IndexerNameAttribute\r
+               [System.Runtime.CompilerServices.IndexerName("Item")]\r
+               public DataRowView this[int recordIndex] {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return rowCache [recordIndex];\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates an expression used to filter the data returned by this DataView.")]\r
+               [DefaultValue ("")]\r
+               public virtual string RowFilter {\r
+                       get { return rowFilter; }\r
+                       [MonoTODO]\r
+                       set {\r
+                               if (value == null)\r
+                                       value = String.Empty;\r
+                               if (isInitPhase) {\r
+                                       initRowFilter = value;\r
+                                       return;\r
+                               }\r
+\r
+                               CultureInfo info = (Table != null) ? Table.Locale : CultureInfo.CurrentCulture;\r
+                               if (String.Compare(rowFilter, value, false, info) == 0)\r
+                                       return;\r
+\r
+                               if (value == String.Empty) \r
+                                       rowFilterExpr = null;\r
+                               else {\r
+                                       Parser parser = new Parser ();\r
+                                       rowFilterExpr = parser.Compile (value);\r
+                               }\r
+                               rowFilter = value;\r
+                               if (!inEndInit)\r
+                                       UpdateIndex (true);\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the versions of data returned by this DataView.")]\r
+               [DefaultValue (DataViewRowState.CurrentRows)]\r
+               public DataViewRowState RowStateFilter {\r
+                       get { return rowState; }\r
+                       set {\r
+                               if (isInitPhase) {\r
+                                       initRowState = value;\r
+                                       return;\r
+                               }\r
+\r
+                               if (value == rowState)\r
+                                       return;\r
+\r
+                               rowState = value;\r
+                               if (!inEndInit)\r
+                                       UpdateIndex (true);\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the order in which data is returned by this DataView.")]\r
+               [DefaultValue ("")]\r
+               public string Sort {\r
+                       get { return sort; }\r
+                       set {\r
+                               if (isInitPhase) {\r
+                                       initSort = value;\r
+                                       return;\r
+                               }\r
+                               if (value == sort)\r
+                                       return;\r
+\r
+                               if (value == null) {    \r
+                               /* if given value is null useDefaultSort */\r
+                                       useDefaultSort = true;\r
+                                       /* if ApplyDefault sort is true try appling it */\r
+                                       if (ApplyDefaultSort == true)\r
+                                               PopulateDefaultSort ();\r
+                               }\r
+                               else {  \r
+                                       /* else donot useDefaultSort. set it as false */\r
+                                       /* sort is set to value specified */\r
+                                       useDefaultSort = false;\r
+                                       sort = value;\r
+                                       //sortedColumns = SortableColumn.ParseSortString (dataTable, value, true);\r
+                               }\r
+                               if (!inEndInit)\r
+                                       UpdateIndex (true);\r
+                       }\r
+               }\r
+\r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the table this DataView uses to get data.")]\r
+               [DefaultValue (null)]\r
+               [RefreshProperties (RefreshProperties.All)]\r
+               public DataTable Table {\r
+                       get { return dataTable; }\r
+                       set {\r
+                               if (isInitPhase) {\r
+                                       initTable = value;\r
+                                       return;\r
+                               }\r
+\r
+                               if (value != null && value.TableName.Equals("")) {\r
+                                       throw new DataException("Cannot bind to DataTable with no name.");\r
+                               }\r
+\r
+                               if (dataTable != null) {\r
+                                       UnregisterEventHandlers ();\r
+                               }\r
+\r
+                               dataTable = value;\r
+\r
+                               if (dataTable != null) {\r
+                                       RegisterEventHandlers ();\r
+                                       OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged, 0, 0));\r
+                                       sort = null;\r
+                                       rowFilter = null;\r
+                                       rowFilterExpr = null;\r
+                                       if (!inEndInit)\r
+                                               UpdateIndex (true);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               #endregion // PublicProperties\r
+               \r
+               #region PublicMethods\r
+\r
+               [MonoTODO]\r
+               public virtual DataRowView AddNew() \r
+               {\r
+                       if (!IsOpen)\r
+                               throw new DataException ("DataView is not open.");\r
+                       if (!AllowNew)\r
+                               throw new DataException ("Cannot call AddNew on a DataView where AllowNew is false.");\r
+                       \r
+                       if (_lastAdded != null) {\r
+                               // FIXME : finish last added\r
+                               CompleteLastAdded(true);\r
+                       }\r
+\r
+                       _lastAdded = dataTable.NewRow ();\r
+                       UpdateIndex(true);\r
+                       OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, Count - 1, -1));\r
+                        \r
+                       return this[Count - 1];\r
+               }\r
+\r
+               internal void CompleteLastAdded(bool add)\r
+               {\r
+                       DataRow dr = _lastAdded;\r
+\r
+                       if (add) {\r
+                               try {\r
+                                       dataTable.Rows.Add(_lastAdded);\r
+                                       OnListChanged(new ListChangedEventArgs(ListChangedType.ItemAdded, Count - 1, -1));\r
+                                       _lastAdded = null;\r
+                               }\r
+                               catch(Exception e) {\r
+                                       _lastAdded = dr;\r
+                                       throw e;\r
+                               }\r
+                       }\r
+                       else {\r
+                               _lastAdded.CancelEdit();\r
+                               _lastAdded = null;\r
+                               OnListChanged(new ListChangedEventArgs(ListChangedType.ItemDeleted, Count - 1));\r
+                       }\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void BeginInit() \r
+               {\r
+                       initTable = Table;\r
+                       initApplyDefaultSort = ApplyDefaultSort;\r
+                       initSort = Sort;\r
+                       initRowFilter = RowFilter;\r
+                       initRowState = RowStateFilter;\r
+\r
+                       isInitPhase = true;\r
+               }\r
+\r
+               [MonoTODO]\r
+               public void CopyTo (Array array, int index) \r
+               {\r
+                       if (index + rowCache.Length > array.Length) {\r
+                               throw new IndexOutOfRangeException();\r
+                       }\r
+\r
+                       int row = 0;\r
+                       for (; row < rowCache.Length && row < array.Length; row++) {\r
+                               array.SetValue (rowCache[row], index + row);\r
+                       }\r
+               }\r
+\r
+               public void Delete(int index) \r
+               {\r
+                       if (!IsOpen)\r
+                               throw new DataException ("DataView is not open.");\r
+\r
+                       if (_lastAdded != null && index == Count) {\r
+                               CompleteLastAdded(false);\r
+                               return;\r
+                       }\r
+\r
+                       if (!AllowDelete)\r
+                               throw new DataException ("Cannot delete on a DataSource where AllowDelete is false.");\r
+                       \r
+                       if (index > rowCache.Length)\r
+                               throw new IndexOutOfRangeException ("There is no row at " +\r
+                                               "position: " + index + ".");\r
+                       DataRowView row = rowCache [index];\r
+                       row.Row.Delete();\r
+               }\r
+\r
+#if NET_2_0\r
+               [MonoTODO]\r
+               public virtual bool Equals (DataView dv)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+#endif\r
+\r
+               [MonoTODO]\r
+               public void EndInit() \r
+               {\r
+                       isInitPhase = false;\r
+\r
+                       inEndInit = true;\r
+\r
+                       Table = initTable;\r
+                       ApplyDefaultSort = initApplyDefaultSort;\r
+                       Sort = initSort;\r
+                       RowFilter = initRowFilter;\r
+                       RowStateFilter = initRowState;\r
+\r
+                       inEndInit = false;\r
+\r
+                       UpdateIndex (true);\r
+               }\r
+\r
+               [MonoTODO]\r
+               public int Find(object key) \r
+               {\r
+                       object [] keys = new object[] { key };\r
+                       return Find(keys);\r
+               }\r
+               \r
+               [MonoTODO]\r
+               public int Find(object[] keys) \r
+               {\r
+                       if (sort == null || sort == string.Empty) {\r
+                               throw new ArgumentException ("Find finds a row based on a Sort order, and no Sort order is specified");\r
+                       }\r
+\r
+                       if (Index == null) {\r
+                               UpdateIndex(true);\r
+                       }\r
+\r
+                       int index = -1;                                 \r
+                       try {\r
+                               index = Index.FindIndex(keys);\r
+                       }\r
+                       catch(FormatException) {\r
+                               // suppress exception\r
+                       }\r
+                       catch(InvalidCastException) {\r
+                               // suppress exception\r
+                       }\r
+                       return index;\r
+               }\r
+               \r
+               [MonoTODO]\r
+               public DataRowView[] FindRows(object key) \r
+               {\r
+                       return FindRows(new object[] {key});\r
+               }\r
+\r
+               [MonoTODO]\r
+               public DataRowView[] FindRows(object[] keys) \r
+               {\r
+                       if (sort == null || sort == string.Empty) {\r
+                               throw new ArgumentException ("Find finds a row based on a Sort order, and no Sort order is specified");\r
+                       }\r
+\r
+                       if (Index == null) {\r
+                               UpdateIndex(true);\r
+                       }\r
+\r
+                       int[] indexes = Index.FindAllIndexes(keys);\r
+\r
+                       DataRowView[] rowViewArr = new DataRowView[indexes.Length];                     \r
+                       for (int r = 0; r < indexes.Length; r++) {\r
+                               rowViewArr[r] = rowCache[indexes[r]];\r
+                       }\r
+                       return rowViewArr;\r
+               }\r
+\r
+               public IEnumerator GetEnumerator() \r
+               {\r
+                       DataRowView[] dataRowViews = new DataRowView[Count];\r
+                       CopyTo(dataRowViews,0);\r
+                       return dataRowViews.GetEnumerator();\r
+               }\r
+\r
+               #endregion // PublicMethods\r
+               \r
+               [DataCategory ("Data")]\r
+               [DataSysDescription ("Indicates the data returned by this DataView has somehow changed.")]\r
+               public event ListChangedEventHandler ListChanged;\r
+\r
+               [Browsable (false)]\r
+               [DataSysDescription ("Indicates whether the view is open.")]\r
+               protected bool IsOpen {\r
+                       get { return isOpen; }\r
+               }\r
+\r
+               internal Index Index\r
+               {\r
+                       get {\r
+                               return _index;\r
+                       }\r
+\r
+                       set {\r
+                               if (_index != null) {\r
+                                       _index.RemoveRef();\r
+                                       Table.DropIndex(_index);\r
+                               }\r
+\r
+                               _index = value;\r
+\r
+                               if (_index != null) {\r
+                                       _index.AddRef();\r
+                               }\r
+                       }\r
+               }\r
+\r
+               protected void Close ()\r
+               {\r
+                       if (dataTable != null)\r
+                               UnregisterEventHandlers ();\r
+                       Index = null;\r
+                       rowCache = null;\r
+                       isOpen = false;\r
+               }\r
+\r
+               protected override void Dispose (bool disposing)\r
+               {\r
+                       if (disposing)\r
+                               Close ();\r
+\r
+                       base.Dispose (disposing);\r
+               }\r
+\r
+               protected virtual void IndexListChanged (\r
+                       object sender, ListChangedEventArgs e)\r
+               {\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected virtual void OnListChanged(ListChangedEventArgs e) \r
+               {\r
+                       // Yes, under MS.NET, when it is overriden, the \r
+                       // events are not fired (even if it is essential\r
+                       // to internal processing).\r
+                       try {\r
+                       if (ListChanged != null)\r
+                               ListChanged (this, e);\r
+                       } catch {\r
+                       }\r
+               }\r
+\r
+               internal void ChangedList(ListChangedType listChangedType, int newIndex,int oldIndex)\r
+               {\r
+                       ListChangedEventArgs e = new ListChangedEventArgs(listChangedType,newIndex,oldIndex);\r
+                       OnListChanged(e);\r
+               }\r
+\r
+               [MonoTODO]\r
+               protected void Open() \r
+               {\r
+                       // I wonder if this comment is still valid, but keep\r
+                       // in the meantime.\r
+\r
+                       // FIXME: create the initial index cache to the DataTable, and \r
+                       //        only refresh the index when the DataTable\r
+                       //        has changes via column, row, or constraint\r
+                       //        changed events. the index cache is generally\r
+                       //        a DataViewRow array that points to the actual\r
+                       //        DataRows in the this DataTable's DataRowCollection;\r
+                       //        this index is really a cache that gets \r
+                       //        created during Open(), gets Updated \r
+                       //        when various properties of this view\r
+                       //        changes, gets Updated when this DataTable's \r
+                       //        row, column, or constraint collections have changed.\r
+                       //        I'm not sure what else.\r
+                       //        The data view will know one of the DataTable's\r
+                       //        collections have changed via one of \r
+                       //        its changed events.\r
+                       //        Otherwise, if getting a/the DataRowView(s),\r
+                       //        Count, or other properties, then just use the\r
+                       //        index cache.\r
+                       //              dataTable.ColumnChanged  += new DataColumnChangeEventHandler(OnColumnChanged);\r
+                       \r
+                       UpdateIndex (true);\r
+                       if (dataTable != null) {\r
+                               RegisterEventHandlers();\r
+                       }\r
+                       isOpen = true;\r
+               }\r
+               \r
+               private void RegisterEventHandlers()\r
+               {\r
+                       //dataTable.ColumnChanging += new DataColumnChangeEventHandler(OnColumnChanging);\r
+                       dataTable.ColumnChanged  += new DataColumnChangeEventHandler(OnColumnChanged);\r
+                       dataTable.RowChanged     += new DataRowChangeEventHandler(OnRowChanged);\r
+                       //dataTable.RowDeleting    += new DataRowChangeEventHandler(OnRowDeleting);\r
+                       dataTable.RowDeleted     += new DataRowChangeEventHandler(OnRowDeleted);\r
+                       dataTable.Columns.CollectionChanged += new CollectionChangeEventHandler(ColumnCollectionChanged);\r
+                       dataTable.Constraints.CollectionChanged += new CollectionChangeEventHandler(OnConstraintCollectionChanged);\r
+               }\r
+\r
+               private void UnregisterEventHandlers()\r
+               {\r
+//                     dataTable.ColumnChanging -= new DataColumnChangeEventHandler(OnColumnChanging);\r
+                       dataTable.ColumnChanged  -= new DataColumnChangeEventHandler(OnColumnChanged);\r
+                       dataTable.RowChanged     -= new DataRowChangeEventHandler(OnRowChanged);\r
+//                     dataTable.RowDeleting    -= new DataRowChangeEventHandler(OnRowDeleting);\r
+                       dataTable.RowDeleted     -= new DataRowChangeEventHandler(OnRowDeleted);\r
+                       dataTable.Columns.CollectionChanged -= new CollectionChangeEventHandler(ColumnCollectionChanged);\r
+                       dataTable.Constraints.CollectionChanged -= new CollectionChangeEventHandler(OnConstraintCollectionChanged);\r
+               }\r
+\r
+               // These index storing and rowView preservation must be done\r
+               // before the actual row value is changed; thus we can't use\r
+               // RowChanging which accepts "already modified" DataRow.\r
+\r
+               private void OnColumnChanged(object sender, DataColumnChangeEventArgs args)\r
+               {       /* not used */\r
+                       //UpdateIndex(true);\r
+               }\r
+               \r
+               private void OnRowChanged(object sender, DataRowChangeEventArgs args)\r
+               {\r
+                       int oldIndex,newIndex;\r
+                       oldIndex = newIndex = -1;\r
+                       oldIndex = IndexOf (args.Row);\r
+                       UpdateIndex (true);\r
+                       newIndex = IndexOf (args.Row);\r
+\r
+                       /* ItemAdded */\r
+                       if(args.Action == DataRowAction.Add)\r
+                       {\r
+                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, newIndex, -1));\r
+                       }\r
+                               \r
+                       /* ItemChanged or ItemMoved */\r
+                       if (args.Action == DataRowAction.Change) {\r
+                                       if (oldIndex == newIndex)\r
+                                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, newIndex, -1));\r
+                                       else\r
+                                               OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, newIndex, oldIndex));\r
+                               }\r
+                       }\r
+\r
+               private void OnRowDeleted (object sender, DataRowChangeEventArgs args)\r
+               {\r
+                       /* ItemDeleted */\r
+                       int newIndex;\r
+                       newIndex = IndexOf (args.Row);\r
+                       UpdateIndex (true);\r
+                       OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, newIndex, -1));\r
+               }\r
+               \r
+               protected virtual void ColumnCollectionChanged (object sender, CollectionChangeEventArgs args)\r
+               {\r
+                       // UpdateIndex() is not invoked here (even if the sort\r
+                       // column is being removed).\r
+\r
+                       /* PropertyDescriptor Add */\r
+                       if (args.Action == CollectionChangeAction.Add)\r
+                               OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorAdded,0,0));\r
+                       /* PropertyDescriptor Removed */\r
+                       if (args.Action == CollectionChangeAction.Remove)\r
+                               OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorDeleted,0,0));\r
+                       /* FIXME: PropertyDescriptor Changed ???*/\r
+                       if (args.Action == CollectionChangeAction.Refresh)\r
+                               OnListChanged (new ListChangedEventArgs (ListChangedType.PropertyDescriptorChanged,0,0));\r
+               }\r
+               private void OnConstraintCollectionChanged(object sender, CollectionChangeEventArgs args)\r
+               {\r
+                       //      The Sort variable is set to the UniqueConstraint column.\r
+                       //  if ApplyDefault Sort is true and Sort is null or is not set Explicitly\r
+                       \r
+                       // FIXME: The interal cache may change as result of change in Constraint collection\r
+                       // one such scenerio is taken care.\r
+                       // There may be more. I dont know what else can be done.\r
+                       /* useDefaultSort is set to false when Sort is set explicitly */\r
+                       if (args.Action == CollectionChangeAction.Add && args.Element is UniqueConstraint) {\r
+                               if (ApplyDefaultSort == true && useDefaultSort == true)\r
+                                       PopulateDefaultSort ((UniqueConstraint) args.Element);\r
+                       }\r
+                       // UpdateIndex() is not invoked here.\r
+               }\r
+\r
+               // internal use by Mono\r
+               protected void Reset() \r
+               {\r
+                       // TODO: what really happens?\r
+                       Close ();\r
+                       rowCache = null;\r
+                       Open ();\r
+                       OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1 ));\r
+               }\r
+\r
+#if NET_2_0\r
+               [MonoTODO]\r
+               public DataTable ToTable ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               public DataTable ToTable (bool isDistinct, string[] columnNames)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+#endif\r
+               protected void UpdateIndex() {\r
+                       UpdateIndex(false);\r
+               }\r
+\r
+               // This is method is internal to \r
+               // the Mono implementation of DataView; it\r
+               // is not to be used from your code.\r
+               //\r
+               // Update the DataRowView array which is an index cache\r
+               // into the DataTable's DataRowCollection.\r
+               //\r
+               // I assume this is what UpdateIndex is used for\r
+               protected virtual void UpdateIndex(bool force) \r
+               {\r
+                       if (Table == null) {\r
+                               // FIXME\r
+                               return;\r
+                       }\r
+\r
+                       if (Index == null || force) {\r
+                               ListSortDirection[] sortOrder = null;\r
+                               DataColumn[] columns = DataTable.ParseSortString(Table, Sort, out sortOrder, false);\r
+                               Index = dataTable.GetIndex(columns,sortOrder,RowStateFilter,FilterExpression,true);\r
+                       }\r
+                       else {\r
+                               Index.Key.RowStateFilter = RowStateFilter;\r
+                               Index.Reset();\r
+                       }\r
+\r
+                       int[] records = Index.GetAll();\r
+\r
+                       if (records != null) {\r
+                               InitDataRowViewArray(records,Index.Size);\r
+                       }\r
+                       else {\r
+                               rowCache = new DataRowView[0];\r
+                       }\r
+\r
+                       OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1, -1));\r
+               }\r
+\r
+               internal virtual IExpression FilterExpression\r
+               {\r
+                       get {\r
+                               return rowFilterExpr;\r
+                       }\r
+               }\r
+\r
+               private void InitDataRowViewArray(int[] records,int size) \r
+               {\r
+                       if (_lastAdded != null) {\r
+                               rowCache = new DataRowView[size + 1];   \r
+                       }\r
+                       else {\r
+                               rowCache = new DataRowView[size];                       \r
+                       }\r
+\r
+                       for (int r = 0; r < size; r++) {\r
+                               rowCache[r] = new DataRowView (this, Table.RecordCache[records[r]],r);\r
+                       }\r
+\r
+                       if(_lastAdded != null) {\r
+                               rowCache[size] = new DataRowView(this,_lastAdded,size);\r
+                       }\r
+               }\r
+\r
+               [MonoTODO]\r
+               PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors) \r
+               {\r
+                       // FIXME: use listAccessors somehow\r
+                       DataColumnPropertyDescriptor [] descriptors = \r
+                               new DataColumnPropertyDescriptor [dataTable.Columns.Count];\r
+\r
+                       DataColumnPropertyDescriptor descriptor;\r
+                       DataColumn dataColumn;\r
+                       for (int col = 0; col < dataTable.Columns.Count; col ++) {\r
+                               dataColumn = dataTable.Columns[col];\r
+                               descriptor = new DataColumnPropertyDescriptor(\r
+                                       dataColumn.ColumnName, col, null);\r
+                               descriptor.SetComponentType (typeof (System.Data.DataRowView));\r
+                               descriptor.SetPropertyType (dataColumn.DataType);\r
+                               descriptor.SetReadOnly (dataColumn.ReadOnly);\r
+                               descriptors [col] = descriptor;\r
+                       }\r
+                       return new PropertyDescriptorCollection (descriptors);\r
+               }\r
+\r
+               [MonoTODO]\r
+               string ITypedList.GetListName (PropertyDescriptor[] listAccessors) \r
+               {\r
+                       return "";\r
+               }\r
+\r
+               bool ICollection.IsSynchronized { \r
+                       [MonoTODO]\r
+                       get {\r
+                               return false;\r
+                       } \r
+               }\r
+\r
+               object ICollection.SyncRoot { \r
+                       [MonoTODO]\r
+                       get {\r
+                               // FIXME:\r
+                               return this;\r
+                       }\r
+               }\r
+\r
+               bool IList.IsFixedSize {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return false;\r
+                       }\r
+               }\r
+               \r
+               bool IList.IsReadOnly {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               object IList.this[int recordIndex] {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return this[recordIndex];\r
+                       }\r
+\r
+                       [MonoTODO]\r
+                       set{\r
+                               throw new InvalidOperationException();\r
+                       }\r
+               }\r
+\r
+               int IList.Add (object value) \r
+               {\r
+                       throw new ArgumentException ("Cannot add external objects to this list.");\r
+               }\r
+\r
+               void IList.Clear () \r
+               {\r
+                       throw new ArgumentException ("Cannot clear this list.");\r
+               }\r
+\r
+               bool IList.Contains (object value) \r
+               {\r
+                       DataRowView drv = value as DataRowView;\r
+                       if (drv == null)\r
+                               return false;\r
+\r
+                       return drv.DataView == this;\r
+               }\r
+\r
+               int IList.IndexOf (object value) \r
+               {\r
+                       DataRowView drv = value as DataRowView;\r
+                       if (drv != null && drv.DataView == this) {\r
+                               return drv.Index;\r
+                       }\r
+\r
+                       return -1;\r
+               }\r
+\r
+               void IList.Insert(int index,object value) \r
+               {\r
+                       throw new ArgumentException ("Cannot insert external objects to this list.");\r
+               }\r
+\r
+               void IList.Remove(object value) \r
+               {\r
+                       DataRowView drv = value as DataRowView;\r
+                       if (drv != null && drv.DataView == this) {\r
+                               ((IList)this).RemoveAt(drv.Index);\r
+                       }\r
+\r
+                       throw new ArgumentException ("Cannot remove external objects to this list.");\r
+               }\r
+\r
+               void IList.RemoveAt(int index) \r
+               {\r
+                       Delete(index);\r
+               }\r
+\r
+               #region IBindingList implementation\r
+\r
+               [MonoTODO]\r
+               void IBindingList.AddIndex (PropertyDescriptor property) \r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               object IBindingList.AddNew () \r
+               {\r
+                       return this.AddNew ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction) \r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               int IBindingList.Find (PropertyDescriptor property, object key) \r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               void IBindingList.RemoveIndex (PropertyDescriptor property) \r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+\r
+               [MonoTODO]\r
+               void IBindingList.RemoveSort () \r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+               \r
+               bool IBindingList.AllowEdit {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return AllowEdit;\r
+                       }\r
+               }\r
+\r
+               bool IBindingList.AllowNew {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return AllowNew;\r
+                       }\r
+               }\r
+\r
+               bool IBindingList.AllowRemove {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return AllowDelete;\r
+                       }\r
+               }\r
+\r
+               bool IBindingList.IsSorted {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return isSorted;\r
+                       }\r
+               }\r
+\r
+               ListSortDirection IBindingList.SortDirection {\r
+                       [MonoTODO]\r
+                       get {\r
+                               // FIXME: \r
+                               return ListSortDirection.Ascending;\r
+                       }\r
+               }\r
+\r
+               PropertyDescriptor IBindingList.SortProperty {\r
+                       [MonoTODO]\r
+                       get {\r
+                               // FIXME:\r
+                               return null;\r
+                       }\r
+               }\r
+\r
+               bool IBindingList.SupportsChangeNotification {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               bool IBindingList.SupportsSearching {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               bool IBindingList.SupportsSorting {\r
+                       [MonoTODO]\r
+                       get {\r
+                               return false;\r
+                       }\r
+               }\r
+\r
+               #endregion // IBindingList implementation\r
+               private int IndexOf(DataRow dr)\r
+               {\r
+                       for (int i=0; i < rowCache.Length; i++)\r
+                               if (dr.Equals (rowCache [i].Row))\r
+                               return i;\r
+                       return -1;\r
+               }\r
+               \r
+               private void PopulateDefaultSort () {\r
+                       sort = "";\r
+                       foreach (Constraint c in dataTable.Constraints) {\r
+                               if (c is UniqueConstraint) {\r
+                                       PopulateDefaultSort ((UniqueConstraint) c);\r
+                                       break;\r
+                               }\r
+                       }\r
+               }\r
+\r
+               private void PopulateDefaultSort (UniqueConstraint uc) {\r
+                       if (isInitPhase)\r
+                               return;\r
+\r
+                       DataColumn[] columns = uc.Columns;\r
+                       if (columns.Length == 0) {\r
+                               sort = String.Empty;\r
+                               return;\r
+                       }\r
+\r
+                       StringBuilder builder = new StringBuilder();\r
+                       builder.Append(columns[0].ColumnName);\r
+                       for (int i = 1; i<columns.Length; i++) {\r
+                               builder.Append(", ");\r
+                               builder.Append(columns[i].ColumnName);\r
+                       }\r
+                       sort = builder.ToString();\r
+               }\r
+               \r
+               // FIXME : complete the implementation\r
+               internal DataView CreateChildView (DataRelation relation,object[] keyValues)\r
+               {\r
+                       if (relation == null || relation.ParentTable != Table) {\r
+                               throw new ArgumentException("The relation is not parented to the table to which this DataView points.");\r
+                       }\r
+                       return new RelatedDataView(relation.ChildColumns,keyValues);\r
+               }\r
+\r
+               // FIXME : complete the implementation\r
+               internal DataView CreateChildView (string name,object[] keyValues)\r
+               {\r
+                       DataRelation relation = Table.ChildRelations[name];\r
+\r
+                       if (relation != null) {\r
+                               return CreateChildView(relation,keyValues);\r
+                       }\r
+\r
+                       throw new ArgumentException("Relation " + name + " not found in the table");\r
+               }\r
+\r
+               private int GetRecord(int index) {\r
+                       if (index < 0 || index >= Count)\r
+                               throw new IndexOutOfRangeException(String.Format("There is no row at position {0}.", index));\r
+\r
+                       return(index == Index.Size) ?\r
+                               _lastAdded.IndexFromVersion(DataRowVersion.Default) :\r
+                               Index.IndexToRecord(index);\r
+               }\r
+\r
+               internal DataRowVersion GetRowVersion(int index) {\r
+                       int record = GetRecord(index);\r
+                       return Table.RecordCache[record].VersionFromIndex(record);\r
+               }\r
+       }\r
+}\r
index 4fd66ec8d1430b182a89d27485c31e0e108b6edb..9a2f6788a4543971aef8b6b631263ff33f3d9c06 100644 (file)
-//
-// System.Data.DataViewManager
-//
-// Author:
-//   Rodrigo Moya (rodrigo@ximian.com)
-//   Tim Coleman (tim@timcoleman.com)
-//   Atsushi Enomoto (atsushi@ximian.com)
-//
-// (C) Ximian, Inc. 2002
-// Copyright (C) Tim Coleman, 2002
-// Copyright (C) 2005 Novell Inc,
-//
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
-using System;
-using System.Collections;
-using System.ComponentModel;
-using System.IO;
-using System.Xml;
-
-namespace System.Data
-{
-       /// <summary>
-       /// Contains a default DataViewSettingCollection for each DataTable in a DataSet.
-       /// </summary>
-       //[Designer]
-       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataViewManagerDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]
-       public class DataViewManager : MarshalByValueComponent, IBindingList, ICollection, IList, ITypedList, IEnumerable
-       {
-               #region Fields
-
-               DataSet dataSet;
-               DataViewManagerListItemTypeDescriptor descriptor;
-               DataViewSettingCollection settings;
-               string xml;
-
-               #endregion // Fields
-
-               #region Constructors
-
-               public DataViewManager ()
-                       : this (null)
-               {
-               }
-
-               public DataViewManager (DataSet ds)
-               {
-                       // Null argument is allowed here.
-                       SetDataSet (ds);
-               }
-
-               #endregion // Constructors
-
-               #region Properties
-
-               [DataSysDescription ("Indicates the source of data for this DataViewManager.")]
-               [DefaultValue (null)]
-               public DataSet DataSet {
-                       get { return dataSet; }
-                       set {
-                               if (value == null)
-                                       throw new DataException ("Cannot set null DataSet.");
-                               SetDataSet (value);
-                       }
-               }
-
-               public string DataViewSettingCollectionString {
-                       get { return xml; }
-                       set {
-                               try {
-                                       ParseSettingString (value);
-                                       xml = BuildSettingString ();
-                               } catch (XmlException ex) {
-                                       throw new DataException ("Cannot set DataViewSettingCollectionString.", ex);
-                               }
-                       }
-               }
-
-               [DataSysDescription ("Indicates the sorting/filtering/state settings for any table in the corresponding DataSet.")]
-                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]
-               public DataViewSettingCollection DataViewSettings {
-                       get { return settings; }
-               }
-
-               int ICollection.Count {
-                       get { return settings.Count; }
-               }
-
-               bool ICollection.IsSynchronized {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               object ICollection.SyncRoot {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IList.IsFixedSize {
-                       get { return true; }
-               }
-
-               bool IList.IsReadOnly {
-                       get { return true; }
-               }
-
-               object IList.this [int index] {
-                       get { 
-                               if (descriptor == null)
-                                       descriptor = new DataViewManagerListItemTypeDescriptor (this);
-
-                               return descriptor;
-                       }
-
-                       set { throw new ArgumentException ("Not modifiable"); }
-               }
-
-               bool IBindingList.AllowEdit {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IBindingList.AllowNew {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IBindingList.AllowRemove {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IBindingList.IsSorted {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               ListSortDirection IBindingList.SortDirection {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               PropertyDescriptor IBindingList.SortProperty {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IBindingList.SupportsChangeNotification {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IBindingList.SupportsSearching {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               bool IBindingList.SupportsSorting {
-                       [MonoTODO]
-                       get { throw new NotImplementedException (); }
-               }
-
-               #endregion // Properties
-
-               #region Methods
-               private void SetDataSet (DataSet ds)
-               {
-                       dataSet = ds;
-                       settings = new DataViewSettingCollection (this);
-                       xml = BuildSettingString ();
-               }
-
-               private void ParseSettingString (string source)
-               {
-                       XmlTextReader xtr = new XmlTextReader (source,
-                               XmlNodeType.Element, null);
-
-                       xtr.Read ();
-                       if (xtr.Name != "DataViewSettingCollectionString")
-                               // easy way to throw the expected exception ;-)
-                               xtr.ReadStartElement ("DataViewSettingCollectionString");
-                       if (xtr.IsEmptyElement)
-                               return; // MS does not change the value.
-
-                       ArrayList result = new ArrayList ();
-                       xtr.Read ();
-                       do {
-                               xtr.MoveToContent ();
-                               if (xtr.NodeType == XmlNodeType.EndElement)
-                                       break;
-                               if (xtr.NodeType == XmlNodeType.Element)
-                                       ReadTableSetting (xtr);
-                               else
-                                       xtr.Skip ();
-                       } while (!xtr.EOF);
-                       if (xtr.NodeType == XmlNodeType.EndElement)
-                               xtr.ReadEndElement ();
-               }
-
-               private void ReadTableSetting (XmlReader reader)
-               {
-                       // Namespace is ignored BTW.
-                       DataTable dt = DataSet.Tables [XmlConvert.DecodeName (
-                               reader.LocalName)];
-                       // The code below might result in NullReference error.
-                       DataViewSetting s = settings [dt];
-                       string sort = reader.GetAttribute ("Sort");
-                       if (sort != null)
-                               s.Sort = sort.Trim ();
-                       string ads = reader.GetAttribute ("ApplyDefaultSort");
-                       if (ads != null && ads.Trim () == "true")
-                               s.ApplyDefaultSort = true;
-                       string rowFilter = reader.GetAttribute ("RowFilter");
-                       if (rowFilter != null)
-                               s.RowFilter = rowFilter.Trim ();
-                       string rsf = reader.GetAttribute ("RowStateFilter");
-                       if (rsf != null)
-                               s.RowStateFilter = (DataViewRowState)
-                                       Enum.Parse (typeof (DataViewRowState), 
-                                       rsf.Trim ());
-                       reader.Skip ();
-               }
-
-               private string BuildSettingString ()
-               {
-                       if (dataSet == null)
-                               return String.Empty;
-
-                       StringWriter sw = new StringWriter ();
-                       sw.Write ('<');
-                       sw.Write ("DataViewSettingCollectionString>");
-                       foreach (DataViewSetting s in DataViewSettings) {
-                               sw.Write ('<');
-                               sw.Write (XmlConvert.EncodeName (
-                                               s.Table.TableName));
-                               sw.Write (" Sort=\"");
-                               sw.Write (Escape (s.Sort));
-                               sw.Write ('"');
-                               // LAMESPEC: MS.NET does not seem to handle this property as expected.
-                               if (s.ApplyDefaultSort)
-                                       sw.Write (" ApplyDefaultSort=\"true\"");
-                               sw.Write (" RowFilter=\"");
-                               sw.Write (Escape (s.RowFilter));
-                               sw.Write ("\" RowStateFilter=\"");
-                               sw.Write (s.RowStateFilter.ToString ());
-                               sw.Write ("\"/>");
-                       }
-                       sw.Write ("</DataViewSettingCollectionString>");
-                       return sw.ToString ();
-               }
-
-               private string Escape (string s)
-               {
-                       return s.Replace ("&", "&amp;")
-                               .Replace ("\"", "&quot;")
-                               .Replace ("\'", "&apos;")
-                               .Replace ("<", "&lt;")
-                               .Replace (">", "&gt;");
-               }
-
-               public DataView CreateDataView (DataTable table) 
-               {
-                       DataViewSetting s = settings [table];
-                       return new DataView (table, this, s.Sort, s.RowFilter, s.RowStateFilter);
-               }
-
-               [MonoTODO]
-               void IBindingList.AddIndex (PropertyDescriptor property)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               object IBindingList.AddNew ()
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               int IBindingList.Find (PropertyDescriptor property, object key)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IBindingList.RemoveIndex (PropertyDescriptor property)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IBindingList.RemoveSort ()
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void ICollection.CopyTo (Array array, int index)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               IEnumerator IEnumerable.GetEnumerator ()
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               int IList.Add (object value)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IList.Clear ()
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               bool IList.Contains (object value)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               int IList.IndexOf (object value)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IList.Insert (int index, object value)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IList.Remove (object value)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               [MonoTODO]
-               void IList.RemoveAt (int index)
-               {
-                       throw new NotImplementedException ();
-               }
-       
-               PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors)
-               {
-                       if (dataSet == null)
-                               throw new DataException ("dataset is null");
-
-                       if (listAccessors == null || listAccessors.Length == 0) {
-                               ICustomTypeDescriptor desc = new DataViewManagerListItemTypeDescriptor (this);
-                               return desc.GetProperties ();
-                       }
-                               
-                       throw new NotImplementedException ();
-               }
-                       
-               string ITypedList.GetListName (PropertyDescriptor[] listAccessors)
-               {                       
-                       if (dataSet != null) {                                                  
-                               if (listAccessors == null || listAccessors.Length == 0) {
-                                       return  dataSet.DataSetName;
-                               }                               
-                       }                       
-                       
-                       return string.Empty;
-               }
-       
-               protected virtual void OnListChanged (ListChangedEventArgs e) 
-               {
-                       if (ListChanged != null)
-                               ListChanged (this, e);
-               }
-
-               protected virtual void RelationCollectionChanged (object sender, CollectionChangeEventArgs e) 
-               {
-               }
-
-               protected virtual void TableCollectionChanged (object sender, CollectionChangeEventArgs e) 
-               {
-               }
-
-               #endregion // Methods
-
-               #region Events
-
-               public event ListChangedEventHandler ListChanged;
-
-               #endregion // Events
-       }
-}
+//\r
+// System.Data.DataViewManager\r
+//\r
+// Author:\r
+//   Rodrigo Moya (rodrigo@ximian.com)\r
+//   Tim Coleman (tim@timcoleman.com)\r
+//   Atsushi Enomoto (atsushi@ximian.com)\r
+//\r
+// (C) Ximian, Inc. 2002\r
+// Copyright (C) Tim Coleman, 2002\r
+// Copyright (C) 2005 Novell Inc,\r
+//\r
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
+using System;\r
+using System.Collections;\r
+using System.ComponentModel;\r
+using System.IO;\r
+using System.Xml;\r
+\r
+namespace System.Data\r
+{\r
+       /// <summary>\r
+       /// Contains a default DataViewSettingCollection for each DataTable in a DataSet.\r
+       /// </summary>\r
+       //[Designer]\r
+       [DesignerAttribute ("Microsoft.VSDesigner.Data.VS.DataViewManagerDesigner, "+ Consts.AssemblyMicrosoft_VSDesigner, "System.ComponentModel.Design.IDesigner")]\r
+       public class DataViewManager : MarshalByValueComponent, IBindingList, ICollection, IList, ITypedList, IEnumerable\r
+       {\r
+               #region Fields\r
+\r
+               DataSet dataSet;\r
+               DataViewManagerListItemTypeDescriptor descriptor;\r
+               DataViewSettingCollection settings;\r
+               string xml;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+\r
+               public DataViewManager ()\r
+                       : this (null)\r
+               {\r
+               }\r
+\r
+               public DataViewManager (DataSet ds)\r
+               {\r
+                       // Null argument is allowed here.\r
+                       SetDataSet (ds);\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Properties\r
+\r
+               [DataSysDescription ("Indicates the source of data for this DataViewManager.")]\r
+               [DefaultValue (null)]\r
+               public DataSet DataSet {\r
+                       get { return dataSet; }\r
+                       set {\r
+                               if (value == null)\r
+                                       throw new DataException ("Cannot set null DataSet.");\r
+                               SetDataSet (value);\r
+                       }\r
+               }\r
+\r
+               public string DataViewSettingCollectionString {\r
+                       get { return xml; }\r
+                       set {\r
+                               try {\r
+                                       ParseSettingString (value);\r
+                                       xml = BuildSettingString ();\r
+                               } catch (XmlException ex) {\r
+                                       throw new DataException ("Cannot set DataViewSettingCollectionString.", ex);\r
+                               }\r
+                       }\r
+               }\r
+\r
+               [DataSysDescription ("Indicates the sorting/filtering/state settings for any table in the corresponding DataSet.")]\r
+                [DesignerSerializationVisibility (DesignerSerializationVisibility.Content)]\r
+               public DataViewSettingCollection DataViewSettings {\r
+                       get { return settings; }\r
+               }\r
+\r
+               int ICollection.Count {\r
+                       get { return settings.Count; }\r
+               }\r
+\r
+               bool ICollection.IsSynchronized {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               object ICollection.SyncRoot {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IList.IsFixedSize {\r
+                       get { return true; }\r
+               }\r
+\r
+               bool IList.IsReadOnly {\r
+                       get { return true; }\r
+               }\r
+\r
+               object IList.this [int index] {\r
+                       get { \r
+                               if (descriptor == null)\r
+                                       descriptor = new DataViewManagerListItemTypeDescriptor (this);\r
+\r
+                               return descriptor;\r
+                       }\r
+\r
+                       set { throw new ArgumentException ("Not modifiable"); }\r
+               }\r
+\r
+               bool IBindingList.AllowEdit {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IBindingList.AllowNew {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IBindingList.AllowRemove {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IBindingList.IsSorted {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               ListSortDirection IBindingList.SortDirection {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               PropertyDescriptor IBindingList.SortProperty {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IBindingList.SupportsChangeNotification {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IBindingList.SupportsSearching {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               bool IBindingList.SupportsSorting {\r
+                       [MonoTODO]\r
+                       get { throw new NotImplementedException (); }\r
+               }\r
+\r
+               #endregion // Properties\r
+\r
+               #region Methods\r
+               private void SetDataSet (DataSet ds)\r
+               {\r
+                       dataSet = ds;\r
+                       settings = new DataViewSettingCollection (this);\r
+                       xml = BuildSettingString ();\r
+               }\r
+\r
+               private void ParseSettingString (string source)\r
+               {\r
+                       XmlTextReader xtr = new XmlTextReader (source,\r
+                               XmlNodeType.Element, null);\r
+\r
+                       xtr.Read ();\r
+                       if (xtr.Name != "DataViewSettingCollectionString")\r
+                               // easy way to throw the expected exception ;-)\r
+                       xtr.ReadStartElement ("DataViewSettingCollectionString");\r
+                       if (xtr.IsEmptyElement)\r
+                               return; // MS does not change the value.\r
+\r
+                       ArrayList result = new ArrayList ();\r
+                       xtr.Read ();\r
+                       do {\r
+                               xtr.MoveToContent ();\r
+                               if (xtr.NodeType == XmlNodeType.EndElement)\r
+                                       break;\r
+                               if (xtr.NodeType == XmlNodeType.Element)\r
+                                       ReadTableSetting (xtr);\r
+                               else\r
+                                       xtr.Skip ();\r
+                       } while (!xtr.EOF);\r
+                       if (xtr.NodeType == XmlNodeType.EndElement)\r
+                               xtr.ReadEndElement ();\r
+               }\r
+\r
+               private void ReadTableSetting (XmlReader reader)\r
+               {\r
+                       // Namespace is ignored BTW.\r
+                       DataTable dt = DataSet.Tables [XmlConvert.DecodeName (\r
+                               reader.LocalName)];\r
+                       // The code below might result in NullReference error.\r
+                       DataViewSetting s = settings [dt];\r
+                       string sort = reader.GetAttribute ("Sort");\r
+                       if (sort != null)\r
+                               s.Sort = sort.Trim ();\r
+                       string ads = reader.GetAttribute ("ApplyDefaultSort");\r
+                       if (ads != null && ads.Trim () == "true")\r
+                               s.ApplyDefaultSort = true;\r
+                       string rowFilter = reader.GetAttribute ("RowFilter");\r
+                       if (rowFilter != null)\r
+                               s.RowFilter = rowFilter.Trim ();\r
+                       string rsf = reader.GetAttribute ("RowStateFilter");\r
+                       if (rsf != null)\r
+                               s.RowStateFilter = (DataViewRowState)\r
+                                       Enum.Parse (typeof (DataViewRowState), \r
+                                       rsf.Trim ());\r
+                       reader.Skip ();\r
+               }\r
+\r
+               private string BuildSettingString ()\r
+               {\r
+                       if (dataSet == null)\r
+                               return String.Empty;\r
+\r
+                       StringWriter sw = new StringWriter ();\r
+                       sw.Write ('<');\r
+                       sw.Write ("DataViewSettingCollectionString>");\r
+                       foreach (DataViewSetting s in DataViewSettings) {\r
+                               sw.Write ('<');\r
+                               sw.Write (XmlConvert.EncodeName (\r
+                                               s.Table.TableName));\r
+                               sw.Write (" Sort=\"");\r
+                               sw.Write (Escape (s.Sort));\r
+                               sw.Write ('"');\r
+                               // LAMESPEC: MS.NET does not seem to handle this property as expected.\r
+                               if (s.ApplyDefaultSort)\r
+                                       sw.Write (" ApplyDefaultSort=\"true\"");\r
+                               sw.Write (" RowFilter=\"");\r
+                               sw.Write (Escape (s.RowFilter));\r
+                               sw.Write ("\" RowStateFilter=\"");\r
+                               sw.Write (s.RowStateFilter.ToString ());\r
+                               sw.Write ("\"/>");\r
+                       }\r
+                       sw.Write ("</DataViewSettingCollectionString>");\r
+                       return sw.ToString ();\r
+               }\r
+\r
+               private string Escape (string s)\r
+               {\r
+                       return s.Replace ("&", "&amp;")\r
+                               .Replace ("\"", "&quot;")\r
+                               .Replace ("\'", "&apos;")\r
+                               .Replace ("<", "&lt;")\r
+                               .Replace (">", "&gt;");\r
+               }\r
+\r
+               public DataView CreateDataView (DataTable table) \r
+               {\r
+                       DataViewSetting s = settings [table];\r
+                       return new DataView (table, this, s.Sort, s.RowFilter, s.RowStateFilter);\r
+               }\r
+\r
+               [MonoTODO]\r
+               void IBindingList.AddIndex (PropertyDescriptor property)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               object IBindingList.AddNew ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IBindingList.ApplySort (PropertyDescriptor property, ListSortDirection direction)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               int IBindingList.Find (PropertyDescriptor property, object key)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IBindingList.RemoveIndex (PropertyDescriptor property)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IBindingList.RemoveSort ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void ICollection.CopyTo (Array array, int index)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               IEnumerator IEnumerable.GetEnumerator ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               int IList.Add (object value)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IList.Clear ()\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               bool IList.Contains (object value)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               int IList.IndexOf (object value)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IList.Insert (int index, object value)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IList.Remove (object value)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               [MonoTODO]\r
+               void IList.RemoveAt (int index)\r
+               {\r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               PropertyDescriptorCollection ITypedList.GetItemProperties (PropertyDescriptor[] listAccessors)\r
+               {\r
+                       if (dataSet == null)\r
+                               throw new DataException ("dataset is null");\r
+\r
+                       if (listAccessors == null || listAccessors.Length == 0) {\r
+                               ICustomTypeDescriptor desc = new DataViewManagerListItemTypeDescriptor (this);\r
+                               return desc.GetProperties ();\r
+                       }\r
+                               \r
+                       throw new NotImplementedException ();\r
+               }\r
+       \r
+               string ITypedList.GetListName (PropertyDescriptor[] listAccessors)\r
+               {\r
+                       if (dataSet != null) {                                                  \r
+                               if (listAccessors == null || listAccessors.Length == 0) {\r
+                                       return  dataSet.DataSetName;\r
+                               }                               \r
+                       }                       \r
+                       \r
+                       return string.Empty;\r
+               }\r
+       \r
+               protected virtual void OnListChanged (ListChangedEventArgs e) \r
+               {\r
+                       if (ListChanged != null)\r
+                               ListChanged (this, e);\r
+               }\r
+\r
+               protected virtual void RelationCollectionChanged (object sender, CollectionChangeEventArgs e) \r
+               {\r
+                       ListChangedEventArgs args;\r
+\r
+                       if (e.Action == CollectionChangeAction.Remove) {\r
+                               args = null;\r
+                       }\r
+                       else if (e.Action == CollectionChangeAction.Refresh) {\r
+                               args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorChanged, null);\r
+                       }\r
+                       else if (e.Action == CollectionChangeAction.Add) {\r
+                               args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorAdded, new DataRelationPropertyDescriptor(((DataRelation) e.Element)));\r
+                       }\r
+                       else {\r
+                               args = new ListChangedEventArgs(ListChangedType.PropertyDescriptorDeleted, new DataRelationPropertyDescriptor(((DataRelation) e.Element)));\r
+                       }\r
+\r
+                       this.OnListChanged(args);\r
+               }\r
+\r
+               protected virtual void TableCollectionChanged (object sender, CollectionChangeEventArgs e) \r
+               {\r
+               }\r
+\r
+               #endregion // Methods\r
+\r
+               #region Events\r
+\r
+               public event ListChangedEventHandler ListChanged;\r
+\r
+               #endregion // Events\r
+       }\r
+}\r
index dd33fc053e7fe12f60257a04e52e9395f84816a1..a17fd34bc2500c9fb2ea711f580c3bfd6174d90f 100644 (file)
@@ -48,8 +48,8 @@ namespace System.Data
                Added = 4,
                Deleted = 8,
                ModifiedCurrent = 16,
-               CurrentRows = 22,
+               CurrentRows = Unchanged | Added | ModifiedCurrent,
                ModifiedOriginal = 32,
-               OriginalRows = 42
+               OriginalRows = Unchanged | Deleted | ModifiedOriginal
        }
 }
diff --git a/mcs/class/System.Data/System.Data/ExpressionElement.cs b/mcs/class/System.Data/System.Data/ExpressionElement.cs
new file mode 100644 (file)
index 0000000..3b79735
--- /dev/null
@@ -0,0 +1,3404 @@
+//\r
+// System.Data.ExpressionElement \r
+//\r
+// Author:\r
+//   Ville Palo <vi64pa@kolumbus.fi>\r
+//\r
+// Copyright (C) Ville Palo, 2003\r
+//\r
+// TODO: - Some functionelements and aggregates.\r
+//       - New parsing style.\r
+//       - Exceptions\r
+//\r
+\r
+using System;\r
+using System.Data;\r
+using System.Reflection;\r
+\r
+using System.Collections;\r
+using System.Text;\r
+\r
+namespace System.Data\r
+{\r
+#if false\r
+       /// <summary>\r
+       /// The main element which includes whole expression\r
+       /// </summary>\r
+       internal class ExpressionMainElement : ExpressionElement\r
+       {\r
+               \r
+               \r
+\r
+               public ExpressionMainElement (string s)\r
+               {\r
+                       s = ExpressionElement.ValidateExpression (s);\r
+                       ParseExpression (s);\r
+               }\r
+               \r
+               public override bool Test (DataRow Row) \r
+               {\r
+\r
+                       foreach (ExpressionElement El in Elements) \r
+                       {\r
+                               if (!El.Test (Row))\r
+                                       return false;\r
+                       }\r
+                       \r
+                       return true;\r
+               }\r
+\r
+               \r
+       }\r
+\r
+       //\r
+       // O_P_E_R_A_T_O_R_S\r
+       //\r
+\r
+       /// <summary>\r
+       ///  Class for =\r
+       /// </summary>\r
+       internal class ExpressionEquals : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionEquals (string exp1, string exp2) \r
+               {       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+                       \r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+                       return ExpressionElement.Compare (E1, E2, Row) == 0;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for <\r
+       /// </summary>\r
+       internal class ExpressionLessThan : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionLessThan (string exp1, string exp2) \r
+               {       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+                                                               \r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+                                          \r
+                       return ExpressionElement.Compare (E1, E2, Row) < 0;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for <=\r
+       /// </summary>\r
+       internal class ExpressionLessThanOrEqual : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionLessThanOrEqual (string exp1, string exp2) \r
+               {       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+                       return ExpressionElement.Compare (E1, E2, Row) <= 0;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for >\r
+       /// </summary>\r
+       internal class ExpressionGreaterThan : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionGreaterThan (string exp1, string exp2) \r
+               {       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+                       \r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+                       return ExpressionElement.Compare (E1, E2, Row) > 0;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for >=\r
+       /// </summary>\r
+       internal class ExpressionGreaterThanOrEqual : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionGreaterThanOrEqual (string exp1, string exp2) \r
+               {       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+                       return ExpressionElement.Compare (E1, E2, Row) >= 0;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for <>\r
+       /// </summary>\r
+       internal class ExpressionUnequals : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionUnequals (string exp1, string exp2) \r
+               {       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+                       \r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+\r
+                       return ExpressionElement.Compare (E1, E2, Row) != 0;\r
+               }\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       ///  Class for LIKE-operator\r
+       /// </summary>\r
+       internal class ExpressionLike : ExpressionElement\r
+       {       \r
+\r
+               public ExpressionLike (string exp1, string exp2) \r
+               {\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+                       object value1 = E1.Result (Row);\r
+                       object value2 = E2.Result (Row);\r
+                       \r
+                       if (value1.GetType () != typeof (string) || value2.GetType () != typeof (string))\r
+                               throw new Exception (); // TODO: what exception\r
+                       \r
+                       string operand1 = value1.ToString ();\r
+                       string operand2 = value2.ToString ();\r
+\r
+                       // find out is there wildcards like * or %.\r
+                       while (operand2.EndsWith ("*") || operand2.EndsWith ("%"))                             \r
+                               operand2 = operand2.Remove (operand2.Length - 1, 1);\r
+                       while (operand2.StartsWith ("*") || operand2.StartsWith ("%"))\r
+                               operand2 = operand2.Remove (0, 1);\r
+\r
+                       int oldIndex = 0;\r
+                       int indexOf = -1;\r
+\r
+                       indexOf = operand2.IndexOf ("*");\r
+                       while (indexOf != -1) \r
+                       {\r
+\r
+                               oldIndex = indexOf + 1;\r
+                               if (operand2 [indexOf + 1] != ']' || operand2 [indexOf - 1] != '[')\r
+                                       throw new EvaluateException ("Error in Like operator: ther string pattern " + operand1 + " is invalid");\r
+                               else \r
+                               {\r
+                                       operand2 = operand2.Remove (indexOf + 1, 1);\r
+                                       operand2 = operand2.Remove (indexOf -1, 1);\r
+                                       oldIndex--;\r
+                               }\r
+                                       \r
+                               indexOf = operand2.IndexOf ("*", oldIndex);\r
+                       }\r
+\r
+                       oldIndex = 0;\r
+                       indexOf = operand2.IndexOf ("%");\r
+                       while (indexOf != -1) \r
+                       {\r
+\r
+                               oldIndex = indexOf + 1;\r
+                               \r
+                               if (operand2 [indexOf + 1] != ']' || operand2 [indexOf - 1] != '[')\r
+                                       throw new EvaluateException ("Error in Like operator: ther string pattern " + operand2 + " is invalid");\r
+                               else \r
+                               {\r
+                                       operand2 = operand2.Remove (indexOf + 1, 1);\r
+                                       operand2 = operand2.Remove (indexOf -1, 1);                                     \r
+                                       oldIndex--;\r
+                               }\r
+\r
+                               indexOf = operand2.IndexOf ("%", oldIndex);\r
+                       }\r
+\r
+                       int len2 = operand2.Length;\r
+                       int startIndex = 0;\r
+                       while ((startIndex + len2) <= operand1.Length) \r
+                       {\r
+                               if (String.Compare (operand1.Substring (startIndex, len2), operand2, !Row.Table.CaseSensitive) == 0)\r
+                                       return true;\r
+                               startIndex++;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       ///  Class for OR\r
+       /// </summary>\r
+       internal class ExpressionOr : ExpressionElement\r
+       {                               \r
+               public ExpressionOr (string exp1, string exp2)\r
+               {\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {                       \r
+                       foreach (ExpressionElement El in Elements) \r
+                       {\r
+                               if (El.Test (Row))\r
+                                       return true;\r
+                       }\r
+                       \r
+                       return false;\r
+               }                               \r
+       }\r
+               \r
+       /// <summary>\r
+       ///  Class for AND\r
+       /// </summary>\r
+       internal class ExpressionAnd : ExpressionElement\r
+       {                               \r
+               public ExpressionAnd (string exp1, string exp2)\r
+               {\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+              \r
+               public override object Result (DataRow Row) \r
+               {\r
+                       \r
+                       return Test(Row);\r
+               }\r
+\r
+               public override bool Test (DataRow Row) \r
+               {\r
+                       foreach (ExpressionElement El in Elements) \r
+                       {\r
+                               if (!El.Test (Row))\r
+                                       return false;\r
+                       }\r
+                       \r
+                       return true;\r
+               }                               \r
+       }\r
+\r
+\r
+       //\r
+       // A_R_I_T_H_M_E_T_I_C  O_P_E_R_A_T_O_R_S\r
+       //\r
+\r
+       /// <summary>\r
+       ///  Class for +\r
+       /// </summary>\r
+       internal class ExpressionAddition : ExpressionElement\r
+       {\r
+               public ExpressionAddition (string exp1, string exp2)\r
+               {                       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+               \r
+               public override Type ResultType (DataRow Row)\r
+               {\r
+                       Type ResultType = typeof (string);\r
+                       ExpressionElement exp1Temp = ((ExpressionElement)Elements [0]);\r
+                       ExpressionElement exp2Temp = ((ExpressionElement)Elements [1]);\r
+\r
+                       if (exp1Temp.ResultType (Row) == typeof (string) || exp2Temp.ResultType (Row) == typeof (string))\r
+                               ResultType = typeof (string);\r
+\r
+                       else if (exp1Temp.ResultType (Row) == typeof (long) || exp2Temp.ResultType (Row) == typeof (long))\r
+                               ResultType = typeof (long);\r
+\r
+                       else if (exp1Temp.ResultType (Row) == typeof (int) || exp2Temp.ResultType (Row) == typeof (int))\r
+                               ResultType = typeof (int);\r
+\r
+                       return ResultType;\r
+               }\r
+\r
+               public override object Result (DataRow Row) \r
+               {\r
+                       return CalculateResult (Row);\r
+               }\r
+               \r
+               protected override object Calculate (object value1, object value2, Type TempType) \r
+               {\r
+                       object Result = null;                   \r
+\r
+                       if (TempType == typeof (string))\r
+                               Result = (string)value1 + (string)value2;\r
+                       else if (TempType == typeof (long))\r
+                               Result = (long)value1 + (long)value2;\r
+                       else if (TempType == typeof (int))\r
+                               Result = (int)value1 + (int)value2;\r
+                       else if (TempType == typeof (short))\r
+                               Result = (short)value1 + (short)value2;\r
+                       else if (TempType == typeof (ulong))\r
+                               Result = (ulong)value1 + (ulong)value2;\r
+                       else if (TempType == typeof (uint))\r
+                               Result = (uint)value1 + (uint)value2;\r
+                       else if (TempType == typeof (ushort))\r
+                               Result = (ushort)value1 + (ushort)value2;\r
+                       else if (TempType == typeof (byte))\r
+                               Result = (byte)value1 + (byte)value2;\r
+                       else if (TempType == typeof (sbyte))\r
+                               Result = (sbyte)value1 + (sbyte)value2;\r
+                               // FIXME:\r
+                               //else if (TempType == typeof (bool))\r
+                               //      Result = (bool)value1 + (bool)value2;\r
+                       else if (TempType == typeof (float))\r
+                               Result = (float)value1 + (float)value2;\r
+                       else if (TempType == typeof (double))\r
+                               Result = (double)value1 + (double)value2;\r
+                       else if (TempType == typeof (decimal))\r
+                               Result = (decimal)value1 + (decimal)value2;\r
+                       // FIXME:\r
+                       //else if (TempType == typeof (DateTime))\r
+                       //      Result = (DateTime)value1 + (DateTime)value2;\r
+                       \r
+                       return Result;\r
+               }\r
+\r
+\r
+               // This method is shouldnt never invoked\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for -\r
+       /// </summary>\r
+       internal class ExpressionSubtraction : ExpressionElement\r
+       {\r
+               public ExpressionSubtraction (string exp1, string exp2)\r
+               {                       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+               \r
+               public override object Result (DataRow Row) \r
+               {                       \r
+                       return CalculateResult (Row);\r
+               }\r
+               \r
+               // This method is shouldnt never invoked\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               protected override object Calculate (object value1, object value2, Type TempType) \r
+               {\r
+                       object Result = null;                   \r
+\r
+                       // FIXME:\r
+                       //if (TempType == typeof (string))\r
+                       //      Result = (string)value1 - (string)value2;\r
+                       if (TempType == typeof (long))\r
+                               Result = (long)value1 - (long)value2;\r
+                       else if (TempType == typeof (int))\r
+                               Result = (int)value1 - (int)value2;\r
+                       else if (TempType == typeof (short))\r
+                               Result = (short)value1 - (short)value2;\r
+                       else if (TempType == typeof (ulong))\r
+                               Result = (ulong)value1 + (ulong)value2;\r
+                       else if (TempType == typeof (uint))\r
+                               Result = (uint)value1 - (uint)value2;\r
+                       else if (TempType == typeof (ushort))\r
+                               Result = (ushort)value1 - (ushort)value2;\r
+                       else if (TempType == typeof (byte))\r
+                               Result = (byte)value1 - (byte)value2;\r
+                       else if (TempType == typeof (sbyte))\r
+                               Result = (sbyte)value1 - (sbyte)value2;\r
+                               // FIXME:\r
+                               //else if (TempType == typeof (bool))\r
+                               //      Result = (bool)value1 - (bool)value2;\r
+                       else if (TempType == typeof (float))\r
+                               Result = (float)value1 - (float)value2;\r
+                       else if (TempType == typeof (double))\r
+                               Result = (double)value1 - (double)value2;\r
+                       else if (TempType == typeof (decimal))\r
+                               Result = (decimal)value1 - (decimal)value2;\r
+                       // FIXME:\r
+                       //else if (TempType == typeof (DateTime))\r
+                       //      Result = (DateTime)value1 - (DateTime)value2;\r
+                       \r
+                       return Result;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for *\r
+       /// </summary>\r
+       internal class ExpressionMultiply : ExpressionElement\r
+       {\r
+               public ExpressionMultiply (string exp1, string exp2)\r
+               {                       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+               \r
+               public override Type ResultType (DataRow Row)\r
+               {\r
+                       Type ResultType = null;\r
+                       ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+                       ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+                       Type t1 = E1.ResultType (Row);\r
+                       Type t2 = E2.ResultType (Row);\r
+                               \r
+                       if (t1 == typeof (string) || t2 == typeof (string))\r
+                               throw new EvaluateException ("Cannon perform '*' operation on " + t1.ToString () + \r
+                                       " and " + t2.ToString ());\r
+\r
+                       else if (t1 == typeof (long) || t2 == typeof (long))\r
+                               ResultType = typeof (long);\r
+\r
+                       else if (t1 == typeof (int) || t2 == typeof (int))\r
+                               ResultType = typeof (int);\r
+\r
+                       return ResultType;\r
+               }\r
+\r
+               public override object Result (DataRow Row) \r
+               {\r
+                       return CalculateResult (Row);\r
+               }\r
+               \r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               protected override object Calculate (object value1, object value2, Type TempType) \r
+               {\r
+                       object Result = null;                   \r
+\r
+                       if (TempType == typeof (long))\r
+                               Result = (long)value1 * (long)value2;\r
+                       else if (TempType == typeof (int))\r
+                               Result = (int)value1 * (int)value2;\r
+                       else if (TempType == typeof (short))\r
+                               Result = (short)value1 * (short)value2;\r
+                       else if (TempType == typeof (ulong))\r
+                               Result = (ulong)value1 * (ulong)value2;\r
+                       else if (TempType == typeof (uint))\r
+                               Result = (uint)value1 * (uint)value2;\r
+                       else if (TempType == typeof (ushort))\r
+                               Result = (ushort)value1 * (ushort)value2;\r
+                       else if (TempType == typeof (byte))\r
+                               Result = (byte)value1 * (byte)value2;\r
+                       else if (TempType == typeof (sbyte))\r
+                               Result = (sbyte)value1 * (sbyte)value2;\r
+                               // FIXME:\r
+                               //else if (TempType == typeof (bool))\r
+                               //      Result = (bool)value1 * (bool)value2;\r
+                       else if (TempType == typeof (float))\r
+                               Result = (float)value1 * (float)value2;\r
+                       else if (TempType == typeof (double))\r
+                               Result = (double)value1 * (double)value2;\r
+                       else if (TempType == typeof (decimal))\r
+                               Result = (decimal)value1 * (decimal)value2;\r
+                       // FIXME:\r
+                       //else if (TempType == typeof (DateTime))\r
+                       //      Result = (DateTime)value1 * (DateTime)value2;\r
+                       \r
+                       return Result;\r
+               }\r
+\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for *\r
+       /// </summary>\r
+       internal class ExpressionDivide : ExpressionElement\r
+       {\r
+               public ExpressionDivide (string exp1, string exp2)\r
+               {                       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+               \r
+               public override object Result (DataRow Row) \r
+               {\r
+                       return CalculateResult (Row);\r
+               }\r
+               \r
+               // This method is shouldnt never invoked\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               protected  override object Calculate (object value1, object value2, Type TempType) \r
+               {\r
+                       object Result = null;                   \r
+\r
+                       if (TempType == typeof (long))\r
+                               Result = (long)value1 / (long)value2;\r
+                               // FIXME: \r
+                               //else if (TempType == typeof (int))\r
+                               //      Result = (string)value1 / (string)value2;\r
+                       else if (TempType == typeof (int))\r
+                               Result = (int)value1 / (int)value2;\r
+                       else if (TempType == typeof (short))\r
+                               Result = (short)value1 / (short)value2;\r
+                       else if (TempType == typeof (ulong))\r
+                               Result = (ulong)value1 / (ulong)value2;\r
+                       else if (TempType == typeof (uint))\r
+                               Result = (uint)value1 / (uint)value2;\r
+                       else if (TempType == typeof (ushort))\r
+                               Result = (ushort)value1 / (ushort)value2;\r
+                       else if (TempType == typeof (byte))\r
+                               Result = (byte)value1 / (byte)value2;\r
+                       else if (TempType == typeof (sbyte))\r
+                               Result = (sbyte)value1 / (sbyte)value2;\r
+                               // FIXME:\r
+                               //else if (TempType == typeof (bool))\r
+                               //      Result = (bool)value1 // (bool)value2;\r
+                       else if (TempType == typeof (float))\r
+                               Result = (float)value1 / (float)value2;\r
+                       else if (TempType == typeof (double))\r
+                               Result = (double)value1 / (double)value2;\r
+                       else if (TempType == typeof (decimal))\r
+                               Result = (decimal)value1 / (decimal)value2;\r
+                       // FIXME:\r
+                       //else if (TempType == typeof (DateTime))\r
+                       //      Result = (DateTime)value1 / (DateTime)value2;\r
+                       \r
+                       return Result;\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for *\r
+       /// </summary>\r
+       internal class ExpressionModulus : ExpressionElement\r
+       {\r
+               public ExpressionModulus (string exp1, string exp2)\r
+               {                       \r
+                       this.exp1 = exp1;\r
+                       this.exp2 = exp2;\r
+                       ParseExpression (exp1);\r
+                       ParseExpression (exp2);\r
+               }\r
+               \r
+               public override object Result (DataRow Row) \r
+               {\r
+                       return CalculateResult (Row);\r
+               }\r
+               \r
+               // This method is shouldnt never invoked\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               protected  override object Calculate (object value1, object value2, Type TempType) \r
+               {\r
+                       object Result = null;                   \r
+\r
+                       if (TempType == typeof (long))\r
+                               Result = (long)value1 % (long)value2;\r
+                               // FIXME: \r
+                               //else if (TempType == typeof (int))\r
+                               //      Result = (string)value1 % (string)value2;\r
+                       else if (TempType == typeof (int))\r
+                               Result = (int)value1 % (int)value2;\r
+                       else if (TempType == typeof (short))\r
+                               Result = (short)value1 % (short)value2;\r
+                       else if (TempType == typeof (ulong))\r
+                               Result = (ulong)value1 % (ulong)value2;\r
+                       else if (TempType == typeof (uint))\r
+                               Result = (uint)value1 % (uint)value2;\r
+                       else if (TempType == typeof (ushort))\r
+                               Result = (ushort)value1 % (ushort)value2;\r
+                       else if (TempType == typeof (byte))\r
+                               Result = (byte)value1 % (byte)value2;\r
+                       else if (TempType == typeof (sbyte))\r
+                               Result = (sbyte)value1 % (sbyte)value2;\r
+                               // FIXME:\r
+                               //else if (TempType == typeof (bool))\r
+                               //      Result = (bool)value1 // (bool)value2;\r
+                       else if (TempType == typeof (float))\r
+                               Result = (float)value1 % (float)value2;\r
+                       else if (TempType == typeof (double))\r
+                               Result = (double)value1 % (double)value2;\r
+                       else if (TempType == typeof (decimal))\r
+                               Result = (decimal)value1 % (decimal)value2;\r
+                       // FIXME:\r
+                       //else if (TempType == typeof (DateTime))\r
+                       //      Result = (DateTime)value1 / (DateTime)value2;\r
+                       \r
+                       return Result;\r
+               }\r
+       }\r
+\r
+       //\r
+       // _____A_G_G_R_E_G_A_T_E_S_____\r
+       //\r
+\r
+       internal class ExpressionAggregate : ExpressionElement\r
+       {\r
+               \r
+               public ExpressionAggregate()\r
+               {\r
+               }\r
+\r
+               public ExpressionAggregate(string s)\r
+               {\r
+                       s = ExpressionElement.ValidateExpression (s);\r
+                       ParseExpression (s);\r
+               }\r
+\r
+               \r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               public override object Result(DataRow Row)\r
+               {\r
+                       DataRow[] rows = new DataRow[Row.Table.Rows.Count];\r
+                       Row.Table.Rows.CopyTo(rows, 0);\r
+                       return ((ExpressionAggregate)Elements[0]).Result(rows);\r
+               }\r
+\r
+               public virtual object Result(DataRow[] rows)\r
+               {\r
+                       return ((ExpressionAggregate)Elements[0]).Result(rows);\r
+               }\r
+\r
+\r
+               protected virtual void ParseParameters (string s)\r
+               {\r
+                       string stemp = s.ToLower ();\r
+                       bool inString = false;\r
+                       string p1 = null;\r
+\r
+                       // find (\r
+                       while (!s.StartsWith ("("))\r
+                               s = s.Remove (0, 1);\r
+                       \r
+                       // remove (\r
+                       s = s.Remove (0, 1);\r
+\r
+                       int parentheses = 0;\r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               if (s [i] == '\'')\r
+                                       inString = !inString;\r
+                               else if (s [i] == '(')\r
+                                       parentheses++;\r
+                               else if (s [i] == ')')\r
+                                       parentheses--;\r
+\r
+                               if ((s [i] == ',' ||  s [i] == ')') && !inString && parentheses == -1) \r
+                               { // Parameter changed\r
+\r
+                                       if (p1 == null) \r
+                                       {\r
+                                               p1 = s.Substring (0, i);\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       if (p1 == null)\r
+                               throw new Exception ();\r
+\r
+                       ParseExpression (p1);           \r
+               }\r
+               \r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for Sum (column_Name)\r
+       /// </summary\r
+       internal class ExpressionSum : ExpressionAggregate\r
+       {\r
+               public ExpressionSum (string exp1)\r
+               {\r
+                       ParseParameters (exp1);\r
+               }\r
+\r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       object value1 = E1.Result (rows[0]);\r
+                       Type t1 = value1.GetType ();\r
+                       object result = 0;\r
+                       \r
+                       // This could be optimized. If E1 is single element (Not child or parent) the\r
+                       // result of Sum() aggregate is allways same\r
+\r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+                               \r
+                               // This should be optimized somehow\r
+                               for (int i = 0; i < rows.Length; i++) \r
+                               {\r
+\r
+                                       // TODO: other types and exceptions\r
+                                       object v = E1.Result (rows[i]);\r
+                                       t1 = v.GetType ();\r
+\r
+                                       if (v == null || v == DBNull.Value)\r
+                                               continue;\r
+\r
+                                       if (t1 == typeof (long)) \r
+                                       {\r
+                                               result = (long)result + (long)v;\r
+                                       }\r
+                                       else if (t1 == typeof (int)) \r
+                                       {\r
+                                               result = (int)result + (int)v;\r
+                                       }\r
+                                       else if (t1 == typeof (short)) \r
+                                       {\r
+                                               result = (short)result + (short)v;\r
+                                       }\r
+                                       else if (t1 == typeof (double)) \r
+                                       {\r
+                                               result = (double)result + (double)v;\r
+                                       }\r
+                                       else if (t1 == typeof (float)) \r
+                                       {\r
+                                               result = (float)result + (float)v;\r
+                                       }\r
+                                       else\r
+                                               throw new NotImplementedException ();\r
+                               }\r
+                       }\r
+                       \r
+                       return result;\r
+               }\r
+\r
+               \r
+               //\r
+               // Copy: This method is copy-paste in every Aggregate class.\r
+               //\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for Avg (column_Name)\r
+       /// </summary\r
+       internal class ExpressionAvg : ExpressionAggregate\r
+       {\r
+               public ExpressionAvg (string exp1)\r
+               {\r
+                       ParseParameters (exp1);\r
+               }\r
+\r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       object value1 = E1.Result (rows[0]);\r
+                       Type original = value1.GetType ();\r
+                       object result = null;\r
+                       \r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+                               \r
+                               Type t1 = null;\r
+                               // This should be optimized somehow\r
+                               for (int i = 0; i < rows.Length; i++) \r
+                               {\r
+                                      \r
+                                       // TODO: other types and exceptions\r
+                                       object v = E1.Result (rows[i]);\r
+\r
+                                       if (v == null || v == DBNull.Value)\r
+                                               continue;\r
+\r
+                                       t1 = v.GetType ();\r
+\r
+                                       if (result == null)\r
+                                               result = 0;\r
+                                       \r
+                                       if (t1 == typeof (long)) \r
+                                       {\r
+                                               result = (long)result + (long)v;\r
+                                       }\r
+                                       else if (t1 == typeof (int)) \r
+                                       {\r
+                                               result = (int)result + (int)v;\r
+                                       }\r
+                                       else if (t1 == typeof (short)) \r
+                                       {\r
+                                               result = (short)result + (short)v;\r
+                                       }\r
+                                       else if (t1 == typeof (double)) \r
+                                       {\r
+                                               result = (double)result + (double)v;\r
+                                       }\r
+                                       else if (t1 == typeof (float)) \r
+                                       {\r
+                                               result = (float)result + (float)v;\r
+                                       }\r
+                                       else\r
+                                               throw new NotImplementedException ();\r
+                               }\r
+\r
+                               // TODO: types\r
+\r
+                               if (t1 == typeof (long))\r
+                                       result = (long)result / rows.Length;\r
+                               else if (t1 == typeof (int))\r
+                                       result = (int)result / rows.Length;\r
+                               else if (t1 == typeof (short))\r
+                                       result = (short)result / rows.Length;\r
+                               else if (t1 == typeof (double))\r
+                                       result = (double)result / rows.Length;\r
+                       }\r
+                       \r
+                       return result;\r
+               }\r
+\r
+               /// <summary>\r
+               ///  This is used from ExpressionStdDev for evaluating avg.\r
+               /// </summary>\r
+               public ExpressionAvg (ExpressionElement E)\r
+               {\r
+                       Elements.Add (E);\r
+               }\r
+       \r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for Min (column_Name)\r
+       /// </summary\r
+       internal class ExpressionMin : ExpressionAggregate\r
+       {\r
+               public ExpressionMin (string exp1)\r
+               {\r
+                       ParseParameters (exp1);\r
+               }\r
+\r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       object value1 = E1.Result (rows[0]);\r
+                       Type original = value1.GetType ();\r
+                       object result = null;\r
+                       \r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+                               \r
+                               Type t1 = null;\r
+                               // This should be optimized somehow\r
+                               for (int i = 0; i < rows.Length; i++)\r
+                               {\r
+                                      \r
+                                       // TODO: other types and exceptions\r
+                                       object v = E1.Result (rows[i]);\r
+\r
+                                       if (v == null || v == DBNull.Value)\r
+                                               continue;\r
+\r
+                                       t1 = v.GetType ();\r
+\r
+                                       if (result == null)\r
+                                               result = 0;\r
+\r
+                                       object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
+                                               BindingFlags.InvokeMethod, null, \r
+                                               v, \r
+                                               new object [] {result});\r
+\r
+                                       if ((int)CompResult < 0)\r
+                                               result = v;\r
+\r
+                               }\r
+                       }\r
+                       \r
+                       return result;\r
+               }\r
+\r
+               \r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for Max (column_Name)\r
+       /// </summary\r
+       internal class ExpressionMax : ExpressionAggregate\r
+       {\r
+               public ExpressionMax (string exp1)\r
+               {\r
+                       ParseParameters (exp1);\r
+               }\r
+\r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       object value1 = E1.Result (rows[0]);\r
+                       Type original = value1.GetType ();\r
+                       object result = null;\r
+                       \r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+                               \r
+                               Type t1 = null;\r
+                               // This should be optimized somehow\r
+                               for (int i = 0; i < rows.Length; i++) \r
+                               {\r
+                                      \r
+                                       // TODO: other types and exceptions\r
+                                       object v = E1.Result (rows[i]);\r
+\r
+                                       if (v == null || v == DBNull.Value)\r
+                                               continue;\r
+\r
+                                       t1 = v.GetType ();\r
+\r
+                                       if (result == null)\r
+                                               result = 0;\r
+\r
+                                       object CompResult = t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
+                                               BindingFlags.InvokeMethod, null, \r
+                                               v, \r
+                                               new object [] {result});\r
+\r
+                                       if ((int)CompResult > 0)\r
+                                               result = v;\r
+\r
+                               }\r
+                       }\r
+                       \r
+                       return result;\r
+               }\r
+\r
+               \r
+       }\r
+\r
+\r
+       /// <summary>\r
+       ///  Class for count (column)\r
+       /// </summary>\r
+       internal class ExpressionCount : ExpressionAggregate\r
+       {\r
+               public ExpressionCount (string exp1)\r
+               {\r
+                       ParseParameters (exp1);\r
+               }\r
+               \r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       int count = 0;\r
+\r
+                       if (E1 is ExpressionSingleElement) \r
+                               count = rows.Length;\r
+                       \r
+                       return count;\r
+               }\r
+\r
+               public override object Result (DataRow Row) \r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       int count = 0;\r
+\r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+                               \r
+                               count = Row.Table.Rows.Count;\r
+                       }\r
+                       \r
+                       return count;\r
+               }\r
+       }\r
+\r
+\r
+       /// <summary>\r
+       ///  Class for StdDev (column)\r
+       /// </summary>\r
+       internal class ExpressionStdev : ExpressionAggregate\r
+       {\r
+               public ExpressionStdev (string exp1)\r
+               {               \r
+                       ParseParameters (exp1);\r
+               }\r
+\r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionAvg Avg = new ExpressionAvg (E1);\r
+\r
+                       object tempAvg = Avg.Result (rows[0]);\r
+                       double avg = 0;\r
+                       double sum = 0;\r
+                       double result = 0;\r
+\r
+                       if (tempAvg.GetType () == typeof (int))\r
+                               avg = (double)(int)tempAvg;\r
+                       \r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+\r
+                               for (int i = 0; i <rows.Length; i++)\r
+                               {\r
+                                       // (value - avg)²\r
+                                       object v = E1.Result (rows[i]);\r
+\r
+                                       if (v == null || v == DBNull.Value)\r
+                                               continue;\r
+\r
+                                       if (v.GetType () == typeof (long))\r
+                                               sum = avg - (long)v;\r
+                                       else if (v.GetType () == typeof (int))\r
+                                               sum = avg - (int)v;\r
+                                       else if (v.GetType () == typeof (short))\r
+                                               sum = avg - (short)v;\r
+                                       else\r
+                                               throw new NotImplementedException ();\r
+\r
+                                       result += Math.Pow (sum, 2);\r
+                               }\r
+                               \r
+                               result = result / (rows.Length - 1);\r
+                               result = Math.Sqrt (result);\r
+                       }\r
+\r
+                       return result;\r
+               }\r
+               \r
+               \r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for Var (column)\r
+       /// </summary>\r
+       internal class ExpressionVar : ExpressionAggregate\r
+       {\r
+               public ExpressionVar (string exp1)\r
+               {\r
+                       ParseParameters (exp1);\r
+               }\r
+\r
+               public override object Result(DataRow[] rows)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionAvg Avg = new ExpressionAvg (E1);\r
+\r
+                       object tempAvg = Avg.Result (rows[0]);\r
+                       double avg = 0;\r
+                       double sum = 0;\r
+                       double result = 0;\r
+\r
+                       if (tempAvg.GetType () == typeof (int))\r
+                               avg = (double)(int)tempAvg;\r
+                       \r
+                       if (E1 is ExpressionSingleElement) \r
+                       {\r
+\r
+                               for (int i = 0; i < rows.Length; i++)\r
+                               {\r
+\r
+                                      \r
+                                       // (value - avg)²\r
+                                       object v = E1.Result (rows[i]);\r
+\r
+                                       if (v == null || v == DBNull.Value)\r
+                                               continue;\r
+\r
+                                       if (v.GetType () == typeof (long))\r
+                                               sum = avg - (long)v;\r
+                                       else if (v.GetType () == typeof (int))\r
+                                               sum = avg - (int)v;\r
+                                       else if (v.GetType () == typeof (short))\r
+                                               sum = avg - (short)v;\r
+                                       else\r
+                                               throw new NotImplementedException ();\r
+\r
+                                       result += Math.Pow (sum, 2);\r
+                               }\r
+                               \r
+                               result = result / (rows.Length - 1);\r
+                       }\r
+\r
+                       return result;\r
+               }\r
+               \r
+               \r
+       }\r
+\r
+       // \r
+       // _____F_U_ N_C_T_I_O_N_S_______\r
+       //\r
+\r
+       /// <summary>\r
+       ///  Class for len (string) function\r
+       /// </summary>\r
+       internal class ExpressionLen : ExpressionElement\r
+       {\r
+               public ExpressionLen (string exp1)\r
+               {                       \r
+                       _ResultType = typeof (int);\r
+                       ParseParameters (exp1);\r
+               }\r
+               \r
+               public override object Result (DataRow Row) \r
+               {\r
+                       ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+                       object value1 = E1.Result (Row);\r
+                       \r
+                       return value1.ToString ().Length;\r
+               }\r
+               \r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               public void ParseParameters (string s)\r
+               {\r
+                       string stemp = s.ToLower ();\r
+                       bool inString = false;\r
+                       string p1 = null;\r
+\r
+                       // find (\r
+                       while (!s.StartsWith ("("))\r
+                               s = s.Remove (0, 1);\r
+\r
+                       // remove (\r
+                       s = s.Remove (0, 1);\r
+                       int parentheses = 0;\r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               if (s [i] == '\'')\r
+                                       inString = !inString;\r
+                               else if (s [i] == '(')\r
+                                       parentheses++;\r
+                               else if (s [i] == ')')\r
+                                       parentheses--;\r
+\r
+                               if ((s [i] == ',' ||  s [i] == ')') && !inString && parentheses == -1) \r
+                               { // Parameter changed\r
+\r
+                                       if (p1 == null) \r
+                                       {\r
+                                               p1 = s.Substring (0, i);\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+\r
+                       if (p1 == null)\r
+                               throw new Exception ();\r
+\r
+                       ParseExpression (p1);           \r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for iif (exp1, truepart, falsepart) function\r
+       /// </summary>\r
+       internal class ExpressionIif : ExpressionElement\r
+       {\r
+               public ExpressionIif (string exp)\r
+               {       \r
+                       ParseParameters (exp);\r
+               }\r
+\r
+               public override object Result (DataRow Row) \r
+               {\r
+                       ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+                       ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+                       ExpressionElement E3 = ((ExpressionElement)Elements [2]);\r
+\r
+                       if (E1.Test (Row)) // expression\r
+                               return E2.Result (Row); // truepart\r
+                       else\r
+                               return E3.Result (Row); // false part                   \r
+               }\r
+               \r
+               // This method is shouldnt never invoked\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               public override Type ResultType (DataRow Row)\r
+               {                                               \r
+                       ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+                       ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+                       ExpressionElement E3 = ((ExpressionElement)Elements [2]);\r
+                       \r
+                       if (E1.Test (Row)) // expression\r
+                               return E2.Result (Row).GetType (); // truepart\r
+                       else\r
+                               return E3.Result (Row).GetType (); // false part                        \r
+               }\r
+\r
+               /// <summary>\r
+               ///  Parses expressions in parameters (exp, truepart, falsepart)\r
+               /// </summary>\r
+               private void ParseParameters (string s)\r
+               {\r
+                       bool inString = false;\r
+                       string stemp = s.ToLower ();\r
+                       string p1 = null;\r
+                       string p2 = null;\r
+                       string p3 = null;\r
+                       s = s.Substring (stemp.IndexOf ("iif") + 3);\r
+\r
+                       // find (\r
+                       while (!s.StartsWith ("("))\r
+                               s = s.Remove (0, 1);\r
+\r
+                       // remove (\r
+                       s = s.Remove (0, 1);\r
+                       int parentheses = 0;\r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               if (s [i] == '\'')\r
+                                       inString = !inString;\r
+                               else if (s [i] == '(')\r
+                                       parentheses++;\r
+                               else if (s [i] == ')')\r
+                                       parentheses--;\r
+\r
+                               if ((s [i] == ',' && !inString && parentheses == 0) || \r
+                                       (s [i] == ')' && i == (s.Length -1))) \r
+                               { // Parameter changed\r
+\r
+                                       if (p1 == null) \r
+                                       {\r
+                                               p1 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else if (p2 == null) \r
+                                       {\r
+                                               p2 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else if (p3 == null) \r
+                                       {\r
+                                               p3 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else\r
+                                               throw new Exception (); // FIXME: What exception\r
+                               }\r
+                       }\r
+\r
+                       if (p1 == null || p2 == null || p3 == null)\r
+                               throw new Exception ();\r
+\r
+                       ParseExpression (p1);\r
+                       ParseExpression (p2);\r
+                       ParseExpression (p3);\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for isnull (expression, returnvalue) function\r
+       /// </summary>\r
+       internal class ExpressionIsNull : ExpressionElement\r
+       {\r
+               public ExpressionIsNull (string exp)\r
+               {                       \r
+                       ParseParameters (exp);\r
+               }\r
+               \r
+               public override object Result (DataRow Row) \r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+                       \r
+                       object R1 = E1.Result (Row);\r
+                       object value1 = null;\r
+                       if (R1 == null || R1 == DBNull.Value)\r
+                               return E2.Result (Row);\r
+                       else\r
+                               return R1;\r
+               }\r
+\r
+               public override Type ResultType (DataRow Row)\r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+                       \r
+                       object R1 = E1.Result (Row);\r
+                       object value1 = null;\r
+                       if (R1 == null || R1 == DBNull.Value)\r
+                               return E2.Result (Row).GetType ();\r
+                       else\r
+                               return R1.GetType ();\r
+               }\r
+               \r
+               /// <summary>\r
+               ///  IsNull function does not return boolean value, so throw exception\r
+               /// </summary>\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Parses parameters of function and invoke ParseExpression methods\r
+               /// </summary>\r
+               private void ParseParameters (string s)\r
+               {\r
+                       bool inString = false;\r
+                       string stemp = s.ToLower ();\r
+                       string p1 = null;\r
+                       string p2 = null;\r
+\r
+                       s = s.Substring (stemp.IndexOf ("isnull") + 6);\r
+\r
+                       // find (\r
+                       while (!s.StartsWith ("("))\r
+                               s = s.Remove (0, 1);\r
+\r
+                       // remove (\r
+                       s = s.Remove (0, 1);\r
+                       int parentheses = 0;\r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               if (s [i] == '\'')\r
+                                       inString = !inString;\r
+                               else if (s [i] == '(')\r
+                                       parentheses++;\r
+                               else if (s [i] == ')')\r
+                                       parentheses--;\r
+\r
+                               if ((s [i] == ',' && !inString && parentheses == 0) || \r
+                                       (s [i] == ')' && i == (s.Length -1))) \r
+                               { // Parameter changed\r
+\r
+                                       if (p1 == null) \r
+                                       {\r
+                                               p1 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else if (p2 == null) \r
+                                       {\r
+                                               p2 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else\r
+                                               throw new Exception (); // FIXME: What exception\r
+                               }\r
+                       }\r
+\r
+                       if (p1 == null || p2 == null)\r
+                               throw new Exception ();\r
+\r
+                       ParseExpression (p1);\r
+                       ParseExpression (p2);\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for Substring (expression, start, length) function\r
+       /// </summary>\r
+       internal class ExpressionSubstring : ExpressionElement\r
+       {\r
+               public ExpressionSubstring (string exp)\r
+               {                       \r
+                       ParseParameters (exp);\r
+                       _ResultType = typeof (string);\r
+               }\r
+               \r
+               public override object Result (DataRow Row) \r
+               {\r
+                       ExpressionElement E1 = (ExpressionElement)Elements [0];\r
+                       ExpressionElement E2 = (ExpressionElement)Elements [1];\r
+                       ExpressionElement E3 = (ExpressionElement)Elements [2];\r
+                       \r
+                       object value1 = E1.Result (Row);\r
+                       object value2 = E2.Result (Row);\r
+                       object value3 = E3.Result (Row);\r
+                       Type t1 = value1.GetType ();\r
+                       Type t2 = value2.GetType ();\r
+                       Type t3 = value3.GetType ();\r
+\r
+                       if (value1 == null || value2 == null || value3 == null \r
+                               || value1 == DBNull.Value || value2 == DBNull.Value || value3 == DBNull.Value)\r
+                               return string.Empty;\r
+\r
+                       if (t1 != typeof (string))\r
+                               throw new Exception (); // FIXME: what exception\r
+                       else if (t2 != typeof (int))\r
+                               throw new EvaluateException ("Type mismatch is function argument: Substring (), argument 2, excepted System.Int32");\r
+                       else if (t3 != typeof (int))\r
+                               throw new EvaluateException ("Type mismatch is function argument: Substring (), argument 3, excepted System.Int32");\r
+\r
+                       string str = value1.ToString ();\r
+                       int start = (int)value2;\r
+                       int length = (int)value3;\r
+\r
+                       if (str.Length < start)\r
+                               str =  string.Empty;\r
+                       else \r
+                       {\r
+                               if ((start + length - 1) > str.Length)\r
+                                       str = str.Substring (start - 1);\r
+                               else\r
+                                       str = str.Substring (start - 1, length);\r
+                       }\r
+\r
+                       return str;\r
+               }\r
+\r
+               /// <summary>\r
+               ///  IsNull function does not return boolean value, so throw exception\r
+               /// </summary>\r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Parses parameters of function and invoke ParseExpression methods\r
+               /// </summary>\r
+               private void ParseParameters (string s)\r
+               {\r
+                       bool inString = false;\r
+                       string stemp = s.ToLower ();\r
+                       string p1 = null;\r
+                       string p2 = null;\r
+                       string p3 = null;\r
+\r
+                       s = s.Substring (stemp.IndexOf ("substring") + 9);\r
+\r
+                       // find (\r
+                       while (!s.StartsWith ("("))\r
+                               s = s.Remove (0, 1);\r
+\r
+                       // remove (\r
+                       s = s.Remove (0, 1);\r
+                       int parentheses = 0;\r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               if (s [i] == '\'')\r
+                                       inString = !inString;\r
+                               else if (s [i] == '(')\r
+                                       parentheses++;\r
+                               else if (s [i] == ')')\r
+                                       parentheses--;\r
+\r
+\r
+                               if ((s [i] == ',' && !inString && parentheses == 0) || \r
+                                       (s [i] == ')' && i == (s.Length -1))) \r
+                               { // Parameter changed\r
+\r
+                                       if (p1 == null) \r
+                                       {\r
+                                               p1 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else if (p2 == null) \r
+                                       {\r
+                                               p2 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else if (p3 == null) \r
+                                       {\r
+                                               p3 = s.Substring (0, i);\r
+                                               s = s.Substring (i + 1);\r
+                                               i = 0;\r
+                                       }\r
+\r
+                                       else\r
+                                               throw new Exception (); // FIXME: What exception\r
+                               }\r
+                       }\r
+\r
+                       if (p1 == null || p2 == null)\r
+                               throw new Exception ();\r
+\r
+                       ParseExpression (p1);\r
+                       ParseExpression (p2);\r
+                       ParseExpression (p3);                   \r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for In (exp, exp, exp, ...) function\r
+       /// </summary>\r
+       internal class ExpressionIn : ExpressionElement\r
+       {\r
+               public ExpressionIn (string exp1, string exp2)\r
+               {       \r
+                       ParseExpression(exp1);\r
+                       ParseParameters (exp2);\r
+               }\r
+\r
+               /// <summary>\r
+               ///  IsNull function does not return boolean value, so throw exception\r
+               /// </summary>\r
+               public override bool Test (DataRow Row) \r
+               {\r
+                       ExpressionElement E;\r
+                       ExpressionElement columnElement = (ExpressionElement)Elements [0];\r
+\r
+                       ExpressionElementComparer comparer = new ExpressionElementComparer(columnElement, Row);\r
+\r
+                       for (int i = 1; i < Elements.Count; i++)\r
+                       {\r
+                               E = (ExpressionElement)Elements [i];\r
+                               if(comparer.CompareTo(E) == 0)\r
+                                       return true;\r
+                       }\r
+                       return false;\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Parses parameters of function and invoke ParseExpression methods\r
+               /// </summary>\r
+               private void ParseParameters (string s)\r
+               {\r
+                       bool inString = false;\r
+                       ArrayList parameters = new ArrayList();\r
+                       \r
+                       // find (\r
+                       while (!s.StartsWith ("("))\r
+                               s = s.Remove (0, 1);\r
+\r
+                       // remove (\r
+                       s = s.Remove (0, 1);\r
+                       int parentheses = 0;\r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               if (s [i] == '\'')\r
+                                       inString = !inString;\r
+                               else if (s [i] == '(')\r
+                                       parentheses++;\r
+                               else if (s [i] == ')')\r
+                                       parentheses--;\r
+\r
+\r
+                               if ((s [i] == ',' && !inString && parentheses == 0) || \r
+                                       (s [i] == ')' && i == (s.Length -1))) \r
+                               {\r
+                                       parameters.Add(s.Substring (0, i));\r
+                                       s = s.Substring (i + 1);\r
+                                       i = 0;\r
+                               }\r
+                       }\r
+                       \r
+                       for (int i = 0; i < parameters.Count; i++)\r
+                               ParseExpression((string)parameters[i]);\r
+               }\r
+       }\r
+\r
+       /// <summary>\r
+       ///  Class for just one element for example string, int, ...\r
+       /// </summary>\r
+       internal class ExpressionSingleElement : ExpressionElement\r
+       {               \r
+               private object Element = null;\r
+               \r
+               public ExpressionSingleElement (string s)\r
+               {\r
+                       // TODO: Every type should be checked\r
+                       if (s.StartsWith ("'") && s.EndsWith ("'")) \r
+                       {\r
+                               Element = s.Substring (1, s.Length - 2);\r
+                               _ResultType = typeof (string);\r
+                       }\r
+                       else if (!Char.IsDigit (s [0]) && s [0] != '-' && s [0] != '+') \r
+                       {\r
+                               Element = s;\r
+                               _ResultType = typeof (DataColumn);\r
+                       }\r
+                       else if (s.StartsWith ("#") && s.EndsWith ("#")) \r
+                       {\r
+                               Element = DateTime.Parse (s.Substring (1, s.Length - 2));\r
+                               _ResultType = typeof (DateTime);\r
+                       }\r
+                       else \r
+                       {\r
+                               try \r
+                               {\r
+                                       Element = int.Parse (s);\r
+                                       _ResultType = typeof (int);\r
+                               } \r
+                               catch \r
+                               {\r
+                                       Element = Decimal.Parse (s);\r
+                                       _ResultType = typeof (Decimal);\r
+                               }\r
+                       }                               \r
+               }\r
+\r
+               public override object Result (DataRow Row)\r
+               {\r
+                       object Result = null;\r
+                       if (ResultType (Row) == typeof (DataColumn)) \r
+                       {\r
+                               \r
+                               if (!Row.Table.Columns.Contains (Element.ToString ()))\r
+                                       throw new EvaluateException ("Column name '" + Element.ToString () + "' not found.");\r
+                               else\r
+                               {\r
+                                       DataRowVersion rowVersion = DataRowVersion.Default;\r
+                                       // if this row is deleted we get the original version, or else we get an exception.\r
+                                       if (Row.RowState == DataRowState.Deleted)\r
+                                               rowVersion = DataRowVersion.Original;\r
+                                       Result = Row [Element.ToString (), rowVersion];\r
+                               }\r
+                       }\r
+                       else\r
+                               Result = Element;\r
+                               \r
+                       return Result;\r
+               }\r
+               \r
+               public override bool Test (DataRow Row)\r
+               {\r
+                       throw new EvaluateException ();\r
+               }               \r
+       }\r
+\r
+       /// <summary>\r
+       ///  Parent class of all the elements of expression\r
+       /// </summary>\r
+       internal abstract class ExpressionElement\r
+       {        \r
+               enum OP {OPERATOR, OPERAND};\r
+               enum OPERATOR_TYPE {SYMBOLIC, LITERAL, UNDEFINED};\r
+               enum OPERAND_TYPE {NUMERIC, STRING, UNDEFINED};\r
+\r
+               // \r
+               // TODO/FIXME: This class should be inherited more than once. I mean own subclass for operators, functions,...\r
+               //\r
+\r
+               protected string exp1;\r
+               protected string exp2;\r
+               protected  Type _ResultType;\r
+\r
+               protected ArrayList Elements = new ArrayList ();\r
+\r
+               enum AGGREGATE {SUM, AVG, MIN, MAX, COUNT, STDEV, VAR}\r
+               //protected ArrayList Singles = new ArrayList ();\r
+               \r
+               /// <summary>\r
+               /// Tells does the current expressions match to current DataRow\r
+               /// </summary>\r
+               abstract public bool Test (DataRow Row);\r
+\r
+               public virtual object Result (DataRow Row) {return null;}\r
+                \r
+               public virtual Type ResultType (DataRow Row)\r
+               {\r
+                       return _ResultType;\r
+               }\r
+\r
+               protected object CalculateResult (DataRow Row)\r
+               {\r
+                       ExpressionElement E1 = ((ExpressionElement)Elements [0]);\r
+                       ExpressionElement E2 = ((ExpressionElement)Elements [1]);\r
+                       object Result = null;\r
+                       object value1 = E1.Result (Row);\r
+                       object value2 = E2.Result (Row);\r
+                       Type t1 = value1.GetType ();\r
+                       Type t2 = value2.GetType ();\r
+                       \r
+                       // Check nulls\r
+                       if (value1 ==  DBNull.Value && value2 == DBNull.Value)\r
+                               return null;\r
+                       \r
+                       // TODO: More types\r
+                       \r
+                       if (t1 == typeof (string) || t2 == typeof (string)) \r
+                       {\r
+                               \r
+                               if (t1 != typeof (string))\r
+                                       value1 = Convert.ChangeType (value1, Type.GetTypeCode (t2));\r
+                               else if (t2 != typeof (string))\r
+                                       value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));\r
+                       }\r
+                       \r
+                       if (t1 != t2)\r
+                               value2 = Convert.ChangeType (value2, Type.GetTypeCode (t1));\r
+                       \r
+                       Result = Calculate (value1, value2, t1);\r
+                       \r
+                       return Result; \r
+               }\r
+               protected virtual object Calculate (object value1, object value2, Type TempType)\r
+               {\r
+                       return null;\r
+               }\r
+               \r
+               /// <summary>\r
+               ///  static method for comparing two ExpressionElement. This is used in =, <, >, <>, <=, >= elements.\r
+               ///  If elements are equal returns 0, if E1 is less that E2, return -1 else if E1 is greater 1 \r
+               /// </summary>\r
+               protected static int Compare (ExpressionElement E1, ExpressionElement E2, DataRow Row)\r
+               { \r
+                       ExpressionElementComparer comparer = new ExpressionElementComparer(E1, Row);\r
+\r
+                       return comparer.CompareTo(E2);\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Checks syntax of expression and throws exception if needed.\r
+               ///  Also removes whitespaces between operator elements for example: age < = 64 --> age <= 64\r
+               /// </summary>\r
+               internal static string ValidateExpression (string s)\r
+               {                       \r
+                       //\r
+                       // TODO: find out nice way to do this. This is NOT nice way :-P\r
+                       //\r
+                       //string temp = "";\r
+                       OP op = OP.OPERAND;\r
+                       OPERATOR_TYPE operatorType = OPERATOR_TYPE.UNDEFINED;\r
+\r
+                       StringBuilder strOperator = new StringBuilder();\r
+                       StringBuilder strOperand = new StringBuilder();\r
+                       int quotes = 0;\r
+                       int parentheses = 0;\r
+                       StringBuilder newExp = new StringBuilder();\r
+                       bool isDigit = false;\r
+                       //bool litOperator = false;\r
+                       s = s.Trim();\r
+                       \r
+                       for (int i = 0; i < s.Length; i++) \r
+                       {\r
+\r
+                               char c = s [i];\r
+                               \r
+                               if (c == '\'')\r
+                                       quotes++;\r
+\r
+                               if ((c == '\n' || c == '\t') && quotes == 0)\r
+                                       c = ' ';\r
+\r
+                               if (op == OP.OPERAND && c == '(')\r
+                                       parentheses++;\r
+                               else if (op == OP.OPERAND && c == ')')\r
+                                       parentheses--;\r
+\r
+                               if (c == ' ' && op ==  OP.OPERAND && (quotes % 2) == 0 && parentheses == 0) \r
+                               {\r
+                                       \r
+                                       op = OP.OPERATOR;\r
+                                       int max = strOperand.Length;\r
+                                       for (int it = 0; it < max; it++)\r
+                                               newExp.Append(strOperand[it]);\r
+                                       strOperand.Remove(0, max);\r
+                                       strOperator.Append(' ');\r
+                               }\r
+\r
+                               if (op == OP.OPERAND) \r
+                               {\r
+\r
+                                       if (!Char.IsDigit (c) && isDigit && (quotes % 2) == 0) \r
+                                       {\r
+                                               int max = strOperand.Length;\r
+                                               for (int it = 0; it < max; it++)\r
+                                                       newExp.Append(strOperand[it]);\r
+                                               strOperand.Remove(0, max);\r
+                                               op = OP.OPERATOR;\r
+                                               operatorType = OPERATOR_TYPE.UNDEFINED;\r
+                                       }\r
+                                       else\r
+                                               strOperand.Append(c);\r
+                               }\r
+\r
+                               if (op == OP.OPERATOR) \r
+                               {\r
+\r
+                                       isDigit = false;\r
+                                       if (operatorType == OPERATOR_TYPE.UNDEFINED) \r
+                                       {\r
+\r
+                                               if (c == '<' || c == '=' || c == '>' || c == '*' || c == '/' || c == '%' \r
+                                                       || c == '-' || c == '+')\r
+\r
+                                                       operatorType = OPERATOR_TYPE.SYMBOLIC;\r
+                                               else if (c != ' ')\r
+                                                       operatorType = OPERATOR_TYPE.LITERAL;\r
+                                       }\r
+                                       else if (operatorType == OPERATOR_TYPE.SYMBOLIC) \r
+                                       {\r
+                                               \r
+                                               //Checking for operators following one another\r
+                                               if ((c == '=' || c== '<' || c== '>') &&\r
+                                                       (strOperator.Length == 2) &&\r
+                                                       (strOperator[0] == ' '))\r
+                                               {\r
+                                                       char chSecond = strOperator[1];\r
+                                                       if (chSecond == '+' ||\r
+                                                               chSecond == '-' ||\r
+                                                               chSecond == '%' ||\r
+                                                               chSecond == '*')\r
+                                                       throw new SyntaxErrorException (\r
+                                                               "The operator " + strOperator.ToString() + c + " is not valid");\r
+                                               }\r
+\r
+                                               // this is COPY-PASTE\r
+                                               op = OP.OPERAND;\r
+                                               if (newExp[newExp.Length - 1] != ' '  && \r
+                                                       strOperator[0] != ' ')\r
+                                                       newExp.Append(' ');\r
+\r
+                                               int max = strOperator.Length;\r
+                                               for (int it = 0; it < max; it++)\r
+                                                       newExp.Append(strOperator[it]);\r
+                                               strOperator.Remove(0, max);\r
+\r
+                                               if (Char.IsDigit (c))\r
+                                                       isDigit = true;\r
+                                                       \r
+                                               strOperand.Remove(0, strOperand.Length);\r
+                                               strOperand.Append(c);\r
+                                               \r
+                                               continue;\r
+\r
+                                       }\r
+\r
+                                       if (operatorType == OPERATOR_TYPE.LITERAL && c == ' ') \r
+                                       {\r
+                                               op = OP.OPERAND;\r
+                                               int max = strOperator.Length;\r
+                                               for (int it = 0; it < max; it++)\r
+                                                       newExp.Append(strOperator[it]);\r
+                                               strOperator.Remove(0, max);\r
+\r
+                                               strOperand.Append(' ');\r
+                                       }\r
+\r
+\r
+                                       if (Char.IsDigit (c) && operatorType != OPERATOR_TYPE.LITERAL) \r
+                                       {\r
+\r
+                                               op = OP.OPERAND;\r
+                                               if (newExp[newExp.Length - 1] != ' '  && \r
+                                                       strOperator[0] != ' ')\r
+                                                       newExp.Append(' ');\r
+\r
+                                               int max = strOperator.Length;\r
+                                               for (int it = 0; it < max; it++)\r
+                                                       newExp.Append(strOperator[it]);\r
+                                               strOperator.Remove(0, max);\r
+\r
+                                               if (Char.IsDigit (c))\r
+                                                       isDigit = true;\r
+                                                       \r
+                                               strOperand.Remove(0, strOperand.Length);\r
+                                               strOperand.Append(c);\r
+                                       }\r
+\r
+                                       else if (c != ' ')\r
+                                               strOperator.Append(c);                                  \r
+                               }\r
+                       }\r
+\r
+                       if (op == OP.OPERATOR)\r
+                               throw new SyntaxErrorException (\r
+                                       "Missing operand after '" + strOperator.ToString() + "' operator");\r
+                       else\r
+                       {\r
+                               int max = strOperand.Length;\r
+                               for (int it = 0; it < max; it++)\r
+                                       newExp.Append(strOperand[it]);\r
+                       }\r
+\r
+                       return newExp.ToString();\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Finds and creates Expression elements.\r
+               ///  This presumes that expression is valid.\r
+               /// </summary>\r
+               protected void ParseExpression (string s)\r
+               {       \r
+                       //\r
+                       // TODO/FIXME: IMHO, this should be done with different kind of parsing:\r
+                       // char by char not operand by operand. \r
+                       // fixed the easy places, should consider better parsing\r
+                       //\r
+\r
+                       string inside = String.Empty; // stores string betwee parentheses like a = 12 and (b = 1 or b = 2)\r
+                       string lower = s.ToLower();\r
+                       //string function = ""; // stores fuction paramters like substring (this, are, paramters)\r
+                       //string s1 = "";\r
+                       //string s2 = "";\r
+                       int startIndex = lower.IndexOf ('(');\r
+                       \r
+                       // Find parenthesis\r
+                       if (startIndex != -1) \r
+                       {\r
+                               string functionName = String.Empty;\r
+                               if (startIndex > 0)\r
+                               {\r
+                                       int functionStart = lower.LastIndexOf('=', startIndex-1, startIndex);\r
+                                       if (functionStart < 0)\r
+                                               functionStart++;\r
+                                       functionName = lower.Substring(functionStart, startIndex);\r
+\r
+                                       functionName = functionName.Trim ();\r
+                               }\r
+\r
+                               // check if previous element is a function\r
+                               if (functionName.Length == 0 || (!functionName.EndsWith ("convert") && !functionName.EndsWith ("len") &&\r
+                                       !functionName.EndsWith ("isnull") && !functionName.EndsWith ("iif") &&\r
+                                       !functionName.EndsWith ("trim") && !functionName.EndsWith ("substring") &&\r
+                                       !functionName.EndsWith ("sum") && !functionName.EndsWith ("avg") &&\r
+                                       !functionName.EndsWith ("min") && !functionName.EndsWith ("max") &&\r
+                                       !functionName.EndsWith ("count") && !functionName.EndsWith ("stdev") &&\r
+                                       !functionName.EndsWith ("var")&& !functionName.EndsWith ("in"))) \r
+                               {\r
+                                       \r
+                                       \r
+                                       int i = startIndex + 1;\r
+                                       int max = lower.Length;\r
+                       \r
+                                       for (int par = 1; par > 0 && i < max; i++) \r
+                                       {\r
+\r
+                                               char c = s [i];\r
+                                               if (c == '(')\r
+                                                       par++;\r
+                                               else\r
+                                               if (c == ')')\r
+                                                       par--;\r
+                                       }\r
+                                       \r
+                                       inside = s.Substring(startIndex + 1, i - startIndex - 2); \r
+                                       lower = lower.Remove (startIndex, i - startIndex);\r
+                                       s = s.Remove (startIndex, i - startIndex);\r
+                               }               \r
+                                            \r
+                       }\r
+                       \r
+                       string string1 = null;\r
+                       string string2 = null;\r
+                       if (FindOrElement (s, lower, ref string1, ref string2))         \r
+                               CreateOrElement (string1, string2, inside);\r
+\r
+                       else if (FindAndElement (s, lower, ref string1, ref string2))\r
+                               CreateAndElement (string1, string2, inside);\r
+\r
+                               // find LIKE\r
+                       else if (FindLikeElement (s, lower, ref string1, ref string2))\r
+                               CreateLikeElement (string1, string2, inside);\r
+                       \r
+                               // find IN\r
+                       else if (FindInElement (s, lower, ref string1, ref string2))\r
+                               CreateInElement (string1, string2, inside);\r
+\r
+                               // find =\r
+                       else if (FindEqualElement (s, lower, ref string1, ref string2))\r
+                               CreateEqualsElement (string1, string2, inside);\r
+\r
+                               // find <>\r
+                       else if (FindUnequalElement (s, lower, ref string1, ref string2))\r
+                               CreateUnequalsElement (string1, string2, inside);\r
+\r
+                               // find <=\r
+                       else if (FindLessThanOrEqualElement (s, lower, ref string1, ref string2))\r
+                               CreateLessThanOrEqualElement (string1, string2, inside);\r
+\r
+                               // find <\r
+                       else if (FindLessThanElement (s, lower, ref string1, ref string2))\r
+                               CreateLessThanElement (string1, string2, inside);\r
+\r
+                               // find >=\r
+                       else if (FindGreaterThanOrEqualElement (s, lower, ref string1, ref string2))\r
+                               CreateGreaterThanOrEqualElement (string1, string2, inside);\r
+\r
+                               // find >\r
+                       else if (FindGreaterThanElement (s, lower, ref string1, ref string2))\r
+                               CreateGreaterThanElement (string1, string2,  inside);\r
+\r
+                               // if there wasn't any operators like 'and' or 'not' there still could be\r
+                               // arithmetic operators like '+' or '-' or functions like 'iif' or 'substring'\r
+\r
+                               // find *\r
+                       else if (FindMultiplyElement (s, lower, ref string1, ref string2))\r
+                               CreateMultiplyElement (string1, string2, inside);\r
+                       \r
+                               // find /\r
+                       else if (FindDivideElement (s, lower, ref string1, ref string2))\r
+                               CreateDivideElement (string1, string2, inside);\r
+\r
+\r
+                               // find +\r
+                       else if (FindAdditionElement (s, lower, ref string1, ref string2))\r
+                               CreateAdditionElement (string1, string2, inside);\r
+\r
+                               // find -\r
+                       else if (FindSubtractElement (s, lower, ref string1, ref string2))\r
+                               CreateSubtractionElement (string1, string2, inside);\r
+\r
+                               // find %\r
+                       else if (FindModulusElement (s, lower, ref string1, ref string2))\r
+                               CreateModulusElement (string1, string2, inside);\r
+\r
+                               // find sum ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.SUM))\r
+                               Elements.Add (new ExpressionSum (s.Trim ()));\r
+\r
+                               // find avg ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.AVG))\r
+                               Elements.Add (new ExpressionAvg (s.Trim ()));\r
+\r
+                               // find min ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.MIN))\r
+                               Elements.Add (new ExpressionMin (s.Trim ()));\r
+\r
+                               // find max ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.MAX))\r
+                               Elements.Add (new ExpressionMax (s.Trim ()));\r
+\r
+                               // find count ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.COUNT))\r
+                               Elements.Add (new ExpressionCount (s.Trim ()));                            \r
+\r
+                               // find stdev ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.STDEV))\r
+                               Elements.Add (new ExpressionStdev (s.Trim ()));\r
+\r
+                               // find var ()\r
+                       else if (FindAggregateElement (s, lower, AGGREGATE.VAR))\r
+                               Elements.Add (new ExpressionVar (s.Trim ()));\r
+\r
+                               // find len\r
+                       else if (FindLenElement (s, lower))\r
+                               Elements.Add (new ExpressionLen (s.Trim ()));\r
+\r
+                               // find iif\r
+                       else if (FindIifElement (s, lower))\r
+                               Elements.Add (new ExpressionIif (s.Trim ()));\r
+\r
+                               // find isnull\r
+                       else if (FindIsNullElement (s, lower))\r
+                               Elements.Add (new ExpressionIsNull (s.Trim ()));\r
+\r
+                               // find substring\r
+                       else if (FindSubstringElement (s, lower))\r
+                               Elements.Add (new ExpressionSubstring (s.Trim ()));\r
+\r
+                               // if expression is like '(something someoperator something)'\r
+                       else if (inside.Trim () != string.Empty)\r
+                               ParseExpression (inside);\r
+\r
+                               // At least, if it wasnt any of the above it is just normat string or int\r
+                               // or....                       \r
+                       else\r
+                               Elements.Add (new ExpressionSingleElement (s.Trim ()));                 \r
+               }\r
+\r
+               #region CheckElement methods\r
+\r
+               //\r
+               // These methods are temporary for now\r
+               //\r
+\r
+               private bool FindOrElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf("or");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       // Test if or is between ''\r
+                       int oldIndex = -1;                      \r
+                       while ((indexOf = stemp.IndexOf ("or", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+                               \r
+                               oldIndex = indexOf;\r
+\r
+                               // check is the 'or' element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+                               \r
+                               // Check is or part of something else for example column name\r
+                               if (indexOf != 0) \r
+                               {\r
+                                       \r
+                                       if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+                                               continue;\r
+                               }\r
+                               \r
+                               if (indexOf < s.Length + 2) \r
+                               {\r
+                                       \r
+                                       if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')\r
+                                               continue;\r
+                               }\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 2).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+               \r
+               private bool FindAndElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf("and");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       // Test if or is between ''\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("and", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+                               \r
+                               oldIndex = indexOf;\r
+                               \r
+                               // check is the 'and' element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               // Check is or part of something else for example column name\r
+                               if (indexOf != 0) \r
+                               {\r
+                                       \r
+                                       if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+                                               continue;\r
+                               }\r
+                               \r
+                               if (indexOf < stemp.Length + 3) \r
+                               {\r
+                                       \r
+                                       if (stemp [indexOf + 3] != ' ' && stemp [indexOf + 3] != '\'')\r
+                                               continue;\r
+                               }\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 3).Trim ();\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               private bool FindLikeElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf("like");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       // Test if or is between ''\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("like", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+                               \r
+                               oldIndex = indexOf;\r
+                               \r
+                               // check is the 'and' element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               // Check is or part of something else for example column name\r
+                               if (indexOf != 0) \r
+                               {\r
+                                       \r
+                                       if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+                                               continue;\r
+                               }\r
+                               \r
+                               if (indexOf < stemp.Length + 4) \r
+                               {\r
+                                       \r
+                                       if (stemp [indexOf + 4] != ' ' && stemp [indexOf + 4] != '\'')\r
+                                               continue;\r
+                               }\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 4).Trim ();\r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               private bool FindEqualElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("=");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+                       \r
+                       int oldIndex = -1;\r
+\r
+                       while ((indexOf = stemp.IndexOf ("=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+\r
+                               // Check is the = part of <= or >=\r
+                               if (stemp [indexOf - 1] == '<' || stemp [indexOf - 1] == '>')\r
+                                       continue;\r
+\r
+                               // Check is the = element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+                                       \r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+                               \r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               private bool FindUnequalElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("<>");\r
+\r
+                       if (stemp.IndexOf ("<>") == -1)\r
+                               return false;\r
+                      \r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("<>", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+\r
+                               // test if next charachter is something else than ' '\r
+                               bool failed = false;\r
+\r
+                               // Check is the <> element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+                                       \r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 2).Trim ();\r
+                               \r
+                               return true;\r
+                       }\r
+\r
+                       return false;\r
+                       \r
+               }\r
+\r
+\r
+               private bool FindLessThanElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("<");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("<", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+\r
+                               // if < is part of <> or <=\r
+                               if (stemp [indexOf + 1] == '>' || stemp [indexOf + 1] == '=')\r
+                                       continue;\r
+\r
+                               // Test is < element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindLessThanOrEqualElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("<=");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("<=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               // Test is <= element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 2).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindGreaterThanElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf (">");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf (">", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+\r
+                               // if < is part of <> or <=\r
+                               if (stemp [indexOf - 1] == '<' || stemp [indexOf + 1] == '=')\r
+                                       continue;\r
+\r
+                               // Test is < element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindGreaterThanOrEqualElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf (">=");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf (">=", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+                               // Test is <= element part of string element\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 2).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindAdditionElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("+");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("+", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               // FIXME: if '+' represents sign of integer\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindSubtractElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("-");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("-", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // check is this lonely element         \r
+                               failed = true;\r
+                               for (int i = indexOf - 1; i >= 0; i--) \r
+                               {\r
+                                       if (stemp [i] != ' ') \r
+                                       {\r
+                                               failed = false;\r
+                                               break;\r
+                                       }\r
+                               }\r
+                                       \r
+                               if (failed)\r
+                                       continue;\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindMultiplyElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("*");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("*", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // FIXME: If there is a divide operator before multiply operator.\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindDivideElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("/");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("/", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // FIXME: If there is a multiply operator before divide operator.\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+                                   \r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindModulusElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("%");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("%", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // FIXME: If there is a multiply operator before divide operator.\r
+\r
+                               // Check is or part of column name\r
+                               if (IsPartOfColumnName (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 1).Trim ();\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindAggregateElement (string s, string lower, AGGREGATE aggregate)\r
+               {\r
+                       string agg = null;\r
+\r
+                       switch (aggregate) \r
+                       {\r
+\r
+                               case AGGREGATE.SUM:\r
+                                       agg = "sum";\r
+                                       break;\r
+                               case AGGREGATE.AVG:\r
+                                       agg = "avg";\r
+                                       break;\r
+                               case AGGREGATE.MIN:\r
+                                       agg = "min";\r
+                                       break;\r
+                               case AGGREGATE.MAX:\r
+                                       agg = "max";\r
+                                       break;\r
+                               case AGGREGATE.COUNT:\r
+                                       agg = "count";\r
+                                       break;\r
+                               case AGGREGATE.STDEV:\r
+                                       agg = "stdev";\r
+                                       break;\r
+                               case AGGREGATE.VAR:\r
+                                       agg = "var";\r
+                                       break;\r
+                               default:\r
+                                       throw new NotImplementedException ();\r
+                       }\r
+                              \r
+                               \r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf (agg);\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf (agg, oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+\r
+               }\r
+               \r
+               private bool FindSumElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("sum");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("sum", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindAvgElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("avg");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("avg", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindMinElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("min");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("min", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindMaxElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("max");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("max", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindCountElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("count");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("count", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindStdevElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("stdev");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("stdev", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindVarElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("var");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("var", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindLenElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("len");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("len", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindIifElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("iif");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("iif", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindIsNullElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("isnull");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("isnull", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+                               \r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindSubstringElement (string s, string lower)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("substring");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("substring", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+\r
+                               oldIndex = indexOf;\r
+                               bool failed = false;\r
+\r
+                               // Check is or part of column name\r
+                               if (indexOf != 0 && stemp [indexOf - 1] != ' ')\r
+                                       continue;\r
+\r
+                               // is the element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               private bool FindInElement (string s, string lower, ref string s1, ref string s2)\r
+               {\r
+                       string stemp = lower;\r
+                       int indexOf = stemp.IndexOf ("in");\r
+\r
+                       if (indexOf == -1)\r
+                               return false;\r
+\r
+                       int oldIndex = -1;\r
+                       while ((indexOf = stemp.IndexOf ("in", oldIndex + 1)) != -1 && indexOf > oldIndex) \r
+                       {\r
+                               oldIndex = indexOf;\r
+                               \r
+                               // check is the 'and' element part of string element\r
+                               if (IsPartOfStringElement (stemp, indexOf))\r
+                                       continue;\r
+\r
+\r
+                               // Check is or part of something else for example column name\r
+                               if (indexOf != 0) \r
+                               {       \r
+                                       if (stemp [indexOf - 1] != ' ' && stemp [indexOf - 1] != '\'')\r
+                                               continue;\r
+                               }\r
+                               \r
+                               if (indexOf < stemp.Length + 2) \r
+                               {\r
+                                       if (stemp [indexOf + 2] != ' ' && stemp [indexOf + 2] != '\'')\r
+                                               continue;\r
+                               }\r
+\r
+                               if (IsPartOfFunction (stemp, indexOf))\r
+                                       continue;\r
+\r
+                               s1 = s.Substring (0, indexOf).Trim ();\r
+                               s2 = s.Substring (indexOf + 2).Trim ();\r
+                               return true;\r
+                       }\r
+               \r
+                       return false;                   \r
+               }\r
+\r
+               \r
+               #endregion // CheckElement methods\r
+\r
+               #region CreateElement methods\r
+\r
+               // \r
+               // These methods are going to be removed when way of parsing is changed\r
+               //\r
+\r
+               private void CreateOrElement (string s1, string s2, string inside) \r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionOr (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateAndElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionAnd (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateLikeElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionLike (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateInElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionIn (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateEqualsElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionEquals (s1.Trim (), s2.Trim ()));                   \r
+               }\r
+\r
+               private void CreateUnequalsElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionUnequals (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateLessThanElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionLessThan (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateLessThanOrEqualElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionLessThanOrEqual (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateGreaterThanElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionGreaterThan (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+\r
+               private void CreateGreaterThanOrEqualElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionGreaterThanOrEqual (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateAdditionElement (string s1, string s2,  string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);                      \r
+                       Elements.Add (new ExpressionAddition (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateSubtractionElement (string s1, string s2,  string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);                      \r
+                       Elements.Add (new ExpressionSubtraction (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateMultiplyElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionMultiply (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateDivideElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionDivide (s1.Trim (), s2.Trim ()));\r
+               }\r
+\r
+               private void CreateModulusElement (string s1, string s2, string inside)\r
+               {\r
+                       CheckParenthesis (inside, ref s1, ref s2);\r
+                       Elements.Add (new ExpressionModulus (s1.Trim (), s2.Trim ()));\r
+               }                       \r
+\r
+               #endregion // CreateElemnt methods\r
+\r
+               #region Little helppers\r
+\r
+               private void CheckParenthesis (string inside, ref string s1, ref string s2)\r
+               {\r
+                       if (s1 == string.Empty && inside != string.Empty)\r
+                               s1 = inside;\r
+                       else if (s2 == string.Empty && inside != string.Empty)\r
+                               s2 = inside;    \r
+               }\r
+\r
+\r
+               /// <summary>\r
+               ///  Checks is the element part of stringelement\r
+               /// </summary>\r
+               private bool IsPartOfStringElement (string s, int indexOf)\r
+               {\r
+                       // count how many '-charachters are before or. If count is odd it means or IS between quotes\r
+                       int quotes = 0;\r
+                       for (int i = indexOf - 1; i >= 0; i--) \r
+                       {\r
+                               if (s [i] == '\'')\r
+                                       quotes++;\r
+                       }\r
+                       \r
+                       if ((quotes & 1) != 0)\r
+                               return true;\r
+                       else \r
+                               return false;\r
+               }\r
+\r
+               /// <summary>\r
+               ///  Checks is the element part of column table\r
+               /// </summary>\r
+               private bool IsPartOfColumnName (string s, int indexOf)\r
+               {\r
+                       for (int i = indexOf; i >= 0; i--) \r
+                       {\r
+                               \r
+                               // If the element is between [] it is part of columnname\r
+                               if (s [i] == '\'' || s [i] == ']') \r
+                               {\r
+                                       break;\r
+                               }\r
+                               else if (s [i] == '[') \r
+                               {\r
+                                       return true;\r
+                               }\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+\r
+               /// <summary>\r
+               ///  Checks are element part of function\r
+               /// </summary>\r
+               private bool IsPartOfFunction (string s, int indexOf)\r
+               {\r
+\r
+                       // \r
+                       // If ',' or '\''  comes before '(' this element is not part of function's parameters\r
+                       //\r
+                       \r
+                       for (int i = indexOf; i >= 0; i--) \r
+                       {\r
+                               \r
+                               if (s [i] == '(' || s [i] == ',') \r
+                               {\r
+                                       return true;\r
+                               }\r
+                               else if (s [i] == ')') \r
+                               {\r
+                                       break;\r
+                               }\r
+                       }\r
+\r
+                       return false;\r
+               }\r
+\r
+               #endregion // Little helppers\r
+\r
+               #region ExpressionElementComparer\r
+               protected sealed class ExpressionElementComparer\r
+               {\r
+                       object _value1 = null;\r
+                       Type _t1 = null;\r
+                       Type _RT1 = null;\r
+                       DataRow _row = null;\r
+\r
+                       public ExpressionElementComparer(ExpressionElement E1, DataRow Row)\r
+                       {\r
+                               _value1 = E1.Result (Row);\r
+\r
+                               _row = Row;\r
+\r
+                               if (_value1 == null || _value1 == DBNull.Value)\r
+                                       return;\r
+\r
+                               _t1 = _value1.GetType ();\r
+                               _RT1 = E1.ResultType (Row);\r
+                       }\r
+\r
+                       public int CompareTo (ExpressionElement E2)\r
+                       {\r
+                               object value1 = _value1;\r
+                               object value2 = E2.Result (_row);\r
+\r
+                               if ((value1 == null || value1 == DBNull.Value) && (value2 == null || value2 == DBNull.Value))\r
+                                       return 0;\r
+                               else if (value2 == null || value2 == DBNull.Value)\r
+                                       return 1;\r
+                               else if (value1 == null || value1 == DBNull.Value)\r
+                                       return -1;\r
+\r
+                               Type t2 = value2.GetType ();\r
+                       \r
+                               Type RT2 = E2.ResultType (_row);\r
+\r
+                               if (_t1 == typeof (string) || t2 == typeof (string)) \r
+                               {\r
+                                       // FIXME: If one of elements are string they both should be???\r
+                                       return String.Compare(value1.ToString(), value2.ToString(), !_row.Table.CaseSensitive);\r
+                               }\r
+\r
+                               if (_t1 != t2) \r
+                               {\r
+                                       value2 = Convert.ChangeType (value2, Type.GetTypeCode (_t1));\r
+                               }\r
+\r
+                               if (value1 is IComparable)\r
+                                       return ((IComparable)value1).CompareTo(value2);\r
+\r
+                               return (int) _t1.InvokeMember ("CompareTo", BindingFlags.Default | \r
+                                       BindingFlags.InvokeMethod, null, \r
+                                       value1, \r
+                                       new object [] {value2});\r
+                       }\r
+               }\r
+               #endregion\r
+       }    \r
+       #endif    \r
+}\r
index 618b6d249d57bb1d37fc3c000937d05c32dcd5f8..268b82721876eaf38980b1ee18d6ef72a6037cff 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+
 
 namespace System.Data {
        public enum FillOptions 
@@ -42,4 +42,4 @@ namespace System.Data {
        }
 }
 
-#endif // NET_2_0
+
index 62b480bff56379ae7d927221c86aba862a7b067b..ed85b5e8ba7bd3d86dd9c510535ae7ce7d20333b 100644 (file)
@@ -36,6 +36,7 @@ using System;
 using System.Collections;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
+using System.Data.Common;
 
 namespace System.Data {
        [Editor]
@@ -44,17 +45,19 @@ namespace System.Data {
        public class ForeignKeyConstraint : Constraint 
        {
                private UniqueConstraint _parentUniqueConstraint;
+               //FIXME: create a class which will wrap this collection
                private DataColumn [] _parentColumns;
+               //FIXME: create a class which will wrap this collection
                private DataColumn [] _childColumns;
-               private DataColumn [] _childColumnsExtended;
                private Rule _deleteRule = Rule.Cascade;
                private Rule _updateRule = Rule.Cascade;
                private AcceptRejectRule _acceptRejectRule = AcceptRejectRule.None;
-               private string _parentTableName;
-                private string _childTableName;
-                private string [] _parentColumnNames;
-                private string [] _childColumnNames;
-                private bool _dataColsNotValidated = false;
+           private string _parentTableName;
+        private string _childTableName;
+               //FIXME: remove those; and use only DataColumns[]
+        private string [] _parentColumnNames;
+        private string [] _childColumnNames;
+        private bool _dataColsNotValidated = false;
                        
                #region Constructors
 
@@ -94,68 +97,68 @@ namespace System.Data {
                public ForeignKeyConstraint(string constraintName, string parentTableName, string[] parentColumnNames, string[] childColumnNames, AcceptRejectRule acceptRejectRule, Rule deleteRule, Rule updateRule) 
                {
                        _dataColsNotValidated = true;
-                        base.ConstraintName = constraintName;
-                                                                                                    
-                        // "parentTableName" is searched in the "DataSet" to which the "DataTable"
-                        // from which AddRange() is called
-                        // childTable is the "DataTable" which calls AddRange()
-                                                                                                    
-                        // Keep reference to parentTableName to resolve later
-                        _parentTableName = parentTableName;
-                                                                                                    
-                        // Keep reference to parentColumnNames to resolve later
-                        _parentColumnNames = parentColumnNames;
-                                                                                                    
-                        // Keep reference to childColumnNames to resolve later
-                        _childColumnNames = childColumnNames;
-                                                                                                    
-                        _acceptRejectRule = acceptRejectRule;
-                        _deleteRule = deleteRule;
-                        _updateRule = updateRule;
+            base.ConstraintName = constraintName;
+                                                                                        
+            // "parentTableName" is searched in the "DataSet" to which the "DataTable"
+            // from which AddRange() is called
+            // childTable is the "DataTable" which calls AddRange()
+                                                                                        
+            // Keep reference to parentTableName to resolve later
+            _parentTableName = parentTableName;
+                                                                                        
+            // Keep reference to parentColumnNames to resolve later
+            _parentColumnNames = parentColumnNames;
+                                                                                        
+            // Keep reference to childColumnNames to resolve later
+            _childColumnNames = childColumnNames;
+                                                                                        
+            _acceptRejectRule = acceptRejectRule;
+            _deleteRule = deleteRule;
+            _updateRule = updateRule;
 
                }
 
-                internal void postAddRange (DataTable childTable)
-                {
-                        // LAMESPEC - Does not say that this is mandatory
-                        // Check whether childTable belongs to a DataSet
-                        if (childTable.DataSet == null)
-                                throw new InvalidConstraintException ("ChildTable : " + childTable.TableName + " does not belong to any DataSet");
-                        DataSet dataSet = childTable.DataSet;
-                        _childTableName = childTable.TableName;
-                        // Search for the parentTable in the childTable's DataSet
-                        if (!dataSet.Tables.Contains (_parentTableName))
-                                throw new InvalidConstraintException ("Table : " + _parentTableName + "does not exist in DataSet : " + dataSet);
-                                                                                                    
-                        // Keep reference to parentTable
-                        DataTable parentTable = dataSet.Tables [_parentTableName];
-                                                                                                    
-                        int i = 0, j = 0;
-                                                                                                    
-                        // LAMESPEC - Does not say which Exception is thrown
-                        if (_parentColumnNames.Length < 0 || _childColumnNames.Length < 0)
-                                throw new InvalidConstraintException ("Neither parent nor child columns can be zero length");
-                        // LAMESPEC - Does not say which Exception is thrown
-                        if (_parentColumnNames.Length != _childColumnNames.Length)
-                                         throw new InvalidConstraintException ("Both parent and child columns must be of same length");                                                                                                    
-                        DataColumn []parentColumns = new DataColumn [_parentColumnNames.Length];
-                        DataColumn []childColumns = new DataColumn [_childColumnNames.Length];
-                                                                                                    
-                        // Search for the parentColumns in parentTable
-                        foreach (string parentCol in _parentColumnNames){
-                                if (!parentTable.Columns.Contains (parentCol))
-                                        throw new InvalidConstraintException ("Table : " + _parentTableName + "does not contain the column :" + parentCol);
-                                parentColumns [i++] = parentTable. Columns [parentCol];
-                        }
-                        // Search for the childColumns in childTable
-                        foreach (string childCol in _childColumnNames){
-                                if (!childTable.Columns.Contains (childCol))
-                                        throw new InvalidConstraintException ("Table : " + _childTableName + "does not contain the column : " + childCol);
-                                childColumns [j++] = childTable.Columns [childCol];
-                        }
-                        _validateColumns (parentColumns, childColumns);
-                        _parentColumns = parentColumns;
-                        _childColumns = childColumns;
+               internal void postAddRange (DataTable childTable)
+        {
+            // LAMESPEC - Does not say that this is mandatory
+            // Check whether childTable belongs to a DataSet
+            if (childTable.DataSet == null)
+                    throw new InvalidConstraintException ("ChildTable : " + childTable.TableName + " does not belong to any DataSet");
+            DataSet dataSet = childTable.DataSet;
+            _childTableName = childTable.TableName;
+            // Search for the parentTable in the childTable's DataSet
+            if (!dataSet.Tables.Contains (_parentTableName))
+                    throw new InvalidConstraintException ("Table : " + _parentTableName + "does not exist in DataSet : " + dataSet);
+                                                                                        
+            // Keep reference to parentTable
+            DataTable parentTable = dataSet.Tables [_parentTableName];
+                                                                                        
+            int i = 0, j = 0;
+                                                                                        
+            // LAMESPEC - Does not say which Exception is thrown
+            if (_parentColumnNames.Length < 0 || _childColumnNames.Length < 0)
+                    throw new InvalidConstraintException ("Neither parent nor child columns can be zero length");
+            // LAMESPEC - Does not say which Exception is thrown
+            if (_parentColumnNames.Length != _childColumnNames.Length)
+                               throw new InvalidConstraintException ("Both parent and child columns must be of same length");                                                                                                    
+            DataColumn []parentColumns = new DataColumn [_parentColumnNames.Length];
+            DataColumn []childColumns = new DataColumn [_childColumnNames.Length];
+                                                                                        
+            // Search for the parentColumns in parentTable
+            foreach (string parentCol in _parentColumnNames){
+                    if (!parentTable.Columns.Contains (parentCol))
+                            throw new InvalidConstraintException ("Table : " + _parentTableName + "does not contain the column :" + parentCol);
+                    parentColumns [i++] = parentTable. Columns [parentCol];
+            }
+            // Search for the childColumns in childTable
+            foreach (string childCol in _childColumnNames){
+                    if (!childTable.Columns.Contains (childCol))
+                            throw new InvalidConstraintException ("Table : " + _childTableName + "does not contain the column : " + childCol);
+                    childColumns [j++] = childTable.Columns [childCol];
+            }
+            _validateColumns (parentColumns, childColumns);
+            _parentColumns = parentColumns;
+            _childColumns = childColumns;
                }
                        
 #if NET_2_0
@@ -225,6 +228,12 @@ namespace System.Data {
                                //All columns must belong to the same table.
                                if (ctable != cc.Table)
                                        throw new InvalidConstraintException("Child columns must all belong to the same table.");
+
+                               if (pc.CompiledExpression != null)
+                                       throw new ArgumentException(String.Format("Cannot create a constraint based on Expression column {0}.", pc.ColumnName));
+
+                               if (cc.CompiledExpression != null)
+                                       throw new ArgumentException(String.Format("Cannot create a constraint based on Expression column {0}.", cc.ColumnName));
                                
                        }
 
@@ -305,10 +314,6 @@ namespace System.Data {
                        //we can fail the validation
                        //collection.ValidateRemoveConstraint += new DelegateValidateRemoveConstraint(
                        //              _validateRemoveParentConstraint);
-
-                       parentColumns [0].Table.Constraints.ValidateRemoveConstraint += new DelegateValidateRemoveConstraint(
-                               _validateRemoveParentConstraint);
-
                }
                
                
@@ -380,9 +385,12 @@ namespace System.Data {
                        }
                }
 
-               internal bool DataColsNotValidated{
-                        get{ return (_dataColsNotValidated); }
-                }
+               internal bool DataColsNotValidated
+               {
+            get { 
+                               return (_dataColsNotValidated); 
+                       }
+        }
 
 
                #endregion // Properties
@@ -440,8 +448,7 @@ namespace System.Data {
 
                internal override void AddToConstraintCollectionSetup(
                                ConstraintCollection collection)
-               {
-                       
+               {                       
                        if (collection.Table != Table)
                                throw new InvalidConstraintException("This constraint cannot be added since ForeignKey doesn't belong to table " + RelatedTable.TableName + ".");
 
@@ -449,79 +456,56 @@ namespace System.Data {
                        _validateColumns(_parentColumns, _childColumns);
                        
                        //we must have a unique constraint on the parent
-                       _ensureUniqueConstraintExists(collection, _parentColumns);      
+                       _ensureUniqueConstraintExists(collection, _parentColumns);
                        
                        //Make sure we can create this thing
-                       AssertConstraint(); 
-                       //TODO:if this fails and we created a unique constraint
+                       //AssertConstraint(); 
+                       if (IsConstraintViolated())
+                               throw new ArgumentException("This constraint cannot be enabled as not all values have corresponding parent values.");
+                       //FIXME : if this fails and we created a unique constraint
                        //we should probably roll it back
                        // and remove index form Table                  
                }
                                        
-       
-               [MonoTODO]
                internal override void RemoveFromConstraintCollectionCleanup( 
                                ConstraintCollection collection)
                {
-                       // this is not referncing the index anymore
-                       Index index = this.Index;
-                       this.Index = null;
-                       // drop the extended index on child table
-                       this.Table.DropIndex(index);
+                       Index = null;
                }
                
-               [MonoTODO]
-               internal override void AssertConstraint()
+               protected override bool IsConstraintViolated()
                {
-                       //Constraint only works if both tables are part of the same dataset                     
-                       //if DataSet ...
-                       if (Table == null || RelatedTable == null) return; //TODO: Do we want this
-
-                       if (Table.DataSet == null || RelatedTable.DataSet == null) return; //   
-                       
-                       try {
-                               foreach (DataRow row in Table.Rows) {
-                                       // first we check if all values in _childColumns place are nulls.
-                                       // if yes we return.
-                                       if (row.IsNullColumns(_childColumns))
-                                               continue;
-
-                                       // check whenever there is (at least one) parent row  in RelatedTable
-                                       if(!RelatedTable.RowsExist(_parentColumns,_childColumns,row)) { 
-                                               // if no parent row exists - constraint is violated
-                                               string values = "";
-                                               for (int i = 0; i < _childColumns.Length; i++) {
-                                                       values += row[_childColumns[0]].ToString();
-                                                       if (i != _childColumns.Length - 1)
-                                                               values += ",";
-                                               }
-                                               throw new InvalidConstraintException("ForeignKeyConstraint " + ConstraintName + " requires the child key values (" + values + ") to exist in the parent table.");
+                       if (Table.DataSet == null || RelatedTable.DataSet == null) return false; //     
+                               
+                       bool hasErrors = false;
+                       foreach (DataRow row in Table.Rows) {
+                               // first we check if all values in _childColumns place are nulls.
+                               // if yes we return.
+                               if (row.IsNullColumns(_childColumns))
+                                       continue;
+
+                               // check whenever there is (at least one) parent row  in RelatedTable
+                               if(!RelatedTable.RowsExist(_parentColumns,_childColumns,row)) { 
+                                       // if no parent row exists - constraint is violated
+                                       hasErrors = true;
+                                       string[] values = new string[_childColumns.Length];
+                                       for (int i = 0; i < _childColumns.Length; i++){
+                                               DataColumn col = _childColumns[i];
+                                               values[i] = row[col].ToString();
                                        }
+
+                                       row.RowError = String.Format("ForeignKeyConstraint {0} requires the child key values ({1}) to exist in the parent table.",
+                                               ConstraintName, String.Join(",", values));
                                }
                        }
-                       catch (InvalidConstraintException){
-                               throw new ArgumentException("This constraint cannot be enabled as not all values have corresponding parent values.");
-                       }
-
-                       // Create or rebuild index on Table
-                       // We create index for FK only if PK on the Table exists
-                       // and extended index is created based on appending PK columns to the 
-                       // FK columns                   
-                       if((this.Table.PrimaryKey != null) && (this.Table.PrimaryKey.Length > 0)) {
-                               // rebuild extended columns
-                               RebuildExtendedColumns();
 
-                               if(this.Index == null) {
-                                       this.Index = this.Table.CreateIndex(this.ConstraintName + "_index",_childColumnsExtended,false);
-                               }
+                       if (hasErrors)
+                               //throw new ConstraintException("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");
+                               return true;
 
-                               if(UniqueConstraint.GetUniqueConstraintForColumnSet(this.Table.Constraints,this.Index.Columns) == null) {
-                                       this.Table.InitializeIndex(this.Index);
-                               }       
-                       }
+                       return false;
                }
                
-               [MonoTODO]
                internal override void AssertConstraint(DataRow row)
                {
                        // first we check if all values in _childColumns place are nulls.
@@ -532,57 +516,39 @@ namespace System.Data {
                        // check whenever there is (at least one) parent row  in RelatedTable
                        if(!RelatedTable.RowsExist(_parentColumns,_childColumns,row)) { 
                                // if no parent row exists - constraint is violated
-                               string values = "";
-                               for (int i = 0; i < _childColumns.Length; i++) {
-                                       values += row[_childColumns[0]].ToString();
-                                       if (i != _childColumns.Length - 1)
-                                               values += ",";
-                               }
-                               throw new InvalidConstraintException("ForeignKeyConstraint " + ConstraintName + " requires the child key values (" + values + ") to exist in the parent table.");
-                       }
-
-                       // if row can be inserted - add it to constraint index
-                       // if there is no UniqueConstraint on the same columns
-                       if(this.Index != null && UniqueConstraint.GetUniqueConstraintForColumnSet(this.Table.Constraints,this.Index.Columns) == null) {
-                               UpdateIndex(row);
+                               throw new InvalidConstraintException(GetErrorMessage(row));
                        }
                }
 
-               internal override void RollbackAssert (DataRow row)
+               internal override bool IsColumnContained(DataColumn column)
                {
-                       // first we check if all values in _childColumns place are DBNull.
-                       // if yes we return.
-                       if (row.IsNullColumns(_childColumns))
-                               return;
+                       for (int i = 0; i < _parentColumns.Length; i++)
+                               if (column == _parentColumns[i])
+                                       return true;
 
-                       // if there is no UniqueConstraint on the same columns
-                       // we should rollback row from index
-                       if(this.Index != null && UniqueConstraint.GetUniqueConstraintForColumnSet(this.Table.Constraints,this.Index.Columns) == null) {
-                               RollbackIndex(row);
-                       }
+                       for (int i = 0; i < _childColumns.Length; i++)
+                               if (column == _childColumns[i])
+                                       return true;
+
+                       return false;
+               }
+
+               internal override bool CanRemoveFromCollection(ConstraintCollection col, bool shouldThrow){
+                       return true;
                }
 
-               internal void RebuildExtendedColumns()
+               private string GetErrorMessage(DataRow row)
                {
-                       DataColumn[] pkColumns = this.Table.PrimaryKey;
-                       if((pkColumns != null) && (pkColumns.Length > 0)) {
-                               _childColumnsExtended = new DataColumn[_childColumns.Length + pkColumns.Length];                                        
-                               Array.Copy(_childColumns,0,_childColumnsExtended,0,_childColumns.Length);
-                               Array.Copy(pkColumns,0,_childColumnsExtended,_childColumns.Length,pkColumns.Length);
-                       }
-                       else {
-                               throw new InvalidOperationException("Can not extend columns for foreign key");
+                       System.Text.StringBuilder sb = new System.Text.StringBuilder();
+                       for (int i = 0; i < _childColumns.Length; i++) {
+                               sb.Append(row[_childColumns[0]].ToString());
+                               if (i != _childColumns.Length - 1) {
+                                       sb.Append(',');
+                               }
                        }
-               }
-               
-                internal bool Contains (DataColumn c, bool asParent)
-                {
-                        DataColumn [] columns = asParent? RelatedColumns : Columns;
-                        foreach (DataColumn col in columns)
-                                if (col == c)
-                                        return true;
-                        return false;
-                }
+                       string valStr = sb.ToString();
+                       return "ForeignKeyConstraint " + ConstraintName + " requires the child key values (" + valStr + ") to exist in the parent table.";
+               }               
                 
                #endregion // Methods
        }
index 2f0eded0760497139b598ee913353e3ac0be178f..42b12bef974bde0b7b59fea07a80479abda7de55 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data {
        public interface IDataReader2
        {
                #region Properties
-
+#if NET_2_0
                bool HasRows { get; }
-
+#endif
                #endregion // Properties
        }
 }
index 8efa6bd9b29c38aee388d1a500b38eab8db0a6fb..8c67cd1ff7b8738ae7404fac21ea76549945f6c7 100644 (file)
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+#if NET_2_0 || TARGET_JVM
 
 namespace System.Data {
        public interface IDataRecord2
        {
                #region Properties
 
+#if NET_2_0
                int VisibleFieldCount { get; }
-
+#endif
                #endregion // Properties
 
                #region Methods
-
+#if NET_2_0
                Type GetFieldProviderSpecificType (int i);
                object GetProviderSpecificValue (int i);
                int GetProviderSpecificValues (object[] values);
-
+#endif
                #endregion // Methods
        }
 }
 
 #endif
+
+
diff --git a/mcs/class/System.Data/System.Data/ISafeDataRecord.cs b/mcs/class/System.Data/System.Data/ISafeDataRecord.cs
new file mode 100644 (file)
index 0000000..6cf35dc
--- /dev/null
@@ -0,0 +1,63 @@
+//\r
+// System.Data.ISafeDataRecord\r
+//\r
+// Author:\r
+//   Boris Kirzner (borisk@mainsoft.com)\r
+//\r
+using System;\r
+\r
+namespace System.Data\r
+{\r
+       internal interface ISafeDataRecord\r
+       {\r
+               bool GetBooleanSafe(int i);
+
+               byte GetByteSafe(int i);
+
+               //long GetBytes(int i, long fieldOffset, byte[] buffer, int bufferOffset, int length);
+
+               char GetCharSafe(int i);
+
+               //long GetChars(int i, long fieldOffset, char[] buffer, int bufferOffset, int length);
+
+               //IDataReader GetData(int i);
+
+               //string GetDataTypeName(int i);
+
+               //DateTime GetDateTime(int i);
+
+               decimal GetDecimalSafe(int i);
+
+               double GetDoubleSafe(int i);
+
+               //Type GetFieldType(int i);
+
+               float GetFloatSafe(int i);
+
+               //Guid GetGuid(int i);
+
+               short GetInt16Safe(int i);
+
+               int GetInt32Safe(int i);
+
+               long GetInt64Safe(int i);
+
+               //string GetName(int i);
+
+               //int GetOrdinal(string name);
+
+               string GetStringSafe(int i);
+
+               //object GetValue(int i);
+
+               //int GetValues(object[] values);
+
+               //bool IsDBNull(int i);
+
+               //int FieldCount{get;}
+
+               //object this[string name]{get;}
+               
+               //object this[int i]{get;}\r
+       }\r
+}\r
index 5e173a84106f49da088faf199566587f7b172a18..b6d4d3654fe22003ff6d2315b1adeb25acfc2dd3 100644 (file)
@@ -1,4 +1,4 @@
-
+/*
 //
 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
 //
@@ -29,7 +29,7 @@ namespace System.Data
        /// <summary>
        /// Summary description for Index.
        /// </summary>
-       internal class Index 
+       internal class Index1 
        {
 
                // fields
@@ -41,7 +41,7 @@ namespace System.Data
 
 
                
-               internal Index (string name, DataTable table, DataColumn[] columns,
+               internal Index1 (string name, DataTable table, DataColumn[] columns,
                        bool unique) 
                {
 
@@ -753,4 +753,4 @@ namespace System.Data
 //                     return sb.ToString();
 //             }
        }
-}
+} */
index f98fb95874f90a6c11f4c8c6e47089d75712b8c3..4fe5306a789dbffe37e1c874541a21f9078a7699 100644 (file)
@@ -40,11 +40,11 @@ namespace System.Data
        [Serializable]
        public enum IsolationLevel
        {
-               Unspecified = -1,
                Chaos = 16,
                ReadUncommitted = 256,
-               ReadCommitted = 4096,
+               ReadCommitted = 4096,           
                RepeatableRead = 65536,
-               Serializable = 1048576
+               Serializable = 1048576,
+               Unspecified = -1
        }
 }
\ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data/Locale.cs b/mcs/class/System.Data/System.Data/Locale.cs
new file mode 100644 (file)
index 0000000..767abfd
--- /dev/null
@@ -0,0 +1,15 @@
+using System;\r
+\r
+namespace System.Globalization\r
+{\r
+       /// <summary>\r
+       /// Summary description for Locale.\r
+       /// </summary>\r
+       public class Locale\r
+       {\r
+        public static String GetText (string str)\r
+        {\r
+            return str;\r
+        }\r
+       }\r
+}\r
index 720653e32c0374611f072c7ff1c053b6850327fa..e886d10b249d634ab1c3886e6beaeb35b367407c 100644 (file)
@@ -22,6 +22,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 using System;
+using System.Collections;
 
 namespace System.Data
 {
@@ -51,6 +52,9 @@ namespace System.Data
                        if(sourceTable == null)
                                throw new ArgumentNullException("sourceTable");
 
+                       bool savedEnfoceConstraints = targetSet.EnforceConstraints;
+                       targetSet.EnforceConstraints = false;
+
                        DataTable targetTable = null;
                        if (!AdjustSchema(targetSet, sourceTable, missingSchemaAction,ref targetTable)) {
                                return;
@@ -58,7 +62,13 @@ namespace System.Data
                        if (targetTable != null) {
                                checkColumnTypes(targetTable, sourceTable); // check that the colums datatype is the same
                                fillData(targetTable, sourceTable, preserveChanges);
-                       }                       
+                       }
+                       targetSet.EnforceConstraints = savedEnfoceConstraints;
+                       
+                       if (!targetSet.EnforceConstraints && targetTable != null) {
+                               // indexes are still outdated
+                               targetTable.ResetIndexes();
+                       }
                }
 
                internal static void Merge(DataSet targetSet, DataRow[] sourceRows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
@@ -68,6 +78,10 @@ namespace System.Data
                        if(sourceRows == null)
                                throw new ArgumentNullException("sourceRows");
 
+                       bool savedEnfoceConstraints = targetSet.EnforceConstraints;
+                       targetSet.EnforceConstraints = false;
+
+                       ArrayList targetTables = new ArrayList();
                        for (int i = 0; i < sourceRows.Length; i++) {
                                DataRow row = sourceRows[i];
                                DataTable sourceTable = row.Table;
@@ -78,8 +92,17 @@ namespace System.Data
                                if (targetTable != null) {
                                        checkColumnTypes(targetTable, row.Table);
                                        MergeRow(targetTable, row, preserveChanges);
+                                       if (!(targetTables.IndexOf(targetTable) >= 0)) {
+                                               targetTables.Add(targetTable);
+                                       }
                                }
                        }
+
+                       targetSet.EnforceConstraints = savedEnfoceConstraints;
+
+                       foreach(DataTable table in targetTables) {
+                               table.ResetIndexes();
+                       }
                }
 
                // merge a row into a target table.
@@ -110,6 +133,7 @@ namespace System.Data
                        if (targetRow == null)
                        { 
                                targetRow = targetTable.NewRow();
+                               targetRow.Proposed = -1;
                                row.CopyValuesToRow(targetRow);
                                targetTable.Rows.Add(targetRow);
                        }
@@ -119,7 +143,6 @@ namespace System.Data
                        {
                                row.CopyValuesToRow(targetRow);
                        }
-
                }
                        
 
@@ -138,6 +161,7 @@ namespace System.Data
                                                DataColumn[] childColumns = ResolveColumns(sourceSet,targetTable,relation.ChildColumns);
                                                if (parentColumns != null && childColumns != null) {
                                                        DataRelation newRelation = new DataRelation(relation.RelationName,parentColumns,childColumns);
+                                                       newRelation.Nested = relation.Nested; 
                                                        targetSet.Relations.Add(newRelation);
                                                }
                                        }
@@ -150,33 +174,37 @@ namespace System.Data
                                        DataTable targetTable = targetSet.Tables[sourceTable.TableName];
 
                                        if (targetTable != null) {
-                                               foreach(UniqueConstraint uc in sourceTable.Constraints.UniqueConstraints) {
-                                                       // TODO : add more precise condition (columns)
-                                                       if ( !targetTable.Constraints.Contains(uc.ConstraintName) ) {           
-                                                               DataColumn[] columns = ResolveColumns(sourceSet,targetTable,uc.Columns);
-                                                               if (columns != null) {
-                                                                       UniqueConstraint newConstraint = new UniqueConstraint(uc.ConstraintName,columns,uc.IsPrimaryKey);
-                                                                       targetTable.Constraints.Add(newConstraint);
-                                                               }
-                                                       }
-                                                       else {
-                                                               // TODO : should we throw an exeption ?
-                                                       }
-                                               }
+                                               foreach(Constraint constraint in sourceTable.Constraints) {
 
-                                               foreach(ForeignKeyConstraint fc in sourceTable.Constraints.ForeignKeyConstraints) {
-                                                       // TODO : add more precise condition (columns)
-                                                       if (!targetTable.Constraints.Contains(fc.ConstraintName)) {
-                                                               DataColumn[] columns = ResolveColumns(sourceSet,targetTable,fc.Columns);
-                                                               DataTable relatedTable = targetSet.Tables[fc.RelatedTable.TableName];
-                                                               DataColumn[] relatedColumns = ResolveColumns(sourceSet,relatedTable,fc.RelatedColumns);
-                                                               if (columns != null && relatedColumns != null) {
-                                                                       ForeignKeyConstraint newConstraint = new ForeignKeyConstraint(fc.ConstraintName,relatedColumns,columns);
-                                                                       targetTable.Constraints.Add(newConstraint);
+                                                       if (constraint is UniqueConstraint) {
+                                                               UniqueConstraint uc = (UniqueConstraint)constraint;
+                                                               // FIXME : add more precise condition (columns)
+                                                               if ( !targetTable.Constraints.Contains(uc.ConstraintName) ) {           
+                                                                       DataColumn[] columns = ResolveColumns(sourceSet,targetTable,uc.Columns);
+                                                                       if (columns != null) {
+                                                                               UniqueConstraint newConstraint = new UniqueConstraint(uc.ConstraintName,columns,uc.IsPrimaryKey);
+                                                                               targetTable.Constraints.Add(newConstraint);
+                                                                       }
+                                                               }
+                                                               else {
+                                                                       // FIXME : should we throw an exception ?
                                                                }
                                                        }
                                                        else {
-                                                               // TODO : should we throw an exeption ?
+                                                               ForeignKeyConstraint fc = (ForeignKeyConstraint)constraint;
+                                                               // FIXME : add more precise condition (columns)
+                                                               if (!targetTable.Constraints.Contains(fc.ConstraintName)) {
+                                                                       DataColumn[] columns = ResolveColumns(sourceSet,targetTable,fc.Columns);
+                                                                       DataTable relatedTable = targetSet.Tables[fc.RelatedTable.TableName];
+                                                                       DataColumn[] relatedColumns = ResolveColumns(sourceSet,relatedTable,fc.RelatedColumns);
+                                                                       if (columns != null && relatedColumns != null) {
+                                                                               ForeignKeyConstraint newConstraint = new ForeignKeyConstraint(fc.ConstraintName,relatedColumns,columns);
+                                                                               targetTable.Constraints.Add(newConstraint);
+                                                                       }
+                                                               }
+                                                               else {
+                                                                       // FIXME : should we throw an exception ?
+                                                               }
                                                        }
                                                }
                                        }
diff --git a/mcs/class/System.Data/System.Data/RelatedDataView.cs b/mcs/class/System.Data/System.Data/RelatedDataView.cs
new file mode 100644 (file)
index 0000000..86aa7f1
--- /dev/null
@@ -0,0 +1,76 @@
+//\r
+// System.Data.RelatedDataView\r
+//\r
+// Author:\r
+//   Konstantin Triger (kostat@mainsoft.com)\r
+//\r
+\r
+using System;\r
+using System.Collections;\r
+using Mono.Data.SqlExpressions;\r
+using System.Data.Common;\r
+\r
+namespace System.Data\r
+{\r
+       /// <summary>\r
+       /// Summary description for RelatedDataView.\r
+       /// </summary>\r
+       internal class RelatedDataView : DataView, IExpression\r
+       {\r
+               #region Fields\r
+               \r
+               object[] _keyValues;\r
+               DataColumn[] _columns;\r
+\r
+               #endregion // Fields\r
+\r
+               #region Constructors\r
+               internal RelatedDataView(DataColumn[] relatedColumns,object[] keyValues)\r
+               {\r
+                       dataTable = relatedColumns[0].Table;\r
+                       _columns = relatedColumns;\r
+                       _keyValues = keyValues;\r
+\r
+                       UpdateIndex(true);\r
+               }\r
+\r
+               #endregion // Constructors\r
+\r
+               #region Methods\r
+\r
+               internal override IExpression FilterExpression {\r
+                       get {\r
+                               return this;\r
+                       }\r
+               }\r
+\r
+\r
+               #endregion // Methods\r
+\r
+               #region IExpression Members\r
+\r
+               public object Eval(DataRow row) {\r
+                       return EvalBoolean(row);\r
+               }\r
+\r
+               public bool EvalBoolean(DataRow row) {\r
+                       for (int i = 0; i < _columns.Length; i++)\r
+                               if (!row[_columns[i]].Equals(_keyValues[i]))\r
+                                       return false;\r
+\r
+                       IExpression filter = base.FilterExpression;\r
+                       return filter != null ? filter.EvalBoolean(row) : true;\r
+               }\r
+\r
+               public bool DependsOn(DataColumn other) {\r
+                       for (int i = 0; i < _columns.Length; i++)\r
+                               if (_columns[i] == other)\r
+                                       return true;\r
+\r
+                       IExpression filter = base.FilterExpression;\r
+                       return filter != null ? filter.DependsOn(other) : false;\r
+               }\r
+\r
+               #endregion\r
+       }\r
+}\r
diff --git a/mcs/class/System.Data/System.Data/Res.cs b/mcs/class/System.Data/System.Data/Res.cs
new file mode 100644 (file)
index 0000000..e9e799a
--- /dev/null
@@ -0,0 +1,155 @@
+namespace System.Data\r
+{\r
+\r
+    using java.util;\r
+\r
+    using System.Globalization;\r
+    //using clr.System;\r
+\r
+    public class Res\r
+    {\r
+        private static readonly String FILE_NAME = "SystemData";\r
+        private static readonly ResourceBundle _resource =\r
+            ResourceBundle.getBundle(FILE_NAME);\r
+\r
+        public static String GetString(String name, Object[] args)\r
+        {\r
+            return GetString(null, name, args);\r
+        }\r
+\r
+        public static String GetString(CultureInfo culture, String name, Object[] args)\r
+        {\r
+            try\r
+            {\r
+                String str = _resource.getString(name);\r
+                if (args != null && (int) args.Length > 0)\r
+                {\r
+                    return String.Format(str, args);\r
+                }\r
+                else\r
+                {\r
+                    return str;\r
+                }\r
+            }\r
+            catch (MissingResourceException)\r
+            {\r
+                return null;\r
+            }\r
+        }\r
+\r
+        public static String GetString(String name)\r
+        {\r
+            return GetString(null, name);\r
+        }\r
+\r
+        public static String GetString(CultureInfo culture, String name)\r
+        {\r
+            try\r
+            {\r
+                return _resource.getString(name);\r
+            }\r
+            catch (MissingResourceException)\r
+            {\r
+                return null;\r
+            }\r
+        }\r
+\r
+        public static bool GetBoolean(String name)\r
+        {\r
+            return GetBoolean(name);\r
+        }\r
+\r
+        public static bool GetBoolean(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return false;\r
+        }\r
+\r
+        public static char GetChar(String name)\r
+        {\r
+            return GetChar(null, name);\r
+        }\r
+\r
+        public static char GetChar(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return (char)0;\r
+        }\r
+\r
+        public static int GetByte(String name)\r
+        {\r
+            return GetByte(null, name);\r
+        }\r
+\r
+        public static int GetByte(CultureInfo culture, String name)\r
+        {\r
+            return 0;\r
+        }\r
+\r
+        public static short GetShort(String name)\r
+        {\r
+            return GetShort(null, name);\r
+        }\r
+\r
+        public static short GetShort(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return 0;\r
+        }\r
+\r
+        public static int GetInt(String name)\r
+        {\r
+            return GetInt(null, name);\r
+        }\r
+\r
+        public static int GetInt(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return 0;\r
+        }\r
+\r
+        public static long GetLong(String name)\r
+        {\r
+            return GetLong(null, name);\r
+        }\r
+\r
+        public static long GetLong(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return 0;\r
+        }\r
+\r
+        public static float GetFloat(String name)\r
+        {\r
+            return GetFloat(null, name);\r
+        }\r
+\r
+        public static float GetFloat(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return 0.0f;\r
+        }\r
+\r
+        public static double GetDouble(String name)\r
+        {\r
+            return GetDouble(null, name);\r
+        }\r
+\r
+        public static double GetDouble(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return 0.0;\r
+        }\r
+\r
+        public static Object GetObject(String name)\r
+        {\r
+            return GetObject(null, name);\r
+        }\r
+\r
+        public static Object GetObject(CultureInfo culture, String name)\r
+        {\r
+            // This online demo only decompiles 10 methods in each class\r
+            return null;\r
+        }\r
+    }\r
+}
\ No newline at end of file
index ac082c963b01e79b748e612eebedcea7c6efe0f4..d1cbd99b283c9812e9afdd922db3506efae95aee 100644 (file)
@@ -37,6 +37,7 @@ using System;
 using System.Collections;
 using System.ComponentModel;
 using System.Runtime.InteropServices;
+using System.Data.Common;
 
 namespace System.Data {
        [Editor]
@@ -45,9 +46,10 @@ namespace System.Data {
        public class UniqueConstraint : Constraint 
        {
                private bool _isPrimaryKey = false;
-               private bool __isPrimaryKey = false;
+               private bool _belongsToCollection = false;
                private DataTable _dataTable; //set by ctor except when unique case
                
+               //FIXME: create a class which will wrap this collection
                private DataColumn [] _dataColumns;
 
                //TODO:provide helpers for this case
@@ -103,12 +105,12 @@ namespace System.Data {
                {
                         _dataColsNotValidated = true;
                                                                                                     
-                        //keep list of names to resolve later
-                        _dataColumnNames = columnNames;
-                                                                                                    
-                        base.ConstraintName = name;
-                                                                                                    
-                        _isPrimaryKey = isPrimaryKey;
+            //keep list of names to resolve later
+            _dataColumnNames = columnNames;
+                                                                                        
+            base.ConstraintName = name;
+                                                                                        
+            _isPrimaryKey = isPrimaryKey;
 
                }
 
@@ -122,15 +124,13 @@ namespace System.Data {
                        //Set Constraint Name
                        base.ConstraintName = name;
 
-                       __isPrimaryKey = isPrimaryKey;
+                       _isPrimaryKey = isPrimaryKey;
 
                        //keep reference 
                        _dataColumns = new DataColumn [] {column};
                        
                        //Get table reference
-                       _dataTable = column.Table;
-
-                       
+                       _dataTable = column.Table;                      
                }
 
                //helpter ctor  
@@ -148,9 +148,7 @@ namespace System.Data {
                        _dataColumns = columns;
 
                        //PK?
-                       __isPrimaryKey = isPrimaryKey;
-
-                       
+                       _isPrimaryKey = isPrimaryKey;                   
                }
                
                #endregion // Constructors
@@ -207,20 +205,6 @@ namespace System.Data {
                                throw new ArgumentException ("Column must belong to a table.");                 
                }
 
-               /// <summary>
-               ///  If IsPrimaryKey is set to be true, this sets it true
-               /// </summary>
-               internal void UpdatePrimaryKey ()
-               {
-                       _isPrimaryKey = __isPrimaryKey;
-                       // if unique constraint defined on single column
-                       // the column becomes unique
-                       if (_dataColumns.Length == 1){
-                               // use SetUnique - because updating Unique property causes loop
-                               _dataColumns[0].SetUnique();
-                       }
-               }
-
                internal static void SetAsPrimaryKey(ConstraintCollection collection, UniqueConstraint newPrimaryKey)
                {
                        //not null
@@ -267,47 +251,43 @@ namespace System.Data {
                        if (null == collection) throw new ArgumentNullException("Collection can't be null.");
                        if (null == columns ) return null;
                        
-                       UniqueConstraint uniqueConstraint;
-                       IEnumerator enumer = collection.GetEnumerator();
-                       while (enumer.MoveNext())
-                       {
-                               uniqueConstraint = enumer.Current as UniqueConstraint;
-                               if (uniqueConstraint != null)
-                               {
-                                       if ( DataColumn.AreColumnSetsTheSame(uniqueConstraint.Columns, columns) )
-                                       {
-                                               return uniqueConstraint;
+                       foreach(Constraint constraint in collection) {
+                               if (constraint is UniqueConstraint) {
+                                       UniqueConstraint uc = constraint as UniqueConstraint;
+                                       if ( DataColumn.AreColumnSetsTheSame(uc.Columns, columns) ) {
+                                               return uc;
                                        }
                                }
                        }
                        return null;
                }
 
-                internal bool DataColsNotValidated {
-                        
-                       get { return (_dataColsNotValidated); 
+               internal bool DataColsNotValidated 
+               {               
+                       get { 
+                               return (_dataColsNotValidated); 
                        }
-                }
+                }
 
                // Helper Special Ctor
-                // Set the _dataTable property to the table to which this instance is bound when AddRange()
-                // is called with the special constructor.
-                // Validate whether the named columns exist in the _dataTable
-                internal void PostAddRange( DataTable _setTable ) {
-                
+        // Set the _dataTable property to the table to which this instance is bound when AddRange()
+        // is called with the special constructor.
+        // Validate whether the named columns exist in the _dataTable
+        internal void PostAddRange( DataTable _setTable ) 
+               {                
                        _dataTable = _setTable;
-                        DataColumn []cols = new DataColumn [_dataColumnNames.Length];
-                        int i = 0;
-                        foreach ( string _columnName in _dataColumnNames ){
-                                 if ( _setTable.Columns.Contains (_columnName) ){
-                                        cols [i] = _setTable.Columns [_columnName];
-                                        i++;
-                                        continue;
-                                }
-                                throw( new InvalidConstraintException ( "The named columns must exist in the table" ));
-                        }
-                        _dataColumns = cols;
-                }
+            DataColumn []cols = new DataColumn [_dataColumnNames.Length];
+            int i = 0;
+            foreach ( string _columnName in _dataColumnNames ) {
+                if ( _setTable.Columns.Contains (_columnName) ) {
+                                       cols [i] = _setTable.Columns [_columnName];
+                                       i++;
+                                       continue;
+                               }
+                               throw( new InvalidConstraintException ( "The named columns must exist in the table" ));
+            }
+            _dataColumns = cols;
+        }
 
                        
                #endregion //Helpers
@@ -324,7 +304,12 @@ namespace System.Data {
                [DataCategory ("Data")]
                [DataSysDescription ("Indicates if this constraint is a primary key.")]
                public bool IsPrimaryKey {
-                       get { return _isPrimaryKey; }
+                       get { 
+                               if (Table == null || (!_belongsToCollection)) {
+                                       return false;
+                               }
+                               return _isPrimaryKey; 
+                       }
                }
 
                [DataCategory ("Data")]
@@ -373,10 +358,12 @@ namespace System.Data {
                        return hash ;
                }
                
-               [MonoTODO]
                internal override void AddToConstraintCollectionSetup(
                                ConstraintCollection collection)
                {
+                       for (int i = 0; i < Columns.Length; i++)
+                               if (Columns[i].Table != collection.Table)
+                                       throw new ArgumentException("These columns don't point to this table.");
                        //run Ctor rules again
                        _validateColumns(_dataColumns);
                        
@@ -386,111 +373,120 @@ namespace System.Data {
                                        " columns. Existing ConstraintName is " + uc.ConstraintName);
 
                        //Allow only one primary key
-                       if (this.IsPrimaryKey)
-                       {
+                       if (this.IsPrimaryKey) {
                                uc = GetPrimaryKeyConstraint(collection);
                                if (null != uc) uc._isPrimaryKey = false;
+                       }
 
+                       // if constraint is based on one column only
+                       // this column becomes unique
+                       if (_dataColumns.Length == 1) {
+                               _dataColumns[0].SetUnique();
                        }
                                        
                        //FIXME: ConstraintCollection calls AssertContraint() again rigth after calling
                        //this method, so that it is executed twice. Need to investigate which
                        // call to remove as that migth affect other parts of the classes.
-                       AssertConstraint();
+                       //AssertConstraint();
+                       if (IsConstraintViolated())
+                               throw new ArgumentException("These columns don't currently have unique values.");
+
+                       _belongsToCollection = true;
                }
                                        
                
                internal override void RemoveFromConstraintCollectionCleanup( 
                                ConstraintCollection collection)
                {
-                       Index index = this.Index;
-                       this.Index = null;
-                       // if a foreign key constraint references the same index - 
-                       // change the index be to not unique.
-                       // In this case we can not just drop the index
-                       ICollection fkCollection = collection.ForeignKeyConstraints;
-                       foreach (ForeignKeyConstraint fkc in fkCollection) {
-                               if (index == fkc.Index) {
-                                       fkc.Index.SetUnique (false);
-                                       // this is not referencing the index anymore
-                                       return;
-                               }
-                       }
-                       
-                       // if we are here no one is using this index so we can remove it.
-                       // There is no need calling drop index here
-                       // since two unique constraints never references the same index
-                       // and we already check that there is no foreign key constraint referencing it.
-                       Table.RemoveIndex (index);
+                       _belongsToCollection = false;
+                       Index index = Index;
+                       Index = null;
                }
 
-               [MonoTODO]
-               internal override void AssertConstraint()
-               {                       
-                       if (_dataTable == null) return; //???
-                       if (_dataColumns == null) return; //???         
-                       
-                       Index fromTableIndex = null;
+               protected override bool IsConstraintViolated()
+               {       
                        if (Index == null) {
-                               fromTableIndex = Table.GetIndexByColumns (Columns);
-                               if (fromTableIndex == null) {
-                                       Index = new Index (ConstraintName, _dataTable, _dataColumns, true);     
-                               }
-                               else {
-                                       fromTableIndex.SetUnique (true);
-                                       Index = fromTableIndex;
-                               }
+                               Index = Table.GetIndex(Columns,null,DataViewRowState.None,null,false);
                        }
 
-                       try {
-                               Table.InitializeIndex (Index);
-                       }
-                       catch (ConstraintException) {
-#if NET_1_1
-                               throw;
-#else
-                               Index = null;
-                               throw new ArgumentException (String.Format ("Column '{0}' contains non-unique values", this._dataColumns[0]));
-#endif
+                       if (Index.HasDuplicates) {
+                               int[] dups = Index.Duplicates;
+                               for (int i = 0; i < dups.Length; i++){
+                                       DataRow row = Table.RecordCache[dups[i]];
+                                       ArrayList columns = new ArrayList();
+                                       ArrayList values = new ArrayList();
+                                       foreach (DataColumn col in Columns){
+                                               columns.Add(col.ColumnName);
+                                               values.Add(row[col].ToString());
+                                       }
+
+                                       string columnNames = String.Join(",", (string[])columns.ToArray(typeof(string)));
+                                       string columnValues = String.Join(",", (string[])values.ToArray(typeof(string)));
+
+                                       row.RowError = String.Format("Column(s) '{0}' are constrained to be unique.  Value(s) '{1}' are already present", columnNames, columnValues);
+                               }
+                               // FIXME : check the exception to be thrown here
+                               // throw new ConstraintException("These columns don't currently have unique values");
+                               //throw new ConstraintException ("Failed to enable constraints. One or more rows contain values violating non-null, unique, or foreign-key constraints.");
+                               return true;
                        }
-                       
-                       // if there is no index with same columns - add the new index to the table.
-                       if (fromTableIndex == null)
-                               Table.AddIndex (Index);
+
+                       return false;
                }
 
-               [MonoTODO]
                internal override void AssertConstraint(DataRow row)
-               {
-                       if (_dataTable == null) return; //???
-                       if (_dataColumns == null) return; //???
+               {       
+                       if (IsPrimaryKey && row.HasVersion(DataRowVersion.Default)) {
+                               for (int i = 0; i < Columns.Length; i++) {
+                                       if (row.IsNull(Columns[i])) {
+                                               throw new NoNullAllowedException("Column '" + Columns[i].ColumnName + "' does not allow nulls.");
+                                       }
+                               }
+                       }
                        
                        if (Index == null) {
-                               Index = Table.GetIndexByColumns (Columns, true);
-                               if (Index == null) {
-                                       Index = new Index (ConstraintName, _dataTable, _dataColumns, true);
-                                       Table.AddIndex (Index);
-                               }
+                               Index = Table.GetIndex(Columns,null,DataViewRowState.None,null,false);
                        }
 
-                       if (IsPrimaryKey) {
-                               object val;
-                               for (int i = 0; i < _dataColumns.Length; i++) {
-                                        if (row.RowState == DataRowState.Deleted)
-                                                val = row.GetValue (i, DataRowVersion.Original);
-                                        else
-                                                val = row.GetValue (i, DataRowVersion.Default);
-                                       if (val == null || val == DBNull.Value)
-                                               throw new NoNullAllowedException("Column '" + _dataColumns[i].ColumnName + "' does not allow nulls.");
-                               }
+                       if (Index.HasDuplicates) {
+                               throw new ConstraintException(GetErrorMessage(row));
                        }
+               }
 
-                       try {
-                               UpdateIndex (row);
+               internal override bool IsColumnContained(DataColumn column)
+               {
+                       for (int i = 0; i < _dataColumns.Length; i++)
+                               if (column == _dataColumns[i])
+                                       return true;
+
+                       return false;
+               }
+
+               internal override bool CanRemoveFromCollection(ConstraintCollection col, bool shouldThrow){
+                       if (Equals(col.Table.PrimaryKey)){
+                               if (shouldThrow)
+                                       throw new ArgumentException("Cannot remove unique constraint since it's the primary key of a table.");
+
+                               return false;
                        }
-                       catch (ConstraintException) {
-                               throw new ConstraintException(GetErrorMessage(row));
+
+                       if (Table.DataSet != null){
+                               foreach (DataTable table in Table.DataSet.Tables){
+                                       foreach (Constraint constraint in table.Constraints){
+                                               if (constraint is ForeignKeyConstraint)
+                                                       if (((ForeignKeyConstraint)constraint).RelatedTable == Table){
+                                                               if (shouldThrow)
+                                                                       throw new ArgumentException(
+                                                                               String.Format("Cannot remove unique constraint '{0}'. Remove foreign key constraint '{1}' first.",
+                                                                               ConstraintName, constraint.ConstraintName)
+                                                                               );
+                                                               return false;
+                                                       }
+                                       }
+                               }
                        }
+
+                       return true;
                }
 
                private string GetErrorMessage(DataRow row)
@@ -498,24 +494,18 @@ namespace System.Data {
                        int i;
                         
                        System.Text.StringBuilder sb = new System.Text.StringBuilder(row[_dataColumns[0]].ToString());
-                       for (i = 1; i < _dataColumns.Length; i++)
+                       for (i = 1; i < _dataColumns.Length; i++) {
                                sb = sb.Append(", ").Append(row[_dataColumns[i].ColumnName]);
+                       }
                        string valStr = sb.ToString();
                        sb = new System.Text.StringBuilder(_dataColumns[0].ColumnName);
-                       for (i = 1; i < _dataColumns.Length; i++)
+                       for (i = 1; i < _dataColumns.Length; i++) {
                                sb = sb.Append(", ").Append(_dataColumns[i].ColumnName);
+                       }
                        string colStr = sb.ToString();
                        return "Column '" + colStr + "' is constrained to be unique.  Value '" + valStr + "' is already present.";
                }
-               
-                internal bool Contains (DataColumn c)
-                {
-                        foreach (DataColumn col in Columns)
-                                if (c == col)
-                                        return true;
-                        return false;
-                }
-                
+                                      
                
                #endregion // Methods
 
index c97b84b98c804c5d335df7224e6420b1a0408f48..f6f1d1616f7933f14af52a0e63ef2b013f68d688 100644 (file)
@@ -30,7 +30,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0
+
 
 namespace System.Data {
        public enum UpdateOptions 
@@ -42,4 +42,4 @@ namespace System.Data {
        }
 }
 
-#endif // NET_2_0
+
index a41afa2e60dcc74f8bac3959cba5eba4308a2865..5cd45b62bb19fbeb08c0912337da724d21013ba1 100755 (executable)
@@ -1,5 +1,5 @@
 // 
-// System.Data/DataSet.cs
+// System.Data/XmlConstants.cs
 //
 // Author:
 //   Stuart Caborn <stuart.caborn@virgin.net>
index f2e04e1084f6b2a4566d9fcf7d959ee9d0f0e046..d5e9747fbd486e708bbcd7630dd99c88449d449a 100755 (executable)
@@ -118,30 +118,30 @@ namespace System.Data
                        return GetColumn (name) != null;\r
                }\r
 \r
-               public DataColumn GetColumn (string name)
-               {
-                       foreach (DataColumn col in Elements)
-                               if (col.ColumnName == name)
-                                       return col;
-                       foreach (DataColumn col in Attributes)
-                               if (col.ColumnName == name)
-                                       return col;
-                       if (SimpleContent != null && name == SimpleContent.ColumnName)
-                               return SimpleContent;
-                       if (PrimaryKey != null && name == PrimaryKey.ColumnName)
-                               return PrimaryKey;
-                       return null;
-               }
-
-               public void RemoveElementColumn (string name)
-               {
-                       foreach (DataColumn col in Elements) {
-                               if (col.ColumnName == name) {
-                                       Elements.Remove (col);
-                                       return;
-                               }
-                       }
-               }
+               public DataColumn GetColumn (string name)\r
+               {\r
+                       foreach (DataColumn col in Elements)\r
+                               if (col.ColumnName == name)\r
+                                       return col;\r
+                       foreach (DataColumn col in Attributes)\r
+                               if (col.ColumnName == name)\r
+                                       return col;\r
+                       if (SimpleContent != null && name == SimpleContent.ColumnName)\r
+                               return SimpleContent;\r
+                       if (PrimaryKey != null && name == PrimaryKey.ColumnName)\r
+                               return PrimaryKey;\r
+                       return null;\r
+               }\r
+\r
+               public void RemoveElementColumn (string name)\r
+               {\r
+                       foreach (DataColumn col in Elements) {\r
+                               if (col.ColumnName == name) {\r
+                                       Elements.Remove (col);\r
+                                       return;\r
+                               }\r
+                       }\r
+               }\r
        }\r
 \r
        internal class XmlDataInferenceLoader\r
index abf4e5692c27214258ec54f13ba4aeb51d086f91..cef1ef44e5dd04f764376d440ab1d6440d02663a 100755 (executable)
@@ -1,27 +1,27 @@
-
-//
-// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
-//
-// Permission is hereby granted, free of charge, to any person obtaining
-// a copy of this software and associated documentation files (the
-// "Software"), to deal in the Software without restriction, including
-// without limitation the rights to use, copy, modify, merge, publish,
-// 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
-// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
-// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
-// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
-// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-//
-
+\r
+//\r
+// Copyright (C) 2004 Novell, Inc (http://www.novell.com)\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
 using System;\r
 using System.IO;\r
 using System.Data;\r
@@ -107,10 +107,10 @@ namespace System.Data
                        bool savedEnforceConstraints =\r
                                dataset.EnforceConstraints;\r
                        try {\r
-                               dataset.EnforceConstraints = false;\r
-                               reader.MoveToContent ();\r
+                       dataset.EnforceConstraints = false;\r
+                       reader.MoveToContent ();\r
 \r
-                               if (mode == XmlReadMode.Fragment) {\r
+                       if (mode == XmlReadMode.Fragment) {\r
                                        while (reader.NodeType == XmlNodeType.Element && !reader.EOF) {\r
                                                ReadTopLevelElement ();\r
                                        }\r
@@ -153,16 +153,16 @@ namespace System.Data
                                reader.Skip ();\r
                        else if (mode == XmlReadMode.Fragment ||\r
                                IsTopLevelDataSet ()) {\r
-                               int depth = reader.Depth;\r
-                               reader.Read ();\r
-                               reader.MoveToContent ();\r
-                               do {\r
-                                       ReadDataSetContent ();\r
-                               } while (reader.Depth > depth && !reader.EOF);\r
-                               if (reader.NodeType == XmlNodeType.EndElement)\r
-                                       reader.ReadEndElement ();\r
-                               reader.MoveToContent ();\r
-                       }\r
+                       int depth = reader.Depth;\r
+                       reader.Read ();\r
+                       reader.MoveToContent ();\r
+                       do {\r
+                               ReadDataSetContent ();\r
+                       } while (reader.Depth > depth && !reader.EOF);\r
+                       if (reader.NodeType == XmlNodeType.EndElement)\r
+                               reader.ReadEndElement ();\r
+                       reader.MoveToContent ();\r
+               }\r
                        else\r
                                ReadDataSetContent ();\r
                }\r
index 76a0adfa97241b9876d187697b64ee5a68940e8e..13ef898fdaaac0b737cedbb358b12eb31ddfa83e 100644 (file)
@@ -118,7 +118,7 @@ namespace System.Data {
                private void LoadCurrent (XmlReader reader) 
                {
                        if (reader.IsEmptyElement) {
-                               reader.Skip ();
+                               reader.Skip();
                                return;
                        }
                        reader.ReadStartElement ();             // Dataset root