activerecord-jdbc-adapter 60.0.rc1-java → 60.1-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.travis.yml +42 -30
  4. data/README.md +36 -18
  5. data/Rakefile +30 -4
  6. data/Rakefile.jdbc +8 -1
  7. data/activerecord-jdbc-adapter.gemspec +6 -9
  8. data/lib/arjdbc/abstract/connection_management.rb +5 -0
  9. data/lib/arjdbc/abstract/core.rb +1 -1
  10. data/lib/arjdbc/abstract/database_statements.rb +8 -21
  11. data/lib/arjdbc/db2/adapter.rb +11 -0
  12. data/lib/arjdbc/db2/column.rb +0 -39
  13. data/lib/arjdbc/derby/adapter.rb +1 -20
  14. data/lib/arjdbc/firebird/adapter.rb +0 -21
  15. data/lib/arjdbc/h2/adapter.rb +0 -15
  16. data/lib/arjdbc/hsqldb/adapter.rb +0 -14
  17. data/lib/arjdbc/informix/adapter.rb +0 -23
  18. data/lib/arjdbc/jdbc.rb +0 -4
  19. data/lib/arjdbc/jdbc/adapter.rb +4 -0
  20. data/lib/arjdbc/jdbc/column.rb +1 -5
  21. data/lib/arjdbc/mysql/adapter.rb +12 -1
  22. data/lib/arjdbc/mysql/connection_methods.rb +13 -7
  23. data/lib/arjdbc/postgresql/adapter.rb +10 -19
  24. data/lib/arjdbc/postgresql/column.rb +6 -3
  25. data/lib/arjdbc/postgresql/connection_methods.rb +3 -1
  26. data/lib/arjdbc/sqlite3/adapter.rb +14 -21
  27. data/lib/arjdbc/sqlite3/connection_methods.rb +1 -0
  28. data/lib/arjdbc/tasks/databases.rake +3 -1
  29. data/lib/arjdbc/version.rb +1 -1
  30. data/rakelib/02-test.rake +0 -3
  31. data/rakelib/rails.rake +1 -1
  32. data/src/java/arjdbc/jdbc/RubyJdbcConnection.java +103 -33
  33. data/src/java/arjdbc/mssql/MSSQLRubyJdbcConnection.java +259 -14
  34. data/src/java/arjdbc/postgresql/PostgreSQLRubyJdbcConnection.java +1 -13
  35. data/src/java/arjdbc/util/DateTimeUtils.java +34 -12
  36. metadata +8 -22
  37. data/lib/active_record/connection_adapters/mssql_adapter.rb +0 -1
  38. data/lib/active_record/connection_adapters/sqlserver_adapter.rb +0 -1
  39. data/lib/arjdbc/mssql.rb +0 -7
  40. data/lib/arjdbc/mssql/adapter.rb +0 -804
  41. data/lib/arjdbc/mssql/column.rb +0 -200
  42. data/lib/arjdbc/mssql/connection_methods.rb +0 -79
  43. data/lib/arjdbc/mssql/explain_support.rb +0 -99
  44. data/lib/arjdbc/mssql/limit_helpers.rb +0 -231
  45. data/lib/arjdbc/mssql/lock_methods.rb +0 -77
  46. data/lib/arjdbc/mssql/types.rb +0 -343
  47. data/lib/arjdbc/mssql/utils.rb +0 -82
@@ -80,45 +80,6 @@ module ArJdbc
80
80
 
81
81
  private
82
82
 
