activerecord-jdbc-adapter 1.3.16 → 1.3.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/History.md +20 -0
- data/Rakefile +19 -5
- data/lib/arjdbc/jdbc.rb +5 -0
- data/lib/arjdbc/jdbc/adapter.rb +13 -2
- data/lib/arjdbc/jdbc/adapter_java.jar +0 -0
- data/lib/arjdbc/mysql/adapter.rb +74 -15
- data/lib/arjdbc/mysql/bulk_change_table.rb +1 -1
- data/lib/arjdbc/mysql/schema_creation.rb +24 -1
- data/lib/arjdbc/postgresql/adapter.rb +149 -178
- data/lib/arjdbc/postgresql/base/pgconn.rb +8 -0
- data/lib/arjdbc/postgresql/base/schema_definitions.rb +131 -0
- data/lib/arjdbc/postgresql/column.rb +15 -14
- data/lib/arjdbc/postgresql/oid_types.rb +23 -10
- data/lib/arjdbc/postgresql/schema_creation.rb +21 -3
- data/lib/arjdbc/version.rb +1 -1
- data/rakelib/db.rake +1 -1
- data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +47 -7
- metadata +4 -2
@@ -0,0 +1,8 @@
|
|
1
|
+
module ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
2
|
+
class PGconn # emulate PGconn#unescape_bytea due #652
|
3
|
+
# NOTE: on pg gem ... PGconn = (class) PG::Connection
|
4
|
+
def self.unescape_bytea(escaped)
|
5
|
+
ArJdbc::PostgreSQL.unescape_bytea(escaped)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
end
|
@@ -0,0 +1,131 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module ConnectionAdapters
|
3
|
+
module PostgreSQL
|
4
|
+
class ColumnDefinition < ActiveRecord::ConnectionAdapters::ColumnDefinition
|
5
|
+
attr_accessor :array
|
6
|
+
def array?; !!@array; end
|
7
|
+
end
|
8
|
+
|
9
|
+
module ColumnMethods
|
10
|
+
def xml(*args)
|
11
|
+
options = args.extract_options!
|
12
|
+
column(args[0], 'xml', options)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tsvector(*args)
|
16
|
+
options = args.extract_options!
|
17
|
+
column(args[0], 'tsvector', options)
|
18
|
+
end
|
19
|
+
|
20
|
+
def int4range(name, options = {})
|
21
|
+
column(name, 'int4range', options)
|
22
|
+
end
|
23
|
+
|
24
|
+
def int8range(name, options = {})
|
25
|
+
column(name, 'int8range', options)
|
26
|
+
end
|
27
|
+
|
28
|
+
def tsrange(name, options = {})
|
29
|
+
column(name, 'tsrange', options)
|
30
|
+
end
|
31
|
+
|
32
|
+
def tstzrange(name, options = {})
|
33
|
+
column(name, 'tstzrange', options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def numrange(name, options = {})
|
37
|
+
column(name, 'numrange', options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def daterange(name, options = {})
|
41
|
+
column(name, 'daterange', options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def hstore(name, options = {})
|
45
|
+
column(name, 'hstore', options)
|
46
|
+
end
|
47
|
+
|
48
|
+
def ltree(name, options = {})
|
49
|
+
column(name, 'ltree', options)
|
50
|
+
end
|
51
|
+
|
52
|
+
def inet(name, options = {})
|
53
|
+
column(name, 'inet', options)
|
54
|
+
end
|
55
|
+
|
56
|
+
def cidr(name, options = {})
|
57
|
+
column(name, 'cidr', options)
|
58
|
+
end
|
59
|
+
|
60
|
+
def macaddr(name, options = {})
|
61
|
+
column(name, 'macaddr', options)
|
62
|
+
end
|
63
|
+
|
64
|
+
def uuid(name, options = {})
|
65
|
+
column(name, 'uuid', options)
|
66
|
+
end
|
67
|
+
|
68
|
+
def json(name, options = {})
|
69
|
+
column(name, 'json', options)
|
70
|
+
end
|
71
|
+
|
72
|
+
def jsonb(name, options = {})
|
73
|
+
column(name, :jsonb, options)
|
74
|
+
end
|
75
|
+
|
76
|
+
def bit(name, options)
|
77
|
+
column(name, 'bit', options)
|
78
|
+
end
|
79
|
+
|
80
|
+
def bit_varying(name, options)
|
81
|
+
column(name, 'bit varying', options)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition
|
86
|
+
include ColumnMethods
|
87
|
+
|
88
|
+
def primary_key(name, type = :primary_key, options = {})
|
89
|
+
return super unless type == :uuid
|
90
|
+
options[:default] = options.fetch(:default, 'uuid_generate_v4()')
|
91
|
+
options[:primary_key] = true
|
92
|
+
column name, type, options
|
93
|
+
end if ::ActiveRecord::VERSION::MAJOR > 3 # 3.2 super expects (name)
|
94
|
+
|
95
|
+
def column(name, type = nil, options = {})
|
96
|
+
super
|
97
|
+
column = self[name]
|
98
|
+
# NOTE: <= 3.1 no #new_column_definition hard-coded ColumnDef.new :
|
99
|
+
# column = self[name] || ColumnDefinition.new(@base, name, type)
|
100
|
+
# thus we simply do not support array column definitions on <= 3.1
|
101
|
+
column.array = options[:array] if column.is_a?(ColumnDefinition)
|
102
|
+
self
|
103
|
+
end
|
104
|
+
|
105
|
+
private
|
106
|
+
|
107
|
+
if ::ActiveRecord::VERSION::MAJOR > 3
|
108
|
+
|
109
|
+
def create_column_definition(name, type)
|
110
|
+
ColumnDefinition.new name, type
|
111
|
+
end
|
112
|
+
|
113
|
+
else # no #create_column_definition on 3.2
|
114
|
+
|
115
|
+
def new_column_definition(base, name, type)
|
116
|
+
definition = ColumnDefinition.new base, name, type
|
117
|
+
@columns << definition
|
118
|
+
@columns_hash[name] = definition
|
119
|
+
definition
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
class Table < ActiveRecord::ConnectionAdapters::Table
|
127
|
+
include ColumnMethods
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
end
|
@@ -52,6 +52,7 @@ module ArJdbc
|
|
52
52
|
module Column
|
53
53
|
|
54
54
|
attr_accessor :array
|
55
|
+
alias array? array
|
55
56
|
|
56
57
|
def initialize(name, default, cast_type, sql_type = nil, null = true, default_function = nil,
|
57
58
|
oid = nil, adapter = nil) # added arguments
|
@@ -69,7 +70,7 @@ module ArJdbc
|
|
69
70
|
@default_function = default_function
|
70
71
|
end
|
71
72
|
|
72
|
-
end if
|
73
|
+
end if AR42
|
73
74
|
|
74
75
|
# @private (AR < 4.2 version) documented above
|
75
76
|
module Column
|
@@ -83,7 +84,7 @@ module ArJdbc
|
|
83
84
|
else # NOTE: AR <= 3.2 : (name, default, sql_type = nil, null = true)
|
84
85
|
null, sql_type, oid_type = !! sql_type, oid_type, nil
|
85
86
|
end
|
86
|
-
if sql_type.to_s[-2, 2] == '[]' &&
|
87
|
+
if sql_type.to_s[-2, 2] == '[]' && AR40
|
87
88
|
@array = true if respond_to?(:array)
|
88
89
|
super(name, default, sql_type[0..-3], null)
|
89
90
|
else
|
@@ -107,20 +108,20 @@ module ArJdbc
|
|
107
108
|
require 'pg_array_parser'
|
108
109
|
base_meta.send :include, PgArrayParser
|
109
110
|
rescue LoadError
|
110
|
-
if
|
111
|
+
if AR42
|
111
112
|
require 'active_record/connection_adapters/postgresql/array_parser'
|
112
113
|
else
|
113
114
|
require 'arjdbc/postgresql/base/array_parser'
|
114
115
|
end
|
115
116
|
base_meta.send :include, ActiveRecord::ConnectionAdapters::PostgreSQL::ArrayParser
|
116
|
-
end if
|
117
|
+
end if AR40
|
117
118
|
|
118
119
|
base_meta.send :include, Cast
|
119
120
|
|
120
121
|
base.send :include, ColumnHelpers
|
121
122
|
end
|
122
123
|
|
123
|
-
if
|
124
|
+
if AR40 && ! AR42
|
124
125
|
|
125
126
|
# @private
|
126
127
|
def oid_type
|
@@ -135,10 +136,10 @@ module ArJdbc
|
|
135
136
|
|
136
137
|
end
|
137
138
|
|
138
|
-
( attr_accessor :array; def array?; array; end ) if
|
139
|
+
( attr_accessor :array; def array?; array; end ) if AR40
|
139
140
|
|
140
|
-
def number?; !array && super end if
|
141
|
-
def text?; !array && super end if
|
141
|
+
def number?; !array && super end if AR40
|
142
|
+
def text?; !array && super end if AR40
|
142
143
|
|
143
144
|
# Extracts the value from a PostgreSQL column default definition.
|
144
145
|
#
|
@@ -286,7 +287,7 @@ module ArJdbc
|
|
286
287
|
super(value)
|
287
288
|
end
|
288
289
|
end
|
289
|
-
end if
|
290
|
+
end if AR40
|
290
291
|
|
291
292
|
private
|
292
293
|
|
@@ -398,7 +399,7 @@ module ArJdbc
|
|
398
399
|
else
|
399
400
|
super
|
400
401
|
end
|
401
|
-
end if
|
402
|
+
end if AR40
|
402
403
|
|
403
404
|
# OID Type::Range helpers :
|
404
405
|
|
@@ -409,11 +410,11 @@ module ArJdbc
|
|
409
410
|
:to => (value[-2] == ',' || t == 'infinity') ? infinity : t,
|
410
411
|
:exclude_start => (value[0] == '('), :exclude_end => (value[-1] == ')')
|
411
412
|
}
|
412
|
-
end if
|
413
|
+
end if AR40
|
413
414
|
|
414
415
|
def infinity(options = {})
|
415
416
|
::Float::INFINITY * (options[:negative] ? -1 : 1)
|
416
|
-
end if
|
417
|
+
end if AR40
|
417
418
|
|
418
419
|
private
|
419
420
|
|
@@ -495,7 +496,7 @@ module ArJdbc
|
|
495
496
|
else
|
496
497
|
value # Bit-string notation
|
497
498
|
end
|
498
|
-
end if
|
499
|
+
end if AR40
|
499
500
|
|
500
501
|
def hstore_to_string(object, array_member = false)
|
501
502
|
if Hash === object
|
@@ -634,6 +635,6 @@ module ArJdbc
|
|
634
635
|
|
635
636
|
end
|
636
637
|
|
637
|
-
end unless
|
638
|
+
end unless AR42
|
638
639
|
end
|
639
640
|
end
|
@@ -3,12 +3,18 @@ require 'thread'
|
|
3
3
|
module ArJdbc
|
4
4
|
module PostgreSQL
|
5
5
|
|
6
|
-
if
|
6
|
+
if AR42
|
7
7
|
require 'active_record/connection_adapters/postgresql/oid'
|
8
8
|
else
|
9
9
|
require 'arjdbc/postgresql/base/oid'
|
10
10
|
end
|
11
11
|
|
12
|
+
require 'arjdbc/postgresql/base/pgconn'
|
13
|
+
|
14
|
+
def self.unescape_bytea(escaped)
|
15
|
+
String.from_java_bytes Java::OrgPostgresqlUtil::PGbytea.toBytes escaped.to_java_bytes
|
16
|
+
end
|
17
|
+
|
12
18
|
# @private
|
13
19
|
OID = ::ActiveRecord::ConnectionAdapters::PostgreSQL::OID
|
14
20
|
|
@@ -36,12 +42,18 @@ module ArJdbc
|
|
36
42
|
@extensions ||= super
|
37
43
|
end
|
38
44
|
|
45
|
+
# @override
|
46
|
+
def lookup_cast_type(sql_type)
|
47
|
+
oid = execute("SELECT #{quote(sql_type)}::regtype::oid", "SCHEMA")
|
48
|
+
super oid.first['oid'].to_i
|
49
|
+
end if AR42
|
50
|
+
|
39
51
|
def get_oid_type(oid, fmod, column_name)
|
40
52
|
type_map.fetch(oid, fmod) {
|
41
53
|
warn "unknown OID #{oid}: failed to recognize type of '#{column_name}'. It will be treated as String."
|
42
54
|
type_map[oid] = OID::Identity.new
|
43
55
|
}
|
44
|
-
end unless
|
56
|
+
end unless AR42
|
45
57
|
|
46
58
|
def get_oid_type(oid, fmod, column_name, sql_type = '')
|
47
59
|
if !type_map.key?(oid)
|
@@ -54,14 +66,12 @@ module ArJdbc
|
|
54
66
|
type_map.register_type(oid, cast_type)
|
55
67
|
end
|
56
68
|
}
|
57
|
-
end if
|
58
|
-
|
59
|
-
private
|
69
|
+
end if AR42
|
60
70
|
|
61
71
|
@@type_map_cache = {}
|
62
72
|
@@type_map_cache_lock = Mutex.new
|
63
73
|
|
64
|
-
if
|
74
|
+
if AR42
|
65
75
|
TypeMap = ActiveRecord::Type::HashLookupTypeMap
|
66
76
|
else
|
67
77
|
TypeMap = OID::TypeMap
|
@@ -99,6 +109,8 @@ module ArJdbc
|
|
99
109
|
end
|
100
110
|
end
|
101
111
|
|
112
|
+
private
|
113
|
+
|
102
114
|
def cache_type_map(type_map)
|
103
115
|
@@type_map_cache_lock.synchronize do
|
104
116
|
@@type_map_cache[ type_cache_key ] = type_map
|
@@ -148,7 +160,7 @@ module ArJdbc
|
|
148
160
|
array = OID::Array.new type_map[ row['typelem'].to_i ]
|
149
161
|
type_map[ row['oid'].to_i ] = array
|
150
162
|
end
|
151
|
-
end unless
|
163
|
+
end unless AR42
|
152
164
|
|
153
165
|
def initialize_type_map(m)
|
154
166
|
register_class_with_limit m, 'int2', OID::Integer
|
@@ -219,7 +231,7 @@ module ArJdbc
|
|
219
231
|
end
|
220
232
|
|
221
233
|
load_additional_types(m)
|
222
|
-
end if
|
234
|
+
end if AR42
|
223
235
|
|
224
236
|
def load_additional_types(type_map, oids = nil)
|
225
237
|
if supports_ranges?
|
@@ -238,8 +250,9 @@ module ArJdbc
|
|
238
250
|
initializer = OID::TypeMapInitializer.new(type_map)
|
239
251
|
|
240
252
|
if oids
|
241
|
-
query << "WHERE t.oid::integer IN (%s)" % oids.join(", ")
|
253
|
+
query << ( "WHERE t.oid::integer IN (%s)" % oids.join(", ") )
|
242
254
|
else
|
255
|
+
# query_conditions_for_initial_load only available since AR > 4.2.1
|
243
256
|
if initializer.respond_to?(:query_conditions_for_initial_load)
|
244
257
|
query << initializer.query_conditions_for_initial_load(type_map)
|
245
258
|
end
|
@@ -247,7 +260,7 @@ module ArJdbc
|
|
247
260
|
|
248
261
|
records = execute(query, 'SCHEMA')
|
249
262
|
initializer.run(records)
|
250
|
-
end if
|
263
|
+
end if AR42
|
251
264
|
|
252
265
|
end
|
253
266
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module ArJdbc
|
2
2
|
module PostgreSQL
|
3
|
-
# @private copied from native adapter 4.0/4.1
|
3
|
+
# @private copied (and adjusted) from native adapter 4.0/4.1/4.2
|
4
4
|
class SchemaCreation < ::ActiveRecord::ConnectionAdapters::AbstractAdapter::SchemaCreation
|
5
5
|
|
6
6
|
private
|
@@ -9,7 +9,7 @@ module ArJdbc
|
|
9
9
|
sql_type = type_to_sql(o.type.to_sym, o.limit, o.precision, o.scale)
|
10
10
|
sql = "ADD COLUMN #{quote_column_name(o.name)} #{sql_type}"
|
11
11
|
add_column_options!(sql, column_options(o))
|
12
|
-
end
|
12
|
+
end unless AR42
|
13
13
|
|
14
14
|
def visit_ColumnDefinition(o)
|
15
15
|
sql = super
|
@@ -18,7 +18,16 @@ module ArJdbc
|
|
18
18
|
add_column_options!(sql, column_options(o))
|
19
19
|
end
|
20
20
|
sql
|
21
|
-
end
|
21
|
+
end unless AR42
|
22
|
+
|
23
|
+
def visit_ColumnDefinition(o)
|
24
|
+
sql = super
|
25
|
+
if o.primary_key? && o.type != :primary_key
|
26
|
+
sql << " PRIMARY KEY "
|
27
|
+
add_column_options!(sql, column_options(o))
|
28
|
+
end
|
29
|
+
sql
|
30
|
+
end if AR42
|
22
31
|
|
23
32
|
def add_column_options!(sql, options)
|
24
33
|
if options[:array] || options[:column].try(:array)
|
@@ -32,6 +41,15 @@ module ArJdbc
|
|
32
41
|
super
|
33
42
|
end
|
34
43
|
end
|
44
|
+
|
45
|
+
def type_for_column(column)
|
46
|
+
if column.array
|
47
|
+
@conn.lookup_cast_type("#{column.sql_type}[]")
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end if AR42
|
52
|
+
|
35
53
|
end
|
36
54
|
|
37
55
|
def schema_creation
|
data/lib/arjdbc/version.rb
CHANGED
data/rakelib/db.rake
CHANGED
@@ -481,7 +481,7 @@ public class RubyJdbcConnection extends RubyObject {
|
|
481
481
|
return getInstanceVariable("@connection");
|
482
482
|
}
|
483
483
|
|
484
|
-
@JRubyMethod(name = "active?")
|
484
|
+
@JRubyMethod(name = "active?", alias = "valid?")
|
485
485
|
public IRubyObject active_p(final ThreadContext context) {
|
486
486
|
IRubyObject connection = getInstanceVariable("@connection");
|
487
487
|
if ( connection != null && ! connection.isNil() ) {
|
@@ -529,6 +529,36 @@ public class RubyJdbcConnection extends RubyObject {
|
|
529
529
|
}
|
530
530
|
}
|
531
531
|
|
532
|
+
@JRubyMethod(name = { "open?" /* "conn?" */ })
|
533
|
+
public IRubyObject open_p(final ThreadContext context) {
|
534
|
+
final Connection connection = getConnection(false);
|
535
|
+
if ( connection == null ) return context.getRuntime().getFalse();
|
536
|
+
try {
|
537
|
+
// NOTE: isClosed method generally cannot be called to determine
|
538
|
+
// whether a connection to a database is valid or invalid ...
|
539
|
+
return context.getRuntime().newBoolean( ! connection.isClosed() );
|
540
|
+
}
|
541
|
+
catch (SQLException e) {
|
542
|
+
return handleException(context, e);
|
543
|
+
}
|
544
|
+
}
|
545
|
+
|
546
|
+
@JRubyMethod(name = "close")
|
547
|
+
public IRubyObject close(final ThreadContext context) {
|
548
|
+
final Connection connection = getConnection(false);
|
549
|
+
if ( connection == null ) return context.getRuntime().getFalse();
|
550
|
+
try {
|
551
|
+
final boolean closed = connection.isClosed();
|
552
|
+
if ( closed ) return context.getRuntime().getFalse();
|
553
|
+
setConnection(null); // does connection.close();
|
554
|
+
return context.getRuntime().getTrue();
|
555
|
+
}
|
556
|
+
catch (Exception e) {
|
557
|
+
debugStackTrace(context, e);
|
558
|
+
return context.getRuntime().getNil();
|
559
|
+
}
|
560
|
+
}
|
561
|
+
|
532
562
|
@JRubyMethod(name = "database_name")
|
533
563
|
public IRubyObject database_name(final ThreadContext context) throws SQLException {
|
534
564
|
final Connection connection = getConnection(true);
|
@@ -1032,28 +1062,38 @@ public class RubyJdbcConnection extends RubyObject {
|
|
1032
1062
|
return keyNames;
|
1033
1063
|
}
|
1034
1064
|
|
1035
|
-
@JRubyMethod(name = "tables")
|
1065
|
+
@Deprecated //@JRubyMethod(name = "tables")
|
1036
1066
|
public IRubyObject tables(ThreadContext context) {
|
1037
1067
|
return tables(context, null, null, null, TABLE_TYPE);
|
1038
1068
|
}
|
1039
1069
|
|
1040
|
-
@JRubyMethod(name = "tables")
|
1070
|
+
@Deprecated //@JRubyMethod(name = "tables")
|
1041
1071
|
public IRubyObject tables(ThreadContext context, IRubyObject catalog) {
|
1042
1072
|
return tables(context, toStringOrNull(catalog), null, null, TABLE_TYPE);
|
1043
1073
|
}
|
1044
1074
|
|
1045
|
-
@JRubyMethod(name = "tables")
|
1075
|
+
@Deprecated //@JRubyMethod(name = "tables")
|
1046
1076
|
public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern) {
|
1047
1077
|
return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), null, TABLE_TYPE);
|
1048
1078
|
}
|
1049
1079
|
|
1050
|
-
@JRubyMethod(name = "tables")
|
1080
|
+
@Deprecated //@JRubyMethod(name = "tables")
|
1051
1081
|
public IRubyObject tables(ThreadContext context, IRubyObject catalog, IRubyObject schemaPattern, IRubyObject tablePattern) {
|
1052
1082
|
return tables(context, toStringOrNull(catalog), toStringOrNull(schemaPattern), toStringOrNull(tablePattern), TABLE_TYPE);
|
1053
1083
|
}
|
1054
1084
|
|
1055
|
-
@JRubyMethod(name = "tables", required =
|
1056
|
-
public IRubyObject tables(ThreadContext context, IRubyObject[] args) {
|
1085
|
+
@JRubyMethod(name = "tables", required = 0, optional = 4)
|
1086
|
+
public IRubyObject tables(final ThreadContext context, final IRubyObject[] args) {
|
1087
|
+
switch ( args.length ) {
|
1088
|
+
case 0: // ()
|
1089
|
+
return tables(context, null, null, null, TABLE_TYPE);
|
1090
|
+
case 1: // (catalog)
|
1091
|
+
return tables(context, toStringOrNull(args[0]), null, null, TABLE_TYPE);
|
1092
|
+
case 2: // (catalog, schemaPattern)
|
1093
|
+
return tables(context, toStringOrNull(args[0]), toStringOrNull(args[1]), null, TABLE_TYPE);
|
1094
|
+
case 3: // (catalog, schemaPattern, tablePattern)
|
1095
|
+
return tables(context, toStringOrNull(args[0]), toStringOrNull(args[1]), toStringOrNull(args[2]), TABLE_TYPE);
|
1096
|
+
}
|
1057
1097
|
return tables(context, toStringOrNull(args[0]), toStringOrNull(args[1]), toStringOrNull(args[2]), getTypes(args[3]));
|
1058
1098
|
}
|
1059
1099
|
|