activerecord-jdbc-adapter 51.2-java → 51.3-java

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: b92cd70cfbcb8827986847b53e1d527f5fcee621
4
- data.tar.gz: 2480d4df7693895d1ca20ac406dadb26f7c432e4
2
+ SHA256:
3
+ metadata.gz: 7117b15f231051ebccb138e4f19e65780e179a751dc44fdb58dd54677af296b6
4
+ data.tar.gz: bad84fbfae38b6d2b30d6bbc09893001c0e2a60ab7137ace692462e257197807
5
5
  SHA512:
6
- metadata.gz: 42f15c16ca5d768f29993be86e43234b832be0fd580625a1d080f9827f405fe9b3a44752cf25970e11a00aeafd3e9d1b20ee715eac15404f042027e5cb8e5643
7
- data.tar.gz: ba4acdb1f07ab847ee0f560c8c9869f72456cfb812e69823b01ad4c0fb62126331401941a015ccd8058e40be7d395f14c418021a14f8f8d9d8eb42befb7ae16f
6
+ metadata.gz: 22e383cc2c136411ce1b70fcb28bb17f83aee13ecffa69bdc5768c53787fc1eb9f8ba566dcc31433a5bfca46788d905222cc4f721c0dc1b83af1fe721a494c91
7
+ data.tar.gz: '084f6078c6887cf33d8c99f9ecf1b2fb907d3e5a1c27ea04058c30773970a295701846d6869e672aff9e8e7141ce29883be763f8b829dbefb36e8ddb562cbd01'
data/.travis.yml CHANGED
@@ -1,9 +1,18 @@
1
1
  language: ruby
2
2
  sudo: false
3
+ branches:
4
+ only:
5
+ - master
6
+ - /.*-stable$/
7
+ - /^test-.*/
8
+ - /maintenance|support/
9
+ - /.*dev$/
3
10
  bundler_args: --without development
4
11
  script: bundle exec rake ${TEST_PREFIX}test_$DB
5
12
  before_install:
6
13
  - unset _JAVA_OPTIONS
14
+ - rvm @default,@global do gem uninstall bundler -a -x -I || true
15
+ - gem install bundler -v "~>1.17.3"
7
16
  before_script:
8
17
  - echo "JAVA_OPTS=$JAVA_OPTS"
9
18
  - export JRUBY_OPTS="-J-Xms64M -J-Xmx1024M"
@@ -33,6 +42,8 @@ rvm:
33
42
  - jruby-9.1.16.0
34
43
  jdk:
35
44
  - openjdk8
45
+ addons:
46
+ postgresql: "9.4"
36
47
  env:
37
48
  - DB=mysql2 PREPARED_STATEMENTS=false
38
49
  - DB=mysql2 PREPARED_STATEMENTS=true
@@ -43,19 +54,29 @@ env:
43
54
  - DB=postgresql PREPARED_STATEMENTS=true INSERT_RETURNING=true
44
55
  - DB=sqlite3 PREPARED_STATEMENTS=false
45
56
  - DB=sqlite3 PREPARED_STATEMENTS=true
46
- #- DB=jndi PREPARED_STATEMENTS=false
47
- #- DB=jndi PREPARED_STATEMENTS=true
48
- branches:
49
- only:
50
- - master
51
- - /.*-stable$/
52
- - /^test-.*/
53
- - /maintenance|support/
54
- - /.*dev$/
57
+ - DB=jndi PREPARED_STATEMENTS=false
58
+ - DB=jndi PREPARED_STATEMENTS=true
55
59
  matrix:
56
60
  allow_failures:
57
61
  - rvm: jruby-head
58
62
  include:
63
+ # jruby-9.2
64
+ - rvm: jruby-9.2.6.0
65
+ env: DB=mysql2
66
+ - rvm: jruby-9.2.6.0
67
+ env: DB=postgresql
68
+ - rvm: jruby-9.2.6.0
69
+ env: DB=sqlite3
70
+ # jruby-9.2 + Java 11
71
+ - rvm: jruby-9.2.6.0
72
+ env: DB=mysql2
73
+ jdk: openjdk11
74
+ - rvm: jruby-9.2.6.0
75
+ env: DB=postgresql
76
+ jdk: openjdk11
77
+ - rvm: jruby-9.2.6.0
78
+ env: DB=sqlite3
79
+ jdk: openjdk11
59
80
  # jruby-head
60
81
  - rvm: jruby-head
61
82
  env: DB=mysql2
@@ -71,9 +92,9 @@ matrix:
71
92
  mariadb: '10.1'
72
93
  env: DB=mariadb PREPARED_STATEMENTS=true
