Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/mcs
diff options
context:
space:
mode:
authorAtsushi Eno <atsushieno@gmail.com>2005-02-02 00:09:00 +0300
committerAtsushi Eno <atsushieno@gmail.com>2005-02-02 00:09:00 +0300
commit65a8962295f56e25320b68d360b41697cc01a87b (patch)
treee43e6c963f6ef73e765776e8e7632e895e10e7a9 /mcs
parent41a5c19ed998a4be9b85c1fb48a0794254330f9a (diff)
2005-02-01 Atsushi Enomoto <atsushi@ximian.com>
* DataView.cs : Mostly reimplemented. - UpdateIndex() is invoked only when it is required (results in significant performance improvement). - Use SortedList and wrapper OptionalSortedList which switches between SortedList (with Sort) and UnsortedList (without Sort). - DataView itself now contains two collections for rowviews: Table rows based pool and AddNew() based cache. Consider those two collections in every members. - Reset() does not clear rows. Just invokes UpdateIndex(). - Hook RowDeleting, ColumnChanging and ColumnChanged events in table which is required to handle state changes. - Reimplemented Find() and FindRows() because of internal changes. svn path=/trunk/mcs/; revision=39945
Diffstat (limited to 'mcs')
-rw-r--r--mcs/class/System.Data/System.Data/ChangeLog15
-rw-r--r--mcs/class/System.Data/System.Data/DataView.cs709
2 files changed, 544 insertions, 180 deletions
diff --git a/mcs/class/System.Data/System.Data/ChangeLog b/mcs/class/System.Data/System.Data/ChangeLog
index 3d94114bfa5..55e7e9eceae 100644
--- a/mcs/class/System.Data/System.Data/ChangeLog
+++ b/mcs/class/System.Data/System.Data/ChangeLog
@@ -1,5 +1,20 @@
2005-02-01 Atsushi Enomoto <atsushi@ximian.com>
+ * DataView.cs : Mostly reimplemented.
+ - UpdateIndex() is invoked only when it is required (results in
+ significant performance improvement).
+ - Use SortedList and wrapper OptionalSortedList which switches
+ between SortedList (with Sort) and UnsortedList (without Sort).
+ - DataView itself now contains two collections for rowviews:
+ Table rows based pool and AddNew() based cache. Consider those
+ two collections in every members.
+ - Reset() does not clear rows. Just invokes UpdateIndex().
+ - Hook RowDeleting, ColumnChanging and ColumnChanged events in table
+ which is required to handle state changes.
+ - Reimplemented Find() and FindRows() because of internal changes.
+
+2005-02-01 Atsushi Enomoto <atsushi@ximian.com>
+
* DataTable.cs : Fixed row comparer. Even if every of the sort target
columns are identical for two rows, they should not be regarded as
the same unless they are Object.ReferenceEquals.
diff --git a/mcs/class/System.Data/System.Data/DataView.cs b/mcs/class/System.Data/System.Data/DataView.cs
index aaeffa28ab5..2a21a3e0f9e 100644
--- a/mcs/class/System.Data/System.Data/DataView.cs
+++ b/mcs/class/System.Data/System.Data/DataView.cs
@@ -5,12 +5,17 @@
// 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;
@@ -36,10 +41,9 @@ namespace System.Data
string sort = "";
SortableColumn [] sortedColumns = null;
DataViewRowState rowState;
- DataRowView[] rowCache = new DataRowView[0];
// DataRow -> DataRowView
- Hashtable addNewCache = new Hashtable ();
- Hashtable rowViewPool = new Hashtable ();
+ ListDictionary addNewCache = new ListDictionary ();
+ OptionalSortedList rowViewPool = new OptionalSortedList ();
bool allowNew = true;
bool allowEdit = true;
@@ -53,6 +57,13 @@ namespace System.Data
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 ()
{
@@ -134,12 +145,7 @@ namespace System.Data
[DefaultValue (false)]
[RefreshProperties (RefreshProperties.All)]
public bool ApplyDefaultSort {
- [MonoTODO]
- get {
- return applyDefaultSort;
- }
-
- [MonoTODO]
+ get { return applyDefaultSort; }
set {
if (applyDefaultSort == value)
return;
@@ -163,19 +169,13 @@ namespace System.Data
[Browsable (false)]
[DataSysDescription ("Returns the number of items currently in this view.")]
public int Count {
- [MonoTODO]
- get {
- return rowCache.Length;
- }
+ 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 {
- [MonoTODO]
- get {
- return dataViewManager;
- }
+ get { return dataViewManager; }
}
// Item indexer
@@ -183,9 +183,18 @@ namespace System.Data
// this IndexerNameAttribute
[System.Runtime.CompilerServices.IndexerName("Item")]
public DataRowView this[int recordIndex] {
- [MonoTODO]
get {
- return rowCache [recordIndex];
+ if (recordIndex >= rowViewPool.Count + addNewCache.Count)
+ throw new IndexOutOfRangeException ();
+
+ if (recordIndex < rowViewPool.Count)
+ return (DataRowView) rowViewPool.GetByIndex (recordIndex);
+ IEnumerator e = addNewCache.GetEnumerator ();
+ int to = recordIndex - rowViewPool.Count;
+ for (int i = 0; i <= to; i++)
+ if (!e.MoveNext ())
+ throw new IndexOutOfRangeException ();
+ return (DataRowView) (((DictionaryEntry) e.Current).Value);
}
}
@@ -193,12 +202,7 @@ namespace System.Data
[DataSysDescription ("Indicates an expression used to filter the data returned by this DataView.")]
[DefaultValue ("")]
public virtual string RowFilter {
- [MonoTODO]
- get {
- return rowFilter;
- }
-
- [MonoTODO]
+ get { return rowFilter; }
set {
if (value == null)
value = String.Empty;
@@ -220,12 +224,7 @@ namespace System.Data
[DataSysDescription ("Indicates the versions of data returned by this DataView.")]
[DefaultValue (DataViewRowState.CurrentRows)]
public DataViewRowState RowStateFilter {
- [MonoTODO]
- get {
- return rowState;
- }
-
- [MonoTODO]
+ get { return rowState; }
set {
if (value == rowState)
return;
@@ -239,12 +238,7 @@ namespace System.Data
[DataSysDescription ("Indicates the order in which data is returned by this DataView.")]
[DefaultValue ("")]
public string Sort {
- [MonoTODO]
- get {
- return sort;
- }
-
- [MonoTODO]
+ get { return sort; }
set {
if (value == sort)
return;
@@ -282,12 +276,7 @@ namespace System.Data
[RefreshProperties (RefreshProperties.All)]
[TypeConverter (typeof (DataTableTypeConverter))]
public DataTable Table {
- [MonoTODO]
- get {
- return dataTable;
- }
-
- [MonoTODO]
+ get { return dataTable; }
set {
if (value != null && value.TableName.Equals("")) {
throw new DataException("Cannot bind to DataTable with no name.");
@@ -321,17 +310,9 @@ namespace System.Data
throw new SystemException ("Row not created");
DataRowView rowView = new DataRowView (this, row, true);
addNewCache.Add (row, rowView);
- rowViewPool.Add (row, rowView);
-
- // Add to the end of the list (i.e. recreate rowCache),
- // regardless of Sort property.
- DataRowView [] newCache = new DataRowView [rowCache.Length + 1];
- rowCache.CopyTo (newCache, 0);
- newCache [newCache.Length - 1] = rowView;
- rowCache = newCache;
// DataRowView is added, but DataRow is still Detached.
- OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, newCache.Length - 1, -1));
+ OnListChanged (new ListChangedEventArgs (ListChangedType.ItemAdded, rowViewPool.Count + addNewCache.Count - 1, -1));
return rowView;
}
@@ -342,10 +323,10 @@ namespace System.Data
// FIXME:
}
- [MonoTODO]
public void CopyTo (Array array, int index)
{
- rowCache.CopyTo (array, index);
+ rowViewPool.CopyTo (array, index);
+ addNewCache.CopyTo (array, index + rowViewPool.Count);
}
public void Delete(int index)
@@ -355,10 +336,10 @@ namespace System.Data
if (!AllowDelete)
throw new DataException ("Cannot delete on a DataSource where AllowDelete is false.");
- if (index > rowCache.Length)
+ if (index > rowViewPool.Count + addNewCache.Count)
throw new IndexOutOfRangeException ("There is no row at " +
"position: " + index + ".");
- DataRowView row = rowCache [index];
+ DataRowView row = this [index];
row.Row.Delete ();
}
@@ -379,59 +360,79 @@ namespace System.Data
internal void CancelEditRowView (DataRowView rowView)
{
- addNewCache.Remove (rowView.Row);
- rowViewPool.Remove (rowView.Row);
- // FIXME: it should not be required. MS does not do it.
- UpdateIndex ();
+ if (addNewCache.Contains (rowView))
+ addNewCache.Remove (rowView.Row);
+ else
+ rowViewPool.Remove (rowView.Row);
rowView.Row.CancelEdit ();
}
internal void DeleteRowView (DataRowView rowView)
{
- addNewCache.Remove (rowView.Row);
- rowViewPool.Remove (rowView.Row);
- // FIXME: it should not be required. MS does not do it.
- UpdateIndex ();
+ if (addNewCache.Contains (rowView))
+ addNewCache.Remove (rowView.Row);
+ else
+ rowViewPool.Remove (rowView.Row);
rowView.Row.Delete ();
}
internal void EndEditRowView (DataRowView rowView)
{
- if (rowView.Row.RowState == DataRowState.Detached)
- Table.Rows.Add (rowView.Row);
+ 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);
}
- public int Find(object key)
+ private IExpression [] PrepareExpr (object [] key)
{
- object [] keys = new object[1];
- keys[0] = key;
- return Find(keys);
+ 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)
{
- int index;
- if (sort == null || sort == string.Empty)
- throw new ArgumentException ("Find finds a row based on a Sort order, and no Sort order is specified");
- else {
- // FIXME: maybe some of those thecks could be removed.
- 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 ("Expecting " + sortedColumns.Length +
- " value(s) from the key being indexed, but recieved "+
- key.Length+" value(s).");
- RowViewComparer rowComparer = new RowViewComparer (dataTable,sortedColumns);
- int searchResult = Array.BinarySearch (rowCache,key,rowComparer);
- if (searchResult < 0)
- return -1;
- else
- return searchResult;
+ 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)
@@ -439,57 +440,51 @@ namespace System.Data
return FindRows (new object [] {key});
}
- public DataRowView[] FindRows (object[] key)
+ public DataRowView [] FindRows (object[] key)
{
- if (Sort == String.Empty)
- throw new ArgumentException ("Find method depends on an explicit Sort property value.");
- 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]));
+ IExpression [] compExpr = PrepareExpr (key);
// Find first match.
int r = 0;
- for (; r < rowCache.Length; r++) {
- if (!compExpr [0].EvalBoolean (rowCache [r].Row))
+ IEnumerator e = GetEnumerator ();
+ bool hasNext = false;
+ while (e.MoveNext ()) {
+ if (!hasNext)
+ hasNext = true;
+ if (!compExpr [0].EvalBoolean (((DataRowView) e.Current).Row))
continue;
break;
}
- if (r == rowCache.Length) // no match
- return new DataRowView [0];
-
- bool finish = false;
- int start = r;
+ ArrayList al = new ArrayList ();
// Find first no-match from here.
- for (; r < rowCache.Length; r++) {
+ do {
+ if (!hasNext)
+ break;
+ bool finish = false;
for (int c = 0; c < key.Length; c++) {
- if (!compExpr [c].EvalBoolean (rowCache [r].Row)) {
+ if (!compExpr [c].EvalBoolean (((DataRowView) e.Current).Row)) {
finish = true;
break;
}
}
if (finish)
break;
- }
-
- DataRowView [] ret = new DataRowView [r - start];
- for (int i = 0; i < ret.Length; i++)
- ret [i] = rowCache [start + i];
+ al.Add (e.Current);
+ } while (e.MoveNext ());
- return ret;
+ return (DataRowView []) al.ToArray (typeof (DataRowView));
}
public IEnumerator GetEnumerator()
{
- return new DataViewEnumerator (rowCache);
+ 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
- [MonoTODO]
[DataCategory ("Data")]
[DataSysDescription ("Indicates the data returned by this DataView has somehow changed.")]
public event ListChangedEventHandler ListChanged;
@@ -497,18 +492,14 @@ namespace System.Data
[Browsable (false)]
[DataSysDescription ("Indicates whether the view is open.")]
protected bool IsOpen {
- [MonoTODO]
- get {
- return isOpen;
- }
+ get { return isOpen; }
}
- [MonoTODO]
- protected void Close()
+ protected void Close ()
{
if (dataTable != null)
UnregisterEventHandlers ();
- rowCache = new DataRowView [0];
+ rowViewPool.Clear ();
isOpen = false;
}
@@ -539,9 +530,11 @@ namespace System.Data
ListChanged (this, e);
}
- [MonoTODO]
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
@@ -569,7 +562,10 @@ namespace System.Data
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(OnColumnCollectionChanged);
dataTable.Constraints.CollectionChanged += new CollectionChangeEventHandler(OnConstraintCollectionChanged);
@@ -577,44 +573,95 @@ namespace System.Data
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(OnColumnCollectionChanged);
dataTable.Constraints.CollectionChanged -= new CollectionChangeEventHandler(OnConstraintCollectionChanged);
}
-
- private void OnRowChanged(object sender, DataRowChangeEventArgs args)
+
+ // 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)
{
- int oldIndex,newIndex;
- oldIndex = newIndex = -1;
- oldIndex = IndexOf (args.Row);
- // FIXME: it should not be required. MS does not do it.
- UpdateIndex (true);
- newIndex = IndexOf (args.Row);
+ 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) {
- if (oldIndex == newIndex)
- OnListChanged (new ListChangedEventArgs (ListChangedType.ItemChanged, newIndex, -1));
- else
- OnListChanged (new ListChangedEventArgs (ListChangedType.ItemMoved, newIndex, oldIndex));
+ 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)
{
- /* ItemDeleted */
- int newIndex;
- newIndex = IndexOf (args.Row);
- // FIXME: it should not be required. MS does not do it.
- UpdateIndex (true);
- OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, newIndex, -1));
+ OnListChanged (new ListChangedEventArgs (ListChangedType.ItemDeleted, deletedIndex, -1));
}
private void OnColumnCollectionChanged (object sender, CollectionChangeEventArgs args)
@@ -656,8 +703,9 @@ namespace System.Data
protected void Reset()
{
// TODO: what really happens?
- Close ();
- rowCache = new DataRowView[0];
+ if (IsOpen)
+ Close ();
+ UpdateIndex (true);
Open ();
OnListChanged (new ListChangedEventArgs (ListChangedType.Reset, -1 ));
}
@@ -690,9 +738,8 @@ namespace System.Data
// into the DataTable's DataRowCollection.
//
// I assume this is what UpdateIndex is used for
- protected virtual void UpdateIndex(bool force)
+ protected virtual void UpdateIndex (bool force)
{
- DataRowView[] newRowCache = null;
DataRow[] rows = null;
// I guess, "force" parameter is used to indicate
@@ -702,26 +749,25 @@ namespace System.Data
// Handle sort by itself, considering AddNew rows.
rows = dataTable.Select (rowFilterExpr, null, RowStateFilter);
- DataRow [] tmp = new DataRow [rows.Length + addNewCache.Count];
- rows.CopyTo (tmp, 0);
- addNewCache.Keys.CopyTo (tmp, rows.Length);
- rows = tmp;
+
+ OptionalSortedList newPool = null;
if (sortedColumns != null)
- new DataTable.RowSorter (dataTable, sortedColumns).SortRows (rows);
+ newPool = new OptionalSortedList (
+ dataTable,
+ sortedColumns,
+ rows.Length + 3);
+ else
+ newPool = new OptionalSortedList (rows.Length + 3);
- newRowCache = new DataRowView [rows.Length];
- Hashtable newPool = rowViewPool.Count > 0 ? new Hashtable (rows.Length + 2) : rowViewPool;
for (int r = 0; r < rows.Length; r++) {
DataRow dr = rows [r];
DataRowView rv = (DataRowView) rowViewPool [dr];
- if (rv == null) {
+ if (rv == null)
rv = new DataRowView (this, dr);
- newPool.Add (dr, rv);
- }
- newRowCache[r] = rv;
+ newPool.Add (dr, rv);
}
+
rowViewPool = newPool;
- rowCache = newRowCache;
}
[MonoTODO]
@@ -818,7 +864,7 @@ namespace System.Data
DataRowView drv = value as DataRowView;
if (drv == null)
return false;
- return IndexOf (drv) >= 0;
+ return rowViewPool.Contains (drv) || addNewCache.Contains (drv);
}
int IList.IndexOf (object value)
@@ -826,7 +872,7 @@ namespace System.Data
DataRowView drv = value as DataRowView;
if (drv == null)
return -1;
- return IndexOf (drv);
+ return IndexOfRowView (drv);
}
void IList.Insert (int index,object value)
@@ -843,7 +889,7 @@ namespace System.Data
void IList.RemoveAt (int index)
{
- DataRowView drv = rowCache [index]; // might raise OutOfRangeException here.
+ DataRowView drv = this [index]; // might raise OutOfRangeException here.
if (drv == null)
throw new ArgumentException ("Cannot remove from this list.");
drv.Delete ();
@@ -952,20 +998,32 @@ namespace System.Data
}
#endregion // IBindingList implementation
- private int IndexOf (DataRowView drv)
+ private int IndexOfRowView (DataRowView drv)
{
- for (int i = 0; i < rowCache.Length; i++)
- if (rowCache [i] == drv)
- return i;
+ 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 IndexOf(DataRow dr)
+ private int IndexOfRow (DataRow dr)
{
- for (int i=0; i < rowCache.Length; i++)
- if (dr.Equals (rowCache [i].Row))
- return i;
- return -1;
+ 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 string GetSortString (UniqueConstraint uc)
@@ -1010,9 +1068,7 @@ namespace System.Data
public bool MoveNext ()
{
- // TODO: how do you determine
- // if a collection has been
- // changed?
+ // It does not care about collection being changed.
if (on < rows.Length - 1) {
on++;
return true;
@@ -1025,12 +1081,12 @@ namespace System.Data
on = -1;
}
}
-
- private class RowViewComparer : IComparer
+
+ private class RowViewFindComparer : IComparer
{
private SortableColumn [] sortColumns;
private DataTable table;
- public RowViewComparer (DataTable table, SortableColumn[] sortColumns)
+ public RowViewFindComparer (DataTable table, SortableColumn[] sortColumns)
{
this.table = table;
this.sortColumns = sortColumns;
@@ -1096,4 +1152,297 @@ namespace System.Data
}
}
+
+ 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);
+ }
+ }
}