83
- def simplified_type(field_type)
84
- case field_type
85
- when /^decimal\(1\)$/i then DB2.emulate_booleans? ? :boolean : :integer
86
- when /smallint/i then DB2.emulate_booleans? ? :boolean : :integer
87
- when /boolean/i then :boolean
88
- when /^real|double/i then :float
89
- when /int|serial/i then :integer
90
- # if a numeric column has no scale, lets treat it as an integer.
91
- # The AS400 rpg guys do this ALOT since they have no integer datatype ...
92
- when /decimal|numeric|decfloat/i
93
- extract_scale(field_type) == 0 ? :integer : :decimal
94
- when /timestamp/i then :timestamp
95
- when /datetime/i then :datetime
96
- when /time/i then :time
97
- when /date/i then :date
98
- # DB2 provides three data types to store these data objects as strings of up to 2 GB in size:
99
- # Character large objects (CLOBs)
100
- # Use the CLOB data type to store SBCS or mixed data, such as documents that contain
101
- # single character set. Use this data type if your data is larger (or might grow larger)
102
- # than the VARCHAR data type permits.
103
- # Double-byte character large objects (DBCLOBs)
104
- # Use the DBCLOB data type to store large amounts of DBCS data, such as documents that
105
- # use a DBCS character set.
106
- # Binary large objects (BLOBs)
107
- # Use the BLOB data type to store large amounts of noncharacter data, such as pictures,
108
- # voice, and mixed media.
109
- when /clob|text/i then :text # handles DBCLOB
110
- when /^long varchar/i then :text # :limit => 32700
111
- when /blob|binary/i then :binary
112
- # varchar () for bit data, char () for bit data, long varchar for bit data
113
- when /for bit data/i then :binary
114
- when /xml/i then :xml
115
- when /graphic/i then :graphic # vargraphic, long vargraphic
116
- when /rowid/i then :rowid # rowid is a supported datatype on z/OS and i/5
117
- else
118
- super
119
- end
120
- end
121
-
122
83
  # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
123
84
  def default_value(value)
124
85
  # IBM i (AS400) will return an empty string instead of null for no default
@@ -65,25 +65,6 @@ module ArJdbc
65
65
  limit
66
66
  end
67
67
 
68
- def simplified_type(field_type)
69
- case field_type
70
- when /^smallint/i then Derby.emulate_booleans? ? :boolean : :integer
71
- when /^bigint|int/i then :integer
72
- when /^real|double/i then :float
73
- when /^dec/i then # DEC is a DECIMAL alias
74
- extract_scale(field_type) == 0 ? :integer : :decimal
75
- when /^timestamp/i then :datetime
76
- when /^xml/i then :xml
77
- when 'long varchar' then :text
78
- when /for bit data/i then :binary
79
- # :name=>"long varchar for bit data", :limit=>32700
80
- # :name=>"varchar() for bit data", :limit=>32672
81
- # :name=>"char() for bit data", :limit=>254}
82
- else
83
- super
84
- end
85
- end
86
-
87
68
  # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
88
69
  def default_value(value)
89
70
  # JDBC returns column default strings with actual single quotes around the value.
@@ -420,7 +401,7 @@ module ArJdbc
420
401
 
421
402
  # @override
422
403
  def supports_ddl_transactions?; true end
423
-
404
+
424
405
  # @override
425
406
  def supports_foreign_keys?; true end
426
407
 
@@ -38,27 +38,6 @@ module ArJdbc
38
38
  return $1 unless $1.upcase == 'NULL'
39
39
  end
40
40
  end
41
-
42
- private
43
-
44
- def simplified_type(field_type)
45
- case field_type
46
- when /timestamp/i then :datetime
47
- when /^smallint/i then :integer
48
- when /^bigint|int/i then :integer
49
- when /^double/i then :float # double precision
50
- when /^decimal/i then
51
- extract_scale(field_type) == 0 ? :integer : :decimal
52
- when /^char\(1\)$/i then Firebird.emulate_booleans? ? :boolean : :string
53
- when /^char/i then :string
54
- when /^blob\ssub_type\s(\d)/i
55
- return :binary if $1 == '0'
56
- return :text if $1 == '1'
57
- else
58
- super
59
- end
60
- end
61
-
62
41
  end
63
42
 
64
43
  # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_column_class
@@ -47,21 +47,6 @@ module ArJdbc
47
47
  limit
48
48
  end
49
49
 
50
- def simplified_type(field_type)
51
- case field_type
52
- when /^bit|bool/i then :boolean
53
- when /^signed|year/i then :integer
54
- when /^real|double/i then :float
55
- when /^varchar/i then :string
56
- when /^longvarchar/i then :text
57
- when /^binary|raw|bytea/i then :binary
58
- when /varbinary/i then :binary # longvarbinary, varbinary
59
- when /^blob|image|oid/i then :binary
60
- else
61
- super
62
- end
63
- end
64
-
65
50
  # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
