DbConvert.cs 12 KB

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