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.
@@ -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 AR42_COMPAT
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] == '[]' && ArJdbc::PostgreSQL::AR4_COMPAT
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 AR42_COMPAT
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 AR4_COMPAT
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 AR4_COMPAT && ! AR42_COMPAT
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 AR4_COMPAT
139
+ ( attr_accessor :array; def array?; array; end ) if AR40
139
140
 
140
- def number?; !array && super end if AR4_COMPAT
141
- def text?; !array && super end if AR4_COMPAT
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 AR4_COMPAT
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 AR4_COMPAT
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 AR4_COMPAT
413
+ end if AR40
413
414
 
414
415
  def infinity(options = {})
415
416
  ::Float::INFINITY * (options[:negative] ? -1 : 1)
416
- end if AR4_COMPAT
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 AR4_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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 AR42_COMPAT
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
@@ -1,5 +1,5 @@
1
1
  module ArJdbc
2
- VERSION = "1.3.16"
2
+ VERSION = "1.3.17"
3
3
  # @deprecated
4
4
  module Version
5
5
  # @private 1.2.x compatibility
@@ -44,7 +44,7 @@ SQL
44
44
  private
45
45
 
46
46
  def sql_script(sql_content, name = 'sql_script')
47
- script = Tempfile.new(name)
47
+ require 'tempfile'; script = Tempfile.new(name)
48
48
  script.puts sql_content
49
49
  yield(script) if block_given?
50
50
  script.close
@@ -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 = 4, rest = true)
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