Drop of Mainsoft.System.Data
authorBoris Kirzner <borisk@mono-cvs.ximian.com>
Tue, 26 Apr 2005 17:22:27 +0000 (17:22 -0000)
committerBoris Kirzner <borisk@mono-cvs.ximian.com>
Tue, 26 Apr 2005 17:22:27 +0000 (17:22 -0000)
svn path=/branches/Mainsoft.System.Data/mcs/; revision=43607

19 files changed:
mcs/class/System.Data/System.Data.Common/AbstractDBCommand.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/AbstractDBConnection.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/AbstractDBParameter.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/AbstractDataReader.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/AbstractTransaction.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/CallableStatementWrapper.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbConvert.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbMetaDataCache.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbPortResolver.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbStringManager.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/DbTypes.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/ExceptionHelper.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/Index.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/JDCConnection.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/JDCConnectionDriver.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/JDCConnectionPool.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/Key.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/ParameterMetadataWrapper.cs [new file with mode: 0644]
mcs/class/System.Data/System.Data.Common/ReaderCache.cs [new file with mode: 0644]

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