activerecord-jdbc-adapter 50.8-java → 51.1-java
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -2
- data/.travis.yml +26 -51
- data/Gemfile +3 -1
- data/README.md +9 -11
- data/Rakefile +15 -78
- data/activerecord-jdbc-adapter.gemspec +2 -2
- data/lib/active_record/connection_adapters/mssql_adapter.rb +1 -0
- data/lib/active_record/connection_adapters/sqlserver_adapter.rb +1 -0
- data/lib/arjdbc/abstract/core.rb +4 -12
- data/lib/arjdbc/abstract/database_statements.rb +4 -10
- data/lib/arjdbc/abstract/statement_cache.rb +4 -4
- data/lib/arjdbc/abstract/transaction_support.rb +2 -9
- data/lib/arjdbc/jdbc.rb +4 -0
- data/lib/arjdbc/jdbc/column.rb +11 -5
- data/lib/arjdbc/jdbc/connection_methods.rb +9 -2
- data/lib/arjdbc/jdbc/error.rb +1 -1
- data/lib/arjdbc/jdbc/jdbc.rake +4 -0
- data/lib/arjdbc/mssql.rb +7 -0
- data/lib/arjdbc/mssql/adapter.rb +804 -0
- data/lib/arjdbc/mssql/column.rb +200 -0
- data/lib/arjdbc/mssql/connection_methods.rb +79 -0
- data/lib/arjdbc/mssql/explain_support.rb +99 -0
- data/lib/arjdbc/mssql/limit_helpers.rb +231 -0
- data/lib/arjdbc/mssql/lock_methods.rb +77 -0
- data/lib/arjdbc/mssql/types.rb +343 -0
- data/lib/arjdbc/mssql/utils.rb +82 -0
- data/lib/arjdbc/mysql/adapter.rb +14 -11
- data/lib/arjdbc/mysql/connection_methods.rb +9 -18
- data/lib/arjdbc/postgresql/adapter.rb +108 -59
- data/lib/arjdbc/postgresql/column.rb +3 -6
- data/lib/arjdbc/postgresql/connection_methods.rb +3 -12
- data/lib/arjdbc/postgresql/oid_types.rb +14 -93
- data/lib/arjdbc/sqlite3/adapter.rb +171 -140
- data/lib/arjdbc/sqlite3/connection_methods.rb +1 -2
- data/lib/arjdbc/tasks/database_tasks.rb +36 -16
- data/lib/arjdbc/tasks/databases.rake +75 -32
- data/lib/arjdbc/tasks/databases3.rake +215 -0
- data/lib/arjdbc/tasks/databases4.rake +39 -0
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/01-tomcat.rake +2 -2
- data/rakelib/02-test.rake +3 -0
- data/rakelib/compile.rake +70 -0
- data/rakelib/db.rake +7 -21
- data/rakelib/rails.rake +4 -5
- data/src/java/arjdbc/ArJdbcModule.java +15 -5
- data/src/java/arjdbc/derby/DerbyRubyJdbcConnection.java +2 -2
- data/src/java/arjdbc/jdbc/ConnectionFactory.java +87 -0
- data/src/java/arjdbc/jdbc/DataSourceConnectionFactory.java +1 -0
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +41 -120
- data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +14 -310
- data/src/java/arjdbc/mysql/MySQLRubyJdbcConnection.java +2 -2
- data/src/java/arjdbc/postgresql/ByteaUtils.java +1 -0
- data/src/java/arjdbc/postgresql/PgResultSetMetaDataWrapper.java +23 -0
- data/src/java/arjdbc/postgresql/PostgreSQLResult.java +13 -21
- data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +46 -41
- data/src/java/arjdbc/util/DateTimeUtils.java +5 -141
- data/src/java/arjdbc/util/QuotingUtils.java +7 -6
- data/src/java/arjdbc/util/StringHelper.java +20 -6
- metadata +25 -16
- data/src/java/arjdbc/jdbc/RubyConnectionFactory.java +0 -61
- data/src/java/arjdbc/postgresql/PgDateTimeUtils.java +0 -52
@@ -27,6 +27,7 @@ package arjdbc.postgresql;
|
|
27
27
|
|
28
28
|
import arjdbc.jdbc.Callable;
|
29
29
|
import arjdbc.jdbc.DriverWrapper;
|
30
|
+
import arjdbc.postgresql.PostgreSQLResult;
|
30
31
|
import arjdbc.util.DateTimeUtils;
|
31
32
|
import arjdbc.util.StringHelper;
|
32
33
|
|
@@ -54,7 +55,6 @@ import org.joda.time.DateTimeZone;
|
|
54
55
|
import org.jruby.*;
|
55
56
|
import org.jruby.anno.JRubyMethod;
|
56
57
|
import org.jruby.exceptions.RaiseException;
|
57
|
-
import org.jruby.ext.bigdecimal.RubyBigDecimal;
|
58
58
|
import org.jruby.javasupport.JavaUtil;
|
59
59
|
import org.jruby.runtime.ObjectAllocator;
|
60
60
|
import org.jruby.runtime.ThreadContext;
|
@@ -100,7 +100,6 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
100
100
|
POSTGRES_JDBC_TYPE_FOR.put("line", Types.OTHER);
|
101
101
|
POSTGRES_JDBC_TYPE_FOR.put("lseg", Types.OTHER);
|
102
102
|
POSTGRES_JDBC_TYPE_FOR.put("ltree", Types.OTHER);
|
103
|
-
POSTGRES_JDBC_TYPE_FOR.put("money", Types.OTHER);
|
104
103
|
POSTGRES_JDBC_TYPE_FOR.put("numrange", Types.OTHER);
|
105
104
|
POSTGRES_JDBC_TYPE_FOR.put("path", Types.OTHER);
|
106
105
|
POSTGRES_JDBC_TYPE_FOR.put("point", Types.OTHER);
|
@@ -281,30 +280,6 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
281
280
|
return mapExecuteResult(context, connection, resultSet).toARResult(context);
|
282
281
|
}
|
283
282
|
|
284
|
-
@Override
|
285
|
-
protected void setArrayParameter(final ThreadContext context,
|
286
|
-
final Connection connection, final PreparedStatement statement,
|
287
|
-
final int index, final IRubyObject value,
|
288
|
-
final IRubyObject attribute, final int type) throws SQLException {
|
289
|
-
|
290
|
-
final String typeName = resolveArrayBaseTypeName(context, attribute);
|
291
|
-
final RubyArray valueForDB = (RubyArray) value.callMethod(context, "values");
|
292
|
-
|
293
|
-
Object[] values;
|
294
|
-
switch (typeName) {
|
295
|
-
case "datetime":
|
296
|
-
case "timestamp": {
|
297
|
-
values = PgDateTimeUtils.timestampStringArray(context, valueForDB);
|
298
|
-
break;
|
299
|
-
}
|
300
|
-
default:
|
301
|
-
values = valueForDB.toArray();
|
302
|
-
break;
|
303
|
-
}
|
304
|
-
|
305
|
-
statement.setArray(index, connection.createArrayOf(typeName, values));
|
306
|
-
}
|
307
|
-
|
308
283
|
@Override
|
309
284
|
protected void setBlobParameter(final ThreadContext context,
|
310
285
|
final Connection connection, final PreparedStatement statement,
|
@@ -328,9 +303,47 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
328
303
|
final Connection connection, final PreparedStatement statement,
|
329
304
|
final int index, IRubyObject value,
|
330
305
|
final IRubyObject attribute, final int type) throws SQLException {
|
331
|
-
|
332
|
-
|
333
|
-
|
306
|
+
|
307
|
+
if ( value instanceof RubyFloat ) {
|
308
|
+
final double doubleValue = ( (RubyFloat) value ).getValue();
|
309
|
+
if ( Double.isInfinite(doubleValue) ) {
|
310
|
+
setTimestampInfinity(statement, index, doubleValue);
|
311
|
+
return;
|
312
|
+
}
|
313
|
+
}
|
314
|
+
|
315
|
+
RubyTime timeValue = toTime(context, value);
|
316
|
+
|
317
|
+
final Timestamp timestamp;
|
318
|
+
|
319
|
+
if (timeValue.getDateTime().getYear() > 0) {
|
320
|
+
timeValue = timeInDefaultTimeZone(context, timeValue);
|
321
|
+
DateTime dateTime = timeValue.getDateTime();
|
322
|
+
timestamp = new Timestamp(dateTime.getMillis());
|
323
|
+
|
324
|
+
if (timeValue.getNSec() > 0) timestamp.setNanos((int) (timestamp.getNanos() + timeValue.getNSec()));
|
325
|
+
|
326
|
+
statement.setTimestamp(index, timestamp, getCalendar(dateTime.getZone()));
|
327
|
+
}
|
328
|
+
else {
|
329
|
+
setTimestampBC(statement, index, timeValue);
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
private static void setTimestampBC(final PreparedStatement statement,
|
334
|
+
final int index, final RubyTime timeValue) throws SQLException {
|
335
|
+
DateTime dateTime = timeValue.getDateTime();
|
336
|
+
@SuppressWarnings("deprecated")
|
337
|
+
Timestamp timestamp = new Timestamp(dateTime.getYear() - 1900,
|
338
|
+
dateTime.getMonthOfYear() - 1,
|
339
|
+
dateTime.getDayOfMonth(),
|
340
|
+
dateTime.getHourOfDay(),
|
341
|
+
dateTime.getMinuteOfHour(),
|
342
|
+
dateTime.getSecondOfMinute(),
|
343
|
+
dateTime.getMillisOfSecond() * 1_000_000 + (int) timeValue.getNSec()
|
344
|
+
);
|
345
|
+
|
346
|
+
statement.setObject(index, timestamp);
|
334
347
|
}
|
335
348
|
|
336
349
|
private static void setTimestampInfinity(final PreparedStatement statement,
|
@@ -352,8 +365,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
352
365
|
final int index, IRubyObject value,
|
353
366
|
final IRubyObject attribute, final int type) throws SQLException {
|
354
367
|
// to handle more fractional second precision than (default) 59.123 only
|
355
|
-
|
356
|
-
statement.setObject(index, timeStr, Types.OTHER);
|
368
|
+
super.setTimestampParameter(context, connection, statement, index, value, attribute, type);
|
357
369
|
}
|
358
370
|
|
359
371
|
@Override
|
@@ -407,7 +419,8 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
407
419
|
break;
|
408
420
|
|
409
421
|
case "enum":
|
410
|
-
|
422
|
+
// FIXME: This doesn't work but it gives a better error message than letting it be treated as a PGobject
|
423
|
+
statement.setObject(index, value.toString());
|
411
424
|
break;
|
412
425
|
|
413
426
|
case "interval":
|
@@ -428,14 +441,6 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
428
441
|
}
|
429
442
|
break;
|
430
443
|
|
431
|
-
case "money":
|
432
|
-
if (value instanceof RubyBigDecimal) {
|
433
|
-
statement.setBigDecimal(index, ((RubyBigDecimal) value).getValue());
|
434
|
-
} else {
|
435
|
-
setPGobjectParameter(statement, index, value, columnType);
|
436
|
-
}
|
437
|
-
break;
|
438
|
-
|
439
444
|
case "lseg":
|
440
445
|
pointValues = parseDoubles(value);
|
441
446
|
statement.setObject(index, new PGlseg(pointValues[0], pointValues[1], pointValues[2], pointValues[3]));
|
@@ -480,7 +485,7 @@ public class PostgreSQLRubyJdbcConnection extends arjdbc.jdbc.RubyJdbcConnection
|
|
480
485
|
return points;
|
481
486
|
}
|
482
487
|
|
483
|
-
private
|
488
|
+
private Double[] parseDoubles(IRubyObject value) {
|
484
489
|
Matcher matches = doubleValuePattern.matcher(value.toString());
|
485
490
|
ArrayList<Double> doubles = new ArrayList<Double>(4); // Paths and polygons may be larger but this covers points/circles/boxes/line segments
|
486
491
|
|
@@ -28,10 +28,8 @@ import java.sql.Time;
|
|
28
28
|
import java.sql.Timestamp;
|
29
29
|
import java.util.TimeZone;
|
30
30
|
|
31
|
-
import org.joda.time.Chronology;
|
32
31
|
import org.joda.time.DateTime;
|
33
32
|
import org.joda.time.DateTimeZone;
|
34
|
-
import org.joda.time.chrono.GJChronology;
|
35
33
|
import org.joda.time.chrono.ISOChronology;
|
36
34
|
import org.jruby.Ruby;
|
37
35
|
import org.jruby.RubyFloat;
|
@@ -42,7 +40,6 @@ import org.jruby.runtime.Block;
|
|
42
40
|
import org.jruby.runtime.ThreadContext;
|
43
41
|
import org.jruby.runtime.builtin.IRubyObject;
|
44
42
|
import org.jruby.util.ByteList;
|
45
|
-
import org.jruby.util.TypeConverter;
|
46
43
|
|
47
44
|
import static arjdbc.util.StringHelper.decByte;
|
48
45
|
|
@@ -52,20 +49,6 @@ import static arjdbc.util.StringHelper.decByte;
|
|
52
49
|
*/
|
53
50
|
public abstract class DateTimeUtils {
|
54
51
|
|
55
|
-
private static final GJChronology CHRONO_ITALY_UTC = GJChronology.getInstance(DateTimeZone.UTC);
|
56
|
-
|
57
|
-
public static RubyTime toTime(final ThreadContext context, final IRubyObject value) {
|
58
|
-
if (!(value instanceof RubyTime)) { // unlikely
|
59
|
-
return (RubyTime) TypeConverter.convertToTypeWithCheck(value, context.runtime.getTime(), "to_time");
|
60
|
-
}
|
61
|
-
return (RubyTime) value;
|
62
|
-
}
|
63
|
-
|
64
|
-
public static DateTime dateTimeInZone(final DateTime dateTime, final DateTimeZone zone) {
|
65
|
-
if (zone == dateTime.getZone()) return dateTime;
|
66
|
-
return dateTime.withZone(zone);
|
67
|
-
}
|
68
|
-
|
69
52
|
@SuppressWarnings("deprecation")
|
70
53
|
public static ByteList timeToString(final Time time) {
|
71
54
|
final ByteList str = new ByteList(8); // hh:mm:ss
|
@@ -221,11 +204,9 @@ public abstract class DateTimeUtils {
|
|
221
204
|
final int hours = time.getHours();
|
222
205
|
final int minutes = time.getMinutes();
|
223
206
|
final int seconds = time.getSeconds();
|
224
|
-
int nanos = time.getNanos(); // max 999-999-999
|
225
|
-
final int millis = nanos / 1000000;
|
226
|
-
nanos = nanos % 1000000;
|
207
|
+
final int nanos = time.getNanos(); // max 999-999-999
|
227
208
|
|
228
|
-
DateTime dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds,
|
209
|
+
DateTime dateTime = new DateTime(2000, 1, 1, hours, minutes, seconds, defaultZone);
|
229
210
|
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
230
211
|
}
|
231
212
|
|
@@ -238,11 +219,9 @@ public abstract class DateTimeUtils {
|
|
238
219
|
final int hours = timestamp.getHours();
|
239
220
|
final int minutes = timestamp.getMinutes();
|
240
221
|
final int seconds = timestamp.getSeconds();
|
241
|
-
int nanos = timestamp.getNanos(); // max 999-999-999
|
242
|
-
final int millis = nanos / 1000000;
|
243
|
-
nanos = nanos % 1000000;
|
222
|
+
final int nanos = timestamp.getNanos(); // max 999-999-999
|
244
223
|
|
245
|
-
DateTime dateTime = new DateTime(year, month, day, hours, minutes, seconds,
|
224
|
+
DateTime dateTime = new DateTime(year, month, day, hours, minutes, seconds, 0, defaultZone);
|
246
225
|
return RubyTime.newTime(context.runtime, dateTime, nanos);
|
247
226
|
}
|
248
227
|
|
@@ -267,15 +246,6 @@ public abstract class DateTimeUtils {
|
|
267
246
|
return newDate(context, year, month, day, ISOChronology.getInstance(zone));
|
268
247
|
}
|
269
248
|
|
270
|
-
@SuppressWarnings("deprecation")
|
271
|
-
public static IRubyObject newDate(final ThreadContext context, final Date date) {
|
272
|
-
final int year = date.getYear() + 1900;
|
273
|
-
final int month = date.getMonth() + 1;
|
274
|
-
final int day = date.getDate();
|
275
|
-
|
276
|
-
return newDate(context, year, month, day, CHRONO_ITALY_UTC);
|
277
|
-
}
|
278
|
-
|
279
249
|
// @Deprecated
|
280
250
|
public static Timestamp convertToTimestamp(final RubyFloat value) {
|
281
251
|
final Timestamp timestamp = new Timestamp(value.getLongValue() * 1000); // millis
|
@@ -570,7 +540,7 @@ public abstract class DateTimeUtils {
|
|
570
540
|
}
|
571
541
|
|
572
542
|
private static IRubyObject newDate(final ThreadContext context, final int year, final int month, final int day,
|
573
|
-
final
|
543
|
+
final ISOChronology chronology) {
|
574
544
|
// NOTE: JRuby really needs a native date.rb until than its a bit costly going from ...
|
575
545
|
// java.sql.Date -> allocating a DateTime proxy, help a bit by shooting at the internals
|
576
546
|
//
|
@@ -607,110 +577,4 @@ public abstract class DateTimeUtils {
|
|
607
577
|
return n;
|
608
578
|
}
|
609
579
|
|
610
|
-
|
611
|
-
private static final char[] ZEROS = {'0', '0', '0', '0', '0', '0'};
|
612
|
-
private static final char[][] NUMBERS;
|
613
|
-
|
614
|
-
static {
|
615
|
-
// maximum value is 60 (seconds)
|
616
|
-
NUMBERS = new char[60][];
|
617
|
-
for (int i = 0; i < NUMBERS.length; i++) {
|
618
|
-
NUMBERS[i] = ((i < 10 ? "0" : "") + Integer.toString(i)).toCharArray();
|
619
|
-
}
|
620
|
-
}
|
621
|
-
|
622
|
-
/**
|
623
|
-
* Converts a ruby timestamp to a java string, optionally with timezone and timezone adjustment
|
624
|
-
* @param context
|
625
|
-
* @param value the ruby value, typically a Time
|
626
|
-
* @param zone DateTimeZone to adjust to, optional
|
627
|
-
* @param withZone include timezone in the string?
|
628
|
-
* @return timestamp as string
|
629
|
-
*/
|
630
|
-
public static String timestampTimeToString(final ThreadContext context,
|
631
|
-
final IRubyObject value, DateTimeZone zone, boolean withZone) {
|
632
|
-
RubyTime timeValue = toTime(context, value);
|
633
|
-
DateTime dt = timeValue.getDateTime();
|
634
|
-
|
635
|
-
StringBuilder sb = new StringBuilder(36);
|
636
|
-
|
637
|
-
int year = dt.getYear();
|
638
|
-
if (year <= 0) {
|
639
|
-
year--;
|
640
|
-
} else if (zone != null) {
|
641
|
-
dt = dateTimeInZone(dt, zone);
|
642
|
-
year = dt.getYear();
|
643
|
-
}
|
644
|
-
|
645
|
-
Chronology chrono = dt.getChronology();
|
646
|
-
long millis = dt.getMillis();
|
647
|
-
|
648
|
-
// always use 4 digits for year to avoid short dates being misinterpreted
|
649
|
-
sb.append(Math.abs(year));
|
650
|
-
int lead = 4 - sb.length();
|
651
|
-
if (lead > 0) sb.insert(0, ZEROS, 0, lead);
|
652
|
-
sb.append('-');
|
653
|
-
sb.append(NUMBERS[chrono.monthOfYear().get(millis)]);
|
654
|
-
sb.append('-');
|
655
|
-
sb.append(NUMBERS[chrono.dayOfMonth().get(millis)]);
|
656
|
-
if (year < 0) sb.append(" BC");
|
657
|
-
sb.append(' ');
|
658
|
-
|
659
|
-
appendTime(sb, chrono, millis, (int) timeValue.getUSec(), withZone);
|
660
|
-
|
661
|
-
return sb.toString();
|
662
|
-
}
|
663
|
-
|
664
|
-
/**
|
665
|
-
* Converts a ruby time to a java string, optionally with timezone and timezone adjustment
|
666
|
-
* @param context
|
667
|
-
* @param value the ruby value, typically a Time
|
668
|
-
* @param zone DateTimeZone to adjust to, optional
|
669
|
-
* @param withZone include timezone in the string?
|
670
|
-
* @return time as string
|
671
|
-
*/
|
672
|
-
public static String timeString(final ThreadContext context,
|
673
|
-
final IRubyObject value, DateTimeZone zone, boolean withZone) {
|
674
|
-
StringBuilder sb = new StringBuilder(21);
|
675
|
-
RubyTime timeValue = toTime(context, value);
|
676
|
-
DateTime dt = timeValue.getDateTime();
|
677
|
-
if (zone != null) dt = dateTimeInZone(dt, zone);
|
678
|
-
|
679
|
-
appendTime(sb, dt.getChronology(), dt.getMillis(), (int) timeValue.getUSec(), withZone);
|
680
|
-
return sb.toString();
|
681
|
-
}
|
682
|
-
|
683
|
-
private static void appendTime(StringBuilder sb, Chronology chrono,
|
684
|
-
long millis, int usec, boolean withZone) {
|
685
|
-
sb.append(NUMBERS[chrono.hourOfDay().get(millis)]);
|
686
|
-
sb.append(':');
|
687
|
-
sb.append(NUMBERS[chrono.minuteOfHour().get(millis)]);
|
688
|
-
sb.append(':');
|
689
|
-
sb.append(NUMBERS[chrono.secondOfMinute().get(millis)]);
|
690
|
-
|
691
|
-
// PG has microsecond resolution. Change when nanos are required
|
692
|
-
int micros = chrono.millisOfSecond().get(millis) * 1000 + usec;
|
693
|
-
if (micros > 0) {
|
694
|
-
sb.append('.');
|
695
|
-
|
696
|
-
int len = sb.length();
|
697
|
-
sb.append(micros);
|
698
|
-
int lead = 6 - (sb.length() - len);
|
699
|
-
if (lead > 0) sb.insert(len, ZEROS, 0, lead);
|
700
|
-
|
701
|
-
for (int end = sb.length() - 1; sb.charAt(end) == '0'; end--) {
|
702
|
-
sb.setLength(end);
|
703
|
-
}
|
704
|
-
}
|
705
|
-
|
706
|
-
if (withZone) {
|
707
|
-
int offset = chrono.getZone().getOffset(millis) / 1000;
|
708
|
-
int absoff = Math.abs(offset);
|
709
|
-
int hours = absoff / 3600;
|
710
|
-
int mins = (absoff - hours * 3600) / 60;
|
711
|
-
|
712
|
-
sb.append(offset < 0 ? '-' : '+');
|
713
|
-
sb.append(NUMBERS[hours]).append(':').append(NUMBERS[mins]);
|
714
|
-
}
|
715
|
-
}
|
716
580
|
}
|
@@ -52,6 +52,7 @@ public abstract class QuotingUtils {
|
|
52
52
|
return quoteCharWith(context, string, value, quote, 0, 8);
|
53
53
|
}
|
54
54
|
|
55
|
+
@SuppressWarnings("deprecation")
|
55
56
|
public static RubyString quoteCharWith(
|
56
57
|
final ThreadContext context,
|
57
58
|
final RubyString string,
|
@@ -71,8 +72,8 @@ public abstract class QuotingUtils {
|
|
71
72
|
new byte[realSize + newOffset + newSizeDiff],
|
72
73
|
stringBytes.getEncoding(), false
|
73
74
|
);
|
74
|
-
quotedBytes.
|
75
|
-
quotedBytes.
|
75
|
+
quotedBytes.begin = newOffset;
|
76
|
+
quotedBytes.realSize = 0;
|
76
77
|
}
|
77
78
|
quotedBytes.append(bytes, appendFrom, i - appendFrom);
|
78
79
|
quotedBytes.append(quote).append(value); // e.g. "'" => "''"
|
@@ -87,6 +88,7 @@ public abstract class QuotingUtils {
|
|
87
88
|
return context.runtime.newString(quotedBytes);
|
88
89
|
}
|
89
90
|
|
91
|
+
@SuppressWarnings("deprecation")
|
90
92
|
public static RubyString quoteCharAndDecorateWith(
|
91
93
|
final ThreadContext context, final RubyString string,
|
92
94
|
final char value, final char quote,
|
@@ -100,7 +102,7 @@ public abstract class QuotingUtils {
|
|
100
102
|
final ByteList quoted = new ByteList(
|
101
103
|
new byte[realSize + 2], string.getEncoding(), false
|
102
104
|
);
|
103
|
-
quoted.
|
105
|
+
quoted.begin = 0; quoted.realSize = 0;
|
104
106
|
quoted.append(prefix);
|
105
107
|
quoted.append(str.unsafeBytes(), str.getBegin(), realSize);
|
106
108
|
quoted.append(suffix);
|
@@ -108,9 +110,8 @@ public abstract class QuotingUtils {
|
|
108
110
|
}
|
109
111
|
// we got a new string with a reserve of 1 byte front and back :
|
110
112
|
final ByteList quoted = quotedString.getByteList();
|
111
|
-
quoted.
|
112
|
-
quoted.
|
113
|
-
quoted.setRealSize(quoted.getRealSize() + 1);
|
113
|
+
quoted.begin = 0; // setBegin invalidates
|
114
|
+
quoted.bytes[0] = prefix; quoted.realSize++;
|
114
115
|
quoted.append(suffix);
|
115
116
|
return quotedString;
|
116
117
|
}
|
@@ -25,9 +25,12 @@ package arjdbc.util;
|
|
25
25
|
|
26
26
|
import java.io.IOException;
|
27
27
|
import java.io.InputStream;
|
28
|
+
import java.nio.charset.Charset;
|
28
29
|
|
29
30
|
import org.jcodings.Encoding;
|
31
|
+
import org.jcodings.specific.UTF8Encoding;
|
30
32
|
import org.jruby.Ruby;
|
33
|
+
import org.jruby.RubyEncoding;
|
31
34
|
import org.jruby.RubyString;
|
32
35
|
import org.jruby.util.ByteList;
|
33
36
|
|
@@ -58,6 +61,18 @@ public abstract class StringHelper {
|
|
58
61
|
return RubyString.newString(runtime, new ByteList(bytes, false));
|
59
62
|
}
|
60
63
|
|
64
|
+
private static final Charset ASCII_CHARSET = Charset.forName("ISO-8859-1");
|
65
|
+
|
66
|
+
public static RubyString newASCIIString(final Ruby runtime, final String str) {
|
67
|
+
final ByteList byteList = new ByteList(str.getBytes(ASCII_CHARSET), false);
|
68
|
+
return RubyString.newString(runtime, byteList);
|
69
|
+
}
|
70
|
+
|
71
|
+
public static RubyString newUTF8String(final Ruby runtime, final byte[] bytes) {
|
72
|
+
final ByteList byteList = new ByteList(bytes, false);
|
73
|
+
return RubyString.newString(runtime, byteList, UTF8Encoding.INSTANCE);
|
74
|
+
}
|
75
|
+
|
61
76
|
public static RubyString newDefaultInternalString(final Ruby runtime, final byte[] bytes) {
|
62
77
|
final ByteList byteList = new ByteList(bytes, false);
|
63
78
|
Encoding enc = runtime.getDefaultInternalEncoding();
|
@@ -68,19 +83,18 @@ public abstract class StringHelper {
|
|
68
83
|
public static RubyString newDefaultInternalString(final Ruby runtime, final CharSequence str) {
|
69
84
|
Encoding enc = runtime.getDefaultInternalEncoding();
|
70
85
|
if (enc == null) enc = runtime.getEncodingService().getJavaDefault();
|
71
|
-
return
|
86
|
+
return RubyString.newString(runtime, new ByteList(RubyEncoding.encode(str, enc.getCharset()), enc));
|
72
87
|
}
|
73
88
|
|
74
|
-
// NOTE: a 'better' RubyString.newInternalFromJavaExternal - to be back-ported in JRuby 9.2
|
75
89
|
public static RubyString newDefaultInternalString(final Ruby runtime, final String str) {
|
76
|
-
|
77
|
-
if (enc == null) enc = runtime.getEncodingService().getJavaDefault();
|
78
|
-
return RubyString.newString(runtime, str, enc);
|
90
|
+
return RubyString.newInternalFromJavaExternal(runtime, str);
|
79
91
|
}
|
80
92
|
|
81
93
|
public static int readBytes(final ByteList output, final InputStream input)
|
82
94
|
throws IOException {
|
83
|
-
|
95
|
+
@SuppressWarnings("deprecation") // capacity :
|
96
|
+
final int buffSize = output.bytes.length - output.begin;
|
97
|
+
return readBytes(output, input, buffSize);
|
84
98
|
}
|
85
99
|
|
86
100
|
public static int readBytes(final ByteList output, final InputStream input, int buffSize)
|