+2006-07-14 Senganal T <tsenganal@novell.com>
+
+ * DataTable.cs :
+ - Merge - Implement the merge methods
+ - Clone - Ensure column's DateTimeMode property is also copied
+ * DataColumn.cs :
+ - DateTimeMode : Implemement
+ - DataTypeMatches : Added. In 2.0 profile, test DateTime
+ property when verifying column types.
+ * DataRelation.cs :
+ - ctr : For DateTime columns, check DateTimeMode property
+ * ForeignKeyConstraint.cs :
+ - _validateColumns : For DateTime columns, check DateTimeMode
+ property
+ * MergeManager :
+ - Merge : Added. Overload to merge two tables
+ - ResolveColumns : Change the method to use a table instead of
+ a DataSet
+ - Renamed AdjustSchema to AdjustSchemaRelations
+
2006-07-13 Senganal T <tsenganal@novell.com>
* DataSet.cs :
}\r
}\r
\r
+#if NET_2_0\r
+ DataSetDateTime _datetimeMode = DataSetDateTime.UnspecifiedLocal;\r
+ [DefaultValue (DataSetDateTime.UnspecifiedLocal)]\r
+ [RefreshProperties (RefreshProperties.All)]\r
+ public DataSetDateTime DateTimeMode {\r
+ get { return _datetimeMode; }\r
+ set {\r
+ if (DataType != typeof (DateTime))\r
+ throw new InvalidOperationException ("The DateTimeMode can be set only on DataColumns of type DateTime.");\r
+ \r
+ if (!Enum.IsDefined (typeof (DataSetDateTime), value))\r
+ throw new InvalidEnumArgumentException ("The DataSetDateTime enumeration value, " + \r
+ (int)value + ", is invalid.");\r
+ \r
+ if (_datetimeMode == value)\r
+ return;\r
+ if (_table == null || _table.Rows.Count == 0) {\r
+ _datetimeMode = value;\r
+ return;\r
+ }\r
+ if ((_datetimeMode == DataSetDateTime.Unspecified || _datetimeMode == DataSetDateTime.UnspecifiedLocal)\r
+ && (value == DataSetDateTime.Unspecified || value == DataSetDateTime.UnspecifiedLocal)) {\r
+ _datetimeMode = value;\r
+ return;\r
+ }\r
+\r
+ throw new InvalidOperationException ( String.Format (\r
+ "Cannot change DateTimeMode from '{0}' to '{1}' " +\r
+ "once the table has data.",_datetimeMode, value));\r
+ }\r
+ }\r
+#endif\r
+\r
[DataCategory ("Data")]\r
#if !NET_2_0\r
[DataSysDescription ("Indicates whether null values are allowed in this column.")]\r
throw new InvalidConstraintException ("Cannot change datatype, " + \r
"when column is part of a relation");\r
\r
+#if NET_2_0\r
+ if (_dataContainer != null && _dataContainer.Type == typeof (DateTime))\r
+ _datetimeMode = DataSetDateTime.UnspecifiedLocal;\r
+#endif\r
_dataContainer = AbstractDataContainer.CreateInstance(value, this);\r
\r
//Check AutoIncrement status, make compatible datatype\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
+#if NET_2_0\r
+ if (DataType == typeof (DateTime))\r
+ copy.DateTimeMode = _datetimeMode;\r
+#endif\r
\r
return copy;\r
}\r
if (_compiledExpression != null)\r
_compiledExpression.ResetExpression ();\r
}\r
+\r
+ internal bool DataTypeMatches (DataColumn col)\r
+ {\r
+ if (DataType != col.DataType)\r
+ return false;\r
+#if NET_2_0\r
+ if (DataType != typeof (DateTime))\r
+ return true;\r
+\r
+ if (DateTimeMode == col.DateTimeMode)\r
+ return true;\r
+ \r
+ if (DateTimeMode == DataSetDateTime.Local || DateTimeMode == DataSetDateTime.Utc)\r
+ return false;\r
+\r
+ if (col.DateTimeMode == DataSetDateTime.Local || col.DateTimeMode == DataSetDateTime.Utc)\r
+ return false;\r
+#endif\r
+ return true;\r
+ }\r
#endregion // Methods\r
}\r
}\r
throw new InvalidConstraintException ();
for (int i=0; i<ChildColumns.Length; i++)
- if (!( parentColumns[i].DataType.Equals( childColumns[i].DataType)))
- throw new InvalidConstraintException();
+ if (!parentColumns[i].DataTypeMatches (childColumns[i]))
+ throw new InvalidConstraintException("Parent Columns and Child Columns don't have " +
+ "matching column types");
}
[MonoTODO]
[MonoTODO]\r
public void Merge (DataTable table)\r
{\r
- throw new NotImplementedException ();\r
+ Merge (table, false, MissingSchemaAction.Add);\r
}\r
\r
[MonoTODO]\r
public void Merge (DataTable table, bool preserveChanges)\r
{\r
- throw new NotImplementedException ();\r
+ Merge (table, preserveChanges, MissingSchemaAction.Add);\r
}\r
\r
[MonoTODO]\r
public void Merge (DataTable table, bool preserveChanges, MissingSchemaAction missingSchemaAction)\r
{\r
- throw new NotImplementedException ();\r
+ MergeManager.Merge (this, table, preserveChanges, missingSchemaAction);\r
}\r
#endif\r
\r
if (pc == cc)
throw new InvalidOperationException("Parent and child columns can't be the same column.");
- if (! pc.DataType.Equals(cc.DataType))
- {
+ if (!pc.DataTypeMatches (cc)) {
//LAMESPEC: spec says throw InvalidConstraintException
// implementation throws InvalidOperationException
- throw new InvalidConstraintException("Parent column is not type compatible with it's child"
+ throw new InvalidOperationException ("Parent column is not type compatible with it's child"
+ " column.");
}
}
foreach (DataTable t in sourceSet.Tables)
MergeManager.Merge(targetSet, t, preserveChanges, missingSchemaAction);
- AdjustSchema(targetSet,sourceSet,missingSchemaAction);
+ AdjustSchemaRelations (targetSet, sourceSet, missingSchemaAction);
targetSet.EnforceConstraints = prevEC;
}
}
}
+ internal static void Merge (DataTable targetTable,
+ DataTable sourceTable,
+ bool preserveChanges,
+ MissingSchemaAction missingSchemaAction)
+ {
+ if(targetTable== null)
+ throw new ArgumentNullException("targetTable");
+ if(sourceTable == null)
+ throw new ArgumentNullException("sourceTable");
+
+ bool savedEnforceConstraints = targetTable.EnforceConstraints;
+ targetTable.EnforceConstraints = false;
+
+ if (!AdjustSchema(targetTable, sourceTable, missingSchemaAction))
+ return;
+
+ checkColumnTypes(targetTable, sourceTable); // check that the colums datatype is the same
+ fillData(targetTable, sourceTable, preserveChanges);
+
+ targetTable.EnforceConstraints = savedEnforceConstraints;
+ }
+
internal static void Merge(DataSet targetSet, DataRow[] sourceRows, bool preserveChanges, MissingSchemaAction missingSchemaAction)
{
if(targetSet == null)
}
}
-
- // adjust the dataset schema according to the missingschemaaction param
- // (relations).
- // return false if adjusting fails.
- private static bool AdjustSchema(DataSet targetSet, DataSet sourceSet, MissingSchemaAction missingSchemaAction)
+ private static bool AdjustSchemaRelations (DataSet targetSet, DataSet sourceSet, MissingSchemaAction missingSchemaAction)
{
if (missingSchemaAction == MissingSchemaAction.Ignore)
return true;
foreach(DataTable sourceTable in sourceSet.Tables) {
DataTable targetTable = targetSet.Tables[sourceTable.TableName];
- if (targetTable == null)
+ if (targetTable == null)
continue;
-
+
foreach (Constraint constraint in sourceTable.Constraints) {
Constraint targetConstraint = null;
if (uc != null) {
if (uc.IsPrimaryKey || uc.ChildConstraint != null)
continue;
- DataColumn[] columns = ResolveColumns (targetSet, uc.Columns);
+ DataColumn[] columns = ResolveColumns (targetTable, uc.Columns);
targetConstraint = new UniqueConstraint (constraintName, columns, false);
}
ForeignKeyConstraint fc = constraint as ForeignKeyConstraint;
if (fc != null) {
- DataColumn[] columns = ResolveColumns (targetSet, fc.Columns);
- DataColumn[] relatedColumns = ResolveColumns (targetSet, fc.RelatedColumns);
+ DataColumn[] columns = ResolveColumns (targetTable, fc.Columns);
+ DataColumn[] relatedColumns = ResolveColumns (targetSet.Tables [fc.RelatedTable.TableName],
+ fc.RelatedColumns);
targetConstraint = new ForeignKeyConstraint (constraintName, relatedColumns, columns);
}
bool dupConstraintFound = false;
foreach (Constraint cons in targetTable.Constraints) {
- if (!targetConstraint.Equals (cons))
- continue;
- dupConstraintFound = true;
- break;
+ if (!targetConstraint.Equals (cons))
+ continue;
+ dupConstraintFound = true;
+ break;
}
// If equivalent-constraint already exists, then just do nothing
if (targetRelation == null) {
if (missingSchemaAction == MissingSchemaAction.Error)
throw new ArgumentException ("Target DataSet mising definition for " +
- relation.RelationName);
+ relation.RelationName);
- DataColumn[] parentColumns = ResolveColumns (targetSet, relation.ParentColumns);
- DataColumn[] childColumns = ResolveColumns (targetSet, relation.ChildColumns);
+ DataColumn[] parentColumns = ResolveColumns (targetSet.Tables [relation.ParentTable.TableName],
+ relation.ParentColumns);
+ DataColumn[] childColumns = ResolveColumns (targetSet.Tables [relation.ChildTable.TableName],
+ relation.ChildColumns);
targetRelation = targetSet.Relations.Add (relation.RelationName, parentColumns,
- childColumns, false);
+ childColumns, false);
targetRelation.Nested = relation.Nested;
} else if (!CompareColumnArrays (relation.ParentColumns, targetRelation.ParentColumns) ||
!CompareColumnArrays (relation.ChildColumns, targetRelation.ChildColumns)) {
return true;
}
- private static DataColumn[] ResolveColumns(DataSet targetSet, DataColumn[] sourceColumns)
+ private static DataColumn[] ResolveColumns(DataTable targetTable, DataColumn[] sourceColumns)
{
if (sourceColumns != null && sourceColumns.Length > 0) {
// lets just assume that all columns are from the Same table
- DataTable targetTable = targetSet.Tables [sourceColumns[0].Table.TableName];
if (targetTable != null) {
int i=0;
DataColumn[] targetColumns = new DataColumn[sourceColumns.Length];
targetSet.Tables.Add(targetTable);
}
+ AdjustSchema (targetTable, sourceTable, missingSchemaAction);
+
+ newTable = targetTable;
+ return true;
+ }
+
+
+ private static bool AdjustSchema(DataTable targetTable, DataTable sourceTable, MissingSchemaAction missingSchemaAction)
+ {
+ if (missingSchemaAction == MissingSchemaAction.Ignore)
+ return true;
+
for (int i = 0; i < sourceTable.Columns.Count; i++) {
DataColumn sourceColumn = sourceTable.Columns[i];
// if a column from the source table doesn't exists in the target table
// we act according to the missingschemaaction param.
DataColumn targetColumn = targetTable.Columns [sourceColumn.ColumnName];
if(targetColumn == null) {
- if (missingSchemaAction == MissingSchemaAction.Ignore)
- continue;
if (missingSchemaAction == MissingSchemaAction.Error)
throw new DataException ("Target table " + targetTable.TableName +
" missing definition for column " + sourceColumn.ColumnName);
if (!AdjustPrimaryKeys(targetTable, sourceTable))
return false;
- newTable = targetTable;
return true;
}
// If targetTable does not have a PrimaryKey, just import the sourceTable PrimaryKey
if (targetTable.PrimaryKey.Length == 0) {
- DataColumn[] targetColumns = ResolveColumns (targetTable.DataSet, sourceTable.PrimaryKey);
+ DataColumn[] targetColumns = ResolveColumns (targetTable, sourceTable.PrimaryKey);
targetTable.PrimaryKey = targetColumns;
return true;
}
{
DataColumn fromCol = sourceTable.Columns[i];
DataColumn toCol = targetTable.Columns[fromCol.ColumnName];
- if((toCol != null) && (toCol.DataType != fromCol.DataType))
- throw new DataException("<target>." + fromCol.ColumnName + " and <source>." +
- fromCol.ColumnName + " have conflicting properties: DataType " +
- " property mismatch.");
+ if (toCol == null)
+ continue;
+ if (toCol.DataTypeMatches (fromCol))
+ continue;
+ throw new DataException("<target>." + fromCol.ColumnName + " and <source>." +
+ fromCol.ColumnName + " have conflicting properties: DataType " +
+ " property mismatch.");
}
}
private static void RaiseMergeFailedEvent (DataTable targetTable, string errMsg)
{
MergeFailedEventArgs args = new MergeFailedEventArgs (targetTable, errMsg);
- targetTable.DataSet.OnMergeFailed (args);
+ if (targetTable.DataSet != null)
+ targetTable.DataSet.OnMergeFailed (args);
}
}
}
+2006-07-14 Senganal T <tsenganal@novell.com>
+
+ * DataRelationTest2.cs
+ * ForeignKeyConstraintTest2.cs
+ * DataColumnTest2.cs
+ Tests for DateTimeMode property
+ * DataTableTest2.cs
+ Tests for Merge Methods
+
2006-07-13 Senganal T <tsenganal@novell.com>
* DataSetTest2.cs : Test for bug #78842
using NUnit.Framework;
using System;
+using System.ComponentModel;
using System.Data;
using MonoTests.System.Data.Utils;
Assert.AreEqual (10, ptable.Rows [0][1], "#1");
Assert.AreEqual (-1, ptable.Rows [1][1], "#2");
}
+
+#if NET_2_0
+ [Test]
+ public void DateTimeMode_DataType ()
+ {
+ DataColumn col = new DataColumn("col", typeof(int));
+ Assert.AreEqual (DataSetDateTime.UnspecifiedLocal, col.DateTimeMode, "#1");
+ try {
+ col.DateTimeMode = DataSetDateTime.Local;
+ Assert.Fail ("#2");
+ } catch (InvalidOperationException e) {}
+
+ col = new DataColumn ("col", typeof (DateTime));
+ col.DateTimeMode = DataSetDateTime.Utc;
+ Assert.AreEqual (DataSetDateTime.Utc, col.DateTimeMode, "#3");
+ col.DataType = typeof (int);
+ Assert.AreEqual (DataSetDateTime.UnspecifiedLocal, col.DateTimeMode, "#4");
+ }
+
+ [Test]
+ public void DateTimeMode_InvalidValues ()
+ {
+ DataColumn col = new DataColumn("col", typeof(DateTime));
+ try {
+ col.DateTimeMode = (DataSetDateTime)(-1);
+ Assert.Fail("#1");
+ } catch (InvalidEnumArgumentException e) {}
+
+ try {
+ col.DateTimeMode = (DataSetDateTime)5;
+ Assert.Fail("#2");
+ } catch (InvalidEnumArgumentException e) {}
+ }
+
+ [Test]
+ public void DateTimeMode_RowsAdded ()
+ {
+ DataTable table = new DataTable();
+ table.Columns.Add("col", typeof(DateTime));
+ table.Rows.Add(new object[] {DateTime.Now});
+
+ Assert.AreEqual(DataSetDateTime.UnspecifiedLocal, table.Columns[0].DateTimeMode, "#1");
+ // allowed
+ table.Columns[0].DateTimeMode = DataSetDateTime.Unspecified;
+ table.Columns[0].DateTimeMode = DataSetDateTime.UnspecifiedLocal;
+
+ try {
+ table.Columns[0].DateTimeMode = DataSetDateTime.Local;
+ Assert.Fail("#2");
+ } catch (InvalidOperationException e) {}
+
+ try {
+ table.Columns[0].DateTimeMode = DataSetDateTime.Utc;
+ Assert.Fail("#3");
+ } catch (InvalidOperationException e) {}
+ }
+#endif
}
}
// RelationName get/set
Assert.AreEqual("myRelation", dRel.RelationName , "DR63");
}
+
+#if NET_2_0
+ [Test]
+ public void DataRelationTest()
+ {
+ DataSet ds = new DataSet();
+
+ DataTable t1 = new DataTable("t1");
+ t1.Columns.Add("col", typeof(DateTime));
+
+ DataTable t2 = new DataTable("t2");
+ t2.Columns.Add("col", typeof(DateTime));
+ t2.Columns[0].DateTimeMode = DataSetDateTime.Unspecified;
+
+ ds.Tables.Add(t1);
+ ds.Tables.Add(t2);
+ ds.Relations.Add("rel", t1.Columns[0], t2.Columns[0], false);
+
+ ds.Relations.Clear();
+ t2.Columns[0].DateTimeMode = DataSetDateTime.Local;
+
+ try {
+ ds.Relations.Add("rel", t1.Columns[0], t2.Columns[0], false);
+ Assert.Fail ("#1");
+ } catch (InvalidConstraintException) { }
+ }
+#endif
}
}
Assert.AreEqual (6, result [0][0], "# incorrect sorting order");
}
+#if NET_2_0
+
+ [Test]
+ public void DataTable_Clone ()
+ {
+ DataTable table = new DataTable ();
+ table.Columns.Add ("col1", typeof (DateTime));
+ table.Columns [0].DateTimeMode = DataSetDateTime.Local;
+ DataTable table1 = table.Clone ();
+ Assert.AreEqual (DataSetDateTime.Local, table1.Columns [0].DateTimeMode, "#1");
+
+ //Test any other new prop in 2.0
+ }
+
+ [Test]
+ public void Merge_SchemaTest ()
+ {
+ DataTable table1 = new DataTable ("t1");
+ table1.Columns.Add ("col1", typeof (int));
+
+ DataTable table2 = new DataTable ("t2");
+ table2.Columns.Add ("col2", typeof (int));
+
+ DataTable table3;
+
+ table3 = table1.Clone ();
+ table3.Merge (table2);
+ Assert.AreEqual (2, table3.Columns.Count, "#1");
+ table3 = table1.Clone ();
+ table3.Merge (table2, false, MissingSchemaAction.Ignore);
+ Assert.AreEqual (1, table3.Columns.Count, "#2");
+
+ // source constraints are ignored
+ table2.Constraints.Add ("uc", table2.Columns [0], false);
+ table3 = table1.Clone ();
+ table3.Merge (table2);
+ Assert.AreEqual (0, table3.Constraints.Count, "#3");
+
+ // source PK is merged depending on MissingSchemaAction
+ table2.PrimaryKey = new DataColumn[] {table2.Columns[0]};
+ table3 = table1.Clone ();
+ table3.Merge (table2);
+ Assert.AreEqual (1, table3.Constraints.Count, "#4");
+ table3 = table1.Clone ();
+ table3.Merge (table2, false, MissingSchemaAction.Ignore);
+ Assert.AreEqual (0, table3.Constraints.Count, "#5");
+
+ //FIXME : If both source and target have PK, then
+ // shud be the exception raised when schema is merged?
+ // ms.net throws a nullreference exception.
+ // If any data is merged, exception is anyways raised.
+ /*
+ table1.PrimaryKey = new DataColumn[] {table1.Columns[0]};
+ table3 = table1.Clone ();
+ try {
+ table3.Merge(table2);
+ Assert.Fail("#6");
+ } catch (DataException e) {}
+ */
+
+ table3.Merge (table2,false,MissingSchemaAction.Ignore);
+ table1.PrimaryKey = null;
+
+ // DateTime columns, DataType match only if DateTimeMode matches
+ table1.Columns.Add ("col_datetime", typeof (DateTime));
+ table2.Columns.Add ("col_datetime", typeof (DateTime));
+ table1.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.Local;
+ table2.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.Unspecified;
+
+ table3 = table1.Clone ();
+ try {
+ table3.Merge (table2);
+ Assert.Fail ("#7");
+ } catch (DataException) { }
+
+ table1.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.Unspecified;
+ table2.Columns ["col_datetime"].DateTimeMode = DataSetDateTime.UnspecifiedLocal;
+ table3 = table1.Clone ();
+ table3.Merge (table2);
+ Assert.AreEqual (DataSetDateTime.Unspecified, table3.Columns ["col_datetime"].DateTimeMode, "#9");
+ }
+
+
+ [Test]
+ public void Merge_TestData ()
+ {
+ DataTable t1 = new DataTable ("t1");
+ DataTable t2 = new DataTable ("t2");
+
+ t1.Columns.Add ("c1", typeof (int));
+ t1.Columns.Add ("c2", typeof (int));
+ t2.Columns.Add ("c1", typeof (int));
+ t2.Columns.Add ("c2", typeof (int));
+
+ t1.Rows.Add (new object[] {1, 1});
+ t1.Rows.Add (new object[] {2, 2});
+
+ t2.Rows.Add (new object[] {1, 5});
+ t2.Rows.Add (new object[] {1, 10});
+
+ DataTable t3 = t1.Copy ();
+ // When primary key is not defined, rows are not merged.
+ t3.Merge (t2);
+ Assert.AreEqual (4, t3.Rows.Count, "#1");
+
+ t1.PrimaryKey = new DataColumn[] {t1.Columns[0]};
+ t3 = t1.Copy ();
+ t3.Merge (t2);
+ Assert.AreEqual (2, t3.Rows.Count, "#2");
+ Assert.AreEqual (10, t3.Rows [0][1], "#3");
+
+ t3 = t1.Copy ();
+ t3.Merge (t2, true);
+ Assert.AreEqual (2, t3.Rows.Count, "#4");
+ Assert.AreEqual (1, t3.Rows [0][1], "#5");
+ }
+#endif
internal class DataRowsComparer : System.Collections.IComparer\r
{\r
\r
return ds1;\r
}
+#if NET_2_0
+ [Test]
+ public void ForeignConstraint_DateTimeModeTest()
+ {
+ DataTable t1 = new DataTable("t1");
+ t1.Columns.Add("col", typeof(DateTime));
+
+ DataTable t2 = new DataTable("t2");
+ t2.Columns.Add("col", typeof(DateTime));
+ t2.Columns[0].DateTimeMode = DataSetDateTime.Unspecified;
+
+ // DataColumn type shud match, and no exception shud be raised
+ t2.Constraints.Add("fk", t1.Columns[0], t2.Columns[0]);
+
+ t2.Constraints.Clear();
+ t2.Columns[0].DateTimeMode = DataSetDateTime.Local;
+ try {
+ // DataColumn type shud not match, and exception shud be raised
+ t2.Constraints.Add("fk", t1.Columns[0], t2.Columns[0]);
+ Assert.Fail("#1");
+ } catch (InvalidOperationException e) {}
+ }
+#endif
}
}