//
// 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 class RecordCache {
#region Fields
const int MIN_CACHE_SIZE = 128;
Stack _records = new Stack (16);
int _nextFreeIndex = 0;
int _currentCapacity = 0;
DataTable _table;
DataRow [] _rowsToRecords;
#endregion // Fields
#region Constructors
internal RecordCache (DataTable table)
{
_table = table;
_rowsToRecords = table.NewRowArray (16);
}
#endregion //Constructors
#region Properties
internal int CurrentCapacity {
get { return _currentCapacity; }
}
internal DataRow this [int index] {
get { return _rowsToRecords [index]; }
set {
if (index >= 0)
_rowsToRecords [index] = value;
}
}
#endregion // Properties
#region Methods
internal int NewRecord ()
{
if (_records.Count > 0)
return (int) _records.Pop ();
DataColumnCollection cols = _table.Columns;
if (_nextFreeIndex >= _currentCapacity) {
_currentCapacity *= 2;
if (_currentCapacity < MIN_CACHE_SIZE)
_currentCapacity = MIN_CACHE_SIZE;
for (int i = 0; i < cols.Count; ++i)
cols [i].DataContainer.Capacity = _currentCapacity;
DataRow [] old = _rowsToRecords;
_rowsToRecords = _table.NewRowArray (_currentCapacity);
Array.Copy (old, 0, _rowsToRecords, 0, old.Length);
}
return _nextFreeIndex++;
}
internal void DisposeRecord (int index)
{
if (index < 0)
throw new ArgumentException ();
if (!_records.Contains (index))
_records.Push (index);
this [index] = null;
}
// FIXME: This doesn't seem to be the right class to have this method
internal int CopyRecord (DataTable fromTable, int fromRecordIndex, int toRecordIndex)
{
int recordIndex = toRecordIndex;
if (toRecordIndex == -1)
recordIndex = NewRecord ();
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);
throw;
}
}
// FIXME: This doesn't seem to be the right class to have this method
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
}
}
|