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
diff options
context:
space:
mode:
authorBoris Kirzner <borisk@mono-cvs.ximian.com>2005-04-26 21:22:27 +0400
committerBoris Kirzner <borisk@mono-cvs.ximian.com>2005-04-26 21:22:27 +0400
commitcc4891c52cea956a9e30c11df7689f219a760bfa (patch)
tree0ee15f72b5ae1a26aafcfa7a1d6f887c8e4b608a /mcs/class/System.Data/System.Data.Common
parent13b3fc466db93c7f78b7541fd5e596de0a9b777f (diff)
Drop of Mainsoft.System.Data
svn path=/branches/Mainsoft.System.Data/mcs/; revision=43607
Diffstat (limited to 'mcs/class/System.Data/System.Data.Common')
-rw-r--r--mcs/class/System.Data/System.Data.Common/AbstractDBCommand.cs751
-rw-r--r--mcs/class/System.Data/System.Data.Common/AbstractDBConnection.cs1158
-rw-r--r--mcs/class/System.Data/System.Data.Common/AbstractDBParameter.cs259
-rw-r--r--mcs/class/System.Data/System.Data.Common/AbstractDataReader.cs1179
-rw-r--r--mcs/class/System.Data/System.Data.Common/AbstractTransaction.cs152
-rw-r--r--mcs/class/System.Data/System.Data.Common/CallableStatementWrapper.cs320
-rw-r--r--mcs/class/System.Data/System.Data.Common/DbConvert.cs330
-rw-r--r--mcs/class/System.Data/System.Data.Common/DbMetaDataCache.cs60
-rw-r--r--mcs/class/System.Data/System.Data.Common/DbPortResolver.cs107
-rw-r--r--mcs/class/System.Data/System.Data.Common/DbStringManager.cs56
-rw-r--r--mcs/class/System.Data/System.Data.Common/DbTypes.cs74
-rw-r--r--mcs/class/System.Data/System.Data.Common/ExceptionHelper.cs224
-rw-r--r--mcs/class/System.Data/System.Data.Common/Index.cs653
-rw-r--r--mcs/class/System.Data/System.Data.Common/JDCConnection.cs271
-rw-r--r--mcs/class/System.Data/System.Data.Common/JDCConnectionDriver.cs63
-rw-r--r--mcs/class/System.Data/System.Data.Common/JDCConnectionPool.cs88
-rw-r--r--mcs/class/System.Data/System.Data.Common/Key.cs226
-rw-r--r--mcs/class/System.Data/System.Data.Common/ParameterMetadataWrapper.cs70
-rw-r--r--mcs/class/System.Data/System.Data.Common/ReaderCache.cs659
19 files changed, 6700 insertions, 0 deletions
diff --git a/mcs/class/System.Data/System.Data.Common/AbstractDBCommand.cs b/mcs/class/System.Data/System.Data.Common/AbstractDBCommand.cs
new file mode 100644
index 00000000000..51746512183
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/AbstractDBCommand.cs
@@ -0,0 +1,751 @@
+//namespace System.Data.Common
+//{
+//
+// using java.sql;
+// using java.util;
+//
+// using System;
+// using System.Collections;
+// using System.Data;
+// using System.Data.ProviderBase;
+//
+// /**
+// * @author erand
+// */
+// public abstract class AbstractDBCommand : DbCommandBase
+// {
+// protected String _cmdText, _javaCmdText;
+// protected AbstractDBConnection _connection;
+// protected IDbTransaction _transaction;
+// protected int _cmdTimeout = 30;
+// protected CommandType _cmdType = CommandType.Text;
+// protected UpdateRowSource _updateRowSource = UpdateRowSource.Both;
+// protected Statement _statement;
+// protected IDataParameterCollection _paramCollection;
+// protected IDataReader _reader;
+// private bool _isCommandTextChanged;
+// private CommandBehavior _behvior = CommandBehavior.Default;
+//
+// private static readonly int _oracleRefCursor;
+// protected const int oracleTypeRefCursor = 1111; // Types.OTHER
+//
+//
+// static AbstractDBCommand()
+// {
+// try {
+// java.lang.Class OracleTypesClass = java.lang.Class.forName("oracle.jdbc.OracleTypes");
+// _oracleRefCursor = OracleTypesClass.getField("CURSOR").getInt(null);
+// }
+// catch(java.lang.ClassNotFoundException e) {
+// // oracle driver is not in classpath - just continue
+// }
+// }
+//
+// public AbstractDBCommand(
+// String cmdText,
+// AbstractDBConnection connection,
+// IDbTransaction transaction)
+// {
+// _connection = connection;
+// _cmdText = cmdText;
+// _transaction = transaction;
+// _isCommandTextChanged = true;
+// }
+//
+// public java.sql.Statement Statement
+// {
+// get
+// {
+// return _statement;
+// }
+// set
+// {
+// _statement = value;
+// }
+// }
+//
+// public virtual String JavaCommandText
+// {
+// get
+// {
+// return _javaCmdText;
+// }
+// set
+// {
+// _javaCmdText = value;
+// }
+// }
+//
+// protected bool getCommandTextChanged()
+// {
+// return _isCommandTextChanged;
+// }
+//
+// internal void setCommandTextChanged(bool value)
+// {
+// _isCommandTextChanged = value;
+// }
+//
+// public Statement getStatement()
+// {
+// return _statement;
+// }
+// /**
+// * @see System.Data.IDbCommand#Cancel()
+// */
+// public override void Cancel()
+// {
+// try
+// {
+// if (_statement != null)
+// _statement.cancel();
+// }
+// catch (SQLException exp)
+// {
+// Console.WriteLine(exp);
+// }
+// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#ExecuteScalar()
+//// */
+//// public virtual Object ExecuteScalar()
+//// {
+//// Object result = null;
+//// IDataReader reader = ((IDbCommand)this).ExecuteReader();
+////
+//// if (reader != null && reader.Read())
+//// {
+//// result = ((IDataRecord) reader).GetValue(0);
+//// }
+//// reader.Close();
+////
+//// return result;
+//// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#CommandTimeout
+//// */
+//// public virtual int CommandTimeout
+//// {
+//// get
+//// {
+//// return _cmdTimeout;
+//// }
+//// set
+//// {
+//// _cmdTimeout = value;
+//// }
+//// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#CommandType
+//// */
+//// public virtual CommandType CommandType
+//// {
+//// get
+//// {
+//// return _cmdType;
+//// }
+//// set
+//// {
+//// _cmdType = value;
+//// }
+//// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#Connection
+//// */
+//// public virtual IDbConnection Connection
+//// {
+//// get
+//// {
+//// return (IDbConnection)_connection;
+//// }
+//// set
+//// {
+//// _connection = (AbstractDBConnection) value;
+//// }
+//// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#Transaction
+//// */
+//// public virtual IDbTransaction Transaction
+//// {
+//// get
+//// {
+//// return _transaction;
+//// }
+//// set
+//// {
+//// _transaction = value;
+//// }
+//// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#UpdatedRowSource
+//// */
+//// public virtual UpdateRowSource UpdatedRowSource
+//// {
+//// get
+//// {
+//// return _updateRowSource;
+//// }
+//// set
+//// {
+//// _updateRowSource = value;
+//// }
+//// }
+//
+//// /**
+//// * @see System.Data.IDbCommand#CommandText
+//// */
+//// public virtual String CommandText
+//// {
+//// get
+//// {
+//// return _cmdText;
+//// }
+//// set
+//// {
+//// if (_cmdText == null || String.Compare(_cmdText, value, true) != 0)
+//// {
+//// _cmdText = value;
+//// _isCommandTextChanged = true;
+//// }
+//// }
+//// }
+//
+// protected virtual void setInputForStatement(
+// PreparedStatement stm,
+// int javaType,
+// int place,
+// Object value)
+// //throws SQLException
+// {
+// // by the type of the the parameter we know wich method of
+// // the statement to use
+//
+// if (value is DBNull)
+// stm.setNull(place, javaType);
+//
+// else if (javaType == Types.BINARY)
+// stm.setBytes(place, vmw.common.TypeUtils.ToSByteArray((byte[]) value));
+//
+// else if (javaType == Types.BLOB)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.CLOB)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.DISTINCT)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.ARRAY)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.JAVA_OBJECT)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.REF)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.STRUCT)
+// stm.setObject(place, value);
+//
+// else if (javaType == Types.VARBINARY)
+// stm.setBytes(place, vmw.common.TypeUtils.ToSByteArray((byte[]) value));
+//
+// else if (javaType == Types.BIGINT)
+// stm.setLong(place, ((java.lang.Long) value).longValue());
+//
+// else if (javaType == Types.BIT)
+// stm.setBoolean(place, ((java.lang.Boolean) value).booleanValue());
+//
+// else if (javaType == Types.CHAR)
+// stm.setString(place, ((java.lang.Character) value).toString());
+//
+// else if (javaType == Types.DATE)
+// {
+// DateTime tmp = (DateTime) value;
+// Calendar c = vmw.common.DateTimeUtils.DateTimeToCalendar(tmp);
+// stm.setDate(
+// place, new java.sql.Date(c.getTime().getTime()));
+// }
+// else if (javaType == Types.DECIMAL || javaType == Types.NUMERIC)
+// stm.setBigDecimal(place, vmw.common.PrimitiveTypeUtils.DecimalToBigDecimal((Decimal) value));
+//
+// else if (javaType == Types.DOUBLE)
+// stm.setDouble(place, ((java.lang.Double) value).doubleValue());
+//
+// else if (javaType == Types.FLOAT)
+// stm.setFloat(place, ((java.lang.Float) value).floatValue());
+//
+// else if (javaType == Types.INTEGER)
+// stm.setInt(place, ((java.lang.Integer) value).intValue());
+//
+// else if (javaType == Types.LONGVARCHAR)
+// stm.setString(place, (String) value);
+//
+// else if (javaType == Types.LONGVARBINARY)
+// stm.setBytes(place, vmw.common.TypeUtils.ToSByteArray((byte[]) value));
+//
+// else if (javaType == Types.REAL)
+// stm.setFloat(place, ((java.lang.Float) value).floatValue());
+//
+// else if (javaType == Types.SMALLINT)
+// stm.setShort(place, ((java.lang.Short) value).shortValue());
+//
+// else if (javaType == Types.TIME)
+// {
+// Calendar c = vmw.common.DateTimeUtils.DateTimeToCalendar(value);
+// stm.setTime(
+// place,
+// new java.sql.Time(c.getTime().getTime()));
+// }
+// else if (javaType == Types.TIMESTAMP)
+// {
+// DateTime tmp = (DateTime) value;
+// Calendar c = vmw.common.DateTimeUtils.DateTimeToCalendar(value);
+// stm.setTimestamp(
+// place,
+// new java.sql.Timestamp(c.getTime().getTime()));
+// }
+//
+// else if (javaType == Types.TINYINT)
+// stm.setByte(place, ((java.lang.Byte) value).byteValue());
+//
+// else if (javaType == Types.VARCHAR)
+// stm.setString(place, (String) value);
+//
+// else
+// stm.setObject(place, value, javaType);
+//
+// }
+//
+// // create the _javaCmdText from the _cmdText (the .NET text)
+// protected String createCommandForStoreProcedure(String text)
+// {
+// IDbDataParameter param;
+// bool isFirst = true;
+// IList paramCollection = (IList) ((IDbCommand)this).Parameters;
+//
+// //in .Net the name of sore procedure can be wraped by '[' and ']'
+// // so we remove them.
+// int indx1 = text.IndexOf('[');
+// if (indx1 != -1)
+// {
+// int indx2 = text.IndexOf(']', indx1);
+// if (indx2 != -1)
+// text = text.Substring(indx1 + 1, indx2 - (indx1 + 1));
+// }
+//
+// java.lang.StringBuffer sb = new java.lang.StringBuffer(text);
+// sb.insert(0, "{call ");
+//
+// for (int i = 0; i < paramCollection.Count; i++)
+// {
+// param = (IDbDataParameter) paramCollection[i];
+//
+// if (param.Direction == ParameterDirection.ReturnValue)
+// sb = sb.insert(1, "? =");
+// else if (isFirst)
+// {
+// sb = sb.append("(?");
+// isFirst = false;
+// }
+// else
+// sb = sb.append(",?");
+// }
+//
+// String retVal = sb.toString();
+//
+// if (retVal.IndexOf("(") != -1)
+// retVal = retVal + ")";
+//
+// retVal += "}";
+//
+// _javaCmdText = retVal;
+//
+// return retVal;
+//
+// }
+//
+// // prepare the input and output parameters for the jdbc prepared statement
+// // from the SqlParameters of this instance
+// internal virtual void prepareStatementForStoreProcedure()// throws SQLException
+// {
+// CallableStatement stm = (CallableStatement) _statement;
+// AbstractDBParameter param;
+// IList paramCollection = (IList) ((IDbCommand)this).Parameters;
+// ParameterDirection direction;
+// //int place;
+//
+// // NOTE - we add 1 to the index because in .NET it is zero base
+// // and in jdbc it is one base
+// for (int i = 0; i < paramCollection.Count; i++)
+// {
+// param = (AbstractDBParameter) paramCollection[i];
+// direction = param.Direction;
+//
+// if (direction == ParameterDirection.Input)
+// setInput(stm, i + 1, param);
+// else if (direction == ParameterDirection.Output)
+// {
+// setOutput(stm, i + 1, param);
+// param.setParameterPlace(i + 1);
+// }
+// else if (direction == ParameterDirection.InputOutput)
+// {
+// setInput(stm, i + 1, param);
+// setOutput(stm, i + 1, param);
+// param.setParameterPlace(i + 1);
+// }
+// else if (direction == ParameterDirection.ReturnValue)
+// {
+// setOutput(stm, 1, param);
+// param.setParameterPlace(1);
+// }
+// }
+//
+// }
+//
+// // set input parameter for the statement
+// protected void setInput(
+// PreparedStatement stm,
+// int place,
+// AbstractDbParameter param)
+// //throws SQLException
+// {
+// int javaType = param.JdbcType;
+// Object value = param.Value;
+//
+// value = getJavaWrapperFromCSharp(value);
+//
+// setInputForStatement(stm, javaType, place, value);
+// }
+//
+// public static Object getJavaWrapperFromCSharp(Object obj)
+// {
+// if (obj is bool)
+// return new java.lang.Boolean((bool)obj);
+// else if (obj is byte)
+// return new java.lang.Byte((sbyte)obj);
+// else if (obj is char)
+// return new java.lang.Character((char) obj);
+// else if (obj is short)
+// return new java.lang.Short((short)obj);
+// else if (obj is int)
+// return new java.lang.Integer((int)obj);
+// else if (obj is long)
+// return new java.lang.Long((long)obj);
+// else if (obj is float)
+// return new java.lang.Float((float)obj);
+// else if (obj is double)
+// return new java.lang.Double((double)obj);
+//
+// return obj;
+//
+// }
+//
+// // set an output parameter to the statement.
+// protected void setOutput(
+// CallableStatement stm,
+// int place,
+// AbstractDbParameter param)
+// //throws SQLException
+// {
+// int javaType = param.JdbcType;
+//
+// // the scale has a meening only in DECIMAL parameters
+// if (javaType == Types.DECIMAL || javaType == Types.NUMERIC)
+// {
+// if(param.DbType == DbType.Currency)
+// stm.registerOutParameter(place, javaType, 4);
+// else
+// stm.registerOutParameter(place, javaType, param.Scale);
+// }
+// else if (javaType == oracleTypeRefCursor) {
+// stm.registerOutParameter(place, _oracleRefCursor);
+// }
+// else {
+// stm.registerOutParameter(place, javaType);
+// }
+//
+// }
+//
+// // get the the output parameter for a specific statement at a specific place
+// // returns the value of the output parameter
+// protected Object getOutputValue(
+// AbstractDbParameter param,
+// CallableStatement stm)
+// //throws SQLException
+// {
+// Object retVal = null;
+//
+// int place = param.getParameterPlace();
+//
+// // by the type of the parameter we know wich method to use
+// // on the statement
+// int type = param.JdbcType;
+//
+// if (type == Types.ARRAY)
+// retVal = stm.getObject(place);
+// else if (type == Types.BIGINT)
+// retVal = stm.getLong(place);
+// else if (type == Types.BINARY)
+// retVal = stm.getBytes(place);
+// else if (type == Types.BIT)
+// retVal = stm.getBoolean(place);
+// else if (type == Types.BLOB)
+// retVal = stm.getObject(place);
+// else if (type == Types.CHAR)
+// retVal = stm.getString(place);
+// else if (type == Types.CLOB)
+// retVal = stm.getObject(place);
+// else if (type == Types.DATE)
+// {
+// java.sql.Date date = stm.getDate(place);
+// if(date != null)
+// {
+// // convertirn sql.Date to DateTime
+// Calendar c = Calendar.getInstance();
+// c.setTime(date);
+//
+// retVal = vmw.common.DateTimeUtils.CalendarToDateTime(c);
+// }
+//
+// }
+// else if (type == Types.DECIMAL)
+// {
+// java.math.BigDecimal bd = stm.getBigDecimal(place);
+// if(bd != null)
+// retVal = vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bd);
+// }
+// else if (type == Types.DISTINCT)
+// retVal = stm.getObject(place);
+// else if (type == Types.DOUBLE)
+// retVal = stm.getDouble(place);
+// else if (type == Types.FLOAT)
+// retVal = stm.getFloat(place);
+// else if (type == Types.INTEGER)
+// retVal = stm.getInt(place);
+// else if (type == Types.JAVA_OBJECT)
+// retVal = stm.getObject(place);
+// else if (type == Types.LONGVARBINARY)
+// retVal = stm.getBytes(place);
+// else if (type == Types.LONGVARCHAR)
+// retVal = stm.getString(place);
+// else if (type == Types.NULL)
+// retVal = DBNull.Value;
+// else if (type == Types.NUMERIC)
+// retVal = stm.getBigDecimal(place);
+// else if (type == Types.OTHER)
+// retVal = stm.getObject(place);
+// else if (type == Types.REAL)
+// retVal = stm.getFloat(place);
+// else if (type == Types.REF)
+// retVal = stm.getObject(place);
+// else if (type == Types.SMALLINT)
+// retVal = stm.getShort(place);
+// else if (type == Types.STRUCT)
+// retVal = stm.getObject(place);
+// else if (type == Types.TIME)
+// {
+// Time t = stm.getTime(place);
+// if(t != null)
+// {
+// java.util.Date d = new java.util.Date(t.getTime());
+// // convertirn sql.Date to DateTime
+// Calendar c = Calendar.getInstance();
+// c.setTime(d);
+//
+// retVal = vmw.common.DateTimeUtils.CalendarToDateTime(c);
+// }
+//
+// }
+// else if (type == Types.TIMESTAMP)
+// {
+// Timestamp ts = stm.getTimestamp(place);
+// if(ts != null)
+// {
+// java.util.Calendar cal = java.util.Calendar.getInstance();
+// cal.setTime(new java.util.Date(ts.getTime() + ts.getNanos()/1000000));
+// retVal = (DateTime)vmw.common.DateTimeUtils.CalendarToDateTime(cal);
+// }
+// }
+// else if (type == Types.TINYINT)
+// retVal = stm.getByte(place);
+// else if (type == Types.VARBINARY)
+// retVal = stm.getBytes(place);
+// else if (type == Types.VARCHAR)
+// retVal = stm.getString(place);
+//
+// if(stm.wasNull())
+// retVal = DBNull.Value;
+//
+// return retVal;
+// }
+//
+//
+//// IDbDataParameter IDbCommand.CreateParameter()
+//// {
+//// return null;
+//// }
+//
+//// IDataReader IDbCommand.ExecuteReader(CommandBehavior behavior)
+//// {
+//// return null;
+//// }
+////
+//// IDataReader IDbCommand.ExecuteReader()
+//// {
+//// return null;
+//// }
+////
+//// int IDbCommand.ExecuteNonQuery()
+//// {
+//// return -1;
+//// }
+////
+//// void IDbCommand.Prepare()
+//// {
+//// }
+//
+//
+//// public IDataParameterCollection Parameters
+//// {
+//// get
+//// {
+//// return _paramCollection;
+//// }
+//// }
+//
+// ~AbstractDBCommand()
+// {
+// Dispose();
+// }
+//
+// public new void Dispose()
+// {
+// if (_paramCollection != null)
+// _paramCollection.Clear();
+//
+// _connection = null;
+// _transaction = null;
+//
+// if (_statement != null)
+// {
+// _statement.close();
+// _statement = null;
+// }
+// base.Dispose();
+// }
+//
+// protected void CheckTrasactionContext()
+// {
+// if (_connection.Transaction != null &&
+// (Transaction == null || Transaction != _connection.Transaction)) {
+// throw new InvalidOperationException("Execute requires the command to have a transaction object" +
+// " when the connection assigned to the command is in a pending local transaction." +
+// " The Transaction property of the command has not been initialized.");
+// }
+// }
+//
+// protected String buildJavaCommand(String command)
+// {
+// IDataParameterCollection parameters = Parameters;
+//
+// if (parameters != null && parameters.Count > 0) {
+// string tokens = command;
+// System.Text.StringBuilder sb = new System.Text.StringBuilder(tokens.Length);
+//
+// int currParameter = 0;
+// int currStart = 0;
+// int curr = 0;
+// char curSeparator = (char)0;
+// bool foundSeparator = false;
+//
+// for(;curr<tokens.Length;curr++) {
+// switch(tokens[curr]) {
+// case '"':
+// case '\'':
+// if (foundSeparator) {
+// if (curSeparator == tokens[curr]) {
+// foundSeparator = false;
+// }
+// }
+// else {
+// // start inner string
+// foundSeparator = true;
+// curSeparator = tokens[curr];
+// }
+// break;
+// case '?':
+// if (!foundSeparator) {
+// if (curr > currStart) {
+// // copy collected
+// sb.Append(tokens,currStart,curr - currStart);
+// }
+// // append parameter value
+// AbstractDBParameter param = (AbstractDBParameter)parameters[currParameter++];
+// sb.Append(param.formatParameter());
+// currStart = curr+1;
+// }
+// break;
+// }
+// }
+//
+// if (curr > currStart) { // end of the stirng
+// sb.Append(tokens,currStart,curr - currStart);
+// }
+//
+// command = sb.ToString();
+// }
+// return command;
+// }
+//
+// 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);
+// }
+// }
+// }
+//
+// protected void setCommandBehabior(CommandBehavior cmdBehavior)
+// {
+// _behvior = cmdBehavior;
+// }
+//
+// internal CommandBehavior getCommandBehavior()
+// {
+// return _behvior;
+// }
+//
+// protected static String GetProcedureName(string cmdText)
+// {
+// if(cmdText[0] == '[' && cmdText[cmdText.Length - 1] == ']')
+// return cmdText.Substring(1, cmdText.Length - 2);
+// return cmdText;
+// }
+//
+// }
+//} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/AbstractDBConnection.cs b/mcs/class/System.Data/System.Data.Common/AbstractDBConnection.cs
new file mode 100644
index 00000000000..4c70f56f582
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/AbstractDBConnection.cs
@@ -0,0 +1,1158 @@
+//
+// System.Data.Common.AbstractDBConnection
+//
+// Author:
+// Boris Kirzner (borisk@mainsoft.com)
+//
+
+using System.Data;
+using System.Data.ProviderBase;
+using System.Data.Configuration;
+using System.Configuration;
+using System.Collections;
+using System.Collections.Specialized;
+using System.Text;
+using System.Text.RegularExpressions;
+
+using java.sql;
+using javax.sql;
+using javax.naming;
+// can not use java.util here - it manes ArrayList an ambiguous reference
+
+namespace System.Data.Common
+{
+ public abstract class AbstractDBConnection : DbConnection
+ {
+ #region ObjectNamesHelper
+
+ private sealed class ObjectNamesHelper
+ {
+ //static readonly Regex NameOrder = new Regex(@"^\s*((\[(?<NAME>(\s*[^\[\]\s])+)\s*\])|(?<NAME>(\w|!|\#|\$)+(\s*(\w|!|\#|\$)+)*))\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
+ static readonly Regex NameOrder = new Regex(@"^((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
+
+ //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);
+ static readonly Regex SchemaNameOrder = new Regex(@"^((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
+ //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);
+ //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);
+ static readonly Regex CatalogSchemaNameOrder = new Regex(@"^((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
+
+ //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);
+ //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);
+ static readonly Regex CatalogNameOrder = new Regex(@"^((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
+ //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);
+ //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);
+ static readonly Regex SchemaCatalogNameOrder = new Regex(@"^((\[(?<SCHEMA>[^\]]+)\])|(?<SCHEMA>[^\.\[\]]+))\s*\.\s*((\[(?<CATALOG>[^\]]+)\])|(?<CATALOG>[^\.\[\]]+))\s*\.\s*((\[(?<NAME>[^\]]+)\])|(?<NAME>[^\.\[\]]+))$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
+
+ internal static ObjectNameResolver[] GetSyntaxPatterns(AbstractDBConnection connection)
+ {
+ ArrayList collection = new ArrayList();
+ collection.Add(new ObjectNameResolver(NameOrder));
+
+ ObjectNameResolversCollection basic = (ObjectNameResolversCollection)ConfigurationSettings.GetConfig("system.data/objectnameresolution");
+
+ DatabaseMetaData metaData = connection.JdbcConnection.getMetaData();
+ string productName = metaData.getDatabaseProductName();
+
+ foreach(ObjectNameResolver nameResolver in basic) {
+ if (productName.IndexOf(nameResolver.DbName) != -1) {
+ collection.Add(nameResolver);
+ }
+ }
+
+ //defaults
+ if (metaData.isCatalogAtStart()) {
+ collection.Add(new ObjectNameResolver(SchemaNameOrder));
+ collection.Add(new ObjectNameResolver(CatalogNameOrder));
+ collection.Add(new ObjectNameResolver(CatalogSchemaNameOrder));
+ collection.Add(new ObjectNameResolver(SchemaCatalogNameOrder));
+ }
+ else {
+ collection.Add(new ObjectNameResolver(CatalogNameOrder));
+ collection.Add(new ObjectNameResolver(SchemaNameOrder));
+ collection.Add(new ObjectNameResolver(SchemaCatalogNameOrder));
+ collection.Add(new ObjectNameResolver(CatalogSchemaNameOrder));
+ }
+
+ return (ObjectNameResolver[])collection.ToArray(typeof(ObjectNameResolver));
+ }
+ }
+
+ #endregion // ObjectNamesHelper
+
+ #region ConnectionStringHelper
+
+ internal sealed class ConnectionStringHelper
+ {
+ internal static string FindValue(NameValueCollection collection, string[] keys)
+ {
+ if (collection == null || keys == null || keys.Length == 0) {
+ return String.Empty;
+ }
+
+ for(int i=0; i < keys.Length; i++) {
+ string value = FindValue(collection,keys[i]);
+ if (!String.Empty.Equals(value)) {
+ return value;
+ }
+ }
+ return String.Empty;
+ }
+
+ internal static string FindValue(NameValueCollection collection, string key)
+ {
+ if (collection == null) {
+ return String.Empty;
+ }
+
+ string value = collection[key];
+ return (value != null) ? value : String.Empty;
+ }
+
+ internal static void UpdateValue(NameValueCollection collection,string[] keys,string value)
+ {
+ for(int i=0; i < keys.Length; i++) {
+ if (collection[keys[i]] != null) {
+ collection[keys[i]] = value;
+ }
+ }
+ }
+
+ internal static void AddValue(NameValueCollection collection,string[] keys,string value)
+ {
+ for(int i=0; i < keys.Length; i++) {
+ collection[keys[i]] = value;
+ }
+ }
+
+ /**
+ * Parses connection string and builds NameValueCollection
+ * for all keys.
+ */
+ internal static NameValueCollection BuildUserParameters (string connectionString)
+ {
+ NameValueCollection userParameters = new NameValueCollection();
+
+ if (connectionString == null || connectionString.Length == 0) {
+ return userParameters;
+ }
+ connectionString += ";";
+
+ bool inQuote = false;
+ bool inDQuote = false;
+ bool inName = true;
+
+ string name = String.Empty;
+ string value = String.Empty;
+ StringBuilder sb = new StringBuilder ();
+
+ for (int i = 0; i < connectionString.Length; i += 1) {
+ char c = connectionString [i];
+ char peek;
+ if (i == connectionString.Length - 1)
+ peek = '\0';
+ else
+ peek = connectionString [i + 1];
+
+ switch (c) {
+ case '\'':
+ if (inDQuote)
+ sb.Append (c);
+ else if (peek.Equals(c)) {
+ sb.Append(c);
+ i += 1;
+ }
+ else
+ inQuote = !inQuote;
+ break;
+ case '"':
+ if (inQuote)
+ sb.Append(c);
+ else if (peek.Equals(c)) {
+ sb.Append(c);
+ i += 1;
+ }
+ else
+ inDQuote = !inDQuote;
+ break;
+ case ';':
+ if (inDQuote || inQuote)
+ sb.Append(c);
+ else {
+ if (name != String.Empty && name != null) {
+ value = sb.ToString();
+ userParameters [name.Trim()] = value.Trim();
+ }
+ inName = true;
+ name = String.Empty;
+ value = String.Empty;
+ sb = new StringBuilder();
+ }
+ break;
+ case '=':
+ if (inDQuote || inQuote || !inName)
+ sb.Append (c);
+ else if (peek.Equals(c)) {
+ sb.Append (c);
+ i += 1;
+ }
+ else {
+ name = sb.ToString();
+ sb = new StringBuilder();
+ inName = false;
+ }
+ break;
+ case ' ':
+ if (inQuote || inDQuote)
+ sb.Append(c);
+ else if (sb.Length > 0 && !peek.Equals(';'))
+ sb.Append(c);
+ break;
+ default:
+ sb.Append(c);
+ break;
+ }
+ }
+ return userParameters;
+ }
+ }
+
+ #endregion // ConnectionStringHelper
+
+ #region DataSourceCache
+
+ private sealed class DataSourceCache : AbstractDbMetaDataCache
+ {
+ internal DataSource GetDataSource(string dataSourceName,string namingProviderUrl,string namingFactoryInitial)
+ {
+ Hashtable cache = Cache;
+
+ DataSource ds = cache[dataSourceName] as DataSource;
+
+ if (ds != null) {
+ return ds;
+ }
+
+ Context ctx = null;
+
+ java.util.Properties properties = new java.util.Properties();
+
+ if ((namingProviderUrl != null) && (namingProviderUrl.Length > 0)) {
+ properties.put("java.naming.provider.url",namingProviderUrl);
+ }
+
+ if ((namingFactoryInitial != null) && (namingFactoryInitial.Length > 0)) {
+ properties.put("java.naming.factory.initial",namingFactoryInitial);
+ }
+
+ ctx = new InitialContext(properties);
+
+ try {
+ ds = (DataSource)ctx.lookup(dataSourceName);
+ }
+ catch(javax.naming.NameNotFoundException e) {
+ // possible that is a Tomcat bug,
+ // so try to lookup for jndi datasource with "java:comp/env/" appended
+ ds = (DataSource)ctx.lookup("java:comp/env/" + dataSourceName);
+ }
+
+ cache[dataSourceName] = ds;
+ return ds;
+ }
+ }
+
+ #endregion // DatasourceCache
+
+ #region Declarations
+
+ protected internal enum JDBC_MODE { NONE, DATA_SOURCE_MODE, JDBC_DRIVER_MODE, PROVIDER_MODE }
+ protected internal enum PROVIDER_TYPE { NONE, SQLOLEDB, MSDAORA, IBMDADB2 }
+
+ #endregion // Declarations
+
+ #region Fields
+
+ private static DataSourceCache _dataSourceCache = new DataSourceCache();
+ private const int DEFAULT_TIMEOUT = 15;
+
+ private Connection _jdbcConnnection;
+ private ConnectionState _internalState;
+ private object _internalStateSync = new object();
+
+ private NameValueCollection _userParameters;
+
+ protected string _connectionString = String.Empty;
+ protected string _jdbcUrl;
+
+ private ArrayList _referencedObjects = new ArrayList();
+ private ObjectNameResolver[] _syntaxPatterns;
+
+ #endregion // Fields
+
+ #region Constructors
+
+ public AbstractDBConnection(string connectionString)
+ {
+ _connectionString = connectionString;
+ InitializeSkippedUserParameters();
+ }
+
+ #endregion // Constructors
+
+ #region Properties
+
+ public override String ConnectionString
+ {
+ get { return _connectionString; }
+ set {
+ if (IsOpened) {
+ throw ExceptionHelper.NotAllowedWhileConnectionOpen("ConnectionString",_internalState);
+ }
+ _connectionString = value;
+ _userParameters = null;
+ _jdbcUrl = null;
+ }
+ }
+
+ public override int ConnectionTimeout
+ {
+ get {
+ string timeoutStr = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_TIMEOUT"));
+ if (!String.Empty.Equals(timeoutStr)) {
+ try {
+ return Convert.ToInt32(timeoutStr);
+ }
+ catch(FormatException e) {
+ throw ExceptionHelper.InvalidValueForKey("connect timeout");
+ }
+ catch (OverflowException e) {
+ throw ExceptionHelper.InvalidValueForKey("connect timeout");
+ }
+ }
+ return DEFAULT_TIMEOUT;
+ }
+ }
+
+ public override String Database
+ {
+ get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATABASE")); }
+ }
+
+ public override ConnectionState State
+ {
+ get {
+ try {
+ if ((JdbcConnection == null) || JdbcConnection.isClosed()) {
+ // jdbc connection not initialized or closed
+ if (_internalState == ConnectionState.Closed ) {
+ return ConnectionState.Closed;
+ }
+ }
+ else {
+ // jdbc connection is opened
+ if ((_internalState & ConnectionState.Open) != 0) {
+ return ConnectionState.Open;
+ }
+ }
+ return ConnectionState.Broken;
+ }
+ catch (SQLException) {
+ return ConnectionState.Broken;
+ }
+ }
+ }
+
+ internal bool IsExecuting
+ {
+ get {
+ return ((_internalState & ConnectionState.Executing) != 0);
+ }
+
+ set {
+ lock(_internalStateSync) {
+ // to switch to executing, the connection must be in opened
+ if (value) {
+ if (_internalState != ConnectionState.Open) {
+ if (IsFetching) {
+ throw ExceptionHelper.OpenedReaderExists();
+ }
+ throw ExceptionHelper.OpenConnectionRequired("",_internalState);
+ }
+ _internalState |= ConnectionState.Executing;
+ }
+ else {
+ if (!IsExecuting) {
+ throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Executing.ToString() + " while in state " + _internalState.ToString());
+ }
+ _internalState &= ~ConnectionState.Executing;
+ }
+ }
+ }
+ }
+
+ internal bool IsFetching
+ {
+ get {
+ return ((_internalState & ConnectionState.Fetching) != 0);
+ }
+
+ set {
+ lock(_internalStateSync) {
+ if (value) {
+ // to switch to fetching connection must be in opened, executing
+ if (((_internalState & ConnectionState.Open) == 0) || ((_internalState & ConnectionState.Executing) == 0)) {
+ throw ExceptionHelper.OpenConnectionRequired("",_internalState);
+ }
+ _internalState |= ConnectionState.Fetching;
+ }
+ else {
+ if (!IsFetching) {
+ throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Fetching.ToString() + " while in state " + _internalState.ToString());
+ }
+ _internalState &= ~ConnectionState.Fetching;
+ }
+ }
+ }
+ }
+
+ internal bool IsOpened
+ {
+ get {
+ return ((_internalState & ConnectionState.Open) != 0);
+ }
+
+ set {
+ lock(_internalStateSync) {
+ if (value) {
+ // only connecting connection can be opened
+ if ((_internalState != ConnectionState.Connecting)) {
+ throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);
+ }
+ _internalState |= ConnectionState.Open;
+ }
+ else {
+ if (!IsOpened) {
+ throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Open.ToString() + " while in state " + _internalState.ToString());
+ }
+ _internalState &= ~ConnectionState.Open;
+ }
+ }
+ }
+ }
+
+ internal bool IsConnecting
+ {
+ get {
+ return ((_internalState & ConnectionState.Connecting) != 0);
+ }
+
+ set {
+ lock(_internalStateSync) {
+ if (value) {
+ // to switch to connecting conection must be in closed or in opened
+ if ((_internalState != ConnectionState.Closed) && (_internalState != ConnectionState.Open)) {
+ throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);
+ }
+ _internalState |= ConnectionState.Connecting;
+ }
+ else {
+ if (!IsConnecting) {
+ throw new InvalidOperationException("Connection : Impossible to tear down from state " + ConnectionState.Connecting.ToString() + " while in state " + _internalState.ToString());
+ }
+ _internalState &= ~ConnectionState.Connecting;
+ }
+ }
+ }
+ }
+
+ protected virtual PROVIDER_TYPE ProviderType
+ {
+ get {
+ if (JdbcMode != JDBC_MODE.PROVIDER_MODE) {
+ return PROVIDER_TYPE.NONE;
+ }
+
+ string providerStr = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_PROVIDER"));
+ if (providerStr.StartsWith("SQLOLEDB")) {
+ return PROVIDER_TYPE.SQLOLEDB;
+ }
+ else if (providerStr.StartsWith("MSDAORA")) {
+ return PROVIDER_TYPE.MSDAORA;
+ }
+ else if (providerStr.StartsWith("IBMDADB2")) {
+ return PROVIDER_TYPE.IBMDADB2;
+ }
+ return PROVIDER_TYPE.NONE;
+ }
+ }
+
+ protected internal virtual JDBC_MODE JdbcMode
+ {
+ get {
+ string[] conJndiNameStr = StringManager.GetStringArray("CON_JNDI_NAME");
+ if ( !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,conJndiNameStr))) {
+ return JDBC_MODE.DATA_SOURCE_MODE;
+ }
+
+ string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");
+ string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");
+ bool jdbcDriverSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr));
+ bool jdbcUrlSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr));
+
+ if (jdbcDriverSpecified && jdbcUrlSpecified) {
+ return JDBC_MODE.JDBC_DRIVER_MODE;
+ }
+
+ string[] providerStr = StringManager.GetStringArray("CON_PROVIDER");
+ if (!String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,providerStr))) {
+ return JDBC_MODE.PROVIDER_MODE;
+ }
+
+ return JDBC_MODE.NONE;
+ }
+ }
+
+ protected virtual string JdbcDriverName
+ {
+ get { return String.Empty; }
+ }
+
+ protected abstract DbStringManager StringManager
+ {
+ get;
+ }
+
+ protected virtual string ServerName
+ {
+ get { return DataSource; }
+ }
+
+ protected virtual string CatalogName
+ {
+ get { return Database; }
+ }
+
+ protected virtual string Port
+ {
+ get {
+ string port = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_PORT"));
+ switch (ProviderType) {
+ case PROVIDER_TYPE.SQLOLEDB :
+ if (String.Empty.Equals(port)) {
+ // if needed - resolve MSSQL port
+ // FIXME : decide about behaviour in the case all the timeout spent on port resolution
+ //long start = DateTime.Now.Ticks;
+ port = DbPortResolver.getMSSqlPort(DataSource,InstanceName,ConnectionTimeout).ToString();
+ //long end = DateTime.Now.Ticks;
+ //if( (end - start) < ConnectionTimeout*1000000) {
+ //timeout -= (int)(end - start)/1000000;
+ //}
+ }
+ // todo : what should we do if all the timeout spent on port resolution ?
+ if ("-1".Equals(port)) {
+ port = StringManager.GetString("SQL_CON_PORT", "1433"); //default port of MSSql Server 3167.
+ }
+ ConnectionStringHelper.AddValue(UserParameters,StringManager.GetStringArray("CON_PORT"),port);
+ break;
+ }
+ return port;
+ }
+ }
+
+ public override string DataSource
+ {
+ get {
+ string dataSource = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATA_SOURCE"));
+
+ if (ProviderType == PROVIDER_TYPE.SQLOLEDB) {
+ int instanceIdx;
+ if ((instanceIdx = dataSource.IndexOf("\\")) != -1) {
+ // throw out named instance name
+ dataSource = dataSource.Substring(0,instanceIdx);
+ }
+
+ if (dataSource != null && dataSource.StartsWith("(") && dataSource.EndsWith(")")) {
+ dataSource = dataSource.Substring(1,dataSource.Length - 2);
+ }
+
+ if(String.Empty.Equals(dataSource) || (String.Compare("local",dataSource,true) == 0)) {
+ dataSource = "localhost";
+ }
+ }
+ return dataSource;
+ }
+ }
+
+ protected virtual string InstanceName
+ {
+ get {
+ string dataSource = ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_DATA_SOURCE"));
+ string instanceName = String.Empty;
+ if (ProviderType == PROVIDER_TYPE.SQLOLEDB) {
+ int instanceIdx;
+ if ((instanceIdx = dataSource.IndexOf("\\")) == -1) {
+ // no named instance specified - use a default name
+ instanceName = StringManager.GetString("SQL_DEFAULT_INSTANCE_NAME");
+ }
+ else {
+ // get named instance name
+ instanceName = dataSource.Substring(instanceIdx + 1);
+ }
+ }
+ return instanceName;
+ }
+ }
+
+ protected virtual string User
+ {
+ get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_USER_ID")); }
+ }
+
+ protected virtual string Password
+ {
+ get { return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("CON_PASSWORD")); }
+ }
+
+ protected NameValueCollection UserParameters
+ {
+ get {
+ if (_userParameters == null) {
+ _userParameters = ConnectionStringHelper.BuildUserParameters(ConnectionString);
+ }
+ return _userParameters;
+ }
+ }
+
+ internal String JdbcUrl
+ {
+ get {
+ if ( UserParameters == null) {
+ return String.Empty;
+ }
+
+ if (_jdbcUrl == null) {
+ _jdbcUrl = BuildJdbcUrl();
+ }
+ return _jdbcUrl;
+ }
+ }
+
+ internal ConnectionState InternalState
+ {
+ get { return _internalState; }
+ }
+
+
+ protected internal Connection JdbcConnection
+ {
+ get { return _jdbcConnnection; }
+ set { _jdbcConnnection = value; }
+ }
+
+ protected virtual string[] ResourceIgnoredKeys
+ {
+ get { return new string[0]; }
+ }
+
+ protected virtual Hashtable SkippedUserParameters
+ {
+ get { return new Hashtable(new CaseInsensitiveHashCodeProvider(),new CaseInsensitiveComparer()); }
+ }
+
+ internal ObjectNameResolver[] SyntaxPatterns
+ {
+ get {
+ if (_syntaxPatterns == null) {
+ _syntaxPatterns = ObjectNamesHelper.GetSyntaxPatterns(this);
+ }
+ return _syntaxPatterns;
+ }
+ }
+
+ #endregion // Properties
+
+ #region Methods
+ // since WS also does not permits dynamically change of login timeout and tomcat does no implements - do not do it at all
+ //ds.setLoginTimeout(ConnectionTimeout);
+
+ internal abstract void OnSqlWarning(SQLWarning warning);
+
+ internal abstract void OnStateChanged(ConnectionState orig, ConnectionState current);
+
+ protected abstract SystemException CreateException(SQLException e);
+
+ public override void Close()
+ {
+ try {
+ ClearReferences();
+ if (JdbcConnection != null && !JdbcConnection.isClosed()) {
+ JdbcConnection.close();
+ }
+ }
+ catch (SQLException e) {
+ // suppress exception
+ JdbcConnection = null;
+#if DEBUG
+ Console.WriteLine("Exception catched at Conection.Close() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);
+#endif
+ }
+ catch (Exception e) {
+ // suppress exception
+ JdbcConnection = null;
+#if DEBUG
+ Console.WriteLine("Exception catched at Conection.Close() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);
+#endif
+ }
+ finally {
+ lock(_internalStateSync) {
+ _internalState = ConnectionState.Closed;
+ }
+ }
+ }
+
+ protected internal virtual void CopyTo(AbstractDBConnection target)
+ {
+ target._connectionString = _connectionString;
+ }
+
+ internal protected virtual void OnSqlException(SQLException exp)
+ {
+ throw CreateException(exp);
+ }
+
+ internal void AddReference(object referencedObject)
+ { lock(_referencedObjects.SyncRoot) {
+ _referencedObjects.Add(new WeakReference(referencedObject));
+ }
+ }
+
+ internal void RemoveReference(object referencedObject)
+ {
+ lock(_referencedObjects.SyncRoot) {
+ for(int i = 0; i < _referencedObjects.Count; i++) {
+ WeakReference wr = (WeakReference) _referencedObjects[i];
+ if (wr.IsAlive && (wr.Target == referencedObject)) {
+ _referencedObjects.RemoveAt(i);
+ }
+ }
+ }
+ }
+
+ private void ClearReferences()
+ {
+ ArrayList oldList = _referencedObjects;
+ _referencedObjects = new ArrayList();
+
+ for(int i = 0; i < oldList.Count; i++) {
+ WeakReference wr = (WeakReference) oldList[i];
+ if (wr.IsAlive) {
+ ClearReference(wr.Target);
+ }
+ }
+ }
+
+ private void ClearReference(object referencedObject)
+ {
+ try {
+ if (referencedObject is AbstractDbCommand) {
+ ((AbstractDbCommand)referencedObject).CloseInternal();
+ }
+ else if (referencedObject is AbstractDataReader) {
+ ((AbstractDataReader)referencedObject).CloseInternal();
+ }
+ }
+ catch (SQLException) {
+ // suppress exception since it's possible that command or reader are in inconsistent state
+ }
+ }
+
+ public override void Open()
+ {
+ if (_connectionString == null || _connectionString.Length == 0) {
+ throw ExceptionHelper.ConnectionStringNotInitialized();
+ }
+
+ IsConnecting = true;
+ try {
+ if (JdbcConnection != null && !JdbcConnection.isClosed()) {
+ throw ExceptionHelper.ConnectionAlreadyOpen(_internalState);
+ }
+
+ switch(JdbcMode) {
+ case JDBC_MODE.DATA_SOURCE_MODE :
+ JdbcConnection = GetConnectionFromDataSource();
+ break;
+
+ case JDBC_MODE.JDBC_DRIVER_MODE:
+ JdbcConnection = GetConnectionFromJdbcDriver();
+ break;
+
+ case JDBC_MODE.PROVIDER_MODE :
+ JdbcConnection = GetConnectionFromProvider();
+ break;
+ }
+ IsOpened = true;
+
+ OnStateChanged(ConnectionState.Closed, ConnectionState.Open);
+ }
+ catch (SQLWarning warning) {
+ OnSqlWarning(warning);
+ }
+ catch (SQLException exp) {
+ OnSqlException(exp);
+ }
+ finally {
+ IsConnecting = false;
+ }
+ }
+
+ public override void ChangeDatabase(String database)
+ {
+ IsConnecting = true;
+ try {
+ ClearReferences();
+ Connection con = JdbcConnection;
+ con.setCatalog(database);
+ ConnectionStringHelper.UpdateValue(UserParameters,StringManager.GetStringArray("CON_DATABASE"),database);
+ }
+ catch (SQLWarning warning) {
+ OnSqlWarning(warning);
+ }
+ catch (SQLException exp) {
+ throw CreateException(exp);
+ }
+ finally {
+ IsConnecting = false;
+ }
+ }
+
+ public override string ServerVersion {
+ get {
+ // only if the driver support this methods
+ try {
+ if (JdbcConnection == null)
+ return String.Empty;
+
+ DatabaseMetaData metaData = JdbcConnection.getMetaData();
+ return metaData.getDatabaseProductVersion();
+ }
+ catch (SQLException exp) {
+ throw CreateException(exp);
+ }
+ }
+ }
+
+ internal string JdbcProvider {
+ get {
+ // only if the driver support this methods
+ try {
+ if (JdbcConnection == null)
+ return String.Empty;
+
+ DatabaseMetaData metaData = JdbcConnection.getMetaData();
+ return metaData.getDriverName() + " " + metaData.getDriverVersion();
+ }
+ catch (SQLException exp) {
+ return String.Empty; //suppress
+ }
+ }
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing) {
+ try {
+ if (JdbcConnection != null && !JdbcConnection.isClosed()) {
+ JdbcConnection.close();
+ }
+ JdbcConnection = null;
+ }
+ catch (java.sql.SQLException exp) {
+ throw CreateException(exp);
+ }
+ }
+ base.Dispose(disposing);
+ }
+
+ protected internal virtual void ValidateConnectionString(string connectionString)
+ {
+ JDBC_MODE currentJdbcMode = JdbcMode;
+
+ if (currentJdbcMode == JDBC_MODE.NONE) {
+ string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");
+ string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");
+ bool jdbcDriverSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr));
+ bool jdbcUrlSpecified = !String.Empty.Equals(ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr));
+
+ if (jdbcDriverSpecified ^ jdbcUrlSpecified) {
+ 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>\"");
+ }
+ }
+ }
+
+ protected virtual string BuildJdbcUrl()
+ {
+ switch (JdbcMode) {
+ case JDBC_MODE.JDBC_DRIVER_MODE :
+ return ConnectionStringHelper.FindValue(UserParameters,StringManager.GetStringArray("JDBC_URL"));
+ default :
+ return String.Empty;
+ }
+ }
+
+ protected java.util.Properties BuildProperties()
+ {
+ java.util.Properties properties = new java.util.Properties();
+
+ string user = User;
+ if (user != null && user.Length > 0)
+ properties.put("user", user);
+ string password = Password;
+ if (user != null && user.Length > 0)
+ properties.put("password", password);
+
+ string[] userKeys = UserParameters.AllKeys;
+
+ for(int i=0; i < userKeys.Length; i++) {
+ string userKey = userKeys[i];
+ string userParameter = UserParameters[userKey];
+ if (!SkipUserParameter(userKey)) {
+ properties.put(userKey,userParameter);
+ }
+ }
+ return properties;
+ }
+
+ protected virtual bool SkipUserParameter(string parameterName)
+ {
+ if (SkippedUserParameters.Count == 0) {
+ // skipped parameters not initialized - skip all
+ return true;
+ }
+
+ return SkippedUserParameters.Contains(parameterName);
+ }
+
+ protected virtual void InitializeSkippedUserParameters()
+ {
+ if (SkippedUserParameters.Count > 0) {
+ return;
+ }
+
+ for(int i=0; i < ResourceIgnoredKeys.Length; i++) {
+ string[] userKeys = StringManager.GetStringArray(ResourceIgnoredKeys[i]);
+ for(int j=0; j < userKeys.Length; j++) {
+ SkippedUserParameters.Add(userKeys[j],userKeys[j]);
+ }
+ }
+ }
+
+ internal void ValidateBeginTransaction()
+ {
+ if (State != ConnectionState.Open) {
+ throw new InvalidOperationException(Res.GetString("ADP_OpenConnectionRequired_BeginTransaction", new object[] {"BeginTransaction", State}));
+ }
+
+ if (!JdbcConnection.getAutoCommit()) {
+ throw new System.InvalidOperationException("Parallel transactions are not supported.");
+ }
+ }
+
+ internal virtual Connection GetConnectionFromProvider()
+ {
+ ActivateJdbcDriver(JdbcDriverName);
+ DriverManager.setLoginTimeout(ConnectionTimeout);
+ java.util.Properties properties = BuildProperties();
+ return DriverManager.getConnection (JdbcUrl, properties);
+ }
+
+ internal Connection GetConnectionFromDataSource()
+ {
+ string dataSourceJndi = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_NAME"));
+ string namingProviderUrl = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_PROVIDER"));
+ string namingFactoryInitial = ConnectionStringHelper.FindValue(UserParameters, StringManager.GetStringArray("CON_JNDI_FACTORY"));
+ DataSource ds = _dataSourceCache.GetDataSource(dataSourceJndi,namingProviderUrl,namingFactoryInitial);
+ try {
+ ds.setLoginTimeout(ConnectionTimeout);
+ }
+ catch (java.lang.Exception) {
+ // WebSphere does not allows dynamicall change of login timeout
+ // setLoginTimeout is not supported yet
+ // in Tomcat data source.
+ // In this case we work wthout timeout.
+ }
+ return ds.getConnection();
+ }
+
+ internal virtual Connection GetConnectionFromJdbcDriver()
+ {
+ string[] jdbcDriverStr = StringManager.GetStringArray("JDBC_DRIVER");
+ string[] jdbcUrlStr = StringManager.GetStringArray("JDBC_URL");
+
+ string jdbcDriverName = ConnectionStringHelper.FindValue(UserParameters,jdbcDriverStr);
+ string jdbcUrl = ConnectionStringHelper.FindValue(UserParameters,jdbcUrlStr);
+
+ ActivateJdbcDriver(jdbcDriverName);
+ DriverManager.setLoginTimeout(ConnectionTimeout);
+
+ java.util.Properties properties = BuildProperties();
+
+ return DriverManager.getConnection(jdbcUrl,properties);
+ }
+
+ internal ArrayList GetProcedureColumns(String procedureString, AbstractDbCommand command)
+ {
+ ArrayList col = new ArrayList();
+ try {
+ ObjectNameResolver[] nameResolvers = SyntaxPatterns;
+ ResultSet res = null;
+ string catalog = null;
+ string schema = null;
+ string spname = null;
+
+ DatabaseMetaData metadata = JdbcConnection.getMetaData();
+ bool storesUpperCaseIdentifiers = false;
+ bool storesLowerCaseIdentifiers = false;
+ try {
+ storesUpperCaseIdentifiers = metadata.storesUpperCaseIdentifiers();
+ storesLowerCaseIdentifiers = metadata.storesLowerCaseIdentifiers();
+ }
+ catch (SQLException e) {
+ // suppress
+ }
+
+ for(int i=0; i < nameResolvers.Length; i++) {
+ ObjectNameResolver nameResolver = nameResolvers[i];
+ Match match = nameResolver.Match(procedureString);
+
+ if (match.Success) {
+ spname = ObjectNameResolver.GetName(match);
+ schema = ObjectNameResolver.GetSchema(match);
+ catalog = ObjectNameResolver.GetCatalog(match);
+
+ // make all identifiers uppercase or lowercase according to database metadata
+ if (storesUpperCaseIdentifiers) {
+ spname = (spname.Length > 0) ? spname.ToUpper() : null;
+ schema = (schema.Length > 0) ? schema.ToUpper() : null;
+ catalog = (catalog.Length > 0) ? catalog.ToUpper() : null;
+ }
+ else if (storesLowerCaseIdentifiers) {
+ spname = (spname.Length > 0) ? spname.ToLower() : null;
+ schema = (schema.Length > 0) ? schema.ToLower() : null;
+ catalog = (catalog.Length > 0) ? catalog.ToLower() : null;
+ }
+ else {
+ spname = (spname.Length > 0) ? spname : null;
+ schema = (schema.Length > 0) ? schema : null;
+ catalog = (catalog.Length > 0) ? catalog : null;
+ }
+
+ // catalog from db is always in correct caps
+ if (catalog == null) {
+ catalog = JdbcConnection.getCatalog();
+ }
+
+ try {
+ // always get the first procedure that db returns
+ res = metadata.getProcedures(catalog, schema, spname);
+ if (res.next()) {
+ catalog = res.getString(1);
+ schema = res.getString(2);
+ spname = res.getString(3);
+ break;
+ }
+
+ spname = null;
+ }
+ catch { // suppress exception
+ return null;
+ }
+ finally {
+ if (res != null) {
+ res.close();
+ }
+ }
+ }
+ }
+
+ if (spname == null || spname.Length == 0) {
+ return null;
+ }
+
+ try {
+ // get procedure columns based o procedure metadata
+ res = metadata.getProcedureColumns(catalog, schema, spname, null);
+ while (res.next()) {
+ // since there is still a possibility that some of the parameters to getProcedureColumn were nulls,
+ // we need to filter the results with strict matching
+ if ((res.getString(1) != catalog ) || (res.getString(2) != schema) || (res.getString(3) != spname)) {
+ continue;
+ }
+
+ AbstractDbParameter parameter = (AbstractDbParameter)command.CreateParameter();
+
+ parameter.SetParameterName(res);
+ parameter.SetParameterDbType(res);
+ parameter.SetSpecialFeatures(res);
+
+ //get parameter direction
+ short direction = res.getShort("COLUMN_TYPE");
+ if(direction == 1) //DatabaseMetaData.procedureColumnIn
+ parameter.Direction = ParameterDirection.Input;
+ else if(direction == 2) //DatabaseMetaData.procedureColumnInOut
+ parameter.Direction = ParameterDirection.InputOutput;
+ else if(direction == 4) //DatabaseMetaData.procedureColumnOut
+ parameter.Direction = ParameterDirection.Output;
+ else if(direction == 5) //DatabaseMetaData.procedureColumnReturn
+ parameter.Direction = ParameterDirection.ReturnValue;
+
+ //get parameter precision and scale
+ parameter.SetParameterPrecisionAndScale(res);
+
+ parameter.SetParameterSize(res);
+ parameter.SetParameterIsNullable(res);
+
+ col.Add(parameter);
+ }
+ }
+ finally {
+ if (res != null) {
+ res.close();
+ }
+ }
+ }
+ catch(Exception e) {
+ //supress
+#if DEBUG
+ Console.WriteLine("Exception catched at AbstractDBConnection.GetProcedureColumns() : {0}\n{1}\n{2}",e.GetType().FullName,e.Message,e.StackTrace);
+#endif
+ }
+ return col;
+ }
+
+ protected static void ActivateJdbcDriver(string driver)
+ {
+ if(driver != null) {
+ try {
+ java.lang.Class.forName(driver).newInstance();
+ }
+ catch (java.lang.ClassNotFoundException e) {
+ throw new TypeLoadException(e.Message);
+ }
+ catch (java.lang.InstantiationException e) {
+ throw new MemberAccessException(e.Message);
+ }
+ catch (java.lang.IllegalAccessException e) {
+ throw new MissingMethodException(e.Message);
+ }
+ }
+ }
+
+ protected String BuildMsSqlUrl()
+ {
+ return StringManager.GetString("SQL_JDBC_URL") //"jdbc:microsoft:sqlserver://"
+ + ServerName + ":" + Port + ";DatabaseName=" + CatalogName;
+ }
+
+ #endregion // Methods
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/AbstractDBParameter.cs b/mcs/class/System.Data/System.Data.Common/AbstractDBParameter.cs
new file mode 100644
index 00000000000..493c6a573a5
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/AbstractDBParameter.cs
@@ -0,0 +1,259 @@
+//namespace System.Data.Common
+//{
+//
+// //using clr.System;
+// //using clr.compiler.BitConstants;
+//
+// using System.Data;
+// using System.Data.ProviderBase;
+// using System.Text;
+//
+// /**
+// * @author erand
+// */
+// public abstract class AbstractDBParameter : DbParameterBase, System.ICloneable
+// {
+// /* Properties from IDataParameter */
+//// protected ParameterDirection _direction = ParameterDirection.Input;
+//// protected bool _isNullable = false;
+//// protected String _name = null;
+//// protected String _sourceColumn = null;
+// protected DataRowVersion _version = DataRowVersion.Current;
+//// protected Object _value = null;
+//
+// /* Properties from IDbDataParameter */
+//// protected byte _precision;
+//// protected byte _scale;
+//// protected int _size = -1;
+//
+// private int _place;
+// private int _jdbcType;
+//
+//// /**
+//// * @see System.Data.IDbDataParameter#Precision
+//// */
+//// public virtual byte Precision
+//// {
+//// get
+//// {
+//// return _precision;
+//// }
+//// set
+//// {
+//// _precision = value;
+//// }
+//// }
+//
+//
+//// /**
+//// * @see System.Data.IDbDataParameter#Scale
+//// */
+//// public virtual byte Scale
+//// {
+//// get
+//// {
+//// return _scale;
+//// }
+//// set
+//// {
+//// _scale = value;
+//// }
+//// }
+//
+//
+//
+//// /**
+//// * @see System.Data.IDbDataParameter#Size
+//// */
+//// public virtual int Size
+//// {
+//// get
+//// {
+//// return _size;
+//// }
+//// set
+//// {
+//// _size = value;
+//// }
+//// }
+//
+//
+//// /**
+//// * @see System.Data.IDataParameter#Direction
+//// */
+//// public virtual ParameterDirection Direction
+//// {
+//// get
+//// {
+//// return _direction;
+//// }
+//// set
+//// {
+//// _direction = value;
+//// }
+//// }
+//
+//
+//// /**
+//// * @see System.Data.IDataParameter#IsNullable
+//// */
+//// public virtual bool IsNullable
+//// {
+//// get
+//// {
+//// return _isNullable;
+//// }
+//// set
+//// {
+//// _isNullable = value;
+//// }
+//// }
+//
+//
+//// /**
+//// * @see System.Data.IDataParameter#ParameterName
+//// */
+//// public virtual String ParameterName
+//// {
+//// get
+//// {
+//// /**@todo What's the value of the Empty string ?*/
+//// /*Where to define our Empty String ?*/
+//// if (_name == null)
+//// return String.Empty;
+//// else
+//// return _name;
+//// }
+//// set
+//// {
+//// if ((value != null) && value.Equals(_name))
+//// return;
+//// //if ((value != null) && (value.length() > Constants.MAXIMAL_PARAMETER_LENGTH))
+//// /**@todo Implement Exception::-->*/
+//// // throw InvalidParameterLength(value);
+////
+//// _name = value;
+//// }
+//// }
+//
+//
+//// /**
+//// * @see System.Data.IDataParameter#SourceColumn
+//// */
+//// public virtual String SourceColumn
+//// {
+//// get
+//// {
+//// if (_sourceColumn != null)
+//// return _sourceColumn;
+//// else
+//// return String.Empty;
+//// }
+//// set
+//// {
+//// _sourceColumn = value;
+//// }
+//// }
+//
+//
+//
+//// /**
+//// * @see System.Data.IDataParameter#SourceVersion
+//// */
+//// public virtual DataRowVersion SourceVersion
+//// {
+//// get
+//// {
+//// return _version;
+//// }
+//// set
+//// {
+//// _version = value;
+//// }
+//// }
+//
+//
+//// /**
+//// * @see System.Data.IDataParameter#Value
+//// */
+//// public virtual Object Value
+//// {
+//// get
+//// {
+//// return _value;
+//// }
+//// set
+//// {
+//// _value = value;
+//// }
+//// }
+//
+//
+//
+// public virtual void setParameterPlace(int place)
+// {
+// _place = place;
+// }
+//
+// public virtual int getParameterPlace()
+// {
+// return _place;
+// }
+//
+// abstract internal int getJDBCType(DbType dbType);
+//
+// internal int JdbcType
+// {
+// get {
+// return _jdbcType;
+// }
+//
+// set {
+// _jdbcType = value;
+// }
+// }
+//
+// public abstract DbType DbType
+// {
+// get;
+// set;
+// }
+//
+// public abstract Object Clone();
+//
+// internal virtual bool IsOracleRefCursor
+// {
+// get
+// {
+// return false;
+// }
+// }
+//
+// internal virtual String formatParameter()
+// {
+// if (Value == null || Value == DBNull.Value)
+// return "NULL";
+//
+// switch(DbType) {
+// case DbType.Byte:
+// case DbType.Currency:
+// case DbType.Decimal:
+// case DbType.Double:
+// case DbType.Int16:
+// case DbType.Int32:
+// case DbType.Int64:
+// case DbType.SByte:
+// case DbType.Single:
+// case DbType.UInt16:
+// case DbType.UInt32:
+// case DbType.UInt64:
+// return Value.ToString();
+// case DbType.Boolean:
+// return (bool)Value ? "0x1" : "0x0";
+// case DbType.Binary:
+// default:
+// return String.Concat("\'", Value.ToString().Replace("\'", "\'\'"),"\'");
+// }
+// }
+// }
+//} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/AbstractDataReader.cs b/mcs/class/System.Data/System.Data.Common/AbstractDataReader.cs
new file mode 100644
index 00000000000..b6bdbc5ef5f
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/AbstractDataReader.cs
@@ -0,0 +1,1179 @@
+//
+// System.Data.Common.AbstractDataReader
+//
+// Author:
+// Boris Kirzner (borisk@mainsoft.com)
+// Konstantin Triger (kostat@mainsoft.com)
+//
+
+using System;
+using System.Data;
+using System.Collections;
+using System.Data.ProviderBase;
+
+using java.io;
+using java.sql;
+
+namespace System.Data.Common
+{
+ public abstract class AbstractDataReader : DbDataReaderBase, ISafeDataRecord {
+ #region Fields
+
+ private ResultSetMetaData _resultsMetaData;
+ protected AbstractDbCommand _command;
+ private DataTable _schemaTable;
+ private ReaderState _readerState = ReaderState.Uninitialized;
+
+ private IReaderCacheContainer[] _readerCache;
+ private int _currentCacheFilledPosition;
+ private Stack _resultSetStack = new Stack();
+
+ [Flags]
+ private enum ReaderState { Uninitialized = 0, Empty = 1, HasRows = 2, FirstRed = 4, Eof = 8, Fetching = 16 };
+
+ internal enum SCHEMA_TABLE { ColumnName,
+ ColumnOrdinal,
+ ColumnSize,
+ NumericPrecision,
+ NumericScale,
+ IsUnique,
+ IsKey,
+ BaseServerName,
+ BaseCatalogName,
+ BaseColumnName,
+ BaseSchemaName,
+ BaseTableName,
+ DataType,
+ AllowDBNull,
+ ProviderType,
+ IsAliased,
+ IsExpression,
+ IsIdentity,
+ IsAutoIncrement,
+ IsRowVersion,
+ IsHidden,
+ IsLong,
+ IsReadOnly};
+
+ #endregion // Fields
+
+ #region Constructors
+
+ protected AbstractDataReader() : base (CommandBehavior.Default) {
+ }
+
+ public AbstractDataReader(AbstractDbCommand command): base(command.Behavior) {
+ _command = command;
+ if (_command.Connection != null) {
+ ((AbstractDBConnection)_command.Connection).AddReference(this);
+ }
+ }
+
+ #endregion // Constructors
+
+ #region Properties
+
+ public override bool HasRows {
+ get {
+ if (IsClosed) {
+ throw new InvalidOperationException("Invalid attempt to HasRows when reader is closed.");
+ }
+
+ try {
+ if(null == Results)
+ return false;
+ }
+ catch(SystemException) {
+ //suppress
+ return false;
+ }
+
+ return (_readerState & ReaderState.HasRows) != 0;
+ }
+ }
+
+ public override int RecordsAffected
+ {
+ // MSDN : The RecordsAffected property is not set
+ // until all rows are read and you close the reader.
+ get {
+ return _command.RecordsAffected;
+ }
+ }
+
+ public override int FieldCount
+ {
+ get {
+ if (ResultsMetaData == null)
+ return 0;
+
+ try {
+ return ResultsMetaData.getColumnCount();
+ }
+ catch (SQLException exp) {
+ throw CreateException(exp);
+ }
+
+ }
+ }
+
+ protected internal CommandBehavior Behavior
+ {
+ get {
+ return _command.Behavior;
+ }
+ }
+
+ public override Object this[String columnName]
+ {
+ get {
+ try {
+ int columnIndex = Results.findColumn(columnName) - 1;
+ return this[columnIndex];
+ }
+ catch (SQLException exp) {
+ throw new IndexOutOfRangeException(exp.Message, exp);
+ }
+ }
+ }
+
+ public override Object this[int columnIndex]
+ {
+ get { return GetValue(columnIndex); }
+ }
+
+ protected ResultSet Results
+ {
+ get {
+ if (_readerState == ReaderState.Uninitialized) {
+
+ if (_resultSetStack.Count == 0) {
+ ResultSet resultSet = _command.CurrentResultSet;
+ if (resultSet == null)
+ return null;
+
+ _resultSetStack.Push(resultSet);
+ }
+
+ _readerState = ReaderState.Fetching;
+ for (;;) {
+ try {
+ Configuration.BooleanSetting prefetchSchema = Configuration.Switches.PrefetchSchema;
+
+ if (prefetchSchema == Configuration.BooleanSetting.NotSet) {
+ AbstractDBConnection conn = (AbstractDBConnection)((ICloneable)_command.Connection);
+ string driverName = conn.JdbcConnection.getMetaData().getDriverName();
+ if (driverName.IndexOf("DB2") >= 0)
+ prefetchSchema = Configuration.BooleanSetting.True;
+ }
+
+ if (prefetchSchema == Configuration.BooleanSetting.True)
+ GetSchemaTable();
+
+ ResultSet resultSet = (ResultSet)_resultSetStack.Peek();
+ if (resultSet.next()) {
+ _readerState = (ReaderState.HasRows | ReaderState.FirstRed);
+ ResultSetMetaData rsMetaData = ResultsMetaData;
+ DbTypes.JavaSqlTypes javaSqlType = (DbTypes.JavaSqlTypes)rsMetaData.getColumnType(1);
+ if (javaSqlType == DbTypes.JavaSqlTypes.OTHER) {
+ object value = GetValue(0);
+ if (value != null && value is ResultSet) {
+ _resultsMetaData = null;
+ _readerCache = null;
+ SchemaTable = null;
+ _readerState = ReaderState.Fetching;
+ _resultSetStack.Push(value);
+ continue;
+ }
+ }
+ }
+ else
+ _readerState = ReaderState.Empty;
+
+ break;
+ }
+ catch(SQLException e) {
+ throw CreateException(e);
+ }
+ }
+ }
+
+ return (_resultSetStack.Count > 0) ? (ResultSet)_resultSetStack.Peek() : null;
+ }
+ }
+
+ protected ResultSetMetaData ResultsMetaData
+ {
+ get {
+ ResultSet results = Results;
+ if (results == null) {
+ return null;
+ }
+ if(_resultsMetaData == null) {
+ _resultsMetaData = results.getMetaData();
+ }
+ return _resultsMetaData;
+ }
+ }
+
+ protected DataTable SchemaTable
+ {
+ get {
+ if (_schemaTable == null) {
+ _schemaTable = ConstructSchemaTable();
+ }
+ return _schemaTable;
+ }
+
+ set {_schemaTable = value; }
+ }
+
+ internal protected IReaderCacheContainer[] ReaderCache
+ {
+ get {
+ if (_readerCache == null) {
+ _readerCache = CreateReaderCache();
+ _currentCacheFilledPosition = -1;
+ }
+ return _readerCache;
+ }
+ }
+
+ #endregion // Properties
+
+ #region Methods
+
+ protected abstract int GetProviderType(int jdbcType);
+
+ protected abstract SystemException CreateException(string message, SQLException e);
+
+ protected abstract SystemException CreateException(IOException e);
+
+ protected SystemException CreateException(SQLException e)
+ {
+ return CreateException(e.Message,e);
+ }
+
+ private bool CloseCurrentResultSet() {
+ if (_resultSetStack.Count > 0) {
+ try{
+ _resultsMetaData = null;
+ _readerCache = null;
+ _readerState = ReaderState.Uninitialized;
+ ResultSet rs = (ResultSet)_resultSetStack.Pop();
+ rs.close();
+ return true;
+ }
+ catch (SQLException exp) {
+ throw CreateException(exp);
+ }
+ }
+
+ return false;
+ }
+
+ // FIXME : add Close(bool readAllRecords) and pass this bool to skip looping over NextResult(), override AbstractDbCommand.ExecuteScalar
+ public override void Close()
+ {
+ if (IsClosed)
+ return;
+
+ try {
+ CloseCurrentResultSet();
+ _command.OnReaderClosed(this);
+ }
+ finally {
+ CloseInternal();
+ }
+ }
+
+ internal void CloseInternal()
+ {
+ _resultsMetaData = null;
+ _readerCache = null;
+ _isClosed = true;
+ }
+
+ public override bool NextResult()
+ {
+ CloseCurrentResultSet();
+
+ if ((_command.Behavior & CommandBehavior.SingleResult) != 0) {
+ while (CloseCurrentResultSet());
+ while (_command.NextResultSet());
+ return false;
+ }
+
+ try {
+ while (_resultSetStack.Count > 0) {
+ ResultSet rs = (ResultSet)_resultSetStack.Peek();
+
+ if(!rs.next()) {
+ CloseCurrentResultSet();
+ continue;
+ }
+
+ // must be a ResultSet
+ object childRs = rs.getObject(1);
+ if (childRs != null) {
+ SchemaTable = null;
+ _resultSetStack.Push(childRs);
+ return true;
+ }
+ }
+ }
+ catch (SQLException exp) {
+ throw CreateException(exp);
+ }
+
+ if (_command.NextResultSet()) {
+ SchemaTable = null;
+ return true;
+ }
+ return false;
+ }
+
+ public override bool Read()
+ {
+ if(null == Results ||
+ (_readerState & (ReaderState.HasRows | ReaderState.Eof)) != ReaderState.HasRows)
+ return false;
+
+ bool firstRead = false;
+
+ try {
+ if ((_readerState & ReaderState.FirstRed) != 0) {
+ firstRead = true;
+ _readerState &= ~ReaderState.FirstRed;
+ return true;
+ }
+ else {
+ bool next = Results.next();
+
+ if (!next)
+ _readerState |= ReaderState.Eof;
+
+ return next;
+ }
+ }
+ catch (SQLException exp) {
+ // suppress exception as .Net does
+ return false;
+ }
+ finally {
+ // in case of first read we could sampled the first value
+ // to see whether there is a resultset, so _currentCacheFilledPosition
+ // might be already inited
+ if (!firstRead)
+ _currentCacheFilledPosition = -1;
+ }
+ }
+
+ public override bool GetBoolean(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((BooleanReaderCacheContainer)ReaderCache[columnIndex]).GetBoolean();
+ }
+
+ public bool GetBooleanSafe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is BooleanReaderCacheContainer) {
+ return GetBoolean(columnIndex);
+ }
+ else {
+ return Convert.ToBoolean(GetValue(columnIndex));
+ }
+ }
+
+ public override byte GetByte(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((ByteReaderCacheContainer)ReaderCache[columnIndex]).GetByte();
+ }
+
+ public byte GetByteSafe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is ByteReaderCacheContainer) {
+ return GetByte(columnIndex);
+ }
+ else {
+ return Convert.ToByte(GetValue(columnIndex));
+ }
+ }
+
+ public override long GetBytes(
+ int columnIndex,
+ long dataIndex,
+ byte[] buffer,
+ int bufferIndex,
+ int length)
+ {
+ FillReaderCache(columnIndex);
+ byte[] byteArr = ((BytesReaderCacheContainer)ReaderCache[columnIndex]).GetBytes();
+ long actualLength = ((dataIndex + length) >= byteArr.Length) ? (byteArr.Length - dataIndex) : length;
+ Array.Copy(byteArr,dataIndex,buffer,bufferIndex,actualLength);
+ return actualLength;
+ }
+
+ public virtual byte[] GetBytes(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((BytesReaderCacheContainer)ReaderCache[columnIndex]).GetBytes();
+ }
+
+ public override char GetChar(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ string s = ((StringReaderCacheContainer)ReaderCache[columnIndex]).GetString();
+ if(s == null) {
+ return '\0';
+ }
+ return s[0];
+ }
+
+ public char GetCharSafe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is StringReaderCacheContainer) {
+ return GetChar(columnIndex);
+ }
+ else {
+ return Convert.ToChar(GetValue(columnIndex));
+ }
+ }
+
+ public override long GetChars(
+ int columnIndex,
+ long dataIndex,
+ char[] buffer,
+ int bufferIndex,
+ int length)
+ {
+ FillReaderCache(columnIndex);
+ char[] charArr = ((CharsReaderCacheContainer)ReaderCache[columnIndex]).GetChars();
+ long actualLength = ((dataIndex + length) >= charArr.Length) ? (charArr.Length - dataIndex) : length;
+ Array.Copy(charArr,dataIndex,buffer,bufferIndex,actualLength);
+ return actualLength;
+ }
+
+ public override string GetDataTypeName(int columnIndex)
+ {
+ try {
+ if (ResultsMetaData == null) {
+ return String.Empty;
+ }
+ return ResultsMetaData.getColumnTypeName(columnIndex + 1);
+ }
+ catch (SQLException exp) {
+ throw CreateException(exp);
+ }
+ }
+
+ public override DateTime GetDateTime(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((DateTimeReaderCacheContainer)ReaderCache[columnIndex]).GetDateTime();
+ }
+
+ public virtual TimeSpan GetTimeSpan(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((TimeSpanReaderCacheContainer)ReaderCache[columnIndex]).GetTimeSpan();
+ }
+
+ public override Guid GetGuid(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((GuidReaderCacheContainer)ReaderCache[columnIndex]).GetGuid();
+ }
+
+ public override decimal GetDecimal(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((DecimalReaderCacheContainer)ReaderCache[columnIndex]).GetDecimal();
+ }
+
+ public decimal GetDecimalSafe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is DecimalReaderCacheContainer) {
+ return GetDecimal(columnIndex);
+ }
+ else {
+ return Convert.ToDecimal(GetValue(columnIndex));
+ }
+ }
+
+ public override double GetDouble(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((DoubleReaderCacheContainer)ReaderCache[columnIndex]).GetDouble();
+ }
+
+ public double GetDoubleSafe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is DoubleReaderCacheContainer) {
+ return GetDouble(columnIndex);
+ }
+ else {
+ return Convert.ToDouble(GetValue(columnIndex));
+ }
+ }
+
+ public override float GetFloat(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((FloatReaderCacheContainer)ReaderCache[columnIndex]).GetFloat();
+ }
+
+ public float GetFloatSafe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is FloatReaderCacheContainer) {
+ return GetFloat(columnIndex);
+ }
+ else {
+ return Convert.ToSingle(GetValue(columnIndex));
+ }
+ }
+
+ public override short GetInt16(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((Int16ReaderCacheContainer)ReaderCache[columnIndex]).GetInt16();
+ }
+
+ public short GetInt16Safe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is Int16ReaderCacheContainer) {
+ return GetInt16(columnIndex);
+ }
+ else {
+ return Convert.ToInt16(GetValue(columnIndex));
+ }
+ }
+
+ public override int GetInt32(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((Int32ReaderCacheContainer)ReaderCache[columnIndex]).GetInt32();
+ }
+
+ public int GetInt32Safe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is Int32ReaderCacheContainer) {
+ return GetInt32(columnIndex);
+ }
+ else {
+ return Convert.ToInt32(GetValue(columnIndex));
+ }
+ }
+
+ public override long GetInt64(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((Int64ReaderCacheContainer)ReaderCache[columnIndex]).GetInt64();
+ }
+
+ public long GetInt64Safe(int columnIndex)
+ {
+ if (ReaderCache[columnIndex] is Int64ReaderCacheContainer) {
+ return GetInt64(columnIndex);
+ }
+ else {
+ return Convert.ToInt64(GetValue(columnIndex));
+ }
+ }
+
+ public override string GetName(int columnIndex)
+ {
+ try {
+ if (ResultsMetaData == null) {
+ return String.Empty;
+ }
+ return ResultsMetaData.getColumnName(columnIndex + 1);
+ }
+ catch (SQLException exp) {
+ throw new IndexOutOfRangeException(exp.Message, exp);
+ }
+ }
+
+ public override int GetOrdinal(String columnName)
+ {
+ try {
+ int retVal = Results.findColumn(columnName);
+ if(retVal != -1) {
+ retVal -= 1;
+ }
+ return retVal;
+ }
+ catch (SQLException exp) {
+ throw new IndexOutOfRangeException(exp.Message, exp);
+ }
+ }
+
+ public override string GetString(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ((StringReaderCacheContainer)ReaderCache[columnIndex]).GetString();
+ }
+
+ public string GetStringSafe(int columnIndex) {
+ if (ReaderCache[columnIndex] is StringReaderCacheContainer) {
+ return GetString(columnIndex);
+ }
+ else {
+ return Convert.ToString(GetValue(columnIndex));
+ }
+ }
+
+ public override object GetValue(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ if (ReaderCache[columnIndex].IsNull()) {
+ return DBNull.Value;
+ }
+ return ReaderCache[columnIndex].GetValue();
+ }
+
+ public override int GetValues(Object[] values)
+ {
+ int columnCount = FieldCount;
+ int i = 0;
+ for (; i < values.Length && i < columnCount; i++) {
+ values[i] = GetValue(i);
+ }
+ return i;
+ }
+
+ private void FillReaderCache(int columnIndex)
+ {
+ try {
+ IReaderCacheContainer[] readerCache = ReaderCache;
+ if ((Behavior & CommandBehavior.SequentialAccess) == 0) {
+ while (_currentCacheFilledPosition < columnIndex) {
+ _currentCacheFilledPosition++;
+ readerCache[_currentCacheFilledPosition].Fetch(Results,_currentCacheFilledPosition);
+ }
+ }
+ else {
+ readerCache[columnIndex].Fetch(Results,columnIndex);
+ }
+ }
+ catch(SQLException e) {
+ _currentCacheFilledPosition = -1;
+ throw CreateException(e);
+ }
+ catch (IOException e) {
+ _currentCacheFilledPosition = -1;
+ throw CreateException(e);
+ }
+ }
+
+ private IReaderCacheContainer[] CreateReaderCache()
+ {
+ try {
+ IReaderCacheContainer[] readerCache = new IReaderCacheContainer[FieldCount];
+ for(int i=0; i < readerCache.Length; i++) {
+ DbTypes.JavaSqlTypes javaSqlType = (DbTypes.JavaSqlTypes) ResultsMetaData.getColumnType(i + 1);
+ switch (javaSqlType) {
+ case DbTypes.JavaSqlTypes.ARRAY :
+ readerCache[i] = new ArrayReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.BIGINT :
+ readerCache[i] = new Int64ReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.BINARY :
+ case DbTypes.JavaSqlTypes.VARBINARY :
+ case DbTypes.JavaSqlTypes.LONGVARBINARY :
+ readerCache[i] = new BytesReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.BIT :
+ readerCache[i] = new BooleanReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.BLOB :
+ readerCache[i] = new BlobReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.CHAR :
+ if ("uniqueidentifier".Equals(ResultsMetaData.getColumnTypeName(i + 1))) {
+ readerCache[i] = new GuidReaderCacheContainer();
+ }
+ else {
+ readerCache[i] = new StringReaderCacheContainer();
+ }
+ break;
+ case DbTypes.JavaSqlTypes.CLOB :
+ readerCache[i] = new ClobReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.TIME :
+ readerCache[i] = new TimeSpanReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.DATE :
+ AbstractDBConnection conn = (AbstractDBConnection)((ICloneable)_command.Connection);
+ string driverName = conn.JdbcConnection.getMetaData().getDriverName();
+
+ if (driverName.StartsWith("PostgreSQL")) {
+ readerCache[i] = new DateTimeReaderCacheContainer();
+ break;
+ }
+ else
+ goto case DbTypes.JavaSqlTypes.TIMESTAMP;
+ case DbTypes.JavaSqlTypes.TIMESTAMP :
+ readerCache[i] = new TimestampReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.DECIMAL :
+ case DbTypes.JavaSqlTypes.NUMERIC :
+ // jdbc driver for oracle identitfies both FLOAT and NUMBEr columns as
+ // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal
+ // therefore we relay on scale
+ int scale = ResultsMetaData.getScale(i + 1);
+ if (scale == -127) {
+ // Oracle db type FLOAT
+ readerCache[i] = new DoubleReaderCacheContainer();
+ }
+ else {
+ readerCache[i] = new DecimalReaderCacheContainer();
+ }
+ break;
+ case DbTypes.JavaSqlTypes.DOUBLE :
+ case DbTypes.JavaSqlTypes.FLOAT :
+ readerCache[i] = new DoubleReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.INTEGER :
+ readerCache[i] = new Int32ReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.LONGVARCHAR :
+ case DbTypes.JavaSqlTypes.VARCHAR :
+ readerCache[i] = new StringReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.NULL :
+ readerCache[i] = new NullReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.REAL :
+ readerCache[i] = new FloatReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.REF :
+ readerCache[i] = new RefReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.SMALLINT :
+ readerCache[i] = new Int16ReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.TINYINT :
+ readerCache[i] = new ByteReaderCacheContainer();
+ break;
+ case DbTypes.JavaSqlTypes.DISTINCT :
+ case DbTypes.JavaSqlTypes.JAVA_OBJECT :
+ case DbTypes.JavaSqlTypes.OTHER :
+ case DbTypes.JavaSqlTypes.STRUCT :
+ default :
+ readerCache[i] = new ObjectReaderCacheContainer();
+ break;
+ }
+ // ((ReaderCacheContainerBase)readerCache[i])._jdbcType = (int) javaSqlType;
+ }
+
+ return readerCache;
+ }
+ catch(SQLException e) {
+ throw CreateException(e);
+ }
+ }
+
+ public override bool IsDBNull(int columnIndex)
+ {
+ FillReaderCache(columnIndex);
+ return ReaderCache[columnIndex].IsNull();
+ }
+
+ public override Type GetFieldType(int i)
+ {
+ try {
+ int javaSqlType = ResultsMetaData.getColumnType(i + 1);
+ return DbConvert.JavaSqlTypeToClrType(javaSqlType);
+ }
+ catch (SQLException exp) {
+ throw new IndexOutOfRangeException(exp.Message, exp);
+ }
+ }
+
+ public IDataReader GetData(int i)
+ {
+ throw new NotSupportedException();
+ }
+
+ public override DataTable GetSchemaTable()
+ {
+ if (SchemaTable.Rows != null && SchemaTable.Rows.Count > 0) {
+ return SchemaTable;
+ }
+
+ ResultSetMetaData metaData;
+ if (Behavior == CommandBehavior.SchemaOnly) {
+ try {
+ metaData = ((PreparedStatement)_command.JdbcStatement).getMetaData();
+ }
+ catch(SQLException e) {
+ throw CreateException("CommandBehaviour.SchemaOnly is not supported by the JDBC driver.",e);
+ }
+ }
+ else {
+ metaData = ResultsMetaData;
+ }
+
+ if (metaData == null) {
+ return SchemaTable;
+ }
+
+ DatabaseMetaData dbMetaData = null;
+ AbstractDBConnection clonedConnection = null;
+ if ((_command.Behavior & CommandBehavior.KeyInfo) != 0) {
+ clonedConnection = (AbstractDBConnection)((ICloneable)_command.Connection).Clone();
+
+ try {
+ clonedConnection.Open();
+ dbMetaData = clonedConnection.JdbcConnection.getMetaData();
+ }
+ catch {
+ //suppress
+ if (clonedConnection != null) {
+ clonedConnection.Close();
+ }
+ }
+ }
+
+ try {
+ int tmp;
+ for(int i = 1; i <= metaData.getColumnCount(); i++) {
+ DataRow row = SchemaTable.NewRow ();
+ string columnName = metaData.getColumnLabel(i);
+ string baseColumnName = metaData.getColumnName(i);
+
+ row [(int)SCHEMA_TABLE.ColumnName] = columnName; // maybe we should use metaData.getColumnLabel(i);
+ row [(int)SCHEMA_TABLE.ColumnSize] = metaData.getColumnDisplaySize(i);
+ row [(int)SCHEMA_TABLE.ColumnOrdinal] = i - 1;
+ try {
+ // FIXME : workaround for Oracle JDBC driver bug
+ // getPrecision on BLOB, CLOB, NCLOB throws NumberFormatException
+ tmp = metaData.getPrecision(i);
+ }
+ catch(java.lang.NumberFormatException e) {
+ // supress exception
+ tmp = 255;
+ }
+ row [(int)SCHEMA_TABLE.NumericPrecision] = Convert.ToInt16(tmp > 255 ? 255 : tmp);
+ tmp = metaData.getScale(i);
+ row [(int)SCHEMA_TABLE.NumericScale] = Convert.ToInt16(tmp > 255 ? 255 : tmp);
+
+ row [(int)SCHEMA_TABLE.BaseServerName] = DBNull.Value;
+
+ string catalog = null;
+ try {
+ catalog = metaData.getCatalogName(i);
+ }
+ catch (Exception e) {
+ // supress exception
+ }
+ if (catalog != null && catalog.Length == 0)
+ catalog = ((AbstractDBConnection)_command.Connection).JdbcConnection.getCatalog();
+ row [(int)SCHEMA_TABLE.BaseCatalogName] = catalog;
+ row [(int)SCHEMA_TABLE.BaseColumnName] = baseColumnName;
+
+ string schemaName;
+ string tableName;
+
+ try {
+ tableName = metaData.getTableName(i);
+ }
+ catch {
+ tableName = null;
+ }
+
+ try {
+ schemaName = metaData.getSchemaName(i);
+ }
+ catch {
+ schemaName = null;
+ }
+
+ if (tableName != null && tableName.Length == 0)
+ tableName = null;
+ if (schemaName != null && schemaName.Length == 0)
+ schemaName = null;
+
+ row [(int)SCHEMA_TABLE.BaseSchemaName] = schemaName;
+ row [(int)SCHEMA_TABLE.BaseTableName] = tableName;
+
+
+ row [(int)SCHEMA_TABLE.AllowDBNull] = Convert.ToBoolean(metaData.isNullable(i));
+
+ InitKeyInfo(row, dbMetaData, catalog, schemaName, tableName);
+
+ row [(int)SCHEMA_TABLE.IsAliased] = columnName != baseColumnName;
+ row [(int)SCHEMA_TABLE.IsExpression] = false;
+
+ row [(int)SCHEMA_TABLE.IsAutoIncrement] = metaData.isAutoIncrement(i);
+
+ row [(int)SCHEMA_TABLE.IsHidden] = false;
+ row [(int)SCHEMA_TABLE.IsReadOnly] = metaData.isReadOnly(i);
+
+ int columnType = metaData.getColumnType(i);
+ string columnTypeName = metaData.getColumnTypeName(i);
+ if(columnType == Types.ARRAY) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Array);
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.BIGINT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt64;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.BINARY) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.BIT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfBoolean;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.BLOB) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.CHAR) {
+ // FIXME : specific for Microsoft SQl Server driver
+ if (columnTypeName.Equals("uniqueidentifier")) {
+ row [(int)SCHEMA_TABLE.ProviderType] = DbType.Guid;
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfGuid;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ }
+ else if(columnType == Types.CLOB) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString; // instead og .java.sql.Clob
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.DATE) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDateTime;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.DECIMAL) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDecimal;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ // else if(columnType == Types.DISTINCT)
+ // {
+ // row ["ProviderType = (int)GetProviderType(columnType);
+ // row ["DataType = typeof (?);
+ // row ["IsLong = false;
+ // }
+ else if(columnType == Types.DOUBLE) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble; // was typeof(float)
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.FLOAT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDouble;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.REAL) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfFloat;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.INTEGER) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt32;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.JAVA_OBJECT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.LONGVARBINARY) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.LONGVARCHAR) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.NUMERIC) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDecimal;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.REF) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Ref);
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.SMALLINT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfInt16;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.STRUCT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = typeof (java.sql.Struct);
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.TIME) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfTimespan;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.TIMESTAMP) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfDateTime;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.TINYINT) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByte;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else if(columnType == Types.VARBINARY) {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfByteArray;
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ else if(columnType == Types.VARCHAR) {
+ // FIXME : specific for Microsoft SQl Server driver
+ if (columnTypeName.Equals("sql_variant")) {
+ row [(int)SCHEMA_TABLE.ProviderType] = DbType.Object;
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else {
+ row [(int)SCHEMA_TABLE.ProviderType] = GetProviderType(columnType);
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;// (char[]);
+ row [(int)SCHEMA_TABLE.IsLong] = false;//true;
+ }
+ }
+ else if(columnType == -8 && columnTypeName.Equals("ROWID")) {
+ // FIXME : specific for Oracle JDBC driver : OracleTypes.ROWID
+ row [(int)SCHEMA_TABLE.ProviderType] = DbType.String;
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfString;
+ row [(int)SCHEMA_TABLE.IsLong] = false;
+ }
+ else {
+ row [(int)SCHEMA_TABLE.ProviderType] = DbType.Object;
+ row [(int)SCHEMA_TABLE.DataType] = DbTypes.TypeOfObject;
+ row [(int)SCHEMA_TABLE.IsLong] = true;
+ }
+ SchemaTable.Rows.Add (row);
+ }
+ }
+ catch (SQLException e) {
+ throw CreateException(e);
+ }
+ finally {
+ if (clonedConnection != null) {
+ clonedConnection.Close();
+ }
+ }
+ return SchemaTable;
+ }
+
+ private void InitKeyInfo(DataRow row, DatabaseMetaData dbMetaData, String catalog, String schema, String table) {
+ string column = (string)row [(int)SCHEMA_TABLE.BaseColumnName];
+
+ row [(int)SCHEMA_TABLE.IsUnique] = false;
+ row [(int)SCHEMA_TABLE.IsKey] = false;
+ row [(int)SCHEMA_TABLE.IsIdentity] = false;
+ row [(int)SCHEMA_TABLE.IsRowVersion] = false;
+
+ if ((_command.Behavior & CommandBehavior.KeyInfo) == 0)
+ return;
+
+ if(table == null || column == null || dbMetaData == null)
+ return;
+
+ ResultSet indexInfoRes = dbMetaData.getIndexInfo(catalog,schema,table,true,false);
+ try {
+ while(indexInfoRes.next()) {
+ if(indexInfoRes.getString("COLUMN_NAME") == column)
+ row [(int)SCHEMA_TABLE.IsUnique] = true;
+ }
+ }
+ finally {
+ indexInfoRes.close();
+ }
+
+ ResultSet versionCol = dbMetaData.getVersionColumns(catalog, schema, table);
+ try {
+ while(versionCol.next()) {
+ if(versionCol.getString("COLUMN_NAME") == column) {
+ if (DatabaseMetaData__Finals.versionColumnPseudo == versionCol.getShort("PSEUDO_COLUMN")) {
+ row [(int)SCHEMA_TABLE.IsIdentity] = true;
+ row [(int)SCHEMA_TABLE.IsRowVersion] = true;
+ }
+ }
+ }
+ }
+ finally {
+ versionCol.close();
+ }
+
+ ResultSet bestRowId = dbMetaData.getBestRowIdentifier(catalog, schema, table, DatabaseMetaData__Finals.bestRowTemporary, false);
+ try {
+ while(bestRowId.next()) {
+ if(bestRowId.getString("COLUMN_NAME") == column)
+ row [(int)SCHEMA_TABLE.IsKey] = true;
+ }
+ }
+ finally {
+ bestRowId.close();
+ }
+ }
+
+ protected static DataTable ConstructSchemaTable ()
+ {
+ Type booleanType = DbTypes.TypeOfBoolean;
+ Type stringType = DbTypes.TypeOfString;
+ Type intType = DbTypes.TypeOfInt32;
+ Type typeType = DbTypes.TypeOfType;
+ Type shortType = DbTypes.TypeOfInt16;
+
+ DataTable schemaTable = new DataTable ("SchemaTable");
+ schemaTable.Columns.Add ("ColumnName", stringType);
+ schemaTable.Columns.Add ("ColumnOrdinal", intType);
+ schemaTable.Columns.Add ("ColumnSize", intType);
+ schemaTable.Columns.Add ("NumericPrecision", shortType);
+ schemaTable.Columns.Add ("NumericScale", shortType);
+ schemaTable.Columns.Add ("IsUnique", booleanType);
+ schemaTable.Columns.Add ("IsKey", booleanType);
+ schemaTable.Columns.Add ("BaseServerName", stringType);
+ schemaTable.Columns.Add ("BaseCatalogName", stringType);
+ schemaTable.Columns.Add ("BaseColumnName", stringType);
+ schemaTable.Columns.Add ("BaseSchemaName", stringType);
+ schemaTable.Columns.Add ("BaseTableName", stringType);
+ schemaTable.Columns.Add ("DataType", typeType);
+ schemaTable.Columns.Add ("AllowDBNull", booleanType);
+ schemaTable.Columns.Add ("ProviderType", intType);
+ schemaTable.Columns.Add ("IsAliased", booleanType);
+ schemaTable.Columns.Add ("IsExpression", booleanType);
+ schemaTable.Columns.Add ("IsIdentity", booleanType);
+ schemaTable.Columns.Add ("IsAutoIncrement", booleanType);
+ schemaTable.Columns.Add ("IsRowVersion", booleanType);
+ schemaTable.Columns.Add ("IsHidden", booleanType);
+ schemaTable.Columns.Add ("IsLong", booleanType);
+ schemaTable.Columns.Add ("IsReadOnly", booleanType);
+ return schemaTable;
+ }
+
+ #endregion // Methods
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/AbstractTransaction.cs b/mcs/class/System.Data/System.Data.Common/AbstractTransaction.cs
new file mode 100644
index 00000000000..586976b19b0
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/AbstractTransaction.cs
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 2002-2004 Mainsoft Corporation.
+ *
+ * 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.
+ */
+
+namespace System.Data.Common
+{
+
+ using java.sql;
+
+ using System.Data;
+ /**
+ * @author erand
+ */
+ public abstract class AbstractTransaction : DbTransaction
+ {
+
+ protected String _transactionName;
+ protected AbstractDBConnection _connection;
+
+ protected IsolationLevel _isolationLevel;
+
+ public AbstractTransaction(
+ IsolationLevel isolationLevel,
+ AbstractDBConnection connection,
+ String transactionName)
+ {
+ connection.ValidateBeginTransaction();
+ _transactionName = transactionName;
+ _connection = connection;
+ _isolationLevel = isolationLevel;
+ try
+ {
+ _connection.JdbcConnection.setAutoCommit(false);
+ _connection.JdbcConnection.setTransactionIsolation(
+ convertIsolationLevel(isolationLevel));
+ }
+ catch (SQLException exp)
+ {
+ throw new System.InvalidOperationException(exp.Message);
+ }
+ }
+
+
+ /**
+ * @see System.Data.IDbTransaction#Connection
+ */
+ protected override DbConnection DbConnection
+ {
+ get
+ {
+ return _connection;
+ }
+ }
+
+ /**
+ * @see System.Data.IDbTransaction#IsolationLevel
+ */
+ public override IsolationLevel IsolationLevel
+ {
+ get
+ {
+ return _isolationLevel;
+ }
+ }
+
+ /**
+ * @see System.Data.IDbTransaction#Commit()
+ */
+ public override void Commit()
+ {
+ if (_connection == null)
+ return;
+
+ try
+ {
+ _connection.JdbcConnection.commit();
+ _connection.JdbcConnection.setAutoCommit(true);
+ _connection = null;
+ }
+ catch (SQLException exp)
+ {
+ throw new SystemException(exp.Message);
+ }
+ }
+
+ /**
+ * @see System.Data.IDbTransaction#Rollback()
+ */
+ public override void Rollback()
+ {
+ if (_connection == null)
+ return;
+
+ try
+ {
+ _connection.JdbcConnection.rollback();
+ _connection = null;
+ }
+ catch (SQLException exp)
+ {
+ throw new SystemException(exp.Message);
+ }
+ }
+
+ public override void Dispose()
+ {
+ Rollback();
+ }
+
+ internal AbstractTransaction ActiveTransaction {
+ get {
+ // recoursively return parent transaction when nesting will
+ // be implemented
+ return _connection != null ? this : null;
+ }
+ }
+
+ private int convertIsolationLevel(IsolationLevel isolationLevel)
+ {
+ if (isolationLevel == IsolationLevel.Unspecified)
+ return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_NONE;
+ if (isolationLevel == IsolationLevel.ReadCommitted)
+ return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_READ_COMMITTED;
+ if (isolationLevel == IsolationLevel.ReadUncommitted)
+ return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_READ_UNCOMMITTED;
+ if (isolationLevel == IsolationLevel.RepeatableRead)
+ return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_REPEATABLE_READ;
+ if (isolationLevel == IsolationLevel.Serializable)
+ return vmw.@internal.sql.ConnectionUtils__Finals.TRANSACTION_SERIALIZABLE;
+
+ throw new NotSupportedException("The Isolation level '" + isolationLevel + "' is not supported");
+ }
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/CallableStatementWrapper.cs b/mcs/class/System.Data/System.Data.Common/CallableStatementWrapper.cs
new file mode 100644
index 00000000000..b657bf3ca22
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/CallableStatementWrapper.cs
@@ -0,0 +1,320 @@
+using System;
+
+using java.sql;
+using java.util;
+
+namespace System.Data.Common
+{
+ public class CallableStatementWrapper : ResultSet
+ {
+ #region Fields
+
+ CallableStatement _callableStatement;
+
+ #endregion // Fields
+
+ #region Constructors
+
+ public CallableStatementWrapper(CallableStatement callableStatement)
+ {
+ _callableStatement = callableStatement;
+ }
+
+ #endregion // constructors
+
+ #region Methods
+
+ public int getConcurrency() { throw new NotImplementedException(); }
+
+ public int getFetchDirection() { throw new NotImplementedException(); }
+
+ public int getFetchSize() { throw new NotImplementedException(); }
+
+ public int getRow() { throw new NotImplementedException(); }
+
+ public int getType() { throw new NotImplementedException(); }
+
+ public void afterLast() { throw new NotImplementedException(); }
+
+ public void beforeFirst() { throw new NotImplementedException(); }
+
+ public void cancelRowUpdates() { throw new NotImplementedException(); }
+
+ public void clearWarnings() { throw new NotImplementedException(); }
+
+ public void close() { throw new NotImplementedException(); }
+
+ public void deleteRow() { throw new NotImplementedException(); }
+
+ public void insertRow() { throw new NotImplementedException(); }
+
+ public void moveToCurrentRow() { throw new NotImplementedException(); }
+
+ public void moveToInsertRow() { throw new NotImplementedException(); }
+
+ public void refreshRow() { throw new NotImplementedException(); }
+
+ public void updateRow() { throw new NotImplementedException(); }
+
+ public bool first() { throw new NotImplementedException(); }
+
+ public bool isAfterLast() { throw new NotImplementedException(); }
+
+ public bool isBeforeFirst() { throw new NotImplementedException(); }
+
+ public bool isFirst() { throw new NotImplementedException(); }
+
+ public bool isLast() { throw new NotImplementedException(); }
+
+ public bool last() { throw new NotImplementedException(); }
+
+ public bool next() { throw new NotImplementedException(); }
+
+ public bool previous() { throw new NotImplementedException(); }
+
+ public bool rowDeleted() { throw new NotImplementedException(); }
+
+ public bool rowInserted() { throw new NotImplementedException(); }
+
+ public bool rowUpdated() { throw new NotImplementedException(); }
+
+ public bool wasNull() { return _callableStatement.wasNull(); }
+
+ public sbyte getByte(int i) { return _callableStatement.getByte(i); }
+
+ public double getDouble(int i) { return _callableStatement.getDouble(i); }
+
+ public float getFloat(int i) { return _callableStatement.getFloat(i); }
+
+ public int getInt(int i) { return _callableStatement.getInt(i); }
+
+ public long getLong(int i) { return _callableStatement.getLong(i); }
+
+ public short getShort(int i) { return _callableStatement.getShort(i); }
+
+ public void setFetchDirection(int i) { throw new NotImplementedException(); }
+
+ public void setFetchSize(int i) { throw new NotImplementedException(); }
+
+ public void updateNull(int i) { throw new NotImplementedException(); }
+
+ public bool absolute(int i) { throw new NotImplementedException(); }
+
+ public bool getBoolean(int i) { return _callableStatement.getBoolean(i); }
+
+ public bool relative(int i) { throw new NotImplementedException(); }
+
+ public sbyte[] getBytes(int i) { return _callableStatement.getBytes(i); }
+
+ public void updateByte(int i, sbyte b) { throw new NotImplementedException(); }
+
+ public void updateDouble(int i, double v) { throw new NotImplementedException(); }
+
+ public void updateFloat(int i, float v) { throw new NotImplementedException(); }
+
+ public void updateInt(int i, int i1) { throw new NotImplementedException(); }
+
+ public void updateLong(int i, long l) { throw new NotImplementedException(); }
+
+ public void updateShort(int i, short i1) { throw new NotImplementedException(); }
+
+ public void updateBoolean(int i, bool b) { throw new NotImplementedException(); }
+
+ public void updateBytes(int i, sbyte[] bytes) { throw new NotImplementedException(); }
+
+ public java.io.InputStream getAsciiStream(int i) { throw new NotImplementedException(); }
+
+ public java.io.InputStream getBinaryStream(int i) { throw new NotImplementedException(); }
+
+ /**
+ * @deprecated
+ */
+ public java.io.InputStream getUnicodeStream(int i) { throw new NotImplementedException(); }
+
+ public void updateAsciiStream(int i, java.io.InputStream inputStream, int i1) { throw new NotImplementedException(); }
+
+ public void updateBinaryStream(int i, java.io.InputStream inputStream, int i1) { throw new NotImplementedException(); }
+
+ public java.io.Reader getCharacterStream(int i) { throw new NotImplementedException(); }
+
+ public void updateCharacterStream(int i, java.io.Reader reader, int i1) { throw new NotImplementedException(); }
+
+ public Object getObject(int i) { return _callableStatement.getObject(i); }
+
+ public void updateObject(int i, Object o) { throw new NotImplementedException(); }
+
+ public void updateObject(int i, Object o, int i1) { throw new NotImplementedException(); }
+
+ public String getCursorName() { throw new NotImplementedException(); }
+
+ public String getString(int i) { return _callableStatement.getString(i); }
+
+ public void updateString(int i, String s) { throw new NotImplementedException(); }
+
+ public sbyte getByte(String s) { return _callableStatement.getByte(s); }
+
+ public double getDouble(String s) { return _callableStatement.getDouble(s); }
+
+ public float getFloat(String s) { return _callableStatement.getFloat(s); }
+
+ public int findColumn(String s) { throw new NotImplementedException(); }
+
+ public int getInt(String s) { return _callableStatement.getInt(s); }
+
+ public long getLong(String s) { return _callableStatement.getLong(s); }
+
+ public short getShort(String s) { return _callableStatement.getShort(s); }
+
+ public void updateNull(String s) { throw new NotImplementedException(); }
+
+ public bool getBoolean(String s) { return _callableStatement.getBoolean(s); }
+
+ public sbyte[] getBytes(String s) { return _callableStatement.getBytes(s); }
+
+ public void updateByte(String s, sbyte b) { throw new NotImplementedException(); }
+
+ public void updateDouble(String s, double v) { throw new NotImplementedException(); }
+
+ public void updateFloat(String s, float v) { throw new NotImplementedException(); }
+
+ public void updateInt(String s, int i) { throw new NotImplementedException(); }
+
+ public void updateLong(String s, long l) { throw new NotImplementedException(); }
+
+ public void updateShort(String s, short i) { throw new NotImplementedException(); }
+
+ public void updateBoolean(String s, bool b) { throw new NotImplementedException(); }
+
+ public void updateBytes(String s, sbyte[] bytes) { throw new NotImplementedException(); }
+
+ public java.math.BigDecimal getBigDecimal(int i) { return _callableStatement.getBigDecimal(i); }
+
+ /**
+ * @deprecated
+ */
+ public java.math.BigDecimal getBigDecimal(int i, int i1) { throw new NotImplementedException(); }
+
+ public void updateBigDecimal(int i, java.math.BigDecimal bigDecimal) { throw new NotImplementedException(); }
+
+ public java.net.URL getURL(int i) { throw new NotImplementedException(); }
+
+ public java.sql.Array getArray(int i) { return _callableStatement.getArray(i); }
+
+ public void updateArray(int i, java.sql.Array array) { throw new NotImplementedException(); }
+
+ public Blob getBlob(int i) { return _callableStatement.getBlob(i); }
+
+ public void updateBlob(int i, Blob blob) { throw new NotImplementedException(); }
+
+ public Clob getClob(int i) { return _callableStatement.getClob(i); }
+
+ public void updateClob(int i, Clob clob) { throw new NotImplementedException(); }
+
+ public java.sql.Date getDate(int i) { return _callableStatement.getDate(i); }
+
+ public void updateDate(int i, java.sql.Date date) { throw new NotImplementedException(); }
+
+ public Ref getRef(int i) { return _callableStatement.getRef(i); }
+
+ public void updateRef(int i, Ref rf) { throw new NotImplementedException(); }
+
+ public ResultSetMetaData getMetaData() { throw new NotImplementedException(); }
+
+ public SQLWarning getWarnings() { throw new NotImplementedException(); }
+
+ public Statement getStatement() { throw new NotImplementedException(); }
+
+ public Time getTime(int i) { return _callableStatement.getTime(i); }
+
+ public void updateTime(int i, Time time) { throw new NotImplementedException(); }
+
+ public Timestamp getTimestamp(int i) { return _callableStatement.getTimestamp(i); }
+
+ public void updateTimestamp(int i, Timestamp timestamp) { throw new NotImplementedException(); }
+
+ public java.io.InputStream getAsciiStream(String s) { throw new NotImplementedException(); }
+
+ public java.io.InputStream getBinaryStream(String s) { throw new NotImplementedException(); }
+
+ /**
+ * @deprecated
+ */
+ public java.io.InputStream getUnicodeStream(String s) { throw new NotImplementedException(); }
+
+ public void updateAsciiStream(String s, java.io.InputStream inputStream, int i) { throw new NotImplementedException(); }
+
+ public void updateBinaryStream(String s, java.io.InputStream inputStream, int i) { throw new NotImplementedException(); }
+
+ public java.io.Reader getCharacterStream(String s) { throw new NotImplementedException(); }
+
+ public void updateCharacterStream(String s, java.io.Reader reader, int i) { throw new NotImplementedException(); }
+
+ public Object getObject(String s) { return _callableStatement.getObject(s); }
+
+ public void updateObject(String s, Object o) { throw new NotImplementedException(); }
+
+ public void updateObject(String s, Object o, int i) { throw new NotImplementedException(); }
+
+ public Object getObject(int i, Map map) { throw new NotImplementedException(); }
+
+ public String getString(String s) { return _callableStatement.getString(s); }
+
+ public void updateString(String s, String s1) { throw new NotImplementedException(); }
+
+ public java.math.BigDecimal getBigDecimal(String s) { return _callableStatement.getBigDecimal(s); }
+
+ /**
+ * @deprecated
+ */
+ public java.math.BigDecimal getBigDecimal(String s, int i) { throw new NotImplementedException(); }
+
+ public void updateBigDecimal(String s, java.math.BigDecimal bigDecimal) { throw new NotImplementedException(); }
+
+ public java.net.URL getURL(String s) { throw new NotImplementedException(); }
+
+ public java.sql.Array getArray(String s) { return _callableStatement.getArray(s); }
+
+ public void updateArray(String s, java.sql.Array array) { throw new NotImplementedException(); }
+
+ public Blob getBlob(String s) { return _callableStatement.getBlob(s); }
+
+ public void updateBlob(String s, Blob blob) { throw new NotImplementedException(); }
+
+ public Clob getClob(String s) { return _callableStatement.getClob(s); }
+
+ public void updateClob(String s, Clob clob) { throw new NotImplementedException(); }
+
+ public java.sql.Date getDate(String s) { return _callableStatement.getDate(s); }
+
+ public void updateDate(String s, java.sql.Date date) { throw new NotImplementedException(); }
+
+ public java.sql.Date getDate(int i, Calendar calendar) { throw new NotImplementedException(); }
+
+ public Ref getRef(String s) { return _callableStatement.getRef(s); }
+
+ public void updateRef(String s, Ref rf) { throw new NotImplementedException(); }
+
+ public Time getTime(String s) { return _callableStatement.getTime(s); }
+
+ public void updateTime(String s, Time time) { throw new NotImplementedException(); }
+
+ public Time getTime(int i, Calendar calendar) { throw new NotImplementedException(); }
+
+ public Timestamp getTimestamp(String s) { return _callableStatement.getTimestamp(s); }
+
+ public void updateTimestamp(String s, Timestamp timestamp) { throw new NotImplementedException(); }
+
+ public Timestamp getTimestamp(int i, Calendar calendar) { throw new NotImplementedException(); }
+
+ public Object getObject(String s, Map map) { throw new NotImplementedException(); }
+
+ public java.sql.Date getDate(String s, Calendar calendar) { throw new NotImplementedException(); }
+
+ public Time getTime(String s, Calendar calendar) { throw new NotImplementedException(); }
+
+ public Timestamp getTimestamp(String s, Calendar calendar) { throw new NotImplementedException(); }
+
+ #endregion // Methods
+
+ }
+}
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
index 00000000000..d88969edc76
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/DbConvert.cs
@@ -0,0 +1,330 @@
+//
+// System.Data.Common.DbConvert
+//
+// Author:
+// Boris Kirzner (borisk@mainsoft.com)
+//
+
+using System;
+
+using java.io;
+using java.sql;
+
+namespace System.Data.Common
+{
+ internal class DbConvert
+ {
+ #region Fields
+
+ const long JAVA_MIN_MILLIS_UTC = -62135769600000L; // java.sql.Timestamp.valueOf("0001-01-01 00:00:00.000000000").getTime() at Greenwich time zone.
+ static readonly long TIMEZONE_RAW_OFFSET;
+ // .NET milliseconds value of DateTime(1582,1,1,0,0,0,0).Ticks/TimeSpan.TicksPerMillisecond
+ const long CLR_MILLIS_1582 = 49891507200000L;
+ const long MILLIS_PER_TWO_DAYS = 2 * TimeSpan.TicksPerDay / TimeSpan.TicksPerMillisecond; // 172800000L;
+ internal static readonly java.util.TimeZone DEFAULT_TIME_ZONE;
+
+ #endregion // Fields
+
+ #region Methods
+
+ static DbConvert()
+ {
+ DEFAULT_TIME_ZONE = java.util.SimpleTimeZone.getDefault();
+ TIMEZONE_RAW_OFFSET = (long)DEFAULT_TIME_ZONE.getRawOffset();
+ }
+
+ // The diff between .Net and Java goes as the following:
+ // * at 1582: java has 10 days less than .net
+ // * below 1500 (exept 1200,800,400) : each 100'th year java adds 1 day over .net.
+ // Current implementation compatible with .net in 1-99 and since 1582. In 100-1582 we're not compatible with .Ner nor with Java
+
+ internal static long JavaMillisToClrMillis(long javaMillis)
+ {
+ return JavaMillisToClrMillisUTC(javaMillis) + TIMEZONE_RAW_OFFSET;
+ }
+
+ internal static long JavaMillisToClrMillisUTC(long javaMillis) {
+ long clrMillis = javaMillis - JAVA_MIN_MILLIS_UTC;
+ if (clrMillis > CLR_MILLIS_1582) {
+ clrMillis -= MILLIS_PER_TWO_DAYS;
+ }
+ return clrMillis;
+ }
+
+ internal static long ClrMillisToJavaMillis(long clrMillis)
+ {
+ return ClrMillisToJavaMillisUTC(clrMillis) - TIMEZONE_RAW_OFFSET;
+ }
+
+ internal static long ClrMillisToJavaMillisUTC(long clrMillis) {
+ long javaMillis = clrMillis + JAVA_MIN_MILLIS_UTC;
+ if (clrMillis > CLR_MILLIS_1582) {
+ javaMillis += MILLIS_PER_TWO_DAYS;
+ }
+ return javaMillis;
+ }
+
+ internal static java.sql.Time ClrTicksToJavaTime(long ticks) {
+ return new Time((ticks / TimeSpan.TicksPerMillisecond)
+ - DEFAULT_TIME_ZONE.getRawOffset());
+ }
+
+ internal static java.sql.Date ClrTicksToJavaDate(long ticks) {
+ java.sql.Date d = new java.sql.Date(0);
+ ClrTicksToJavaDate(d, ticks);
+ return d;
+ }
+
+ internal static java.sql.Timestamp ClrTicksToJavaTimestamp(long ticks)
+ {
+ java.sql.Timestamp ts = new java.sql.Timestamp(0);
+ ClrTicksToJavaDate(ts, ticks);
+
+// int nanos = (int)(ticks % TimeSpan.TicksPerMillisecond) * 100;
+// ts.setNanos(javaTimestamp.getNanos() + nanos);
+
+ return ts;
+ }
+
+ internal static void ClrTicksToJavaDate(java.util.Date d, long ticks) {
+ long millis = ClrMillisToJavaMillis(ticks / TimeSpan.TicksPerMillisecond);
+
+ d.setTime(millis);
+ if (DEFAULT_TIME_ZONE.inDaylightTime(d)) {
+ millis -= DEFAULT_TIME_ZONE.getDSTSavings();
+ d.setTime(millis);
+ }
+ }
+
+ internal static long JavaTimestampToClrTicks(java.sql.Timestamp ts)
+ {
+ long ticks = JavaDateToClrTicks(ts);
+ // Extra ticks, for dbs that can save them.
+ // We do not use it, since .net does not saves ticks for fractial milliseconds
+ // long ticksLessThanMilliseconds = (ts.getNanos()*100) % TimeSpan.TicksPerMillisecond;
+ // ticks += ticksLessThanMilliseconds;
+
+ return ticks;
+ }
+
+ internal static long JavaDateToClrTicks(java.util.Date d) {
+ long millis = JavaMillisToClrMillis(d.getTime());
+ if (DEFAULT_TIME_ZONE.inDaylightTime(d)) {
+ millis += DEFAULT_TIME_ZONE.getDSTSavings();
+ }
+ return millis * TimeSpan.TicksPerMillisecond;
+ }
+
+ internal static long JavaTimeToClrTicks(java.sql.Time t) {
+ return (t.getTime() + DEFAULT_TIME_ZONE.getRawOffset())
+ * TimeSpan.TicksPerMillisecond;
+ }
+
+ internal protected static Type JavaSqlTypeToClrType(int sqlTypeValue)
+ {
+ DbTypes.JavaSqlTypes sqlType = (DbTypes.JavaSqlTypes)sqlTypeValue;
+
+ switch (sqlType) {
+ case DbTypes.JavaSqlTypes.ARRAY : return typeof (java.sql.Array);
+ case DbTypes.JavaSqlTypes.BIGINT : return DbTypes.TypeOfInt64;
+ case DbTypes.JavaSqlTypes.BINARY : return DbTypes.TypeOfByteArray;
+ case DbTypes.JavaSqlTypes.BIT : return DbTypes.TypeOfBoolean;
+ case DbTypes.JavaSqlTypes.BLOB : return DbTypes.TypeOfByteArray;
+ case DbTypes.JavaSqlTypes.BOOLEAN : return DbTypes.TypeOfBoolean;
+ case DbTypes.JavaSqlTypes.CHAR : return DbTypes.TypeOfString;
+ case DbTypes.JavaSqlTypes.CLOB : return DbTypes.TypeOfString;
+// case DbTypes.JavaSqlTypes.DATALINK :
+ case DbTypes.JavaSqlTypes.DATE : return DbTypes.TypeOfDateTime;
+ case DbTypes.JavaSqlTypes.DECIMAL : return DbTypes.TypeOfDecimal;
+// case DbTypes.JavaSqlTypes.DISTINCT :
+ case DbTypes.JavaSqlTypes.DOUBLE : return DbTypes.TypeOfDouble;
+ case DbTypes.JavaSqlTypes.FLOAT : return DbTypes.TypeOfDouble;
+ case DbTypes.JavaSqlTypes.INTEGER : return DbTypes.TypeOfInt32;
+// case DbTypes.JavaSqlTypes.JAVA_OBJECT :
+ case DbTypes.JavaSqlTypes.LONGVARBINARY : return DbTypes.TypeOfByteArray;
+ case DbTypes.JavaSqlTypes.LONGVARCHAR : return DbTypes.TypeOfString;
+ case DbTypes.JavaSqlTypes.NULL : return null;
+ case DbTypes.JavaSqlTypes.NUMERIC : return DbTypes.TypeOfDecimal;
+// case DbTypes.JavaSqlTypes.OTHER :
+ case DbTypes.JavaSqlTypes.REAL : return DbTypes.TypeOfSingle;
+ case DbTypes.JavaSqlTypes.REF : return typeof (java.sql.Ref);
+ case DbTypes.JavaSqlTypes.SMALLINT : return DbTypes.TypeOfInt16;
+ case DbTypes.JavaSqlTypes.STRUCT : return typeof (java.sql.Struct);
+ case DbTypes.JavaSqlTypes.TIME : return DbTypes.TypeOfTimespan;
+ case DbTypes.JavaSqlTypes.TIMESTAMP : return DbTypes.TypeOfDateTime;
+ case DbTypes.JavaSqlTypes.TINYINT : return DbTypes.TypeOfByte;
+ case DbTypes.JavaSqlTypes.VARBINARY : return DbTypes.TypeOfByteArray;
+ case DbTypes.JavaSqlTypes.VARCHAR : return DbTypes.TypeOfString;
+ default : return DbTypes.TypeOfObject;
+ }
+
+ }
+
+
+ internal protected static object JavaResultSetToClrWrapper(CallableStatement results,int columnIndex,DbTypes.JavaSqlTypes javaSqlType,int maxLength ,ResultSetMetaData resultsMetaData)
+ {
+ object returnValue = null;
+ sbyte[] sbyteArray;
+ long milliseconds;
+ long ticks;
+ string s;
+ columnIndex++; //jdbc style
+ switch (javaSqlType) {
+ case DbTypes.JavaSqlTypes.ARRAY :
+ returnValue = results.getArray(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.BIGINT :
+ returnValue = results.getLong(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.BINARY :
+ case DbTypes.JavaSqlTypes.VARBINARY :
+ case DbTypes.JavaSqlTypes.LONGVARBINARY :
+ // FIXME : comsider using maxLength
+ sbyteArray = results.getBytes(columnIndex);
+ if (sbyteArray != null) {
+ returnValue = vmw.common.TypeUtils.ToByteArray(sbyteArray);
+ }
+ break;
+ case DbTypes.JavaSqlTypes.BIT :
+ returnValue = results.getBoolean(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.BLOB :
+ // FIXME : comsider using maxLength
+ java.sql.Blob blob = results.getBlob(columnIndex);
+ if (blob != null) {
+ InputStream input = blob.getBinaryStream();
+ if (input == null) {
+ returnValue = new byte[0];
+ }
+ else {
+ long length = blob.length();
+ byte[] byteValue = new byte[length];
+ sbyte[] sbyteValue = vmw.common.TypeUtils.ToSByteArray(byteValue);
+ input.read(sbyteValue);
+ returnValue = byteValue;
+ }
+ }
+ break;
+ case DbTypes.JavaSqlTypes.CHAR :
+ if (resultsMetaData != null && "uniqueidentifier".Equals(resultsMetaData.getColumnTypeName(columnIndex))) {
+ returnValue = new Guid(results.getString(columnIndex));
+ }
+ else {
+ // Oracle Jdbc driver returns extra trailing 0 chars for NCHAR columns, so we threat this at parameter.Size level
+ s = results.getString(columnIndex);
+ if ((s != null) && (maxLength < s.Length)) {
+ s = s.Substring(0,maxLength);
+ }
+ returnValue = s;
+ }
+ break;
+ case DbTypes.JavaSqlTypes.CLOB :
+ // FIXME : comsider using maxLength
+ java.sql.Clob clob = results.getClob(columnIndex);
+ if (clob != null) {
+ java.io.Reader reader = clob.getCharacterStream();
+ if (reader == null) {
+ returnValue = String.Empty;
+ }
+ else {
+ long length = clob.length();
+ char[] charValue = new char[length];
+ reader.read(charValue);
+ returnValue = new string(charValue);
+ }
+ }
+ break;
+ case DbTypes.JavaSqlTypes.TIME :
+ Time t = results.getTime(columnIndex);
+ if (t != null) {
+ returnValue = new TimeSpan(JavaTimeToClrTicks(t));
+ }
+ break;
+ case DbTypes.JavaSqlTypes.DATE :
+ Date d = results.getDate(columnIndex);
+ if (d != null) {
+ returnValue = new DateTime(JavaDateToClrTicks(d));
+ }
+ break;
+ case DbTypes.JavaSqlTypes.TIMESTAMP :
+ Timestamp ts = results.getTimestamp(columnIndex);
+ if (ts != null) {
+ returnValue = new DateTime(JavaTimestampToClrTicks(ts));
+ }
+ break;
+ case DbTypes.JavaSqlTypes.DECIMAL :
+ case DbTypes.JavaSqlTypes.NUMERIC :
+ // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal
+ // therefore we rely on scale
+ if (resultsMetaData != null && resultsMetaData.getScale(columnIndex) == -127) {
+ // Oracle db type FLOAT
+ returnValue = results.getDouble(columnIndex);
+ }
+ else {
+ java.math.BigDecimal bigDecimal = results.getBigDecimal(columnIndex);
+ if (bigDecimal != null) {
+ returnValue = vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bigDecimal);
+ }
+ }
+ break;
+ case DbTypes.JavaSqlTypes.DISTINCT :
+ returnValue = results.getObject(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.DOUBLE :
+ returnValue = results.getDouble(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.FLOAT :
+ //float f = results.getFloat(columnIndex);
+ returnValue = results.getDouble(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.INTEGER :
+ returnValue = results.getInt(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.JAVA_OBJECT :
+ returnValue = results.getObject(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.LONGVARCHAR :
+ returnValue = results.getString(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.NULL :
+ returnValue = DBNull.Value;
+ break;
+ case DbTypes.JavaSqlTypes.OTHER :
+ returnValue = results.getObject(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.REAL :
+ returnValue = results.getFloat(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.REF :
+ returnValue = results.getRef(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.SMALLINT :
+ returnValue = results.getShort(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.STRUCT :
+ returnValue = results.getObject(columnIndex);
+ break;
+ case DbTypes.JavaSqlTypes.TINYINT :
+ returnValue = Convert.ToByte(results.getByte(columnIndex));
+ break;
+ case DbTypes.JavaSqlTypes.VARCHAR :
+ s = results.getString(columnIndex);
+ if ((s != null) && (maxLength < s.Length)) {
+ s = s.Substring(0,maxLength);
+ }
+ returnValue = s;
+ break;
+ default :
+ returnValue = results.getObject(columnIndex);
+ break;
+ }
+
+ if (results.wasNull() || results == null) {
+ return DBNull.Value;
+ }
+ return returnValue;
+ }
+
+ #endregion // Methods
+ }
+}
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
index 00000000000..ee279b1ecb0
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/DbMetaDataCache.cs
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2002-2004 Mainsoft Corporation.
+ *
+ * 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 java.sql;
+
+namespace System.Data.Common
+{
+ #region AbstractDbMetaDataCache
+
+ internal abstract class AbstractDbMetaDataCache
+ {
+ Hashtable _cache;
+ const int MINUTES_TIMEOUT = 10;
+ private long _timestamp;
+
+ protected AbstractDbMetaDataCache()
+ {
+ _cache = Hashtable.Synchronized(new Hashtable());
+ }
+
+ protected Hashtable Cache
+ {
+ get
+ {
+ long now = DateTime.Now.Ticks;
+ if (now - _timestamp > MINUTES_TIMEOUT * TimeSpan.TicksPerMinute)
+ {
+ _timestamp = now;
+ _cache.Clear();
+ }
+
+ return _cache;
+ }
+ }
+ }
+
+ #endregion
+}
diff --git a/mcs/class/System.Data/System.Data.Common/DbPortResolver.cs b/mcs/class/System.Data/System.Data.Common/DbPortResolver.cs
new file mode 100644
index 00000000000..d1523198354
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/DbPortResolver.cs
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2002-2004 Mainsoft Corporation.
+ *
+ * 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 java.net;
+
+namespace System.Data.Common
+{
+ public class DbPortResolver
+ {
+ public static int getMSSqlPort(String sqlName, String instanceName,int timeout)
+ {
+ int port = -1;
+ try
+ {
+ DatagramSocket socket = new DatagramSocket();
+
+ // send request
+ sbyte[] buf = new sbyte[] {2};
+ InetAddress address = InetAddress.getByName(sqlName);
+ DatagramPacket packet = new DatagramPacket(buf, buf.Length, address, 1434);
+ socket.send(packet);
+ sbyte[] recbuf = new sbyte[1024];
+ packet = new DatagramPacket(recbuf, recbuf.Length, packet.getAddress(), packet.getPort());
+
+ // try to receive from socket while increasing timeouts in geometric progression
+ int iterationTimeout = 1;
+ int totalTimeout = 0;
+ while (totalTimeout < timeout*1000)
+ {
+ socket.setSoTimeout(iterationTimeout);
+ try
+ {
+ socket.receive(packet);
+ break;
+ }
+ catch (SocketTimeoutException e)
+ {
+ totalTimeout += iterationTimeout;
+ iterationTimeout *= 2;
+ }
+ }
+ sbyte[] rcvdSbytes = packet.getData();
+ char[] rcvdChars = new char[rcvdSbytes.Length];
+ for(int i=0; i < rcvdSbytes.Length; i++)
+ {
+ rcvdChars[i] = (char)rcvdSbytes[i];
+ }
+ String received = new String(rcvdChars);
+
+ java.util.StringTokenizer st = new java.util.StringTokenizer(received, ";");
+ String prev = "";
+ bool instanceReached = false;
+ while (st.hasMoreTokens())
+ {
+ if (!instanceReached)
+ {
+ if (prev.Trim().Equals("InstanceName"))
+ {
+ if (String.Compare(instanceName,st.nextToken().Trim(),true) == 0)
+ {
+ instanceReached = true;
+ }
+ }
+ }
+ else
+ {
+ if (prev.Trim().Equals("tcp"))
+ {
+ port = java.lang.Integer.parseInt(st.nextToken().Trim());
+ break;
+ }
+ }
+ prev = st.nextToken();
+ }
+ socket.close();
+ return port;
+
+ }
+ catch (java.lang.Exception e)
+ {
+ return port;
+ }
+ }
+
+ }
+}
diff --git a/mcs/class/System.Data/System.Data.Common/DbStringManager.cs b/mcs/class/System.Data/System.Data.Common/DbStringManager.cs
new file mode 100644
index 00000000000..efc2cceaab7
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/DbStringManager.cs
@@ -0,0 +1,56 @@
+using java.util;
+
+namespace System.Data.Common
+{
+ public class DbStringManager
+ {
+ public DbStringManager(string bundleName)
+ {
+ _bundleName = bundleName;
+ _resourceBundle = ResourceBundle.getBundle(_bundleName);
+ }
+
+ private readonly string _bundleName;
+
+ private readonly ResourceBundle _resourceBundle;
+
+ public string GetString(string key)
+ {
+ try {
+ return _resourceBundle.getString(key);
+ }
+ catch (MissingResourceException) {
+ return null;
+ }
+ }
+
+ public string GetString(string key, string defaultValue)
+ {
+ try {
+ return _resourceBundle.getString(key);
+ }
+ catch (MissingResourceException) {
+ return defaultValue;
+ }
+ }
+
+
+ public string[] GetStringArray(String key)
+ {
+ try {
+ string tmp = _resourceBundle.getString(key);
+ java.util.StringTokenizer st = new java.util.StringTokenizer(tmp, ",");
+
+ String[] strArr = new String[st.countTokens()];
+
+ for (int i = 0; i < strArr.Length; i++) {
+ strArr[i] = st.nextToken();
+ }
+ return strArr;
+ }
+ catch (MissingResourceException) {
+ return null;
+ }
+ }
+ }
+}
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
index 00000000000..0383b003be9
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/DbTypes.cs
@@ -0,0 +1,74 @@
+using System;
+
+namespace System.Data.Common
+{
+ public class DbTypes
+ {
+ #region java.sql.Types constants
+
+ internal enum JavaSqlTypes {
+ ARRAY = 2003 ,
+ BIGINT = -5,
+ BINARY = -2 ,
+ BIT = -7 ,
+ BLOB = 2004,
+ BOOLEAN = 16,
+ CHAR = 1,
+ CLOB = 2005,
+ DATALINK = 70,
+ DATE = 91,
+ DECIMAL = 3,
+ DISTINCT = 2001,
+ DOUBLE = 8,
+ FLOAT = 6,
+ INTEGER = 4,
+ JAVA_OBJECT = 2000,
+ LONGVARBINARY = -4,
+ LONGVARCHAR = -1,
+ NULL = 0,
+ NUMERIC = 2 ,
+ OTHER = 1111 ,
+ REAL = 7 ,
+ REF = 2006 ,
+ SMALLINT = 5,
+ STRUCT = 2002,
+ TIME = 92,
+ TIMESTAMP = 93,
+ TINYINT = -6,
+ VARBINARY = -3,
+ VARCHAR = 12,
+// NOTSET = int.MinValue
+ }
+
+
+ #endregion // java.sql.Types constants
+
+ #region .Net types constants
+
+ internal static readonly Type TypeOfBoolean = typeof(Boolean);
+ internal static readonly Type TypeOfSByte = typeof(SByte);
+ internal static readonly Type TypeOfChar = typeof(Char);
+ internal static readonly Type TypeOfInt16 = typeof(Int16);
+ internal static readonly Type TypeOfInt32 = typeof(Int32);
+ internal static readonly Type TypeOfInt64 = typeof(Int64);
+ internal static readonly Type TypeOfByte = typeof(Byte);
+ internal static readonly Type TypeOfUInt16 = typeof(UInt16);
+ internal static readonly Type TypeOfUInt32 = typeof(UInt32);
+ internal static readonly Type TypeOfUInt64 = typeof(UInt64);
+ internal static readonly Type TypeOfDouble = typeof(Double);
+ internal static readonly Type TypeOfSingle = typeof(Single);
+ internal static readonly Type TypeOfDecimal = typeof(Decimal);
+ internal static readonly Type TypeOfString = typeof(String);
+ internal static readonly Type TypeOfDateTime = typeof(DateTime);
+ internal static readonly Type TypeOfObject = typeof(object);
+ internal static readonly Type TypeOfGuid = typeof(Guid);
+ internal static readonly Type TypeOfType = typeof(Type);
+
+ // additional types
+ internal static readonly Type TypeOfByteArray = typeof(Byte[]);
+ internal static readonly Type TypeOfFloat = typeof (float);
+ internal static readonly Type TypeOfTimespan = typeof (TimeSpan);
+
+ #endregion // .Net types constants
+ }
+}
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
index 00000000000..0eb66ea27cd
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/ExceptionHelper.cs
@@ -0,0 +1,224 @@
+//
+// System.Data.Common.ExceptionHelper
+//
+// Author:
+// Boris Kirzner (borisk@mainsoft.com)
+//
+
+using System;
+
+using java.util;
+
+namespace System.Data.Common
+{
+ internal sealed class ExceptionHelper
+ {
+ sealed class ResourceManager
+ {
+ private static readonly ResourceBundle _resourceBundle = ResourceBundle.getBundle("SystemData");
+
+ internal ResourceManager()
+ {
+ }
+
+ internal string GetString(string key)
+ {
+ return _resourceBundle.getString(key);
+ }
+ }
+
+ static ResourceManager _resourceManager = new ResourceManager();
+
+ internal static ArgumentException InvalidSizeValue(int value)
+ {
+ string[] args = new string[] {value.ToString()};
+ return new ArgumentException(GetExceptionMessage("ADP_InvalidSizeValue",args));
+ }
+
+ internal static ArgumentOutOfRangeException InvalidDataRowVersion(DataRowVersion value)
+ {
+ return InvalidEnumerationValue(typeof(DataRowVersion), (int) value);
+ }
+
+ internal static ArgumentOutOfRangeException InvalidEnumerationValue(Type type, int value)
+ {
+ object[] args = new object[] { type.Name, value.ToString() } ;
+ return new ArgumentOutOfRangeException(GetExceptionMessage("ADP_InvalidEnumerationValue",args));
+ }
+
+ internal static ArgumentException InvalidOffsetValue(int value)
+ {
+ string[] args = new string[] {value.ToString()};
+ return new ArgumentException(GetExceptionMessage("ADP_InvalidOffsetValue",args));
+ }
+
+ internal static ArgumentOutOfRangeException InvalidParameterDirection(ParameterDirection value)
+ {
+ return InvalidEnumerationValue(typeof(ParameterDirection), (int) value);
+ }
+
+ internal static InvalidOperationException NoStoredProcedureExists(string procedureName) {
+ object[] args = new object[1] { procedureName } ;
+ return new InvalidOperationException(GetExceptionMessage("ADP_NoStoredProcedureExists", args));
+ }
+
+ internal static ArgumentNullException ArgumentNull(string parameter)
+ {
+ return new ArgumentNullException(parameter);
+ }
+
+ internal static InvalidOperationException TransactionRequired()
+ {
+ return new InvalidOperationException(GetExceptionMessage("ADP_TransactionRequired_Execute"));
+ }
+
+ internal static ArgumentOutOfRangeException InvalidOleDbType(int value)
+ {
+ string[] args = new string[] {value.ToString()};
+ return new ArgumentOutOfRangeException(GetExceptionMessage("OleDb_InvalidOleDbType",args));
+ }
+
+ internal static ArgumentException InvalidDbType(int value)
+ {
+ string[] args = new string[] {value.ToString()};
+ return new ArgumentException(GetExceptionMessage("ADP_UnknownDataType",args));
+ }
+
+ internal static InvalidOperationException DeriveParametersNotSupported(Type type,CommandType commandType)
+ {
+ string[] args = new string[] {type.ToString(),commandType.ToString()};
+ return new InvalidOperationException(GetExceptionMessage("ADP_DeriveParametersNotSupported",args));
+ }
+
+ internal static InvalidOperationException ReaderClosed(string mehodName)
+ {
+ string[] args = new string[] {mehodName};
+ return new InvalidOperationException(GetExceptionMessage("ADP_DataReaderClosed",args));
+ }
+
+ internal static ArgumentOutOfRangeException InvalidSqlDbType(int value)
+ {
+ string[] args = new string[] {value.ToString()};
+ return new ArgumentOutOfRangeException(GetExceptionMessage("SQL_InvalidSqlDbType",args));
+ }
+
+ internal static ArgumentException UnknownDataType(string type1, string type2)
+ {
+ string[] args = new string[] {type1, type2};
+ return new ArgumentException(GetExceptionMessage("ADP_UnknownDataType",args));
+ }
+
+ internal static InvalidOperationException TransactionNotInitialized()
+ {
+ return new InvalidOperationException(GetExceptionMessage("ADP_TransactionRequired_Execute"));
+ }
+
+ internal static InvalidOperationException ParametersNotInitialized(int parameterPosition,string parameterName,string parameterType)
+ {
+ object[] args = new object[] {parameterPosition,parameterName,parameterType};
+ return new InvalidOperationException(GetExceptionMessage("OleDb_UninitializedParameters",args));
+ }
+
+ internal static InvalidOperationException WrongParameterSize(string provider)
+ {
+ string[] args = new string[] {provider};
+ return new InvalidOperationException(GetExceptionMessage("ADP_PrepareParameterSize",args));
+ }
+
+ internal static InvalidOperationException ConnectionNotOpened(string operationName, string connectionState)
+ {
+ object[] args = new object[] {operationName,connectionState};
+ return new InvalidOperationException(GetExceptionMessage("ADP_OpenConnectionRequired_PropertySet",args));
+ }
+
+ internal static InvalidOperationException ConnectionNotInitialized(string methodName)
+ {
+ object[] args = new object[] {methodName};
+ return new InvalidOperationException(GetExceptionMessage("ADP_ConnectionRequired_ExecuteReader",args));
+ }
+
+ internal static InvalidOperationException OpenConnectionRequired(string methodName, object connectionState)
+ {
+ object[] args = new object[] {methodName, connectionState};
+ return new InvalidOperationException(GetExceptionMessage("ADP_OpenConnectionRequired_Fill",args));
+ }
+
+ internal static InvalidOperationException OpenedReaderExists()
+ {
+ return new InvalidOperationException(GetExceptionMessage("ADP_OpenReaderExists"));
+ }
+
+ internal static InvalidOperationException ConnectionAlreadyOpen(object connectionState)
+ {
+ object[] args = new object[] {connectionState};
+ return new InvalidOperationException(GetExceptionMessage("ADP_ConnectionAlreadyOpen",args));
+ }
+
+ internal static InvalidOperationException ConnectionStringNotInitialized()
+ {
+ return new InvalidOperationException(GetExceptionMessage("ADP_NoConnectionString"));
+ }
+
+ internal static InvalidOperationException ConnectionIsBusy(object commandType,object connectionState)
+ {
+ object[] args = new object[] {commandType.ToString(), connectionState.ToString()};
+ return new InvalidOperationException(GetExceptionMessage("ADP_CommandIsActive",args));
+ }
+
+ internal static InvalidOperationException NotAllowedWhileConnectionOpen(string propertyName, object connectionState)
+ {
+ object[] args = new object[] {propertyName,connectionState};
+ return new InvalidOperationException(GetExceptionMessage("ADP_OpenConnectionPropertySet",args));
+ }
+
+ internal static ArgumentException OleDbNoProviderSpecified()
+ {
+ return new ArgumentException(GetExceptionMessage("OleDb_NoProviderSpecified"));
+ }
+
+ internal static ArgumentException InvalidValueForKey(string key)
+ {
+ string[] args = new string[] { key };
+ return new ArgumentException(String.Format("Invalid value for key {0}",args));
+ }
+
+ internal static InvalidOperationException ParameterSizeNotInitialized(int parameterIndex, string parameterName,string parameterType,int parameterSize)
+ {
+ object[] args = new object[] { parameterIndex.ToString(),parameterName,parameterType,parameterSize.ToString()};
+ return new InvalidOperationException(GetExceptionMessage("ADP_UninitializedParameterSize",args));
+ }
+
+ internal static ArgumentException InvalidUpdateStatus(UpdateStatus status)
+ {
+ object[] args = new object[] { status };
+ return new ArgumentException(GetExceptionMessage("ADP_InvalidUpdateStatus",args));
+ }
+
+ internal static InvalidOperationException UpdateRequiresCommand(string command)
+ {
+ return new InvalidOperationException(GetExceptionMessage("ADP_UpdateRequiresCommand" + command));
+ }
+
+ internal static DataException RowUpdatedError()
+ {
+ return new DataException(GetExceptionMessage("ADP_RowUpdatedErrors"));
+ }
+
+ internal static string GetExceptionMessage(string key,object[] args)
+ {
+ string exceptionMessage = _resourceManager.GetString(key);
+
+ if ((args == null) || (args.Length == 0)) {
+ return exceptionMessage;
+ }
+ else {
+ return String.Format(exceptionMessage,args);
+ }
+ }
+
+ internal static string GetExceptionMessage(string key)
+ {
+ return GetExceptionMessage(key,null);
+ }
+ }
+}
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
index 00000000000..048f890acd7
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/Index.cs
@@ -0,0 +1,653 @@
+//
+// System.Data.Common.Key.cs
+//
+// Author:
+// Boris Kirzner <borisk@mainsoft.com>
+// Konstantin Triger (kostat@mainsoft.com)
+//
+
+/*
+ * Copyright (c) 2002-2004 Mainsoft Corporation.
+ *
+ * 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.Text;
+
+namespace System.Data.Common
+{
+ enum IndexDuplicatesState { Unknown, True, False };
+ /// <summary>
+ /// Summary description for Index.
+ /// </summary>
+ internal class Index
+ {
+ #region Fields
+
+ int[] _array;
+ int _size;
+ Key _key;
+ int _refCount = 0;
+ IndexDuplicatesState _hasDuplicates;
+
+ #endregion // Fields
+
+ #region Constructors
+
+ internal Index(Key key)
+ {
+ _key = key;
+ Reset();
+ }
+
+ #endregion // Constructors
+
+ #region Properties
+
+ internal Key Key
+ {
+ get {
+ return _key;
+ }
+ }
+
+ internal int Size
+ {
+ get {
+ EnsureArray();
+ return _size;
+ }
+ }
+
+ internal int RefCount
+ {
+ get {
+ return _refCount;
+ }
+ }
+
+ internal int IndexToRecord(int index){
+ return index < 0 ? index : Array[index];
+ }
+
+ private int[] Array
+ {
+ get {
+ EnsureArray();
+ return _array;
+ }
+ }
+
+ internal bool HasDuplicates
+ {
+ get {
+ if (_array == null || _hasDuplicates == IndexDuplicatesState.Unknown) {
+ EnsureArray();
+ if (_hasDuplicates == IndexDuplicatesState.Unknown) {
+ // check for duplicates
+ _hasDuplicates = IndexDuplicatesState.False;
+ for(int i = 0; i < Size - 1; i++) {
+ if (Key.CompareRecords(Array[i],Array[i+1]) == 0) {
+ _hasDuplicates = IndexDuplicatesState.True;
+ break;
+ }
+ }
+ }
+ }
+ return (_hasDuplicates == IndexDuplicatesState.True);
+ }
+ }
+
+ #endregion // Properties
+
+ #region Methods
+
+ internal int[] Duplicates {
+ get {
+ if (!HasDuplicates)
+ return null;
+
+ ArrayList dups = new ArrayList();
+
+ bool inRange = false;
+ for(int i = 0; i < Size - 1; i++) {
+ if (Key.CompareRecords(Array[i],Array[i+1]) == 0){
+ if (!inRange) {
+ dups.Add(Array[i]);
+ inRange = true;
+ }
+
+ dups.Add(Array[i+1]);
+ }
+ else
+ inRange = false;
+ }
+
+ return (int[])dups.ToArray(typeof(int));
+ }
+ }
+
+ private void EnsureArray()
+ {
+ if (_array == null) {
+ RebuildIndex();
+ }
+ }
+
+ internal int[] GetAll()
+ {
+ return Array;
+ }
+
+ internal void Reset()
+ {
+ _array = null;
+ }
+
+ private void RebuildIndex()
+ {
+ // consider better capacity approximation
+ _array = new int[Key.Table.RecordCache.CurrentCapacity];
+ _size = 0;
+ foreach(DataRow row in Key.Table.Rows) {
+ int record = Key.GetRecord(row);
+ if (record != -1) {
+ _array[_size++] = record;
+ }
+ }
+ _hasDuplicates = IndexDuplicatesState.False;
+ // Note : MergeSort may update hasDuplicates to True
+ Sort();
+ }
+
+ private void Sort()
+ {
+ //QuickSort(Array,0,Size-1);
+ MergeSort(Array,Size);
+ }
+
+ /*
+ * Returns record number of the record equal to the key values supplied
+ * in the meaning of index key, or -1 if no equal record found.
+ */
+ internal int Find(object[] keys)
+ {
+ int index = FindIndex(keys);
+ return IndexToRecord(index);
+ }
+
+ /*
+ * Returns record index (location) of the record equal to the key values supplied
+ * in the meaning of index key, or -1 if no equal record found.
+ */
+ internal int FindIndex(object[] keys)
+ {
+ if (keys == null || keys.Length != Key.Columns.Length) {
+ throw new ArgumentException("Expecting " + Key.Columns.Length + " value(s) for the key being indexed, " +
+ "but received " + ((keys == null) ? 0 : keys.Length) + " value(s).");
+ }
+
+ int tmp = Key.Table.RecordCache.NewRecord();
+ try {
+ // init key values for temporal record
+ for(int i = 0; i < Key.Columns.Length; i++) {
+ Key.Columns[i].DataContainer[tmp] = keys[i];
+ }
+ return FindIndex(tmp);
+ }
+// catch(FormatException) {
+// return -1;
+// }
+// catch(InvalidCastException) {
+// return -1;
+// }
+ finally {
+ Key.Table.RecordCache.DisposeRecord(tmp);
+ }
+ }
+
+ /*
+ * Returns record number of the record equal to the record supplied
+ * in the meaning of index key, or -1 if no equal record found.
+ */
+ internal int Find(int record)
+ {
+ int index = FindIndex(record);
+ return IndexToRecord(index);
+ }
+
+ /*
+ * Returns array of record numbers of the records equal equal to the key values supplied
+ * in the meaning of index key, or -1 if no equal record found.
+ */
+ internal int[] FindAll(object[] keys)
+ {
+ int[] indexes = FindAllIndexes(keys);
+ IndexesToRecords(indexes);
+ return indexes;
+ }
+
+ /*
+ * Returns array of indexes of the records inside the index equal equal to the key values supplied
+ * in the meaning of index key, or -1 if no equal record found.
+ */
+ internal int[] FindAllIndexes(object[] keys)
+ {
+ if (keys == null || keys.Length != Key.Columns.Length) {
+ throw new ArgumentException("Expecting " + Key.Columns.Length + " value(s) for the key being indexed," +
+ "but received " + ((keys == null) ? 0 : keys.Length) + " value(s).");
+ }
+
+ int tmp = Key.Table.RecordCache.NewRecord();
+ try {
+ // init key values for temporal record
+ for(int i = 0; i < Key.Columns.Length; i++) {
+ Key.Columns[i].DataContainer[tmp] = keys[i];
+ }
+ return FindAllIndexes(tmp);
+ }
+ catch(FormatException) {
+ return new int[0];
+ }
+ catch(InvalidCastException) {
+ return new int[0];
+ }
+ finally {
+ Key.Table.RecordCache.DisposeRecord(tmp);
+ }
+ }
+
+ /*
+ * Returns array of record numbers of the records equal to the record supplied
+ * in the meaning of index key, or empty list if no equal records found.
+ */
+ internal int[] FindAll(int record)
+ {
+ int[] indexes = FindAllIndexes(record);
+ IndexesToRecords(indexes);
+ return indexes;
+ }
+
+ /*
+ * Returns array of indexes of the records inside the index that equal to the record supplied
+ * in the meaning of index key, or empty list if no equal records found.
+ */
+ internal int[] FindAllIndexes(int record)
+ {
+ int index = FindIndex(record);
+
+ if (index == -1) {
+ return new int[0];
+ }
+
+ int startIndex = index++;
+ int endIndex = index;
+
+ for(;startIndex >= 0 && Key.CompareRecords(Array[startIndex],record) == 0;startIndex--);
+ for(;endIndex < Size && Key.CompareRecords(Array[endIndex],record) == 0;endIndex++);
+
+ int length = endIndex - startIndex - 1;
+ int[] indexes = new int[length];
+
+ for(int i = 0; i < length; i++) {
+ indexes[i] = ++startIndex;
+ }
+
+ return indexes;
+ }
+
+ /*
+ * Returns index inside the array where record number of the record equal to the record supplied
+ * in the meaning of index key is sored, or -1 if no equal record found.
+ */
+ private int FindIndex(int record)
+ {
+ if (Size == 0) {
+ return -1;
+ }
+ return BinarySearch(Array,0,Size - 1,record);
+ }
+
+ /*
+ * Finds exact location of the record specified
+ */
+ private int FindIndexExact(int record)
+ {
+ int index = System.Array.BinarySearch(Array,record);
+ return (index > 0) ? index : -1;
+ }
+
+ /*
+ * Returns array of records from the indexes (locations) inside the index
+ */
+ private void IndexesToRecords(int[] indexes)
+ {
+ for(int i = 0; i < indexes.Length; i++) {
+ indexes[i] = Array[indexes[i]];
+ }
+ }
+
+ internal void Delete(DataRow row)
+ {
+ int oldRecord = Key.GetRecord(row);
+
+ Delete(oldRecord);
+ }
+
+ internal void Delete(int oldRecord)
+ {
+ int index = FindIndex(oldRecord);
+ if (index != -1) {
+ if ((_hasDuplicates == IndexDuplicatesState.True)) {
+ int c1 = 1;
+ int c2 = 1;
+
+ if (index > 0) {
+ c1 = Key.CompareRecords(Array[index - 1],oldRecord);
+ }
+ if (index < Size - 1) {
+ c2 = Key.CompareRecords(Array[index + 1],oldRecord);
+ }
+
+ if (c1 == 0 ^ c2 == 0) {
+ _hasDuplicates = IndexDuplicatesState.Unknown;
+ }
+ }
+ Remove(index);
+ }
+ }
+
+ private void Remove(int index)
+ {
+ if (Size > 1) {
+ System.Array.Copy(Array,index+1,Array,index,Size - index);
+ }
+ _size--;
+ }
+
+ internal void Update(DataRow row,int newRecord)
+ {
+ int oldRecord = Key.GetRecord(row);
+
+ if (oldRecord == -1 || Size == 0) {
+ Add(row,newRecord);
+ return;
+ }
+
+ int oldIdx = FindIndex(oldRecord);
+
+ if( oldIdx == -1) {
+ Add(row,newRecord);
+ return;
+ }
+
+ int newIdx = -1;
+ int compare = Key.CompareRecords(Array[oldIdx],newRecord);
+ int start,end;
+
+ int c1 = 1;
+ int c2 = 1;
+
+ if (compare == 0) {
+ if (Array[oldIdx] == newRecord) {
+ // we deal with the same record that didn't change
+ // in the context of current index.
+ // so , do nothing.
+ return;
+ }
+ }
+ else {
+ if ((_hasDuplicates == IndexDuplicatesState.True)) {
+ if (oldIdx > 0) {
+ c1 = Key.CompareRecords(Array[oldIdx - 1],newRecord);
+ }
+ if (oldIdx < Size - 1) {
+ c2 = Key.CompareRecords(Array[oldIdx + 1],newRecord);
+ }
+
+ if ((c1 == 0 ^ c2 == 0) && compare != 0) {
+ _hasDuplicates = IndexDuplicatesState.Unknown;
+ }
+ }
+ }
+
+ if ((oldIdx == 0 && compare > 0) || (oldIdx == (Size - 1) && compare < 0) || (compare == 0)) {
+ // no need to switch cells
+ newIdx = oldIdx;
+ }
+ else {
+ if (compare < 0) {
+ // search after the old place
+ start = oldIdx + 1;
+ end = Size - 1;
+ }
+ else {
+ // search before the old palce
+ start = 0;
+ end = oldIdx - 1;
+ }
+
+ newIdx = LazyBinarySearch(Array,start,end,newRecord);
+
+ if (oldIdx < newIdx) {
+ System.Array.Copy(Array,oldIdx + 1,Array,oldIdx,newIdx - oldIdx);
+ }
+ else if (oldIdx > newIdx){
+ System.Array.Copy(Array,newIdx,Array,newIdx + 1,oldIdx - newIdx);
+ }
+ }
+ Array[newIdx] = newRecord;
+
+ if (compare != 0) {
+ if (!(_hasDuplicates == IndexDuplicatesState.True)) {
+ if (newIdx > 0) {
+ c1 = Key.CompareRecords(Array[newIdx - 1],newRecord);
+ }
+ if (newIdx < Size - 1) {
+ c2 = Key.CompareRecords(Array[newIdx + 1],newRecord);
+ }
+
+ if (c1 == 0 || c2 == 0) {
+ _hasDuplicates = IndexDuplicatesState.True;
+ }
+ }
+ }
+ }
+
+ private void Add(DataRow row,int newRecord)
+ {
+ int newIdx;
+ if (Size == 0) {
+ newIdx = 0;
+ }
+ else {
+ newIdx = LazyBinarySearch(Array,0,Size - 1,newRecord);
+ // if newl value is greater - insert afer old value
+ // else - insert before old value
+ if (Key.CompareRecords(Array[newIdx],newRecord) < 0) {
+ newIdx++;
+ }
+ }
+
+ Insert(newIdx,newRecord);
+
+ int c1 = 1;
+ int c2 = 1;
+ if (!(_hasDuplicates == IndexDuplicatesState.True)) {
+ if (newIdx > 0) {
+ c1 = Key.CompareRecords(Array[newIdx - 1],newRecord);
+ }
+ if (newIdx < Size - 1) {
+ c2 = Key.CompareRecords(Array[newIdx + 1],newRecord);
+ }
+
+ if (c1 == 0 || c2 == 0) {
+ _hasDuplicates = IndexDuplicatesState.True;
+ }
+ }
+ }
+
+ private void Insert(int index,int r)
+ {
+ if (Array.Length == Size) {
+ int[] tmp = (Size == 0) ? new int[16] : new int[Size << 1];
+ System.Array.Copy(Array,0,tmp,0,index);
+ tmp[index] = r;
+ System.Array.Copy(Array,index,tmp,index + 1,Size - index);
+ _array = tmp;
+ }
+ else {
+ System.Array.Copy(Array,index,Array,index + 1,Size - index);
+ Array[index] = r;
+ }
+ _size++;
+ }
+
+ private void MergeSort(int[] to, int length)
+ {
+ int[] from = new int[length];
+ System.Array.Copy(to, 0, from, 0, from.Length);
+
+ MergeSort(from, to, 0, from.Length);
+ }
+
+ private void MergeSort(int[] from, int[] to,int p, int r)
+ {
+ int q = (p + r) >> 1;
+ if (q == p) {
+ return;
+ }
+
+ MergeSort(to, from, p, q);
+ MergeSort(to, from, q, r);
+
+ // merge
+ for (int middle = q, current = p;;) {
+ int res = Key.CompareRecords(from[p],from[q]);
+ if (res > 0) {
+ to[current++] = from[q++];
+
+ if (q == r) {
+ while( p < middle) {
+ to[current++] = from[p++];
+ }
+ break;
+ }
+ }
+ else {
+
+ if (res == 0) {
+ _hasDuplicates = IndexDuplicatesState.True;
+ }
+
+ to[current++] = from[p++];
+
+ if (p == middle) {
+ while( q < r) {
+ to[current++] = from[q++];
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void QuickSort(int[] a,int p,int r)
+ {
+ if (p < r) {
+ int q = Partition(a,p,r);
+ QuickSort(a,p,q);
+ QuickSort(a,q+1,r);
+ }
+ }
+
+ private int Partition(int[] a,int p,int r)
+ {
+ int x = a[p];
+ int i = p - 1;
+ int j = r + 1;
+
+ while(true) {
+ // decrement upper limit while values are greater then border value
+ do {
+ j--;
+ }
+ while(Key.CompareRecords(a[j],x) > 0); //while(a[j] > x);
+
+ do {
+ i++;
+ }
+ while(Key.CompareRecords(a[i],x) < 0); //while(a[i] < x);
+
+ if (i<j) {
+ int tmp = a[j];
+ a[j] = a[i];
+ a[i] = tmp;
+ }
+ else {
+ return j;
+ }
+ }
+ }
+
+ private int BinarySearch(int[] a, int p, int r,int b)
+ {
+ int i = LazyBinarySearch(a,p,r,b);
+
+ return (Key.CompareRecords(a[i],b) == 0) ? i : -1;
+ }
+
+ // Lazy binary search only returns the cell number the search finished in,
+ // but does not checks that the correct value was actually found
+ private int LazyBinarySearch(int[] a, int p, int r,int b)
+ {
+ if ( p == r ) {
+ return p;
+ }
+
+ int q = (p+r) >> 1;
+
+ int compare = Key.CompareRecords(a[q],b);
+ if (compare < 0) { // if (a[q] < b) {
+ return LazyBinarySearch(a,q+1,r,b);
+ }
+ else if (compare > 0) { // a[q] > b
+ return LazyBinarySearch(a,p,q,b);
+ }
+ else { // a[q] == b
+ return q;
+ }
+ }
+
+ internal void AddRef()
+ {
+ _refCount++;
+ }
+
+ internal void RemoveRef()
+ {
+ _refCount--;
+ }
+
+ #endregion // Methods
+ }
+}
diff --git a/mcs/class/System.Data/System.Data.Common/JDCConnection.cs b/mcs/class/System.Data/System.Data.Common/JDCConnection.cs
new file mode 100644
index 00000000000..414c1fd414f
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/JDCConnection.cs
@@ -0,0 +1,271 @@
+namespace System.Data.Common
+{
+
+ using java.sql;
+ using java.util;
+
+ using System;
+
+ public class JDCConnection : Connection
+ {
+
+ private JDCConnectionPool pool;
+ private Connection conn;
+ private bool inuse;
+ private long timestamp;
+
+
+ public JDCConnection(Connection conn, JDCConnectionPool pool)
+ {
+ this.conn=conn;
+ this.pool=pool;
+ this.inuse=false;
+ this.timestamp=0;
+ }
+
+ public bool lease()
+
+ {
+ lock(this)
+ {
+ if(inuse)
+ {
+ return false;
+ }
+ else
+ {
+ inuse=true;
+ timestamp = java.lang.System.currentTimeMillis();
+ return true;
+ }
+ }
+ }
+ public bool validate()
+ {
+ try
+ {
+ conn.getMetaData();
+ }
+ catch (Exception)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ public bool inUse()
+ {
+ return inuse;
+ }
+
+ public long getLastUse()
+ {
+ return timestamp;
+ }
+
+ public void close() //throws SQLException
+ {
+ pool.returnConnection(this);
+ }
+
+ public void expireLease()
+ {
+ inuse=false;
+ }
+
+ protected Connection getConnection()
+ {
+ return conn;
+ }
+
+ public void setTypeMap(Map map) //throws SQLException
+ {
+ conn.setTypeMap(map);
+ }
+
+
+ public Map getTypeMap() //throws SQLException
+ {
+ return conn.getTypeMap();
+ }
+
+ public PreparedStatement prepareStatement(String sql) //throws SQLException
+ {
+ return conn.prepareStatement(sql);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) //throws SQLException
+ {
+ return conn.prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ public CallableStatement prepareCall(String sql) //throws SQLException
+ {
+ return conn.prepareCall(sql);
+ }
+
+
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) //throws SQLException
+ {
+ return conn.prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency) //throws SQLException
+ {
+ return conn.createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ public Statement createStatement() //throws SQLException
+ {
+ return conn.createStatement();
+ }
+
+ public String nativeSQL(String sql) //throws SQLException
+ {
+ return conn.nativeSQL(sql);
+ }
+
+ public void setAutoCommit(bool autoCommit) //throws SQLException
+ {
+ conn.setAutoCommit(autoCommit);
+ }
+
+ public bool getAutoCommit() //throws SQLException
+ {
+ return conn.getAutoCommit();
+ }
+
+ public void commit() //throws SQLException
+ {
+ conn.commit();
+ }
+
+ public void rollback() //throws SQLException
+ {
+ conn.rollback();
+ }
+
+ public bool isClosed() //throws SQLException
+ {
+ if(conn.isClosed())
+ return true;
+
+ return !inUse();
+ }
+
+ public DatabaseMetaData getMetaData() //throws SQLException
+ {
+ return conn.getMetaData();
+ }
+
+ public void setReadOnly(bool readOnly) //throws SQLException
+ {
+ conn.setReadOnly(readOnly);
+ }
+
+ public bool isReadOnly()// throws SQLException
+ {
+ return conn.isReadOnly();
+ }
+
+ public void setCatalog(String catalog) //throws SQLException
+ {
+ conn.setCatalog(catalog);
+ }
+
+ public String getCatalog() //throws SQLException
+ {
+ return conn.getCatalog();
+ }
+
+ public void setTransactionIsolation(int level) //throws SQLException
+ {
+ conn.setTransactionIsolation(level);
+ }
+
+ public int getTransactionIsolation() //throws SQLException
+ {
+ return conn.getTransactionIsolation();
+ }
+
+ public SQLWarning getWarnings() //throws SQLException
+ {
+ return conn.getWarnings();
+ }
+
+ public void clearWarnings() //throws SQLException
+ {
+ conn.clearWarnings();
+ }
+
+ // --------- JDBC 3.0 -------------
+ /*
+ public void setHoldability(int holdability)
+ {
+ conn.setHoldability(holdability);
+ }
+
+ public int getHoldability()
+ {
+ return conn.getHoldability();
+ }
+
+ public Savepoint setSavepoint()
+ {
+ return conn.setSavepoint();
+ }
+
+ public Savepoint setSavepoint(string name)
+ {
+ return conn.setSavepoint(name);
+ }
+
+ public void rollback(Savepoint savepoint)
+ {
+ conn.rollback(savepoint);
+ }
+
+ public void releaseSavepoint(Savepoint savepoint)
+ {
+ conn.releaseSavepoint(savepoint);
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability)
+ {
+ return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ {
+ throw new NotImplementedException();
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability)
+ {
+ return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ {
+ return conn.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ {
+ return conn.prepareStatement(sql, columnIndexes);
+ }
+
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ {
+ return conn.prepareStatement(sql, columnNames);
+ }
+
+ */
+ }
+} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/JDCConnectionDriver.cs b/mcs/class/System.Data/System.Data.Common/JDCConnectionDriver.cs
new file mode 100644
index 00000000000..1ec4d983285
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/JDCConnectionDriver.cs
@@ -0,0 +1,63 @@
+namespace System.Data.Common
+{
+
+using java.sql;
+using java.util;
+
+
+class JDCConnectionDriver : Driver
+{
+
+ public static readonly String URL_PREFIX = "jdbc:jdc:";
+ private static readonly int MAJOR_VERSION = 1;
+ private static readonly int MINOR_VERSION = 0;
+ private JDCConnectionPool pool;
+
+ public JDCConnectionDriver(String driver, String url,
+ String user, String password)
+ //throws ClassNotFoundException,
+ // InstantiationException, IllegalAccessException,
+ //SQLException
+ {
+ DriverManager.registerDriver(this);
+ java.lang.Class.forName(driver).newInstance();
+ pool = new JDCConnectionPool(url, user, password);
+ }
+
+ public Connection connect(String url, Properties props)
+ // throws SQLException
+ {
+ if(!url.StartsWith(URL_PREFIX))
+ {
+ return null;
+ }
+
+ return pool.getConnection();
+ }
+
+ public bool acceptsURL(String url)
+ {
+ return url.StartsWith(URL_PREFIX);
+ }
+
+ public int getMajorVersion()
+ {
+ return MAJOR_VERSION;
+ }
+
+ public int getMinorVersion()
+ {
+ return MINOR_VERSION;
+ }
+
+ public DriverPropertyInfo[] getPropertyInfo(String str, Properties props)
+ {
+ return new DriverPropertyInfo[0];
+ }
+
+ public bool jdbcCompliant()
+ {
+ return false;
+ }
+}
+} \ No newline at end of file
diff --git a/mcs/class/System.Data/System.Data.Common/JDCConnectionPool.cs b/mcs/class/System.Data/System.Data.Common/JDCConnectionPool.cs
new file mode 100644
index 00000000000..dd4b5f3eae4
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/JDCConnectionPool.cs
@@ -0,0 +1,88 @@
+namespace System.Data.Common
+{
+
+ using java.sql;
+ using java.util;
+
+
+ public class JDCConnectionPool
+ {
+
+ private ArrayList _connections;
+ private String _url, _user, _password;
+ readonly private long timeout = 10000;
+ readonly private int _initPoolsize = 10;
+ private int _maxPoolSize = 100;
+ private static bool _shutdown = false;
+
+ public JDCConnectionPool(String url, String user, String password)
+ {
+ _url = url;
+ _user = user;
+ _password = password;
+ _connections = new ArrayList(_initPoolsize);
+ }
+
+
+ public void closeConnections()
+ {
+ lock(this)
+ {
+ if(_connections.size() > 0)
+ {
+ Iterator connlist = _connections.iterator();
+
+ while (connlist.hasNext())
+ {
+ JDCConnection conn = (JDCConnection) connlist.next();
+ removeConnection(conn);
+ }
+ }
+ }
+ }
+
+ private void removeConnection(JDCConnection conn)
+ {
+ lock(this)
+ {
+ _connections.remove(conn);
+ }
+ }
+
+ public Connection getConnection() //throws SQLException
+ {
+ lock(this)
+ {
+
+ JDCConnection c;
+ for (int i = 0; i < _connections.size(); i++)
+ {
+ c = (JDCConnection) _connections.get(i);
+
+ if (c.lease())
+ return c;
+ }
+
+ if(_connections.size() < _maxPoolSize)
+{
+ Connection conn = DriverManager.getConnection(_url, _user, _password);
+ c = new JDCConnection(conn, this);
+ c.lease();
+ _connections.add(c);
+ return c;
+}
+
+ return null;
+}
+ }
+
+ public void returnConnection(JDCConnection conn)
+ {
+ lock(this)
+ {
+ conn.expireLease();
+ }
+ }
+
+}
+} \ No newline at end of file
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
index 00000000000..8433277bc95
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/Key.cs
@@ -0,0 +1,226 @@
+//
+// System.Data.Common.Key.cs
+//
+// Author:
+// Boris Kirzner <borisk@mainsoft.com>
+// Konstantin Triger (kostat@mainsoft.com)
+//
+
+/*
+ * Copyright (c) 2002-2004 Mainsoft Corporation.
+ *
+ * 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 Mono.Data.SqlExpressions;
+using System.ComponentModel;
+
+namespace System.Data.Common
+{
+ internal class Key
+ {
+ #region Fields
+
+ DataTable _table;
+ DataColumn[] _columns;
+ ListSortDirection[] _sortDirection;
+ DataViewRowState _rowStateFilter;
+ IExpression _filter;
+ //Currently IExpression.Eval does not receive DataRowVersion
+ // and always uses the _current version
+ //so need a temp row for Eval calls
+ DataRow _tmpRow;
+
+ #endregion //Fields
+
+ #region Constructors
+
+ internal Key(DataTable table,DataColumn[] columns,ListSortDirection[] sort, DataViewRowState rowState, IExpression filter)
+ {
+ _table = table;
+ _filter = filter;
+ if (_filter != null)
+ _tmpRow = _table.NewNotInitializedRow();
+ _columns = columns;
+ if (sort != null && sort.Length == columns.Length) {
+ _sortDirection = sort;
+ }
+ else {
+ _sortDirection = new ListSortDirection[columns.Length];
+ for(int i=0; i < _sortDirection.Length; i++) {
+ _sortDirection[i] = ListSortDirection.Ascending;
+ }
+ }
+
+ if (rowState != DataViewRowState.None) {
+ _rowStateFilter = rowState;
+ }
+ else {
+ // FIXME : what is the correct value ?
+ _rowStateFilter = DataViewRowState.CurrentRows;
+ }
+ }
+
+ #endregion // Constructors
+
+ #region Properties
+
+ internal DataColumn[] Columns
+ {
+ get {
+ return _columns;
+ }
+ }
+
+ internal DataTable Table
+ {
+ get {
+ return _table;
+ }
+ }
+
+ ListSortDirection[] Sort
+ {
+ get {
+ return _sortDirection;
+ }
+ }
+
+ internal DataViewRowState RowStateFilter
+ {
+ get {
+ return _rowStateFilter;
+ }
+
+ set {
+ _rowStateFilter = value;
+ }
+ }
+
+ #endregion // Properties
+
+ #region Methods
+
+ internal int CompareRecords(int first, int second)
+ {
+ if (first == second) {
+ return 0;
+ }
+
+ for(int i = 0; i < Columns.Length; i++) {
+
+ int res = Columns[i].CompareValues(first,second);
+
+ if (res == 0) {
+ continue;
+ }
+
+ return (Sort[i] == ListSortDirection.Ascending) ? res : -res;
+ }
+ return 0;
+ }
+
+ internal int GetRecord(DataRow row)
+ {
+ int index = Key.GetRecord(row,_rowStateFilter);
+ if (_filter == null)
+ return index;
+
+ if (index < 0)
+ return index;
+
+ _tmpRow._current = index;
+ return _filter.EvalBoolean(_tmpRow) ? index : -1;
+ }
+
+ internal static int GetRecord(DataRow row, DataViewRowState rowStateFilter)
+ {
+
+ if (row.Original == row.Current) {
+ if ((rowStateFilter & DataViewRowState.Unchanged) != DataViewRowState.None) {
+ return row.Current;
+ }
+ }
+ else if (row.Original == -1) {
+ if ((rowStateFilter & DataViewRowState.Added) != DataViewRowState.None) {
+ return row.Current;
+ }
+ }
+ else if (row.Current == -1) {
+ if ((rowStateFilter & DataViewRowState.Deleted) != DataViewRowState.None) {
+ return row.Original;
+ }
+ }
+ else if ((rowStateFilter & DataViewRowState.ModifiedCurrent) != DataViewRowState.None) {
+ return row.Current;
+ }
+ else if ((rowStateFilter & DataViewRowState.ModifiedOriginal) != DataViewRowState.None) {
+ return row.Original;
+ }
+
+ return -1;
+ }
+
+ /// <summary>
+ /// Checks for key equality to parameters set given
+ /// </summary>
+ /// <param name="columns">Columns the key consits of. If this parameter is null, it does not affects equality check</param>
+ /// <param name="sort">Sort order of columns. If this parameter is null, it does not affects equality check</param>
+ /// <param name="rowState">DataViewRowState to check for.If this parameter is null, it does not affects equality check</param>
+ /// <param name="unique">Indicates whenever the index managed by this key allows non-uniqie keys to appear.</param>
+ /// <param name="strict">Indicates whenever unique parameter should affect the equality check.</param>
+ /// <returns></returns>
+ internal bool Equals(DataColumn[] columns, ListSortDirection[] sort, DataViewRowState rowState, IExpression filter)
+ {
+ if (rowState != DataViewRowState.None && RowStateFilter != rowState) {
+ return false;
+ }
+
+ if (_filter != filter)
+ return false;
+
+ if (Columns.Length != columns.Length) {
+ return false;
+ }
+
+ if (sort != null && Sort.Length != sort.Length) {
+ return false;
+ }
+
+ if (sort != null) {
+ for(int i=0; i < columns.Length; i++) {
+ if (Sort[i] != sort[i] || Columns[i] != columns[i]) {
+ return false;
+ }
+ }
+ }
+ else {
+ for(int i=0; i < columns.Length; i++) {
+ if (Columns[i] != columns[i]) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ #endregion // Methods
+ }
+}
diff --git a/mcs/class/System.Data/System.Data.Common/ParameterMetadataWrapper.cs b/mcs/class/System.Data/System.Data.Common/ParameterMetadataWrapper.cs
new file mode 100644
index 00000000000..3fcbf4cee5b
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/ParameterMetadataWrapper.cs
@@ -0,0 +1,70 @@
+using System;
+
+using java.sql;
+
+namespace System.Data.Common
+{
+ public class ParameterMetadataWrapper : java.sql.ResultSetMetaData
+ {
+ #region Fields
+
+ ParameterMetaData _parameterMetaData;
+
+ #endregion // Fields
+
+ #region Constructors
+
+ public ParameterMetadataWrapper(ParameterMetaData parameterMetaData)
+ {
+ _parameterMetaData = parameterMetaData;
+ }
+
+ #endregion // Constructors
+
+ #region Methods
+
+ public int getColumnCount() { throw new NotImplementedException(); }
+
+ public int getColumnDisplaySize(int i) { throw new NotImplementedException(); }
+
+ public int getColumnType(int i) { throw new NotImplementedException(); }
+
+ public int getPrecision(int i) { throw new NotImplementedException(); }
+
+ public int getScale(int i) { throw new NotImplementedException(); }
+
+ public int isNullable(int i) { throw new NotImplementedException(); }
+
+ public bool isAutoIncrement(int i) { throw new NotImplementedException(); }
+
+ public bool isCaseSensitive(int i) { throw new NotImplementedException(); }
+
+ public bool isCurrency(int i) { throw new NotImplementedException(); }
+
+ public bool isDefinitelyWritable(int i) { throw new NotImplementedException(); }
+
+ public bool isReadOnly(int i) { throw new NotImplementedException(); }
+
+ public bool isSearchable(int i) { throw new NotImplementedException(); }
+
+ public bool isSigned(int i) { throw new NotImplementedException(); }
+
+ public bool isWritable(int i) { throw new NotImplementedException(); }
+
+ public String getCatalogName(int i) { throw new NotImplementedException(); }
+
+ public String getColumnClassName(int i) { throw new NotImplementedException(); }
+
+ public String getColumnLabel(int i) { throw new NotImplementedException(); }
+
+ public String getColumnName(int i) { throw new NotImplementedException(); }
+
+ public String getColumnTypeName(int i) { return _parameterMetaData.getParameterTypeName(i); }
+
+ public String getSchemaName(int i) { throw new NotImplementedException(); }
+
+ public String getTableName(int i) { throw new NotImplementedException(); }
+
+ #endregion // Methods
+ }
+}
diff --git a/mcs/class/System.Data/System.Data.Common/ReaderCache.cs b/mcs/class/System.Data/System.Data.Common/ReaderCache.cs
new file mode 100644
index 00000000000..13a7b96e7cb
--- /dev/null
+++ b/mcs/class/System.Data/System.Data.Common/ReaderCache.cs
@@ -0,0 +1,659 @@
+using System;
+using java.sql;
+
+namespace System.Data.Common
+{
+ public interface IReaderCacheContainer
+ {
+ void Fetch(ResultSet rs, int columnIndex);
+ bool IsNull();
+ object GetValue();
+ }
+
+ internal abstract class ReaderCacheContainerBase : IReaderCacheContainer
+ {
+ #region Fields
+
+ bool _isNull;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected abstract void FetchInternal(ResultSet rs, int columnIndex);
+
+ public abstract object GetValue();
+
+ public void Fetch(ResultSet rs, int columnIndex)
+ {
+ FetchInternal(rs, columnIndex + 1);
+ _isNull = rs.wasNull();
+ }
+
+ public bool IsNull()
+ {
+ return _isNull;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class ArrayReaderCacheContainer : ReaderCacheContainerBase // Types.ARRAY
+ {
+ #region Fields
+
+ java.sql.Array _a;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _a = rs.getArray(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _a;
+ }
+
+ internal java.sql.Array GetArray()
+ {
+ return _a;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class Int64ReaderCacheContainer : ReaderCacheContainerBase // Types.BIGINT
+ {
+ #region Fields
+
+ long _l;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _l = rs.getLong(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _l;
+ }
+
+ internal long GetInt64()
+ {
+ return _l;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal class BytesReaderCacheContainer : ReaderCacheContainerBase // Types.BINARY, Types.VARBINARY, Types.LONGVARBINARY
+ {
+ #region Fields
+
+ protected byte[] _b;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ sbyte[] sbyteArray = rs.getBytes(columnIndex);
+ if (sbyteArray != null) {
+ _b = (byte[])vmw.common.TypeUtils.ToByteArray(sbyteArray);
+ }
+ }
+
+ public override object GetValue()
+ {
+ return _b;
+ }
+
+ internal byte[] GetBytes()
+ {
+ return _b;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class BooleanReaderCacheContainer : ReaderCacheContainerBase // Types.BIT
+ {
+ #region Fields
+
+ bool _b;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _b = rs.getBoolean(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _b;
+ }
+
+ internal bool GetBoolean()
+ {
+ return _b;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class BlobReaderCacheContainer : BytesReaderCacheContainer // Types.BLOB
+ {
+ #region Fields
+
+ static readonly byte[] _emptyByteArr = new byte[0];
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ java.sql.Blob blob = rs.getBlob(columnIndex);
+ if (blob != null) {
+ long length = blob.length();
+ if (length == 0) {
+ _b = _emptyByteArr;
+ }
+ else {
+ java.io.InputStream input = blob.getBinaryStream();
+ byte[] byteValue = new byte[length];
+ sbyte[] sbyteValue = vmw.common.TypeUtils.ToSByteArray(byteValue);
+ input.read(sbyteValue);
+ _b = byteValue;
+ }
+ }
+ }
+
+ public override object GetValue()
+ {
+ return _b;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal abstract class CharsReaderCacheContainer : ReaderCacheContainerBase //
+ {
+ #region Fields
+
+ #endregion // Fields
+
+ #region Methods
+
+ internal abstract char[] GetChars();
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class GuidReaderCacheContainer : ReaderCacheContainerBase // Types.CHAR
+ {
+ #region Fields
+
+ Guid _g;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _g = new Guid(rs.getString(columnIndex));
+ }
+
+ public override object GetValue()
+ {
+ return _g;
+ }
+
+ internal Guid GetGuid()
+ {
+ return _g;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class ClobReaderCacheContainer : StringReaderCacheContainer // Types.CLOB
+ {
+ #region Fields
+
+ char[] _c;
+
+ #endregion // Fields
+
+ #region Methods
+
+ // FIXME : conside adding stream wrapper interface
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ java.sql.Clob clob = rs.getClob(columnIndex);
+ if (clob != null) {
+ long length = clob.length();
+ if (length == 0) {
+ _s = String.Empty;
+ _c = String.Empty.ToCharArray();
+ }
+ else {
+ java.io.Reader reader = clob.getCharacterStream();
+ char[] charValue = new char[length];
+ reader.read(charValue);
+ _c = charValue;
+
+ }
+ }
+ }
+
+ public override object GetValue()
+ {
+ if (_s == null && _c != null) {
+ _s = (_c.Length != 0) ? new String(_c) : String.Empty;
+ }
+ return _s;
+ }
+
+ internal override char[] GetChars()
+ {
+ return _c;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class TimeSpanReaderCacheContainer : ReaderCacheContainerBase // Types.TIME
+ {
+ #region Fields
+
+ TimeSpan _t;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ Time t = rs.getTime(columnIndex);
+ if (t != null) {
+ _t = new TimeSpan(DbConvert.JavaTimeToClrTicks(t));
+ }
+ }
+
+ public override object GetValue()
+ {
+ return _t;
+ }
+
+ internal TimeSpan GetTimeSpan()
+ {
+ return _t;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal class DateTimeReaderCacheContainer : ReaderCacheContainerBase // Types.TIMESTAMP
+ {
+ #region Fields
+
+ protected DateTime _d;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ Date d = rs.getDate(columnIndex);
+ if (d != null) {
+ _d = new DateTime(DbConvert.JavaDateToClrTicks(d));
+ }
+ }
+
+ public override object GetValue()
+ {
+ return _d;
+ }
+
+ internal DateTime GetDateTime()
+ {
+ return _d;
+ }
+
+ #endregion // Methods
+ }
+
+ internal sealed class TimestampReaderCacheContainer : DateTimeReaderCacheContainer // Types.DATE
+ {
+ protected override void FetchInternal(ResultSet rs, int columnIndex) {
+ Timestamp ts = rs.getTimestamp(columnIndex);
+ if (ts != null) {
+ _d = new DateTime(DbConvert.JavaTimestampToClrTicks(ts));
+ }
+ }
+ }
+
+
+ internal sealed class DecimalReaderCacheContainer : ReaderCacheContainerBase // Types.DECIMAL, Types.NUMERIC
+ {
+ #region Fields
+
+ decimal _d;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ java.math.BigDecimal bigDecimal = rs.getBigDecimal(columnIndex);
+ if (bigDecimal != null) {
+ _d = (decimal)vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bigDecimal);
+ }
+ }
+
+ public override object GetValue()
+ {
+ return _d;
+ }
+
+ internal decimal GetDecimal()
+ {
+ return _d;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class DoubleReaderCacheContainer : ReaderCacheContainerBase // Types.DOUBLE, Types.Float, Types.NUMERIC for Oracle with scale = -127
+ {
+ #region Fields
+
+ double _d;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _d = rs.getDouble(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _d;
+ }
+
+ internal double GetDouble()
+ {
+ return _d;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class Int32ReaderCacheContainer : ReaderCacheContainerBase // Types.INTEGER
+ {
+ #region Fields
+
+ int _i;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _i = rs.getInt(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _i;
+ }
+
+ internal int GetInt32()
+ {
+ return _i;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal class StringReaderCacheContainer : CharsReaderCacheContainer // Types.LONGVARCHAR, Types.VARCHAR, Types.CHAR
+ {
+ #region Fields
+
+ protected string _s;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _s = rs.getString(columnIndex);
+ // Oracle Jdbc driver returns extra trailing 0 chars for NCHAR columns
+// if ((_s != null) && (_jdbcType == 1)) {
+// Console.WriteLine(_jdbcType);
+// int zeroIndex = ((string)_s).IndexOf((char)0);
+// if (zeroIndex > 0) {
+// Console.WriteLine("zero-padded");
+// _s = ((string)_s).Substring(0,zeroIndex);
+// }
+// else {
+// // Oracle sometimes pads with blanks (32)
+// int blankIndex = ((string)_s).IndexOf((char)32);
+// if (blankIndex > 0) {
+// Console.WriteLine("blank-padded");
+// _s = ((string)_s).Substring(0,blankIndex);
+// }
+// }
+// }
+ }
+
+ public override object GetValue()
+ {
+ return _s;
+ }
+
+ internal string GetString()
+ {
+ return _s;
+ }
+
+ internal override char[] GetChars()
+ {
+ return _s.ToCharArray();
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class NullReaderCacheContainer : ReaderCacheContainerBase // Types.NULL
+ {
+ #region Fields
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ }
+
+ public override object GetValue()
+ {
+ return DBNull.Value;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class FloatReaderCacheContainer : ReaderCacheContainerBase // Types.REAL
+ {
+ #region Fields
+
+ float _f;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _f = rs.getFloat(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _f;
+ }
+
+ internal float GetFloat()
+ {
+ return _f;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class RefReaderCacheContainer : ReaderCacheContainerBase // Types.REF
+ {
+ #region Fields
+
+ java.sql.Ref _r;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _r = rs.getRef(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _r;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class Int16ReaderCacheContainer : ReaderCacheContainerBase // Types.SMALLINT
+ {
+ #region Fields
+
+ short _s;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _s = rs.getShort(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _s;
+ }
+
+ internal short GetInt16()
+ {
+ return _s;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class ByteReaderCacheContainer : ReaderCacheContainerBase // Types.TINYINT
+ {
+ #region Fields
+
+ byte _b;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ _b = (byte)rs.getByte(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return _b;
+ }
+
+ internal byte GetByte()
+ {
+ return _b;
+ }
+
+ #endregion // Methods
+ }
+
+
+ internal sealed class ObjectReaderCacheContainer : ReaderCacheContainerBase // Types.Distinct, Types.JAVA_OBJECT, Types.OTHER, Types.STRUCT
+ {
+ #region Fields
+
+ object o;
+
+ #endregion // Fields
+
+ #region Methods
+
+ protected override void FetchInternal(ResultSet rs, int columnIndex)
+ {
+ o = rs.getObject(columnIndex);
+ }
+
+ public override object GetValue()
+ {
+ return o;
+ }
+
+ #endregion // Methods
+ }
+
+}