73
94
  # Rails test-suite :
74
- - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.6" # PS off by default
75
- - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.6" PREPARED_STATEMENTS=true
76
- - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.6" DRIVER=MariaDB
77
- - env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="v5.1.6" # PS on by default
78
- - env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="v5.1.6" PREPARED_STATEMENTS=false
79
- - env: DB=sqlite3 TEST_PREFIX="rails:" AR_VERSION="v5.1.6"
95
+ - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.7" # PS off by default
96
+ - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.7" PREPARED_STATEMENTS=true
97
+ - env: DB=mysql2 TEST_PREFIX="rails:" AR_VERSION="v5.1.7" DRIVER=MariaDB
98
+ - env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="v5.1.7" # PS on by default
99
+ - env: DB=postgresql TEST_PREFIX="rails:" AR_VERSION="v5.1.7" PREPARED_STATEMENTS=false
100
+ - env: DB=sqlite3 TEST_PREFIX="rails:" AR_VERSION="v5.1.7"
@@ -26,8 +26,8 @@ module ArJdbc
26
26
  log(sql, name) { @connection.execute_query(sql) }
27
27
  else
28
28
  log(sql, name, binds) do
29
- # It seems that #supports_statement_cache? is defined but isn't checked before setting "prepare" (AR 5.0)
30
- cached_statement = fetch_cached_statement(sql) if prepare && supports_statement_cache?
29
+ # this is different from normal AR that always caches
30
+ cached_statement = fetch_cached_statement(sql) if prepare && @jdbc_statement_cache_enabled
31
31
  @connection.execute_prepared_query(sql, binds, cached_statement)
32
32
  end
33
33
  end
@@ -23,7 +23,7 @@ module ArJdbc
23
23
  # Only say we support the statement cache if we are using prepared statements
24
24
  # and have a max number of statements defined
25
25
  statement_limit = self.class.type_cast_config_to_integer(config[:statement_limit])
26
- @jdbc_statement_cache_enabled = config[:prepared_statements] && (statement_limit.nil? || statement_limit > 0)
26
+ @jdbc_statement_cache_enabled = prepared_statements && (statement_limit.nil? || statement_limit > 0)
27
27
 
28
28
  @statements = StatementPool.new(statement_limit) # AR (5.0) expects this to be stored as @statements
29
29
  end
@@ -34,11 +34,11 @@ module ArJdbc
34
34
  end
35
35
 
36
36
  def delete_cached_statement(sql)
37
- @statements.delete(cached_statement_key(sql))
37
+ @statements.delete(sql_key(sql))
38
38
  end
39
39
 
40
40
  def fetch_cached_statement(sql)
41
- @statements[cached_statement_key(sql)] ||= @connection.connection.prepare_statement(sql)
41
+ @statements[sql_key(sql)] ||= @connection.prepare_statement(sql)
42
42
  end
43
43
 
44
44
  def supports_statement_cache?
@@ -49,7 +49,7 @@ module ArJdbc
49
49
 
50
50
  # This should be overridden by the adapter if the sql itself
51
51
  # is not enough to make the key unique
52
- def cached_statement_key(sql)
52
+ def sql_key(sql)
53
53
  sql
54
54
  end
55
55
 
@@ -342,60 +342,10 @@ module ArJdbc
342
342
 
343
343
  # Properly quotes the various data types.
344
344
  # @param value contains the data
345
- # @param column (optional) contains info on the field
346
345
  # @override
347
- def quote(value, column = nil)
348
- return value.quoted_id if value.respond_to?(:quoted_id)
346
+ def quote(value)
349
347
  return value if sql_literal?(value)
350
-
351
- if column
352
- if column.respond_to?(:primary) && column.primary && column.klass != String
353
- return value.to_i.to_s
354
- end
355
- if value && (column.type.to_sym == :decimal || column.type.to_sym == :integer)
356
- return value.to_s
357
- end
358
- end
359
-
360
- column_type = column && column.type.to_sym
361
-
362
- case value
363
- when nil then 'NULL'
364
- when Numeric # IBM_DB doesn't accept quotes on numeric types
365
- # if the column type is text or string, return the quote value
366
- if column_type == :text || column_type == :string
367
- "'#{value}'"
368
- else
369
- value.to_s
370
- end
371
- when String, ActiveSupport::Multibyte::Chars
372
- if column_type == :binary && column.sql_type !~ /for bit data/i
373
- if update_lob_value?(value, column)
374
- value.nil? ? 'NULL' : BLOB_VALUE_MARKER # '@@@IBMBINARY@@@'"
375
- else
376
- "BLOB('#{quote_string(value)}')"
377
- end
378
- elsif column && column.sql_type =~ /clob/ # :text
379
- if update_lob_value?(value, column)
380
- value.nil? ? 'NULL' : CLOB_VALUE_MARKER # "'@@@IBMTEXT@@@'"
381
- else
382
- "'#{quote_string(value)}'"
383
- end
384
- elsif column_type == :xml
385
- value.nil? ? 'NULL' : "'#{quote_string(value)}'" # "'<ibm>@@@IBMXML@@@</ibm>'"
386
- else
387
- "'#{quote_string(value)}'"
388
- end
389
- when Symbol then "'#{quote_string(value.to_s)}'"
390
- when Time
391
- # AS400 doesn't support date in time column
392
- if column_type == :time
393
- quote_time(value)
394
- else
395
- super
396
- end
397
- else super
398
- end
348
+ super
399
349
  end
