DbConvert.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. //
  2. // System.Data.Common.DbConvert
  3. //
  4. // Author:
  5. // Boris Kirzner ([email protected])
  6. //
  7. using System;
  8. using java.io;
  9. using java.sql;
  10. namespace System.Data.Common
  11. {
  12. internal class DbConvert
  13. {
  14. #region Fields
  15. const long JAVA_MIN_MILLIS_UTC = -62135769600000L; // java.sql.Timestamp.valueOf("0001-01-01 00:00:00.000000000").getTime() at Greenwich time zone.
  16. static readonly long TIMEZONE_RAW_OFFSET;
  17. // .NET milliseconds value of DateTime(1582,1,1,0,0,0,0).Ticks/TimeSpan.TicksPerMillisecond
  18. const long CLR_MILLIS_1582 = 49891507200000L;
  19. const long MILLIS_PER_TWO_DAYS = 2 * TimeSpan.TicksPerDay / TimeSpan.TicksPerMillisecond; // 172800000L;
  20. internal static readonly java.util.TimeZone DEFAULT_TIME_ZONE;
  21. #endregion // Fields
  22. #region Methods
  23. static DbConvert()
  24. {
  25. DEFAULT_TIME_ZONE = java.util.SimpleTimeZone.getDefault();
  26. TIMEZONE_RAW_OFFSET = (long)DEFAULT_TIME_ZONE.getRawOffset();
  27. }
  28. // The diff between .Net and Java goes as the following:
  29. // * at 1582: java has 10 days less than .net
  30. // * below 1500 (exept 1200,800,400) : each 100'th year java adds 1 day over .net.
  31. // Current implementation compatible with .net in 1-99 and since 1582. In 100-1582 we're not compatible with .Ner nor with Java
  32. internal static long JavaMillisToClrMillis(long javaMillis)
  33. {
  34. return JavaMillisToClrMillisUTC(javaMillis) + TIMEZONE_RAW_OFFSET;
  35. }
  36. internal static long JavaMillisToClrMillisUTC(long javaMillis) {
  37. long clrMillis = javaMillis - JAVA_MIN_MILLIS_UTC;
  38. if (clrMillis > CLR_MILLIS_1582) {
  39. clrMillis -= MILLIS_PER_TWO_DAYS;
  40. }
  41. return clrMillis;
  42. }
  43. internal static long ClrMillisToJavaMillis(long clrMillis)
  44. {
  45. return ClrMillisToJavaMillisUTC(clrMillis) - TIMEZONE_RAW_OFFSET;
  46. }
  47. internal static long ClrMillisToJavaMillisUTC(long clrMillis) {
  48. long javaMillis = clrMillis + JAVA_MIN_MILLIS_UTC;
  49. if (clrMillis > CLR_MILLIS_1582) {
  50. javaMillis += MILLIS_PER_TWO_DAYS;
  51. }
  52. return javaMillis;
  53. }
  54. internal static java.sql.Time ClrTicksToJavaTime(long ticks) {
  55. return new Time((ticks / TimeSpan.TicksPerMillisecond)
  56. - DEFAULT_TIME_ZONE.getRawOffset());
  57. }
  58. internal static java.sql.Date ClrTicksToJavaDate(long ticks) {
  59. java.sql.Date d = new java.sql.Date(0);
  60. ClrTicksToJavaDate(d, ticks);
  61. return d;
  62. }
  63. internal static java.sql.Timestamp ClrTicksToJavaTimestamp(long ticks)
  64. {
  65. java.sql.Timestamp ts = new java.sql.Timestamp(0);
  66. ClrTicksToJavaDate(ts, ticks);
  67. // int nanos = (int)(ticks % TimeSpan.TicksPerMillisecond) * 100;
  68. // ts.setNanos(javaTimestamp.getNanos() + nanos);
  69. return ts;
  70. }
  71. internal static void ClrTicksToJavaDate(java.util.Date d, long ticks) {
  72. long millis = ClrMillisToJavaMillis(ticks / TimeSpan.TicksPerMillisecond);
  73. d.setTime(millis);
  74. if (DEFAULT_TIME_ZONE.inDaylightTime(d)) {
  75. millis -= DEFAULT_TIME_ZONE.getDSTSavings();
  76. d.setTime(millis);
  77. }
  78. }
  79. internal static long JavaTimestampToClrTicks(java.sql.Timestamp ts)
  80. {
  81. long ticks = JavaDateToClrTicks(ts);
  82. // Extra ticks, for dbs that can save them.
  83. // We do not use it, since .net does not saves ticks for fractial milliseconds
  84. // long ticksLessThanMilliseconds = (ts.getNanos()*100) % TimeSpan.TicksPerMillisecond;
  85. // ticks += ticksLessThanMilliseconds;
  86. return ticks;
  87. }
  88. internal static long JavaDateToClrTicks(java.util.Date d) {
  89. long millis = JavaMillisToClrMillis(d.getTime());
  90. if (DEFAULT_TIME_ZONE.inDaylightTime(d)) {
  91. millis += DEFAULT_TIME_ZONE.getDSTSavings();
  92. }
  93. return millis * TimeSpan.TicksPerMillisecond;
  94. }
  95. internal static long JavaTimeToClrTicks(java.sql.Time t) {
  96. return (t.getTime() + DEFAULT_TIME_ZONE.getRawOffset())
  97. * TimeSpan.TicksPerMillisecond;
  98. }
  99. internal protected static Type JavaSqlTypeToClrType(int sqlTypeValue)
  100. {
  101. DbTypes.JavaSqlTypes sqlType = (DbTypes.JavaSqlTypes)sqlTypeValue;
  102. switch (sqlType) {
  103. case DbTypes.JavaSqlTypes.ARRAY : return typeof (java.sql.Array);
  104. case DbTypes.JavaSqlTypes.BIGINT : return DbTypes.TypeOfInt64;
  105. case DbTypes.JavaSqlTypes.BINARY : return DbTypes.TypeOfByteArray;
  106. case DbTypes.JavaSqlTypes.BIT : return DbTypes.TypeOfBoolean;
  107. case DbTypes.JavaSqlTypes.BLOB : return DbTypes.TypeOfByteArray;
  108. case DbTypes.JavaSqlTypes.BOOLEAN : return DbTypes.TypeOfBoolean;
  109. case DbTypes.JavaSqlTypes.CHAR : return DbTypes.TypeOfString;
  110. case DbTypes.JavaSqlTypes.CLOB : return DbTypes.TypeOfString;
  111. // case DbTypes.JavaSqlTypes.DATALINK :
  112. case DbTypes.JavaSqlTypes.DATE : return DbTypes.TypeOfDateTime;
  113. case DbTypes.JavaSqlTypes.DECIMAL : return DbTypes.TypeOfDecimal;
  114. // case DbTypes.JavaSqlTypes.DISTINCT :
  115. case DbTypes.JavaSqlTypes.DOUBLE : return DbTypes.TypeOfDouble;
  116. case DbTypes.JavaSqlTypes.FLOAT : return DbTypes.TypeOfDouble;
  117. case DbTypes.JavaSqlTypes.INTEGER : return DbTypes.TypeOfInt32;
  118. // case DbTypes.JavaSqlTypes.JAVA_OBJECT :
  119. case DbTypes.JavaSqlTypes.LONGVARBINARY : return DbTypes.TypeOfByteArray;
  120. case DbTypes.JavaSqlTypes.LONGVARCHAR : return DbTypes.TypeOfString;
  121. case DbTypes.JavaSqlTypes.NULL : return null;
  122. case DbTypes.JavaSqlTypes.NUMERIC : return DbTypes.TypeOfDecimal;
  123. // case DbTypes.JavaSqlTypes.OTHER :
  124. case DbTypes.JavaSqlTypes.REAL : return DbTypes.TypeOfSingle;
  125. case DbTypes.JavaSqlTypes.REF : return typeof (java.sql.Ref);
  126. case DbTypes.JavaSqlTypes.SMALLINT : return DbTypes.TypeOfInt16;
  127. case DbTypes.JavaSqlTypes.STRUCT : return typeof (java.sql.Struct);
  128. case DbTypes.JavaSqlTypes.TIME : return DbTypes.TypeOfTimespan;
  129. case DbTypes.JavaSqlTypes.TIMESTAMP : return DbTypes.TypeOfDateTime;
  130. case DbTypes.JavaSqlTypes.TINYINT : return DbTypes.TypeOfByte;
  131. case DbTypes.JavaSqlTypes.VARBINARY : return DbTypes.TypeOfByteArray;
  132. case DbTypes.JavaSqlTypes.VARCHAR : return DbTypes.TypeOfString;
  133. default : return DbTypes.TypeOfObject;
  134. }
  135. }
  136. internal protected static object JavaResultSetToClrWrapper(CallableStatement results,int columnIndex,DbTypes.JavaSqlTypes javaSqlType,int maxLength ,ResultSetMetaData resultsMetaData)
  137. {
  138. object returnValue = null;
  139. sbyte[] sbyteArray;
  140. long milliseconds;
  141. long ticks;
  142. string s;
  143. columnIndex++; //jdbc style
  144. switch (javaSqlType) {
  145. case DbTypes.JavaSqlTypes.ARRAY :
  146. returnValue = results.getArray(columnIndex);
  147. break;
  148. case DbTypes.JavaSqlTypes.BIGINT :
  149. returnValue = results.getLong(columnIndex);
  150. break;
  151. case DbTypes.JavaSqlTypes.BINARY :
  152. case DbTypes.JavaSqlTypes.VARBINARY :
  153. case DbTypes.JavaSqlTypes.LONGVARBINARY :
  154. // FIXME : comsider using maxLength
  155. sbyteArray = results.getBytes(columnIndex);
  156. if (sbyteArray != null) {
  157. returnValue = vmw.common.TypeUtils.ToByteArray(sbyteArray);
  158. }
  159. break;
  160. case DbTypes.JavaSqlTypes.BIT :
  161. returnValue = results.getBoolean(columnIndex);
  162. break;
  163. case DbTypes.JavaSqlTypes.BLOB :
  164. // FIXME : comsider using maxLength
  165. java.sql.Blob blob = results.getBlob(columnIndex);
  166. if (blob != null) {
  167. InputStream input = blob.getBinaryStream();
  168. if (input == null) {
  169. returnValue = new byte[0];
  170. }
  171. else {
  172. long length = blob.length();
  173. byte[] byteValue = new byte[length];
  174. sbyte[] sbyteValue = vmw.common.TypeUtils.ToSByteArray(byteValue);
  175. input.read(sbyteValue);
  176. returnValue = byteValue;
  177. }
  178. }
  179. break;
  180. case DbTypes.JavaSqlTypes.CHAR :
  181. if (resultsMetaData != null && "uniqueidentifier".Equals(resultsMetaData.getColumnTypeName(columnIndex))) {
  182. returnValue = new Guid(results.getString(columnIndex));
  183. }
  184. else {
  185. // Oracle Jdbc driver returns extra trailing 0 chars for NCHAR columns, so we threat this at parameter.Size level
  186. s = results.getString(columnIndex);
  187. if ((s != null) && (maxLength < s.Length)) {
  188. s = s.Substring(0,maxLength);
  189. }
  190. returnValue = s;
  191. }
  192. break;
  193. case DbTypes.JavaSqlTypes.CLOB :
  194. // FIXME : comsider using maxLength
  195. java.sql.Clob clob = results.getClob(columnIndex);
  196. if (clob != null) {
  197. java.io.Reader reader = clob.getCharacterStream();
  198. if (reader == null) {
  199. returnValue = String.Empty;
  200. }
  201. else {
  202. long length = clob.length();
  203. char[] charValue = new char[length];
  204. reader.read(charValue);
  205. returnValue = new string(charValue);
  206. }
  207. }
  208. break;
  209. case DbTypes.JavaSqlTypes.TIME :
  210. Time t = results.getTime(columnIndex);
  211. if (t != null) {
  212. returnValue = new TimeSpan(JavaTimeToClrTicks(t));
  213. }
  214. break;
  215. case DbTypes.JavaSqlTypes.DATE :
  216. Date d = results.getDate(columnIndex);
  217. if (d != null) {
  218. returnValue = new DateTime(JavaDateToClrTicks(d));
  219. }
  220. break;
  221. case DbTypes.JavaSqlTypes.TIMESTAMP :
  222. Timestamp ts = results.getTimestamp(columnIndex);
  223. if (ts != null) {
  224. returnValue = new DateTime(JavaTimestampToClrTicks(ts));
  225. }
  226. break;
  227. case DbTypes.JavaSqlTypes.DECIMAL :
  228. case DbTypes.JavaSqlTypes.NUMERIC :
  229. // java.sql.Types.NUMERIC (2), columnTypeName NUMBER, columnClassName java.math.BigDecimal
  230. // therefore we rely on scale
  231. if (resultsMetaData != null && resultsMetaData.getScale(columnIndex) == -127) {
  232. // Oracle db type FLOAT
  233. returnValue = results.getDouble(columnIndex);
  234. }
  235. else {
  236. java.math.BigDecimal bigDecimal = results.getBigDecimal(columnIndex);
  237. if (bigDecimal != null) {
  238. returnValue = vmw.common.PrimitiveTypeUtils.BigDecimalToDecimal(bigDecimal);
  239. }
  240. }
  241. break;
  242. case DbTypes.JavaSqlTypes.DISTINCT :
  243. returnValue = results.getObject(columnIndex);
  244. break;
  245. case DbTypes.JavaSqlTypes.DOUBLE :
  246. returnValue = results.getDouble(columnIndex);
  247. break;
  248. case DbTypes.JavaSqlTypes.FLOAT :
  249. //float f = results.getFloat(columnIndex);
  250. returnValue = results.getDouble(columnIndex);
  251. break;
  252. case DbTypes.JavaSqlTypes.INTEGER :
  253. returnValue = results.getInt(columnIndex);
  254. break;
  255. case DbTypes.JavaSqlTypes.JAVA_OBJECT :
  256. returnValue = results.getObject(columnIndex);
  257. break;
  258. case DbTypes.JavaSqlTypes.LONGVARCHAR :
  259. returnValue = results.getString(columnIndex);
  260. break;
  261. case DbTypes.JavaSqlTypes.NULL :
  262. returnValue = DBNull.Value;
  263. break;
  264. case DbTypes.JavaSqlTypes.OTHER :
  265. returnValue = results.getObject(columnIndex);
  266. break;
  267. case DbTypes.JavaSqlTypes.REAL :
  268. returnValue = results.getFloat(columnIndex);
  269. break;
  270. case DbTypes.JavaSqlTypes.REF :
  271. returnValue = results.getRef(columnIndex);
  272. break;
  273. case DbTypes.JavaSqlTypes.SMALLINT :
  274. returnValue = results.getShort(columnIndex);
  275. break;
  276. case DbTypes.JavaSqlTypes.STRUCT :
  277. returnValue = results.getObject(columnIndex);
  278. break;
  279. case DbTypes.JavaSqlTypes.TINYINT :
  280. returnValue = Convert.ToByte(results.getByte(columnIndex));
  281. break;
  282. case DbTypes.JavaSqlTypes.VARCHAR :
  283. s = results.getString(columnIndex);
  284. if ((s != null) && (maxLength < s.Length)) {
  285. s = s.Substring(0,maxLength);
  286. }
  287. returnValue = s;
  288. break;
  289. default :
  290. returnValue = results.getObject(columnIndex);
  291. break;
  292. }
  293. if (results.wasNull() || results == null) {
  294. return DBNull.Value;
  295. }
  296. return returnValue;
  297. }
  298. #endregion // Methods
  299. }
  300. }