66
51
  def default_value(value)
67
52
  # H2 auto-generated key default value
@@ -42,20 +42,6 @@ module ArJdbc
42
42
  limit
43
43
  end
44
44
 
45
- def simplified_type(field_type)
46
- case field_type
47
- when /^nvarchar/i then :string
48
- when /^character/i then :string
49
- when /^longvarchar/i then :text
50
- when /int/i then :integer # TINYINT, SMALLINT, BIGINT, INT
51
- when /real|double/i then :float
52
- when /^bit/i then :boolean
53
- when /binary/i then :binary # VARBINARY, LONGVARBINARY
54
- else
55
- super
56
- end
57
- end
58
-
59
45
  # Post process default value from JDBC into a Rails-friendly format (columns{-internal})
60
46
  def default_value(value)
61
47
  # JDBC returns column default strings with actual single quotes around the value.
@@ -28,11 +28,6 @@ module ArJdbc
28
28
  end
29
29
  end
30
30
 
31
- # @see ActiveRecord::ConnectionAdapters::JdbcColumn#column_types
32
- def self.column_selector
33
- [ /informix/i, lambda { |cfg, column| column.extend(ColumnMethods) } ]
34
- end
35
-
36
31
  JdbcConnection = ::ActiveRecord::ConnectionAdapters::InformixJdbcConnection
37
32
 
38
33
  # @see ActiveRecord::ConnectionAdapters::JdbcAdapter#jdbc_connection_class
@@ -45,20 +40,6 @@ module ArJdbc
45
40
  ::ActiveRecord::ConnectionAdapters::InformixColumn
46
41
  end
47
42
 
48
- module ColumnMethods
49
-
50
- private
51
- # TODO: Test all Informix column types.
52
- def simplified_type(field_type)
53
- if field_type =~ /serial/i
54
- :primary_key
55
- else
56
- super
57
- end
58
- end
59
-
60
- end
61
-
62
43
  def modify_types(types)
63
44
  super(types)
64
45
  types[:primary_key] = "SERIAL PRIMARY KEY"
@@ -152,10 +133,6 @@ module ArJdbc
152
133
  end # module ::ArJdbc
153
134
 
154
135
  module ActiveRecord::ConnectionAdapters
155
- class InformixColumn < JdbcColumn
156
- include ::ArJdbc::Informix::ColumnMethods
157
- end
158
-
159
136
  class InformixAdapter < JdbcAdapter
160
137
  include ::ArJdbc::Informix
161
138
  end
data/lib/arjdbc/jdbc.rb CHANGED
@@ -2,12 +2,8 @@ require 'active_support/deprecation'
2
2
 
3
3
  module ArJdbc
4
4
 
5
- # @private
6
- AR40 = ::ActiveRecord::VERSION::MAJOR > 3
7
5
  # @private
8
6
  AR42 = ::ActiveRecord::VERSION::STRING >= '4.2'
9
- # @private
10
- AR50 = ::ActiveRecord::VERSION::MAJOR > 4
11
7
 
12
8
  # @private
13
9
  AR52 = ::ActiveRecord::VERSION::STRING >= '5.2'
@@ -360,6 +360,10 @@ module ActiveRecord
360
360
  # @return [Integer, NilClass]
361
361
  def last_inserted_id(result)
362
362
  if result.is_a?(Hash) || result.is_a?(ActiveRecord::Result)
363
+ # If table does not have primary key defined
364
+ return nil if result.first.blank?
365
+
366
+
363
367
  result.first.first[1] # .first = { "id"=>1 } .first = [ "id", 1 ]
364
368
  else
365
369
  result
@@ -30,17 +30,13 @@ module ActiveRecord
30
30
 
31
31
  if ArJdbc::AR52
32
32
  # undefined method `cast' for #<ActiveRecord::ConnectionAdapters::SqlTypeMetadata> on AR52