400
350
 
401
351
  # @override
@@ -32,7 +32,15 @@ module ActiveRecord
32
32
  include ArJdbc::MySQL
33
33
 
34
34
  def initialize(connection, logger, connection_parameters, config)
35
+ # workaround to skip version check on JNDI to be lazy, dummy version is high enough for Rails 5.0 - 6.0
36
+ is_jndi = ::ActiveRecord::ConnectionAdapters::JdbcConnection.jndi_config?(config)
37
+ @version = '8.1.5' if is_jndi
38
+
35
39
  super
40
+
41
+ # set to nil to have it lazy-load the real value when required
42
+ @version = nil if is_jndi
43
+
36
44
  @prepared_statements = false unless config.key?(:prepared_statements)
37
45
  # configure_connection taken care of at ArJdbc::Abstract::Core
38
46
  end
@@ -528,67 +528,6 @@ module ArJdbc
528
528
  execute "TRUNCATE TABLE #{quote_table_name(table_name)}", name
529
529
  end
530
530
 
531
- # Returns an array of indexes for the given table.
532
- def indexes(table_name, name = nil)
533
- if name
534
- ActiveSupport::Deprecation.warn(<<-MSG.squish)
535
- Passing name to #indexes is deprecated without replacement.
536
- MSG
537
- end
538
-
539
- # FIXME: AR version => table = Utils.extract_schema_qualified_name(table_name.to_s)
540
- schema, table = extract_schema_and_table(table_name.to_s)
541
-
542
- result = query(<<-SQL, 'SCHEMA')
543
- SELECT distinct i.relname, d.indisunique, d.indkey, pg_get_indexdef(d.indexrelid), t.oid,
544
- pg_catalog.obj_description(i.oid, 'pg_class') AS comment,
545
- (SELECT COUNT(*) FROM pg_opclass o
546
- JOIN (SELECT unnest(string_to_array(d.indclass::text, ' '))::int oid) c
547
- ON o.oid = c.oid WHERE o.opcdefault = 'f')
548
- FROM pg_class t
549
- INNER JOIN pg_index d ON t.oid = d.indrelid
550
- INNER JOIN pg_class i ON d.indexrelid = i.oid
551
- LEFT JOIN pg_namespace n ON n.oid = i.relnamespace
552
- WHERE i.relkind = 'i'
553
- AND d.indisprimary = 'f'
554
- AND t.relname = '#{table}'
555
- AND n.nspname = #{schema ? "'#{schema}'" : 'ANY (current_schemas(false))'}
556
- ORDER BY i.relname
557
- SQL
558
-
559
- result.map do |row|
560
- index_name = row[0]
561
- # FIXME: These values [1,2] are returned in a different format than AR expects, maybe we could update it on the Java side to be more accurate
562
- unique = row[1].is_a?(String) ? row[1] == 't' : row[1] # JDBC gets us a boolean
563
- indkey = row[2].is_a?(Java::OrgPostgresqlUtil::PGobject) ? row[2].value : row[2]
564
- indkey = indkey.split(" ").map(&:to_i)
565
- inddef = row[3]
566
- oid = row[4]
567
- comment = row[5]
568
- opclass = row[6]
569
-
570
- using, expressions, where = inddef.scan(/ USING (\w+?) \((.+?)\)(?: WHERE (.+))?\z/m).flatten
571
-
572
- if indkey.include?(0) || opclass > 0
573
- columns = expressions
574
- else
575
- columns = Hash[query(<<-SQL.strip_heredoc, "SCHEMA")].values_at(*indkey).compact
576
- SELECT a.attnum, a.attname
577
- FROM pg_attribute a
578
- WHERE a.attrelid = #{oid}
579
- AND a.attnum IN (#{indkey.join(",")})
580
- SQL
581
-
582
- # add info on sort order for columns (only desc order is explicitly specified, asc is the default)
583
- orders = Hash[
584
- expressions.scan(/(\w+) DESC/).flatten.map { |order_column| [order_column, :desc] }
585
- ]
586
- end
587
-
588
- IndexDefinition.new(table_name, index_name, unique, columns, [], orders, where, nil, using.to_sym, comment.presence)
589
- end.compact
590
- end
591
-
592
531
  # @private
593
532
  def column_name_for_operation(operation, node)
594
533
  case operation
@@ -757,7 +696,7 @@ module ActiveRecord::ConnectionAdapters
757
696
 
758
697
  # Prepared statements aren't schema aware so we need to make sure we
759
698
  # store different PreparedStatement objects for different schemas
760
- def cached_statement_key(sql)
699
+ def sql_key(sql)
761
700
  "#{schema_search_path}-#{sql}"
762
701
  end
763
702
 
@@ -9,6 +9,61 @@ module ArJdbc
9
9
  # @private
10
10
  OID = ::ActiveRecord::ConnectionAdapters::PostgreSQL::OID
11
11
 
12
+ # this version makes sure to register the types by name as well
13
+ # we still need to version with OID since it's used from SchemaStatements as well
14
+ class ArjdbcTypeMapInitializer < OID::TypeMapInitializer
15
+ private
16
+
17
+ def name_with_ns(row)
18
+ if row['in_ns']
19
+ row['typname']
20
+ else
21
+ %Q("#{row['nspname']}"."#{row['typname']}")
22
+ end
23
+ end
24
+
25
+ def register_enum_type(row)
26
+ super
27
+ register name_with_ns(row), OID::Enum.new
28
+ end
29
+
30
+ def register_array_type(row)
31
+ super
32
+ register_with_subtype(name_with_ns(row), row['typelem'].to_i) do |subtype|
33
+ OID::Array.new(subtype, row['typdelim'])
34
+ end
35
+ end
36
+
37
+ def register_range_type(row)
38
+ super
39
+ name = name_with_ns(row)
40
+ register_with_subtype(name, row['rngsubtype'].to_i) do |subtype|
41
+ OID::Range.new(subtype, name.to_sym)
42
+ end
43
+ end
44
+
45
+ def register_domain_type(row)
46
+ if base_type = @store.lookup(row['typbasetype'].to_i)
47
+ register row['oid'], base_type
48
+ register name_with_ns(row), base_type
49
+ else
50
+ warn "unknown base type (OID: #{row['typbasetype']}) for domain #{row['typname']}."
51
+ end
52
+ end
53
+
54
+ def register_composite_type(row)
55
+ if subtype = @store.lookup(row['typelem'].to_i)
56
+ register row['oid'], OID::Vector.new(row['typdelim'], subtype)
57
+ register name_with_ns(row), OID::Vector.new(row['typdelim'], subtype)
58
+ end
59
+ end
60
+
61
+ def assert_valid_registration(oid, oid_type)
62
+ ret = super
63
+ ret == 0 ? oid : ret
64
+ end
65
+ end
66
+
12
67
  # @private
13
68
  module OIDTypes
14
69
 
@@ -41,7 +96,7 @@ module ArJdbc
41
96
 
42
97
  def get_oid_type(oid, fmod, column_name, sql_type = '') # :nodoc:
43
98
  if !type_map.key?(oid)
44
- load_additional_types(type_map, [oid])
99
+ load_additional_types(type_map, oid)
45
100
  end
46
101
 
47
102
  type_map.fetch(oid, fmod, sql_type) {
@@ -133,26 +188,45 @@ module ArJdbc
133
188
  end
134
189
 
135
190
  load_additional_types(m)
191
+
192
+ # pgjdbc returns these if the column is auto-incrmenting
193
+ m.alias_type 'serial', 'int4'
194
+ m.alias_type 'bigserial', 'int8'
136
195
  end
137
196
 
138
- def load_additional_types(type_map, oids = nil) # :nodoc:
139
- initializer = OID::TypeMapInitializer.new(type_map)
197
+ def load_additional_types(type_map, oid = nil) # :nodoc:
198
+ initializer = ArjdbcTypeMapInitializer.new(type_map)
140
199
 
141
200
  if supports_ranges?
142
201
  query = <<-SQL
143
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype
202
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, r.rngsubtype, t.typtype, t.typbasetype,
203
+ ns.nspname, ns.nspname = ANY(current_schemas(true)) in_ns
144
204
  FROM pg_type as t
145
205
  LEFT JOIN pg_range as r ON oid = rngtypid
206
+ JOIN pg_namespace AS ns ON t.typnamespace = ns.oid
146
207
  SQL
147
208
  else
148
209
  query = <<-SQL
149
- SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype
210
+ SELECT t.oid, t.typname, t.typelem, t.typdelim, t.typinput, t.typtype, t.typbasetype,
211
+ ns.nspname, ns.nspname = ANY(current_schemas(true)) in_ns
150
212
  FROM pg_type as t
213
+ JOIN pg_namespace AS ns ON t.typnamespace = ns.oid
151
214
  SQL
152
215
  end
153
216
 
154
- if oids
155
- query += "WHERE t.oid::integer IN (%s)" % oids.join(", ")
217
+ if oid
218
+ if oid.is_a? Numeric || oid.match(/^\d+$/)
219
+ # numeric OID
220
+ query += "WHERE t.oid::integer = %s" % oid
221
+
222
+ elsif m = oid.match(/"?(\w+)"?\."?(\w+)"?/)
223
+ # namespace and type name
224
+ query += "WHERE ns.nspname = '%s' AND t.typname = '%s'" % [m[1], m[2]]
225
+
226
+ else
227
+ # only type name
228
+ query += "WHERE t.typname = '%s' AND ns.nspname = ANY(current_schemas(true))" % oid
229
+ end
156
230
  else
157
231
  query += initializer.query_conditions_for_initial_load(type_map)
158
232
  end
@@ -1,3 +1,3 @@
1
1
  module ArJdbc
2
- VERSION = '51.2'
2
+ VERSION = '51.3'
3
3
  end
data/rakelib/rails.rake CHANGED
@@ -9,14 +9,15 @@ namespace :rails do
9
9
  if ENV['RAILS']
10
10
  ar_path = File.join(ENV['RAILS'], 'activerecord')
11
11
  end
12
-
12
+
13
13
  unless ar_path && File.exist?(ar_path)
14
- ar_path = `bundle info --path activerecord`.chomp
14
+ ar_path = `bundle info --path activerecord`.lines.last.chomp
15
15
  end
16
16
 
17
17
  unless File.exist? ar_test_dir = File.join(ar_path, 'test')
18
18
  raise "can not directly load Rails tests;" +
19
- " try setting a local repository path e.g. export RAILS=`pwd`/../rails"
19
+ " try setting a local repository path e.g. export RAILS=`pwd`/../rails;" +
20
+ " failed guess: #{ar_path}"
20
21
  end
21
22
 
22
23
  driver = "jdbc-#{ENV['DRIVER'] ? ENV['DRIVER'].downcase : (adapter =~ /postgres/i ? 'postgres' : adapter)}"
@@ -29,7 +29,6 @@ import java.util.HashMap;
29
29
  import java.util.Map;
30
30
  import java.util.WeakHashMap;
31
31
 
32
- import org.jruby.NativeException;
33
32
  import org.jruby.Ruby;
34
33
  import org.jruby.RubyArray;
35
34
  import org.jruby.RubyClass;
@@ -148,13 +147,7 @@ public class ArJdbcModule {
148
147
  }
149
148
  }
150
149
  catch (ClassNotFoundException e) { /* ignored */ }
151
- catch (NoSuchMethodException e) {
152
- throw newNativeException(runtime, e);
153
- }
154
- catch (IllegalAccessException e) {
155
- throw newNativeException(runtime, e);
156
- }
157
- catch (InvocationTargetException e) {
150
+ catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
158
151
  throw newNativeException(runtime, e);
159
152
  }
160
153
 
@@ -263,18 +256,15 @@ public class ArJdbcModule {
263
256
  try {
264
257
  return klass.getMethod(name, argType).invoke(null, arg);
265
258
  }
266
- catch (IllegalAccessException e) {
267
- throw newNativeException(runtime, e);
268
- }
269
- catch (InvocationTargetException e) {
259
+ catch (IllegalAccessException | InvocationTargetException e) {
270
260
  throw newNativeException(runtime, e);
271
261
  }
272
262
  }
273
263
 
274
264
  private static RaiseException newNativeException(final Ruby runtime, final Throwable cause) {
275
- RubyClass nativeClass = runtime.getClass(NativeException.CLASS_NAME);
276
- NativeException nativeException = new NativeException(runtime, nativeClass, cause);
277
- return new RaiseException(cause, nativeException);
265
+ final RaiseException error = runtime.newRuntimeError(cause.toString());
266
+ error.initCause(cause);
267
+ return error;
278
268
  }
279
269
 
280
270
  @JRubyMethod(meta = true)