2
0

DbConvert.cs 12 KB

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