33
- elsif ArJdbc::AR50
33
+ else
34
34
  default = args[0].cast(default)
35
35
 
36
36
  sql_type = args.delete_at(1)
37
37
  type = args.delete_at(0)
38
38
 
39
39
  args.unshift(SqlTypeMetadata.new(:sql_type => sql_type, :type => type))
40
- elsif ArJdbc::AR42
41
- default = args[0].type_cast_from_database(default)
42
- else
43
- default = default_value(default)
44
40
  end
45
41
 
46
42
  # super <= 4.1: (name, default, sql_type = nil, null = true)
@@ -40,6 +40,15 @@ module ActiveRecord
40
40
  # configure_connection taken care of at ArJdbc::Abstract::Core
41
41
  end
42
42
 
43
+ def self.database_exists?(config)
44
+ conn = ActiveRecord::Base.mysql2_connection(config)
45
+ conn && conn.really_valid?
46
+ rescue ActiveRecord::NoDatabaseError
47
+ false
48
+ ensure
49
+ conn.disconnect! if conn
50
+ end
51
+
43
52
  def check_version
44
53
  # for JNDI, don't check version as the whole connection should be lazy
45
54
  return if ::ActiveRecord::ConnectionAdapters::JdbcConnection.jndi_config?(config)
@@ -78,7 +87,9 @@ module ActiveRecord
78
87
  # HELPER METHODS ===========================================
79
88
 
80
89
  # from MySQL::DatabaseStatements
81
- READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback) # :nodoc:
90
+ READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(
91
+ :begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback, :describe, :desc
92
+ ) # :nodoc:
82
93
  private_constant :READ_QUERY
83
94
 
84
95
  def write_query?(sql) # :nodoc:
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  ArJdbc::ConnectionMethods.module_eval do
3
3
  def mysql_connection(config)
4
+ config = config.deep_dup
4
5
  # NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
5
6
  # ActiveRecord::Base.mysql2_connection ActiveRecord::Base.configurations['arunit'].merge(database: ...)
6
7
  config = symbolize_keys_if_necessary(config)
@@ -10,11 +11,9 @@ ArJdbc::ConnectionMethods.module_eval do
10
11
 
11
12
  return jndi_connection(config) if jndi_config?(config)
12
13
 
13
- driver = config[:driver] ||=
14
- defined?(::Jdbc::MySQL.driver_name) ? ::Jdbc::MySQL.driver_name : 'com.mysql.jdbc.Driver'
15
-
16
- mysql_driver = driver.start_with?('com.mysql.')
17
- mariadb_driver = ! mysql_driver && driver.start_with?('org.mariadb.')
14
+ driver = config[:driver]
15
+ mysql_driver = driver.nil? || driver.to_s.start_with?('com.mysql.')
16
+ mariadb_driver = ! mysql_driver && driver.to_s.start_with?('org.mariadb.')
18
17
 
19
18
  begin
20
19
  require 'jdbc/mysql'
@@ -22,6 +21,11 @@ ArJdbc::ConnectionMethods.module_eval do
22
21
  rescue LoadError # assuming driver.jar is on the class-path
23
22
  end if mysql_driver
24
23
 
24
+ if driver.nil?
25
+ config[:driver] ||=
26
+ defined?(::Jdbc::MySQL.driver_name) ? ::Jdbc::MySQL.driver_name : 'com.mysql.jdbc.Driver'
27
+ end
28
+
25
29
  config[:username] = 'root' unless config.key?(:username)
26
30
  # jdbc:mysql://[host][,failoverhost...][:port]/[database]
27
31
  # - if the host name is not specified, it defaults to 127.0.0.1
@@ -36,7 +40,8 @@ ArJdbc::ConnectionMethods.module_eval do
36
40
 
37
41
  properties = ( config[:properties] ||= {} )
38
42
  if mysql_driver
39
- properties['zeroDateTimeBehavior'] ||= 'convertToNull'
43
+ properties['zeroDateTimeBehavior'] ||=
44
+ config[:driver].to_s.start_with?('com.mysql.cj.') ? 'CONVERT_TO_NULL' : 'convertToNull'
40
45
  properties['jdbcCompliantTruncation'] ||= false
