// // System.Data.Common.DbConvert // // Author: // Boris Kirzner (borisk@mainsoft.com) // using System; using System.Data.Common; using java.io; using java.sql; namespace System.Data.ProviderBase { public abstract class DbConvert { #region Fields const long JAVA_MIN_MILLIS_UTC = -62135769600000L; // java.sql.Timestamp.valueOf("0001-01-01 00:00:00.000000000").getTime() at Greenwich time zone. static readonly long TIMEZONE_RAW_OFFSET; // .NET milliseconds value of DateTime(1582,1,1,0,0,0,0).Ticks/TimeSpan.TicksPerMillisecond const long CLR_MILLIS_1582 = 49891507200000L; const long MILLIS_PER_TWO_DAYS = 2 * TimeSpan.TicksPerDay / TimeSpan.TicksPerMillisecond; // 172800000L; internal static readonly java.util.TimeZone DEFAULT_TIME_ZONE; #endregion // Fields #region java.sql.Types constants internal enum JavaSqlTypes { ARRAY = 2003 , BIGINT = -5, BINARY = -2 , BIT = -7 , BLOB = 2004, BOOLEAN = 16, CHAR = 1, CLOB = 2005, DATALINK = 70, DATE = 91, DECIMAL = 3, DISTINCT = 2001, DOUBLE = 8, FLOAT = 6, INTEGER = 4, JAVA_OBJECT = 2000, LONGVARBINARY = -4, LONGVARCHAR = -1, NULL = 0, NUMERIC = 2 , OTHER = 1111 , REAL = 7 , REF = 2006 , SMALLINT = 5, STRUCT = 2002, TIME = 92, TIMESTAMP = 93, TINYINT = -6, VARBINARY = -3, VARCHAR = 12, // NOTSET = int.MinValue } #endregion // java.sql.Types constants #region Methods static DbConvert() { DEFAULT_TIME_ZONE = java.util.SimpleTimeZone.getDefault(); TIMEZONE_RAW_OFFSET = (long)DEFAULT_TIME_ZONE.getRawOffset(); } // The diff between .Net and Java goes as the following: // * at 1582: java has 10 days less than .net // * below 1500 (exept 1200,800,400) : each 100'th year java adds 1 day over .net. // Current implementation compatible with .net in 1-99 and since 1582. In 100-1582 we're not compatible with .Ner nor with Java internal static long JavaMillisToClrMillis(long javaMillis) { return JavaMillisToClrMillisUTC(javaMillis) + TIMEZONE_RAW_OFFSET; } internal static long JavaMillisToClrMillisUTC(long javaMillis) { long clrMillis = javaMillis - JAVA_MIN_MILLIS_UTC; if (clrMillis > CLR_MILLIS_1582) { clrMillis -= MILLIS_PER_TWO_DAYS; } return clrMillis; } internal static long ClrMillisToJavaMillis(long clrMillis) { return ClrMillisToJavaMillisUTC(clrMillis) - TIMEZONE_RAW_OFFSET; } internal static long ClrMillisToJavaMillisUTC(long clrMillis) { long javaMillis = clrMillis + JAVA_MIN_MILLIS_UTC; if (clrMillis > CLR_MILLIS_1582) { javaMillis += MILLIS_PER_TWO_DAYS; } return javaMillis; } internal static java.sql.Time ClrTicksToJavaTime(long ticks) { return new Time((ticks / TimeSpan.TicksPerMillisecond) - DEFAULT_TIME_ZONE.getRawOffset()); } internal static java.sql.Date ClrTicksToJavaDate(long ticks) { java.sql.Date d = new java.sql.Date(0); ClrTicksToJavaDate(d, ticks); return d; } internal static java.sql.Timestamp ClrTicksToJavaTimestamp(long ticks) { java.sql.Timestamp ts = new java.sql.Timestamp(0); ClrTicksToJavaDate(ts, ticks); // int nanos = (int)(ticks % TimeSpan.TicksPerMillisecond) * 100; // ts.setNanos(javaTimestamp.getNanos() + nanos); return ts; } internal static void ClrTicksToJavaDate(java.util.Date d, long ticks) { long millis = ClrMillisToJavaMillis(ticks / TimeSpan.TicksPerMillisecond); d.setTime(millis); if (DEFAULT_TIME_ZONE.inDaylightTime(d)) { millis -= DEFAULT_TIME_ZONE.getDSTSavings(); d.setTime(millis); } } internal static long JavaTimestampToClrTicks(java.sql.Timestamp ts) { long ticks = JavaDateToClrTicks(ts); // Extra ticks, for dbs that can save them. // We do not use it, since .net does not saves ticks for fractial milliseconds // long ticksLessThanMilliseconds = (ts.getNanos()*100) % TimeSpan.TicksPerMillisecond; // ticks += ticksLessThanMilliseconds; return ticks; } internal static long JavaDateToClrTicks(java.util.Date d) { long millis = JavaMillisToClrMillis(d.getTime()); if (DEFAULT_TIME_ZONE.inDaylightTime(d)) { millis += DEFAULT_TIME_ZONE.getDSTSavings(); } return millis * TimeSpan.TicksPerMillisecond; } internal static long JavaTimeToClrTicks(java.sql.Time t) { return (t.getTime() + DEFAULT_TIME_ZONE.getRawOffset()) * TimeSpan.TicksPerMillisecond; } internal static Type JavaSqlTypeToClrType(int sqlTypeValue) { JavaSqlTypes sqlType = (JavaSqlTypes)sqlTypeValue; switch (sqlType) { case JavaSqlTypes.ARRAY : return typeof (java.sql.Array); case JavaSqlTypes.BIGINT : return DbTypes.TypeOfInt64; case JavaSqlTypes.BINARY : return DbTypes.TypeOfByteArray; case JavaSqlTypes.BIT : return DbTypes.TypeOfBoolean; case JavaSqlTypes.BLOB : return DbTypes.TypeOfByteArray; case JavaSqlTypes.BOOLEAN : return DbTypes.TypeOfBoolean; case JavaSqlTypes.CHAR : return DbTypes.TypeOfString; case JavaSqlTypes.CLOB : return DbTypes.TypeOfString; // case JavaSqlTypes.DATALINK : case JavaSqlTypes.DATE : return DbTypes.TypeOfDateTime; case JavaSqlTypes.DECIMAL : return DbTypes.TypeOfDecimal; // case JavaSqlTypes.DISTINCT : case JavaSqlTypes.DOUBLE : return DbTypes.TypeOfDouble; case JavaSqlTypes.FLOAT : return DbTypes.TypeOfDouble; case JavaSqlTypes.INTEGER : return DbTypes.TypeOfInt32; // case JavaSqlTypes.JAVA_OBJECT : case JavaSqlTypes.LONGVARBINARY : return DbTypes.TypeOfByteArray; case JavaSqlTypes.LONGVARCHAR : return DbTypes.TypeOfString; case JavaSqlTypes.NULL : return null; case JavaSqlTypes.NUMERIC : return DbTypes.TypeOfDecimal; // case JavaSqlTypes.OTHER : case JavaSqlTypes.REAL : return DbTypes.TypeOfSingle; case JavaSqlTypes.REF : return typeof (java.sql.Ref); case JavaSqlTypes.SMALLINT : return DbTypes.TypeOfInt16; case JavaSqlTypes.STRUCT : return typeof (java.sql.Struct); case JavaSqlTypes.TIME : return DbTypes.TypeOfTimespan; case JavaSqlTypes.TIMESTAMP : return DbTypes.TypeOfDateTime; case JavaSqlTypes.TINYINT : return DbTypes.TypeOfByte; case JavaSqlTypes.VARBINARY : return DbTypes.TypeOfByteArray; case JavaSqlTypes.VARCHAR : return DbTypes.TypeOfString; default : return DbTypes.TypeOfObject; } } internal static object JavaResultSetToClrWrapper(CallableStatement results,int columnIndex,JavaSqlTypes javaSqlType,int maxLength ,ResultSetMetaData resultsMetaData) { object returnValue = null; sbyte[] sbyteArray; long milliseconds; long ticks; string s; columnIndex++; //jdbc style switch (javaSqlType) { case JavaSqlTypes.ARRAY : returnValue = results.getArray(columnIndex); break; case JavaSqlTypes.BIGINT : returnValue = results.getLong(columnIndex); break; case JavaSqlTypes.BINARY : case JavaSqlTypes.VARBINARY : case JavaSqlTypes.LONGVARBINARY : // FIXME : comsider using maxLength sbyteArray = results.getBytes(columnIndex); if (sbyteArray != null) { returnValue = vmw.common.TypeUtils.ToByteArray(sbyteArray); } break; case JavaSqlTypes.BIT : returnValue = results.getBoolean(columnIndex); break; case JavaSqlTypes.BLOB : // FIXME : comsider using maxLength java.sql.Blob blob = results.getBlob(columnIndex); if (blob != null) { InputStream input = blob.getBinaryStream(); if (input == null) { returnValue = new byte[0]; } else { long length = blob.length(); byte[] byteValue = new byte[length]; sbyte[] sbyteValue = vmw.common.TypeUtils.ToSByteArray(byteValue); input.read(sbyteValue); returnValue = byteValue; } } break; case JavaSqlTypes.CHAR : if (resultsMetaData != null && "uniqueidentifier".Equals(resultsMetaData.getColumnTypeName(columnIndex))) { returnValue = new Guid(results.getString(columnIndex)); } else { // Oracle Jdbc driver returns extra trailing 0 chars for NCHAR columns, so we threat this at parameter.Size level s = results.getString(columnIndex); if ((s != null) && (maxLength < s.Length)) { s = s.Substring(0,maxLength); } returnValue = s; } break; case JavaSqlTypes.CLOB : // FIXME : comsider using maxLength java.sql.Clob clob = results.getClob(columnIndex); if (clob != null) { java.io.Reader reader = clob.getCharacterStream(); if (reader == null) { returnValue = String.Empty; } else { long length = clob.length(); char[] charValue = new char[length]; reader.read(charValue); returnValue = new string(charValue); } } break; case JavaSqlTypes.TIME : Time t = results.getTime(columnIndex); if (t != null) { returnValue = new TimeSpan(JavaTimeToClrTicks(t)); } break; case JavaSqlTypes.DATE : Date d = results.getDate(columnIndex); if (d != null) { returnValue = new DateTime(JavaDateToClrTicks(d)); } break; case JavaSqlTypes.TIMESTAMP : Timestamp ts = results.getTimestamp(columnIndex); if (ts != null) { returnValue = new DateTime(JavaTimestampToClrTicks(ts)); } break; case JavaSqlTypes.DECIMAL : case JavaSqlTypes.NUMERIC : // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal // therefore we rely on scale if (resultsMetaData != null && resultsMetaData.getScale(columnIndex) == -127) { // Oracle db type FLOAT returnValue = results.getDouble(columnIndex); } else { java.math.BigDecimal bigDecimal = results.getBigDecimal(columnIndex); if (bigDecimal != null) { returnValue = vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bigDecimal); } } break; case JavaSqlTypes.DISTINCT : returnValue = results.getObject(columnIndex); break; case JavaSqlTypes.DOUBLE : returnValue = results.getDouble(columnIndex); break; case JavaSqlTypes.FLOAT : //float f = results.getFloat(columnIndex); returnValue = results.getDouble(columnIndex); break; case JavaSqlTypes.INTEGER : returnValue = results.getInt(columnIndex); break; case JavaSqlTypes.JAVA_OBJECT : returnValue = results.getObject(columnIndex); break; case JavaSqlTypes.LONGVARCHAR : returnValue = results.getString(columnIndex); break; case JavaSqlTypes.NULL : returnValue = DBNull.Value; break; case JavaSqlTypes.OTHER : returnValue = results.getObject(columnIndex); break; case JavaSqlTypes.REAL : returnValue = results.getFloat(columnIndex); break; case JavaSqlTypes.REF : returnValue = results.getRef(columnIndex); break; case JavaSqlTypes.SMALLINT : returnValue = results.getShort(columnIndex); break; case JavaSqlTypes.STRUCT : returnValue = results.getObject(columnIndex); break; case JavaSqlTypes.TINYINT : returnValue = Convert.ToByte(results.getByte(columnIndex)); break; case JavaSqlTypes.VARCHAR : s = results.getString(columnIndex); if ((s != null) && (maxLength < s.Length)) { s = s.Substring(0,maxLength); } returnValue = s; break; default : returnValue = results.getObject(columnIndex); break; } if (results.wasNull() || results == null) { return DBNull.Value; } return returnValue; } #endregion // Methods } }