activerecord-jdbc-adapter 1.3.16 → 1.3.17
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|