41
46
  # NOTE: this is "better" than passing what users are used to set on MRI
42
47
  # e.g. 'utf8mb4' will fail cause the driver will check for a Java charset
@@ -108,7 +113,8 @@ ArJdbc::ConnectionMethods.module_eval do
108
113
  rescue LoadError # assuming driver.jar is on the class-path
109
114
  end
110
115
 
111
- config[:driver] ||= 'org.mariadb.jdbc.Driver'
116
+ config[:driver] ||=
117
+ defined?(::Jdbc::MariaDB.driver_name) ? ::Jdbc::MariaDB.driver_name : 'org.mariadb.jdbc.Driver'
112
118
 
113
119
  mysql_connection(config)
114
120
  end
@@ -365,7 +365,7 @@ module ArJdbc
365
365
  @use_insert_returning
366
366
  end
367
367
 
368
- def exec_insert(sql, name, binds, pk = nil, sequence_name = nil)
368
+ def exec_insert(sql, name = nil, binds = [], pk = nil, sequence_name = nil)
369
369
  val = super
370
370
  if !use_insert_returning? && pk
371
371
  unless sequence_name
@@ -384,24 +384,6 @@ module ArJdbc
384
384
  ActiveRecord::ConnectionAdapters::PostgreSQL::ExplainPrettyPrinter.new.pp(exec_query("EXPLAIN #{sql}", 'EXPLAIN', binds))
385
385
  end
386
386
 
387
- # @note Only for "better" AR 4.0 compatibility.
388
- # @private
389
- def query(sql, name = nil)
390
- materialize_transactions
391
-
392
- log(sql, name) do
393
- result = []
394
- @connection.execute_query_raw(sql, []) do |*values|
395
- # We need to use #deep_dup here because it appears that
396
- # the java method is reusing an object in some cases
397
- # which makes all of the entries in the "result"
398
- # array end up with the same values as the last row
399
- result << values.deep_dup
400
- end
401
- result
402
- end
403
- end
404
-
405
387
  # from ActiveRecord::ConnectionAdapters::PostgreSQL::DatabaseStatements
406
388
  READ_QUERY = ActiveRecord::ConnectionAdapters::AbstractAdapter.build_read_query_regexp(:begin, :commit, :explain, :select, :set, :show, :release, :savepoint, :rollback) # :nodoc:
407
389
  private_constant :READ_QUERY
@@ -698,6 +680,15 @@ module ActiveRecord::ConnectionAdapters
698
680
  self.class.type_cast_config_to_boolean(@config[:insert_returning]) : true
699
681
  end
700
682
 
683
+ def self.database_exists?(config)
684
+ conn = ActiveRecord::Base.postgresql_connection(config)
685
+ conn && conn.really_valid?
686
+ rescue ActiveRecord::NoDatabaseError
687
+ false
688
+ ensure
689
+ conn.disconnect! if conn
690
+ end
691
+
701
692
  require 'active_record/connection_adapters/postgresql/schema_definitions'
702
693
 
703
694
  ColumnMethods = ActiveRecord::ConnectionAdapters::PostgreSQL::ColumnMethods
@@ -17,7 +17,7 @@ module ArJdbc
17
17
  end
18
18
 
19
19
  # Extracts the value from a PostgreSQL column default definition.
20
- def extract_value_from_default(default) # :nodoc:
20
+ def extract_value_from_default(default)
21
21
  case default
22
22
  # Quoted types
