// Tim Coleman <tim@timcoleman.com>
// Ville Palo <vi64pa@koti.soon.fi>
// Alan Tam Siu Lung <Tam@SiuLung.com>
+// Sureshkumar T <tsureshkumar@novell.com>
//
// (C) Ximian, Inc 2002
// (C) Daniel Morgan 2002, 2003
//
using System;
+using System.Data.Common;
using System.Collections;
using System.Globalization;
using System.Xml;
}
}
+ /// <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
+ /// or the default value will be used.
+ /// </summary>
+ internal void SetValue (int column, object value, int version)
+ {
+ DataColumn dc = Table.Columns[column];
+
+ if (value == null && ! dc.AutoIncrement) // set default value / auto increment
+ value = dc.DefaultValue;
+
+ Table.ChangingDataColumn (this, dc, value);
+ CheckValue (value, dc);
+ if ( ! dc.AutoIncrement)
+ dc [version] = value;
+ else if (_proposed >= 0 && _proposed != version) // proposed holds the AI
+ dc [version] = dc [_proposed];
+ }
+
/// <summary>
/// Gets the data stored in the column, specified by index and version of the data to
/// retrieve.
object o = column.CompiledExpression.Eval (this);
return Convert.ChangeType (o, column.DataType);
}
+
+ 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];
}
-
- 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.");
throw new VersionNotFoundException (Locale.GetText ("There is no " + version.ToString () + " data to access."));
}
}
}
+ internal bool IsEditing {
+ get { return editing; }
+ }
+
/// <summary>
/// Gets the current state of the row in regards to its relationship to the
/// DataRowCollection.
}
}
- #endregion
+ #endregion // Properties
#region Methods
internal void SetValuesFromDataRecord(IDataRecord record, int[] mapping)
{
- if ( mapping.Length > Table.Columns.Count)
- throw new ArgumentException ();
-
// bool orginalEditing = editing;
// if (!orginalEditing) {
// BeginEdit ();
}
try {
- for(int i=0; i < mapping.Length; i++) {
+ 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));
DataColumn column = _table.Columns[columnName];
_table.ChangingDataColumn (this, column, val);
- if (_original < 0 || _original == _current) {
- // really add a row cache, if _original is not there &
- // make row modified
+ if (_original < 0 || _original == _current) {
+ // This really creates a new record version if one does not exist
_original = Table.RecordCache.NewRecord();
}
CheckValue (val, column);
throw new RowNotInTableException("Cannot perform this operation on a row not in the table.");
}
// Accept from detached
- if (_original >= 0) {
- Table.RecordCache.DisposeRecord(_original);
- }
- _original = _current;
+ if (_original != _current)
+ Original = Current;
}
/// <summary>
/// </summary>
public DataRow[] GetChildRows (DataRelation relation)
{
- return GetChildRows (relation, DataRowVersion.Current);
+ return GetChildRows (relation, DataRowVersion.Default);
}
/// <summary>
if (relation == null)
return new DataRow[0];
- if (this.Table == null || RowState == DataRowState.Detached)
+ //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.");
if (relation.DataSet != this.Table.DataSet)
throw new ArgumentException();
+ if (_table != relation.ParentTable)
+ throw new InvalidConstraintException ("GetChildRow requires a row whose Table is " + relation.ParentTable + ", but the specified row's table is " + _table);
+
if (relation.ChildKeyConstraint != null)
return GetChildRows (relation.ChildKeyConstraint, version);
}
if (allColumnsMatch) rows.Add(row);
}
- }
+ }else
+ throw new VersionNotFoundException("There is no " + version + " data to accces.");
+
DataRow[] result = relation.ChildTable.NewRowArray(rows.Count);
rows.CopyTo(result, 0);
return result;
}
}
else { // if there is no index we search manualy.
- int curIndex = IndexFromVersion(DataRowVersion.Current);
+ int curIndex = IndexFromVersion(DataRowVersion.Default);
int tmpRecord = fkc.Table.RecordCache.NewRecord();
try {
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);
/// </summary>
public DataRow GetParentRow (DataRelation relation)
{
- return GetParentRow (relation, DataRowVersion.Current);
+ return GetParentRow (relation, DataRowVersion.Default);
}
/// <summary>
/// </summary>
public DataRow GetParentRow (string relationName)
{
- return GetParentRow (relationName, DataRowVersion.Current);
+ return GetParentRow (relationName, DataRowVersion.Default);
}
/// <summary>
/// </summary>
public DataRow[] GetParentRows (DataRelation relation)
{
- return GetParentRows (relation, DataRowVersion.Current);
+ return GetParentRows (relation, DataRowVersion.Default);
}
/// <summary>
/// </summary>
public DataRow[] GetParentRows (string relationName)
{
- return GetParentRows (relationName, DataRowVersion.Current);
+ return GetParentRows (relationName, DataRowVersion.Default);
}
/// <summary>
if (relation == null)
return new DataRow[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.");
if (relation.DataSet != this.Table.DataSet)
throw new ArgumentException();
+ if (_table != relation.ChildTable)
+ throw new InvalidConstraintException ("GetParentRows requires a row whose Table is " + relation.ChildTable + ", but the specified row's table is " + _table);
+
ArrayList rows = new ArrayList();
DataColumn[] parentColumns = relation.ParentColumns;
DataColumn[] childColumns = relation.ChildColumns;
int numColumn = parentColumns.Length;
if (HasVersion(version)) {
Index indx = relation.ParentTable.GetIndexByColumns (parentColumns);
- if (indx != null) { // get the child rows from the index
+ 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.Current);
+ int curIndex = IndexFromVersion(DataRowVersion.Default);
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.
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);
/// </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;
- }
+ 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;
}
/// </summary>
public void SetParentRow (DataRow parentRow, DataRelation relation)
{
- if (_table == null || parentRow.Table == null || RowState == DataRowState.Detached)
+ if (_table == null || parentRow.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.");
if (parentRow != null && _table.DataSet != parentRow.Table.DataSet)
{
foreach (DataRelation parentRel in _table.ParentRelations)
{
- DataColumn[] childCols = parentRel.ChildKeyConstraint.Columns;
- DataColumn[] parentCols = parentRel.ChildKeyConstraint.RelatedColumns;
+ DataColumn[] childCols = parentRel.ChildColumns;
+ DataColumn[] parentCols = parentRel.ParentColumns;
for (int i = 0; i < parentCols.Length; i++)
{
}
else
{
- DataColumn[] childCols = relation.ChildKeyConstraint.Columns;
- DataColumn[] parentCols = relation.ChildKeyConstraint.RelatedColumns;
+ DataColumn[] childCols = relation.ChildColumns;
+ DataColumn[] parentCols = relation.ParentColumns;
for (int i = 0; i < parentCols.Length; i++)
{
}
//Saving the current value as the column value
- row[index] = targetColumn[row._current];
-
+ object defaultVal = column [IndexFromVersion (DataRowVersion.Default)];
+ row [index] = defaultVal;
}
}
CopyState(row);
}
#endregion // Methods
+
+#if NET_2_0
+ /// <summary>
+ /// This method loads a given value into the existing row affecting versions,
+ /// state based on the LoadOption. The matrix of changes for this method are as
+ /// mentioned in the DataTable.Load (IDataReader, LoadOption) method.
+ /// </summary>
+ [MonoTODO ("Raise necessary Events")]
+ internal void Load (object [] values, LoadOption loadOption, bool is_new)
+ {
+ DataRowAction action = DataRowAction.Change;
+
+ int temp = Table.RecordCache.NewRecord ();
+ for (int i = 0 ; i < Table.Columns.Count; i++)
+ SetValue (i, values [i], temp);
+
+ if (is_new) { // new row
+ if (editing || RowState == DataRowState.Detached)
+ Proposed = temp;
+ else
+ Current = temp;
+ return;
+ }
+
+ if (loadOption == LoadOption.OverwriteChanges
+ || (loadOption == LoadOption.PreserveChanges
+ && rowState == DataRowState.Unchanged)) {
+ Original = temp;
+ if (editing)
+ Proposed = temp;
+ else
+ Current = temp;
+ rowState = DataRowState.Unchanged;
+ action = DataRowAction.ChangeCurrentAndOriginal;
+ return;
+ }
+
+ if (loadOption == LoadOption.PreserveChanges) {
+ if (rowState != DataRowState.Deleted) {
+ Original = temp;
+ rowState = DataRowState.Modified;
+ action = DataRowAction.ChangeOriginal;
+ }
+ return;
+ }
+
+ bool not_used = true;
+ // Upsert
+ if (rowState != DataRowState.Deleted) {
+ int index = editing ? _proposed : _current;
+ if (! RecordCache.CompareRecords (Table, index, temp)) {
+ if (editing)
+ Proposed = temp;
+ else
+ Current = temp;
+ not_used = false;
+ if (rowState == DataRowState.Unchanged)
+ rowState = DataRowState.Modified;
+ }
+ }
+
+ if (not_used)
+ Table.RecordCache.DisposeRecord (temp);
+ }
+#endif // NET_2_0
}