This repository has been archived by the owner on Apr 17, 2018. It is now read-only.
/
AbstractDriverDefinition.java
855 lines (784 loc) · 25.8 KB
/
AbstractDriverDefinition.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
package data_objects.drivers;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.net.URISyntaxException;
import java.sql.Connection;
import java.sql.Date;
import java.sql.Driver;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Map;
import java.util.Properties;
import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.jruby.Ruby;
import org.jruby.RubyBigDecimal;
import org.jruby.RubyBignum;
import org.jruby.RubyClass;
import org.jruby.RubyFixnum;
import org.jruby.RubyFloat;
import org.jruby.RubyHash;
import org.jruby.RubyNumeric;
import org.jruby.RubyObjectAdapter;
import org.jruby.RubyProc;
import org.jruby.RubyRegexp;
import org.jruby.RubyString;
import org.jruby.RubyTime;
import org.jruby.exceptions.RaiseException;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.builtin.IRubyObject;
import org.jruby.runtime.marshal.UnmarshalStream;
import org.jruby.util.ByteList;
import data_objects.RubyType;
/**
*
* @author alexbcoles
* @author mkristian
*/
public abstract class AbstractDriverDefinition implements DriverDefinition {
// assuming that API is thread safe
protected static final RubyObjectAdapter API = JavaEmbedUtils
.newObjectAdapter();
protected final static DateTimeFormatter DATE_TIME_FORMAT = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
private final static BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE);
private final static BigInteger LONG_MIN = BigInteger.valueOf(Long.MIN_VALUE);
private final static long MRI_FIXNUM_MAX = (1L<<32) - 1;
private final static long MRI_FIXNUM_MIN = -1 * MRI_FIXNUM_MAX - 1;
private final String scheme;
private final String jdbcScheme;
private final String moduleName;
private final Driver driver;
/**
*
* @param scheme
* @param moduleName
* @param jdbcDriver
*/
protected AbstractDriverDefinition(String scheme, String moduleName, String jdbcDriver) {
this(scheme, scheme, moduleName, jdbcDriver);
}
/**
*
* @param scheme
* @param jdbcScheme
* @param moduleName
* @param jdbcDriver
*/
protected AbstractDriverDefinition(String scheme, String jdbcScheme,
String moduleName, String jdbcDriver) {
this.scheme = scheme;
this.jdbcScheme = jdbcScheme;
this.moduleName = moduleName;
try {
this.driver = (Driver)loadClass(jdbcDriver).newInstance();
}
catch (InstantiationException e) {
throw new RuntimeException("should not happen", e);
}
catch (IllegalAccessException e) {
throw new RuntimeException("should not happen", e);
}
catch (ClassNotFoundException e) {
throw new RuntimeException("should not happen", e);
}
}
private Class<?> loadClass(String className)
throws ClassNotFoundException {
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
Class<?> result = null;
try {
if (ccl != null) {
result = ccl.loadClass(className);
}
} catch (ClassNotFoundException e) {
// ignore
}
if (result == null) {
result = getClass().getClassLoader().loadClass(className);
}
return result;
}
/**
*
* @return
*/
public String getModuleName() {
return this.moduleName;
}
/**
*
* @return
*/
public String getErrorName() {
return this.moduleName + "Error";
}
/**
*
* @param uri jdbc uri for which a connection is created
* @param properties further properties needed to create a cconnection, i.e. username + password
* @return
* @throws SQLException
*/
public Connection getConnection(String uri, Properties properties) throws SQLException{
return driver.connect(uri, properties);
}
/**
*
* @param connection_uri
* @return
* @throws URISyntaxException
* @throws UnsupportedEncodingException
*/
@SuppressWarnings("unchecked")
public URI parseConnectionURI(IRubyObject connection_uri)
throws URISyntaxException, UnsupportedEncodingException {
URI uri;
if ("DataObjects::URI".equals(connection_uri.getType().getName())) {
String query;
StringBuilder userInfo = new StringBuilder();
verifyScheme(stringOrNull(API.callMethod(connection_uri, "scheme")));
String user = stringOrNull(API.callMethod(connection_uri, "user"));
String password = stringOrNull(API.callMethod(connection_uri,
"password"));
String host = stringOrNull(API.callMethod(connection_uri, "host"));
int port = intOrMinusOne(API.callMethod(connection_uri, "port"));
String path = stringOrNull(API.callMethod(connection_uri, "path"));
IRubyObject query_values = API.callMethod(connection_uri, "query");
String fragment = stringOrNull(API.callMethod(connection_uri,
"fragment"));
if (user != null && !"".equals(user)) {
userInfo.append(user);
if (password != null) {
userInfo.append(":").append(password);
}
}
if (query_values.isNil()) {
query = null;
} else if (query_values instanceof RubyHash) {
query = mapToQueryString(query_values.convertToHash());
} else {
query = API.callMethod(query_values, "to_s").asJavaString();
}
if (host != null && !"".equals(host)) {
// a client/server database (e.g. MySQL, PostgreSQL, MS
// SQLServer)
String normalizedPath;
if (path != null && path.length() > 0 && path.charAt(0) != '/') {
normalizedPath = '/' + path;
} else {
normalizedPath = path;
}
uri = new URI(this.jdbcScheme,
(userInfo.length() > 0 ? userInfo.toString() : null),
host, port, normalizedPath, query, fragment);
} else {
// an embedded / file-based database (e.g. SQLite3, Derby
// (embedded mode), HSQLDB - use opaque uri
uri = new URI(this.jdbcScheme, path, fragment);
}
} else {
// If connection_uri comes in as a string, we just pass it
// through
uri = new URI(connection_uri.asJavaString());
}
return uri;
}
/**
*
* @param scheme
*/
protected void verifyScheme(String scheme) {
if (!this.scheme.equals(scheme)) {
throw new RuntimeException("scheme mismatch, expected: "
+ this.scheme + " but got: " + scheme);
}
}
/**
* Convert a map of key/values to a URI query string
*
* @param map
* @return
* @throws java.io.UnsupportedEncodingException
*/
private String mapToQueryString(Map<Object, Object> map)
throws UnsupportedEncodingException {
StringBuilder querySb = new StringBuilder();
for (Map.Entry<Object, Object> pairs: map.entrySet()){
String key = (pairs.getKey() != null) ? pairs.getKey().toString()
: "";
String value = (pairs.getValue() != null) ? pairs.getValue()
.toString() : "";
querySb.append(java.net.URLEncoder.encode(key, "UTF-8"))
.append("=");
querySb.append(java.net.URLEncoder.encode(value, "UTF-8"));
}
return querySb.toString();
}
/**
*
* @param runtime
* @param message
* @return
*/
public RaiseException newDriverError(Ruby runtime, String message) {
RubyClass driverError = runtime.getClass(getErrorName());
return new RaiseException(runtime, driverError, message, true);
}
/**
*
* @param runtime
* @param exception
* @return
*/
public RaiseException newDriverError(Ruby runtime, SQLException exception) {
return newDriverError(runtime, exception, null);
}
/**
*
* @param runtime
* @param exception
* @param statement
* @return
*/
public RaiseException newDriverError(Ruby runtime, SQLException exception,
java.sql.Statement statement) {
RubyClass driverError = runtime.getClass(getErrorName());
int code = exception.getErrorCode();
StringBuilder sb = new StringBuilder("(");
// Append the Vendor Code, if there is one
// TODO: parse vendor exception codes
// TODO: replace 'vendor' with vendor name
if (code > 0)
sb.append("vendor_errno=").append(code).append(", ");
sb.append("sql_state=").append(exception.getSQLState()).append(") ");
sb.append(exception.getLocalizedMessage());
if (statement != null)
sb.append("\nQuery: ").append(statementToString(statement));
return new RaiseException(runtime, driverError, sb.toString(), true);
}
/**
*
* @return
*/
public RubyObjectAdapter getObjectAdapter() {
return API;
}
/**
*
* @param type
* @param precision
* @param scale
* @return
*/
public RubyType jdbcTypeToRubyType(int type, int precision, int scale) {
return RubyType.jdbcTypeToRubyType(type, scale);
}
/**
*
* @param runtime
* @param rs
* @param col
* @param type
* @return
* @throws SQLException
* @throws IOException
*/
public IRubyObject getTypecastResultSetValue(Ruby runtime,
ResultSet rs, int col, RubyType type) throws SQLException,
IOException {
//System.out.println(rs.getMetaData().getColumnTypeName(col) + " = " + type.toString());
switch (type) {
case FIXNUM:
case INTEGER:
case BIGNUM:
try {
// in most cases integers will fit into long type
// and therefore should be faster to use getLong
long lng = rs.getLong(col);
if (rs.wasNull()) {
return runtime.getNil();
}
// return RubyNumeric.int2fix(runtime, lng);
//
// Currently problematic as JRUBY has different boundaries for
// Bignum/Fixnum: see http://jira.codehaus.org/browse/JRUBY-1587
if (lng >= MRI_FIXNUM_MAX || lng < MRI_FIXNUM_MIN) {
return RubyBignum.newBignum(runtime, lng);
}
return RubyFixnum.newFixnum(runtime, lng);
} catch (SQLException sqle) {
// if getLong failed then use getBigDecimal
BigDecimal bdi = rs.getBigDecimal(col);
if (bdi == null) {
return runtime.getNil();
}
// will return either Fixnum or Bignum
return RubyBignum.bignorm(runtime, bdi.toBigInteger());
}
case FLOAT:
// TODO: why getDouble is not used here?
BigDecimal bdf = rs.getBigDecimal(col);
if (bdf == null) {
return runtime.getNil();
}
return new RubyFloat(runtime, bdf.doubleValue());
case BIG_DECIMAL:
BigDecimal bd = rs.getBigDecimal(col);
if (bd == null) {
return runtime.getNil();
}
return new RubyBigDecimal(runtime, bd);
case DATE:
java.sql.Date date = rs.getDate(col);
if (date == null) {
return runtime.getNil();
}
return prepareRubyDateFromSqlDate(runtime, sqlDateToDateTime(date));
case DATE_TIME:
java.sql.Timestamp dt = null;
// DateTimes with all-zero components throw a SQLException with
// SQLState S1009 in MySQL Connector/J 3.1+
// See
// http://dev.mysql.com/doc/refman/5.0/en/connector-j-installing-upgrading.html
try {
dt = rs.getTimestamp(col);
} catch (SQLException ignored) {
}
if (dt == null) {
return runtime.getNil();
}
return prepareRubyDateTimeFromSqlTimestamp(runtime, sqlTimestampToDateTime(dt));
case TIME:
switch (rs.getMetaData().getColumnType(col)) {
case Types.TIME:
java.sql.Time tm = rs.getTime(col);
if (tm == null) {
return runtime.getNil();
}
return prepareRubyTimeFromSqlTime(runtime, new DateTime(tm));
case Types.TIMESTAMP:
java.sql.Timestamp ts = rs.getTimestamp(col);
if (ts == null) {
return runtime.getNil();
}
return prepareRubyTimeFromSqlTime(runtime, sqlTimestampToDateTime(ts));
case Types.DATE:
java.sql.Date da = rs.getDate(col);
if (da == null) {
return runtime.getNil();
}
return prepareRubyTimeFromSqlDate(runtime, da);
default:
String str = rs.getString(col);
if (str == null) {
return runtime.getNil();
}
RubyString return_str = RubyString.newUnicodeString(runtime,
str);
return_str.setTaint(true);
return return_str;
}
case TRUE_CLASS:
// getBoolean delivers False in case the underlying data is null
if (rs.getString(col) == null){
return runtime.getNil();
}
return runtime.newBoolean(rs.getBoolean(col));
case BYTE_ARRAY:
InputStream binaryStream = rs.getBinaryStream(col);
ByteList bytes = new ByteList(2048);
try {
byte[] buf = new byte[2048];
for (int n = binaryStream.read(buf); n != -1; n = binaryStream
.read(buf)) {
bytes.append(buf, 0, n);
}
} finally {
binaryStream.close();
}
return API.callMethod(runtime.fastGetModule("Extlib").fastGetClass(
"ByteArray"), "new", runtime.newString(bytes));
case CLASS:
String classNameStr = rs.getString(col);
if (classNameStr == null) {
return runtime.getNil();
}
RubyString class_name_str = RubyString.newUnicodeString(runtime, rs
.getString(col));
class_name_str.setTaint(true);
return API.callMethod(runtime.fastGetModule("DataObjects"), "full_const_get",
class_name_str);
case OBJECT:
InputStream asciiStream = rs.getAsciiStream(col);
IRubyObject obj = runtime.getNil();
UnmarshalStream ums = null;
try {
ums = new UnmarshalStream(runtime, asciiStream,
RubyProc.NEVER);
obj = ums.unmarshalObject();
} catch (IOException ioe) {
// TODO: log this
}finally {
if(ums != null){
try{
ums.close();
}catch (Exception ex){
//TODO log this
}
}
}
return obj;
case NIL:
return runtime.getNil();
case STRING:
default:
String str = rs.getString(col);
if (str == null) {
return runtime.getNil();
}
RubyString return_str = RubyString.newUnicodeString(runtime, str);
return_str.setTaint(true);
return return_str;
}
}
/**
*
* @param ps
* @param arg
* @param idx
* @throws SQLException
*/
public void setPreparedStatementParam(PreparedStatement ps,
IRubyObject arg, int idx) throws SQLException {
switch (RubyType.inferRubyType(arg)) {
case FIXNUM:
ps.setInt(idx, Integer.parseInt(arg.toString()));
break;
case BIGNUM:
BigInteger big = ((RubyBignum) arg).getValue();
if (big.compareTo(LONG_MIN) < 0 || big.compareTo(LONG_MAX) > 0) {
// set as big decimal
ps.setBigDecimal(idx, new BigDecimal(((RubyBignum) arg).getValue()));
} else {
// set as long
ps.setLong(idx, ((RubyBignum) arg).getLongValue());
}
break;
case FLOAT:
ps.setDouble(idx, RubyNumeric.num2dbl(arg));
break;
case BIG_DECIMAL:
ps.setBigDecimal(idx, ((RubyBigDecimal) arg).getValue());
break;
case NIL:
ps.setNull(idx, ps.getParameterMetaData().getParameterType(idx));
break;
case TRUE_CLASS:
case FALSE_CLASS:
ps.setBoolean(idx, arg.toString().equals("true"));
break;
case STRING:
ps.setString(idx, arg.toString());
break;
case CLASS:
ps.setString(idx, arg.toString());
break;
case BYTE_ARRAY:
ps.setBytes(idx, ((RubyString) arg).getBytes());
break;
// TODO: add support for ps.setBlob();
case DATE:
ps.setDate(idx, java.sql.Date.valueOf(arg.toString()));
break;
case TIME:
DateTime dateTime = ((RubyTime) arg).getDateTime();
Timestamp ts = new Timestamp(dateTime.getMillis());
ps.setTimestamp(idx, ts, dateTime.toGregorianCalendar());
break;
case DATE_TIME:
String datetime = arg.toString().replace('T', ' ');
ps.setTimestamp(idx, Timestamp.valueOf(datetime
.replaceFirst("[-+]..:..$", "")));
break;
case REGEXP:
ps.setString(idx, ((RubyRegexp) arg).source().toString());
break;
// default case handling is simplified
// TODO: if something is not working because of that then should be added to specs
default:
int jdbcType = ps.getParameterMetaData().getParameterType(idx);
ps.setObject(idx, arg.toString(), jdbcType);
}
}
/**
*
* @param sqlText
* @param ps
* @param idx
* @return
* @throws SQLException
*/
public boolean registerPreparedStatementReturnParam(String sqlText, PreparedStatement ps, int idx) throws SQLException {
return false;
}
/**
*
* @param ps
* @return
* @throws SQLException
*/
public long getPreparedStatementReturnParam(PreparedStatement ps) throws SQLException {
return 0;
}
/**
*
* @param sqlText
* @param args
* @return
*/
public String prepareSqlTextForPs(String sqlText, IRubyObject[] args) {
return sqlText;
}
/**
*
* @return
*/
public abstract boolean supportsJdbcGeneratedKeys();
/**
*
* @return
*/
public abstract boolean supportsJdbcScrollableResultSets();
/**
*
* @return
*/
public boolean supportsConnectionEncodings() {
return false;
}
/**
*
* @return
*/
public boolean supportsConnectionPrepareStatementMethodWithGKFlag() {
return true;
}
/**
*
* @param connection
* @return
*/
public ResultSet getGeneratedKeys(Connection connection) {
return null;
}
/**
*
* @return
*/
public Properties getDefaultConnectionProperties() {
return new Properties();
}
/**
*
* @param connectionUri
* @return
*/
public String getJdbcUri(URI connectionUri) {
String jdbcUri = connectionUri.toString();
if (jdbcUri.contains("@")) {
jdbcUri = connectionUri.toString().replaceFirst("://.*@", "://");
}
// Replace . with : in scheme name - necessary for Oracle scheme oracle:thin
// : cannot be used in JDBC_URI_SCHEME as then it is identified as opaque URI
// jdbcUri = jdbcUri.replaceFirst("^([a-z]+)(\\.)", "$1:");
if (!jdbcUri.startsWith("jdbc:")) {
jdbcUri = "jdbc:" + jdbcUri;
}
return jdbcUri;
}
/**
*
* @param doConn
* @param conn
* @param query
* @throws SQLException
*/
public void afterConnectionCallback(IRubyObject doConn, Connection conn,
Map<String, String> query) throws SQLException {
// do nothing
}
/**
*
* @param props
* @param encodingName
*/
public void setEncodingProperty(Properties props, String encodingName) {
// do nothing
}
/**
*
* @param runtime
* @param connection
* @param url
* @param props
* @return
* @throws SQLException
*/
public Connection getConnectionWithEncoding(Ruby runtime, IRubyObject connection,
String url, Properties props) throws SQLException {
throw new UnsupportedOperationException("This method only returns a method"
+ " for drivers that support specifiying an encoding.");
}
/**
*
* @param str
* @return
*/
public String quoteString(String str) {
StringBuilder quotedValue = new StringBuilder(str.length() + 2);
quotedValue.append("\'");
quotedValue.append(str.replaceAll("'", "''"));
quotedValue.append("\'");
return quotedValue.toString();
}
/**
*
* @param connection
* @param value
* @return
*/
public String quoteByteArray(IRubyObject connection, IRubyObject value) {
return quoteString(value.asJavaString());
}
/**
*
* @param s
* @return
*/
public String statementToString(Statement s) {
return s.toString();
}
/**
*
* @param date
* @return
*/
protected static DateTime sqlDateToDateTime(Date date) {
if (date == null)
return null;
else
return new DateTime(date);
}
/**
*
* @param ts
* @return
*/
protected static DateTime sqlTimestampToDateTime(Timestamp ts) {
if (ts == null)
return null;
else
return new DateTime(ts);
}
/**
*
* @param runtime
* @param stamp
* @return
*/
protected static IRubyObject prepareRubyDateTimeFromSqlTimestamp(
Ruby runtime, DateTime stamp) {
if (stamp.getMillis() == 0) {
return runtime.getNil();
}
int zoneOffset = stamp.getZone().getOffset(stamp.getMillis()) / 3600000;
RubyClass klazz = runtime.fastGetClass("DateTime");
IRubyObject rbOffset = runtime.fastGetClass("Rational").callMethod(
runtime.getCurrentContext(),
"new",
new IRubyObject[] { runtime.newFixnum(zoneOffset),
runtime.newFixnum(24) });
return klazz.callMethod(runtime.getCurrentContext(), "civil",
new IRubyObject[] { runtime.newFixnum(stamp.getYear()),
runtime.newFixnum(stamp.getMonthOfYear()),
runtime.newFixnum(stamp.getDayOfMonth()),
runtime.newFixnum(stamp.getHourOfDay()),
runtime.newFixnum(stamp.getMinuteOfHour()),
runtime.newFixnum(stamp.getSecondOfMinute()),
rbOffset });
}
/**
*
* @param runtime
* @param time
* @return
*/
protected static IRubyObject prepareRubyTimeFromSqlTime(Ruby runtime,
DateTime time) {
// TODO: why in this case nil is returned?
if (time.getMillis() + 3600000 == 0) {
return runtime.getNil();
}
RubyTime rbTime = RubyTime.newTime(runtime, time);
return rbTime;
}
/**
*
* @param runtime
* @param date
* @return
*/
protected static IRubyObject prepareRubyTimeFromSqlDate(Ruby runtime,
Date date) {
if (date.getTime() + 3600000 == 0) {
return runtime.getNil();
}
RubyTime rbTime = RubyTime.newTime(runtime, date.getTime());
return rbTime;
}
/**
*
* @param runtime
* @param date
* @return
*/
public static IRubyObject prepareRubyDateFromSqlDate(Ruby runtime,
DateTime date) {
if (date.getMillis() == 0) {
return runtime.getNil();
}
RubyClass klazz = runtime.fastGetClass("Date");
return klazz.callMethod(runtime.getCurrentContext(), "civil",
new IRubyObject[] { runtime.newFixnum(date.getYear()),
runtime.newFixnum(date.getMonthOfYear()),
runtime.newFixnum(date.getDayOfMonth()) });
}
/**
*
* @param obj
* @return
*/
private static String stringOrNull(IRubyObject obj) {
return (!obj.isNil()) ? obj.asJavaString() : null;
}
/**
*
* @param obj
* @return
*/
private static int intOrMinusOne(IRubyObject obj) {
return (!obj.isNil()) ? RubyFixnum.fix2int(obj) : -1;
}
// private static Integer integerOrNull(IRubyObject obj) {
// return (!obj.isNil()) ? RubyFixnum.fix2int(obj) : null;
// }
}