Skip to content

Commit fa546ee

Browse files
committed
[postgres] allow returning string values for (JDBC) arrays with (fixes #510)
... due compatibility with AR < 4.0 (and gems that depend on previous func)
1 parent 28d0acf commit fa546ee

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

lib/arjdbc/postgresql/adapter.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1412,6 +1412,7 @@ def jdbc_column_class
14121412
end
14131413

14141414
if ActiveRecord::VERSION::MAJOR < 4 # Rails 3.x compatibility
1415+
PostgreSQLJdbcConnection.raw_array_type = true if PostgreSQLJdbcConnection.raw_array_type? == nil
14151416
PostgreSQLJdbcConnection.raw_hstore_type = true if PostgreSQLJdbcConnection.raw_hstore_type? == nil
14161417
end
14171418

src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,9 @@ protected IRubyObject timestampToRuby(final ThreadContext context,
458458
protected IRubyObject arrayToRuby(final ThreadContext context,
459459
final Ruby runtime, final ResultSet resultSet, final int column)
460460
throws SQLException {
461+
if ( rawArrayType == Boolean.TRUE ) { // pre AR 4.0 compatibility
462+
return runtime.newString( resultSet.getString(column) );
463+
}
461464
// NOTE: avoid `finally { array.free(); }` on PostgreSQL due :
462465
// java.sql.SQLFeatureNotSupportedException:
463466
// Method org.postgresql.jdbc4.Jdbc4Array.free() is not yet implemented.
@@ -552,6 +555,29 @@ private String formatInterval(final Object object) {
552555
return str.toString();
553556
}
554557

558+
protected static Boolean rawArrayType;
559+
static {
560+
final String arrayRaw = System.getProperty("arjdbc.postgresql.array.raw");
561+
if ( arrayRaw != null ) rawArrayType = Boolean.parseBoolean(arrayRaw);
562+
}
563+
564+
@JRubyMethod(name = "raw_array_type?", meta = true)
565+
public static IRubyObject useRawArrayType(final ThreadContext context, final IRubyObject self) {
566+
if ( rawArrayType == null ) return context.getRuntime().getNil();
567+
return context.getRuntime().newBoolean(rawArrayType);
568+
}
569+
570+
@JRubyMethod(name = "raw_array_type=", meta = true)
571+
public static IRubyObject setRawArrayType(final IRubyObject self, final IRubyObject value) {
572+
if ( value instanceof RubyBoolean ) {
573+
rawArrayType = ((RubyBoolean) value).isTrue() ? Boolean.TRUE : Boolean.FALSE;
574+
}
575+
else {
576+
rawArrayType = value.isNil() ? null : Boolean.TRUE;
577+
}
578+
return value;
579+
}
580+
555581
protected static Boolean rawHstoreType;
556582
static {
557583
final String hstoreRaw = System.getProperty("arjdbc.postgresql.hstore.raw");
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# encoding: utf-8
2+
require 'test_helper'
3+
require 'db/postgres'
4+
5+
class PostgreSQLArrayCompatTest < Test::Unit::TestCase
6+
7+
class PgArray < ActiveRecord::Base
8+
self.table_name = 'pg_arrays'
9+
end
10+
11+
def setup
12+
@connection = ActiveRecord::Base.connection
13+
@connection.execute 'CREATE TABLE "pg_arrays" ("id" serial primary key, "str_2d" character varying(255)[][])'
14+
@connection.execute 'ALTER TABLE "pg_arrays" ADD COLUMN "int_1d" integer[] DEFAULT \'{}\''
15+
@connection.execute 'ALTER TABLE "pg_arrays" ADD COLUMN "bool_1d" boolean[]'
16+
17+
@connection.execute "INSERT INTO \"pg_arrays\"(bool_1d, str_2d, int_1d) " <<
18+
" VALUES ('{f, t, t}', '{{\"a\",\"b\"}, {\"c\",\"d\"}}', '{1, 2, 3}')"
19+
end
20+
21+
def teardown
22+
@connection.execute 'DROP TABLE IF EXISTS pg_arrays'
23+
end
24+
25+
def test_column_types
26+
int_1d_column = PgArray.columns.find { |c| c.name == 'int_1d' }
27+
assert_equal :string, int_1d_column.type
28+
assert_equal 'integer[]', int_1d_column.sql_type
29+
30+
bool_1d_column = PgArray.columns.find { |c| c.name == 'bool_1d' }
31+
assert_equal :string, bool_1d_column.type
32+
assert_equal 'boolean[]', bool_1d_column.sql_type
33+
end
34+
35+
def test_column_values
36+
assert arr = PgArray.first
37+
assert_equal "{{a,b},{c,d}}", arr.str_2d
38+
assert_equal "{1,2,3}", arr.int_1d
39+
assert_equal "{f,t,t}", arr.bool_1d
40+
end
41+
42+
end if ActiveRecord::VERSION::MAJOR < 4

0 commit comments

Comments
 (0)