23
23
  when /\A[\(B]?'(.*)'.*::"?([\w. ]+)"?(?:\[\])?\z/m
@@ -43,10 +43,13 @@ module ArJdbc
43
43
  end
44
44
  end
45
45
 
46
- def extract_default_function(default_value, default) # :nodoc:
47
- default if ! default_value && ( %r{\w+\(.*\)|\(.*\)::\w+} === default )
46
+ def extract_default_function(default_value, default)
47
+ default if has_default_function?(default_value, default)
48
48
  end
49
49
 
50
+ def has_default_function?(default_value, default)
51
+ !default_value && %r{\w+\(.*\)|\(.*\)::\w+|CURRENT_DATE|CURRENT_TIMESTAMP}.match?(default)
52
+ end
50
53
  end
51
54
 
52
55
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  ArJdbc::ConnectionMethods.module_eval do
3
3
  def postgresql_connection(config)
4
+ config = config.deep_dup
4
5
  # NOTE: this isn't "really" necessary but Rails (in tests) assumes being able to :
5
6
  # ActiveRecord::Base.postgresql_connection ActiveRecord::Base.configurations['arunit'].merge(:insert_returning => false)
6
7
  # ... while using symbols by default but than configurations returning string keys ;(
@@ -16,7 +17,8 @@ ArJdbc::ConnectionMethods.module_eval do
16
17
  ::Jdbc::Postgres.load_driver(:require) if defined?(::Jdbc::Postgres.load_driver)
17
18
  rescue LoadError # assuming driver.jar is on the class-path
18
19
  end
19
- driver = config[:driver] ||= 'org.postgresql.Driver'
20
+ driver = (config[:driver] ||=
21
+ defined?(::Jdbc::Postgres.driver_name) ? ::Jdbc::Postgres.driver_name : 'org.postgresql.Driver')
20
22
 
21
23
  host = config[:host] ||= ( config[:hostaddr] || ENV['PGHOST'] || 'localhost' )
22
24
  port = config[:port] ||= ( ENV['PGPORT'] || 5432 )
@@ -494,9 +494,9 @@ module ArJdbc
494
494
  result = exec_query(sql, "SCHEMA").first
495
495
 
496
496
  if result
497
- # Splitting with left parentheses and picking up last will return all
497
+ # Splitting with left parentheses and discarding the first part will return all
498
498
  # columns separated with comma(,).
499
- columns_string = result["sql"].split("(").last
499
+ columns_string = result["sql"].split("(", 2).last
500
500
 
501
501
  columns_string.split(",").each do |column_string|
502
502
  # This regex will match the column name and collation type and will save
@@ -596,24 +596,6 @@ module ActiveRecord::ConnectionAdapters
596
596
 
597
597
  private
598
598
 
599
- # @override {ActiveRecord::ConnectionAdapters::Column#simplified_type}
600
- def simplified_type(field_type)
601
- case field_type
602
- when /boolean/i then :boolean
603
- when /text/i then :text
604
- when /varchar/i then :string
605
- when /int/i then :integer
606
- when /float/i then :float
607
- when /real|decimal/i then
608
- extract_scale(field_type) == 0 ? :integer : :decimal
609
- when /datetime/i then :datetime
610
- when /date/i then :date
611
- when /time/i then :time
612
- when /blob/i then :binary
613
- else super
614
- end
615
- end
616
-
617
599
  # @override {ActiveRecord::ConnectionAdapters::Column#extract_limit}
618
600
  def extract_limit(sql_type)
619
601
  return nil if sql_type =~ /^(real)\(\d+/i
@@ -660,6 +642,17 @@ module ActiveRecord::ConnectionAdapters
660
642
  )
661
643
  end
662
644
 
645
+ def self.database_exists?(config)
646
+ config = config.symbolize_keys
647
+ if config[:database] == ":memory:"
648
+ return true
649
+ else
650
+ database_file = defined?(Rails.root) ? File.expand_path(config[:database], Rails.root) : config[:database]
651
+ File.exist?(database_file)
652
+ end
653
+ end
654
+
655
+
663
656
  def supports_transaction_isolation?
664
657
  false
665
658
  end
@@ -667,7 +660,7 @@ module ActiveRecord::ConnectionAdapters
667
660
  def begin_isolated_db_transaction(isolation)
668
661
  raise ActiveRecord::TransactionIsolationError, 'adapter does not support setting transaction isolation'
669
662
  end
670
-
663
+
671
664
  # SQLite driver doesn't support all types of insert statements with executeUpdate so
672
665
  # make it act like a regular query and the ids will be returned from #last_inserted_id
673
666
  # example: INSERT INTO "aircraft" DEFAULT VALUES